F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c
F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h
+AMLOGIC DRM
+M: Ao Xu <ao.xu@amlogic.com>
+M: Dezhi Kong <dezhi.kong@amlogic.com>
+F: include/linux/meson_ion.h
+F: include/uapi/drm/meson_drm.h
+F: include/uapi/drm/drm_fourcc.c
+F: drivers/gpu/Makefile
+F: drivers/amlogic/Kconfig
+F: drivers/amlogic/Makefile
+F: drivers/amlogic/drm/*
+F: drivers/staging/android/ion/ion.h
+F: drivers/staging/android/ion/ion_cma_heap.c
+F: drivers/amlogic/media/osd/osd_fb.c
+F: drivers/amlogic/media/common/ion_dev/dev_ion.c
+F: drivers/amlogic/media/common/ion_dev/dev_ion.h
+F: arch/arm/boot/dts/amlogic/meson-g12a-u200.dts
+F: arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi
+F: arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts
+F: arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts
+F: arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
+F: arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi
+F: arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts
+F: arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts
+F: arch/arm/configs/meson64_a32_defconfig
+F: arch/arm64/configs/meson64_a64_defconfig
+F: arch/arm/boot/dts/amlogic/Makefile
+F: arch/arm64/boot/dts/amlogic/Makefile
+
&drm_vpu {
status = "okay";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V1>;
};
&drm_amhdmitx {
#include "mesong12b.dtsi"
#include "mesong12b_skt-panel.dtsi"
-#include "mesong12a_drm.dtsi"
+#include "mesong12b_drm.dtsi"
/ {
model = "Amlogic";
status = "okay";
compatible = "amlogic,meson-g12b-vpu";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V3>;
};
&drm_amhdmitx {
status = "okay";
compatible = "amlogic,meson-g12b-vpu";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V2>;
};
&drm_amhdmitx {
--- /dev/null
+/*
+ * arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+/dts-v1/;
+
+#include "mesong12b_a.dtsi"
+#include "mesong12b_skt-panel.dtsi"
+#include "mesong12b_drm.dtsi"
+
+/ {
+ model = "Amlogic";
+ amlogic-dt-id = "g12b_w400_a";
+ compatible = "amlogic, g12b";
+ interrupt-parent = <&gic>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ serial0 = &uart_AO;
+ serial1 = &uart_A;
+ serial2 = &uart_B;
+ serial3 = &uart_C;
+ serial4 = &uart_AO_B;
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c_AO;
+ tsensor0 = &p_tsensor;
+ tsensor1 = &d_tsensor;
+ };
+
+ memory@00000000 {
+ device_type = "memory";
+ linux,usable-memory = <0x100000 0x7ff00000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ /* global autoconfigured region for contiguous allocations */
+ ramoops@0x07400000 {
+ compatible = "ramoops";
+ reg = <0x07400000 0x00100000>;
+ record-size = <0x8000>;
+ console-size = <0x8000>;
+ ftrace-size = <0x0>;
+ pmsg-size = <0x8000>;
+ };
+
+ secmon_reserved:linux,secmon {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x400000>;
+ alignment = <0x400000>;
+ alloc-ranges = <0x05000000 0x400000>;
+ clear-map;
+ };
+
+ secos_reserved:linux,secos {
+ status = "disable";
+ compatible = "amlogic, aml_secos_memory";
+ reg = <0x05300000 0x2000000>;
+ no-map;
+ };
+ logo_reserved:linux,meson-fb {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x800000>;
+ alignment = <0x400000>;
+ alloc-ranges = <0x7f800000 0x800000>;
+ };
+ ion_cma_reserved:linux,ion-dev {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x8000000>;
+ alignment = <0x400000>;
+ };
+
+ //di_reserved:linux,di {
+ //compatible = "amlogic, di-mem";
+ /* buffer_size = 3621952(yuv422 8bit) */
+ /* 4179008(yuv422 10bit full pack mode) */
+ /** 10x3621952=34.6M(0x23) support 8bit **/
+ /** 10x4736064=45.2M(0x2e) support 12bit **/
+ /** 10x4179008=40M(0x28) support 10bit **/
+ //size = <0x2800000>;
+ //no-map;
+ //};
+ /*di CMA pool */
+ di_cma_reserved:linux,di_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* buffer_size = 3621952(yuv422 8bit)
+ * | 4736064(yuv422 10bit)
+ * | 4074560(yuv422 10bit full pack mode)
+ * 10x3621952=34.6M(0x23) support 8bit
+ * 10x4736064=45.2M(0x2e) support 12bit
+ * 10x4074560=40M(0x28) support 10bit
+ */
+ size = <0x02800000>;
+ alignment = <0x400000>;
+ };
+ /* POST PROCESS MANAGER */
+ ppmgr_reserved:linux,ppmgr {
+ compatible = "shared-dma-pool";
+ size = <0x0>;
+ };
+ codec_mm_cma:linux,codec_mm_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* ion_codec_mm max can alloc size 80M*/
+ size = <0x13400000>;
+ alignment = <0x400000>;
+ linux,contiguous-region;
+ };
+ /* codec shared reserved */
+ codec_mm_reserved:linux,codec_mm_reserved {
+ compatible = "amlogic, codec-mm-reserved";
+ size = <0x0>;
+ alignment = <0x100000>;
+ //no-map;
+ };
+ /* vdin0 CMA pool */
+ vdin0_cma_reserved:linux,vdin0_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* 1920x1080x2x4 =16+4 M */
+ size = <0x04000000>;
+ alignment = <0x400000>;
+ };
+ /* vdin1 CMA pool */
+ vdin1_cma_reserved:linux,vdin1_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* 1920x1080x2x4 =16 M */
+ size = <0x04000000>;
+ alignment = <0x400000>;
+ };
+ galcore_reserved:linux,galcore {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x1000000>;
+ alignment = <0x400000>;
+ linux,contiguous-region;
+ };
+
+ isp_cma_reserved:linux,isp_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x1f000000>;
+ alignment = <0x400000>;
+ };
+
+ adapt_cma_reserved:linux,adapt_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x03000000>;
+ alignment = <0x400000>;
+ };
+ gdc_cma_reserved:linux,gdc_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x04000000>;
+ alignment = <0x400000>;
+ };
+ };
+ galcore {
+ status = "okay";
+ memory-region = <&galcore_reserved>;
+ };
+ gpioleds {
+ compatible = "gpio-leds";
+ status = "okay";
+
+ sys_led {
+ label="sys_led";
+ gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>;
+ default-state ="on";
+ retain-state-suspended;
+ linux,default-trigger="cpu0";
+ };
+ };
+
+ cvbsout {
+ compatible = "amlogic, cvbsout-g12b";
+ dev_name = "cvbsout";
+ status = "okay";
+ clocks = <&clkc CLKID_VCLK2_ENCI
+ &clkc CLKID_VCLK2_VENCI0
+ &clkc CLKID_VCLK2_VENCI1
+ &clkc CLKID_DAC_CLK>;
+ clock-names = "venci_top_gate",
+ "venci_0_gate",
+ "venci_1_gate",
+ "vdac_clk_gate";
+
+ /* performance: reg_address, reg_value */
+ /* g12b */
+ performance = <0x1bf0 0x9
+ 0x1b56 0x333
+ 0x1b12 0x8080
+ 0x1b05 0xfd
+ 0x1c59 0xf850
+ 0xffff 0x0>; /* ending flag */
+ performance_sarft = <0x1bf0 0x9
+ 0x1b56 0x333
+ 0x1b12 0x0
+ 0x1b05 0x9
+ 0x1c59 0xfc48
+ 0xffff 0x0>; /* ending flag */
+ };
+
+ bt-dev{
+ compatible = "amlogic, bt-dev";
+ dev_name = "bt-dev";
+ status = "okay";
+ gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+ gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>;
+ };
+
+ wifi{
+ compatible = "amlogic, aml_wifi";
+ dev_name = "aml_wifi";
+ status = "okay";
+ interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>;
+ irq_trigger_type = "GPIO_IRQ_LOW";
+ power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>;
+ dhd_static_buf; //if use bcm wifi, config dhd_static_buf
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_e_pins>;
+ pwm_config = <&wifi_pwm_conf>;
+ };
+
+ wifi_pwm_conf:wifi_pwm_conf{
+ pwm_channel1_conf {
+ pwms = <&pwm_ef MESON_PWM_0 30541 0>;
+ duty-cycle = <15270>;
+ times = <10>;
+ };
+ pwm_channel2_conf {
+ pwms = <&pwm_ef MESON_PWM_2 30500 0>;
+ duty-cycle = <15250>;
+ times = <12>;
+ };
+ };
+
+ codec_mm {
+ compatible = "amlogic, codec, mm";
+ memory-region = <&codec_mm_cma &codec_mm_reserved>;
+ dev_name = "codec_mm";
+ status = "okay";
+ };
+
+ ppmgr {
+ compatible = "amlogic, ppmgr";
+ memory-region = <&ppmgr_reserved>;
+ dev_name = "ppmgr";
+ status = "okay";
+ };
+
+ deinterlace {
+ compatible = "amlogic, deinterlace";
+ status = "okay";
+ /* 0:use reserved; 1:use cma; 2:use cma as reserved */
+ flag_cma = <1>;
+ //memory-region = <&di_reserved>;
+ memory-region = <&di_cma_reserved>;
+ interrupts = <0 46 1
+ 0 40 1>;
+ interrupt-names = "pre_irq", "post_irq";
+ clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>,
+ <&clkc CLKID_VPU_CLKB_COMP>;
+ clock-names = "vpu_clkb_tmp_composite",
+ "vpu_clkb_composite";
+ clock-range = <334 667>;
+ /* buffer-size = <3621952>;(yuv422 8bit) */
+ buffer-size = <4074560>;/*yuv422 fullpack*/
+ /* reserve-iomap = "true"; */
+ /* if enable nr10bit, set nr10bit-support to 1 */
+ post-wr-support = <1>;
+ nr10bit-support = <1>;
+ nrds-enable = <1>;
+ pps-enable = <1>;
+ };
+ ionvideo {
+ compatible = "amlogic, ionvideo";
+ dev_name = "ionvideo";
+ status = "okay";
+ };
+
+
+ partitions: partitions{
+ parts = <14>;
+ part-0 = <&logo>;
+ part-1 = <&recovery>;
+ part-2 = <&misc>;
+ part-3 = <&dto>;
+ part-4 = <&cri_data>;
+ part-5 = <¶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 = <SARADC_CH2 SARADC_CH2 SARADC_CH2>;
+ key_code = <114 115 28>;
+ key_val = <143 266 389>; //val=voltage/1800mV*1023
+ key_tolerance = <40 40 40>;
+ };
+
+ unifykey{
+ compatible = "amlogic, unifykey";
+ status = "ok";
+ unifykey-num = <15>;
+ unifykey-index-0 = <&keysn_0>;
+ unifykey-index-1 = <&keysn_1>;
+ unifykey-index-2 = <&keysn_2>;
+ unifykey-index-3 = <&keysn_3>;
+ unifykey-index-4 = <&keysn_4>;
+ unifykey-index-5 = <&keysn_5>;
+ unifykey-index-6 = <&keysn_6>;
+ unifykey-index-7 = <&keysn_7>;
+ unifykey-index-8 = <&keysn_8>;
+ unifykey-index-9 = <&keysn_9>;
+ unifykey-index-10= <&keysn_10>;
+ unifykey-index-11= <&keysn_11>;
+ unifykey-index-12= <&keysn_12>;
+ unifykey-index-13= <&keysn_13>;
+ unifykey-index-14= <&keysn_14>;
+
+ keysn_0: key_0{
+ key-name = "usid";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_1:key_1{
+ key-name = "mac";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_2:key_2{
+ key-name = "hdcp";
+ key-device = "secure";
+ key-type = "sha1";
+ key-permit = "read","write","del";
+ };
+ keysn_3:key_3{
+ key-name = "secure_boot_set";
+ key-device = "efuse";
+ key-permit = "write";
+ };
+ keysn_4:key_4{
+ key-name = "mac_bt";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ key-type = "mac";
+ };
+ keysn_5:key_5{
+ key-name = "mac_wifi";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ key-type = "mac";
+ };
+ keysn_6:key_6{
+ key-name = "hdcp2_tx";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_7:key_7{
+ key-name = "hdcp2_rx";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_8:key_8{
+ key-name = "widevinekeybox";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_9:key_9{
+ key-name = "deviceid";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_10:key_10{
+ key-name = "hdcp22_fw_private";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_11:key_11{
+ key-name = "PlayReadykeybox25";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_12:key_12{
+ key-name = "prpubkeybox";// PlayReady
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_13:key_13{
+ key-name = "prprivkeybox";// PlayReady
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_14:key_14{
+ key-name = "netflix_mgkid";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ };//End unifykey
+
+ amlvecm {
+ compatible = "amlogic, vecm";
+ dev_name = "aml_vecm";
+ status = "okay";
+ gamma_en = <0>;/*1:enabel ;0:disable*/
+ wb_en = <0>;/*1:enabel ;0:disable*/
+ cm_en = <0>;/*1:enabel ;0:disable*/
+ };
+ amdolby_vision {
+ compatible = "amlogic, dolby_vision_g12a";
+ dev_name = "aml_amdolby_vision_driver";
+ status = "okay";
+ tv_mode = <0>;/*1:enabel ;0:disable*/
+ };
+
+ /* Audio Related start */
+ pdm_codec:dummy{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, pdm_dummy_codec";
+ status = "okay";
+ };
+ dummy_codec:dummy{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, aml_dummy_codec";
+ status = "okay";
+ };
+ amlogic_codec:t9015{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, aml_codec_T9015";
+ reg = <0xFF632000 0x2000>;
+ is_auge_used = <1>; /* meson or auge chipset used */
+ tdmout_index = <1>;
+ status = "okay";
+ };
+ audio_effect:eqdrc{
+ /*eq_enable = <1>;*/
+ /*drc_enable = <1>;*/
+ /*
+ * 0:tdmout_a
+ * 1:tdmout_b
+ * 2:tdmout_c
+ * 3:spdifout
+ * 4:spdifout_b
+ */
+ eqdrc_module = <1>;
+ /* max 0xf, each bit for one lane, usually one lane */
+ lane_mask = <0x1>;
+ /* max 0xff, each bit for one channel */
+ channel_mask = <0x3>;
+ };
+ auge_sound {
+ compatible = "amlogic, g12a-sound-card";
+ aml-audio-card,name = "AML-AUGESOUND";
+
+ //aml-audio-card,loopback = <&aml_loopback>;
+ //aml-audio-card,aux-devs = <&amlogic_codec>;
+ /*avout mute gpio*/
+ avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
+ /*for audio effect ,eqdrc */
+ aml-audio-card,effect = <&audio_effect>;
+
+ aml-audio-card,dai-link@0 {
+ format = "dsp_a";
+ mclk-fs = <512>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ //bitclock-master = <&tdmacodec>;
+ //frame-master = <&tdmacodec>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-pcm";
+ tdmacpu: cpu {
+ sound-dai = <&aml_tdma>;
+ dai-tdm-slot-tx-mask =
+ <1 1 1 1 1 1 1 1>;
+ dai-tdm-slot-rx-mask =
+ <1 1 1 1 1 1 1 1>;
+ dai-tdm-slot-num = <8>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <24576000>;
+ };
+ tdmacodec: codec {
+ sound-dai = <&dummy_codec &dummy_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@1 {
+ format = "i2s";
+ mclk-fs = <256>;
+ continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ bitclock-master = <&aml_tdmb>;
+ frame-master = <&aml_tdmb>;
+ //bitclock-master = <&tdmbcodec>;
+ //frame-master = <&tdmbcodec>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-i2s";
+ cpu {
+ sound-dai = <&aml_tdmb>;
+ dai-tdm-slot-tx-mask = <1 1>;
+ dai-tdm-slot-rx-mask = <1 1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <12288000>;
+ };
+ tdmbcodec: codec {
+ sound-dai = <&dummy_codec &dummy_codec
+ &amlogic_codec &ad82584f_62>;
+ };
+ };
+
+ aml-audio-card,dai-link@2 {
+ format = "i2s";
+ mclk-fs = <256>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ bitclock-master = <&aml_tdmc>;
+ frame-master = <&aml_tdmc>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ //suffix-name = "alsaPORT-tdm";
+ cpu {
+ sound-dai = <&aml_tdmc>;
+ dai-tdm-slot-tx-mask = <1 1>;
+ dai-tdm-slot-rx-mask = <1 1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <12288000>;
+ };
+ codec {
+ sound-dai = <&dummy_codec &dummy_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@3 {
+ mclk-fs = <64>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-pdm";
+ cpu {
+ sound-dai = <&aml_pdm>;
+ };
+ codec {
+ sound-dai = <&pdm_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@4 {
+ mclk-fs = <128>;
+ continuous-clock;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-spdif";
+ cpu {
+ sound-dai = <&aml_spdif>;
+ system-clock-frequency = <6144000>;
+ };
+ codec {
+ sound-dai = <&dummy_codec>;
+ };
+ };
+ };
+ audiolocker: locker {
+ compatible = "amlogic, audiolocker";
+ clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT
+ &clkaudio CLKID_AUDIO_LOCKER_IN
+ &clkaudio CLKID_AUDIO_MCLK_D
+ &clkaudio CLKID_AUDIO_MCLK_E
+ &clkc CLKID_MPLL1
+ &clkc CLKID_MPLL2>;
+ clock-names = "lock_out", "lock_in", "out_src",
+ "in_src", "out_calc", "in_ref";
+ interrupts = <GIC_SPI 1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "irq";
+ frequency = <49000000>; /* pll */
+ dividor = <49>; /* locker's parent */
+ status = "okay";
+ };
+ /* Audio Related end */
+
+ cpu_opp_table0: cpu_opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <731000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <731000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <731000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <731000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <731000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <731000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <761000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <791000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <831000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <861000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <981000>;
+ };
+ };
+
+ cpu_opp_table1: cpu_opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <751000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <751000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <751000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <751000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <771000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <771000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <791000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <821000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <861000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <891000>;
+ };
+ };
+
+ cpufreq-meson {
+ compatible = "amlogic, cpufreq-meson";
+ status = "okay";
+ };
+
+ sensor: sensor {
+ compatible = "soc, sensor";
+ status = "okay";
+ sensor-name = "imx290"; /*imx290;os08a10;imx227*/
+ pinctrl-names="default";
+ pinctrl-0=<&clk12_24_z_pins>;
+ clocks = <&clkc CLKID_24M>;
+ clock-names = "g12a_24m";
+ reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>;
+ ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH
+ &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>;
+ };
+
+ iq: iq {
+ compatible = "soc, iq";
+ status = "okay";
+ sensor-name = "imx290"; /*imx290;os08a10;imx227*/
+ };
+}; /* end of / */
+
+&i2c2 {
+ status = "okay";
+ pinctrl-names="default";
+ pinctrl-0=<&i2c2_master_pins2>;
+ clock-frequency = <100000>; /* default 100k */
+ sensor-i2c@6c {
+ compatible = "arm, i2c-sensor";
+ reg = <0x6c>;
+ reg-names = "i2c-sensor";
+ slave-addr = <0x6c>;
+ reg-type = <2>;
+ reg-data-type = <1>;
+ link-device = <&phycsi>;
+ };
+};
+
+&isp {
+ status = "okay";
+ memory-region = <&isp_cma_reserved>;
+};
+
+&adapter {
+ status = "okay";
+ memory-region = <&adapt_cma_reserved>;
+};
+
+&gdc {
+ status = "okay";
+ memory-region = <&gdc_cma_reserved>;
+};
+
+&pwm_ab {
+ status = "okay";
+ };
+
+&pwm_ef {
+ status = "okay";
+ };
+
+&pwm_AO_cd {
+ status = "okay";
+ };
+
+&i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_master_pins2>;
+ clock-frequency = <400000>;
+
+ touchscreen@38 {
+ compatible = "focaltech,fts";
+ status = "disabled";
+ reg = <0x38>;
+ reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>;
+ irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>;
+ x_max = <720>;
+ y_max = <1280>;
+ max-touch-number = <10>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+ pinctrl-names="default";
+ pinctrl-0=<&i2c3_master_pins2>;
+ clock-frequency = <100000>; /* default 100k */
+
+ /* for ref board */
+ ad82584f_62: ad82584f_62@62 {
+ compatible = "ESMT, ad82584f";
+ #sound-dai-cells = <0>;
+ reg = <0x31>;
+ status = "okay";
+ reset_pin = <&gpio GPIOA_5 0>;
+ };
+
+ tlv320adc3101_32: tlv320adc3101_32@32 {
+ compatible = "ti,tlv320adc3101";
+ #sound-dai-cells = <0>;
+ reg = <0x19>;
+ differential_pair = <1>;
+ status = "disabled";
+ };
+
+ bl_extern_i2c {
+ compatible = "bl_extern, i2c";
+ dev_name = "lp8556";
+ reg = <0x2c>;
+ status = "disabled";
+ };
+};
+
+&audiobus {
+ aml_tdma: tdma {
+ compatible = "amlogic, g12a-snd-tdma";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <0 1>;
+ dai-tdm-oe-lane-slot-mask-out = <1 0>;
+ dai-tdm-clk-sel = <0>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_A
+ &clkc CLKID_MPLL0>;
+ clock-names = "mclk", "clk_srcpll";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmout_a &tdmin_a>;
+ };
+
+ aml_tdmb: tdmb {
+ compatible = "amlogic, g12a-snd-tdmb";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <0 1 0 0>;
+ dai-tdm-lane-slot-mask-out = <1 0 0 0>;
+ dai-tdm-clk-sel = <1>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_B
+ &clkc CLKID_MPLL1
+ &clkc CLKID_MPLL0
+ &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>;
+ clock-names = "mclk", "clk_srcpll",
+ "samesource_srcpll", "samesource_clk";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>;
+ /*
+ * 0: tdmout_a;
+ * 1: tdmout_b;
+ * 2: tdmout_c;
+ * 3: spdifout;
+ * 4: spdifout_b;
+ */
+ samesource_sel = <3>;
+ };
+
+ aml_tdmc: tdmc {
+ compatible = "amlogic, g12a-snd-tdmc";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <1 0 0 0>;
+ #dai-tdm-lane-slot-mask-out = <1 0 1 1>;
+ #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>;
+ #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>;
+ dai-tdm-clk-sel = <2>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_C
+ &clkc CLKID_MPLL2>;
+ clock-names = "mclk", "clk_srcpll";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>;
+ };
+
+ /* copy a useless tdm to output for hdmi, no pinmux */
+ aml_i2s2hdmi: i2s2hdmi {
+ compatible = "amlogic, g12a-snd-tdmc";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-out = <1 1 1 1>;
+ dai-tdm-clk-sel = <2>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_C
+ &clkc CLKID_MPLL2>;
+ clock-names = "mclk", "clk_srcpll";
+
+ i2s2hdmi = <1>;
+
+ status = "okay";
+ };
+
+ aml_spdif: spdif {
+ compatible = "amlogic, g12a-snd-spdif-a";
+ #sound-dai-cells = <0>;
+ clocks = <&clkc CLKID_MPLL0
+ &clkc CLKID_FCLK_DIV4
+ &clkaudio CLKID_AUDIO_SPDIFIN
+ &clkaudio CLKID_AUDIO_SPDIFOUT
+ &clkaudio CLKID_AUDIO_SPDIFIN_CTRL
+ &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>;
+ clock-names = "sysclk", "fixed_clk", "gate_spdifin",
+ "gate_spdifout", "clk_spdifin", "clk_spdifout";
+ interrupts =
+ <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-names = "irq_spdifin";
+ pinctrl-names = "spdif_pins",
+ "spdif_pins_mute";
+ pinctrl-0 = <&spdifout &spdifin>;
+ pinctrl-1 = <&spdifout_a_mute>;
+ status = "okay";
+ };
+ aml_spdif_b: spdif_b {
+ compatible = "amlogic, g12a-snd-spdif-b";
+ #sound-dai-cells = <0>;
+ clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/
+ &clkaudio CLKID_AUDIO_SPDIFOUTB
+ &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>;
+ clock-names = "sysclk",
+ "gate_spdifout", "clk_spdifout";
+ status = "disabled";
+ };
+ aml_pdm: pdm {
+ compatible = "amlogic, g12a-snd-pdm";
+ #sound-dai-cells = <0>;
+ clocks = <&clkaudio CLKID_AUDIO_PDM
+ &clkc CLKID_FCLK_DIV3
+ &clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_PDMIN0
+ &clkaudio CLKID_AUDIO_PDMIN1>;
+ clock-names = "gate",
+ "sysclk_srcpll",
+ "dclk_srcpll",
+ "pdm_dclk",
+ "pdm_sysclk";
+ pinctrl-names = "pdm_pins";
+ pinctrl-0 = <&pdmin>;
+ filter_mode = <1>; /* mode 0~4, defalut:1 */
+ status = "okay";
+ };
+ aml_loopback: loopback {
+ compatible = "amlogic, snd-loopback";
+ /*
+ * 0: out rate = in data rate;
+ * 1: out rate = loopback data rate;
+ */
+ lb_mode = <0>;
+
+ /* datain src
+ * 0: tdmin_a;
+ * 1: tdmin_b;
+ * 2: tdmin_c;
+ * 3: spdifin;
+ * 4: pdmin;
+ */
+ datain_src = <4>;
+ datain_chnum = <8>;
+ datain_chmask = <0x3f>;
+
+ /* tdmin_lb src
+ * 0: tdmoutA
+ * 1: tdmoutB
+ * 2: tdmoutC
+ * 3: PAD_tdminA
+ * 4: PAD_tdminB
+ * 5: PAD_tdminC
+ */
+ datalb_src = <2>;
+ datalb_chnum = <8>;
+ datalb_chmask = <0x3>;
+
+ status = "disabled";
+ };
+
+ audioresample: resample {
+ compatible = "amlogic, g12a-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A, 0
+ * TDMIN_B, 1
+ * TDMIN_C, 2
+ * SPDIFIN, 3
+ * PDMIN, 4
+ * NONE,
+ * TDMIN_LB, 6
+ * LOOPBACK, 7
+ */
+ resample_module = <4>;
+ status = "disabled";
+ };
+ aml_pwrdet: pwrdet {
+ compatible = "amlogic, g12a-power-detect";
+
+ interrupts = <GIC_SPI 155 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "pwrdet_irq";
+
+ /* pwrdet source sel
+ * 7: loopback;
+ * 6: tdmin_lb;
+ * 5: reserved;
+ * 4: pdmin;
+ * 3: spdifin;
+ * 2: tdmin_c;
+ * 1: tdmin_b;
+ * 0: tdmin_a;
+ */
+ pwrdet_src = <4>;
+
+ hi_th = <0x70000>;
+ lo_th = <0x16000>;
+
+ status = "disabled";
+ };
+}; /* end of audiobus */
+
+&pinctrl_periphs {
+ tdmout_a: tdmout_a {
+ mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */
+ groups = "tdma_sclk",
+ "tdma_fs",
+ "tdma_dout0";
+ function = "tdma_out";
+ };
+ };
+
+ tdmin_a: tdmin_a {
+ mux { /* GPIOX_8 */
+ groups = "tdma_din1";
+ function = "tdma_in";
+ };
+ };
+
+ tdmb_mclk: tdmb_mclk {
+ mux {
+ groups = "mclk0_a";
+ function = "mclk0";
+ drive-strength = <2>;
+ };
+ };
+ tdmout_b: tdmout_b {
+ mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */
+ groups = "tdmb_sclk",
+ "tdmb_fs",
+ "tdmb_dout0";
+ function = "tdmb_out";
+ drive-strength = <2>;
+ };
+ };
+
+ tdmin_b:tdmin_b {
+ mux { /* GPIOA_4 */
+ groups = "tdmb_din1"
+ /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/;
+ function = "tdmb_in";
+ drive-strength = <2>;
+ };
+ };
+
+ tdmc_mclk: tdmc_mclk {
+ mux { /* GPIOA_11 */
+ groups = "mclk1_a";
+ function = "mclk1";
+ };
+ };
+
+ clk12_24_z_pins:clk12_24_z_pins {
+ mux {
+ groups = "clk12_24_z";
+ function = "clk12_24_ee";
+ drive-strength = <3>;
+ };
+ };
+
+ tdmout_c:tdmout_c {
+ mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/
+ groups = "tdmc_sclk_a",
+ "tdmc_fs_a",
+ "tdmc_dout0_a"
+ /*, "tdmc_dout2",
+ * "tdmc_dout3"
+ */;
+ function = "tdmc_out";
+ };
+ };
+
+ tdmin_c:tdmin_c {
+ mux { /* GPIOA_10 */
+ groups = "tdmc_din0_a";
+ function = "tdmc_in";
+ };
+ };
+
+ spdifin: spdifin {
+ mux {/* GPIOH_5 */
+ groups = "spdif_in_h";
+ function = "spdif_in";
+ };
+ };
+
+ /* GPIOH_4 */
+ /*
+ * spdifout: spdifout {
+ * mux {
+ * groups = "spdif_out_h";
+ * function = "spdif_out";
+ * };
+ *};
+ */
+
+ pdmin: pdmin {
+ mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/
+ groups = "pdm_din0_a",
+ /*"pdm_din1_a",*/
+ "pdm_din2_a",
+ /*"pdm_din3_a",*/
+ "pdm_dclk_a";
+ function = "pdm";
+ };
+ };
+
+ bl_pwm_off_pins:bl_pwm_off_pin {
+ mux {
+ pins = "GPIOH_5";
+ function = "gpio_periphs";
+ output-high;
+ };
+ };
+
+}; /* end of pinctrl_periphs */
+
+&pinctrl_aobus {
+ spdifout: spdifout {
+ mux { /* gpiao_10 */
+ groups = "spdif_out_ao";
+ function = "spdif_out_ao";
+ };
+ };
+
+ spdifout_a_mute: spdifout_a_mute {
+ mux { /* gpiao_10 */
+ groups = "GPIOAO_10";
+ function = "gpio_periphs";
+ };
+ };
+}; /* end of pinctrl_aobus */
+
+&irblaster {
+ status = "disabled";
+};
+
+&audio_data {
+ status = "okay";
+};
+
+/*if you want to use vdin just modify status to "ok"*/
+&vdin0 {
+ memory-region = <&vdin0_cma_reserved>;
+ status = "okay";
+ /*vdin write mem color depth support:
+ *bit0:support 8bit
+ *bit1:support 9bit
+ *bit2:support 10bit
+ *bit3:support 12bit
+ *bit4:support yuv422 10bit full pack mode (from txl new add)
+ */
+ tv_bit_mode = <0x15>;
+};
+&vdin1 {
+ memory-region = <&vdin1_cma_reserved>;
+ status = "okay";
+ /*vdin write mem color depth support:
+ *bit0:support 8bit
+ *bit1:support 9bit
+ *bit2:support 10bit
+ *bit3:support 12bit
+ */
+ tv_bit_mode = <1>;
+};
+
+&sd_emmc_c {
+ status = "okay";
+ emmc {
+ caps = "MMC_CAP_8_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED",
+ "MMC_CAP_NONREMOVABLE",
+ /* "MMC_CAP_1_8V_DDR", */
+ "MMC_CAP_HW_RESET",
+ "MMC_CAP_ERASE",
+ "MMC_CAP_CMD23";
+ caps2 = "MMC_CAP2_HS200";
+ /* "MMC_CAP2_HS400";*/
+ f_min = <400000>;
+ f_max = <200000000>;
+ };
+};
+
+&sd_emmc_b {
+ status = "okay";
+ sd {
+ caps = "MMC_CAP_4_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED";
+ f_min = <400000>;
+ f_max = <50000000>;
+ };
+};
+
+&sd_emmc_a {
+ status = "okay";
+ sdio {
+ caps = "MMC_CAP_4_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED",
+ "MMC_CAP_NONREMOVABLE",
+ "MMC_CAP_UHS_SDR12",
+ "MMC_CAP_UHS_SDR25",
+ "MMC_CAP_UHS_SDR50",
+ "MMC_CAP_UHS_SDR104",
+ "MMC_PM_KEEP_POWER",
+ "MMC_CAP_SDIO_IRQ";
+ f_min = <400000>;
+ f_max = <200000000>;
+ };
+};
+
+&nand {
+ status = "disabled";
+ plat-names = "bootloader","nandnormal";
+ plat-num = <2>;
+ plat-part-0 = <&bootloader>;
+ plat-part-1 = <&nandnormal>;
+ bootloader: bootloader{
+ enable_pad ="ce0";
+ busy_pad = "rb0";
+ timming_mode = "mode5";
+ bch_mode = "bch8_1k";
+ t_rea = <20>;
+ t_rhoh = <15>;
+ chip_num = <1>;
+ part_num = <0>;
+ rb_detect = <1>;
+ };
+ nandnormal: nandnormal{
+ enable_pad ="ce0";
+ busy_pad = "rb0";
+ timming_mode = "mode5";
+ bch_mode = "bch8_1k";
+ plane_mode = "twoplane";
+ t_rea = <20>;
+ t_rhoh = <15>;
+ chip_num = <2>;
+ part_num = <3>;
+ partition = <&nand_partitions>;
+ rb_detect = <1>;
+ };
+ nand_partitions:nand_partition{
+ /*
+ * if bl_mode is 1, tpl size was generate by
+ * fip_copies * fip_size which
+ * will not skip bad when calculating
+ * the partition size;
+ *
+ * if bl_mode is 0,
+ * tpl partition must be comment out.
+ */
+ tpl{
+ offset=<0x0 0x0>;
+ size=<0x0 0x0>;
+ };
+ logo{
+ offset=<0x0 0x0>;
+ size=<0x0 0x200000>;
+ };
+ recovery{
+ offset=<0x0 0x0>;
+ size=<0x0 0x1000000>;
+ };
+ boot{
+ offset=<0x0 0x0>;
+ size=<0x0 0x1000000>;
+ };
+ system{
+ offset=<0x0 0x0>;
+ size=<0x0 0x4000000>;
+ };
+ data{
+ offset=<0xffffffff 0xffffffff>;
+ size=<0x0 0x0>;
+ };
+ };
+};
+&dwc3 {
+ status = "okay";
+};
+
+&usb2_phy_v2 {
+ status = "okay";
+ portnum = <2>;
+};
+
+&usb3_phy_v2 {
+ status = "okay";
+ portnum = <0>;
+ otg = <1>;
+ gpio-vbus-power = "GPIOH_6";
+ gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>;
+};
+
+&dwc2_a {
+ status = "okay";
+ /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/
+ controller-type = <3>;
+};
+ð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";
+ osd_ver = /bits/ 8 <OSD_V3>;
+};
+
+&drm_amhdmitx {
+ status = "okay";
+ hdcp = "disabled";
+};
+
+&drm_lcd {
+ status = "disable";
+};
* more details.
*
*/
+#include <dt-bindings/display/meson-drm-ids.h>
/ {
venc-cvbs {
status = "okay";
- compatible = "amlogic,meson-gxbb-cvbs";
+ compatible = "amlogic, meson-g12a-cvbs";
ports {
#address-cells = <1>;
status = "okay";
compatible = "amlogic,drm-subsystem";
ports = <&vpu_out>;
+
+ vpu_topology: vpu_topology {
+ vpu_blocks {
+ osd1_block: block@0 {
+ id = /bits/ 8 <OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <0>;
+ block_name = "osd1_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd1_block>;
+ };
+ osd2_block: block@1 {
+ id = /bits/ 8 <OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <0>;
+ block_name = "osd2_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd2_block>;
+ };
+ osd3_block: block@2 {
+ id = /bits/ 8 <OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <0>;
+ block_name = "osd3_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd3_block>;
+ };
+ afbc_osd1_block: block@3 {
+ id = /bits/ 8 <AFBC_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &osd_blend_block>;
+ };
+ afbc_osd2_block: block@4 {
+ id = /bits/ 8 <AFBC_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd2_block>;
+ };
+ afbc_osd3_block: block@5 {
+ id = /bits/ 8 <AFBC_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd3_block>;
+ };
+ scaler_osd1_block: block@6 {
+ id = /bits/ 8 <SCALER_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_hdr_dolby_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &vpp_postblend_block>;
+ };
+ scaler_osd2_block: block@7 {
+ id = /bits/ 8 <SCALER_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <2 &osd_blend_block>;
+ };
+ scaler_osd3_block: block@8 {
+ id = /bits/ 8 <SCALER_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <3 &osd_blend_block>;
+ };
+ osd_blend_block: block@9 {
+ id = /bits/ 8 <OSD_BLEND_BLOCK>;
+ block_name = "osd_blend_block";
+ type = /bits/ 8 <3>;
+ num_in_links = /bits/ 8 <0x3>;
+ in_links = <0 &afbc_osd1_block>,
+ <0 &scaler_osd2_block>,
+ <0 &scaler_osd3_block>;
+ num_out_links = /bits/ 8 <0x2>;
+ out_links = <0 &osd1_hdr_dolby_block>,
+ <1 &vpp_postblend_block>;
+ };
+ osd1_hdr_dolby_block: block@10 {
+ id = /bits/ 8 <OSD1_HDR_BLOCK>;
+ block_name = "osd1_hdr_dolby_block";
+ type = /bits/ 8 <4>;
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd_blend_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd1_block>;
+ };
+ vpp_postblend_block: block@12 {
+ id = /bits/ 8 <VPP_POSTBLEND_BLOCK>;
+ block_name = "vpp_postblend_block";
+ type = /bits/ 8 <6>;
+ num_in_links = /bits/ 8 <0x2>;
+ in_links = <0 &scaler_osd1_block>,
+ <1 &osd_blend_block>;
+ num_out_links = <0x0>;
+ };
+ };
+ };
+
+ vpu_hw_para: vpu_hw_para@0 {
+ osd_ver = /bits/ 8 <0x2>;
+ afbc_type = /bits/ 8 <0x2>;
+ has_deband = /bits/ 8 <0x1>;
+ has_lut = /bits/ 8 <0x1>;
+ has_rdma = /bits/ 8 <0x1>;
+ osd_fifo_len = /bits/ 8 <64>;
+ vpp_fifo_len = /bits/ 32 <0xfff>;
+ };
};
};
--- /dev/null
+/*
+ * arch/arm/boot/dts/amlogic/meson_drm.dtsi
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <dt-bindings/display/meson-drm-ids.h>
+
+/ {
+ venc-cvbs {
+ status = "okay";
+ compatible = "amlogic, meson-g12b-cvbs";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ enc_cvbs_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ //venc_cvbs_in_vpu: endpoint@0 {
+ // reg = <0>;
+ // remote-endpoint = <&vpu_out_venc_cvbs>;
+ //};
+ };
+ };
+ };
+
+ drm_amhdmitx: drm-amhdmitx {
+ status = "disabled";
+ hdcp = "disabled";
+ compatible = "amlogic,drm-amhdmitx";
+ dev_name = "meson-amhdmitx";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+ ports {
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ hdmi_in_vpu: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_hdmi>;
+ };
+ };
+ };
+ };
+
+ drm_lcd: drm-lcd {
+ status = "disabled";
+ compatible = "amlogic,drm-lcd";
+ dev_name = "meson-lcd";
+ ports {
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ lcd_in_vpu: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_lcd>;
+ };
+ };
+ };
+ };
+
+ drm_vpu: drm-vpu@0xff900000 {
+ status = "disabled";
+ compatible = "amlogic,meson-g12b-vpu";
+ memory-region = <&logo_reserved>;
+ reg = <0xff900000 0x40000>,
+ <0xff63c000 0x2000>,
+ <0xff638000 0x2000>;
+ reg-names = "base", "hhi", "dmc";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 56 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "viu-vsync", "viu2-vsync";
+ clocks = <&clkc CLKID_VPU_CLKC_MUX>;
+ clock-names = "vpu_clkc";
+ dma-coherent;
+ vpu_out: port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vpu_out_hdmi: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hdmi_in_vpu>;
+ };
+ vpu_out_lcd: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&lcd_in_vpu>;
+ };
+ };
+ };
+
+ drm_subsystem: drm-subsystem {
+ status = "okay";
+ compatible = "amlogic,drm-subsystem";
+ ports = <&vpu_out>;
+
+ vpu_topology: vpu_topology {
+ vpu_blocks {
+ osd1_block: block@0 {
+ id = /bits/ 8 <OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <0>;
+ block_name = "osd1_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd1_block>;
+ };
+ osd2_block: block@1 {
+ id = /bits/ 8 <OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <0>;
+ block_name = "osd2_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd2_block>;
+ };
+ osd3_block: block@2 {
+ id = /bits/ 8 <OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <0>;
+ block_name = "osd3_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd3_block>;
+ };
+ afbc_osd1_block: block@3 {
+ id = /bits/ 8 <AFBC_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &osd_blend_block>;
+ };
+ afbc_osd2_block: block@4 {
+ id = /bits/ 8 <AFBC_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd2_block>;
+ };
+ afbc_osd3_block: block@5 {
+ id = /bits/ 8 <AFBC_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd3_block>;
+ };
+ scaler_osd1_block: block@6 {
+ id = /bits/ 8 <SCALER_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_hdr_dolby_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &vpp_postblend_block>;
+ };
+ scaler_osd2_block: block@7 {
+ id = /bits/ 8 <SCALER_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <2 &osd_blend_block>;
+ };
+ scaler_osd3_block: block@8 {
+ id = /bits/ 8 <SCALER_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <3 &osd_blend_block>;
+ };
+ osd_blend_block: block@9 {
+ id = /bits/ 8 <OSD_BLEND_BLOCK>;
+ block_name = "osd_blend_block";
+ type = /bits/ 8 <3>;
+ num_in_links = /bits/ 8 <0x3>;
+ in_links = <0 &afbc_osd1_block>,
+ <0 &scaler_osd2_block>,
+ <0 &scaler_osd3_block>;
+ num_out_links = /bits/ 8 <0x2>;
+ out_links = <0 &osd1_hdr_dolby_block>,
+ <1 &vpp_postblend_block>;
+ };
+ osd1_hdr_dolby_block: block@10 {
+ id = /bits/ 8 <OSD1_HDR_BLOCK>;
+ block_name = "osd1_hdr_dolby_block";
+ type = /bits/ 8 <4>;
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd_blend_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd1_block>;
+ };
+ vpp_postblend_block: block@12 {
+ id = /bits/ 8 <VPP_POSTBLEND_BLOCK>;
+ block_name = "vpp_postblend_block";
+ type = /bits/ 8 <6>;
+ num_in_links = /bits/ 8 <0x2>;
+ in_links = <0 &scaler_osd1_block>,
+ <1 &osd_blend_block>;
+ num_out_links = <0x0>;
+ };
+ };
+ };
+
+ vpu_hw_para: vpu_hw_para@0 {
+ osd_ver = /bits/ 8 <0x2>;
+ afbc_type = /bits/ 8 <0x2>;
+ has_deband = /bits/ 8 <0x1>;
+ has_lut = /bits/ 8 <0x1>;
+ has_rdma = /bits/ 8 <0x1>;
+ osd_fifo_len = /bits/ 8 <64>;
+ vpp_fifo_len = /bits/ 32 <0xfff>;
+ };
+ };
+};
&drm_vpu {
status = "okay";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V1>;
};
&drm_amhdmitx {
#include "mesong12b.dtsi"
#include "mesong12b_skt-panel.dtsi"
-#include "mesong12a_drm.dtsi"
+#include "mesong12b_drm.dtsi"
/ {
model = "Amlogic";
status = "okay";
compatible = "amlogic,meson-g12b-vpu";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V3>;
};
&drm_amhdmitx {
status = "okay";
compatible = "amlogic,meson-g12b-vpu";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V2>;
};
&drm_amhdmitx {
--- /dev/null
+/*
+ * arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+/dts-v1/;
+
+#include "mesong12b_a.dtsi"
+#include "mesong12b_skt-panel.dtsi"
+#include "mesong12b_drm.dtsi"
+
+/ {
+ model = "Amlogic";
+ amlogic-dt-id = "g12b_w400_a";
+ compatible = "amlogic, g12b";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ serial0 = &uart_AO;
+ serial1 = &uart_A;
+ serial2 = &uart_B;
+ serial3 = &uart_C;
+ serial4 = &uart_AO_B;
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c_AO;
+ tsensor0 = &p_tsensor;
+ tsensor1 = &d_tsensor;
+ };
+
+ memory@00000000 {
+ device_type = "memory";
+ linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ /* global autoconfigured region for contiguous allocations */
+ ramoops@0x07400000 {
+ compatible = "ramoops";
+ reg = <0x0 0x07400000 0x0 0x00100000>;
+ record-size = <0x8000>;
+ console-size = <0x8000>;
+ ftrace-size = <0x0>;
+ pmsg-size = <0x8000>;
+ };
+
+ secmon_reserved:linux,secmon {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x400000>;
+ alignment = <0x0 0x400000>;
+ alloc-ranges = <0x0 0x05000000 0x0 0x400000>;
+ clear-map;
+ };
+
+ secos_reserved:linux,secos {
+ status = "disable";
+ compatible = "amlogic, aml_secos_memory";
+ reg = <0x0 0x05300000 0x0 0x2000000>;
+ no-map;
+ };
+ logo_reserved:linux,meson-fb {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x800000>;
+ alignment = <0x0 0x400000>;
+ alloc-ranges = <0x0 0x7f800000 0x0 0x800000>;
+ };
+ ion_cma_reserved:linux,ion-dev {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x8000000>;
+ alignment = <0x0 0x400000>;
+ };
+
+ //di_reserved:linux,di {
+ //compatible = "amlogic, di-mem";
+ /* buffer_size = 3621952(yuv422 8bit) */
+ /* 4179008(yuv422 10bit full pack mode) */
+ /** 10x3621952=34.6M(0x23) support 8bit **/
+ /** 10x4736064=45.2M(0x2e) support 12bit **/
+ /** 10x4179008=40M(0x28) support 10bit **/
+ //size = <0x0 0x2800000>;
+ //no-map;
+ //};
+ /*di CMA pool */
+ di_cma_reserved:linux,di_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* buffer_size = 3621952(yuv422 8bit)
+ * | 4736064(yuv422 10bit)
+ * | 4074560(yuv422 10bit full pack mode)
+ * 10x3621952=34.6M(0x23) support 8bit
+ * 10x4736064=45.2M(0x2e) support 12bit
+ * 10x4074560=40M(0x28) support 10bit
+ */
+ size = <0x0 0x02800000>;
+ alignment = <0x0 0x400000>;
+ };
+ /* POST PROCESS MANAGER */
+ ppmgr_reserved:linux,ppmgr {
+ compatible = "shared-dma-pool";
+ size = <0x0 0x0>;
+ };
+ codec_mm_cma:linux,codec_mm_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* ion_codec_mm max can alloc size 80M*/
+ size = <0x0 0x13400000>;
+ alignment = <0x0 0x400000>;
+ linux,contiguous-region;
+ };
+ /* codec shared reserved */
+ codec_mm_reserved:linux,codec_mm_reserved {
+ compatible = "amlogic, codec-mm-reserved";
+ size = <0x0 0x0>;
+ alignment = <0x0 0x100000>;
+ //no-map;
+ };
+ /* vdin0 CMA pool */
+ vdin0_cma_reserved:linux,vdin0_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* 1920x1080x2x4 =16+4 M */
+ size = <0x0 0x04000000>;
+ alignment = <0x0 0x400000>;
+ };
+ /* vdin1 CMA pool */
+ vdin1_cma_reserved:linux,vdin1_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* 1920x1080x2x4 =16 M */
+ size = <0x0 0x04000000>;
+ alignment = <0x0 0x400000>;
+ };
+ galcore_reserved:linux,galcore {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x0>;
+ alignment = <0x0 0x400000>;
+ linux,contiguous-region;
+ };
+
+ isp_cma_reserved:linux,isp_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x0 0x10000000>;
+ alignment = <0x0 0x400000>;
+ };
+
+ adapt_cma_reserved:linux,adapt_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x0 0x03000000>;
+ alignment = <0x0 0x400000>;
+ };
+ gdc_cma_reserved:linux,gdc_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x0 0x04000000>;
+ alignment = <0x0 0x400000>;
+ };
+ };
+ galcore {
+ status = "okay";
+ memory-region = <&galcore_reserved>;
+ };
+ gpioleds {
+ compatible = "gpio-leds";
+ status = "okay";
+
+ sys_led {
+ label="sys_led";
+ gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>;
+ default-state ="on";
+ retain-state-suspended;
+ linux,default-trigger="cpu0";
+ };
+ };
+
+ cvbsout {
+ compatible = "amlogic, cvbsout-g12b";
+ dev_name = "cvbsout";
+ status = "okay";
+ clocks = <&clkc CLKID_VCLK2_ENCI
+ &clkc CLKID_VCLK2_VENCI0
+ &clkc CLKID_VCLK2_VENCI1
+ &clkc CLKID_DAC_CLK>;
+ clock-names = "venci_top_gate",
+ "venci_0_gate",
+ "venci_1_gate",
+ "vdac_clk_gate";
+
+ /* performance: reg_address, reg_value */
+ /* g12b */
+ performance = <0x1bf0 0x9
+ 0x1b56 0x333
+ 0x1b12 0x8080
+ 0x1b05 0xfd
+ 0x1c59 0xf850
+ 0xffff 0x0>; /* ending flag */
+ performance_sarft = <0x1bf0 0x9
+ 0x1b56 0x333
+ 0x1b12 0x0
+ 0x1b05 0x9
+ 0x1c59 0xfc48
+ 0xffff 0x0>; /* ending flag */
+ };
+
+ bt-dev{
+ compatible = "amlogic, bt-dev";
+ dev_name = "bt-dev";
+ status = "okay";
+ gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+ gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>;
+ };
+
+ wifi{
+ compatible = "amlogic, aml_wifi";
+ dev_name = "aml_wifi";
+ status = "okay";
+ interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>;
+ irq_trigger_type = "GPIO_IRQ_LOW";
+ power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>;
+ dhd_static_buf; //if use bcm wifi, config dhd_static_buf
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_e_pins>;
+ pwm_config = <&wifi_pwm_conf>;
+ };
+
+ wifi_pwm_conf:wifi_pwm_conf{
+ pwm_channel1_conf {
+ pwms = <&pwm_ef MESON_PWM_0 30541 0>;
+ duty-cycle = <15270>;
+ times = <10>;
+ };
+ pwm_channel2_conf {
+ pwms = <&pwm_ef MESON_PWM_2 30500 0>;
+ duty-cycle = <15250>;
+ times = <12>;
+ };
+ };
+
+ codec_mm {
+ compatible = "amlogic, codec, mm";
+ memory-region = <&codec_mm_cma &codec_mm_reserved>;
+ dev_name = "codec_mm";
+ status = "okay";
+ };
+
+ ppmgr {
+ compatible = "amlogic, ppmgr";
+ memory-region = <&ppmgr_reserved>;
+ dev_name = "ppmgr";
+ status = "okay";
+ };
+
+ deinterlace {
+ compatible = "amlogic, deinterlace";
+ status = "okay";
+ /* 0:use reserved; 1:use cma; 2:use cma as reserved */
+ flag_cma = <1>;
+ //memory-region = <&di_reserved>;
+ memory-region = <&di_cma_reserved>;
+ interrupts = <0 46 1
+ 0 40 1>;
+ interrupt-names = "pre_irq", "post_irq";
+ clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>,
+ <&clkc CLKID_VPU_CLKB_COMP>;
+ clock-names = "vpu_clkb_tmp_composite",
+ "vpu_clkb_composite";
+ clock-range = <334 667>;
+ /* buffer-size = <3621952>;(yuv422 8bit) */
+ buffer-size = <4074560>;/*yuv422 fullpack*/
+ /* reserve-iomap = "true"; */
+ /* if enable nr10bit, set nr10bit-support to 1 */
+ post-wr-support = <1>;
+ nr10bit-support = <1>;
+ nrds-enable = <1>;
+ pps-enable = <1>;
+ };
+ ionvideo {
+ compatible = "amlogic, ionvideo";
+ dev_name = "ionvideo";
+ status = "okay";
+ };
+
+
+ partitions: partitions{
+ parts = <14>;
+ part-0 = <&logo>;
+ part-1 = <&recovery>;
+ part-2 = <&misc>;
+ part-3 = <&dto>;
+ part-4 = <&cri_data>;
+ part-5 = <¶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 = <SARADC_CH2 SARADC_CH2 SARADC_CH2>;
+ key_code = <114 115 28>;
+ key_val = <143 266 389>; //val=voltage/1800mV*1023
+ key_tolerance = <40 40 40>;
+ };
+
+ unifykey{
+ compatible = "amlogic, unifykey";
+ status = "ok";
+ unifykey-num = <15>;
+ unifykey-index-0 = <&keysn_0>;
+ unifykey-index-1 = <&keysn_1>;
+ unifykey-index-2 = <&keysn_2>;
+ unifykey-index-3 = <&keysn_3>;
+ unifykey-index-4 = <&keysn_4>;
+ unifykey-index-5 = <&keysn_5>;
+ unifykey-index-6 = <&keysn_6>;
+ unifykey-index-7 = <&keysn_7>;
+ unifykey-index-8 = <&keysn_8>;
+ unifykey-index-9 = <&keysn_9>;
+ unifykey-index-10= <&keysn_10>;
+ unifykey-index-11= <&keysn_11>;
+ unifykey-index-12= <&keysn_12>;
+ unifykey-index-13= <&keysn_13>;
+ unifykey-index-14= <&keysn_14>;
+
+ keysn_0: key_0{
+ key-name = "usid";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_1:key_1{
+ key-name = "mac";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_2:key_2{
+ key-name = "hdcp";
+ key-device = "secure";
+ key-type = "sha1";
+ key-permit = "read","write","del";
+ };
+ keysn_3:key_3{
+ key-name = "secure_boot_set";
+ key-device = "efuse";
+ key-permit = "write";
+ };
+ keysn_4:key_4{
+ key-name = "mac_bt";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ key-type = "mac";
+ };
+ keysn_5:key_5{
+ key-name = "mac_wifi";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ key-type = "mac";
+ };
+ keysn_6:key_6{
+ key-name = "hdcp2_tx";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_7:key_7{
+ key-name = "hdcp2_rx";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_8:key_8{
+ key-name = "widevinekeybox";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_9:key_9{
+ key-name = "deviceid";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_10:key_10{
+ key-name = "hdcp22_fw_private";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_11:key_11{
+ key-name = "PlayReadykeybox25";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_12:key_12{
+ key-name = "prpubkeybox";// PlayReady
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_13:key_13{
+ key-name = "prprivkeybox";// PlayReady
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_14:key_14{
+ key-name = "netflix_mgkid";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ };//End unifykey
+
+ amlvecm {
+ compatible = "amlogic, vecm";
+ dev_name = "aml_vecm";
+ status = "okay";
+ gamma_en = <0>;/*1:enabel ;0:disable*/
+ wb_en = <0>;/*1:enabel ;0:disable*/
+ cm_en = <0>;/*1:enabel ;0:disable*/
+ };
+ amdolby_vision {
+ compatible = "amlogic, dolby_vision_g12a";
+ dev_name = "aml_amdolby_vision_driver";
+ status = "okay";
+ tv_mode = <0>;/*1:enabel ;0:disable*/
+ };
+
+ /* Audio Related start */
+ pdm_codec:dummy{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, pdm_dummy_codec";
+ status = "okay";
+ };
+ dummy_codec:dummy{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, aml_dummy_codec";
+ status = "okay";
+ };
+ amlogic_codec:t9015{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, aml_codec_T9015";
+ reg = <0x0 0xFF632000 0x0 0x2000>;
+ is_auge_used = <1>; /* meson or auge chipset used */
+ tdmout_index = <1>;
+ status = "okay";
+ };
+ audio_effect:eqdrc{
+ /*eq_enable = <1>;*/
+ /*drc_enable = <1>;*/
+ /*
+ * 0:tdmout_a
+ * 1:tdmout_b
+ * 2:tdmout_c
+ * 3:spdifout
+ * 4:spdifout_b
+ */
+ eqdrc_module = <1>;
+ /* max 0xf, each bit for one lane, usually one lane */
+ lane_mask = <0x1>;
+ /* max 0xff, each bit for one channel */
+ channel_mask = <0x3>;
+ };
+ auge_sound {
+ compatible = "amlogic, g12a-sound-card";
+ aml-audio-card,name = "AML-AUGESOUND";
+
+ //aml-audio-card,loopback = <&aml_loopback>;
+ //aml-audio-card,aux-devs = <&amlogic_codec>;
+ /*avout mute gpio*/
+ avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
+ /*for audio effect ,eqdrc */
+ aml-audio-card,effect = <&audio_effect>;
+
+ aml-audio-card,dai-link@0 {
+ format = "dsp_a";
+ mclk-fs = <512>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ //bitclock-master = <&tdmacodec>;
+ //frame-master = <&tdmacodec>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-pcm";
+ tdmacpu: cpu {
+ sound-dai = <&aml_tdma>;
+ dai-tdm-slot-tx-mask =
+ <1 1 1 1 1 1 1 1>;
+ dai-tdm-slot-rx-mask =
+ <1 1 1 1 1 1 1 1>;
+ dai-tdm-slot-num = <8>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <24576000>;
+ };
+ tdmacodec: codec {
+ sound-dai = <&dummy_codec &dummy_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@1 {
+ format = "i2s";
+ mclk-fs = <256>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ bitclock-master = <&aml_tdmb>;
+ frame-master = <&aml_tdmb>;
+ //bitclock-master = <&tdmbcodec>;
+ //frame-master = <&tdmbcodec>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-i2s";
+ cpu {
+ sound-dai = <&aml_tdmb>;
+ dai-tdm-slot-tx-mask = <1 1>;
+ dai-tdm-slot-rx-mask = <1 1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <12288000>;
+ };
+ tdmbcodec: codec {
+ sound-dai = <&dummy_codec &dummy_codec
+ &amlogic_codec &ad82584f_62>;
+ };
+ };
+
+ aml-audio-card,dai-link@2 {
+ format = "i2s";
+ mclk-fs = <256>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ bitclock-master = <&aml_tdmc>;
+ frame-master = <&aml_tdmc>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ //suffix-name = "alsaPORT-tdm";
+ cpu {
+ sound-dai = <&aml_tdmc>;
+ dai-tdm-slot-tx-mask = <1 1>;
+ dai-tdm-slot-rx-mask = <1 1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <12288000>;
+ };
+ codec {
+ sound-dai = <&dummy_codec &dummy_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@3 {
+ mclk-fs = <64>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-pdm";
+ cpu {
+ sound-dai = <&aml_pdm>;
+ };
+ codec {
+ sound-dai = <&pdm_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@4 {
+ mclk-fs = <128>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-spdif";
+ cpu {
+ sound-dai = <&aml_spdif>;
+ system-clock-frequency = <6144000>;
+ };
+ codec {
+ sound-dai = <&dummy_codec>;
+ };
+ };
+ };
+ audiolocker: locker {
+ compatible = "amlogic, audiolocker";
+ clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT
+ &clkaudio CLKID_AUDIO_LOCKER_IN
+ &clkaudio CLKID_AUDIO_MCLK_D
+ &clkaudio CLKID_AUDIO_MCLK_E
+ &clkc CLKID_MPLL1
+ &clkc CLKID_MPLL2>;
+ clock-names = "lock_out", "lock_in", "out_src",
+ "in_src", "out_calc", "in_ref";
+ interrupts = <GIC_SPI 1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "irq";
+ frequency = <49000000>; /* pll */
+ dividor = <49>; /* locker's parent */
+ status = "okay";
+ };
+ /* Audio Related end */
+
+ cpu_opp_table0: cpu_opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <731000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <731000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <731000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <731000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <731000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <731000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <761000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <791000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <831000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <861000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <981000>;
+ };
+ };
+
+ cpu_opp_table1: cpu_opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <751000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <751000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <751000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <751000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <771000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <771000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <791000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <821000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <861000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <891000>;
+ };
+ };
+
+ cpufreq-meson {
+ compatible = "amlogic, cpufreq-meson";
+ status = "okay";
+ };
+
+ sensor: sensor {
+ compatible = "soc, sensor";
+ status = "okay";
+ sensor-name = "imx290"; /*imx290;os08a10;imx227*/
+ pinctrl-names="default";
+ pinctrl-0=<&clk12_24_z_pins>;
+ clocks = <&clkc CLKID_24M>;
+ clock-names = "g12a_24m";
+ reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>;
+ ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH
+ &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>;
+ };
+
+ iq: iq {
+ compatible = "soc, iq";
+ status = "okay";
+ sensor-name = "imx290"; /*imx290;os08a10;imx227*/
+ };
+}; /* end of / */
+
+&i2c2 {
+ status = "okay";
+ pinctrl-names="default";
+ pinctrl-0=<&i2c2_master_pins2>;
+ clock-frequency = <100000>; /* default 100k */
+ sensor-i2c@6c {
+ compatible = "arm, i2c-sensor";
+ reg = <0x6c>;
+ reg-names = "i2c-sensor";
+ slave-addr = <0x6c>;
+ reg-type = <2>;
+ reg-data-type = <1>;
+ link-device = <&phycsi>;
+ };
+};
+
+&isp {
+ status = "okay";
+ memory-region = <&isp_cma_reserved>;
+};
+
+&adapter {
+ status = "okay";
+ memory-region = <&adapt_cma_reserved>;
+};
+
+&gdc {
+ status = "okay";
+ memory-region = <&gdc_cma_reserved>;
+};
+
+&meson_fb {
+ status = "disable";
+ display_size_default = <1920 1080 1920 2160 32>;
+ mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>;
+ logo_addr = "0x7f800000";
+ mem_alloc = <1>;
+ pxp_mode = <0>; /** 0:normal mode 1:pxp mode */
+};
+
+&drm_vpu {
+ status = "okay";
+ compatible = "amlogic,meson-g12b-vpu";
+ logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V3>;
+};
+
+&drm_amhdmitx {
+ status = "okay";
+ hdcp = "disabled";
+};
+
+&drm_lcd {
+ status = "disable";
+};
+
+&pwm_ab {
+ status = "okay";
+ };
+
+&pwm_ef {
+ status = "okay";
+ };
+
+&pwm_AO_cd {
+ status = "okay";
+ };
+
+&i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_master_pins2>;
+ clock-frequency = <400000>;
+
+ touchscreen@38 {
+ compatible = "focaltech,fts";
+ status = "disabled";
+ reg = <0x38>;
+ reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>;
+ irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>;
+ x_max = <720>;
+ y_max = <1280>;
+ max-touch-number = <10>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+ pinctrl-names="default";
+ pinctrl-0=<&i2c3_master_pins2>;
+ clock-frequency = <100000>; /* default 100k */
+
+ /* for ref board */
+ ad82584f_62: ad82584f_62@62 {
+ compatible = "ESMT, ad82584f";
+ #sound-dai-cells = <0>;
+ reg = <0x31>;
+ status = "okay";
+ reset_pin = <&gpio GPIOA_5 0>;
+ };
+
+ tlv320adc3101_32: tlv320adc3101_32@32 {
+ compatible = "ti,tlv320adc3101";
+ #sound-dai-cells = <0>;
+ reg = <0x19>;
+ differential_pair = <1>;
+ status = "disabled";
+ };
+
+ bl_extern_i2c {
+ compatible = "bl_extern, i2c";
+ dev_name = "lp8556";
+ reg = <0x2c>;
+ status = "disabled";
+ };
+};
+
+&audiobus {
+ aml_tdma: tdma {
+ compatible = "amlogic, g12a-snd-tdma";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <0 1>;
+ dai-tdm-oe-lane-slot-mask-out = <1 0>;
+ dai-tdm-clk-sel = <0>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_A
+ &clkc CLKID_MPLL0>;
+ clock-names = "mclk", "clk_srcpll";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmout_a &tdmin_a>;
+ };
+
+ aml_tdmb: tdmb {
+ compatible = "amlogic, g12a-snd-tdmb";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <0 1 0 0>;
+ dai-tdm-lane-slot-mask-out = <1 0 0 0>;
+ dai-tdm-clk-sel = <1>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_B
+ &clkc CLKID_MPLL1
+ &clkc CLKID_MPLL0
+ &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>;
+ clock-names = "mclk", "clk_srcpll",
+ "samesource_srcpll", "samesource_clk";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>;
+ /*
+ * 0: tdmout_a;
+ * 1: tdmout_b;
+ * 2: tdmout_c;
+ * 3: spdifout;
+ * 4: spdifout_b;
+ */
+ samesource_sel = <3>;
+ };
+
+ aml_tdmc: tdmc {
+ compatible = "amlogic, g12a-snd-tdmc";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <1 0 0 0>;
+ #dai-tdm-lane-slot-mask-out = <1 0 1 1>;
+ #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>;
+ #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>;
+ dai-tdm-clk-sel = <2>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_C
+ &clkc CLKID_MPLL2>;
+ clock-names = "mclk", "clk_srcpll";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>;
+ };
+
+ /* copy a useless tdm to output for hdmi, no pinmux */
+ aml_i2s2hdmi: i2s2hdmi {
+ compatible = "amlogic, g12a-snd-tdmc";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-out = <1 1 1 1>;
+ dai-tdm-clk-sel = <2>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_C
+ &clkc CLKID_MPLL2>;
+ clock-names = "mclk", "clk_srcpll";
+
+ i2s2hdmi = <1>;
+
+ status = "okay";
+ };
+
+ aml_spdif: spdif {
+ compatible = "amlogic, g12a-snd-spdif-a";
+ #sound-dai-cells = <0>;
+ clocks = <&clkc CLKID_MPLL0
+ &clkc CLKID_FCLK_DIV4
+ &clkaudio CLKID_AUDIO_SPDIFIN
+ &clkaudio CLKID_AUDIO_SPDIFOUT
+ &clkaudio CLKID_AUDIO_SPDIFIN_CTRL
+ &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>;
+ clock-names = "sysclk", "fixed_clk", "gate_spdifin",
+ "gate_spdifout", "clk_spdifin", "clk_spdifout";
+ interrupts =
+ <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-names = "irq_spdifin";
+ pinctrl-names = "spdif_pins",
+ "spdif_pins_mute";
+ pinctrl-0 = <&spdifout &spdifin>;
+ pinctrl-1 = <&spdifout_a_mute>;
+ status = "okay";
+ };
+ aml_spdif_b: spdif_b {
+ compatible = "amlogic, g12a-snd-spdif-b";
+ #sound-dai-cells = <0>;
+ clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/
+ &clkaudio CLKID_AUDIO_SPDIFOUTB
+ &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>;
+ clock-names = "sysclk",
+ "gate_spdifout", "clk_spdifout";
+ status = "disabled";
+ };
+ aml_pdm: pdm {
+ compatible = "amlogic, g12a-snd-pdm";
+ #sound-dai-cells = <0>;
+ clocks = <&clkaudio CLKID_AUDIO_PDM
+ &clkc CLKID_FCLK_DIV3
+ &clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_PDMIN0
+ &clkaudio CLKID_AUDIO_PDMIN1>;
+ clock-names = "gate",
+ "sysclk_srcpll",
+ "dclk_srcpll",
+ "pdm_dclk",
+ "pdm_sysclk";
+ pinctrl-names = "pdm_pins";
+ pinctrl-0 = <&pdmin>;
+ filter_mode = <1>; /* mode 0~4, defalut:1 */
+ status = "okay";
+ };
+ aml_loopback: loopback {
+ compatible = "amlogic, snd-loopback";
+ /*
+ * 0: out rate = in data rate;
+ * 1: out rate = loopback data rate;
+ */
+ lb_mode = <0>;
+
+ /* datain src
+ * 0: tdmin_a;
+ * 1: tdmin_b;
+ * 2: tdmin_c;
+ * 3: spdifin;
+ * 4: pdmin;
+ */
+ datain_src = <4>;
+ datain_chnum = <8>;
+ datain_chmask = <0x3f>;
+
+ /* tdmin_lb src
+ * 0: tdmoutA
+ * 1: tdmoutB
+ * 2: tdmoutC
+ * 3: PAD_tdminA
+ * 4: PAD_tdminB
+ * 5: PAD_tdminC
+ */
+ datalb_src = <2>;
+ datalb_chnum = <8>;
+ datalb_chmask = <0x3>;
+
+ status = "disabled";
+ };
+
+ audioresample: resample {
+ compatible = "amlogic, g12a-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A, 0
+ * TDMIN_B, 1
+ * TDMIN_C, 2
+ * SPDIFIN, 3
+ * PDMIN, 4
+ * NONE,
+ * TDMIN_LB, 6
+ * LOOPBACK, 7
+ */
+ resample_module = <4>;
+ status = "disabled";
+ };
+ aml_pwrdet: pwrdet {
+ compatible = "amlogic, g12a-power-detect";
+
+ interrupts = <GIC_SPI 155 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "pwrdet_irq";
+
+ /* pwrdet source sel
+ * 7: loopback;
+ * 6: tdmin_lb;
+ * 5: reserved;
+ * 4: pdmin;
+ * 3: spdifin;
+ * 2: tdmin_c;
+ * 1: tdmin_b;
+ * 0: tdmin_a;
+ */
+ pwrdet_src = <4>;
+
+ hi_th = <0x70000>;
+ lo_th = <0x16000>;
+
+ status = "disabled";
+ };
+}; /* end of audiobus */
+
+&pinctrl_periphs {
+ tdmout_a: tdmout_a {
+ mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */
+ groups = "tdma_sclk",
+ "tdma_fs",
+ "tdma_dout0";
+ function = "tdma_out";
+ };
+ };
+
+ tdmin_a: tdmin_a {
+ mux { /* GPIOX_8 */
+ groups = "tdma_din1";
+ function = "tdma_in";
+ };
+ };
+
+ tdmb_mclk: tdmb_mclk {
+ mux {
+ groups = "mclk0_a";
+ function = "mclk0";
+ drive-strength = <2>;
+ };
+ };
+ tdmout_b: tdmout_b {
+ mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */
+ groups = "tdmb_sclk",
+ "tdmb_fs",
+ "tdmb_dout0";
+ function = "tdmb_out";
+ drive-strength = <2>;
+ };
+ };
+
+ tdmin_b:tdmin_b {
+ mux { /* GPIOA_4 */
+ groups = "tdmb_din1"
+ /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/;
+ function = "tdmb_in";
+ drive-strength = <2>;
+ };
+ };
+
+ tdmc_mclk: tdmc_mclk {
+ mux { /* GPIOA_11 */
+ groups = "mclk1_a";
+ function = "mclk1";
+ };
+ };
+
+ clk12_24_z_pins:clk12_24_z_pins {
+ mux {
+ groups = "clk12_24_z";
+ function = "clk12_24_ee";
+ drive-strength = <3>;
+ };
+ };
+
+ tdmout_c:tdmout_c {
+ mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/
+ groups = "tdmc_sclk_a",
+ "tdmc_fs_a",
+ "tdmc_dout0_a"
+ /*, "tdmc_dout2",
+ * "tdmc_dout3"
+ */;
+ function = "tdmc_out";
+ };
+ };
+
+ tdmin_c:tdmin_c {
+ mux { /* GPIOA_10 */
+ groups = "tdmc_din0_a";
+ function = "tdmc_in";
+ };
+ };
+
+ spdifin: spdifin {
+ mux {/* GPIOH_5 */
+ groups = "spdif_in_h";
+ function = "spdif_in";
+ };
+ };
+
+ /* GPIOH_4 */
+ /*
+ * spdifout: spdifout {
+ * mux {
+ * groups = "spdif_out_h";
+ * function = "spdif_out";
+ * };
+ *};
+ */
+
+ pdmin: pdmin {
+ mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/
+ groups = "pdm_din0_a",
+ /*"pdm_din1_a",*/
+ "pdm_din2_a",
+ /*"pdm_din3_a",*/
+ "pdm_dclk_a";
+ function = "pdm";
+ };
+ };
+
+ bl_pwm_off_pins:bl_pwm_off_pin {
+ mux {
+ pins = "GPIOH_5";
+ function = "gpio_periphs";
+ output-high;
+ };
+ };
+
+}; /* end of pinctrl_periphs */
+
+&pinctrl_aobus {
+ spdifout: spdifout {
+ mux { /* gpiao_10 */
+ groups = "spdif_out_ao";
+ function = "spdif_out_ao";
+ };
+ };
+
+ spdifout_a_mute: spdifout_a_mute {
+ mux { /* gpiao_10 */
+ groups = "GPIOAO_10";
+ function = "gpio_periphs";
+ };
+ };
+}; /* end of pinctrl_aobus */
+
+&irblaster {
+ status = "disabled";
+};
+
+&audio_data {
+ status = "okay";
+};
+
+/*if you want to use vdin just modify status to "ok"*/
+&vdin0 {
+ memory-region = <&vdin0_cma_reserved>;
+ status = "okay";
+ /*vdin write mem color depth support:
+ *bit0:support 8bit
+ *bit1:support 9bit
+ *bit2:support 10bit
+ *bit3:support 12bit
+ *bit4:support yuv422 10bit full pack mode (from txl new add)
+ */
+ tv_bit_mode = <0x15>;
+};
+&vdin1 {
+ memory-region = <&vdin1_cma_reserved>;
+ status = "okay";
+ /*vdin write mem color depth support:
+ *bit0:support 8bit
+ *bit1:support 9bit
+ *bit2:support 10bit
+ *bit3:support 12bit
+ */
+ tv_bit_mode = <1>;
+};
+
+&sd_emmc_c {
+ status = "okay";
+ emmc {
+ caps = "MMC_CAP_8_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED",
+ "MMC_CAP_NONREMOVABLE",
+ /* "MMC_CAP_1_8V_DDR", */
+ "MMC_CAP_HW_RESET",
+ "MMC_CAP_ERASE",
+ "MMC_CAP_CMD23";
+ caps2 = "MMC_CAP2_HS200";
+ /* "MMC_CAP2_HS400";*/
+ f_min = <400000>;
+ f_max = <200000000>;
+ };
+};
+
+&sd_emmc_b {
+ status = "okay";
+ sd {
+ caps = "MMC_CAP_4_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED";
+ f_min = <400000>;
+ f_max = <50000000>;
+ };
+};
+
+&sd_emmc_a {
+ status = "okay";
+ sdio {
+ caps = "MMC_CAP_4_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED",
+ "MMC_CAP_NONREMOVABLE",
+ "MMC_CAP_UHS_SDR12",
+ "MMC_CAP_UHS_SDR25",
+ "MMC_CAP_UHS_SDR50",
+ "MMC_CAP_UHS_SDR104",
+ "MMC_PM_KEEP_POWER",
+ "MMC_CAP_SDIO_IRQ";
+ f_min = <400000>;
+ f_max = <200000000>;
+ };
+};
+
+&nand {
+ status = "disabled";
+ plat-names = "bootloader","nandnormal";
+ plat-num = <2>;
+ plat-part-0 = <&bootloader>;
+ plat-part-1 = <&nandnormal>;
+ bootloader: bootloader{
+ enable_pad ="ce0";
+ busy_pad = "rb0";
+ timming_mode = "mode5";
+ bch_mode = "bch8_1k";
+ t_rea = <20>;
+ t_rhoh = <15>;
+ chip_num = <1>;
+ part_num = <0>;
+ rb_detect = <1>;
+ };
+ nandnormal: nandnormal{
+ enable_pad ="ce0";
+ busy_pad = "rb0";
+ timming_mode = "mode5";
+ bch_mode = "bch8_1k";
+ plane_mode = "twoplane";
+ t_rea = <20>;
+ t_rhoh = <15>;
+ chip_num = <2>;
+ part_num = <3>;
+ partition = <&nand_partitions>;
+ rb_detect = <1>;
+ };
+ nand_partitions:nand_partition{
+ /*
+ * if bl_mode is 1, tpl size was generate by
+ * fip_copies * fip_size which
+ * will not skip bad when calculating
+ * the partition size;
+ *
+ * if bl_mode is 0,
+ * tpl partition must be comment out.
+ */
+ tpl{
+ offset=<0x0 0x0>;
+ size=<0x0 0x0>;
+ };
+ logo{
+ offset=<0x0 0x0>;
+ size=<0x0 0x200000>;
+ };
+ recovery{
+ offset=<0x0 0x0>;
+ size=<0x0 0x1000000>;
+ };
+ boot{
+ offset=<0x0 0x0>;
+ size=<0x0 0x1000000>;
+ };
+ system{
+ offset=<0x0 0x0>;
+ size=<0x0 0x4000000>;
+ };
+ data{
+ offset=<0xffffffff 0xffffffff>;
+ size=<0x0 0x0>;
+ };
+ };
+};
+&dwc3 {
+ status = "okay";
+};
+
+&usb2_phy_v2 {
+ status = "okay";
+ portnum = <2>;
+};
+
+&usb3_phy_v2 {
+ status = "okay";
+ portnum = <0>;
+ otg = <1>;
+ gpio-vbus-power = "GPIOH_6";
+ gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>;
+};
+
+&dwc2_a {
+ status = "okay";
+ /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/
+ controller-type = <3>;
+};
+ð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>;
+};
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
-*/
+ */
+#include <dt-bindings/display/meson-drm-ids.h>
/ {
venc-cvbs {
status = "okay";
- compatible = "amlogic,meson-gxbb-cvbs";
+ compatible = "amlogic, meson-g12a-cvbs";
ports {
#address-cells = <1>;
status = "okay";
compatible = "amlogic,drm-subsystem";
ports = <&vpu_out>;
+
+ vpu_topology: vpu_topology {
+ vpu_blocks {
+ osd1_block: block@0 {
+ id = /bits/ 8 <OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <0>;
+ block_name = "osd1_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd1_block>;
+ };
+ osd2_block: block@1 {
+ id = /bits/ 8 <OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <0>;
+ block_name = "osd2_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd2_block>;
+ };
+ osd3_block: block@2 {
+ id = /bits/ 8 <OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <0>;
+ block_name = "osd3_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd3_block>;
+ };
+ afbc_osd1_block: block@3 {
+ id = /bits/ 8 <AFBC_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &osd_blend_block>;
+ };
+ afbc_osd2_block: block@4 {
+ id = /bits/ 8 <AFBC_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd2_block>;
+ };
+ afbc_osd3_block: block@5 {
+ id = /bits/ 8 <AFBC_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd3_block>;
+ };
+ scaler_osd1_block: block@6 {
+ id = /bits/ 8 <SCALER_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_hdr_dolby_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &vpp_postblend_block>;
+ };
+ scaler_osd2_block: block@7 {
+ id = /bits/ 8 <SCALER_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <2 &osd_blend_block>;
+ };
+ scaler_osd3_block: block@8 {
+ id = /bits/ 8 <SCALER_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <3 &osd_blend_block>;
+ };
+ osd_blend_block: block@9 {
+ id = /bits/ 8 <OSD_BLEND_BLOCK>;
+ block_name = "osd_blend_block";
+ type = /bits/ 8 <3>;
+ num_in_links = /bits/ 8 <0x3>;
+ in_links = <0 &afbc_osd1_block>,
+ <0 &scaler_osd2_block>,
+ <0 &scaler_osd3_block>;
+ num_out_links = /bits/ 8 <0x2>;
+ out_links = <0 &osd1_hdr_dolby_block>,
+ <1 &vpp_postblend_block>;
+ };
+ osd1_hdr_dolby_block: block@10 {
+ id = /bits/ 8 <OSD1_HDR_BLOCK>;
+ block_name = "osd1_hdr_dolby_block";
+ type = /bits/ 8 <4>;
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd_blend_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd1_block>;
+ };
+ vpp_postblend_block: block@12 {
+ id = /bits/ 8 <VPP_POSTBLEND_BLOCK>;
+ block_name = "vpp_postblend_block";
+ type = /bits/ 8 <6>;
+ num_in_links = /bits/ 8 <0x2>;
+ in_links = <0 &scaler_osd1_block>,
+ <1 &osd_blend_block>;
+ num_out_links = <0x0>;
+ };
+ };
+ };
+
+ vpu_hw_para: vpu_hw_para@0 {
+ osd_ver = /bits/ 8 <0x2>;
+ afbc_type = /bits/ 8 <0x2>;
+ has_deband = /bits/ 8 <0x1>;
+ has_lut = /bits/ 8 <0x1>;
+ has_rdma = /bits/ 8 <0x1>;
+ osd_fifo_len = /bits/ 8 <64>;
+ vpp_fifo_len = /bits/ 32 <0xfff>;
+ };
};
};
--- /dev/null
+/*
+ * arch/arm64/boot/dts/amlogic/meson_drm.dtsi
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <dt-bindings/display/meson-drm-ids.h>
+
+/ {
+ venc-cvbs {
+ status = "okay";
+ compatible = "amlogic, meson-g12b-cvbs";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ enc_cvbs_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ //venc_cvbs_in_vpu: endpoint@0 {
+ // reg = <0>;
+ // remote-endpoint = <&vpu_out_venc_cvbs>;
+ //};
+ };
+ };
+ };
+
+ drm_amhdmitx: drm-amhdmitx {
+ status = "disabled";
+ hdcp = "disabled";
+ compatible = "amlogic,drm-amhdmitx";
+ dev_name = "meson-amhdmitx";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+ ports {
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ hdmi_in_vpu: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_hdmi>;
+ };
+ };
+ };
+ };
+
+ drm_lcd: drm-lcd {
+ status = "disabled";
+ compatible = "amlogic,drm-lcd";
+ dev_name = "meson-lcd";
+ ports {
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ lcd_in_vpu: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_lcd>;
+ };
+ };
+ };
+ };
+
+ drm_vpu: drm-vpu@0xff900000 {
+ status = "disabled";
+ compatible = "amlogic,meson-g12b-vpu";
+ memory-region = <&logo_reserved>;
+ reg = <0x0 0xff900000 0x0 0x40000>,
+ <0x0 0xff63c000 0x0 0x2000>,
+ <0x0 0xff638000 0x0 0x2000>;
+ reg-names = "base", "hhi", "dmc";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 56 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "viu-vsync", "viu2-vsync";
+ clocks = <&clkc CLKID_VPU_CLKC_MUX>;
+ clock-names = "vpu_clkc";
+ dma-coherent;
+ vpu_out: port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vpu_out_hdmi: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hdmi_in_vpu>;
+ };
+ vpu_out_lcd: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&lcd_in_vpu>;
+ };
+ };
+ };
+
+ drm_subsystem: drm-subsystem {
+ status = "okay";
+ compatible = "amlogic,drm-subsystem";
+ ports = <&vpu_out>;
+
+ vpu_topology: vpu_topology {
+ vpu_blocks {
+ osd1_block: block@0 {
+ id = /bits/ 8 <OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <0>;
+ block_name = "osd1_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd1_block>;
+ };
+ osd2_block: block@1 {
+ id = /bits/ 8 <OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <0>;
+ block_name = "osd2_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd2_block>;
+ };
+ osd3_block: block@2 {
+ id = /bits/ 8 <OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <0>;
+ block_name = "osd3_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd3_block>;
+ };
+ afbc_osd1_block: block@3 {
+ id = /bits/ 8 <AFBC_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &osd_blend_block>;
+ };
+ afbc_osd2_block: block@4 {
+ id = /bits/ 8 <AFBC_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd2_block>;
+ };
+ afbc_osd3_block: block@5 {
+ id = /bits/ 8 <AFBC_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd3_block>;
+ };
+ scaler_osd1_block: block@6 {
+ id = /bits/ 8 <SCALER_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_hdr_dolby_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &vpp_postblend_block>;
+ };
+ scaler_osd2_block: block@7 {
+ id = /bits/ 8 <SCALER_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <2 &osd_blend_block>;
+ };
+ scaler_osd3_block: block@8 {
+ id = /bits/ 8 <SCALER_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <3 &osd_blend_block>;
+ };
+ osd_blend_block: block@9 {
+ id = /bits/ 8 <OSD_BLEND_BLOCK>;
+ block_name = "osd_blend_block";
+ type = /bits/ 8 <3>;
+ num_in_links = /bits/ 8 <0x3>;
+ in_links = <0 &afbc_osd1_block>,
+ <0 &scaler_osd2_block>,
+ <0 &scaler_osd3_block>;
+ num_out_links = /bits/ 8 <0x2>;
+ out_links = <0 &osd1_hdr_dolby_block>,
+ <1 &vpp_postblend_block>;
+ };
+ osd1_hdr_dolby_block: block@10 {
+ id = /bits/ 8 <OSD1_HDR_BLOCK>;
+ block_name = "osd1_hdr_dolby_block";
+ type = /bits/ 8 <4>;
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd_blend_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd1_block>;
+ };
+ vpp_postblend_block: block@12 {
+ id = /bits/ 8 <VPP_POSTBLEND_BLOCK>;
+ block_name = "vpp_postblend_block";
+ type = /bits/ 8 <6>;
+ num_in_links = /bits/ 8 <0x2>;
+ in_links = <0 &scaler_osd1_block>,
+ <1 &osd_blend_block>;
+ num_out_links = <0x0>;
+ };
+ };
+ };
+
+ vpu_hw_para: vpu_hw_para@0 {
+ osd_ver = /bits/ 8 <0x2>;
+ afbc_type = /bits/ 8 <0x2>;
+ has_deband = /bits/ 8 <0x1>;
+ has_lut = /bits/ 8 <0x1>;
+ has_rdma = /bits/ 8 <0x1>;
+ osd_fifo_len = /bits/ 8 <64>;
+ vpp_fifo_len = /bits/ 32 <0xfff>;
+ };
+ };
+};
obj-$(CONFIG_AMLOGIC_DDR_TOOL) += ddr_tool/
-obj-$(CONFIG_DRM_MESON) += drm/
+obj-$(CONFIG_AMLOGIC_DRM) += drm/
obj-$(CONFIG_AMLOGIC_M8B_SM) += secure_monitor/
+menuconfig AMLOGIC_DRM
+ bool "Amlogic drm support"
+ depends on AMLOGIC_DRIVER && DRM
+ default n
+ help
+ amlogic drm driver provide drm support on Amlogic
+ SOC chips.
+choice
+ prompt "meson drm driver type"
+ depends on AMLOGIC_DRM
+ default DRM_MESON
+
config DRM_MESON
- tristate "DRM Support for Amlogic Meson Display Controller"
+ tristate "DRM Support for Amlogic new Display Controller"
+ depends on DRM && OF && (ARM || ARM64)
+ select DRM_KMS_HELPER
+ select DRM_KMS_CMA_HELPER
+ select DRM_GEM_CMA_HELPER
+ select VIDEOMODE_HELPERS
+ select REGMAP_MMIO
+ help
+ amlogic new soc display controller
+ use the pipeline and modularized
+
+config DRM_MESON_V0
+ tristate "DRM Support for Amlogic old Display Controller"
depends on DRM && OF && (ARM || ARM64)
select DRM_KMS_HELPER
select DRM_KMS_CMA_HELPER
select DRM_GEM_CMA_HELPER
select VIDEOMODE_HELPERS
select REGMAP_MMIO
+ help
+ amlogic old soc display controller
+ use the osd driver
+endchoice
+
+if DRM_MESON
config DRM_MESON_VPU
tristate "support drm vpu function for meson drm display."
depends on DRM_MESON && DRM_MESON_USE_ION
help
Emulate framebuffer device for device which need use fbdev api.
+endif
+
+if DRM_MESON_V0
+
+source "drivers/amlogic/drm/drm-v0/Kconfig"
+
+endif
-meson_drv-y += am_meson_drv.o
-ccflags-y += -Idrivers/amlogic/media/osd/
-
ifeq ($(CONFIG_DRM_MESON_USE_ION),y)
- meson_drv-y += am_meson_gem.o am_meson_fb.o
- ccflags-y += -Idrivers/staging/android/
+ meson-drm-y += meson_gem.o meson_fb.o
+ ccflags-y += -Idrivers/staging/android/
endif
ifeq ($(CONFIG_DRM_MESON_EMULATE_FBDEV),y)
- meson_drv-y += am_meson_fbdev.o
+ meson-drm-y += meson_fbdev.o
endif
ifneq ($(CONFIG_DRM_MESON_VPU),)
- meson_vpu-y += am_meson_vpu.o
+ meson-drm-y += meson_vpu.o
endif
ifneq ($(CONFIG_DRM_MESON_HDMI),)
- meson_hdmi-y += am_meson_hdmi.o am_meson_hdcp.o
+ meson-drm-y += meson_hdmi.o meson_hdcp.o
endif
ifneq ($(CONFIG_DRM_MESON_PANEL),)
- meson_lcd-y += am_meson_lcd.o
+ meson-drm-y += meson_lcd.o
endif
-obj-$(CONFIG_DRM_MESON) += meson_drv.o
-obj-$(CONFIG_DRM_MESON_VPU) += meson_vpu.o
-obj-$(CONFIG_DRM_MESON_HDMI) += meson_hdmi.o
-obj-$(CONFIG_DRM_MESON_PANEL) += meson_lcd.o
+meson-drm-y += meson_drv.o meson_plane.o meson_vpu_pipeline_traverse.o \
+ meson_crtc.o meson_vpu_pipeline.o meson_vpu_pipeline_private.o \
+
+meson-drm-y += \
+ vpu-hw/meson_vpu_osd_mif.o \
+ vpu-hw/meson_osd_afbc.o \
+ vpu-hw/meson_osd_scaler.o \
+ vpu-hw/meson_vpu_osdblend.o \
+ vpu-hw/meson_vpu_hdr_dv.o \
+ vpu-hw/meson_vpu_postblend.o
+
+ifneq ($(CONFIG_DRM_MESON_V0), y)
+ ccflags-y += -Idrivers/amlogic/media/osd/ -I$(src)/vpu-hw -I$(src)
+ obj-y += meson-drm.o
+else
+ obj-y += drm-v0/
+endif
+++ /dev/null
-/*
- * drivers/amlogic/drm/am_meson_fbdev.h
- *
- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __AM_MESON_FBDEV_H
-#define __AM_MESON_FBDEV_H
-
-#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
-int am_meson_drm_fbdev_init(struct drm_device *dev);
-void am_meson_drm_fbdev_fini(struct drm_device *dev);
-#endif
-
-#endif /* __AM_MESON_FBDEV_H */
--- /dev/null
+config DRM_MESON_VPU
+ tristate "support drm vpu function for meson drm display."
+ default y
+ depends on DRM_MESON_V0
+ help
+ add drm vpu support.
+ Choose this option if you have a aMLOGIC soc chipset.
+ This driver provides KMS.
+ This driver also provides crtcs and planes management.
+
+config DRM_MESON_HDMI
+ tristate "support drm hdmi function for meson drm display."
+ default y
+ depends on DRM_MESON_V0
+ depends on AMLOGIC_HDMITX
+ help
+ add drm hdmi support.
+ use internal amlogic media vout hdmi driver.
+ We should confirm AMLOGIC_HDMITX is configured if
+ DRM_MESON_HDMI is selected.
+
+config DRM_MESON_PANEL
+ tristate "support drm panel function for meson drm display."
+ default y
+ depends on DRM_MESON_V0
+ depends on AMLOGIC_LCD
+ select DRM_PANEL
+ select DRM_MIPI_DSI
+ help
+ add drm panel support.
+ use internal amlogic media vout lcd driver.
+ We should confirm AMLOGIC_LCD is configured if
+ DRM_MESON_PANEL is selected.
+
+config DRM_MESON_USE_ION
+ bool "gem use ion to alloc/free graphic buffer."
+ default y
+ depends on DRM_MESON_V0
+ help
+ MESON DRM use CMA HELPER to manage framebuffer.
+ It need reserve memory in CMA pool.
+ We implement GEM to allocate/free framebuffer from ion.
+ For dumb used by displaycontrol we alloc from the ION CMA HEAP.
+ For dumb used by app, we can alloc from the ION.
+ SYSTEM HEAP which dont need reserve memory.
+
+config DRM_MESON_EMULATE_FBDEV
+ bool "emulate framebuffer dev by drm."
+ default n
+ depends on DRM_MESON_V0 && DRM_MESON_USE_ION
+ help
+ Emulate framebuffer device for device which need use fbdev api.
--- /dev/null
+meson_drv-y += am_meson_drv.o
+ccflags-y += -Idrivers/amlogic/media/osd/
+
+ifeq ($(CONFIG_DRM_MESON_USE_ION),y)
+ meson_drv-y += am_meson_gem.o am_meson_fb.o
+ ccflags-y += -Idrivers/staging/android/
+endif
+
+ifeq ($(CONFIG_DRM_MESON_EMULATE_FBDEV),y)
+ meson_drv-y += am_meson_fbdev.o
+endif
+
+ifneq ($(CONFIG_DRM_MESON_VPU),)
+ meson_vpu-y += am_meson_vpu.o
+endif
+
+ifneq ($(CONFIG_DRM_MESON_HDMI),)
+ meson_hdmi-y += am_meson_hdmi.o am_meson_hdcp.o
+endif
+
+ifneq ($(CONFIG_DRM_MESON_PANEL),)
+ meson_lcd-y += am_meson_lcd.o
+endif
+
+obj-y += meson_drv.o
+obj-$(CONFIG_DRM_MESON_VPU) += meson_vpu.o
+obj-$(CONFIG_DRM_MESON_HDMI) += meson_hdmi.o
+obj-$(CONFIG_DRM_MESON_PANEL) += meson_lcd.o
/*
- * Copyright (C) 2016 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- * Copyright (C) 2014 Endless Mobile
+ * drivers/amlogic/drm/drm-v0/am_meson_drv.c
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * Written by:
- * Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include <linux/kernel.h>
/*
- * Copyright (C) 2016 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * drivers/amlogic/drm/drm-v0/am_meson_drv.h
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __AM_MESON_DRV_H
/*
- * drivers/amlogic/drm/am_meson_fb.c
+ * drivers/amlogic/drm/drm-v0/am_meson_fb.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* more details.
*
*/
+
#include <drm/drm_atomic_helper.h>
#include "am_meson_fb.h"
/*
- * drivers/amlogic/drm/am_meson_fb.h
+ * drivers/amlogic/drm/drm-v0/am_meson_fb.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
/*
- * drivers/amlogic/drm/am_meson_fbdev.c
+ * drivers/amlogic/drm/drm-v0/am_meson_fbdev.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <drm/drm.h>
--- /dev/null
+/*
+ * drivers/amlogic/drm/drm-v0/am_meson_fbdev.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AM_MESON_FBDEV_H
+#define __AM_MESON_FBDEV_H
+
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+int am_meson_drm_fbdev_init(struct drm_device *dev);
+void am_meson_drm_fbdev_fini(struct drm_device *dev);
+#endif
+
+#endif /* __AM_MESON_FBDEV_H */
/*
- * drivers/amlogic/drm/am_meson_gem.c
+ * drivers/amlogic/drm/drm-v0/am_meson_gem.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* more details.
*
*/
+
#include <drm/drmP.h>
#include <drm/drm_gem.h>
#include <drm/drm_vma_manager.h>
//check flags to set different ion heap type.
//if flags is set to 0, need to use ion dma buffer.
- if (((flags & (BO_USE_SCANOUT | BO_USE_CURSOR)) != 0)
+ if (((flags & (MESON_USE_SCANOUT | MESON_USE_CURSOR)) != 0)
|| (flags == 0)) {
handle = ion_alloc(client, meson_gem_obj->base.size,
0, (1 << ION_HEAP_TYPE_DMA), 0);
- }
- else {
+ } else {
handle = ion_alloc(client, meson_gem_obj->base.size,
0, (1 << ION_HEAP_TYPE_SYSTEM), 0);
bscatter = true;
}
return dst_table;
}
- else {
- DRM_ERROR("Not support import buffer from other driver.\n");
- return NULL;
- }
+
+ DRM_ERROR("Not support import buffer from other driver.\n");
+ return NULL;
}
struct drm_gem_object *am_meson_gem_prime_import_sg_table(
/*
- * drivers/amlogic/drm/am_meson_gem.h
+ * drivers/amlogic/drm/drm-v0/am_meson_gem.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
#ifndef __AM_MESON_GEM_H
#define __AM_MESON_GEM_H
#include <drm/drm_gem.h>
-#include <linux/amlogic/meson_drm.h>
+#include <uapi/drm/meson_drm.h>
#include <ion/ion_priv.h>
#include "am_meson_drv.h"
/*
- * drivers/amlogic/drm/am_meson_hdcp.c
+ * drivers/amlogic/drm/drm-v0/am_meson_hdcp.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
--- /dev/null
+/*
+ * drivers/amlogic/drm/drm-v0/am_meson_hdcp.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AM_MESON_HDCP_H
+#define __AM_MESON_HDCP_H
+
+#define HDCP_SLAVE 0x3a
+#define HDCP2_VERSION 0x50
+#define HDCP_MODE14 1
+#define HDCP_MODE22 2
+
+#define HDCP_QUIT 0
+#define HDCP14_ENABLE 1
+#define HDCP14_AUTH 2
+#define HDCP14_SUCCESS 3
+#define HDCP14_FAIL 4
+#define HDCP22_ENABLE 5
+#define HDCP22_AUTH 6
+#define HDCP22_SUCCESS 7
+#define HDCP22_FAIL 8
+
+int am_hdcp_init(struct am_hdmi_tx *am_hdmi);
+int is_hdcp_hdmitx_supported(struct am_hdmi_tx *am_hdmi);
+int am_hdcp_work(void *data);
+void am_hdcp_disable(struct am_hdmi_tx *am_hdmi);
+
+#endif
/*
- * drivers/amlogic/drm/am_meson_hdmi.c
+ * drivers/amlogic/drm/drm-v0/am_meson_hdmi.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* more details.
*
*/
+
#include <drm/drm_modeset_helper.h>
#include <drm/drmP.h>
#include <drm/drm_edid.h>
/*
- * drivers/amlogic/drm/am_meson_hdmi.h
+ * drivers/amlogic/drm/drm-v0/am_meson_hdmi.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* more details.
*
*/
+
#ifndef __AM_MESON_HDMI_H
#define __AM_MESON_HDMI_H
/*
- * drivers/amlogic/drm/am_meson_lcd.c
+ * drivers/amlogic/drm/drm-v0/am_meson_lcd.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
drm_panel_remove(&am_drm_lcd->panel);
pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
-
- return;
}
static const struct component_ops am_meson_lcd_ops = {
/*
- * drivers/amlogic/drm/am_meson_lcd.h
+ * drivers/amlogic/drm/drm-v0/am_meson_lcd.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
/*
- * drivers/amlogic/drm/am_meson_vpu.c
+ * drivers/amlogic/drm/drm-v0/am_meson_vpu.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* more details.
*
*/
+
#include <drm/drmP.h>
#include <drm/drm_plane.h>
#include <drm/drm_atomic.h>
/*
- * drivers/amlogic/drm/am_meson_vpu.h
+ * drivers/amlogic/drm/drm-v0/am_meson_vpu.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* more details.
*
*/
+
#ifndef __AM_MESON_VPU_H
#define __AM_MESON_VPU_H
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_crtc.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_crtc.h"
+#include "meson_vpu_pipeline.h"
+#include "osd_drm.h"
+
+static int meson_crtc_set_mode(struct drm_mode_set *set)
+{
+ struct am_meson_crtc *amcrtc;
+ int ret;
+
+ DRM_DEBUG_DRIVER("%s\n", __func__);
+ amcrtc = to_am_meson_crtc(set->crtc);
+ ret = drm_atomic_helper_set_config(set);
+
+ return ret;
+}
+
+static void meson_crtc_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct am_meson_crtc_state *meson_crtc_state;
+
+ meson_crtc_state = to_am_meson_crtc_state(state);
+ __drm_atomic_helper_crtc_destroy_state(&meson_crtc_state->base);
+ kfree(meson_crtc_state);
+}
+
+static struct drm_crtc_state *meson_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+ struct am_meson_crtc_state *meson_crtc_state, *old_crtc_state;
+
+ old_crtc_state = to_am_meson_crtc_state(crtc->state);
+
+ meson_crtc_state = kmemdup(old_crtc_state, sizeof(*old_crtc_state),
+ GFP_KERNEL);
+ if (!meson_crtc_state)
+ return NULL;
+
+ __drm_atomic_helper_crtc_duplicate_state(crtc, &meson_crtc_state->base);
+ return &meson_crtc_state->base;
+}
+
+static int meson_crtc_atomic_get_property(struct drm_crtc *crtc,
+ const struct drm_crtc_state *state,
+ struct drm_property *property,
+ uint64_t *val)
+{
+
+ return 0;
+}
+
+static int meson_crtc_atomic_set_property(struct drm_crtc *crtc,
+ struct drm_crtc_state *state,
+ struct drm_property *property,
+ uint64_t val)
+{
+ return 0;
+}
+
+static const struct drm_crtc_funcs am_meson_crtc_funcs = {
+ .atomic_destroy_state = meson_crtc_destroy_state,
+ .atomic_duplicate_state = meson_crtc_duplicate_state,
+ .destroy = drm_crtc_cleanup,
+ .page_flip = drm_atomic_helper_page_flip,
+ .reset = drm_atomic_helper_crtc_reset,
+ .set_config = meson_crtc_set_mode,
+ .atomic_get_property = meson_crtc_atomic_get_property,
+ .atomic_set_property = meson_crtc_atomic_set_property,
+};
+
+static bool am_meson_crtc_mode_fixup(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
+{
+ //DRM_INFO("%s !!\n", __func__);
+
+ return true;
+}
+
+static void am_meson_crtc_enable(struct drm_crtc *crtc)
+{
+ unsigned long flags;
+ char *name;
+ enum vmode_e mode;
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+ struct meson_vpu_pipeline *pipeline = amcrtc->pipeline;
+
+ DRM_INFO("%s\n", __func__);
+ if (!adjusted_mode) {
+ DRM_ERROR("meson_crtc_enable fail, unsupport mode:%s\n",
+ adjusted_mode->name);
+ return;
+ }
+ DRM_INFO("%s: %s\n", __func__, adjusted_mode->name);
+
+ name = am_meson_crtc_get_voutmode(adjusted_mode);
+ mode = validate_vmode(name);
+ if (mode == VMODE_MAX) {
+ DRM_ERROR("no matched vout mode\n");
+ return;
+ }
+ if (is_meson_g12b_cpu() && is_meson_rev_b())
+ set_reset_rdma_trigger_line();
+ set_vout_init(mode);
+ update_vout_viu();
+ memcpy(&pipeline->mode, adjusted_mode,
+ sizeof(struct drm_display_mode));
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ amcrtc->vblank_enable = 1;
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+ enable_irq(amcrtc->vblank_irq);
+}
+
+static void am_meson_crtc_disable(struct drm_crtc *crtc)
+{
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+ unsigned long flags;
+
+ DRM_INFO("%s\n", __func__);
+ if (crtc->state->event && !crtc->state->active) {
+ spin_lock_irq(&crtc->dev->event_lock);
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ spin_unlock_irq(&crtc->dev->event_lock);
+ crtc->state->event = NULL;
+ }
+
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ amcrtc->vblank_enable = 0;
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+
+ disable_irq(amcrtc->vblank_irq);
+}
+
+static void am_meson_crtc_commit(struct drm_crtc *crtc)
+{
+ //DRM_INFO("%s\n", __func__);
+}
+
+static int am_meson_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
+{
+ struct am_meson_crtc *amcrtc;
+ struct meson_vpu_pipeline *pipeline;
+ struct drm_atomic_state *state = crtc_state->state;
+
+ amcrtc = to_am_meson_crtc(crtc);
+ pipeline = amcrtc->pipeline;
+
+ return vpu_pipeline_check(pipeline, state);
+
+}
+
+static void am_meson_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_crtc_state)
+{
+ struct am_meson_crtc *amcrtc;
+ unsigned long flags;
+
+ amcrtc = to_am_meson_crtc(crtc);
+
+ if (crtc->state->event) {
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ amcrtc->event = crtc->state->event;
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ crtc->state->event = NULL;
+ }
+}
+
+static void am_meson_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+ struct drm_color_ctm *ctm;
+ struct drm_color_lut *lut;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+ struct drm_atomic_state *old_atomic_state = old_state->state;
+
+ struct meson_vpu_pipeline *pipeline = amcrtc->pipeline;
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ int gamma_lut_size = 0;
+ #endif
+
+ if (crtc->state->color_mgmt_changed) {
+ DRM_INFO("%s color_mgmt_changed!\n", __func__);
+ if (crtc->state->ctm) {
+ DRM_INFO("%s color_mgmt_changed 1!\n", __func__);
+ ctm = (struct drm_color_ctm *)
+ crtc->state->ctm->data;
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ am_meson_ctm_set(0, ctm);
+ #endif
+ }
+ if (crtc->state->gamma_lut) {
+ DRM_INFO("%s color_mgmt_changed 2!\n", __func__);
+ lut = (struct drm_color_lut *)
+ crtc->state->gamma_lut->data;
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ gamma_lut_size = amvecm_drm_get_gamma_size(0);
+ amvecm_drm_gamma_set(0, lut, gamma_lut_size);
+ #endif
+ }
+ }
+
+ vpu_pipeline_update(pipeline, old_atomic_state);
+}
+
+static const struct drm_crtc_helper_funcs am_crtc_helper_funcs = {
+ .enable = am_meson_crtc_enable,
+ .disable = am_meson_crtc_disable,
+ .commit = am_meson_crtc_commit,
+ .mode_fixup = am_meson_crtc_mode_fixup,
+ .atomic_check = am_meson_atomic_check,
+ .atomic_begin = am_meson_crtc_atomic_begin,
+ .atomic_flush = am_meson_crtc_atomic_flush,
+};
+
+int am_meson_crtc_create(struct am_meson_crtc *amcrtc)
+{
+ struct meson_drm *priv = amcrtc->priv;
+ struct drm_crtc *crtc = &amcrtc->base;
+ struct meson_vpu_pipeline *pipeline = priv->pipeline;
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ int gamma_lut_size = 0;
+ #endif
+ int ret;
+
+ DRM_INFO("%s\n", __func__);
+ ret = drm_crtc_init_with_planes(priv->drm, crtc,
+ priv->primary_plane, priv->cursor_plane,
+ &am_meson_crtc_funcs, "amlogic vpu");
+ if (ret) {
+ dev_err(amcrtc->dev, "Failed to init CRTC\n");
+ return ret;
+ }
+
+ drm_crtc_helper_add(crtc, &am_crtc_helper_funcs);
+ osd_drm_init(&osd_meson_dev);
+
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ amvecm_drm_init(0);
+ amvecm_drm_gamma_enable(0);
+ gamma_lut_size = amvecm_drm_get_gamma_size(0);
+ drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size);
+ drm_crtc_enable_color_mgmt(crtc, 0, true, gamma_lut_size);
+ #endif
+
+ amcrtc->pipeline = pipeline;
+ priv->crtc = crtc;
+ priv->crtcs[priv->num_crtcs++] = amcrtc;
+ return 0;
+}
+
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_crtc.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_CRTC_H
+#define __MESON_CRTC_H
+
+#include <linux/kernel.h>
+#include <drm/drmP.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+#include <linux/amlogic/media/amvecm/amvecm.h>
+#endif
+#include "osd.h"
+#include "osd_drm.h"
+#include "meson_vpu.h"
+#include "meson_drv.h"
+#include "meson_fb.h"
+
+struct am_meson_crtc_state {
+ struct drm_crtc_state base;
+};
+
+struct am_meson_crtc {
+ struct drm_crtc base;
+ struct device *dev;
+ struct drm_device *drm_dev;
+
+ struct meson_drm *priv;
+
+ struct drm_pending_vblank_event *event;
+
+ unsigned int vblank_irq;
+ spinlock_t vblank_irq_lock;/*atomic*/
+ u32 vblank_enable;
+
+ struct dentry *crtc_debugfs_dir;
+
+ struct meson_vpu_pipeline *pipeline;
+};
+
+#define to_am_meson_crtc(x) container_of(x, \
+ struct am_meson_crtc, base)
+#define to_am_meson_crtc_state(x) container_of(x, \
+ struct am_meson_crtc_state, base)
+
+int am_meson_crtc_create(struct am_meson_crtc *amcrtc);
+
+#endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_drv.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/component.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_fb_helper.h>
+
+#include "meson_fbdev.h"
+#ifdef CONFIG_DRM_MESON_USE_ION
+#include "meson_gem.h"
+#include "meson_fb.h"
+#endif
+#include "meson_drv.h"
+#include "meson_vpu_pipeline.h"
+
+
+#define DRIVER_NAME "meson"
+#define DRIVER_DESC "Amlogic Meson DRM driver"
+
+static void am_meson_fb_output_poll_changed(struct drm_device *dev)
+{
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+ struct meson_drm *priv = dev->dev_private;
+
+ drm_fbdev_cma_hotplug_event(priv->fbdev);
+#endif
+}
+
+static const struct drm_mode_config_funcs meson_mode_config_funcs = {
+ .output_poll_changed = am_meson_fb_output_poll_changed,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+#ifdef CONFIG_DRM_MESON_USE_ION
+ .fb_create = am_meson_fb_create,
+#else
+ .fb_create = drm_fb_cma_create,
+#endif
+};
+
+int am_meson_register_crtc_funcs(struct drm_crtc *crtc,
+ const struct meson_crtc_funcs *crtc_funcs)
+{
+ int pipe = drm_crtc_index(crtc);
+ struct meson_drm *priv = crtc->dev->dev_private;
+
+ if (pipe >= MESON_MAX_CRTC)
+ return -EINVAL;
+
+ priv->crtc_funcs[pipe] = crtc_funcs;
+
+ return 0;
+}
+EXPORT_SYMBOL(am_meson_register_crtc_funcs);
+
+void am_meson_unregister_crtc_funcs(struct drm_crtc *crtc)
+{
+ int pipe = drm_crtc_index(crtc);
+ struct meson_drm *priv = crtc->dev->dev_private;
+
+ if (pipe >= MESON_MAX_CRTC)
+ return;
+
+ priv->crtc_funcs[pipe] = NULL;
+}
+EXPORT_SYMBOL(am_meson_unregister_crtc_funcs);
+
+static int am_meson_enable_vblank(struct drm_device *dev, unsigned int crtc)
+{
+ struct meson_drm *priv = dev->dev_private;
+
+ if (crtc >= MESON_MAX_CRTC)
+ return -EBADFD;
+
+ priv->crtc_funcs[crtc]->enable_vblank(priv->crtc);
+ return 0;
+}
+
+static void am_meson_disable_vblank(struct drm_device *dev, unsigned int crtc)
+{
+ struct meson_drm *priv = dev->dev_private;
+
+ if (crtc >= MESON_MAX_CRTC)
+ return;
+
+ priv->crtc_funcs[crtc]->disable_vblank(priv->crtc);
+}
+
+static void am_meson_load(struct drm_device *dev)
+{
+#if 0
+ struct meson_drm *priv = dev->dev_private;
+ struct drm_crtc *crtc = priv->crtc;
+ int pipe = drm_crtc_index(crtc);
+
+ if (priv->crtc_funcs[pipe] &&
+ priv->crtc_funcs[pipe]->loader_protect)
+ priv->crtc_funcs[pipe]->loader_protect(crtc, true);
+#endif
+}
+
+#ifdef CONFIG_DRM_MESON_USE_ION
+static const struct drm_ioctl_desc meson_ioctls[] = {
+ DRM_IOCTL_DEF_DRV(MESON_GEM_CREATE, am_meson_gem_create_ioctl,
+ DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+};
+#endif
+
+static const struct file_operations fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = drm_compat_ioctl,
+#endif
+ .poll = drm_poll,
+ .read = drm_read,
+ .llseek = no_llseek,
+#ifdef CONFIG_DRM_MESON_USE_ION
+ .mmap = am_meson_gem_mmap,
+#else
+ .mmap = drm_gem_cma_mmap,
+#endif
+};
+
+static struct drm_driver meson_driver = {
+ /*driver_features setting move to probe functions*/
+ .driver_features = 0,
+ /* Vblank */
+ .enable_vblank = am_meson_enable_vblank,
+ .disable_vblank = am_meson_disable_vblank,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
+
+#ifdef CONFIG_DRM_MESON_USE_ION
+ /* PRIME Ops */
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+
+ .gem_prime_export = drm_gem_prime_export,
+ .gem_prime_get_sg_table = am_meson_gem_prime_get_sg_table,
+
+ .gem_prime_import = drm_gem_prime_import,
+ /*
+ * If gem_prime_import_sg_table is NULL,only buffer created
+ * by meson driver can be imported ok.
+ */
+ /*.gem_prime_import_sg_table = am_meson_gem_prime_import_sg_table,*/
+
+ .gem_prime_vmap = am_meson_gem_prime_vmap,
+ .gem_prime_vunmap = am_meson_gem_prime_vunmap,
+ .gem_prime_mmap = am_meson_gem_prime_mmap,
+
+ /* GEM Ops */
+ .dumb_create = am_meson_gem_dumb_create,
+ .dumb_destroy = am_meson_gem_dumb_destroy,
+ .dumb_map_offset = am_meson_gem_dumb_map_offset,
+ .gem_free_object_unlocked = am_meson_gem_object_free,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+ .ioctls = meson_ioctls,
+ .num_ioctls = ARRAY_SIZE(meson_ioctls),
+#else
+ /* PRIME Ops */
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+ .gem_prime_import = drm_gem_prime_import,
+ .gem_prime_export = drm_gem_prime_export,
+ .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+ .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+ .gem_prime_vmap = drm_gem_cma_prime_vmap,
+ .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+ .gem_prime_mmap = drm_gem_cma_prime_mmap,
+
+ /* GEM Ops */
+ .dumb_create = drm_gem_cma_dumb_create,
+ .dumb_destroy = drm_gem_dumb_destroy,
+ .dumb_map_offset = drm_gem_cma_dumb_map_offset,
+ .gem_free_object_unlocked = drm_gem_cma_free_object,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+#endif
+
+ /* Misc */
+ .fops = &fops,
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = "20180321",
+ .major = 1,
+ .minor = 0,
+};
+
+static int am_meson_drm_bind(struct device *dev)
+{
+ struct meson_drm *priv;
+ struct drm_device *drm;
+ struct platform_device *pdev = to_platform_device(dev);
+ int ret = 0;
+
+ meson_driver.driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM |
+ DRIVER_MODESET | DRIVER_PRIME |
+ DRIVER_ATOMIC | DRIVER_IRQ_SHARED;
+
+ drm = drm_dev_alloc(&meson_driver, dev);
+ if (!drm)
+ return -ENOMEM;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto err_free1;
+ }
+ drm->dev_private = priv;
+ priv->drm = drm;
+ priv->dev = dev;
+ dev_set_drvdata(dev, priv);
+
+#ifdef CONFIG_DRM_MESON_USE_ION
+ ret = am_meson_gem_create(priv);
+ if (ret)
+ goto err_free2;
+#endif
+
+ vpu_topology_init(pdev, priv);
+ meson_vpu_block_state_init(priv, priv->pipeline);
+
+ drm_mode_config_init(drm);
+
+ /* Try to bind all sub drivers. */
+ ret = component_bind_all(dev, drm);
+ if (ret)
+ goto err_gem;
+ DRM_INFO("mode_config crtc number:%d\n", drm->mode_config.num_crtc);
+
+ ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+ if (ret)
+ goto err_unbind_all;
+
+ drm_mode_config_reset(drm);
+ drm->mode_config.max_width = 4096;
+ drm->mode_config.max_height = 4096;
+ drm->mode_config.funcs = &meson_mode_config_funcs;
+ drm->mode_config.allow_fb_modifiers = true;
+ /*
+ * irq will init in each crtc, just mark the enable flag here.
+ */
+ drm->irq_enabled = true;
+
+ drm_kms_helper_poll_init(drm);
+
+ am_meson_load(drm);
+
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+ ret = am_meson_drm_fbdev_init(drm);
+ if (ret)
+ goto err_poll_fini;
+#endif
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ goto err_fbdev_fini;
+
+ return 0;
+
+
+err_fbdev_fini:
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+ am_meson_drm_fbdev_fini(drm);
+err_poll_fini:
+#endif
+ drm_kms_helper_poll_fini(drm);
+ drm->irq_enabled = false;
+ drm_vblank_cleanup(drm);
+err_unbind_all:
+ component_unbind_all(dev, drm);
+err_gem:
+ drm_mode_config_cleanup(drm);
+#ifdef CONFIG_DRM_MESON_USE_ION
+ am_meson_gem_cleanup(drm->dev_private);
+err_free2:
+#endif
+ drm->dev_private = NULL;
+ dev_set_drvdata(dev, NULL);
+err_free1:
+ drm_dev_unref(drm);
+
+ return ret;
+}
+
+static void am_meson_drm_unbind(struct device *dev)
+{
+ struct drm_device *drm = dev_get_drvdata(dev);
+
+ drm_dev_unregister(drm);
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+ am_meson_drm_fbdev_fini(drm);
+#endif
+ drm_kms_helper_poll_fini(drm);
+ drm->irq_enabled = false;
+ drm_vblank_cleanup(drm);
+ component_unbind_all(dev, drm);
+ drm_mode_config_cleanup(drm);
+#ifdef CONFIG_DRM_MESON_USE_ION
+ am_meson_gem_cleanup(drm->dev_private);
+#endif
+ drm->dev_private = NULL;
+ dev_set_drvdata(dev, NULL);
+ drm_dev_unref(drm);
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+ struct device_node *np = data;
+
+ return dev->of_node == np;
+}
+
+static void am_meson_add_endpoints(struct device *dev,
+ struct component_match **match,
+ struct device_node *port)
+{
+ struct device_node *ep, *remote;
+
+ for_each_child_of_node(port, ep) {
+ remote = of_graph_get_remote_port_parent(ep);
+ if (!remote || !of_device_is_available(remote)) {
+ of_node_put(remote);
+ continue;
+ } else if (!of_device_is_available(remote->parent)) {
+ of_node_put(remote);
+ continue;
+ }
+ component_match_add(dev, match, compare_of, remote);
+ of_node_put(remote);
+ }
+}
+
+static const struct component_master_ops am_meson_drm_ops = {
+ .bind = am_meson_drm_bind,
+ .unbind = am_meson_drm_unbind,
+};
+
+static bool am_meson_drv_use_osd(void)
+{
+ struct device_node *node;
+ const char *str;
+ int ret;
+
+ node = of_find_node_by_path("/meson-fb");
+ if (node) {
+ ret = of_property_read_string(node, "status", &str);
+ if (ret) {
+ DRM_INFO("get 'status' failed:%d\n", ret);
+ return false;
+ }
+
+ if (strcmp(str, "okay") && strcmp(str, "ok")) {
+ DRM_INFO("device %s status is %s\n",
+ node->name, str);
+ } else {
+ DRM_INFO("device %s status is %s\n",
+ node->name, str);
+ return true;
+ }
+ }
+ return false;
+}
+
+static int am_meson_drv_probe_prune(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct meson_drm *priv;
+ struct drm_device *drm;
+ int ret;
+
+ /*driver_features reset to DRIVER_GEM | DRIVER_PRIME, for prune drm*/
+ meson_driver.driver_features = DRIVER_GEM | DRIVER_PRIME;
+
+ drm = drm_dev_alloc(&meson_driver, dev);
+ if (!drm)
+ return -ENOMEM;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto err_free1;
+ }
+ drm->dev_private = priv;
+ priv->drm = drm;
+ priv->dev = dev;
+
+ platform_set_drvdata(pdev, priv);
+
+#ifdef CONFIG_DRM_MESON_USE_ION
+ ret = am_meson_gem_create(priv);
+ if (ret)
+ goto err_free2;
+#endif
+
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ goto err_gem;
+
+ return 0;
+
+err_gem:
+#ifdef CONFIG_DRM_MESON_USE_ION
+ am_meson_gem_cleanup(drm->dev_private);
+err_free2:
+#endif
+ drm->dev_private = NULL;
+ platform_set_drvdata(pdev, NULL);
+err_free1:
+ drm_dev_unref(drm);
+ return ret;
+}
+
+static int am_meson_drv_remove_prune(struct platform_device *pdev)
+{
+ struct drm_device *drm = platform_get_drvdata(pdev);
+
+ drm_dev_unregister(drm);
+#ifdef CONFIG_DRM_MESON_USE_ION
+ am_meson_gem_cleanup(drm->dev_private);
+#endif
+ drm->dev_private = NULL;
+ platform_set_drvdata(pdev, NULL);
+ drm_dev_unref(drm);
+
+ return 0;
+}
+
+static int am_meson_drv_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *port;
+ struct component_match *match = NULL;
+ int i;
+
+ if (am_meson_drv_use_osd())
+ return am_meson_drv_probe_prune(pdev);
+
+ if (!np)
+ return -ENODEV;
+
+ /*
+ * Bind the crtc ports first, so that
+ * drm_of_find_possible_crtcs called from encoder .bind callbacks
+ * works as expected.
+ */
+ for (i = 0;; i++) {
+ port = of_parse_phandle(np, "ports", i);
+ if (!port)
+ break;
+
+ if (!of_device_is_available(port->parent)) {
+ of_node_put(port);
+ continue;
+ }
+
+ component_match_add(dev, &match, compare_of, port->parent);
+ of_node_put(port);
+ }
+
+ if (i == 0) {
+ dev_err(dev, "missing 'ports' property.\n");
+ return -ENODEV;
+ }
+
+ if (!match) {
+ dev_err(dev, "No available vout found for display-subsystem.\n");
+ return -ENODEV;
+ }
+
+ /*
+ * For each bound crtc, bind the encoders attached to its
+ * remote endpoint.
+ */
+ for (i = 0;; i++) {
+ port = of_parse_phandle(np, "ports", i);
+ if (!port)
+ break;
+
+ if (!of_device_is_available(port->parent)) {
+ of_node_put(port);
+ continue;
+ }
+
+ am_meson_add_endpoints(dev, &match, port);
+ of_node_put(port);
+ }
+
+ return component_master_add_with_match(dev, &am_meson_drm_ops, match);
+}
+
+static int am_meson_drv_remove(struct platform_device *pdev)
+{
+ if (am_meson_drv_use_osd())
+ return am_meson_drv_remove_prune(pdev);
+
+ component_master_del(&pdev->dev, &am_meson_drm_ops);
+ return 0;
+}
+
+static const struct of_device_id am_meson_drm_dt_match[] = {
+ { .compatible = "amlogic,drm-subsystem" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, am_meson_drm_dt_match);
+
+static struct platform_driver am_meson_drm_platform_driver = {
+ .probe = am_meson_drv_probe,
+ .remove = am_meson_drv_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .of_match_table = am_meson_drm_dt_match,
+ },
+};
+
+module_platform_driver(am_meson_drm_platform_driver);
+
+MODULE_AUTHOR("Jasper St. Pierre <jstpierre@mecheye.net>");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_drv.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AM_MESON_DRV_H
+#define __AM_MESON_DRV_H
+
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <drm/drmP.h>
+#ifdef CONFIG_DRM_MESON_USE_ION
+#include <ion/ion_priv.h>
+#endif
+
+#define MESON_MAX_CRTC 2
+#define MESON_MAX_OSD 4
+
+/*
+ * Amlogic drm private crtc funcs.
+ * @loader_protect: protect loader logo crtc's power
+ * @enable_vblank: enable crtc vblank irq.
+ * @disable_vblank: disable crtc vblank irq.
+ */
+struct meson_crtc_funcs {
+ int (*loader_protect)(struct drm_crtc *crtc, bool on);
+ int (*enable_vblank)(struct drm_crtc *crtc);
+ void (*disable_vblank)(struct drm_crtc *crtc);
+};
+
+struct meson_drm {
+ struct device *dev;
+
+ struct drm_device *drm;
+ struct drm_crtc *crtc;
+ const struct meson_crtc_funcs *crtc_funcs[MESON_MAX_CRTC];
+ struct drm_fbdev_cma *fbdev;
+ struct drm_fb_helper *fbdev_helper;
+ struct drm_gem_object *fbdev_bo;
+ struct drm_plane *primary_plane;
+ struct drm_plane *cursor_plane;
+
+#ifdef CONFIG_DRM_MESON_USE_ION
+ struct ion_client *gem_client;
+#endif
+
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_funcs *funcs;
+
+ u32 num_crtcs;
+ struct am_meson_crtc *crtcs[MESON_MAX_CRTC];
+
+ u32 num_planes;
+ struct am_osd_plane *planes[MESON_MAX_OSD];
+};
+
+static inline int meson_vpu_is_compatible(struct meson_drm *priv,
+ const char *compat)
+{
+ return of_device_is_compatible(priv->dev->of_node, compat);
+}
+
+extern int am_meson_register_crtc_funcs(struct drm_crtc *crtc,
+ const struct meson_crtc_funcs *crtc_funcs);
+extern void am_meson_unregister_crtc_funcs(struct drm_crtc *crtc);
+
+#endif /* __AM_MESON_DRV_H */
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_fb.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+
+#include "meson_fb.h"
+
+#define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base)
+
+void am_meson_fb_destroy(struct drm_framebuffer *fb)
+{
+ struct am_meson_fb *meson_fb = to_am_meson_fb(fb);
+
+ drm_gem_object_unreference_unlocked(&meson_fb->bufp->base);
+ drm_framebuffer_cleanup(fb);
+ kfree(meson_fb);
+}
+
+int am_meson_fb_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv,
+ unsigned int *handle)
+{
+ struct am_meson_fb *meson_fb = to_am_meson_fb(fb);
+
+ return drm_gem_handle_create(file_priv,
+ &meson_fb->bufp->base, handle);
+}
+
+struct drm_framebuffer_funcs am_meson_fb_funcs = {
+ .create_handle = am_meson_fb_create_handle, //must for fbdev emulate
+ .destroy = am_meson_fb_destroy,
+};
+
+struct drm_framebuffer *
+am_meson_fb_alloc(struct drm_device *dev,
+ struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj)
+{
+ struct am_meson_fb *meson_fb;
+ struct am_meson_gem_object *meson_gem;
+ int ret = 0;
+
+ meson_fb = kzalloc(sizeof(*meson_fb), GFP_KERNEL);
+ if (!meson_fb)
+ return ERR_PTR(-ENOMEM);
+
+ meson_gem = container_of(obj, struct am_meson_gem_object, base);
+ meson_fb->bufp = meson_gem;
+
+ drm_helper_mode_fill_fb_struct(&meson_fb->base, mode_cmd);
+
+ ret = drm_framebuffer_init(dev, &meson_fb->base,
+ &am_meson_fb_funcs);
+ if (ret) {
+ dev_err(dev->dev, "Failed to initialize framebuffer: %d\n",
+ ret);
+ goto err_free_fb;
+ }
+
+ return &meson_fb->base;
+
+err_free_fb:
+ kfree(meson_fb);
+ return ERR_PTR(ret);
+}
+
+struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev,
+ struct drm_file *file_priv,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ struct am_meson_fb *meson_fb = 0;
+ struct drm_gem_object *obj = 0;
+ struct am_meson_gem_object *meson_gem;
+ int ret;
+
+ meson_fb = kzalloc(sizeof(*meson_fb), GFP_KERNEL);
+ if (!meson_fb)
+ return ERR_PTR(-ENOMEM);
+
+ /* only support one handle now.*/
+ obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
+ if (!obj) {
+ dev_err(dev->dev, "Failed to lookup GEM handle\n");
+ kfree(meson_fb);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ meson_gem = container_of(obj, struct am_meson_gem_object, base);
+ meson_fb->bufp = meson_gem;
+
+ drm_helper_mode_fill_fb_struct(&meson_fb->base, mode_cmd);
+
+ ret = drm_framebuffer_init(dev, &meson_fb->base, &am_meson_fb_funcs);
+ if (ret) {
+ dev_err(dev->dev,
+ "Failed to initialize framebuffer: %d\n",
+ ret);
+ drm_gem_object_unreference(obj);
+ kfree(meson_fb);
+ return ERR_PTR(ret);
+ }
+
+ return &meson_fb->base;
+}
+
+struct drm_framebuffer *
+am_meson_drm_framebuffer_init(struct drm_device *dev,
+ struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj)
+{
+ struct drm_framebuffer *fb;
+
+ fb = am_meson_fb_alloc(dev, mode_cmd, obj);
+ if (IS_ERR(fb))
+ return NULL;
+
+ return fb;
+}
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_fb.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AM_MESON_FB_H
+#define __AM_MESON_FB_H
+#include <drm/drmP.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_modeset_helper.h>
+
+#include "meson_gem.h"
+
+struct am_meson_fb {
+ struct drm_framebuffer base;
+ struct am_meson_gem_object *bufp;
+};
+
+struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev,
+ struct drm_file *file_priv,
+ const struct drm_mode_fb_cmd2 *mode_cmd);
+struct drm_framebuffer *am_meson_drm_framebuffer_init(
+ struct drm_device *dev,
+ struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj);
+#endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_fbdev.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drm.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "meson_drv.h"
+#include "meson_gem.h"
+#include "meson_fb.h"
+#include "meson_fbdev.h"
+
+#define PREFERRED_BPP 32
+#define MESON_DRM_MAX_CONNECTOR 2
+
+static int am_meson_fbdev_mmap(struct fb_info *info,
+ struct vm_area_struct *vma)
+{
+ struct drm_fb_helper *helper = info->par;
+ struct meson_drm *private;
+ struct am_meson_gem_object *meson_gem;
+
+ private = helper->dev->dev_private;
+ meson_gem = container_of(private->fbdev_bo,
+ struct am_meson_gem_object, base);
+
+ return am_meson_gem_object_mmap(meson_gem, vma);
+}
+
+static int am_meson_drm_fbdev_sync(struct fb_info *info)
+{
+ return 0;
+}
+
+static int am_meson_drm_fbdev_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+static struct fb_ops meson_drm_fbdev_ops = {
+ .owner = THIS_MODULE,
+ .fb_mmap = am_meson_fbdev_mmap,
+ .fb_fillrect = drm_fb_helper_cfb_fillrect,
+ .fb_copyarea = drm_fb_helper_cfb_copyarea,
+ .fb_imageblit = drm_fb_helper_cfb_imageblit,
+ .fb_check_var = drm_fb_helper_check_var,
+ .fb_set_par = drm_fb_helper_set_par,
+ .fb_blank = drm_fb_helper_blank,
+ .fb_pan_display = drm_fb_helper_pan_display,
+ .fb_setcmap = drm_fb_helper_setcmap,
+ .fb_sync = am_meson_drm_fbdev_sync,
+ .fb_ioctl = am_meson_drm_fbdev_ioctl,
+#ifdef CONFIG_COMPAT
+ .fb_compat_ioctl = am_meson_drm_fbdev_ioctl,
+#endif
+};
+
+static int am_meson_drm_fbdev_create(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct meson_drm *private = helper->dev->dev_private;
+ struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+ struct drm_device *dev = helper->dev;
+ struct am_meson_gem_object *meson_obj;
+ struct drm_framebuffer *fb;
+ struct ion_client *client;
+ unsigned int bytes_per_pixel;
+ unsigned long offset;
+ struct fb_info *fbi;
+ size_t size;
+ int ret;
+
+ bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+ mode_cmd.width = sizes->surface_width;
+ mode_cmd.height = sizes->surface_height;
+ mode_cmd.pitches[0] = ALIGN(sizes->surface_width * bytes_per_pixel, 64);
+ mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+ sizes->surface_depth);
+
+ size = mode_cmd.pitches[0] * mode_cmd.height;
+
+ client = (struct ion_client *)private->gem_client;
+ meson_obj = am_meson_gem_object_create(dev, 0, size, client);
+ if (IS_ERR(meson_obj))
+ return -ENOMEM;
+
+ private->fbdev_bo = &meson_obj->base;
+
+ fbi = drm_fb_helper_alloc_fbi(helper);
+ if (IS_ERR(fbi)) {
+ dev_err(dev->dev, "Failed to create framebuffer info.\n");
+ ret = PTR_ERR(fbi);
+ goto err_meson_gem_free_object;
+ }
+
+ helper->fb = am_meson_drm_framebuffer_init(dev, &mode_cmd,
+ private->fbdev_bo);
+ if (IS_ERR(helper->fb)) {
+ dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
+ ret = PTR_ERR(helper->fb);
+ goto err_release_fbi;
+ }
+
+ fbi->par = helper;
+ fbi->flags = FBINFO_FLAG_DEFAULT;
+ fbi->fbops = &meson_drm_fbdev_ops;
+
+ fb = helper->fb;
+ drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
+ drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
+
+ offset = fbi->var.xoffset * bytes_per_pixel;
+ offset += fbi->var.yoffset * fb->pitches[0];
+
+ dev->mode_config.fb_base = 0;
+ fbi->screen_size = size;
+ fbi->fix.smem_len = size;
+
+ DRM_DEBUG_KMS("FB [%dx%d]-%d offset=%ld size=%zu\n",
+ fb->width, fb->height, fb->depth, offset, size);
+
+ fbi->skip_vt_switch = true;
+
+ return 0;
+
+err_release_fbi:
+ drm_fb_helper_release_fbi(helper);
+err_meson_gem_free_object:
+ am_meson_gem_object_free(&meson_obj->base);
+ return ret;
+}
+
+static const struct drm_fb_helper_funcs meson_drm_fb_helper_funcs = {
+ .fb_probe = am_meson_drm_fbdev_create,
+};
+
+int am_meson_drm_fbdev_init(struct drm_device *dev)
+{
+ struct meson_drm *private = dev->dev_private;
+ struct drm_fb_helper *helper;
+ unsigned int num_crtc;
+ int ret;
+
+ if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
+ return -EINVAL;
+
+ num_crtc = dev->mode_config.num_crtc;
+
+ helper = devm_kzalloc(dev->dev, sizeof(*helper), GFP_KERNEL);
+ if (!helper)
+ return -ENOMEM;
+
+ drm_fb_helper_prepare(dev, helper, &meson_drm_fb_helper_funcs);
+
+ ret = drm_fb_helper_init(dev, helper, num_crtc,
+ MESON_DRM_MAX_CONNECTOR);
+ if (ret < 0) {
+ dev_err(dev->dev, "Failed to initialize drm fb helper - %d.\n",
+ ret);
+ goto err_free;
+ }
+
+ ret = drm_fb_helper_single_add_all_connectors(helper);
+ if (ret < 0) {
+ dev_err(dev->dev, "Failed to add connectors - %d.\n", ret);
+ goto err_drm_fb_helper_fini;
+ }
+
+ ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
+ if (ret < 0) {
+ dev_err(dev->dev, "Failed to set initial hw config - %d.\n",
+ ret);
+ goto err_drm_fb_helper_fini;
+ }
+
+ private->fbdev_helper = helper;
+
+ return 0;
+
+err_drm_fb_helper_fini:
+ drm_fb_helper_fini(helper);
+err_free:
+ kfree(fbdev_cma);
+ return ret;
+}
+
+void am_meson_drm_fbdev_fini(struct drm_device *dev)
+{
+ struct meson_drm *private = dev->dev_private;
+ struct drm_fb_helper *helper = private->fbdev_helper;
+
+ if (!helper)
+ return;
+
+ drm_fb_helper_unregister_fbi(helper);
+ drm_fb_helper_release_fbi(helper);
+
+ if (helper->fb)
+ drm_framebuffer_unreference(helper->fb);
+
+ drm_fb_helper_fini(helper);
+}
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_fbdev.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AM_MESON_FBDEV_H
+#define __AM_MESON_FBDEV_H
+
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+int am_meson_drm_fbdev_init(struct drm_device *dev);
+void am_meson_drm_fbdev_fini(struct drm_device *dev);
+#endif
+
+#endif /* __AM_MESON_FBDEV_H */
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_gem.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_vma_manager.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/dma-buf.h>
+#include <linux/meson_ion.h>
+#include <ion/ion.h>
+
+#include "meson_gem.h"
+
+#define to_am_meson_gem_obj(x) container_of(x, struct am_meson_gem_object, base)
+
+static int am_meson_gem_alloc_ion_buff(
+ struct ion_client *client,
+ struct am_meson_gem_object *meson_gem_obj,
+ int flags)
+{
+ struct ion_handle *handle;
+ bool bscatter = false;
+
+ if (!client)
+ return -EINVAL;
+
+ if (!meson_gem_obj)
+ return -EINVAL;
+
+ //check flags to set different ion heap type.
+ //if flags is set to 0, need to use ion dma buffer.
+ if (((flags & (MESON_USE_SCANOUT | MESON_USE_CURSOR)) != 0)
+ || (flags == 0)) {
+ handle = ion_alloc(client, meson_gem_obj->base.size,
+ 0, (1 << ION_HEAP_TYPE_DMA), 0);
+ } else {
+ handle = ion_alloc(client, meson_gem_obj->base.size,
+ 0, (1 << ION_HEAP_TYPE_SYSTEM), 0);
+ bscatter = true;
+ }
+
+ if (IS_ERR(handle)) {
+ DRM_ERROR("%s: FAILED, flags:0x%x.\n",
+ __func__, flags);
+ return -ENOMEM;
+ }
+
+ meson_gem_obj->handle = handle;
+ meson_gem_obj->bscatter = bscatter;
+ DRM_DEBUG("%s: allocate handle (%p).\n",
+ __func__, meson_gem_obj->handle);
+ return 0;
+}
+
+static void am_meson_gem_free_ion_buf(
+ struct drm_device *dev,
+ struct am_meson_gem_object *meson_gem_obj)
+{
+ struct ion_client *client = NULL;
+
+ if (meson_gem_obj->handle) {
+ DRM_DEBUG("am_meson_gem_free_ion_buf free handle (%p).\n",
+ meson_gem_obj->handle);
+ client = meson_gem_obj->handle->client;
+ ion_free(client, meson_gem_obj->handle);
+ meson_gem_obj->handle = NULL;
+ } else {
+ DRM_ERROR("meson_gem_obj handle is null\n");
+ }
+}
+
+struct am_meson_gem_object *am_meson_gem_object_create(
+ struct drm_device *dev,
+ unsigned int flags,
+ unsigned long size,
+ struct ion_client *client)
+{
+ struct am_meson_gem_object *meson_gem_obj = NULL;
+ int ret;
+
+ if (!size) {
+ DRM_ERROR("invalid size.\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ size = roundup(size, PAGE_SIZE);
+ meson_gem_obj = kzalloc(sizeof(*meson_gem_obj), GFP_KERNEL);
+ if (!meson_gem_obj)
+ return ERR_PTR(-ENOMEM);
+
+ ret = drm_gem_object_init(dev, &meson_gem_obj->base, size);
+ if (ret < 0) {
+ DRM_ERROR("failed to initialize gem object\n");
+ goto error;
+ }
+
+ ret = am_meson_gem_alloc_ion_buff(client, meson_gem_obj, flags);
+ if (ret < 0) {
+ drm_gem_object_release(&meson_gem_obj->base);
+ goto error;
+ }
+
+ return meson_gem_obj;
+
+error:
+ kfree(meson_gem_obj);
+ return ERR_PTR(ret);
+}
+
+void am_meson_gem_object_free(struct drm_gem_object *obj)
+{
+ struct am_meson_gem_object *meson_gem_obj = to_am_meson_gem_obj(obj);
+
+ DRM_DEBUG("am_meson_gem_object_free %p handle count = %d\n",
+ meson_gem_obj, obj->handle_count);
+
+ if (obj->import_attach == false)
+ am_meson_gem_free_ion_buf(obj->dev, meson_gem_obj);
+ else
+ DRM_ERROR("Not support import buffer from other driver.\n");
+
+ drm_gem_free_mmap_offset(obj);
+
+ /* release file pointer to gem object. */
+ drm_gem_object_release(obj);
+
+ kfree(meson_gem_obj);
+ meson_gem_obj = NULL;
+}
+
+int am_meson_gem_object_mmap(
+ struct am_meson_gem_object *obj,
+ struct vm_area_struct *vma)
+{
+ int ret = 0;
+ struct ion_buffer *buffer;
+
+ /*
+ * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
+ * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
+ * the whole buffer.
+ */
+ vma->vm_flags &= ~VM_PFNMAP;
+ vma->vm_pgoff = 0;
+
+ if (obj->base.import_attach) {
+ DRM_ERROR("Not support import buffer from other driver.\n");
+ } else {
+ buffer = obj->handle->buffer;
+
+ if (!buffer->heap->ops->map_user) {
+ DRM_ERROR("%s:heap does not define map to userspace\n",
+ __func__);
+ ret = -EINVAL;
+ } else {
+
+ if (!(buffer->flags & ION_FLAG_CACHED))
+ vma->vm_page_prot =
+ pgprot_writecombine(vma->vm_page_prot);
+
+ mutex_lock(&buffer->lock);
+ /* now map it to userspace */
+ ret = buffer->heap->ops->map_user(
+ buffer->heap, buffer, vma);
+ mutex_unlock(&buffer->lock);
+ }
+ }
+
+ if (ret) {
+ DRM_ERROR("%s: failure mapping buffer to userspace (%d)\n",
+ __func__, ret);
+ drm_gem_vm_close(vma);
+ }
+
+ return ret;
+}
+
+int am_meson_gem_mmap(
+ struct file *filp,
+ struct vm_area_struct *vma)
+{
+ struct drm_gem_object *obj;
+ struct am_meson_gem_object *meson_gem_obj;
+ int ret;
+
+ ret = drm_gem_mmap(filp, vma);
+ if (ret)
+ return ret;
+
+ obj = vma->vm_private_data;
+ meson_gem_obj = to_am_meson_gem_obj(obj);
+ DRM_DEBUG("am_meson_gem_mmap %p.\n", meson_gem_obj);
+
+ ret = am_meson_gem_object_mmap(meson_gem_obj, vma);
+
+ return ret;
+}
+
+int am_meson_gem_object_get_phyaddr(
+ struct meson_drm *drm,
+ struct am_meson_gem_object *meson_gem)
+{
+ int addr;
+ size_t len;
+
+ if (!meson_gem->handle) {
+ DRM_INFO("%s handle null\n", __func__);
+ return -1;
+ }
+
+ ion_phys(drm->gem_client, meson_gem->handle,
+ (ion_phys_addr_t *)&addr, &len);
+
+ return addr;
+}
+EXPORT_SYMBOL(am_meson_gem_object_get_phyaddr);
+
+int am_meson_gem_dumb_create(
+ struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args)
+{
+ int ret = 0;
+ struct am_meson_gem_object *meson_gem_obj;
+ struct meson_drm *drmdrv = dev->dev_private;
+ struct ion_client *client = (struct ion_client *)drmdrv->gem_client;
+ int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+
+ args->pitch = ALIGN(min_pitch, 64);
+ if (args->size < args->pitch * args->height)
+ args->size = args->pitch * args->height;
+
+ args->size = round_up(args->size, PAGE_SIZE);
+
+ meson_gem_obj = am_meson_gem_object_create(
+ dev, args->flags, args->size, client);
+ if (IS_ERR(meson_gem_obj))
+ return PTR_ERR(meson_gem_obj);
+
+ /*
+ * allocate a id of idr table where the obj is registered
+ * and handle has the id what user can see.
+ */
+ ret = drm_gem_handle_create(file_priv,
+ &meson_gem_obj->base, &args->handle);
+ /* drop reference from allocate - handle holds it now. */
+ drm_gem_object_unreference_unlocked(&meson_gem_obj->base);
+ if (ret) {
+ DRM_ERROR("%s: create dumb handle failed %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ DRM_DEBUG("%s: create dumb %p with gem handle (0x%x)\n",
+ __func__, meson_gem_obj, args->handle);
+ return 0;
+}
+
+int am_meson_gem_dumb_destroy(
+ struct drm_file *file,
+ struct drm_device *dev,
+ uint32_t handle)
+{
+ DRM_DEBUG("%s: destroy dumb with handle (0x%x)\n", __func__, handle);
+ drm_gem_handle_delete(file, handle);
+ return 0;
+}
+
+int am_meson_gem_dumb_map_offset(
+ struct drm_file *file_priv,
+ struct drm_device *dev,
+ uint32_t handle,
+ uint64_t *offset)
+{
+ struct drm_gem_object *obj;
+ int ret = 0;
+
+ mutex_lock(&dev->struct_mutex);
+
+ /*
+ * get offset of memory allocated for drm framebuffer.
+ * - this callback would be called by user application
+ * with DRM_IOCTL_MODE_MAP_DUMB command.
+ */
+ obj = drm_gem_object_lookup(file_priv, handle);
+ if (!obj) {
+ DRM_ERROR("failed to lookup gem object.\n");
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ ret = drm_gem_create_mmap_offset(obj);
+ if (ret)
+ goto out;
+
+ *offset = drm_vma_node_offset_addr(&obj->vma_node);
+ DRM_DEBUG("offset = 0x%lx\n", (unsigned long)*offset);
+
+out:
+ drm_gem_object_unreference(obj);
+unlock:
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
+
+int am_meson_gem_create_ioctl(
+ struct drm_device *dev,
+ void *data,
+ struct drm_file *file_priv)
+{
+ struct am_meson_gem_object *meson_gem_obj;
+ struct meson_drm *drmdrv = dev->dev_private;
+ struct ion_client *client = (struct ion_client *)drmdrv->gem_client;
+ struct drm_meson_gem_create *args = data;
+ int ret = 0;
+
+ meson_gem_obj = am_meson_gem_object_create(
+ dev, args->flags, args->size, client);
+ if (IS_ERR(meson_gem_obj))
+ return PTR_ERR(meson_gem_obj);
+
+ /*
+ * allocate a id of idr table where the obj is registered
+ * and handle has the id what user can see.
+ */
+ ret = drm_gem_handle_create(file_priv,
+ &meson_gem_obj->base, &args->handle);
+ /* drop reference from allocate - handle holds it now. */
+ drm_gem_object_unreference_unlocked(&meson_gem_obj->base);
+ if (ret) {
+ DRM_ERROR("%s: create dumb handle failed %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ DRM_DEBUG("%s: create dumb %p with gem handle (0x%x)\n",
+ __func__, meson_gem_obj, args->handle);
+ return 0;
+}
+
+
+int am_meson_gem_create(struct meson_drm *drmdrv)
+{
+ drmdrv->gem_client = meson_ion_client_create(-1, "meson-gem");
+ if (!drmdrv->gem_client) {
+ DRM_ERROR("open ion client error\n");
+ return -EFAULT;
+ }
+
+ DRM_DEBUG("open ion client: %p\n", drmdrv->gem_client);
+ return 0;
+}
+
+void am_meson_gem_cleanup(struct meson_drm *drmdrv)
+{
+ struct ion_client *gem_ion_client = drmdrv->gem_client;
+
+ if (gem_ion_client) {
+ DRM_DEBUG(" destroy ion client: %p\n", gem_ion_client);
+ ion_client_destroy(gem_ion_client);
+ }
+}
+
+struct sg_table *am_meson_gem_prime_get_sg_table(
+ struct drm_gem_object *obj)
+{
+ struct am_meson_gem_object *meson_gem_obj;
+ struct sg_table *dst_table = NULL;
+ struct scatterlist *dst_sg = NULL;
+ struct sg_table *src_table = NULL;
+ struct scatterlist *src_sg = NULL;
+ int ret, i;
+
+ meson_gem_obj = to_am_meson_gem_obj(obj);
+ DRM_DEBUG("am_meson_gem_prime_get_sg_table %p.\n", meson_gem_obj);
+
+ if (meson_gem_obj->base.import_attach == false) {
+ src_table = meson_gem_obj->handle->buffer->sg_table;
+ dst_table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+ if (!dst_table) {
+ ret = -ENOMEM;
+ return ERR_PTR(ret);
+ }
+
+ ret = sg_alloc_table(dst_table, src_table->nents, GFP_KERNEL);
+ if (ret) {
+ kfree(dst_table);
+ return ERR_PTR(ret);
+ }
+
+ dst_sg = dst_table->sgl;
+ src_sg = src_table->sgl;
+ for (i = 0; i < src_table->nents; i++) {
+ sg_set_page(dst_sg, sg_page(src_sg), src_sg->length, 0);
+ dst_sg = sg_next(dst_sg);
+ src_sg = sg_next(src_sg);
+ }
+ return dst_table;
+ }
+ DRM_ERROR("Not support import buffer from other driver.\n");
+ return NULL;
+}
+
+struct drm_gem_object *am_meson_gem_prime_import_sg_table(
+ struct drm_device *dev,
+ struct dma_buf_attachment *attach,
+ struct sg_table *sgt)
+{
+ struct am_meson_gem_object *meson_gem_obj;
+ int ret;
+
+ meson_gem_obj = kzalloc(sizeof(*meson_gem_obj), GFP_KERNEL);
+ if (!meson_gem_obj)
+ return ERR_PTR(-ENOMEM);
+
+ ret = drm_gem_object_init(dev,
+ &meson_gem_obj->base,
+ attach->dmabuf->size);
+ if (ret < 0) {
+ DRM_ERROR("failed to initialize gem object\n");
+ kfree(meson_gem_obj);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ DRM_DEBUG("%s: %p, sg_table %p\n", __func__, meson_gem_obj, sgt);
+ /*meson_gem_obj->sgt = sgt;*/
+ return &meson_gem_obj->base;
+}
+
+void *am_meson_gem_prime_vmap(struct drm_gem_object *obj)
+{
+ DRM_DEBUG("am_meson_gem_prime_vmap %p.\n", obj);
+
+ return NULL;
+}
+
+void am_meson_gem_prime_vunmap(
+ struct drm_gem_object *obj,
+ void *vaddr)
+{
+ DRM_DEBUG("am_meson_gem_prime_vunmap nothing to do.\n");
+}
+
+int am_meson_gem_prime_mmap(
+ struct drm_gem_object *obj,
+ struct vm_area_struct *vma)
+{
+ struct am_meson_gem_object *meson_gem_obj;
+ int ret;
+
+ ret = drm_gem_mmap_obj(obj, obj->size, vma);
+ if (ret < 0)
+ return ret;
+
+ meson_gem_obj = to_am_meson_gem_obj(obj);
+ DRM_DEBUG("am_meson_gem_prime_mmap %p.\n", meson_gem_obj);
+
+ return am_meson_gem_object_mmap(meson_gem_obj, vma);
+}
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_gem.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AM_MESON_GEM_H
+#define __AM_MESON_GEM_H
+#include <drm/drm_gem.h>
+#include <uapi/drm/meson_drm.h>
+#include <ion/ion_priv.h>
+
+#include "meson_drv.h"
+
+struct am_meson_gem_object {
+ struct drm_gem_object base;
+ unsigned int flags;
+
+ /*for buffer create from ion heap */
+ struct ion_handle *handle;
+ bool bscatter;
+};
+
+/* GEM MANAGER CREATE*/
+int am_meson_gem_create(struct meson_drm *drmdrv);
+
+void am_meson_gem_cleanup(struct meson_drm *drmdrv);
+
+int am_meson_gem_mmap(
+ struct file *filp,
+ struct vm_area_struct *vma);
+
+/* GEM DUMB OPERATIONS */
+int am_meson_gem_dumb_create(
+ struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+
+int am_meson_gem_dumb_destroy(
+ struct drm_file *file,
+ struct drm_device *dev,
+ uint32_t handle);
+
+int am_meson_gem_create_ioctl(
+ struct drm_device *dev,
+ void *data,
+ struct drm_file *file_priv);
+
+int am_meson_gem_dumb_map_offset(
+ struct drm_file *file_priv,
+ struct drm_device *dev,
+ uint32_t handle,
+ uint64_t *offset);
+
+/* GEM OBJECT OPERATIONS */
+struct am_meson_gem_object *am_meson_gem_object_create(
+ struct drm_device *dev, unsigned int flags,
+ unsigned long size, struct ion_client *client);
+
+void am_meson_gem_object_free(struct drm_gem_object *gem_obj);
+
+int am_meson_gem_object_mmap(
+ struct am_meson_gem_object *obj,
+ struct vm_area_struct *vma);
+
+extern int am_meson_gem_object_get_phyaddr(
+ struct meson_drm *drm,
+ struct am_meson_gem_object *meson_gem);
+
+/* GEM PRIME OPERATIONS */
+struct sg_table *am_meson_gem_prime_get_sg_table(
+ struct drm_gem_object *obj);
+
+struct drm_gem_object *am_meson_gem_prime_import_sg_table(
+ struct drm_device *dev,
+ struct dma_buf_attachment *attach,
+ struct sg_table *sgt);
+
+void *am_meson_gem_prime_vmap(
+ struct drm_gem_object *obj);
+
+void am_meson_gem_prime_vunmap(
+ struct drm_gem_object *obj,
+ void *vaddr);
+
+int am_meson_gem_prime_mmap(
+ struct drm_gem_object *obj,
+ struct vm_area_struct *vma);
+
+#endif /* __AM_MESON_GEM_H */
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_hdcp.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drm_modeset_helper.h>
+#include <drm/drmP.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include <linux/component.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
+#include <linux/arm-smccc.h>
+
+#include "meson_hdmi.h"
+#include "meson_hdcp.h"
+
+static int hdcp_topo_st = -1;
+static int hdmitx_hdcp_opr(unsigned int val)
+{
+ struct arm_smccc_res res;
+
+ if (val == 1) { /* HDCP14_ENABLE */
+ arm_smccc_smc(0x82000010, 0, 0, 0, 0, 0, 0, 0, &res);
+ }
+ if (val == 2) { /* HDCP14_RESULT */
+ arm_smccc_smc(0x82000011, 0, 0, 0, 0, 0, 0, 0, &res);
+ return (unsigned int)((res.a0)&0xffffffff);
+ }
+ if (val == 0) { /* HDCP14_INIT */
+ arm_smccc_smc(0x82000012, 0, 0, 0, 0, 0, 0, 0, &res);
+ }
+ if (val == 3) { /* HDCP14_EN_ENCRYPT */
+ arm_smccc_smc(0x82000013, 0, 0, 0, 0, 0, 0, 0, &res);
+ }
+ if (val == 4) { /* HDCP14_OFF */
+ arm_smccc_smc(0x82000014, 0, 0, 0, 0, 0, 0, 0, &res);
+ }
+ if (val == 5) { /* HDCP_MUX_22 */
+ arm_smccc_smc(0x82000015, 0, 0, 0, 0, 0, 0, 0, &res);
+ }
+ if (val == 6) { /* HDCP_MUX_14 */
+ arm_smccc_smc(0x82000016, 0, 0, 0, 0, 0, 0, 0, &res);
+ }
+ if (val == 7) { /* HDCP22_RESULT */
+ arm_smccc_smc(0x82000017, 0, 0, 0, 0, 0, 0, 0, &res);
+ return (unsigned int)((res.a0)&0xffffffff);
+ }
+ if (val == 0xa) { /* HDCP14_KEY_LSTORE */
+ arm_smccc_smc(0x8200001a, 0, 0, 0, 0, 0, 0, 0, &res);
+ return (unsigned int)((res.a0)&0xffffffff);
+ }
+ if (val == 0xb) { /* HDCP22_KEY_LSTORE */
+ arm_smccc_smc(0x8200001b, 0, 0, 0, 0, 0, 0, 0, &res);
+ return (unsigned int)((res.a0)&0xffffffff);
+ }
+ if (val == 0xc) { /* HDCP22_KEY_SET_DUK */
+ arm_smccc_smc(0x8200001c, 0, 0, 0, 0, 0, 0, 0, &res);
+ return (unsigned int)((res.a0)&0xffffffff);
+ }
+ if (val == 0xd) { /* HDCP22_SET_TOPO */
+ arm_smccc_smc(0x82000083, hdcp_topo_st, 0, 0, 0, 0, 0, 0, &res);
+ }
+ if (val == 0xe) { /* HDCP22_GET_TOPO */
+ arm_smccc_smc(0x82000084, 0, 0, 0, 0, 0, 0, 0, &res);
+ return (unsigned int)((res.a0)&0xffffffff);
+ }
+ return -1;
+}
+
+static void get_hdcp_bstatus(void)
+{
+ int ret1 = 0;
+ int ret2 = 0;
+
+ hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 0, 1);
+ hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ);
+ ret1 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0);
+ ret2 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_1);
+ hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1);
+ DRM_INFO("BSTATUS0 = 0x%x BSTATUS1 = 0x%x\n", ret1, ret2);
+}
+
+static void hdcp14_events_handle(unsigned long arg)
+{
+ struct am_hdmi_tx *am_hdmi = (struct am_hdmi_tx *)arg;
+ unsigned int bcaps_6_rp;
+ static unsigned int st_flag = -1;
+
+ bcaps_6_rp = !!(hdmitx_rd_reg(HDMITX_DWC_A_HDCPOBS3) & (1 << 6));
+ if (st_flag != hdmitx_rd_reg(HDMITX_DWC_A_APIINTSTAT)) {
+ st_flag = hdmitx_rd_reg(HDMITX_DWC_A_APIINTSTAT);
+ DRM_INFO("hdcp14: instat: 0x%x\n", st_flag);
+ }
+ if (st_flag & (1 << 7)) {
+ hdmitx_wr_reg(HDMITX_DWC_A_APIINTCLR, 1 << 7);
+ hdmitx_hdcp_opr(3);
+ get_hdcp_bstatus();
+ }
+
+ if (st_flag & (1 << 1)) {
+ hdmitx_wr_reg(HDMITX_DWC_A_APIINTCLR, (1 << 1));
+ hdmitx_wr_reg(HDMITX_DWC_A_KSVMEMCTRL, 0x1);
+ hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ);
+ if (hdmitx_rd_reg(HDMITX_DWC_A_KSVMEMCTRL) & (1 << 1))
+ ;//hdcp_ksv_sha1_calc(hdev); todo
+ else {
+ DRM_INFO("hdcptx14: KSV List memory access denied\n");
+ return;
+ }
+ hdmitx_wr_reg(HDMITX_DWC_A_KSVMEMCTRL, 0x4);
+ }
+
+ if (am_hdmi->hdcp_try_times)
+ mod_timer(&am_hdmi->hdcp_timer, jiffies + HZ / 100);
+ else
+ return;
+ am_hdmi->hdcp_try_times--;
+}
+
+static void hdcp14_start_timer(struct am_hdmi_tx *am_hdmi)
+{
+ static int init_flag;
+
+ if (!init_flag) {
+ init_flag = 1;
+ init_timer(&am_hdmi->hdcp_timer);
+ am_hdmi->hdcp_timer.data = (ulong)am_hdmi;
+ am_hdmi->hdcp_timer.function = hdcp14_events_handle;
+ am_hdmi->hdcp_timer.expires = jiffies + HZ / 100;
+ add_timer(&am_hdmi->hdcp_timer);
+ am_hdmi->hdcp_try_times = 500;
+ return;
+ }
+ am_hdmi->hdcp_try_times = 500;
+ am_hdmi->hdcp_timer.expires = jiffies + HZ / 100;
+ mod_timer(&am_hdmi->hdcp_timer, jiffies + HZ / 100);
+}
+
+static int am_hdcp14_enable(struct am_hdmi_tx *am_hdmi)
+{
+ am_hdmi->hdcp_mode = HDCP_MODE14;
+ hdmitx_ddc_hw_op(DDC_MUX_DDC);
+ hdmitx_hdcp_opr(6);
+ hdmitx_hdcp_opr(1);
+ hdcp14_start_timer(am_hdmi);
+ return 0;
+}
+
+static int am_hdcp14_disable(struct am_hdmi_tx *am_hdmi)
+{
+ hdmitx_hdcp_opr(4);
+ return 0;
+}
+
+static void set_pkf_duk_nonce(void)
+{
+ static int nonce_mode = 1; /* 1: use HW nonce 0: use SW nonce */
+
+ /* Configure duk/pkf */
+ hdmitx_hdcp_opr(0xc);
+ if (nonce_mode == 1)
+ hdmitx_wr_reg(HDMITX_TOP_SKP_CNTL_STAT, 0xf);
+ else {
+ hdmitx_wr_reg(HDMITX_TOP_SKP_CNTL_STAT, 0xe);
+/* Configure nonce[127:0].
+ * MSB must be written the last to assert nonce_vld signal.
+ */
+ hdmitx_wr_reg(HDMITX_TOP_NONCE_0, 0x32107654);
+ hdmitx_wr_reg(HDMITX_TOP_NONCE_1, 0xba98fedc);
+ hdmitx_wr_reg(HDMITX_TOP_NONCE_2, 0xcdef89ab);
+ hdmitx_wr_reg(HDMITX_TOP_NONCE_3, 0x45670123);
+ hdmitx_wr_reg(HDMITX_TOP_NONCE_0, 0x76543210);
+ hdmitx_wr_reg(HDMITX_TOP_NONCE_1, 0xfedcba98);
+ hdmitx_wr_reg(HDMITX_TOP_NONCE_2, 0x89abcdef);
+ hdmitx_wr_reg(HDMITX_TOP_NONCE_3, 0x01234567);
+ }
+ udelay(10);
+}
+
+static void am_sysfs_hdcp_event(struct drm_device *dev, unsigned int flag)
+{
+ char *envp1[2] = { "HDCP22=1", NULL };
+ char *envp0[2] = { "HDCP22=0", NULL };
+
+ DRM_INFO("generating hdcp22: %d\n event\n", flag);
+ if (flag)
+ kobject_uevent_env(&dev->primary->kdev->kobj,
+ KOBJ_CHANGE, envp1);
+ else
+ kobject_uevent_env(&dev->primary->kdev->kobj,
+ KOBJ_CHANGE, envp0);
+}
+
+static int am_hdcp22_enable(struct am_hdmi_tx *am_hdmi)
+{
+ am_hdmi->hdcp_mode = HDCP_MODE22;
+ hdmitx_ddc_hw_op(DDC_MUX_DDC);
+ hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, 1, 6, 1);
+ udelay(5);
+ hdmitx_set_reg_bits(HDMITX_DWC_HDCP22REG_CTRL, 3, 1, 2);
+ hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 1, 5, 1);
+ udelay(10);
+ hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 0, 5, 1);
+ udelay(10);
+ hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_MASK, 0);
+ hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_MUTE, 0);
+ set_pkf_duk_nonce();
+
+ /*uevent to open hdcp_tx22*/
+ am_sysfs_hdcp_event(am_hdmi->connector.dev, 1);
+ return 0;
+}
+
+static int am_hdcp22_disable(struct am_hdmi_tx *am_hdmi)
+{
+ hdmitx_hdcp_opr(6);
+ /*uevent to close hdcp_tx22*/
+ am_sysfs_hdcp_event(am_hdmi->connector.dev, 0);
+ return 0;
+}
+
+void am_hdcp_disable(struct am_hdmi_tx *am_hdmi)
+{
+ if (am_hdmi->hdcp_mode == HDCP_MODE22)
+ am_hdcp22_disable(am_hdmi);
+ else if (am_hdmi->hdcp_mode == HDCP_MODE14)
+ am_hdcp14_disable(am_hdmi);
+}
+EXPORT_SYMBOL(am_hdcp_disable);
+
+static int is_hdcp_hdmirx_supported(struct am_hdmi_tx *am_hdmi)
+{
+ unsigned int hdcp_rx_type = 0x1;
+ int st;
+
+ /*if tx has hdcp22, then check if rx support hdcp22*/
+ if (am_hdmi->hdcp_tx_type & 0x2) {
+ hdmitx_ddc_hw_op(DDC_MUX_DDC);
+ //mutex_lock(&am_hdmi->hdcp_mutex);
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, HDCP_SLAVE);
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, HDCP2_VERSION);
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 0);
+ mdelay(2);
+ if (hdmitx_rd_reg(HDMITX_DWC_IH_I2CM_STAT0) & (1 << 0)) {
+ st = 0;
+ DRM_INFO("ddc rd8b error 0x%02x 0x%02x\n",
+ HDCP_SLAVE, HDCP2_VERSION);
+ } else
+ st = 1;
+ hdmitx_wr_reg(HDMITX_DWC_IH_I2CM_STAT0, 0x7);
+ if (hdmitx_rd_reg(HDMITX_DWC_I2CM_DATAI) & (1 << 2))
+ hdcp_rx_type = 0x3;
+ //mutex_unlock(&am_hdmi->hdcp_mutex);
+ } else {
+ /*if tx has hdcp14 or no key, then rx support hdcp14 acquiescently*/
+ hdcp_rx_type = 0x1;
+ }
+ am_hdmi->hdcp_rx_type = hdcp_rx_type;
+
+ DRM_INFO("hdmirx support hdcp14: %d\n", hdcp_rx_type & 0x1);
+ DRM_INFO("hdmirx support hdcp22: %d\n", (hdcp_rx_type & 0x2) >> 1);
+ return hdcp_rx_type;
+}
+
+int am_hdcp14_auth(struct am_hdmi_tx *am_hdmi)
+{
+ return hdmitx_hdcp_opr(0x2);
+}
+
+int am_hdcp22_auth(struct am_hdmi_tx *am_hdmi)
+{
+ return hdmitx_hdcp_opr(0x7);
+}
+
+/*firstly,check the hdmirx key
+ *if hdmirx has hdcp22 key, start hdcp22. check auth status,
+ *if failure,then start hdcp14
+ *if hdmirx has hdcp14 key, start hdcp 14
+ */
+int am_hdcp_work(void *data)
+{
+ struct am_hdmi_tx *am_hdmi = data;
+ struct drm_connector_state *state = am_hdmi->connector.state;
+ int hdcp_fsm = 0;
+
+ is_hdcp_hdmirx_supported(am_hdmi);
+ if ((am_hdmi->hdcp_tx_type & 0x2) &&
+ (am_hdmi->hdcp_rx_type & 0x2))
+ hdcp_fsm = HDCP22_ENABLE;
+ else
+ hdcp_fsm = HDCP14_ENABLE;
+
+ while (hdcp_fsm) {
+ if (am_hdmi->hdcp_stop_flag)
+ hdcp_fsm = HDCP_QUIT;
+
+ switch (hdcp_fsm) {
+ case HDCP22_ENABLE:
+ am_hdcp22_enable(am_hdmi);
+ DRM_INFO("hdcp22 work after 10s\n");
+ /*this time is used to debug*/
+ msleep_interruptible(10000);
+ hdcp_fsm = HDCP22_AUTH;
+ break;
+ case HDCP22_AUTH:
+ if (am_hdcp22_auth(am_hdmi))
+ hdcp_fsm = HDCP22_SUCCESS;
+ else
+ hdcp_fsm = HDCP22_FAIL;
+ break;
+ case HDCP22_SUCCESS:
+ state->content_protection =
+ DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ DRM_DEBUG("hdcp22 is authenticated successfully\n");
+ hdcp_fsm = HDCP22_AUTH;
+ msleep_interruptible(200);
+ break;
+ case HDCP22_FAIL:
+ am_hdcp22_disable(am_hdmi);
+ state->content_protection =
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ DRM_INFO("hdcp22 failure and start hdcp14\n");
+ hdcp_fsm = HDCP14_ENABLE;
+ msleep_interruptible(2000);
+ break;
+ case HDCP14_ENABLE:
+ if ((am_hdmi->hdcp_tx_type & 0x1) == 0) {
+ hdcp_fsm = HDCP_QUIT;
+ break;
+ }
+ am_hdcp14_enable(am_hdmi);
+ msleep_interruptible(500);
+ hdcp_fsm = HDCP14_AUTH;
+ break;
+ case HDCP14_AUTH:
+ if (am_hdcp14_auth(am_hdmi))
+ hdcp_fsm = HDCP14_SUCCESS;
+ else
+ hdcp_fsm = HDCP14_FAIL;
+ break;
+ case HDCP14_SUCCESS:
+ state->content_protection =
+ DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ DRM_DEBUG("hdcp14 is authenticated successfully\n");
+ hdcp_fsm = HDCP14_AUTH;
+ msleep_interruptible(200);
+ break;
+ case HDCP14_FAIL:
+ am_hdcp14_disable(am_hdmi);
+ state->content_protection =
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ DRM_DEBUG("hdcp14 failure\n");
+ hdcp_fsm = HDCP_QUIT;
+ break;
+ case HDCP_QUIT:
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL(am_hdcp_work);
+
+int am_hdcp_init(struct am_hdmi_tx *am_hdmi)
+{
+ int ret;
+
+ ret = drm_connector_attach_content_protection_property(
+ &am_hdmi->connector);
+ if (ret)
+ return ret;
+ return 0;
+}
+EXPORT_SYMBOL(am_hdcp_init);
+
+/*bit0:hdcp14 bit 1:hdcp22*/
+int is_hdcp_hdmitx_supported(struct am_hdmi_tx *am_hdmi)
+{
+ unsigned int hdcp_tx_type = 0;
+
+ hdcp_tx_type |= hdmitx_hdcp_opr(0xa);
+ hdcp_tx_type |= ((hdmitx_hdcp_opr(0xb)) << 1);
+ am_hdmi->hdcp_tx_type = hdcp_tx_type;
+ DRM_INFO("hdmitx support hdcp14: %d\n", hdcp_tx_type & 0x1);
+ DRM_INFO("hdmitx support hdcp22: %d\n", (hdcp_tx_type & 0x2) >> 1);
+ return hdcp_tx_type;
+}
+EXPORT_SYMBOL(is_hdcp_hdmitx_supported);
/*
- * drivers/amlogic/drm/am_meson_hdcp.h
+ * drivers/amlogic/drm/meson_hdcp.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_hdmi.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drm_modeset_helper.h>
+#include <drm/drmP.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+
+#include <linux/component.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/kthread.h>
+#include <linux/device.h>
+
+#include <linux/workqueue.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
+#include "meson_hdmi.h"
+#include "meson_hdcp.h"
+
+#define DEVICE_NAME "amhdmitx"
+struct am_hdmi_tx am_hdmi_info;
+
+struct am_vout_mode {
+ char name[DRM_DISPLAY_MODE_LEN];
+ enum vmode_e mode;
+ int width, height, vrefresh;
+ unsigned int flags;
+};
+
+static struct am_vout_mode am_vout_modes[] = {
+ { "1080p60hz", VMODE_HDMI, 1920, 1080, 60, 0},
+ { "1080p30hz", VMODE_HDMI, 1920, 1080, 30, 0},
+ { "1080p50hz", VMODE_HDMI, 1920, 1080, 50, 0},
+ { "1080p25hz", VMODE_HDMI, 1920, 1080, 25, 0},
+ { "1080p24hz", VMODE_HDMI, 1920, 1080, 24, 0},
+ { "2160p30hz", VMODE_HDMI, 3840, 2160, 30, 0},
+ { "2160p60hz", VMODE_HDMI, 3840, 2160, 60, 0},
+ { "2160p50hz", VMODE_HDMI, 3840, 2160, 50, 0},
+ { "2160p25hz", VMODE_HDMI, 3840, 2160, 25, 0},
+ { "2160p24hz", VMODE_HDMI, 3840, 2160, 24, 0},
+ { "smpte30hz", VMODE_HDMI, 4096, 2160, 30, 0},
+ { "smpte60hz", VMODE_HDMI, 4096, 2160, 60, 0},
+ { "smpte50hz", VMODE_HDMI, 4096, 2160, 50, 0},
+ { "smpte25hz", VMODE_HDMI, 4096, 2160, 25, 0},
+ { "smpte24hz", VMODE_HDMI, 4096, 2160, 24, 0},
+ { "1080i60hz", VMODE_HDMI, 1920, 1080, 60, DRM_MODE_FLAG_INTERLACE},
+ { "1080i50hz", VMODE_HDMI, 1920, 1080, 50, DRM_MODE_FLAG_INTERLACE},
+ { "720p60hz", VMODE_HDMI, 1280, 720, 60, 0},
+ { "720p50hz", VMODE_HDMI, 1280, 720, 50, 0},
+ { "480p60hz", VMODE_HDMI, 720, 480, 60, 0},
+ { "480i60hz", VMODE_HDMI, 720, 480, 60, DRM_MODE_FLAG_INTERLACE},
+ { "576p50hz", VMODE_HDMI, 720, 576, 50, 0},
+ { "576i50hz", VMODE_HDMI, 720, 576, 50, DRM_MODE_FLAG_INTERLACE},
+ { "480p60hz", VMODE_HDMI, 720, 480, 60, 0},
+};
+
+char *am_meson_hdmi_get_voutmode(struct drm_display_mode *mode)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) {
+ if (am_vout_modes[i].width == mode->hdisplay &&
+ am_vout_modes[i].height == mode->vdisplay &&
+ am_vout_modes[i].vrefresh == mode->vrefresh &&
+ am_vout_modes[i].flags ==
+ (mode->flags & DRM_MODE_FLAG_INTERLACE))
+ return am_vout_modes[i].name;
+ }
+ return NULL;
+}
+
+static unsigned char default_edid[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x16, 0x01, 0x03, 0x6d, 0x32, 0x1c, 0x78,
+ 0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
+ 0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xd1, 0xc0,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a,
+ 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0xf4, 0x19, 0x11, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
+ 0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
+ 0x3d, 0x42, 0x44, 0x0f, 0x00, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
+ 0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x46,
+ 0x48, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x05,
+};
+
+int am_hdmi_tx_get_modes(struct drm_connector *connector)
+{
+ struct am_hdmi_tx *am_hdmi = to_am_hdmi(connector);
+ struct edid *edid;
+ int count = 0;
+
+ DRM_INFO("get_edid\n");
+ edid = drm_get_edid(connector, am_hdmi->ddc);
+
+ if (edid) {
+ drm_mode_connector_update_edid_property(connector, edid);
+ count = drm_add_edid_modes(connector, edid);
+ kfree(edid);
+ } else {
+ DRM_INFO("edid error and load default edid\n");
+ drm_mode_connector_update_edid_property(connector,
+ (struct edid *)default_edid);
+ count = drm_add_edid_modes(connector,
+ (struct edid *)default_edid);
+ }
+ return count;
+}
+
+enum drm_mode_status am_hdmi_tx_check_mode(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ if (am_meson_hdmi_get_voutmode(mode))
+ return MODE_OK;
+ else
+ return MODE_NOMODE;
+}
+
+static struct drm_encoder *am_hdmi_connector_best_encoder
+ (struct drm_connector *connector)
+{
+ struct am_hdmi_tx *am_hdmi = to_am_hdmi(connector);
+
+ return &am_hdmi->encoder;
+}
+
+static enum drm_connector_status am_hdmi_connector_detect
+ (struct drm_connector *connector, bool force)
+{
+ struct am_hdmi_tx *am_hdmi = to_am_hdmi(connector);
+
+ /* HPD rising */
+ if (am_hdmi->hpd_flag == 1) {
+ DRM_INFO("connector_status_connected\n");
+ return connector_status_connected;
+ }
+ /* HPD falling */
+ if (am_hdmi->hpd_flag == 2) {
+ DRM_INFO("connector_status_disconnected\n");
+ /*
+ *clean the hdmi info and output : todo
+ */
+ return connector_status_disconnected;
+ }
+ /*if the status is unknown, read GPIO*/
+ if (hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO)) {
+ DRM_INFO("connector_status_connected\n");
+ return connector_status_connected;
+ }
+ if (!(hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO))) {
+ DRM_INFO("connector_status_disconnected\n");
+ return connector_status_disconnected;
+ }
+
+ DRM_INFO("connector_status_unknown\n");
+ return connector_status_unknown;
+}
+
+static int am_hdmi_connector_set_property(struct drm_connector *connector,
+ struct drm_property *property, uint64_t val)
+{
+ struct am_hdmi_tx *am_hdmi = to_am_hdmi(connector);
+ struct drm_connector_state *state = am_hdmi->connector.state;
+
+ if (property == connector->content_protection_property) {
+ DRM_INFO("property:%s val: %lld\n", property->name, val);
+ if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+ DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
+ return -EINVAL;
+ }
+ state->content_protection = val;
+ }
+ /*other parperty todo*/
+ return 0;
+}
+
+static int am_hdmi_connector_atomic_get_property
+ (struct drm_connector *connector,
+ const struct drm_connector_state *state,
+ struct drm_property *property, uint64_t *val)
+{
+ if (property == connector->content_protection_property) {
+ DRM_INFO("get content_protection val: %d\n",
+ state->content_protection);
+ *val = state->content_protection;
+ } else {
+ DRM_DEBUG_ATOMIC("Unknown property %s\n", property->name);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void am_hdmi_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+}
+
+static const
+struct drm_connector_helper_funcs am_hdmi_connector_helper_funcs = {
+ .get_modes = am_hdmi_tx_get_modes,
+ .mode_valid = am_hdmi_tx_check_mode,
+ .best_encoder = am_hdmi_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs am_hdmi_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = am_hdmi_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = am_hdmi_connector_set_property,
+ .atomic_get_property = am_hdmi_connector_atomic_get_property,
+ .destroy = am_hdmi_connector_destroy,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+void am_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ const char attr1[16] = "rgb,8bit";
+ const char attr2[16] = "420,8bit";
+ int vic;
+ struct am_hdmi_tx *am_hdmi = &am_hdmi_info;
+
+ DRM_INFO("mode : %s, adjusted_mode : %s\n",
+ mode->name, adjusted_mode->name);
+ am_hdmi->hdmi_info.vic = drm_match_cea_mode(adjusted_mode);
+ vic = am_hdmi->hdmi_info.vic;
+ DRM_INFO("the hdmi mode vic : %d\n", am_hdmi->hdmi_info.vic);
+ /* Store the display mode for plugin/DPMS poweron events */
+ memcpy(&am_hdmi->previous_mode, adjusted_mode,
+ sizeof(am_hdmi->previous_mode));
+ if (vic == 96 || vic == 97 || vic == 101 || vic == 102 ||
+ vic == 106 || vic == 107)
+ setup_attr(attr2);
+ else
+ setup_attr(attr1);
+}
+
+void am_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+ enum vmode_e vmode = get_current_vmode();
+ struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
+ struct drm_connector_state *state = am_hdmi->connector.state;
+
+ if (vmode == VMODE_HDMI)
+ DRM_INFO("enable\n");
+ else
+ DRM_INFO("enable fail! vmode:%d\n", vmode);
+
+ vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode);
+ set_vout_vmode(vmode);
+ vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &vmode);
+ mdelay(1000);
+ if (state->content_protection ==
+ DRM_MODE_CONTENT_PROTECTION_DESIRED) {
+ if (am_hdmi->hdcp_tx_type) {
+ am_hdmi->hdcp_stop_flag = 0;
+ am_hdmi->hdcp_work = kthread_run(am_hdcp_work,
+ (void *)am_hdmi,
+ "kthread_hdcp_task");
+ } else {
+ DRM_INFO("hdmitx doesn't has hdcp key\n");
+ }
+ }
+}
+
+void am_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+ struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
+ struct drm_connector_state *state = am_hdmi->connector.state;
+
+ /*need to add hdmitx disable function ..todo*/
+ if (state->content_protection !=
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+ state->content_protection =
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ am_hdmi->hdcp_stop_flag = 1;
+ kthread_stop(am_hdmi->hdcp_work);
+ am_hdcp_disable(am_hdmi);
+ }
+}
+
+static int am_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
+
+ DRM_INFO("content_protection:%d\n", conn_state->content_protection);
+
+ if (conn_state->content_protection ==
+ DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+ kthread_stop(am_hdmi->hdcp_work);
+ am_hdcp_disable(am_hdmi);
+ conn_state->content_protection =
+ DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ }
+ return 0;
+}
+
+static const struct drm_encoder_helper_funcs
+ am_hdmi_encoder_helper_funcs = {
+ .mode_set = am_hdmi_encoder_mode_set,
+ .enable = am_hdmi_encoder_enable,
+ .disable = am_hdmi_encoder_disable,
+ .atomic_check = am_hdmi_encoder_atomic_check,
+};
+
+static const struct drm_encoder_funcs am_hdmi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static int am_hdmi_i2c_write(struct am_hdmi_tx *am_hdmi,
+ unsigned char *buf, unsigned int length)
+{
+ struct am_hdmi_i2c *i2c = am_hdmi->i2c;
+ int stat;
+
+ if (!i2c->is_regaddr) {
+ /* Use the first write byte as register address */
+ i2c->slave_reg = buf[0];
+ length--;
+ buf++;
+ i2c->is_regaddr = 1;
+ }
+
+ while (length--) {
+ reinit_completion(&i2c->cmp);
+
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_DATAO, *buf++);
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, i2c->slave_reg++);
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 4);
+
+ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 100);
+
+ stat = 1;
+ /* Check for error condition on the bus */
+ if (i2c->stat & 1)
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int am_hdmi_i2c_read(struct am_hdmi_tx *am_hdmi,
+ unsigned char *buf, unsigned int length)
+{
+ struct am_hdmi_i2c *i2c = am_hdmi->i2c;
+ int stat;
+
+ if (!i2c->is_regaddr) {
+ dev_dbg(am_hdmi->dev, "set read register address to 0\n");
+ i2c->slave_reg = 0x00;
+ i2c->is_regaddr = 1;
+ }
+
+ while (length--) {
+ reinit_completion(&i2c->cmp);
+
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, i2c->slave_reg++);
+ if (i2c->is_segment)
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 1);
+ else
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 0);
+
+ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 100);
+
+ stat = 1;
+
+ /* Check for error condition on the bus */
+ if (i2c->stat & 0x1)
+ return -EIO;
+
+ *buf++ = hdmitx_rd_reg(HDMITX_DWC_I2CM_DATAI);
+ }
+ i2c->is_segment = 0;
+
+ return 0;
+}
+
+static int am_hdmi_i2c_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct am_hdmi_tx *am_hdmi = i2c_get_adapdata(adap);
+ struct am_hdmi_i2c *i2c = am_hdmi->i2c;
+ u8 addr = msgs[0].addr;
+ int i, ret = 0;
+
+ dev_dbg(am_hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
+
+ for (i = 0; i < num; i++) {
+ if (msgs[i].len == 0) {
+ dev_dbg(am_hdmi->dev,
+ "unsupported transfer %d/%d, no data\n",
+ i + 1, num);
+ return -EOPNOTSUPP;
+ }
+ }
+
+ mutex_lock(&i2c->lock);
+
+ /* Clear the EDID interrupt flag and unmute the interrupt */
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_SOFTRSTZ, 0);
+ hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_I2CM_STAT0, 0);
+ /* TODO */
+ hdmitx_ddc_hw_op(DDC_MUX_DDC);
+
+ /* Set slave device address taken from the first I2C message */
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, addr);
+
+ /* Set slave device register address on transfer */
+ i2c->is_regaddr = 0;
+
+ /* Set segment pointer for I2C extended read mode operation */
+ i2c->is_segment = 0;
+
+ for (i = 0; i < num; i++) {
+ dev_dbg(am_hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
+ i + 1, num, msgs[i].len, msgs[i].flags);
+ if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) {
+ i2c->is_segment = 1;
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGADDR,
+ DDC_SEGMENT_ADDR);
+ hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGPTR, *msgs[i].buf);
+ } else {
+ if (msgs[i].flags & I2C_M_RD)
+ ret = am_hdmi_i2c_read(am_hdmi, msgs[i].buf,
+ msgs[i].len);
+ else
+ ret = am_hdmi_i2c_write(am_hdmi, msgs[i].buf,
+ msgs[i].len);
+ }
+ if (ret < 0)
+ break;
+ }
+
+ if (!ret)
+ ret = num;
+
+ mutex_unlock(&i2c->lock);
+
+ return ret;
+}
+
+static u32 am_hdmi_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm am_hdmi_algorithm = {
+ .master_xfer = am_hdmi_i2c_xfer,
+ .functionality = am_hdmi_i2c_func,
+};
+
+static struct i2c_adapter *am_hdmi_i2c_adapter(struct am_hdmi_tx *am_hdmi)
+{
+ struct i2c_adapter *adap;
+ struct am_hdmi_i2c *i2c;
+ int ret;
+
+ i2c = devm_kzalloc(am_hdmi->priv->dev, sizeof(*i2c), GFP_KERNEL);
+ if (!i2c) {
+ ret = -ENOMEM;
+ DRM_INFO("error : %d\n", ret);
+ }
+
+ mutex_init(&i2c->lock);
+ init_completion(&i2c->cmp);
+
+ adap = &i2c->adap;
+ adap->class = I2C_CLASS_DDC;
+ adap->owner = THIS_MODULE;
+ adap->dev.parent = am_hdmi->priv->dev;
+ adap->dev.of_node = am_hdmi->priv->dev->of_node;
+ adap->algo = &am_hdmi_algorithm;
+ strlcpy(adap->name, "Am HDMI", sizeof(adap->name));
+ i2c_set_adapdata(adap, am_hdmi);
+
+ ret = i2c_add_adapter(adap);
+ if (ret) {
+ DRM_INFO("cannot add %s I2C adapter\n",
+ adap->name);
+ devm_kfree(am_hdmi->priv->dev, i2c);
+ return ERR_PTR(ret);
+ }
+ am_hdmi->i2c = i2c;
+ DRM_INFO("registered %s I2C bus driver\n", adap->name);
+
+ return adap;
+
+}
+static irqreturn_t am_hdmi_hardirq(int irq, void *dev_id)
+{
+ unsigned int data32 = 0;
+ irqreturn_t ret = IRQ_NONE;
+
+ data32 = hdmitx_rd_reg(HDMITX_TOP_INTR_STAT);
+
+ /* check HPD status */
+ if ((data32 & (1 << 1)) && (data32 & (1 << 2))) {
+ if (hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO))
+ data32 &= ~(1 << 2);
+ else
+ data32 &= ~(1 << 1);
+ }
+
+ if ((data32 & (1 << 1)) || (data32 & (1 << 2))) {
+ ret = IRQ_WAKE_THREAD;
+ DRM_INFO("hotplug irq: %x\n", data32);
+ am_hdmi_info.hpd_flag = 0;
+ if (data32 & (1 << 1))
+ am_hdmi_info.hpd_flag = 1;/* HPD rising */
+ if (data32 & (1 << 2))
+ am_hdmi_info.hpd_flag = 2;/* HPD falling */
+ /* ack INTERNAL_INTR or else*/
+ hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, data32 | 0x7);
+ }
+ return ret;
+}
+
+static irqreturn_t am_hdmi_irq(int irq, void *dev_id)
+{
+ struct am_hdmi_tx *am_hdmi = dev_id;
+
+ drm_helper_hpd_irq_event(am_hdmi->connector.dev);
+ return IRQ_HANDLED;
+}
+
+static int amhdmitx_get_dt_info(struct am_hdmi_tx *am_hdmi)
+{
+ struct device_node *hdcp_node;
+ unsigned char *hdcp_status;
+ int ret = 0;
+
+ hdcp_node = of_find_node_by_path("/drm-amhdmitx");
+ if (hdcp_node) {
+ ret = of_property_read_string(hdcp_node, "hdcp",
+ (const char **)&(hdcp_status));
+ if (ret) {
+ DRM_INFO("not find hdcp_feature\n");
+ } else {
+ if (memcmp(hdcp_status, "okay", 4) == 0)
+ am_hdmi->hdcp_feature = 1;
+ else
+ am_hdmi->hdcp_feature = 0;
+ DRM_INFO("hdcp_feature: %d\n",
+ am_hdmi->hdcp_feature);
+ }
+ } else {
+ DRM_INFO("not find drm_amhdmitx\n");
+ }
+ return 0;
+}
+
+
+static const struct of_device_id am_meson_hdmi_dt_ids[] = {
+ { .compatible = "amlogic,drm-amhdmitx", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, am_meson_hdmi_dt_ids);
+
+static int am_meson_hdmi_bind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = data;
+ struct meson_drm *priv = drm->dev_private;
+ struct am_hdmi_tx *am_hdmi;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+ int ret;
+ int irq;
+
+ am_hdmi = devm_kzalloc(priv->dev, sizeof(*am_hdmi),
+ GFP_KERNEL);
+ if (!am_hdmi)
+ return -ENOMEM;
+ memcpy(&am_hdmi_info, am_hdmi, sizeof(*am_hdmi));
+ am_hdmi = &am_hdmi_info;
+
+ DRM_INFO("drm hdmitx init and version:%s\n", DRM_HDMITX_VER);
+ am_hdmi->priv = priv;
+ encoder = &am_hdmi->encoder;
+ connector = &am_hdmi->connector;
+
+ /* Connector */
+ am_hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
+ drm_connector_helper_add(connector,
+ &am_hdmi_connector_helper_funcs);
+
+ ret = drm_connector_init(drm, connector, &am_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+ if (ret) {
+ dev_err(priv->dev, "Failed to init hdmi tx connector\n");
+ return ret;
+ }
+
+ connector->interlace_allowed = 1;
+
+ /* Encoder */
+ drm_encoder_helper_add(encoder, &am_hdmi_encoder_helper_funcs);
+
+ ret = drm_encoder_init(drm, encoder, &am_hdmi_encoder_funcs,
+ DRM_MODE_ENCODER_TVDAC, "am_hdmi_encoder");
+ if (ret) {
+ dev_err(priv->dev, "Failed to init hdmi encoder\n");
+ return ret;
+ }
+
+ encoder->possible_crtcs = BIT(0);
+
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ /*DDC init*/
+ am_hdmi->ddc = am_hdmi_i2c_adapter(am_hdmi);
+ DRM_INFO("hdmitx:DDC init complete\n");
+ /*Hotplug irq*/
+ irq = platform_get_irq(pdev, 0);
+ DRM_INFO("hdmi connector irq:%d\n", irq);
+ if (irq < 0)
+ return irq;
+ hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, 0x7);
+ ret = devm_request_threaded_irq(am_hdmi->priv->dev, irq,
+ am_hdmi_hardirq, am_hdmi_irq, IRQF_SHARED,
+ dev_name(am_hdmi->priv->dev), am_hdmi);
+ if (ret) {
+ dev_err(am_hdmi->priv->dev,
+ "failed to request hdmi irq: %d\n", ret);
+ }
+
+ /*HDCP INIT*/
+ amhdmitx_get_dt_info(am_hdmi);
+ if (am_hdmi->hdcp_feature) {
+ if (is_hdcp_hdmitx_supported(am_hdmi)) {
+ ret = am_hdcp_init(am_hdmi);
+ if (ret)
+ DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
+ }
+ }
+ return 0;
+}
+
+static void am_meson_hdmi_unbind(struct device *dev,
+ struct device *master, void *data)
+{
+ am_hdmi_info.connector.funcs->destroy(&am_hdmi_info.connector);
+ am_hdmi_info.encoder.funcs->destroy(&am_hdmi_info.encoder);
+}
+
+static const struct component_ops am_meson_hdmi_ops = {
+ .bind = am_meson_hdmi_bind,
+ .unbind = am_meson_hdmi_unbind,
+};
+
+static int am_meson_hdmi_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &am_meson_hdmi_ops);
+}
+
+static int am_meson_hdmi_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &am_meson_hdmi_ops);
+ return 0;
+}
+
+static struct platform_driver am_meson_hdmi_pltfm_driver = {
+ .probe = am_meson_hdmi_probe,
+ .remove = am_meson_hdmi_remove,
+ .driver = {
+ .name = "meson-amhdmitx",
+ .of_match_table = am_meson_hdmi_dt_ids,
+ },
+};
+
+module_platform_driver(am_meson_hdmi_pltfm_driver);
+
+MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>");
+MODULE_DESCRIPTION("Amlogic Meson Drm HDMI driver");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_hdmi.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AM_MESON_HDMI_H
+#define __AM_MESON_HDMI_H
+
+#include "meson_drv.h"
+#define DDC_SEGMENT_ADDR 0x30
+#define VIC_MAX_NUM 512
+#define DRM_HDMITX_VER "20180705"
+
+struct am_hdmi_data {
+ unsigned int vic;
+ u8 sink_is_hdmi;
+ u8 sink_has_audio;
+ unsigned int colorimetry;
+ unsigned int cd; /* cd8, cd10 or cd12 */
+ unsigned int cs; /* rgb, y444, y422, y420 */
+ unsigned int cr; /* limit, full */
+ struct hdmi_pwr_ctl *pwr_ctl;
+ unsigned int aud_output_ch;
+ unsigned int tx_aud_cfg; /* 0, off; 1, on */
+ unsigned int tmds_clk_div40;
+ unsigned int VIC[VIC_MAX_NUM];
+};
+
+struct am_hdmi_i2c {
+ struct i2c_adapter adap;
+ struct mutex lock;
+ struct completion cmp;
+ u8 ddc_addr;
+ u8 segment_addr;
+ u8 slave_reg;
+ u8 stat;
+ u8 is_regaddr;
+ u8 is_segment;
+};
+
+struct am_hdmi_tx {
+ struct device *dev;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+ struct meson_drm *priv;
+ int irq;
+ unsigned int input_color_format;
+ unsigned int output_color_format;
+ unsigned int color_depth;
+ struct drm_display_mode previous_mode;
+ struct am_hdmi_data hdmi_info;
+ struct am_hdmi_i2c *i2c;
+ struct i2c_adapter *ddc;
+ struct workqueue_struct *hdmi_wq;
+ const char *hpd_pin;
+ const char *ddc_pin;
+ unsigned int hpd_flag;/*0:none 1:up 2:down*/
+ struct mutex hdcp_mutex;
+ unsigned int hdcp_feature;
+ unsigned int hdcp_tx_type;/*bit0:hdcp14 bit 1:hdcp22*/
+ unsigned int hdcp_rx_type;/*bit0:hdcp14 bit 1:hdcp22*/
+ struct timer_list hdcp_timer;
+ unsigned int hdcp_mode;
+ unsigned int hdcp_state;
+ unsigned int hdcp_stop_flag;/*turn off hdcp state machine*/
+ unsigned int hdcp_try_times;
+ struct task_struct *hdcp_work;
+};
+
+#define to_am_hdmi(x) container_of(x, struct am_hdmi_tx, x)
+
+#define HDMITX_REG_IDX 6
+#define HDMITX_SEC_REG_IDX 7
+#define BASE_REG_OFFSET 24
+
+#define HDMITX_SEC_REG_ADDR(reg) \
+ ((HDMITX_SEC_REG_IDX << BASE_REG_OFFSET) + ((reg) << 2))
+#define HDMITX_REG_ADDR(reg) \
+ ((HDMITX_REG_IDX << BASE_REG_OFFSET) + ((reg) << 2))
+
+/* TOP-level wrapper registers addresses
+ * bit24: 1 means secure access
+ * bit28: 1 means DWC, 0 means TOP
+ */
+#define SEC_OFFSET (0x1UL << 24)
+#define TOP_OFFSET_MASK (0x0UL << 24)
+#define TOP_SEC_OFFSET_MASK ((TOP_OFFSET_MASK) | (SEC_OFFSET))
+#define DWC_OFFSET_MASK (0x10UL << 24)
+#define DWC_SEC_OFFSET_MASK ((DWC_OFFSET_MASK) | (SEC_OFFSET))
+
+/* Bit 7 RW Reserved. Default 1.
+ * Bit 6 RW Reserved. Default 1.
+ * Bit 5 RW Reserved. Default 1.
+ * Bit 4 RW sw_reset_phyif: PHY interface. 1=Apply reset; 0=Release from reset.
+ * Default 1.
+ * Bit 3 RW sw_reset_intr: interrupt module. 1=Apply reset;
+ * 0=Release from reset. Default 1.
+ * Bit 2 RW sw_reset_mem: KSV/REVOC mem. 1=Apply reset; 0=Release from reset.
+ * Default 1.
+ * Bit 1 RW sw_reset_rnd: random number interface to HDCP. 1=Apply reset;
+ * 0=Release from reset. Default 1.
+ * Bit 0 RW sw_reset_core: connects to IP's ~irstz. 1=Apply reset;
+ * 0=Release from reset. Default 1.
+ */
+#define HDMITX_TOP_SW_RESET (TOP_OFFSET_MASK + 0x000)
+
+/* Bit 12 RW i2s_ws_inv:1=Invert i2s_ws; 0=No invert. Default 0. */
+/* Bit 11 RW i2s_clk_inv: 1=Invert i2s_clk; 0=No invert. Default 0. */
+/* Bit 10 RW spdif_clk_inv: 1=Invert spdif_clk; 0=No invert. Default 0. */
+/* Bit 9 RW tmds_clk_inv: 1=Invert tmds_clk; 0=No invert. Default 0. */
+/* Bit 8 RW pixel_clk_inv: 1=Invert pixel_clk; 0=No invert. Default 0. */
+/* Bit 4 RW cec_clk_en: 1=enable cec_clk; 0=disable. Default 0. */
+/* Bit 3 RW i2s_clk_en: 1=enable i2s_clk; 0=disable. Default 0. */
+/* Bit 2 RW spdif_clk_en: 1=enable spdif_clk; 0=disable. Default 0. */
+/* Bit 1 RW tmds_clk_en: 1=enable tmds_clk; 0=disable. Default 0. */
+/* Bit 0 RW pixel_clk_en: 1=enable pixel_clk; 0=disable. Default 0. */
+#define HDMITX_TOP_CLK_CNTL (TOP_OFFSET_MASK + 0x001)
+
+/* Bit 11: 0 RW hpd_valid_width: filter out width <= M*1024. Default 0. */
+/* Bit 15:12 RW hpd_glitch_width: filter out glitch <= N. Default 0. */
+#define HDMITX_TOP_HPD_FILTER (TOP_OFFSET_MASK + 0x002)
+
+/* intr_maskn: MASK_N, one bit per interrupt source.
+ * 1=Enable interrupt source; 0=Disable interrupt source. Default 0.
+ * [ 4] hdcp22_rndnum_err
+ * [ 3] nonce_rfrsh_rise
+ * [ 2] hpd_fall_intr
+ * [ 1] hpd_rise_intr
+ * [ 0] core_intr
+ */
+#define HDMITX_TOP_INTR_MASKN (TOP_OFFSET_MASK + 0x003)
+
+/* Bit 30: 0 RW intr_stat: For each bit, write 1 to manually set the interrupt
+ * bit, read back the interrupt status.
+ * Bit 31 R IP interrupt status
+ * Bit 2 RW hpd_fall
+ * Bit 1 RW hpd_rise
+ * Bit 0 RW IP interrupt
+ */
+#define HDMITX_TOP_INTR_STAT (TOP_OFFSET_MASK + 0x004)
+
+/* [4] hdcp22_rndnum_err */
+/* [3] nonce_rfrsh_rise */
+/* [2] hpd_fall */
+/* [1] hpd_rise */
+/* [0] core_intr_rise */
+#define HDMITX_TOP_INTR_STAT_CLR (TOP_OFFSET_MASK + 0x005)
+
+/* Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data;
+ * 3'b010=Output PRBS data; 3'b100=Output shift pattern. Default 0.
+ * Bit 11: 9 RW shift_pttn_repeat: 0=New pattern every clk cycle; 1=New pattern
+ * every 2 clk cycles; ...; 7=New pattern every 8 clk cycles. Default 0.
+ * Bit 8 RW shift_pttn_en: 1= Eanble shift pattern generator; 0=Disable.
+ * Default 0.
+ * Bit 4: 3 RW prbs_pttn_mode: 0=PRBS11; 1=PRBS15; 2=PRBS7; 3=PRBS31. Default 0.
+ * Bit 2: 1 RW prbs_pttn_width: 0=idle; 1=output 8-bit pattern;
+ * 2=Output 1-bit pattern; 3=output 10-bit pattern. Default 0.
+ * Bit 0 RW prbs_pttn_en: 1=Enable PRBS generator; 0=Disable. Default 0.
+ */
+#define HDMITX_TOP_BIST_CNTL (TOP_OFFSET_MASK + 0x006)
+
+/* Bit 29:20 RW shift_pttn_data[59:50]. Default 0. */
+/* Bit 19:10 RW shift_pttn_data[69:60]. Default 0. */
+/* Bit 9: 0 RW shift_pttn_data[79:70]. Default 0. */
+#define HDMITX_TOP_SHIFT_PTTN_012 (TOP_OFFSET_MASK + 0x007)
+
+/* Bit 29:20 RW shift_pttn_data[29:20]. Default 0. */
+/* Bit 19:10 RW shift_pttn_data[39:30]. Default 0. */
+/* Bit 9: 0 RW shift_pttn_data[49:40]. Default 0. */
+#define HDMITX_TOP_SHIFT_PTTN_345 (TOP_OFFSET_MASK + 0x008)
+
+/* Bit 19:10 RW shift_pttn_data[ 9: 0]. Default 0. */
+/* Bit 9: 0 RW shift_pttn_data[19:10]. Default 0. */
+#define HDMITX_TOP_SHIFT_PTTN_67 (TOP_OFFSET_MASK + 0x009)
+
+/* Bit 25:16 RW tmds_clk_pttn[19:10]. Default 0. */
+/* Bit 9: 0 RW tmds_clk_pttn[ 9: 0]. Default 0. */
+#define HDMITX_TOP_TMDS_CLK_PTTN_01 (TOP_OFFSET_MASK + 0x00A)
+
+/* Bit 25:16 RW tmds_clk_pttn[39:30]. Default 0. */
+/* Bit 9: 0 RW tmds_clk_pttn[29:20]. Default 0. */
+#define HDMITX_TOP_TMDS_CLK_PTTN_23 (TOP_OFFSET_MASK + 0x00B)
+
+/* Bit 1 RW shift_tmds_clk_pttn:1=Enable shifting clk pattern,
+ * used when TMDS CLK rate = TMDS character rate /4. Default 0.
+ * Bit 0 R Reserved. Default 0.
+ */
+/* [ 1] shift_tmds_clk_pttn */
+/* [ 0] load_tmds_clk_pttn */
+#define HDMITX_TOP_TMDS_CLK_PTTN_CNTL (TOP_OFFSET_MASK + 0x00C)
+
+/* Bit 0 RW revocmem_wr_fail: Read back 1 to indicate Host write REVOC MEM
+ * failure, write 1 to clear the failure flag. Default 0.
+ */
+#define HDMITX_TOP_REVOCMEM_STAT (TOP_OFFSET_MASK + 0x00D)
+
+/* Bit 0 R filtered HPD status. */
+#define HDMITX_TOP_STAT0 (TOP_OFFSET_MASK + 0x00E)
+#define HDMITX_TOP_SKP_CNTL_STAT (TOP_SEC_OFFSET_MASK + 0x010)
+#define HDMITX_TOP_NONCE_0 (TOP_SEC_OFFSET_MASK + 0x011)
+#define HDMITX_TOP_NONCE_1 (TOP_SEC_OFFSET_MASK + 0x012)
+#define HDMITX_TOP_NONCE_2 (TOP_SEC_OFFSET_MASK + 0x013)
+#define HDMITX_TOP_NONCE_3 (TOP_SEC_OFFSET_MASK + 0x014)
+#define HDMITX_TOP_PKF_0 (TOP_SEC_OFFSET_MASK + 0x015)
+#define HDMITX_TOP_PKF_1 (TOP_SEC_OFFSET_MASK + 0x016)
+#define HDMITX_TOP_PKF_2 (TOP_SEC_OFFSET_MASK + 0x017)
+#define HDMITX_TOP_PKF_3 (TOP_SEC_OFFSET_MASK + 0x018)
+#define HDMITX_TOP_DUK_0 (TOP_SEC_OFFSET_MASK + 0x019)
+#define HDMITX_TOP_DUK_1 (TOP_SEC_OFFSET_MASK + 0x01A)
+#define HDMITX_TOP_DUK_2 (TOP_SEC_OFFSET_MASK + 0x01B)
+#define HDMITX_TOP_DUK_3 (TOP_SEC_OFFSET_MASK + 0x01C)
+/* [26:24] infilter_ddc_intern_clk_divide */
+/* [23:16] infilter_ddc_sample_clk_divide */
+/* [10: 8] infilter_cec_intern_clk_divide */
+/* [ 7: 0] infilter_cec_sample_clk_divide */
+#define HDMITX_TOP_INFILTER (TOP_OFFSET_MASK + 0x01D)
+#define HDMITX_TOP_NSEC_SCRATCH (TOP_OFFSET_MASK + 0x01E)
+#define HDMITX_TOP_SEC_SCRATCH (TOP_SEC_OFFSET_MASK + 0x01F)
+
+#define HDMITX_TOP_DONT_TOUCH0 (TOP_OFFSET_MASK + 0x0FE)
+#define HDMITX_TOP_DONT_TOUCH1 (TOP_OFFSET_MASK + 0x0FF)
+
+/* DWC_HDMI_TX Controller registers addresses */
+
+/* Identification Registers */
+#define HDMITX_DWC_DESIGN_ID (DWC_OFFSET_MASK + 0x0000)
+#define HDMITX_DWC_REVISION_ID (DWC_OFFSET_MASK + 0x0001)
+#define HDMITX_DWC_PRODUCT_ID0 (DWC_OFFSET_MASK + 0x0002)
+#define HDMITX_DWC_PRODUCT_ID1 (DWC_OFFSET_MASK + 0x0003)
+#define HDMITX_DWC_CONFIG0_ID (DWC_OFFSET_MASK + 0x0004)
+#define HDMITX_DWC_CONFIG1_ID (DWC_OFFSET_MASK + 0x0005)
+#define HDMITX_DWC_CONFIG2_ID (DWC_OFFSET_MASK + 0x0006)
+#define HDMITX_DWC_CONFIG3_ID (DWC_OFFSET_MASK + 0x0007)
+
+/* Interrupt Registers */
+#define HDMITX_DWC_IH_FC_STAT0 (DWC_OFFSET_MASK + 0x0100)
+#define HDMITX_DWC_IH_FC_STAT1 (DWC_OFFSET_MASK + 0x0101)
+#define HDMITX_DWC_IH_FC_STAT2 (DWC_OFFSET_MASK + 0x0102)
+#define HDMITX_DWC_IH_AS_STAT0 (DWC_OFFSET_MASK + 0x0103)
+#define HDMITX_DWC_IH_PHY_STAT0 (DWC_OFFSET_MASK + 0x0104)
+#define HDMITX_DWC_IH_I2CM_STAT0 (DWC_OFFSET_MASK + 0x0105)
+#define HDMITX_DWC_IH_CEC_STAT0 (DWC_OFFSET_MASK + 0x0106)
+#define HDMITX_DWC_IH_VP_STAT0 (DWC_OFFSET_MASK + 0x0107)
+#define HDMITX_DWC_IH_I2CMPHY_STAT0 (DWC_OFFSET_MASK + 0x0108)
+#define HDMITX_DWC_IH_DECODE (DWC_OFFSET_MASK + 0x0170)
+/* [ 7] mute_AUDI */
+/* [ 6] mute_ACP */
+/* [ 5] mute_HBR */
+/* [ 4] mute_MAS */
+/* [ 3] mute_NVBI */
+/* [ 2] mute_AUDS */
+/* [ 1] mute_ACR */
+/* [ 0] mute_NULL */
+#define HDMITX_DWC_IH_MUTE_FC_STAT0 (DWC_OFFSET_MASK + 0x0180)
+/* [ 7] mute_GMD */
+/* [ 6] mute_ISRC1 */
+/* [ 5] mute_ISRC2 */
+/* [ 4] mute_VSD */
+/* [ 3] mute_SPD */
+/* [ 2] mute_AMP */
+/* [ 1] mute_AVI */
+/* [ 0] mute_GCP */
+#define HDMITX_DWC_IH_MUTE_FC_STAT1 (DWC_OFFSET_MASK + 0x0181)
+/* [ 1] mute_LowPriority_fifo_full */
+/* [ 0] mute_HighPriority_fifo_full */
+#define HDMITX_DWC_IH_MUTE_FC_STAT2 (DWC_OFFSET_MASK + 0x0182)
+/* [ 4] mute_aud_fifo_underrun */
+/* [ 3] mute_aud_fifo_overrun */
+/* [ 2] mute_aud_fifo_empty_thr. oififoemptythr tied to 0. */
+/* [ 1] mute_aud_fifo_empty */
+/* [ 0] mute_aud_fifo_full */
+#define HDMITX_DWC_IH_MUTE_AS_STAT0 (DWC_OFFSET_MASK + 0x0183)
+#define HDMITX_DWC_IH_MUTE_PHY_STAT0 (DWC_OFFSET_MASK + 0x0184)
+/* [ 2] mute_scdc_readreq */
+/* [ 1] mute_edid_i2c_master_done */
+/* [ 0] mute_edid_i2c_master_error */
+#define HDMITX_DWC_IH_MUTE_I2CM_STAT0 (DWC_OFFSET_MASK + 0x0185)
+/* [ 6] cec_wakeup */
+/* [ 5] cec_error_follower */
+/* [ 4] cec_error_initiator */
+/* [ 3] cec_arb_lost */
+/* [ 2] cec_nack */
+/* [ 1] cec_eom */
+/* [ 0] cec_done */
+#define HDMITX_DWC_IH_MUTE_CEC_STAT0 (DWC_OFFSET_MASK + 0x0186)
+#define HDMITX_DWC_IH_MUTE_VP_STAT0 (DWC_OFFSET_MASK + 0x0187)
+#define HDMITX_DWC_IH_MUTE_I2CMPHY_STAT0 (DWC_OFFSET_MASK + 0x0188)
+/* [ 1] mute_wakeup_interrupt */
+/* [ 0] mute_all_interrupt */
+#define HDMITX_DWC_IH_MUTE (DWC_OFFSET_MASK + 0x01FF)
+
+/* Video Sampler Registers */
+/* [ 7] internal_de_generator */
+/* [4:0] video_mapping */
+#define HDMITX_DWC_TX_INVID0 (DWC_OFFSET_MASK + 0x0200)
+/* [ 2] bcbdata_stuffing */
+/* [ 1] rcrdata_stuffing */
+/* [ 0] gydata_stuffing */
+#define HDMITX_DWC_TX_INSTUFFING (DWC_OFFSET_MASK + 0x0201)
+#define HDMITX_DWC_TX_GYDATA0 (DWC_OFFSET_MASK + 0x0202)
+#define HDMITX_DWC_TX_GYDATA1 (DWC_OFFSET_MASK + 0x0203)
+#define HDMITX_DWC_TX_RCRDATA0 (DWC_OFFSET_MASK + 0x0204)
+#define HDMITX_DWC_TX_RCRDATA1 (DWC_OFFSET_MASK + 0x0205)
+#define HDMITX_DWC_TX_BCBDATA0 (DWC_OFFSET_MASK + 0x0206)
+#define HDMITX_DWC_TX_BCBDATA1 (DWC_OFFSET_MASK + 0x0207)
+
+/* Video Packetizer Registers */
+#define HDMITX_DWC_VP_STATUS (DWC_OFFSET_MASK + 0x0800)
+/* [3:0] desired_pr_factor */
+#define HDMITX_DWC_VP_PR_CD (DWC_OFFSET_MASK + 0x0801)
+/* [ 5] default_phase */
+/* [ 2] ycc422_stuffing */
+/* [ 1] pp_stuffing */
+/* [ 0] pr_stuffing */
+#define HDMITX_DWC_VP_STUFF (DWC_OFFSET_MASK + 0x0802)
+#define HDMITX_DWC_VP_REMAP (DWC_OFFSET_MASK + 0x0803)
+#define HDMITX_DWC_VP_CONF (DWC_OFFSET_MASK + 0x0804)
+/* [ 7] mask_int_full_prpt */
+/* [ 6] mask_int_empty_prpt */
+/* [ 5] mask_int_full_ppack */
+/* [ 4] mask_int_empty_ppack */
+/* [ 3] mask_int_full_remap */
+/* [ 2] mask_int_empty_remap */
+/* [ 1] mask_int_full_byp */
+/* [ 0] mask_int_empty_byp */
+#define HDMITX_DWC_VP_MASK (DWC_OFFSET_MASK + 0x0807)
+
+/* Frmae Composer Registers */
+/* [ 7] HDCP_keepout */
+/* [ 6] vs_in_pol: 0=active low; 1=active high. */
+/* [ 5] hs_in_pol: 0=active low; 1=active high. */
+/* [ 4] de_in_pol: 0=active low; 1=active high. */
+/* [ 3] dvi_modez: 0=dvi; 1=hdmi. */
+/* [ 1] r_v_blank_in_osc */
+/* [ 0] in_I_P: 0=progressive; 1=interlaced. */
+#define HDMITX_DWC_FC_INVIDCONF (DWC_OFFSET_MASK + 0x1000)
+/* [7:0] H_in_active[7:0] */
+#define HDMITX_DWC_FC_INHACTV0 (DWC_OFFSET_MASK + 0x1001)
+/* [5:0] H_in_active[13:8] */
+#define HDMITX_DWC_FC_INHACTV1 (DWC_OFFSET_MASK + 0x1002)
+/* [7:0] H_in_blank[7:0] */
+#define HDMITX_DWC_FC_INHBLANK0 (DWC_OFFSET_MASK + 0x1003)
+/* [4:0] H_in_blank[12:8] */
+#define HDMITX_DWC_FC_INHBLANK1 (DWC_OFFSET_MASK + 0x1004)
+/* [7:0] V_in_active[7:0] */
+#define HDMITX_DWC_FC_INVACTV0 (DWC_OFFSET_MASK + 0x1005)
+/* [4:0] V_in_active[12:8] */
+#define HDMITX_DWC_FC_INVACTV1 (DWC_OFFSET_MASK + 0x1006)
+/* [7:0] V_in_blank */
+#define HDMITX_DWC_FC_INVBLANK (DWC_OFFSET_MASK + 0x1007)
+/* [7:0] H_in_delay[7:0] */
+#define HDMITX_DWC_FC_HSYNCINDELAY0 (DWC_OFFSET_MASK + 0x1008)
+/* [4:0] H_in_delay[12:8] */
+#define HDMITX_DWC_FC_HSYNCINDELAY1 (DWC_OFFSET_MASK + 0x1009)
+/* [7:0] H_in_width[7:0] */
+#define HDMITX_DWC_FC_HSYNCINWIDTH0 (DWC_OFFSET_MASK + 0x100A)
+/* [1:0] H_in_width[9:8] */
+#define HDMITX_DWC_FC_HSYNCINWIDTH1 (DWC_OFFSET_MASK + 0x100B)
+/* [7:0] V_in_delay */
+#define HDMITX_DWC_FC_VSYNCINDELAY (DWC_OFFSET_MASK + 0x100C)
+/* [5:0] V_in_width */
+#define HDMITX_DWC_FC_VSYNCINWIDTH (DWC_OFFSET_MASK + 0x100D)
+#define HDMITX_DWC_FC_INFREQ0 (DWC_OFFSET_MASK + 0x100E)
+#define HDMITX_DWC_FC_INFREQ1 (DWC_OFFSET_MASK + 0x100F)
+#define HDMITX_DWC_FC_INFREQ2 (DWC_OFFSET_MASK + 0x1010)
+#define HDMITX_DWC_FC_CTRLDUR (DWC_OFFSET_MASK + 0x1011)
+#define HDMITX_DWC_FC_EXCTRLDUR (DWC_OFFSET_MASK + 0x1012)
+#define HDMITX_DWC_FC_EXCTRLSPAC (DWC_OFFSET_MASK + 0x1013)
+#define HDMITX_DWC_FC_CH0PREAM (DWC_OFFSET_MASK + 0x1014)
+#define HDMITX_DWC_FC_CH1PREAM (DWC_OFFSET_MASK + 0x1015)
+#define HDMITX_DWC_FC_CH2PREAM (DWC_OFFSET_MASK + 0x1016)
+/* [3:2] YQ */
+/* [1:0] CN */
+#define HDMITX_DWC_FC_AVICONF3 (DWC_OFFSET_MASK + 0x1017)
+/* [ 2] default_phase */
+/* [ 1] set_avmute */
+/* [ 0] clear_avmute */
+#define HDMITX_DWC_FC_GCP (DWC_OFFSET_MASK + 0x1018)
+/* [ 7] rgb_ycc_indication[2] */
+/* [ 6] active_format_present */
+/* [5:4] scan_information */
+/* [3:2] bar_information */
+/* [1:0] rgb_ycc_indication[1:0] */
+#define HDMITX_DWC_FC_AVICONF0 (DWC_OFFSET_MASK + 0x1019)
+/* [7:6] colorimetry */
+/* [5:4] picture_aspect_ratio */
+/* [3:0] active_aspect_ratio */
+#define HDMITX_DWC_FC_AVICONF1 (DWC_OFFSET_MASK + 0x101A)
+/* [ 7] IT_content */
+/* [6:4] extended_colorimetry */
+/* [3:2] quantization_range */
+/* [1:0] non_uniform_picture_scaling */
+#define HDMITX_DWC_FC_AVICONF2 (DWC_OFFSET_MASK + 0x101B)
+#define HDMITX_DWC_FC_AVIVID (DWC_OFFSET_MASK + 0x101C)
+#define HDMITX_DWC_FC_AVIETB0 (DWC_OFFSET_MASK + 0x101D)
+#define HDMITX_DWC_FC_AVIETB1 (DWC_OFFSET_MASK + 0x101E)
+#define HDMITX_DWC_FC_AVISBB0 (DWC_OFFSET_MASK + 0x101F)
+#define HDMITX_DWC_FC_AVISBB1 (DWC_OFFSET_MASK + 0x1020)
+#define HDMITX_DWC_FC_AVIELB0 (DWC_OFFSET_MASK + 0x1021)
+#define HDMITX_DWC_FC_AVIELB1 (DWC_OFFSET_MASK + 0x1022)
+#define HDMITX_DWC_FC_AVISRB0 (DWC_OFFSET_MASK + 0x1023)
+#define HDMITX_DWC_FC_AVISRB1 (DWC_OFFSET_MASK + 0x1024)
+/* [3:0] CT: coding type */
+#define HDMITX_DWC_FC_AUDICONF0 (DWC_OFFSET_MASK + 0x1025)
+/* [5:4] SS: sampling size */
+/* [2:0] SF: sampling frequency */
+#define HDMITX_DWC_FC_AUDICONF1 (DWC_OFFSET_MASK + 0x1026)
+/* CA: channel allocation */
+#define HDMITX_DWC_FC_AUDICONF2 (DWC_OFFSET_MASK + 0x1027)
+/* [6:5] LFEPBL: LFE playback info */
+/* [ 4] DM_INH: down mix enable */
+/* [3:0] LSv: Level shift value */
+#define HDMITX_DWC_FC_AUDICONF3 (DWC_OFFSET_MASK + 0x1028)
+#define HDMITX_DWC_FC_VSDIEEEID0 (DWC_OFFSET_MASK + 0x1029)
+#define HDMITX_DWC_FC_VSDSIZE (DWC_OFFSET_MASK + 0x102A)
+#define HDMITX_DWC_FC_VSDIEEEID1 (DWC_OFFSET_MASK + 0x1030)
+#define HDMITX_DWC_FC_VSDIEEEID2 (DWC_OFFSET_MASK + 0x1031)
+#define HDMITX_DWC_FC_VSDPAYLOAD0 (DWC_OFFSET_MASK + 0x1032)
+#define HDMITX_DWC_FC_VSDPAYLOAD1 (DWC_OFFSET_MASK + 0x1033)
+#define HDMITX_DWC_FC_VSDPAYLOAD2 (DWC_OFFSET_MASK + 0x1034)
+#define HDMITX_DWC_FC_VSDPAYLOAD3 (DWC_OFFSET_MASK + 0x1035)
+#define HDMITX_DWC_FC_VSDPAYLOAD4 (DWC_OFFSET_MASK + 0x1036)
+#define HDMITX_DWC_FC_VSDPAYLOAD5 (DWC_OFFSET_MASK + 0x1037)
+#define HDMITX_DWC_FC_VSDPAYLOAD6 (DWC_OFFSET_MASK + 0x1038)
+#define HDMITX_DWC_FC_VSDPAYLOAD7 (DWC_OFFSET_MASK + 0x1039)
+#define HDMITX_DWC_FC_VSDPAYLOAD8 (DWC_OFFSET_MASK + 0x103A)
+#define HDMITX_DWC_FC_VSDPAYLOAD9 (DWC_OFFSET_MASK + 0x103B)
+#define HDMITX_DWC_FC_VSDPAYLOAD10 (DWC_OFFSET_MASK + 0x103C)
+#define HDMITX_DWC_FC_VSDPAYLOAD11 (DWC_OFFSET_MASK + 0x103D)
+#define HDMITX_DWC_FC_VSDPAYLOAD12 (DWC_OFFSET_MASK + 0x103E)
+#define HDMITX_DWC_FC_VSDPAYLOAD13 (DWC_OFFSET_MASK + 0x103F)
+#define HDMITX_DWC_FC_VSDPAYLOAD14 (DWC_OFFSET_MASK + 0x1040)
+#define HDMITX_DWC_FC_VSDPAYLOAD15 (DWC_OFFSET_MASK + 0x1041)
+#define HDMITX_DWC_FC_VSDPAYLOAD16 (DWC_OFFSET_MASK + 0x1042)
+#define HDMITX_DWC_FC_VSDPAYLOAD17 (DWC_OFFSET_MASK + 0x1043)
+#define HDMITX_DWC_FC_VSDPAYLOAD18 (DWC_OFFSET_MASK + 0x1044)
+#define HDMITX_DWC_FC_VSDPAYLOAD19 (DWC_OFFSET_MASK + 0x1045)
+#define HDMITX_DWC_FC_VSDPAYLOAD20 (DWC_OFFSET_MASK + 0x1046)
+#define HDMITX_DWC_FC_VSDPAYLOAD21 (DWC_OFFSET_MASK + 0x1047)
+#define HDMITX_DWC_FC_VSDPAYLOAD22 (DWC_OFFSET_MASK + 0x1048)
+#define HDMITX_DWC_FC_VSDPAYLOAD23 (DWC_OFFSET_MASK + 0x1049)
+#define HDMITX_DWC_FC_SPDVENDORNAME0 (DWC_OFFSET_MASK + 0x104A)
+#define HDMITX_DWC_FC_SPDVENDORNAME1 (DWC_OFFSET_MASK + 0x104B)
+#define HDMITX_DWC_FC_SPDVENDORNAME2 (DWC_OFFSET_MASK + 0x104C)
+#define HDMITX_DWC_FC_SPDVENDORNAME3 (DWC_OFFSET_MASK + 0x104D)
+#define HDMITX_DWC_FC_SPDVENDORNAME4 (DWC_OFFSET_MASK + 0x104E)
+#define HDMITX_DWC_FC_SPDVENDORNAME5 (DWC_OFFSET_MASK + 0x104F)
+#define HDMITX_DWC_FC_SPDVENDORNAME6 (DWC_OFFSET_MASK + 0x1050)
+#define HDMITX_DWC_FC_SPDVENDORNAME7 (DWC_OFFSET_MASK + 0x1051)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME0 (DWC_OFFSET_MASK + 0x1052)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME1 (DWC_OFFSET_MASK + 0x1053)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME2 (DWC_OFFSET_MASK + 0x1054)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME3 (DWC_OFFSET_MASK + 0x1055)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME4 (DWC_OFFSET_MASK + 0x1056)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME5 (DWC_OFFSET_MASK + 0x1057)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME6 (DWC_OFFSET_MASK + 0x1058)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME7 (DWC_OFFSET_MASK + 0x1059)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME8 (DWC_OFFSET_MASK + 0x105A)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME9 (DWC_OFFSET_MASK + 0x105B)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME10 (DWC_OFFSET_MASK + 0x105C)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME11 (DWC_OFFSET_MASK + 0x105D)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME12 (DWC_OFFSET_MASK + 0x105E)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME13 (DWC_OFFSET_MASK + 0x105F)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME14 (DWC_OFFSET_MASK + 0x1060)
+#define HDMITX_DWC_FC_SPDPRODUCTNAME15 (DWC_OFFSET_MASK + 0x1061)
+#define HDMITX_DWC_FC_SPDDEVICEINF (DWC_OFFSET_MASK + 0x1062)
+/* [7:4] aud_packet_sampflat */
+/* [ 0] aud_packet_layout */
+#define HDMITX_DWC_FC_AUDSCONF (DWC_OFFSET_MASK + 0x1063)
+#define HDMITX_DWC_FC_AUDSSTAT (DWC_OFFSET_MASK + 0x1064)
+/* [ 7] V3r */
+/* [ 6] V2r */
+/* [ 5] V1r */
+/* [ 4] V0r */
+/* [ 3] V3l */
+/* [ 2] V2l */
+/* [ 1] V1l */
+/* [ 0] V0l */
+#define HDMITX_DWC_FC_AUDSV (DWC_OFFSET_MASK + 0x1065)
+#define HDMITX_DWC_FC_AUDSU (DWC_OFFSET_MASK + 0x1066)
+/* bit5:4 CSB 41:40 */
+/* bit0 CSB 2 */
+#define HDMITX_DWC_FC_AUDSCHNLS0 (DWC_OFFSET_MASK + 0x1067)
+/* bit7:0 CSB 15:8 */
+#define HDMITX_DWC_FC_AUDSCHNLS1 (DWC_OFFSET_MASK + 0x1068)
+/* bit6:4 CSB 5:3 */
+/* bit3:0 CSB 17:16 */
+#define HDMITX_DWC_FC_AUDSCHNLS2 (DWC_OFFSET_MASK + 0x1069)
+/* bit7:4 CSB 22:21 2nd right sub */
+/* bit3:0 CSB 22:21 1st right sub */
+#define HDMITX_DWC_FC_AUDSCHNLS3 (DWC_OFFSET_MASK + 0x106A)
+/* bit?? CSB 22:21 4th right sub */
+/* bit?? CSB 22:21 3rd right sub */
+#define HDMITX_DWC_FC_AUDSCHNLS4 (DWC_OFFSET_MASK + 0x106B)
+/* bit7:4 CSB 22:21 2nd left sub */
+/* bit3:0 CSB 22:21 1st left sub */
+#define HDMITX_DWC_FC_AUDSCHNLS5 (DWC_OFFSET_MASK + 0x106C)
+/* bit?? CSB 22:21 4th left sub */
+/* bit?? CSB 22:21 3rd left sub */
+#define HDMITX_DWC_FC_AUDSCHNLS6 (DWC_OFFSET_MASK + 0x106D)
+#define HDMITX_DWC_FC_AUDSCHNLS7 (DWC_OFFSET_MASK + 0x106E)
+#define HDMITX_DWC_FC_AUDSCHNLS8 (DWC_OFFSET_MASK + 0x106F)
+#define HDMITX_DWC_FC_DATACH0FILL (DWC_OFFSET_MASK + 0x1070)
+#define HDMITX_DWC_FC_DATACH1FILL (DWC_OFFSET_MASK + 0x1071)
+#define HDMITX_DWC_FC_DATACH2FILL (DWC_OFFSET_MASK + 0x1072)
+#define HDMITX_DWC_FC_CTRLQHIGH (DWC_OFFSET_MASK + 0x1073)
+#define HDMITX_DWC_FC_CTRLQLOW (DWC_OFFSET_MASK + 0x1074)
+#define HDMITX_DWC_FC_ACP0 (DWC_OFFSET_MASK + 0x1075)
+#define HDMITX_DWC_FC_ACP16 (DWC_OFFSET_MASK + 0x1082)
+#define HDMITX_DWC_FC_ACP15 (DWC_OFFSET_MASK + 0x1083)
+#define HDMITX_DWC_FC_ACP14 (DWC_OFFSET_MASK + 0x1084)
+#define HDMITX_DWC_FC_ACP13 (DWC_OFFSET_MASK + 0x1085)
+#define HDMITX_DWC_FC_ACP12 (DWC_OFFSET_MASK + 0x1086)
+#define HDMITX_DWC_FC_ACP11 (DWC_OFFSET_MASK + 0x1087)
+#define HDMITX_DWC_FC_ACP10 (DWC_OFFSET_MASK + 0x1088)
+#define HDMITX_DWC_FC_ACP9 (DWC_OFFSET_MASK + 0x1089)
+#define HDMITX_DWC_FC_ACP8 (DWC_OFFSET_MASK + 0x108A)
+#define HDMITX_DWC_FC_ACP7 (DWC_OFFSET_MASK + 0x108B)
+#define HDMITX_DWC_FC_ACP6 (DWC_OFFSET_MASK + 0x108C)
+#define HDMITX_DWC_FC_ACP5 (DWC_OFFSET_MASK + 0x108D)
+#define HDMITX_DWC_FC_ACP4 (DWC_OFFSET_MASK + 0x108E)
+#define HDMITX_DWC_FC_ACP3 (DWC_OFFSET_MASK + 0x108F)
+#define HDMITX_DWC_FC_ACP2 (DWC_OFFSET_MASK + 0x1090)
+#define HDMITX_DWC_FC_ACP1 (DWC_OFFSET_MASK + 0x1091)
+#define HDMITX_DWC_FC_ISCR1_0 (DWC_OFFSET_MASK + 0x1092)
+#define HDMITX_DWC_FC_ISCR1_16 (DWC_OFFSET_MASK + 0x1093)
+#define HDMITX_DWC_FC_ISCR1_15 (DWC_OFFSET_MASK + 0x1094)
+#define HDMITX_DWC_FC_ISCR1_14 (DWC_OFFSET_MASK + 0x1095)
+#define HDMITX_DWC_FC_ISCR1_13 (DWC_OFFSET_MASK + 0x1096)
+#define HDMITX_DWC_FC_ISCR1_12 (DWC_OFFSET_MASK + 0x1097)
+#define HDMITX_DWC_FC_ISCR1_11 (DWC_OFFSET_MASK + 0x1098)
+#define HDMITX_DWC_FC_ISCR1_10 (DWC_OFFSET_MASK + 0x1099)
+#define HDMITX_DWC_FC_ISCR1_9 (DWC_OFFSET_MASK + 0x109A)
+#define HDMITX_DWC_FC_ISCR1_8 (DWC_OFFSET_MASK + 0x109B)
+#define HDMITX_DWC_FC_ISCR1_7 (DWC_OFFSET_MASK + 0x109C)
+#define HDMITX_DWC_FC_ISCR1_6 (DWC_OFFSET_MASK + 0x109D)
+#define HDMITX_DWC_FC_ISCR1_5 (DWC_OFFSET_MASK + 0x109E)
+#define HDMITX_DWC_FC_ISCR1_4 (DWC_OFFSET_MASK + 0x109F)
+#define HDMITX_DWC_FC_ISCR1_3 (DWC_OFFSET_MASK + 0x10A0)
+#define HDMITX_DWC_FC_ISCR1_2 (DWC_OFFSET_MASK + 0x10A1)
+#define HDMITX_DWC_FC_ISCR1_1 (DWC_OFFSET_MASK + 0x10A2)
+#define HDMITX_DWC_FC_ISCR0_15 (DWC_OFFSET_MASK + 0x10A3)
+#define HDMITX_DWC_FC_ISCR0_14 (DWC_OFFSET_MASK + 0x10A4)
+#define HDMITX_DWC_FC_ISCR0_13 (DWC_OFFSET_MASK + 0x10A5)
+#define HDMITX_DWC_FC_ISCR0_12 (DWC_OFFSET_MASK + 0x10A6)
+#define HDMITX_DWC_FC_ISCR0_11 (DWC_OFFSET_MASK + 0x10A7)
+#define HDMITX_DWC_FC_ISCR0_10 (DWC_OFFSET_MASK + 0x10A8)
+#define HDMITX_DWC_FC_ISCR0_9 (DWC_OFFSET_MASK + 0x10A9)
+#define HDMITX_DWC_FC_ISCR0_8 (DWC_OFFSET_MASK + 0x10AA)
+#define HDMITX_DWC_FC_ISCR0_7 (DWC_OFFSET_MASK + 0x10AB)
+#define HDMITX_DWC_FC_ISCR0_6 (DWC_OFFSET_MASK + 0x10AC)
+#define HDMITX_DWC_FC_ISCR0_5 (DWC_OFFSET_MASK + 0x10AD)
+#define HDMITX_DWC_FC_ISCR0_4 (DWC_OFFSET_MASK + 0x10AE)
+#define HDMITX_DWC_FC_ISCR0_3 (DWC_OFFSET_MASK + 0x10AF)
+#define HDMITX_DWC_FC_ISCR0_2 (DWC_OFFSET_MASK + 0x10B0)
+#define HDMITX_DWC_FC_ISCR0_1 (DWC_OFFSET_MASK + 0x10B1)
+#define HDMITX_DWC_FC_ISCR0_0 (DWC_OFFSET_MASK + 0x10B2)
+/* [ 4] spd_auto */
+/* [ 3] vsd_auto */
+/* [ 2] isrc2_auto */
+/* [ 1] isrc1_auto */
+/* [ 0] acp_auto */
+#define HDMITX_DWC_FC_DATAUTO0 (DWC_OFFSET_MASK + 0x10B3)
+#define HDMITX_DWC_FC_DATAUTO1 (DWC_OFFSET_MASK + 0x10B4)
+#define HDMITX_DWC_FC_DATAUTO2 (DWC_OFFSET_MASK + 0x10B5)
+#define HDMITX_DWC_FC_DATMAN (DWC_OFFSET_MASK + 0x10B6)
+/* [ 6] drm_auto: instert on Vsync */
+/* [ 5] nvbi_auto: insert on Vsync */
+/* [ 4] amp_auto: insert on Vsync */
+/* [ 3] avi_auto: insert on Vsync */
+/* [ 2] gcp_auto: insert on Vsync */
+/* [ 1] audi_auto: insert on Vsync */
+/* [ 0] acr_auto: insert on CTS update. Assert this bit later to avoid
+ * initial packets with false CTS value
+ */
+#define HDMITX_DWC_FC_DATAUTO3 (DWC_OFFSET_MASK + 0x10B7)
+#define HDMITX_DWC_FC_RDRB0 (DWC_OFFSET_MASK + 0x10B8)
+#define HDMITX_DWC_FC_RDRB1 (DWC_OFFSET_MASK + 0x10B9)
+#define HDMITX_DWC_FC_RDRB2 (DWC_OFFSET_MASK + 0x10BA)
+#define HDMITX_DWC_FC_RDRB3 (DWC_OFFSET_MASK + 0x10BB)
+#define HDMITX_DWC_FC_RDRB4 (DWC_OFFSET_MASK + 0x10BC)
+#define HDMITX_DWC_FC_RDRB5 (DWC_OFFSET_MASK + 0x10BD)
+#define HDMITX_DWC_FC_RDRB6 (DWC_OFFSET_MASK + 0x10BE)
+#define HDMITX_DWC_FC_RDRB7 (DWC_OFFSET_MASK + 0x10BF)
+#define HDMITX_DWC_FC_RDRB8 (DWC_OFFSET_MASK + 0x10C0)
+#define HDMITX_DWC_FC_RDRB9 (DWC_OFFSET_MASK + 0x10C1)
+#define HDMITX_DWC_FC_RDRB10 (DWC_OFFSET_MASK + 0x10C2)
+#define HDMITX_DWC_FC_RDRB11 (DWC_OFFSET_MASK + 0x10C3)
+/* [ 7] AUDI_int_mask */
+/* [ 6] ACP_int_mask */
+/* [ 5] HBR_int_mask */
+/* [ 2] AUDS_int_mask */
+/* [ 1] ACR_int_mask */
+/* [ 0] NULL_int_mask */
+#define HDMITX_DWC_FC_MASK0 (DWC_OFFSET_MASK + 0x10D2)
+/* [ 7] GMD_int_mask */
+/* [ 6] ISRC1_int_mask */
+/* [ 5] ISRC2_int_mask */
+/* [ 4] VSD_int_mask */
+/* [ 3] SPD_int_mask */
+/* [ 1] AVI_int_mask */
+/* [ 0] GCP_int_mask */
+#define HDMITX_DWC_FC_MASK1 (DWC_OFFSET_MASK + 0x10D6)
+/* [ 2] Mask bit for FC_INT2.DRM interrupt bit */
+/* [ 1] LowPriority_fifo_full */
+/* [ 0] HighPriority_fifo_full */
+#define HDMITX_DWC_FC_MASK2 (DWC_OFFSET_MASK + 0x10DA)
+/* [7:4] incoming_pr_factor */
+/* [3:0] output_pr_factor */
+#define HDMITX_DWC_FC_PRCONF (DWC_OFFSET_MASK + 0x10E0)
+/* [ 4] scrambler_ucp_line */
+/* [ 0] scrambler_en. Only update this bit once we've sent SCDC message*/
+#define HDMITX_DWC_FC_SCRAMBLER_CTRL (DWC_OFFSET_MASK + 0x10E1)
+#define HDMITX_DWC_FC_MULTISTREAM_CTRL (DWC_OFFSET_MASK + 0x10E2)
+/* [ 7] drm_tx_en */
+/* [ 6] nvbi_tx_en */
+/* [ 5] amp_tx_en */
+/* [ 4] aut_tx_en */
+/* [ 3] audi_tx_en */
+/* [ 2] avi_tx_en */
+/* [ 1] gcp_tx_en */
+/* [ 0] acr_tx_en */
+#define HDMITX_DWC_FC_PACKET_TX_EN (DWC_OFFSET_MASK + 0x10E3)
+/* [ 1] actspc_hdlr_tgl */
+/* [ 0] actspc_hdlr_en */
+#define HDMITX_DWC_FC_ACTSPC_HDLR_CFG (DWC_OFFSET_MASK + 0x10E8)
+#define HDMITX_DWC_FC_INVACT_2D_0 (DWC_OFFSET_MASK + 0x10E9)
+/* [3:0] fc_invact_2d_0[11:8] */
+/* [7:0] fc_invact_2d_0[7:0] */
+#define HDMITX_DWC_FC_INVACT_2D_1 (DWC_OFFSET_MASK + 0x10EA)
+
+#define HDMITX_DWC_FC_GMD_STAT (DWC_OFFSET_MASK + 0x1100)
+#define HDMITX_DWC_FC_GMD_EN (DWC_OFFSET_MASK + 0x1101)
+#define HDMITX_DWC_FC_GMD_UP (DWC_OFFSET_MASK + 0x1102)
+#define HDMITX_DWC_FC_GMD_CONF (DWC_OFFSET_MASK + 0x1103)
+#define HDMITX_DWC_FC_GMD_HB (DWC_OFFSET_MASK + 0x1104)
+#define HDMITX_DWC_FC_GMD_PB0 (DWC_OFFSET_MASK + 0x1105)
+#define HDMITX_DWC_FC_GMD_PB1 (DWC_OFFSET_MASK + 0x1106)
+#define HDMITX_DWC_FC_GMD_PB2 (DWC_OFFSET_MASK + 0x1107)
+#define HDMITX_DWC_FC_GMD_PB3 (DWC_OFFSET_MASK + 0x1108)
+#define HDMITX_DWC_FC_GMD_PB4 (DWC_OFFSET_MASK + 0x1109)
+#define HDMITX_DWC_FC_GMD_PB5 (DWC_OFFSET_MASK + 0x110A)
+#define HDMITX_DWC_FC_GMD_PB6 (DWC_OFFSET_MASK + 0x110B)
+#define HDMITX_DWC_FC_GMD_PB7 (DWC_OFFSET_MASK + 0x110C)
+#define HDMITX_DWC_FC_GMD_PB8 (DWC_OFFSET_MASK + 0x110D)
+#define HDMITX_DWC_FC_GMD_PB9 (DWC_OFFSET_MASK + 0x110E)
+#define HDMITX_DWC_FC_GMD_PB10 (DWC_OFFSET_MASK + 0x110F)
+#define HDMITX_DWC_FC_GMD_PB11 (DWC_OFFSET_MASK + 0x1110)
+#define HDMITX_DWC_FC_GMD_PB12 (DWC_OFFSET_MASK + 0x1111)
+#define HDMITX_DWC_FC_GMD_PB13 (DWC_OFFSET_MASK + 0x1112)
+#define HDMITX_DWC_FC_GMD_PB14 (DWC_OFFSET_MASK + 0x1113)
+#define HDMITX_DWC_FC_GMD_PB15 (DWC_OFFSET_MASK + 0x1114)
+#define HDMITX_DWC_FC_GMD_PB16 (DWC_OFFSET_MASK + 0x1115)
+#define HDMITX_DWC_FC_GMD_PB17 (DWC_OFFSET_MASK + 0x1116)
+#define HDMITX_DWC_FC_GMD_PB18 (DWC_OFFSET_MASK + 0x1117)
+#define HDMITX_DWC_FC_GMD_PB19 (DWC_OFFSET_MASK + 0x1118)
+#define HDMITX_DWC_FC_GMD_PB20 (DWC_OFFSET_MASK + 0x1119)
+#define HDMITX_DWC_FC_GMD_PB21 (DWC_OFFSET_MASK + 0x111A)
+#define HDMITX_DWC_FC_GMD_PB22 (DWC_OFFSET_MASK + 0x111B)
+#define HDMITX_DWC_FC_GMD_PB23 (DWC_OFFSET_MASK + 0x111C)
+#define HDMITX_DWC_FC_GMD_PB24 (DWC_OFFSET_MASK + 0x111D)
+#define HDMITX_DWC_FC_GMD_PB25 (DWC_OFFSET_MASK + 0x111E)
+#define HDMITX_DWC_FC_GMD_PB26 (DWC_OFFSET_MASK + 0x111F)
+#define HDMITX_DWC_FC_GMD_PB27 (DWC_OFFSET_MASK + 0x1120)
+
+/* Audio Metadata Packet Registers */
+#define HDMITX_DWC_FC_AMP_HB01 (DWC_OFFSET_MASK + 0x1128)
+#define HDMITX_DWC_FC_AMP_HB02 (DWC_OFFSET_MASK + 0x1129)
+#define HDMITX_DWC_FC_AMP_PB00 (DWC_OFFSET_MASK + 0x112A)
+#define HDMITX_DWC_FC_AMP_PB01 (DWC_OFFSET_MASK + 0x112B)
+#define HDMITX_DWC_FC_AMP_PB02 (DWC_OFFSET_MASK + 0x112C)
+#define HDMITX_DWC_FC_AMP_PB03 (DWC_OFFSET_MASK + 0x112D)
+#define HDMITX_DWC_FC_AMP_PB04 (DWC_OFFSET_MASK + 0x112E)
+#define HDMITX_DWC_FC_AMP_PB05 (DWC_OFFSET_MASK + 0x112F)
+#define HDMITX_DWC_FC_AMP_PB06 (DWC_OFFSET_MASK + 0x1130)
+#define HDMITX_DWC_FC_AMP_PB07 (DWC_OFFSET_MASK + 0x1131)
+#define HDMITX_DWC_FC_AMP_PB08 (DWC_OFFSET_MASK + 0x1132)
+#define HDMITX_DWC_FC_AMP_PB09 (DWC_OFFSET_MASK + 0x1133)
+#define HDMITX_DWC_FC_AMP_PB10 (DWC_OFFSET_MASK + 0x1134)
+#define HDMITX_DWC_FC_AMP_PB11 (DWC_OFFSET_MASK + 0x1135)
+#define HDMITX_DWC_FC_AMP_PB12 (DWC_OFFSET_MASK + 0x1136)
+#define HDMITX_DWC_FC_AMP_PB13 (DWC_OFFSET_MASK + 0x1137)
+#define HDMITX_DWC_FC_AMP_PB14 (DWC_OFFSET_MASK + 0x1138)
+#define HDMITX_DWC_FC_AMP_PB15 (DWC_OFFSET_MASK + 0x1139)
+#define HDMITX_DWC_FC_AMP_PB16 (DWC_OFFSET_MASK + 0x113A)
+#define HDMITX_DWC_FC_AMP_PB17 (DWC_OFFSET_MASK + 0x113B)
+#define HDMITX_DWC_FC_AMP_PB18 (DWC_OFFSET_MASK + 0x113C)
+#define HDMITX_DWC_FC_AMP_PB19 (DWC_OFFSET_MASK + 0x113D)
+#define HDMITX_DWC_FC_AMP_PB20 (DWC_OFFSET_MASK + 0x113E)
+#define HDMITX_DWC_FC_AMP_PB21 (DWC_OFFSET_MASK + 0x113F)
+#define HDMITX_DWC_FC_AMP_PB22 (DWC_OFFSET_MASK + 0x1140)
+#define HDMITX_DWC_FC_AMP_PB23 (DWC_OFFSET_MASK + 0x1141)
+#define HDMITX_DWC_FC_AMP_PB24 (DWC_OFFSET_MASK + 0x1142)
+#define HDMITX_DWC_FC_AMP_PB25 (DWC_OFFSET_MASK + 0x1143)
+#define HDMITX_DWC_FC_AMP_PB26 (DWC_OFFSET_MASK + 0x1144)
+#define HDMITX_DWC_FC_AMP_PB27 (DWC_OFFSET_MASK + 0x1145)
+
+/* NTSC VBI Packet Registers */
+#define HDMITX_DWC_FC_NVBI_HB01 (DWC_OFFSET_MASK + 0x1148)
+#define HDMITX_DWC_FC_NVBI_HB02 (DWC_OFFSET_MASK + 0x1149)
+#define HDMITX_DWC_FC_NVBI_PB01 (DWC_OFFSET_MASK + 0x114A)
+#define HDMITX_DWC_FC_NVBI_PB02 (DWC_OFFSET_MASK + 0x114B)
+#define HDMITX_DWC_FC_NVBI_PB03 (DWC_OFFSET_MASK + 0x114C)
+#define HDMITX_DWC_FC_NVBI_PB04 (DWC_OFFSET_MASK + 0x114D)
+#define HDMITX_DWC_FC_NVBI_PB05 (DWC_OFFSET_MASK + 0x114E)
+#define HDMITX_DWC_FC_NVBI_PB06 (DWC_OFFSET_MASK + 0x114F)
+#define HDMITX_DWC_FC_NVBI_PB07 (DWC_OFFSET_MASK + 0x1150)
+#define HDMITX_DWC_FC_NVBI_PB08 (DWC_OFFSET_MASK + 0x1151)
+#define HDMITX_DWC_FC_NVBI_PB09 (DWC_OFFSET_MASK + 0x1152)
+#define HDMITX_DWC_FC_NVBI_PB10 (DWC_OFFSET_MASK + 0x1153)
+#define HDMITX_DWC_FC_NVBI_PB11 (DWC_OFFSET_MASK + 0x1154)
+#define HDMITX_DWC_FC_NVBI_PB12 (DWC_OFFSET_MASK + 0x1155)
+#define HDMITX_DWC_FC_NVBI_PB13 (DWC_OFFSET_MASK + 0x1156)
+#define HDMITX_DWC_FC_NVBI_PB14 (DWC_OFFSET_MASK + 0x1157)
+#define HDMITX_DWC_FC_NVBI_PB15 (DWC_OFFSET_MASK + 0x1158)
+#define HDMITX_DWC_FC_NVBI_PB16 (DWC_OFFSET_MASK + 0x1159)
+#define HDMITX_DWC_FC_NVBI_PB17 (DWC_OFFSET_MASK + 0x115A)
+#define HDMITX_DWC_FC_NVBI_PB18 (DWC_OFFSET_MASK + 0x115B)
+#define HDMITX_DWC_FC_NVBI_PB19 (DWC_OFFSET_MASK + 0x115C)
+#define HDMITX_DWC_FC_NVBI_PB20 (DWC_OFFSET_MASK + 0x115D)
+#define HDMITX_DWC_FC_NVBI_PB21 (DWC_OFFSET_MASK + 0x115E)
+#define HDMITX_DWC_FC_NVBI_PB22 (DWC_OFFSET_MASK + 0x115F)
+#define HDMITX_DWC_FC_NVBI_PB23 (DWC_OFFSET_MASK + 0x1160)
+#define HDMITX_DWC_FC_NVBI_PB24 (DWC_OFFSET_MASK + 0x1161)
+#define HDMITX_DWC_FC_NVBI_PB25 (DWC_OFFSET_MASK + 0x1162)
+#define HDMITX_DWC_FC_NVBI_PB26 (DWC_OFFSET_MASK + 0x1163)
+#define HDMITX_DWC_FC_NVBI_PB27 (DWC_OFFSET_MASK + 0x1164)
+#define HDMITX_DWC_FC_DRM_HB01 (DWC_OFFSET_MASK + 0x1168)
+#define HDMITX_DWC_FC_DRM_HB02 (DWC_OFFSET_MASK + 0x1169)
+#define HDMITX_DWC_FC_DRM_PB00 (DWC_OFFSET_MASK + 0x116A)
+#define HDMITX_DWC_FC_DRM_PB01 (DWC_OFFSET_MASK + 0x116B)
+#define HDMITX_DWC_FC_DRM_PB02 (DWC_OFFSET_MASK + 0x116C)
+#define HDMITX_DWC_FC_DRM_PB03 (DWC_OFFSET_MASK + 0x116D)
+#define HDMITX_DWC_FC_DRM_PB04 (DWC_OFFSET_MASK + 0x116E)
+#define HDMITX_DWC_FC_DRM_PB05 (DWC_OFFSET_MASK + 0x116F)
+#define HDMITX_DWC_FC_DRM_PB06 (DWC_OFFSET_MASK + 0x1170)
+#define HDMITX_DWC_FC_DRM_PB07 (DWC_OFFSET_MASK + 0x1171)
+#define HDMITX_DWC_FC_DRM_PB08 (DWC_OFFSET_MASK + 0x1172)
+#define HDMITX_DWC_FC_DRM_PB09 (DWC_OFFSET_MASK + 0x1173)
+#define HDMITX_DWC_FC_DRM_PB10 (DWC_OFFSET_MASK + 0x1174)
+#define HDMITX_DWC_FC_DRM_PB11 (DWC_OFFSET_MASK + 0x1175)
+#define HDMITX_DWC_FC_DRM_PB12 (DWC_OFFSET_MASK + 0x1176)
+#define HDMITX_DWC_FC_DRM_PB13 (DWC_OFFSET_MASK + 0x1177)
+#define HDMITX_DWC_FC_DRM_PB14 (DWC_OFFSET_MASK + 0x1178)
+#define HDMITX_DWC_FC_DRM_PB15 (DWC_OFFSET_MASK + 0x1179)
+#define HDMITX_DWC_FC_DRM_PB16 (DWC_OFFSET_MASK + 0x117A)
+#define HDMITX_DWC_FC_DRM_PB17 (DWC_OFFSET_MASK + 0x117B)
+#define HDMITX_DWC_FC_DRM_PB18 (DWC_OFFSET_MASK + 0x117C)
+#define HDMITX_DWC_FC_DRM_PB19 (DWC_OFFSET_MASK + 0x117D)
+#define HDMITX_DWC_FC_DRM_PB20 (DWC_OFFSET_MASK + 0x117E)
+#define HDMITX_DWC_FC_DRM_PB21 (DWC_OFFSET_MASK + 0x117F)
+#define HDMITX_DWC_FC_DRM_PB22 (DWC_OFFSET_MASK + 0x1180)
+#define HDMITX_DWC_FC_DRM_PB23 (DWC_OFFSET_MASK + 0x1181)
+#define HDMITX_DWC_FC_DRM_PB24 (DWC_OFFSET_MASK + 0x1182)
+#define HDMITX_DWC_FC_DRM_PB25 (DWC_OFFSET_MASK + 0x1183)
+#define HDMITX_DWC_FC_DRM_PB26 (DWC_OFFSET_MASK + 0x1184)
+
+#define HDMITX_DWC_FC_DBGFORCE (DWC_OFFSET_MASK + 0x1200)
+#define HDMITX_DWC_FC_DBGAUD0CH0 (DWC_OFFSET_MASK + 0x1201)
+#define HDMITX_DWC_FC_DBGAUD1CH0 (DWC_OFFSET_MASK + 0x1202)
+#define HDMITX_DWC_FC_DBGAUD2CH0 (DWC_OFFSET_MASK + 0x1203)
+#define HDMITX_DWC_FC_DBGAUD0CH1 (DWC_OFFSET_MASK + 0x1204)
+#define HDMITX_DWC_FC_DBGAUD1CH1 (DWC_OFFSET_MASK + 0x1205)
+#define HDMITX_DWC_FC_DBGAUD2CH1 (DWC_OFFSET_MASK + 0x1206)
+#define HDMITX_DWC_FC_DBGAUD0CH2 (DWC_OFFSET_MASK + 0x1207)
+#define HDMITX_DWC_FC_DBGAUD1CH2 (DWC_OFFSET_MASK + 0x1208)
+#define HDMITX_DWC_FC_DBGAUD2CH2 (DWC_OFFSET_MASK + 0x1209)
+#define HDMITX_DWC_FC_DBGAUD0CH3 (DWC_OFFSET_MASK + 0x120A)
+#define HDMITX_DWC_FC_DBGAUD1CH3 (DWC_OFFSET_MASK + 0x120B)
+#define HDMITX_DWC_FC_DBGAUD2CH3 (DWC_OFFSET_MASK + 0x120C)
+#define HDMITX_DWC_FC_DBGAUD0CH4 (DWC_OFFSET_MASK + 0x120D)
+#define HDMITX_DWC_FC_DBGAUD1CH4 (DWC_OFFSET_MASK + 0x120E)
+#define HDMITX_DWC_FC_DBGAUD2CH4 (DWC_OFFSET_MASK + 0x120F)
+#define HDMITX_DWC_FC_DBGAUD0CH5 (DWC_OFFSET_MASK + 0x1210)
+#define HDMITX_DWC_FC_DBGAUD1CH5 (DWC_OFFSET_MASK + 0x1211)
+#define HDMITX_DWC_FC_DBGAUD2CH5 (DWC_OFFSET_MASK + 0x1212)
+#define HDMITX_DWC_FC_DBGAUD0CH6 (DWC_OFFSET_MASK + 0x1213)
+#define HDMITX_DWC_FC_DBGAUD1CH6 (DWC_OFFSET_MASK + 0x1214)
+#define HDMITX_DWC_FC_DBGAUD2CH6 (DWC_OFFSET_MASK + 0x1215)
+#define HDMITX_DWC_FC_DBGAUD0CH7 (DWC_OFFSET_MASK + 0x1216)
+#define HDMITX_DWC_FC_DBGAUD1CH7 (DWC_OFFSET_MASK + 0x1217)
+#define HDMITX_DWC_FC_DBGAUD2CH7 (DWC_OFFSET_MASK + 0x1218)
+#define HDMITX_DWC_FC_DBGTMDS0 (DWC_OFFSET_MASK + 0x1219)
+#define HDMITX_DWC_FC_DBGTMDS1 (DWC_OFFSET_MASK + 0x121A)
+#define HDMITX_DWC_FC_DBGTMDS2 (DWC_OFFSET_MASK + 0x121B)
+
+/* HDMI Source PHY Registers */
+#define HDMITX_DWC_PHY_CONF0 (DWC_OFFSET_MASK + 0x3000)
+#define HDMITX_DWC_PHY_TST0 (DWC_OFFSET_MASK + 0x3001)
+#define HDMITX_DWC_PHY_TST1 (DWC_OFFSET_MASK + 0x3002)
+#define HDMITX_DWC_PHY_TST2 (DWC_OFFSET_MASK + 0x3003)
+#define HDMITX_DWC_PHY_STAT0 (DWC_OFFSET_MASK + 0x3004)
+#define HDMITX_DWC_PHY_INT0 (DWC_OFFSET_MASK + 0x3005)
+#define HDMITX_DWC_PHY_MASK0 (DWC_OFFSET_MASK + 0x3006)
+#define HDMITX_DWC_PHY_POL0 (DWC_OFFSET_MASK + 0x3007)
+
+/* I2C Master PHY Registers */
+#define HDMITX_DWC_I2CM_PHY_SLAVE (DWC_OFFSET_MASK + 0x3020)
+#define HDMITX_DWC_I2CM_PHY_ADDRESS (DWC_OFFSET_MASK + 0x3021)
+#define HDMITX_DWC_I2CM_PHY_DATAO_1 (DWC_OFFSET_MASK + 0x3022)
+#define HDMITX_DWC_I2CM_PHY_DATAO_0 (DWC_OFFSET_MASK + 0x3023)
+#define HDMITX_DWC_I2CM_PHY_DATAI_1 (DWC_OFFSET_MASK + 0x3024)
+#define HDMITX_DWC_I2CM_PHY_DATAI_0 (DWC_OFFSET_MASK + 0x3025)
+#define HDMITX_DWC_I2CM_PHY_OPERATION (DWC_OFFSET_MASK + 0x3026)
+#define HDMITX_DWC_I2CM_PHY_INT (DWC_OFFSET_MASK + 0x3027)
+#define HDMITX_DWC_I2CM_PHY_CTLINT (DWC_OFFSET_MASK + 0x3028)
+#define HDMITX_DWC_I2CM_PHY_DIV (DWC_OFFSET_MASK + 0x3029)
+#define HDMITX_DWC_I2CM_PHY_SOFTRSTZ (DWC_OFFSET_MASK + 0x302A)
+#define HDMITX_DWC_I2CM_PHY_SS_SCL_HCNT_1 (DWC_OFFSET_MASK + 0x302B)
+#define HDMITX_DWC_I2CM_PHY_SS_SCL_HCNT_0 (DWC_OFFSET_MASK + 0x302C)
+#define HDMITX_DWC_I2CM_PHY_SS_SCL_LCNT_1 (DWC_OFFSET_MASK + 0x302D)
+#define HDMITX_DWC_I2CM_PHY_SS_SCL_LCNT_0 (DWC_OFFSET_MASK + 0x302E)
+#define HDMITX_DWC_I2CM_PHY_FS_SCL_HCNT_1 (DWC_OFFSET_MASK + 0x302F)
+#define HDMITX_DWC_I2CM_PHY_FS_SCL_HCNT_0 (DWC_OFFSET_MASK + 0x3030)
+#define HDMITX_DWC_I2CM_PHY_FS_SCL_LCNT_1 (DWC_OFFSET_MASK + 0x3031)
+#define HDMITX_DWC_I2CM_PHY_FS_SCL_LCNT_0 (DWC_OFFSET_MASK + 0x3032)
+#define HDMITX_DWC_I2CM_PHY_SDA_HOLD (DWC_OFFSET_MASK + 0x3033)
+
+/* Audio Sampler Registers */
+
+ /* [ 7] sw_audio_fifo_rst */
+ /* [ 5] 0=select SPDIF; 1=select I2S. */
+ /* [3:0] i2s_in_en: enable it later in test.c */
+#define HDMITX_DWC_AUD_CONF0 (DWC_OFFSET_MASK + 0x3100)
+/* [4:0] i2s_width */
+/* [7:5] i2s_mode: 0=standard I2S mode */
+#define HDMITX_DWC_AUD_CONF1 (DWC_OFFSET_MASK + 0x3101)
+/* [ 3] fifo_empty_mask: 0=enable int; 1=mask int. */
+/* [ 2] fifo_full_mask: 0=enable int; 1=mask int. */
+#define HDMITX_DWC_AUD_INT (DWC_OFFSET_MASK + 0x3102)
+ /* [ 1] NLPCM */
+#define HDMITX_DWC_AUD_CONF2 (DWC_OFFSET_MASK + 0x3103)
+
+/* [ 4] fifo_overrun_mask: 0=enable int; 1=mask int.
+ * Enable it later when audio starts.
+ */
+#define HDMITX_DWC_AUD_INT1 (DWC_OFFSET_MASK + 0x3104)
+
+#define HDMITX_DWC_AUD_N1 (DWC_OFFSET_MASK + 0x3200)
+#define HDMITX_DWC_AUD_N2 (DWC_OFFSET_MASK + 0x3201)
+#define HDMITX_DWC_AUD_N3 (DWC_OFFSET_MASK + 0x3202)
+#define HDMITX_DWC_AUD_CTS1 (DWC_OFFSET_MASK + 0x3203)
+#define HDMITX_DWC_AUD_CTS2 (DWC_OFFSET_MASK + 0x3204)
+#define HDMITX_DWC_AUD_CTS3 (DWC_OFFSET_MASK + 0x3205)
+#define HDMITX_DWC_AUD_INPUTCLKFS (DWC_OFFSET_MASK + 0x3206)
+/* [ 7] sw_audio_fifo_rst */
+#define HDMITX_DWC_AUD_SPDIF0 (DWC_OFFSET_MASK + 0x3300)
+/* [4:0] spdif_width */
+/* [ 7] setnlpcm */
+#define HDMITX_DWC_AUD_SPDIF1 (DWC_OFFSET_MASK + 0x3301)
+/* [ 3] SPDIF fifo_empty_mask: 0=enable int; 1=mask int. */
+/* [ 2] SPDIF fifo_full_mask: 0=enable int; 1=mask int. */
+#define HDMITX_DWC_AUD_SPDIFINT (DWC_OFFSET_MASK + 0x3302)
+/* [ 4] SPDIF fifo_overrun_mask: 0=enable int; 1=mask int. */
+#define HDMITX_DWC_AUD_SPDIFINT1 (DWC_OFFSET_MASK + 0x3303)
+
+/* Generic Parallel Audio Interface Registers (DWC_OFFSET_MASK + 0x3500) */
+/* Audio DMA Registers (DWC_OFFSET_MASK + 0x3600) */
+
+/* Main Controller Registers */
+/* [ 6] hdcpclk_disable */
+/* [ 5] cecclk_disable */
+/* [ 4] cscclk_disable */
+/* [ 3] audclk_disable */
+/* [ 2] prepclk_disable */
+/* [ 1] tmdsclk_disable */
+/* [ 0] pixelclk_disable */
+#define HDMITX_DWC_MC_CLKDIS (DWC_OFFSET_MASK + 0x4001)
+/*
+ * [ 7] gpaswrst_req: 0=generate reset pulse; 1=no reset.
+ * [ 6] cecswrst_req: 0=generate reset pulse; 1=no reset.
+ * [ 4] spdifswrst_req: 0=generate reset pulse; 1=no reset.
+ * [ 3] i2sswrst_req: 0=generate reset pulse; 1=no reset.
+ * [ 2] prepswrst_req: 0=generate reset pulse; 1=no reset.
+ * [ 1] tmdsswrst_req: 0=generate reset pulse; 1=no reset.
+ * [ 0] pixelswrst_req: 0=generate reset pulse; 1=no reset.
+ */
+#define HDMITX_DWC_MC_SWRSTZREQ (DWC_OFFSET_MASK + 0x4002)
+#define HDMITX_DWC_MC_OPCTRL (DWC_OFFSET_MASK + 0x4003)
+/* [ 0] CSC enable */
+#define HDMITX_DWC_MC_FLOWCTRL (DWC_OFFSET_MASK + 0x4004)
+#define HDMITX_DWC_MC_PHYRSTZ (DWC_OFFSET_MASK + 0x4005)
+#define HDMITX_DWC_MC_LOCKONCLOCK (DWC_OFFSET_MASK + 0x4006)
+
+/* Color Space Converter Registers */
+/* [ 7] csc_limit */
+#define HDMITX_DWC_CSC_CFG (DWC_OFFSET_MASK + 0x4100)
+#define HDMITX_DWC_CSC_SCALE (DWC_OFFSET_MASK + 0x4101)
+#define HDMITX_DWC_CSC_COEF_A1_MSB (DWC_OFFSET_MASK + 0x4102)
+#define HDMITX_DWC_CSC_COEF_A1_LSB (DWC_OFFSET_MASK + 0x4103)
+#define HDMITX_DWC_CSC_COEF_A2_MSB (DWC_OFFSET_MASK + 0x4104)
+#define HDMITX_DWC_CSC_COEF_A2_LSB (DWC_OFFSET_MASK + 0x4105)
+#define HDMITX_DWC_CSC_COEF_A3_MSB (DWC_OFFSET_MASK + 0x4106)
+#define HDMITX_DWC_CSC_COEF_A3_LSB (DWC_OFFSET_MASK + 0x4107)
+#define HDMITX_DWC_CSC_COEF_A4_MSB (DWC_OFFSET_MASK + 0x4108)
+#define HDMITX_DWC_CSC_COEF_A4_LSB (DWC_OFFSET_MASK + 0x4109)
+#define HDMITX_DWC_CSC_COEF_B1_MSB (DWC_OFFSET_MASK + 0x410A)
+#define HDMITX_DWC_CSC_COEF_B1_LSB (DWC_OFFSET_MASK + 0x410B)
+#define HDMITX_DWC_CSC_COEF_B2_MSB (DWC_OFFSET_MASK + 0x410C)
+#define HDMITX_DWC_CSC_COEF_B2_LSB (DWC_OFFSET_MASK + 0x410D)
+#define HDMITX_DWC_CSC_COEF_B3_MSB (DWC_OFFSET_MASK + 0x410E)
+#define HDMITX_DWC_CSC_COEF_B3_LSB (DWC_OFFSET_MASK + 0x410F)
+#define HDMITX_DWC_CSC_COEF_B4_MSB (DWC_OFFSET_MASK + 0x4110)
+#define HDMITX_DWC_CSC_COEF_B4_LSB (DWC_OFFSET_MASK + 0x4111)
+#define HDMITX_DWC_CSC_COEF_C1_MSB (DWC_OFFSET_MASK + 0x4112)
+#define HDMITX_DWC_CSC_COEF_C1_LSB (DWC_OFFSET_MASK + 0x4113)
+#define HDMITX_DWC_CSC_COEF_C2_MSB (DWC_OFFSET_MASK + 0x4114)
+#define HDMITX_DWC_CSC_COEF_C2_LSB (DWC_OFFSET_MASK + 0x4115)
+#define HDMITX_DWC_CSC_COEF_C3_MSB (DWC_OFFSET_MASK + 0x4116)
+#define HDMITX_DWC_CSC_COEF_C3_LSB (DWC_OFFSET_MASK + 0x4117)
+#define HDMITX_DWC_CSC_COEF_C4_MSB (DWC_OFFSET_MASK + 0x4118)
+#define HDMITX_DWC_CSC_COEF_C4_LSB (DWC_OFFSET_MASK + 0x4119)
+#define HDMITX_DWC_CSC_LIMIT_UP_MSB (DWC_OFFSET_MASK + 0x411A)
+#define HDMITX_DWC_CSC_LIMIT_UP_LSB (DWC_OFFSET_MASK + 0x411B)
+#define HDMITX_DWC_CSC_LIMIT_DN_MSB (DWC_OFFSET_MASK + 0x411C)
+#define HDMITX_DWC_CSC_LIMIT_DN_LSB (DWC_OFFSET_MASK + 0x411D)
+
+/* HDCP Encryption Engine Registers */
+#define HDMITX_DWC_A_HDCPCFG0 (DWC_SEC_OFFSET_MASK + 0x5000)
+/* [ 4] hdcp_lock */
+/* [ 3] dissha1check */
+/* [ 2] ph2upshiftenc */
+/* [ 1] encryptiondisable */
+/* [ 0] swresetn. Write 0 to activate, self-clear to 1. */
+#define HDMITX_DWC_A_HDCPCFG1 (DWC_SEC_OFFSET_MASK + 0x5001)
+#define HDMITX_DWC_A_HDCPOBS0 (DWC_OFFSET_MASK + 0x5002)
+#define HDMITX_DWC_A_HDCPOBS1 (DWC_OFFSET_MASK + 0x5003)
+#define HDMITX_DWC_A_HDCPOBS2 (DWC_OFFSET_MASK + 0x5004)
+#define HDMITX_DWC_A_HDCPOBS3 (DWC_OFFSET_MASK + 0x5005)
+#define HDMITX_DWC_A_APIINTCLR (DWC_OFFSET_MASK + 0x5006)
+#define HDMITX_DWC_A_APIINTSTAT (DWC_OFFSET_MASK + 0x5007)
+/* [ 7] hdcp_engaged_int_mask */
+/* [ 6] hdcp_failed_int_mask */
+/* [ 4] i2c_nack_int_mask */
+/* [ 3] lost_arbitration_int_mask */
+/* [ 2] keepout_error_int_mask */
+/* [ 1] ksv_sha1_calc_int_mask */
+/* [ 0] ksv_access_int_mask */
+#define HDMITX_DWC_A_APIINTMSK (DWC_OFFSET_MASK + 0x5008)
+/* [6:5] unencryptconf */
+/* [ 4] dataenpol */
+/* [ 3] vsyncpol */
+/* [ 1] hsyncpol */
+#define HDMITX_DWC_A_VIDPOLCFG (DWC_OFFSET_MASK + 0x5009)
+#define HDMITX_DWC_A_OESSWCFG (DWC_OFFSET_MASK + 0x500A)
+#define HDMITX_DWC_A_COREVERLSB (DWC_OFFSET_MASK + 0x5014)
+#define HDMITX_DWC_A_COREVERMSB (DWC_OFFSET_MASK + 0x5015)
+/* [ 3] sha1_fail */
+/* [ 2] ksv_ctrl_update */
+/* [ 1] Rsvd for read-only ksv_mem_access */
+/* [ 0] ksv_mem_request */
+#define HDMITX_DWC_A_KSVMEMCTRL (DWC_OFFSET_MASK + 0x5016)
+
+#define HDMITX_DWC_HDCP_BSTATUS_0 (DWC_OFFSET_MASK + 0x5020)
+#define HDMITX_DWC_HDCP_BSTATUS_1 (DWC_OFFSET_MASK + 0x5021)
+#define HDMITX_DWC_HDCP_M0_0 (DWC_OFFSET_MASK + 0x5022)
+#define HDMITX_DWC_HDCP_M0_1 (DWC_OFFSET_MASK + 0x5023)
+#define HDMITX_DWC_HDCP_M0_2 (DWC_OFFSET_MASK + 0x5024)
+#define HDMITX_DWC_HDCP_M0_3 (DWC_OFFSET_MASK + 0x5025)
+#define HDMITX_DWC_HDCP_M0_4 (DWC_OFFSET_MASK + 0x5026)
+#define HDMITX_DWC_HDCP_M0_5 (DWC_OFFSET_MASK + 0x5027)
+#define HDMITX_DWC_HDCP_M0_6 (DWC_OFFSET_MASK + 0x5028)
+#define HDMITX_DWC_HDCP_M0_7 (DWC_OFFSET_MASK + 0x5029)
+#define HDMITX_DWC_HDCP_KSV (DWC_OFFSET_MASK + 0x502A)
+#define HDMITX_DWC_HDCP_VH (DWC_OFFSET_MASK + 0x52A5)
+#define HDMITX_DWC_HDCP_REVOC_SIZE_0 (DWC_OFFSET_MASK + 0x52B9)
+#define HDMITX_DWC_HDCP_REVOC_SIZE_1 (DWC_OFFSET_MASK + 0x52BA)
+#define HDMITX_DWC_HDCP_REVOC_LIST (DWC_OFFSET_MASK + 0x52BB)
+#define HDMITX_DWC_HDCP_REVOC_LIST_END (DWC_OFFSET_MASK + 0x667E)
+
+/* HDCP BKSV Registers */
+#define HDMITX_DWC_HDCPREG_BKSV0 (DWC_OFFSET_MASK + 0x7800)
+#define HDMITX_DWC_HDCPREG_BKSV1 (DWC_OFFSET_MASK + 0x7801)
+#define HDMITX_DWC_HDCPREG_BKSV2 (DWC_OFFSET_MASK + 0x7802)
+#define HDMITX_DWC_HDCPREG_BKSV3 (DWC_OFFSET_MASK + 0x7803)
+#define HDMITX_DWC_HDCPREG_BKSV4 (DWC_OFFSET_MASK + 0x7804)
+
+/* HDCP AN Registers */
+#define HDMITX_DWC_HDCPREG_ANCONF (DWC_OFFSET_MASK + 0x7805)
+#define HDMITX_DWC_HDCPREG_AN0 (DWC_OFFSET_MASK + 0x7806)
+#define HDMITX_DWC_HDCPREG_AN1 (DWC_OFFSET_MASK + 0x7807)
+#define HDMITX_DWC_HDCPREG_AN2 (DWC_OFFSET_MASK + 0x7808)
+#define HDMITX_DWC_HDCPREG_AN3 (DWC_OFFSET_MASK + 0x7809)
+#define HDMITX_DWC_HDCPREG_AN4 (DWC_OFFSET_MASK + 0x780A)
+#define HDMITX_DWC_HDCPREG_AN5 (DWC_OFFSET_MASK + 0x780B)
+#define HDMITX_DWC_HDCPREG_AN6 (DWC_OFFSET_MASK + 0x780C)
+#define HDMITX_DWC_HDCPREG_AN7 (DWC_OFFSET_MASK + 0x780D)
+#define HDMITX_DWC_HDCPREG_RMLCTL (DWC_OFFSET_MASK + 0x780E)
+
+/* Encrypted DPK Embedded Storage Registers */
+#define HDMITX_DWC_HDCPREG_RMLSTS (DWC_OFFSET_MASK + 0x780F)
+#define HDMITX_DWC_HDCPREG_SEED0 (DWC_SEC_OFFSET_MASK + 0x7810)
+#define HDMITX_DWC_HDCPREG_SEED1 (DWC_SEC_OFFSET_MASK + 0x7811)
+#define HDMITX_DWC_HDCPREG_DPK0 (DWC_SEC_OFFSET_MASK + 0x7812)
+#define HDMITX_DWC_HDCPREG_DPK1 (DWC_SEC_OFFSET_MASK + 0x7813)
+#define HDMITX_DWC_HDCPREG_DPK2 (DWC_SEC_OFFSET_MASK + 0x7814)
+#define HDMITX_DWC_HDCPREG_DPK3 (DWC_SEC_OFFSET_MASK + 0x7815)
+#define HDMITX_DWC_HDCPREG_DPK4 (DWC_SEC_OFFSET_MASK + 0x7816)
+#define HDMITX_DWC_HDCPREG_DPK5 (DWC_SEC_OFFSET_MASK + 0x7817)
+#define HDMITX_DWC_HDCPREG_DPK6 (DWC_SEC_OFFSET_MASK + 0x7818)
+
+/* HDCP22 Registers */
+#define HDMITX_DWC_HDCP22REG_ID (DWC_OFFSET_MASK + 0x7900)
+#define HDMITX_DWC_HDCP22REG_CTRL (DWC_SEC_OFFSET_MASK + 0x7904)
+#define HDMITX_DWC_HDCP22REG_CTRL1 (DWC_OFFSET_MASK + 0x7905)
+#define HDMITX_DWC_HDCP22REG_STS (DWC_OFFSET_MASK + 0x7908)
+#define HDMITX_DWC_HDCP22REG_MASK (DWC_OFFSET_MASK + 0x790C)
+#define HDMITX_DWC_HDCP22REG_STAT (DWC_OFFSET_MASK + 0x790D)
+#define HDMITX_DWC_HDCP22REG_MUTE (DWC_OFFSET_MASK + 0x790E)
+
+
+/* ********** CEC related ********** */
+
+/* CEC 2.0 Engine Registers */
+#define HDMITX_DWC_CEC_CTRL (DWC_OFFSET_MASK + 0x7D00)
+#define HDMITX_DWC_CEC_INTR_MASK (DWC_OFFSET_MASK + 0x7D02)
+#define HDMITX_DWC_CEC_LADD_LOW (DWC_OFFSET_MASK + 0x7D05)
+#define HDMITX_DWC_CEC_LADD_HIGH (DWC_OFFSET_MASK + 0x7D06)
+#define HDMITX_DWC_CEC_TX_CNT (DWC_OFFSET_MASK + 0x7D07)
+#define HDMITX_DWC_CEC_RX_CNT (DWC_OFFSET_MASK + 0x7D08)
+#define HDMITX_DWC_CEC_TX_DATA00 (DWC_OFFSET_MASK + 0x7D10)
+#define HDMITX_DWC_CEC_TX_DATA01 (DWC_OFFSET_MASK + 0x7D11)
+#define HDMITX_DWC_CEC_TX_DATA02 (DWC_OFFSET_MASK + 0x7D12)
+#define HDMITX_DWC_CEC_TX_DATA03 (DWC_OFFSET_MASK + 0x7D13)
+#define HDMITX_DWC_CEC_TX_DATA04 (DWC_OFFSET_MASK + 0x7D14)
+#define HDMITX_DWC_CEC_TX_DATA05 (DWC_OFFSET_MASK + 0x7D15)
+#define HDMITX_DWC_CEC_TX_DATA06 (DWC_OFFSET_MASK + 0x7D16)
+#define HDMITX_DWC_CEC_TX_DATA07 (DWC_OFFSET_MASK + 0x7D17)
+#define HDMITX_DWC_CEC_TX_DATA08 (DWC_OFFSET_MASK + 0x7D18)
+#define HDMITX_DWC_CEC_TX_DATA09 (DWC_OFFSET_MASK + 0x7D19)
+#define HDMITX_DWC_CEC_TX_DATA10 (DWC_OFFSET_MASK + 0x7D1A)
+#define HDMITX_DWC_CEC_TX_DATA11 (DWC_OFFSET_MASK + 0x7D1B)
+#define HDMITX_DWC_CEC_TX_DATA12 (DWC_OFFSET_MASK + 0x7D1C)
+#define HDMITX_DWC_CEC_TX_DATA13 (DWC_OFFSET_MASK + 0x7D1D)
+#define HDMITX_DWC_CEC_TX_DATA14 (DWC_OFFSET_MASK + 0x7D1E)
+#define HDMITX_DWC_CEC_TX_DATA15 (DWC_OFFSET_MASK + 0x7D1F)
+#define HDMITX_DWC_CEC_RX_DATA00 (DWC_OFFSET_MASK + 0x7D20)
+#define HDMITX_DWC_CEC_RX_DATA01 (DWC_OFFSET_MASK + 0x7D21)
+#define HDMITX_DWC_CEC_RX_DATA02 (DWC_OFFSET_MASK + 0x7D22)
+#define HDMITX_DWC_CEC_RX_DATA03 (DWC_OFFSET_MASK + 0x7D23)
+#define HDMITX_DWC_CEC_RX_DATA04 (DWC_OFFSET_MASK + 0x7D24)
+#define HDMITX_DWC_CEC_RX_DATA05 (DWC_OFFSET_MASK + 0x7D25)
+#define HDMITX_DWC_CEC_RX_DATA06 (DWC_OFFSET_MASK + 0x7D26)
+#define HDMITX_DWC_CEC_RX_DATA07 (DWC_OFFSET_MASK + 0x7D27)
+#define HDMITX_DWC_CEC_RX_DATA08 (DWC_OFFSET_MASK + 0x7D28)
+#define HDMITX_DWC_CEC_RX_DATA09 (DWC_OFFSET_MASK + 0x7D29)
+#define HDMITX_DWC_CEC_RX_DATA10 (DWC_OFFSET_MASK + 0x7D2A)
+#define HDMITX_DWC_CEC_RX_DATA11 (DWC_OFFSET_MASK + 0x7D2B)
+#define HDMITX_DWC_CEC_RX_DATA12 (DWC_OFFSET_MASK + 0x7D2C)
+#define HDMITX_DWC_CEC_RX_DATA13 (DWC_OFFSET_MASK + 0x7D2D)
+#define HDMITX_DWC_CEC_RX_DATA14 (DWC_OFFSET_MASK + 0x7D2E)
+#define HDMITX_DWC_CEC_RX_DATA15 (DWC_OFFSET_MASK + 0x7D2F)
+#define HDMITX_DWC_CEC_LOCK_BUF (DWC_OFFSET_MASK + 0x7D30)
+#define HDMITX_DWC_CEC_WAKEUPCTRL (DWC_OFFSET_MASK + 0x7D31)
+
+/* I2C Master Registers(E-DDC/SCDC) */
+#define HDMITX_DWC_I2CM_SLAVE (DWC_OFFSET_MASK + 0x7E00)
+#define HDMITX_DWC_I2CM_ADDRESS (DWC_OFFSET_MASK + 0x7E01)
+#define HDMITX_DWC_I2CM_DATAO (DWC_OFFSET_MASK + 0x7E02)
+#define HDMITX_DWC_I2CM_DATAI (DWC_OFFSET_MASK + 0x7E03)
+#define HDMITX_DWC_I2CM_OPERATION (DWC_OFFSET_MASK + 0x7E04)
+/* [ 2] done_mask */
+/* [ 6] read_req_mask */
+#define HDMITX_DWC_I2CM_INT (DWC_OFFSET_MASK + 0x7E05)
+/* [ 6] nack_mask */
+/* [ 2] arbitration_error_mask */
+#define HDMITX_DWC_I2CM_CTLINT (DWC_OFFSET_MASK + 0x7E06)
+/* [ 3] i2c_fast_mode: 0=standard mode; 1=fast mode. */
+#define HDMITX_DWC_I2CM_DIV (DWC_OFFSET_MASK + 0x7E07)
+#define HDMITX_DWC_I2CM_SEGADDR (DWC_OFFSET_MASK + 0x7E08)
+#define HDMITX_DWC_I2CM_SOFTRSTZ (DWC_OFFSET_MASK + 0x7E09)
+#define HDMITX_DWC_I2CM_SEGPTR (DWC_OFFSET_MASK + 0x7E0A)
+/* I2CM_SS_SCL_HCNT = RndUp(min_ss_scl_htime*Freq(sfrclkInMHz)/1000) */
+/* I2CM_SS_SCL_LCNT = RndUp(min_ss_scl_ltime*Freq(sfrclkInMHz)/1000) */
+/* I2CM_FS_SCL_HCNT = RndUp(min_fs_scl_htime*Freq(sfrclkInMHz)/1000) */
+/* I2CM_FS_SCL_LCNT = RndUp(min_fs_scl_ltime*Freq(sfrclkInMHz)/1000) */
+/* Where Freq(sfrclkInMHz)=24; */
+#define HDMITX_DWC_I2CM_SS_SCL_HCNT_1 (DWC_OFFSET_MASK + 0x7E0B)
+#define HDMITX_DWC_I2CM_SS_SCL_HCNT_0 (DWC_OFFSET_MASK + 0x7E0C)
+#define HDMITX_DWC_I2CM_SS_SCL_LCNT_1 (DWC_OFFSET_MASK + 0x7E0D)
+#define HDMITX_DWC_I2CM_SS_SCL_LCNT_0 (DWC_OFFSET_MASK + 0x7E0E)
+#define HDMITX_DWC_I2CM_FS_SCL_HCNT_1 (DWC_OFFSET_MASK + 0x7E0F)
+#define HDMITX_DWC_I2CM_FS_SCL_HCNT_0 (DWC_OFFSET_MASK + 0x7E10)
+#define HDMITX_DWC_I2CM_FS_SCL_LCNT_1 (DWC_OFFSET_MASK + 0x7E11)
+#define HDMITX_DWC_I2CM_FS_SCL_LCNT_0 (DWC_OFFSET_MASK + 0x7E12)
+#define HDMITX_DWC_I2CM_SDA_HOLD (DWC_OFFSET_MASK + 0x7E13)
+/* [ 5] updt_rd_vsyncpoll_en */
+/* [ 4] read_request_en */
+/* [ 0] read_update */
+#define HDMITX_DWC_I2CM_SCDC_UPDATE (DWC_OFFSET_MASK + 0x7E14)
+#define HDMITX_DWC_I2CM_READ_BUFF0 (DWC_OFFSET_MASK + 0x7E20)
+#define HDMITX_DWC_I2CM_READ_BUFF1 (DWC_OFFSET_MASK + 0x7E21)
+#define HDMITX_DWC_I2CM_READ_BUFF2 (DWC_OFFSET_MASK + 0x7E22)
+#define HDMITX_DWC_I2CM_READ_BUFF3 (DWC_OFFSET_MASK + 0x7E23)
+#define HDMITX_DWC_I2CM_READ_BUFF4 (DWC_OFFSET_MASK + 0x7E24)
+#define HDMITX_DWC_I2CM_READ_BUFF5 (DWC_OFFSET_MASK + 0x7E25)
+#define HDMITX_DWC_I2CM_READ_BUFF6 (DWC_OFFSET_MASK + 0x7E26)
+#define HDMITX_DWC_I2CM_READ_BUFF7 (DWC_OFFSET_MASK + 0x7E27)
+#define HDMITX_DWC_I2CM_SCDC_UPDATE0 (DWC_OFFSET_MASK + 0x7E30)
+#define HDMITX_DWC_I2CM_SCDC_UPDATE1 (DWC_OFFSET_MASK + 0x7E31)
+#endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_lcd.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drm_modeset_helper.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_mipi_dsi.h>
+#include <video/display_timing.h>
+#include <linux/component.h>
+#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
+#include <linux/amlogic/media/vout/lcd/lcd_notify.h>
+
+#include "meson_lcd.h"
+
+struct am_drm_lcd_s {
+ struct drm_panel panel;
+ struct drm_connector connector;
+ struct drm_encoder encoder;
+ struct mipi_dsi_host dsi_host;
+ struct drm_device *drm;
+ struct aml_lcd_drv_s *lcd_drv;
+ struct drm_display_mode *mode;
+ struct display_timing *timing;
+};
+
+static struct am_drm_lcd_s *am_drm_lcd;
+
+static struct drm_display_mode am_lcd_mode = {
+ .name = "panel",
+ .status = 0,
+ .clock = 74250,
+ .hdisplay = 1280,
+ .hsync_start = 1390,
+ .hsync_end = 1430,
+ .htotal = 1650,
+ .hskew = 0,
+ .vdisplay = 720,
+ .vsync_start = 725,
+ .vsync_end = 730,
+ .vtotal = 750,
+ .vscan = 0,
+ .vrefresh = 60,
+};
+
+static struct display_timing am_lcd_timing = {
+ .pixelclock = { 55000000, 65000000, 75000000 },
+ .hactive = { 1024, 1024, 1024 },
+ .hfront_porch = { 40, 40, 40 },
+ .hback_porch = { 220, 220, 220 },
+ .hsync_len = { 20, 60, 100 },
+ .vactive = { 768, 768, 768 },
+ .vfront_porch = { 7, 7, 7 },
+ .vback_porch = { 21, 21, 21 },
+ .vsync_len = { 10, 10, 10 },
+ .flags = DISPLAY_FLAGS_DE_HIGH,
+};
+
+/* ***************************************************************** */
+/* drm driver function */
+/* ***************************************************************** */
+#if 0
+static inline struct am_drm_lcd_s *host_to_lcd(struct mipi_dsi_host *host)
+{
+ return container_of(host, struct am_drm_lcd_s, dsi_host);
+}
+#endif
+
+static inline struct am_drm_lcd_s *con_to_lcd(struct drm_connector *con)
+{
+ return container_of(con, struct am_drm_lcd_s, connector);
+}
+
+static inline struct am_drm_lcd_s *encoder_to_lcd(struct drm_encoder *encoder)
+{
+ return container_of(encoder, struct am_drm_lcd_s, encoder);
+}
+
+static inline struct am_drm_lcd_s *panel_to_lcd(struct drm_panel *panel)
+{
+ return container_of(panel, struct am_drm_lcd_s, panel);
+}
+
+static int am_lcd_connector_get_modes(struct drm_connector *connector)
+{
+ struct drm_display_mode *mode;
+ struct am_drm_lcd_s *lcd;
+ int count = 0;
+
+ lcd = con_to_lcd(connector);
+
+ pr_info("***************************************************\n");
+ pr_info("am_drm_lcd: %s: lcd mode [%s] display size: %d x %d\n",
+ __func__, lcd->mode->name,
+ lcd->mode->hdisplay, lcd->mode->vdisplay);
+
+ mode = drm_mode_duplicate(connector->dev, lcd->mode);
+ pr_info("am_drm_lcd: %s: drm mode [%s] display size: %d x %d\n",
+ __func__, mode->name, mode->hdisplay, mode->vdisplay);
+ pr_info("am_drm_lcd: %s: lcd config size: %d x %d\n",
+ __func__, lcd->lcd_drv->lcd_config->lcd_basic.h_active,
+ lcd->lcd_drv->lcd_config->lcd_basic.v_active);
+
+ drm_mode_probed_add(connector, mode);
+ count = 1;
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+ pr_info("***************************************************\n");
+
+ return count;
+}
+
+enum drm_mode_status am_lcd_connector_mode_valid(
+ struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ struct am_drm_lcd_s *lcd;
+
+ lcd = con_to_lcd(connector);
+ if (!lcd)
+ return MODE_ERROR;
+ if (!lcd->lcd_drv)
+ return MODE_ERROR;
+
+ pr_info("am_drm_lcd: %s: mode [%s] display size: %d x %d\n",
+ __func__, mode->name, mode->hdisplay, mode->vdisplay);
+ pr_info("am_drm_lcd: %s: lcd config size: %d x %d\n",
+ __func__, lcd->lcd_drv->lcd_config->lcd_basic.h_active,
+ lcd->lcd_drv->lcd_config->lcd_basic.v_active);
+
+ if (mode->hdisplay != lcd->lcd_drv->lcd_config->lcd_basic.h_active)
+ return MODE_BAD_WIDTH;
+ if (mode->vdisplay != lcd->lcd_drv->lcd_config->lcd_basic.v_active)
+ return MODE_BAD_WIDTH;
+
+ pr_info("am_drm_lcd: %s %d: check mode OK\n", __func__, __LINE__);
+
+ return MODE_OK;
+}
+
+
+static const struct drm_connector_helper_funcs am_lcd_connector_helper_funcs = {
+ .get_modes = am_lcd_connector_get_modes,
+ .mode_valid = am_lcd_connector_mode_valid,
+ //.best_encoder
+ //.atomic_best_encoder
+};
+
+static enum drm_connector_status am_lcd_connector_detect(
+ struct drm_connector *connector, bool force)
+{
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+ return connector_status_connected;
+}
+
+#if 0
+static const struct drm_connector_funcs am_lcd_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = am_lcd_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+#else
+
+static int am_lcd_connector_dpms(struct drm_connector *connector, int mode)
+{
+ int ret = 0;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ ret = drm_atomic_helper_connector_dpms(connector, mode);
+ return ret;
+}
+
+static int am_lcd_connector_fill_modes(struct drm_connector *connector,
+ uint32_t maxX, uint32_t maxY)
+{
+ int count = 0;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+ count = drm_helper_probe_single_connector_modes(connector, maxX, maxY);
+ pr_info("am_drm_lcd: %s %d: count=%d\n", __func__, __LINE__, count);
+ return count;
+}
+
+static void am_lcd_connector_destroy(struct drm_connector *connector)
+{
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ drm_connector_cleanup(connector);
+}
+
+static void am_lcd_connector_reset(struct drm_connector *connector)
+{
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ drm_atomic_helper_connector_reset(connector);
+}
+
+static struct drm_connector_state *am_lcd_connector_duplicate_state(
+ struct drm_connector *connector)
+{
+ struct drm_connector_state *state;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ state = drm_atomic_helper_connector_duplicate_state(connector);
+ return state;
+}
+
+static void am_lcd_connector_destroy_state(struct drm_connector *connector,
+ struct drm_connector_state *state)
+{
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ drm_atomic_helper_connector_destroy_state(connector, state);
+}
+
+static const struct drm_connector_funcs am_lcd_connector_funcs = {
+ .dpms = am_lcd_connector_dpms,
+ .detect = am_lcd_connector_detect,
+ .fill_modes = am_lcd_connector_fill_modes,
+ .destroy = am_lcd_connector_destroy,
+ .reset = am_lcd_connector_reset,
+ .atomic_duplicate_state = am_lcd_connector_duplicate_state,
+ .atomic_destroy_state = am_lcd_connector_destroy_state,
+};
+#endif
+
+static void am_lcd_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static void am_lcd_encoder_enable(struct drm_encoder *encoder)
+{
+ enum vmode_e vmode = get_current_vmode();
+ struct am_drm_lcd_s *lcd = encoder_to_lcd(encoder);
+
+ if (!lcd)
+ return;
+ if (!lcd->lcd_drv)
+ return;
+
+ if (vmode == VMODE_LCD)
+ DRM_INFO("enable\n");
+ else
+ DRM_INFO("enable fail! vmode:%d\n", vmode);
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+ vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode);
+ mutex_lock(&lcd->lcd_drv->power_mutex);
+ aml_lcd_notifier_call_chain(LCD_EVENT_PREPARE, NULL);
+ aml_lcd_notifier_call_chain(LCD_EVENT_ENABLE, NULL);
+
+ lcd->lcd_drv->lcd_config->retry_enable_cnt = 0;
+ while (lcd->lcd_drv->lcd_config->retry_enable_flag) {
+ if (lcd->lcd_drv->lcd_config->retry_enable_cnt++ >=
+ LCD_ENABLE_RETRY_MAX)
+ break;
+ pr_info("am_drm_lcd: retry enable...%d\n",
+ lcd->lcd_drv->lcd_config->retry_enable_cnt);
+ aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, NULL);
+ msleep(1000);
+ aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_ON, NULL);
+ }
+ lcd->lcd_drv->lcd_config->retry_enable_cnt = 0;
+
+ mutex_unlock(&lcd->lcd_drv->power_mutex);
+ vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &vmode);
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static void am_lcd_encoder_disable(struct drm_encoder *encoder)
+{
+ struct am_drm_lcd_s *lcd = encoder_to_lcd(encoder);
+
+ if (!lcd)
+ return;
+ if (!lcd->lcd_drv)
+ return;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+ mutex_lock(&lcd->lcd_drv->power_mutex);
+ aml_lcd_notifier_call_chain(LCD_EVENT_DISABLE, NULL);
+ aml_lcd_notifier_call_chain(LCD_EVENT_UNPREPARE, NULL);
+ mutex_unlock(&lcd->lcd_drv->power_mutex);
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static void am_lcd_encoder_commit(struct drm_encoder *encoder)
+{
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static int am_lcd_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+ return 0;
+}
+
+static const struct drm_encoder_helper_funcs am_lcd_encoder_helper_funcs = {
+ .commit = am_lcd_encoder_commit,
+ .mode_set = am_lcd_encoder_mode_set,
+ .enable = am_lcd_encoder_enable,
+ .disable = am_lcd_encoder_disable,
+ .atomic_check = am_lcd_encoder_atomic_check,
+};
+
+static const struct drm_encoder_funcs am_lcd_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static int am_lcd_disable(struct drm_panel *panel)
+{
+ struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+ if (!lcd)
+ return -ENODEV;
+ if (!lcd->lcd_drv)
+ return -ENODEV;
+
+ mutex_lock(&lcd->lcd_drv->power_mutex);
+ aml_lcd_notifier_call_chain(LCD_EVENT_DISABLE, NULL);
+ mutex_unlock(&lcd->lcd_drv->power_mutex);
+
+ return 0;
+}
+
+static int am_lcd_unprepare(struct drm_panel *panel)
+{
+ struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+ if (!lcd)
+ return -ENODEV;
+ if (!lcd->lcd_drv)
+ return -ENODEV;
+
+ mutex_lock(&lcd->lcd_drv->power_mutex);
+ aml_lcd_notifier_call_chain(LCD_EVENT_UNPREPARE, NULL);
+ mutex_unlock(&lcd->lcd_drv->power_mutex);
+
+ return 0;
+}
+
+static int am_lcd_prepare(struct drm_panel *panel)
+{
+ struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+ if (!lcd)
+ return -ENODEV;
+ if (!lcd->lcd_drv)
+ return -ENODEV;
+
+ mutex_lock(&lcd->lcd_drv->power_mutex);
+ aml_lcd_notifier_call_chain(LCD_EVENT_PREPARE, NULL);
+ mutex_unlock(&lcd->lcd_drv->power_mutex);
+
+ return 0;
+}
+
+static int am_lcd_enable(struct drm_panel *panel)
+{
+ struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+ if (!lcd)
+ return -ENODEV;
+ if (!lcd->lcd_drv)
+ return -ENODEV;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ mutex_lock(&lcd->lcd_drv->power_mutex);
+ aml_lcd_notifier_call_chain(LCD_EVENT_ENABLE, NULL);
+ mutex_unlock(&lcd->lcd_drv->power_mutex);
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ return 0;
+}
+
+static int am_lcd_get_modes(struct drm_panel *panel)
+{
+ struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+ struct drm_connector *connector = panel->connector;
+ struct drm_device *drm = panel->drm;
+ struct drm_display_mode *mode;
+ struct lcd_config_s *pconf;
+
+ if (!lcd->mode)
+ return 0;
+
+ mode = drm_mode_duplicate(drm, lcd->mode);
+ if (!mode)
+ return 0;
+
+ mode->type |= DRM_MODE_TYPE_DRIVER;
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_set_name(mode);
+
+ drm_mode_probed_add(connector, mode);
+
+ pconf = lcd->lcd_drv->lcd_config;
+ connector->display_info.bpc = pconf->lcd_basic.lcd_bits * 3;
+ connector->display_info.width_mm = pconf->lcd_basic.screen_width;
+ connector->display_info.height_mm = pconf->lcd_basic.screen_height;
+
+ connector->display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ return 1;
+}
+
+static int am_lcd_get_timings(struct drm_panel *panel,
+ unsigned int num_timings,
+ struct display_timing *timings)
+{
+ struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+ if (!lcd)
+ return 0;
+ if (!lcd->timing)
+ return 0;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ if (timings)
+ memcpy(&timings[0], lcd->timing, sizeof(struct display_timing));
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs am_drm_lcd_funcs = {
+ .disable = am_lcd_disable,
+ .unprepare = am_lcd_unprepare,
+ .prepare = am_lcd_prepare,
+ .enable = am_lcd_enable,
+ .get_modes = am_lcd_get_modes,
+ .get_timings = am_lcd_get_timings,
+};
+
+static void am_drm_lcd_display_mode_timing_init(struct am_drm_lcd_s *lcd)
+{
+ struct lcd_config_s *pconf;
+ unsigned short tmp;
+
+ if (!lcd->lcd_drv) {
+ pr_info("invalid lcd driver\n");
+ return;
+ }
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ pconf = lcd->lcd_drv->lcd_config;
+
+ lcd->mode = &am_lcd_mode;
+ lcd->timing = &am_lcd_timing;
+
+ lcd->mode->clock = pconf->lcd_timing.lcd_clk / 1000;
+ lcd->mode->hdisplay = pconf->lcd_basic.h_active;
+ tmp = pconf->lcd_basic.h_period - pconf->lcd_basic.h_active -
+ pconf->lcd_timing.hsync_bp;
+ lcd->mode->hsync_start = pconf->lcd_basic.h_active + tmp -
+ pconf->lcd_timing.hsync_width;
+ lcd->mode->hsync_end = pconf->lcd_basic.h_active + tmp;
+ lcd->mode->htotal = pconf->lcd_basic.h_period;
+ lcd->mode->vdisplay = pconf->lcd_basic.v_active;
+ tmp = pconf->lcd_basic.v_period - pconf->lcd_basic.v_active -
+ pconf->lcd_timing.vsync_bp;
+ lcd->mode->vsync_start = pconf->lcd_basic.v_active + tmp -
+ pconf->lcd_timing.vsync_width;
+ lcd->mode->vsync_end = pconf->lcd_basic.v_active + tmp;
+ lcd->mode->vtotal = pconf->lcd_basic.v_period;
+ lcd->mode->width_mm = pconf->lcd_basic.screen_width;
+ lcd->mode->height_mm = pconf->lcd_basic.screen_height;
+ lcd->mode->vrefresh = pconf->lcd_timing.sync_duration_num /
+ pconf->lcd_timing.sync_duration_den;
+
+ lcd->timing->pixelclock.min = pconf->lcd_timing.lcd_clk;
+ lcd->timing->pixelclock.typ = pconf->lcd_timing.lcd_clk;
+ lcd->timing->pixelclock.max = pconf->lcd_timing.lcd_clk;
+ lcd->timing->hactive.min = pconf->lcd_basic.h_active;
+ lcd->timing->hactive.typ = pconf->lcd_basic.h_active;
+ lcd->timing->hactive.max = pconf->lcd_basic.h_active;
+ tmp = pconf->lcd_basic.h_period - pconf->lcd_basic.h_active -
+ pconf->lcd_timing.hsync_bp - pconf->lcd_timing.hsync_width;
+ lcd->timing->hfront_porch.min = tmp;
+ lcd->timing->hfront_porch.typ = tmp;
+ lcd->timing->hfront_porch.max = tmp;
+ lcd->timing->hback_porch.min = pconf->lcd_timing.hsync_bp;
+ lcd->timing->hback_porch.typ = pconf->lcd_timing.hsync_bp;
+ lcd->timing->hback_porch.max = pconf->lcd_timing.hsync_bp;
+ lcd->timing->hsync_len.min = pconf->lcd_timing.hsync_width;
+ lcd->timing->hsync_len.typ = pconf->lcd_timing.hsync_width;
+ lcd->timing->hsync_len.max = pconf->lcd_timing.hsync_width;
+ lcd->timing->vactive.min = pconf->lcd_basic.v_active;
+ lcd->timing->vactive.typ = pconf->lcd_basic.v_active;
+ lcd->timing->vactive.max = pconf->lcd_basic.v_active;
+ tmp = pconf->lcd_basic.v_period - pconf->lcd_basic.v_active -
+ pconf->lcd_timing.vsync_bp - pconf->lcd_timing.vsync_width;
+ lcd->timing->vfront_porch.min = tmp;
+ lcd->timing->vfront_porch.typ = tmp;
+ lcd->timing->vfront_porch.max = tmp;
+ lcd->timing->vback_porch.min = pconf->lcd_timing.vsync_bp;
+ lcd->timing->vback_porch.typ = pconf->lcd_timing.vsync_bp;
+ lcd->timing->vback_porch.max = pconf->lcd_timing.vsync_bp;
+ lcd->timing->vsync_len.min = pconf->lcd_timing.vsync_width;
+ lcd->timing->vsync_len.typ = pconf->lcd_timing.vsync_width;
+ lcd->timing->vsync_len.max = pconf->lcd_timing.vsync_width;
+
+ pr_info("am_drm_lcd: %s: lcd config:\n"
+ "lcd_clk %d\n"
+ "h_active %d\n"
+ "v_active %d\n"
+ "screen_width %d\n"
+ "screen_height %d\n"
+ "sync_duration_den %d\n"
+ "sync_duration_num %d\n",
+ __func__,
+ lcd->lcd_drv->lcd_config->lcd_timing.lcd_clk,
+ lcd->lcd_drv->lcd_config->lcd_basic.h_active,
+ lcd->lcd_drv->lcd_config->lcd_basic.v_active,
+ lcd->lcd_drv->lcd_config->lcd_basic.screen_width,
+ lcd->lcd_drv->lcd_config->lcd_basic.screen_height,
+ lcd->lcd_drv->lcd_config->lcd_timing.sync_duration_den,
+ lcd->lcd_drv->lcd_config->lcd_timing.sync_duration_num);
+ pr_info("am_drm_lcd: %s: display mode:\n"
+ "clock %d\n"
+ "hdisplay %d\n"
+ "vdisplay %d\n"
+ "width_mm %d\n"
+ "height_mm %d\n"
+ "vrefresh %d\n",
+ __func__,
+ lcd->mode->clock,
+ lcd->mode->hdisplay,
+ lcd->mode->vdisplay,
+ lcd->mode->width_mm,
+ lcd->mode->height_mm,
+ lcd->mode->vrefresh);
+ pr_info("am_drm_lcd: %s: timing:\n"
+ "pixelclock %d\n"
+ "hactive %d\n"
+ "vactive %d\n",
+ __func__,
+ lcd->timing->pixelclock.typ,
+ lcd->timing->hactive.typ,
+ lcd->timing->vactive.typ);
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static const struct of_device_id am_meson_lcd_dt_ids[] = {
+ { .compatible = "amlogic,drm-lcd", },
+ {},
+};
+
+static int am_meson_lcd_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_device *drm = data;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+ int encoder_type, connector_type;
+ int ret = 0;
+
+ am_drm_lcd = kzalloc(sizeof(*am_drm_lcd), GFP_KERNEL);
+ if (!am_drm_lcd)
+ return -ENOMEM;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ am_drm_lcd->lcd_drv = aml_lcd_get_driver();
+ if (!am_drm_lcd->lcd_drv) {
+ pr_err("invalid lcd driver, exit\n");
+ return -ENODEV;
+ }
+
+ am_drm_lcd_display_mode_timing_init(am_drm_lcd);
+
+ drm_panel_init(&am_drm_lcd->panel);
+ am_drm_lcd->panel.dev = NULL;
+ am_drm_lcd->panel.funcs = &am_drm_lcd_funcs;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ ret = drm_panel_add(&am_drm_lcd->panel);
+ if (ret < 0)
+ return ret;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ am_drm_lcd->drm = drm;
+
+ encoder = &am_drm_lcd->encoder;
+ connector = &am_drm_lcd->connector;
+ encoder_type = DRM_MODE_ENCODER_LVDS;
+ connector_type = DRM_MODE_CONNECTOR_LVDS;
+
+ /* Encoder */
+ drm_encoder_helper_add(encoder, &am_lcd_encoder_helper_funcs);
+ ret = drm_encoder_init(drm, encoder, &am_lcd_encoder_funcs,
+ encoder_type, "am_lcd_encoder");
+ if (ret) {
+ pr_err("error: am_drm_lcd: Failed to init lcd encoder\n");
+ return ret;
+ }
+ pr_info("am_drm_lcd: %s %d: encoder possible_crtcs=%d\n",
+ __func__, __LINE__, encoder->possible_crtcs);
+
+ /* Connector */
+ drm_connector_helper_add(connector, &am_lcd_connector_helper_funcs);
+ ret = drm_connector_init(drm, connector, &am_lcd_connector_funcs,
+ connector_type);
+ if (ret) {
+ pr_err("error: am_drm_lcd: Failed to init lcd connector\n");
+ return ret;
+ }
+
+ /* force possible_crtcs */
+ encoder->possible_crtcs = BIT(0);
+
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ pr_info("am_drm_lcd: register ok\n");
+
+ return ret;
+}
+
+static void am_meson_lcd_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ if (!am_drm_lcd)
+ return;
+
+ if (!am_drm_lcd->lcd_drv)
+ return;
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+ drm_panel_detach(&am_drm_lcd->panel);
+ drm_panel_remove(&am_drm_lcd->panel);
+
+ pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static const struct component_ops am_meson_lcd_ops = {
+ .bind = am_meson_lcd_bind,
+ .unbind = am_meson_lcd_unbind,
+};
+
+static int am_meson_lcd_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &am_meson_lcd_ops);
+}
+
+static int am_meson_lcd_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &am_meson_lcd_ops);
+ return 0;
+}
+
+static struct platform_driver am_meson_lcd_pltfm_driver = {
+ .probe = am_meson_lcd_probe,
+ .remove = am_meson_lcd_remove,
+ .driver = {
+ .name = "meson-lcd",
+ .of_match_table = am_meson_lcd_dt_ids,
+ },
+};
+
+module_platform_driver(am_meson_lcd_pltfm_driver);
+
+MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>");
+MODULE_DESCRIPTION("Amlogic Meson Drm LCD driver");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_lcd.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AM_DRM_LCD_H
+#define __AM_DRM_LCD_H
+
+#include "meson_drv.h"
+
+#endif
+
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_plane.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_plane.h"
+#include "meson_crtc.h"
+#include "meson_vpu.h"
+#include "meson_drv.h"
+#include "meson_vpu_pipeline.h"
+
+static const u32 supported_drm_formats[] = {
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_RGBX8888,
+ DRM_FORMAT_BGRX8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_RGBA8888,
+ DRM_FORMAT_BGRA8888,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_ARGB1555,
+ DRM_FORMAT_ARGB4444,
+};
+
+static u64 afbc_wb_modifier[] = {
+ DRM_FORMAT_MOD_MESON_AFBC_WB,
+ DRM_FORMAT_MOD_LINEAR,
+ DRM_FORMAT_MOD_INVALID
+};
+
+static void meson_plane_position_calc(
+ struct meson_vpu_osd_layer_info *plane_info,
+ struct drm_plane_state *state,
+ struct drm_display_mode *mode)
+{
+ u32 dst_w, dst_h, src_w, src_h, scan_mode_out;
+
+ scan_mode_out = mode->flags & DRM_MODE_FLAG_INTERLACE;
+ plane_info->src_x = state->src_x;
+ plane_info->src_y = state->src_y;
+ plane_info->src_w = (state->src_w >> 16) & 0xffff;
+ plane_info->src_h = (state->src_h >> 16) & 0xffff;
+
+ plane_info->dst_x = state->crtc_x;
+ plane_info->dst_y = state->crtc_y;
+ plane_info->dst_w = state->crtc_w;
+ plane_info->dst_h = state->crtc_h;
+ if (scan_mode_out) {
+ plane_info->dst_y >>= 1;
+ plane_info->dst_h >>= 1;
+ }
+ /*negative position process*/
+ if (state->crtc_x < 0) {
+ dst_w = state->crtc_w + state->crtc_x;
+ if (dst_w > 0) {
+ src_w = plane_info->src_w * dst_w / state->crtc_w;
+ plane_info->src_x = plane_info->src_w - src_w;
+ plane_info->src_w = src_w;
+ plane_info->dst_w = dst_w;
+ plane_info->dst_x = 0;
+ } else {
+ plane_info->enable = 0;
+ }
+ }
+ if (state->crtc_y < 0) {
+ dst_h = state->crtc_h + state->crtc_y;
+ if (dst_h > 0) {
+ src_h = plane_info->src_h * dst_h / state->crtc_h;
+ plane_info->src_y = plane_info->src_h - src_h;
+ plane_info->src_h = src_h;
+ plane_info->dst_h = dst_h;
+ plane_info->dst_y = 0;
+ } else {
+ plane_info->enable = 0;
+ }
+ }
+ /*overdisplay process*/
+ if ((plane_info->dst_x + plane_info->dst_w) > mode->hdisplay) {
+ if (plane_info->dst_x >= mode->hdisplay)
+ plane_info->enable = 0;
+ else
+ plane_info->dst_w =
+ mode->hdisplay - plane_info->dst_x;
+ }
+ if ((plane_info->dst_y + plane_info->dst_h) > mode->vdisplay) {
+ if (plane_info->dst_y >= mode->vdisplay)
+ plane_info->enable = 0;
+ else
+ plane_info->dst_h = mode->vdisplay - plane_info->dst_y;
+ }
+}
+
+static int
+meson_plane_check_size_range(struct meson_vpu_osd_layer_info *plane_info)
+{
+ u32 dst_w, dst_h, src_w, src_h, ratio_x, ratio_y;
+ int ret;
+
+ src_w = plane_info->src_w;
+ src_h = plane_info->src_h;
+ dst_w = plane_info->dst_w;
+ dst_h = plane_info->dst_h;
+ ratio_x = 0;
+ ratio_y = 0;
+ ret = 0;
+
+ if (src_w > dst_w)
+ ratio_x = (src_w + dst_w - 1) / dst_w;
+ if (src_h > dst_h)
+ ratio_y = (src_h + dst_h - 1) / dst_h;
+ if (ratio_x > MESON_OSD_SCLAE_DOWN_LIMIT ||
+ ratio_y > MESON_OSD_SCLAE_DOWN_LIMIT)
+ ret = -EDOM;
+ if (src_w < dst_w)
+ ratio_x = (dst_w + src_w - 1) / src_w;
+ if (src_h < dst_h)
+ ratio_y = (dst_h + src_h - 1) / src_h;
+ if (ratio_x > MESON_OSD_SCLAE_UP_LIMIT ||
+ ratio_y > MESON_OSD_SCLAE_UP_LIMIT)
+ ret = -EDOM;
+ return ret;
+}
+
+static int meson_plane_fb_check(struct drm_plane *plane,
+ struct drm_plane_state *new_state,
+ struct meson_vpu_osd_layer_info *plane_info)
+{
+ struct drm_framebuffer *fb = new_state->fb;
+ #ifdef CONFIG_DRM_MESON_USE_ION
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+ struct meson_drm *drv = osd_plane->drv;
+ struct am_meson_fb *meson_fb;
+ #else
+ struct drm_gem_cma_object *gem;
+ #endif
+ dma_addr_t phyaddr;
+
+ #ifdef CONFIG_DRM_MESON_USE_ION
+ meson_fb = container_of(fb, struct am_meson_fb, base);
+ if (!meson_fb) {
+ DRM_INFO("meson_fb is NULL!\n");
+ return -EINVAL;
+ }
+ phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
+ if (meson_fb->bufp->bscatter)
+ DRM_ERROR("am_meson_plane meet a scatter framebuffer.\n");
+ #else
+ if (!fb) {
+ DRM_INFO("fb is NULL!\n");
+ return -EINVAL;
+ }
+ /* Update Canvas with buffer address */
+ gem = drm_fb_cma_get_gem_obj(fb, 0);
+ if (!gem) {
+ DRM_INFO("gem is NULL!\n");
+ return -EINVAL;
+ }
+ phyaddr = gem->paddr;
+ #endif
+ plane_info->phy_addr = phyaddr;
+ return 0;
+}
+
+static int meson_plane_get_fb_info(struct drm_plane *plane,
+ struct drm_plane_state *new_state,
+ struct meson_vpu_osd_layer_info *plane_info)
+{
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+ struct drm_framebuffer *fb = new_state->fb;
+ struct meson_drm *drv = osd_plane->drv;
+ #ifdef CONFIG_DRM_MESON_USE_ION
+ struct am_meson_fb *meson_fb;
+ #else
+ struct drm_gem_cma_object *gem;
+ #endif
+ dma_addr_t phyaddr;
+
+ if (!drv) {
+ DRM_INFO("%s new_state/meson_drm is NULL!\n", __func__);
+ return -EINVAL;
+ }
+ if (osd_plane->plane_index >= MESON_MAX_OSDS) {
+ DRM_INFO("%s invalid plane_index!\n", __func__);
+ return -EINVAL;
+ }
+
+ #ifdef CONFIG_DRM_MESON_USE_ION
+ meson_fb = container_of(fb, struct am_meson_fb, base);
+ if (!meson_fb) {
+ DRM_INFO("meson_fb is NULL!\n");
+ return 0;
+ }
+ phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
+ if (meson_fb->bufp->bscatter)
+ DRM_ERROR("ERROR:am_meson_plane meet a scatter framebuffer.\n");
+ #else
+ if (!fb) {
+ DRM_INFO("fb is NULL!\n");
+ return -EINVAL;
+ }
+ /* Update Canvas with buffer address */
+ gem = drm_fb_cma_get_gem_obj(fb, 0);
+ phyaddr = gem->paddr;
+ #endif
+
+ plane_info->pixel_format = fb->pixel_format;
+ plane_info->phy_addr = phyaddr;
+ plane_info->byte_stride = fb->pitches[0];
+
+ /*setup afbc info*/
+ switch (fb->modifier) {
+ case DRM_FORMAT_MOD_MESON_AFBC:
+ plane_info->afbc_en = 1;
+ plane_info->afbc_inter_format = AFBC_EN;
+ break;
+ case DRM_FORMAT_MOD_MESON_AFBC_WB:
+ plane_info->afbc_en = 1;
+ plane_info->afbc_inter_format = AFBC_EN |
+ YUV_TRANSFORM | BLOCK_SPLIT |
+ SUPER_BLOCK_ASPECT;
+ break;
+ case DRM_FORMAT_MOD_INVALID:
+ case DRM_FORMAT_MOD_LINEAR:
+ default:
+ plane_info->afbc_en = 0;
+ plane_info->afbc_inter_format = 0;
+ break;
+ };
+
+ DRM_DEBUG("flags:%d pixel_format:%d,modifer=%llu\n",
+ fb->flags, fb->pixel_format,
+ fb->modifier);
+ DRM_DEBUG("plane afbc_en=%u, afbc_inter_format=%x\n",
+ plane_info->afbc_en, plane_info->afbc_inter_format);
+
+ DRM_DEBUG("phy_addr=0x%x,byte_stride=%d,pixel_format=%d\n",
+ plane_info->phy_addr, plane_info->byte_stride,
+ plane_info->pixel_format);
+ DRM_DEBUG("plane_index %d.\n", osd_plane->plane_index);
+ return 0;
+}
+
+static int meson_plane_atomic_get_property(struct drm_plane *plane,
+ const struct drm_plane_state *state,
+ struct drm_property *property,
+ uint64_t *val)
+{
+ return 0;
+}
+
+static int meson_plane_atomic_set_property(struct drm_plane *plane,
+ struct drm_plane_state *state,
+ struct drm_property *property,
+ uint64_t val)
+{
+ return 0;
+}
+
+static struct drm_plane_state *
+meson_plane_duplicate_state(struct drm_plane *plane)
+{
+ struct am_meson_plane_state *meson_plane_state, *old_plane_state;
+
+ if (WARN_ON(!plane->state))
+ return NULL;
+
+ old_plane_state = to_am_meson_plane_state(plane->state);
+ meson_plane_state = kmemdup(old_plane_state,
+ sizeof(*meson_plane_state), GFP_KERNEL);
+ if (!meson_plane_state)
+ return NULL;
+
+ __drm_atomic_helper_plane_duplicate_state(plane,
+ &meson_plane_state->base);
+
+ return &meson_plane_state->base;
+}
+
+static void meson_plane_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct am_meson_plane_state *amps;
+
+ amps = to_am_meson_plane_state(state);
+ __drm_atomic_helper_plane_destroy_state(state);
+ kfree(amps);
+}
+
+bool am_meson_vpu_check_format_mod(struct drm_plane *plane,
+ u32 format, u64 modifier)
+{
+ bool ret = false;
+
+ switch (modifier) {
+ case DRM_FORMAT_MOD_LINEAR:
+ ret = true;
+ break;
+ case DRM_FORMAT_MOD_MESON_AFBC:
+ if (osd_meson_dev.afbc_type == MESON_AFBC &&
+ plane->type == DRM_PLANE_TYPE_PRIMARY)
+ ret = true;
+ break;
+ case DRM_FORMAT_MOD_MESON_AFBC_WB:
+ if (osd_meson_dev.afbc_type == MALI_AFBC &&
+ plane->type == DRM_PLANE_TYPE_PRIMARY) {
+ if (format == DRM_FORMAT_BGR565)
+ ret = false;
+ else
+ ret = true;
+ }
+ break;
+ };
+
+ DRM_DEBUG("modifier %llu return %d",
+ modifier, ret);
+ return ret;
+}
+
+static const struct drm_plane_funcs am_osd_plane_funs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_plane_cleanup,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = meson_plane_duplicate_state,
+ .atomic_destroy_state = meson_plane_destroy_state,
+ .atomic_set_property = meson_plane_atomic_set_property,
+ .atomic_get_property = meson_plane_atomic_get_property,
+ .format_mod_supported = am_meson_vpu_check_format_mod,
+};
+
+static int meson_plane_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
+{
+ return 0;
+}
+
+static void meson_plane_cleanup_fb(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+
+ DRM_DEBUG("%s osd %d.\n", __func__, osd_plane->plane_index);
+}
+
+static void meson_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ DRM_DEBUG("plane atomic_update.\n");
+}
+
+static int meson_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline_state *mvps;
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+ struct meson_drm *drv = osd_plane->drv;
+ int ret;
+
+ if (!state || !drv) {
+ DRM_INFO("%s state/meson_drm is NULL!\n", __func__);
+ return -EINVAL;
+ }
+ mvps = meson_vpu_pipeline_get_state(drv->pipeline, state->state);
+ if (!mvps || osd_plane->plane_index >= MESON_MAX_OSDS) {
+ DRM_INFO("%s mvps/osd_plane is NULL!\n", __func__);
+ return -EINVAL;
+ }
+ plane_info = &mvps->plane_info[osd_plane->plane_index];
+ plane_info->plane_index = osd_plane->plane_index;
+ plane_info->zorder = state->zpos;
+
+ mvps->plane_index[osd_plane->plane_index] = osd_plane->plane_index;
+ meson_plane_position_calc(plane_info, state, &mvps->pipeline->mode);
+ ret = meson_plane_check_size_range(plane_info);
+ if (ret < 0) {
+ plane_info->enable = 0;
+ DRM_INFO("plane%d size check unsupport!!!\n",
+ plane_info->plane_index);
+ return ret;
+ }
+ ret = meson_plane_fb_check(plane, state, plane_info);
+ if (ret < 0) {
+ plane_info->enable = 0;
+ DRM_DEBUG("plane%d fb is NULL,disable the plane!\n",
+ plane_info->plane_index);
+ return 0;
+ }
+ ret = meson_plane_get_fb_info(plane, state, plane_info);
+ if (ret < 0 || plane_info->src_w > MESON_OSD_INPUT_W_LIMIT ||
+ plane_info->src_w == 0) {
+ plane_info->enable = 0;
+ return ret;
+ }
+
+ plane_info->enable = 1;
+ DRM_DEBUG("index=%d, zorder=%d\n",
+ plane_info->plane_index, plane_info->zorder);
+ DRM_DEBUG("src_x/y/w/h=%d/%d/%d/%d\n",
+ plane_info->src_x, plane_info->src_y,
+ plane_info->src_w, plane_info->src_h);
+ DRM_DEBUG("dst_x/y/w/h=%d/%d/%d/%d\n",
+ plane_info->dst_x, plane_info->dst_y,
+ plane_info->dst_w, plane_info->dst_h);
+ return 0;
+}
+
+static void meson_plane_atomic_disable(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+
+ DRM_DEBUG("%s osd %d.\n", __func__, osd_plane->plane_index);
+}
+
+static const struct drm_plane_helper_funcs am_osd_helper_funcs = {
+ .prepare_fb = meson_plane_prepare_fb,
+ .cleanup_fb = meson_plane_cleanup_fb,
+ .atomic_update = meson_plane_atomic_update,
+ .atomic_check = meson_plane_atomic_check,
+ .atomic_disable = meson_plane_atomic_disable,
+};
+
+static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i)
+{
+ struct am_osd_plane *osd_plane;
+ struct drm_plane *plane;
+ u32 type = 0;
+ char plane_name[8];
+ const u64 *format_modifiers = afbc_wb_modifier;
+
+ osd_plane = devm_kzalloc(priv->drm->dev, sizeof(*osd_plane),
+ GFP_KERNEL);
+ if (!osd_plane)
+ return 0;
+
+ if (i == 0)
+ type = DRM_PLANE_TYPE_PRIMARY;
+ else
+ type = DRM_PLANE_TYPE_OVERLAY;
+
+ osd_plane->drv = priv;
+ osd_plane->plane_index = i;
+
+ plane = &osd_plane->base;
+ sprintf(plane_name, "osd%d", i);
+
+ drm_universal_plane_init(priv->drm, plane, 0xFF,
+ &am_osd_plane_funs,
+ supported_drm_formats,
+ ARRAY_SIZE(supported_drm_formats),
+ format_modifiers,
+ type, plane_name);
+
+ drm_plane_helper_add(plane, &am_osd_helper_funcs);
+ osd_drm_debugfs_add(&osd_plane->plane_debugfs_dir,
+ plane_name, osd_plane->plane_index);
+ return osd_plane;
+}
+
+int am_meson_plane_create(struct meson_drm *priv)
+{
+ struct am_osd_plane *plane;
+ struct meson_vpu_pipeline *pipeline = priv->pipeline;
+ int i, osd_index;
+
+
+ for (i = 0; i < pipeline->num_osds; i++) {
+ osd_index = pipeline->osds[i]->base.index;
+ plane = am_plane_create(priv, osd_index);
+
+ if (!plane)
+ return -ENOMEM;
+
+ if (i == 0)
+ priv->primary_plane = &plane->base;
+
+ priv->planes[priv->num_planes++] = plane;
+ }
+
+ DRM_DEBUG("%s. enter\n", __func__);
+
+ return 0;
+}
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_plane.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_PLANE_H
+#define __MESON_PLANE_H
+
+#include <linux/kernel.h>
+#include <drm/drmP.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+
+#include "osd.h"
+#include "osd_drm.h"
+#include "meson_fb.h"
+
+struct am_meson_plane_state {
+ struct drm_plane_state base;
+};
+
+struct am_osd_plane {
+ struct drm_plane base; //must be first element.
+ struct meson_drm *drv; //point to struct parent.
+ struct dentry *plane_debugfs_dir;
+ int plane_index;
+};
+
+#define to_am_osd_plane(x) container_of(x, \
+ struct am_osd_plane, base)
+#define to_am_meson_plane_state(x) container_of(x, \
+ struct am_meson_plane_state, base)
+
+int am_meson_plane_create(struct meson_drm *priv);
+
+#endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_vpu.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/component.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/dma-contiguous.h>
+#include <linux/cma.h>
+#ifdef CONFIG_DRM_MESON_USE_ION
+#include <ion/ion_priv.h>
+#endif
+
+/* Amlogic Headers */
+#include <linux/amlogic/media/vout/vout_notify.h>
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+#include <linux/amlogic/media/amvecm/amvecm.h>
+#endif
+#include "osd.h"
+#include "osd_drm.h"
+#ifdef CONFIG_DRM_MESON_USE_ION
+#include "meson_fb.h"
+#endif
+#include "meson_vpu.h"
+#include "meson_plane.h"
+#include "meson_crtc.h"
+#include "meson_vpu_pipeline.h"
+
+struct vpu_device_data_s {
+ enum cpuid_type_e cpu_id;
+ enum osd_ver_e osd_ver;
+ enum osd_afbc_e afbc_type;
+ u8 osd_count;
+ u8 has_deband;
+ u8 has_lut;
+ u8 has_rdma;
+ u8 osd_fifo_len;
+ u32 vpp_fifo_len;
+ u32 dummy_data;
+ u32 has_viu2;
+ u32 viu1_osd_count;
+ struct clk *vpu_clkc;
+};
+
+static struct am_vout_mode am_vout_modes[] = {
+ { "1080p60hz", VMODE_HDMI, 1920, 1080, 60, 0},
+ { "1080p30hz", VMODE_HDMI, 1920, 1080, 30, 0},
+ { "1080p50hz", VMODE_HDMI, 1920, 1080, 50, 0},
+ { "1080p25hz", VMODE_HDMI, 1920, 1080, 25, 0},
+ { "1080p24hz", VMODE_HDMI, 1920, 1080, 24, 0},
+ { "2160p30hz", VMODE_HDMI, 3840, 2160, 30, 0},
+ { "2160p60hz", VMODE_HDMI, 3840, 2160, 60, 0},
+ { "2160p50hz", VMODE_HDMI, 3840, 2160, 50, 0},
+ { "2160p25hz", VMODE_HDMI, 3840, 2160, 25, 0},
+ { "2160p24hz", VMODE_HDMI, 3840, 2160, 24, 0},
+ { "1080i60hz", VMODE_HDMI, 1920, 1080, 60, DRM_MODE_FLAG_INTERLACE},
+ { "1080i50hz", VMODE_HDMI, 1920, 1080, 50, DRM_MODE_FLAG_INTERLACE},
+ { "720p60hz", VMODE_HDMI, 1280, 720, 60, 0},
+ { "720p50hz", VMODE_HDMI, 1280, 720, 50, 0},
+ { "480p60hz", VMODE_HDMI, 720, 480, 60, 0},
+ { "480i60hz", VMODE_HDMI, 720, 480, 60, DRM_MODE_FLAG_INTERLACE},
+ { "576p50hz", VMODE_HDMI, 720, 576, 50, 0},
+ { "576i50hz", VMODE_HDMI, 720, 576, 50, DRM_MODE_FLAG_INTERLACE},
+ { "480p60hz", VMODE_HDMI, 720, 480, 60, 0},
+};
+
+
+static struct osd_device_data_s osd_gxbb = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_GXBB,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = NO_AFBC,
+ .osd_count = 2,
+ .has_deband = 0,
+ .has_lut = 0,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 32,
+ .vpp_fifo_len = 0x77f,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_gxl = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_GXL,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = NO_AFBC,
+ .osd_count = 2,
+ .has_deband = 0,
+ .has_lut = 0,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 32,
+ .vpp_fifo_len = 0x77f,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_gxm = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_GXM,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = MESON_AFBC,
+ .osd_count = 2,
+ .has_deband = 0,
+ .has_lut = 0,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 32,
+ .vpp_fifo_len = 0xfff,
+ .dummy_data = 0x00202000,/* dummy data is different */
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_txl = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_TXL,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = NO_AFBC,
+ .osd_count = 2,
+ .has_deband = 0,
+ .has_lut = 0,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 64,
+ .vpp_fifo_len = 0x77f,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_txlx = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_TXLX,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = NO_AFBC,
+ .osd_count = 2,
+ .has_deband = 1,
+ .has_lut = 1,
+ .has_rdma = 1,
+ .has_dolby_vision = 1,
+ .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
+ .vpp_fifo_len = 0x77f,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_axg = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_AXG,
+ .osd_ver = OSD_SIMPLE,
+ .afbc_type = NO_AFBC,
+ .osd_count = 1,
+ .has_deband = 1,
+ .has_lut = 1,
+ .has_rdma = 0,
+ .has_dolby_vision = 0,
+ /* use iomap its self, no rdma, no canvas, no freescale */
+ .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
+ .vpp_fifo_len = 0x400,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_g12a = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_G12A,
+ .osd_ver = OSD_HIGH_ONE,
+ .afbc_type = MALI_AFBC,
+ .osd_count = 4,
+ .has_deband = 1,
+ .has_lut = 1,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
+ .vpp_fifo_len = 0xfff,/* 2048 */
+ .dummy_data = 0x00808000,
+ .has_viu2 = 1,
+};
+
+static struct osd_device_data_s osd_g12b = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_G12B,
+ .osd_ver = OSD_HIGH_ONE,
+ .afbc_type = MALI_AFBC,
+ .osd_count = 4,
+ .has_deband = 1,
+ .has_lut = 1,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
+ .vpp_fifo_len = 0xfff,/* 2048 */
+ .dummy_data = 0x00808000,
+ .has_viu2 = 1,
+};
+
+struct osd_device_data_s osd_meson_dev;
+static u32 logo_memsize;
+static struct page *logo_page;
+static struct delayed_work osd_dwork;
+static struct platform_device *gp_dev;
+static unsigned long gem_mem_start, gem_mem_size;
+
+int am_meson_crtc_dts_info_set(const void *dt_match_data)
+{
+ struct osd_device_data_s *osd_meson;
+
+ osd_meson = (struct osd_device_data_s *)dt_match_data;
+ if (osd_meson) {
+ memcpy(&osd_meson_dev, osd_meson,
+ sizeof(struct osd_device_data_s));
+ osd_meson_dev.viu1_osd_count = osd_meson_dev.osd_count;
+ if (osd_meson_dev.has_viu2) {
+ /* set viu1 osd count */
+ osd_meson_dev.viu1_osd_count--;
+ osd_meson_dev.viu2_index = osd_meson_dev.viu1_osd_count;
+ }
+ } else {
+ DRM_ERROR("%s data NOT match\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int am_meson_crtc_loader_protect(struct drm_crtc *crtc, bool on)
+{
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+
+ DRM_INFO("%s %d\n", __func__, on);
+
+ if (on) {
+ enable_irq(amcrtc->vblank_irq);
+ drm_crtc_vblank_on(crtc);
+ } else {
+ disable_irq(amcrtc->vblank_irq);
+ drm_crtc_vblank_off(crtc);
+ }
+
+ return 0;
+}
+
+static int am_meson_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+ unsigned long flags;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ amcrtc->vblank_enable = true;
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+
+ return 0;
+}
+
+static void am_meson_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+ unsigned long flags;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ amcrtc->vblank_enable = false;
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+}
+
+const struct meson_crtc_funcs meson_private_crtc_funcs = {
+ .loader_protect = am_meson_crtc_loader_protect,
+ .enable_vblank = am_meson_crtc_enable_vblank,
+ .disable_vblank = am_meson_crtc_disable_vblank,
+};
+
+char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode)
+{
+ int i;
+
+ if (!strcmp(mode->name, "panel"))
+ return "panel";
+
+ for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) {
+ if (am_vout_modes[i].width == mode->hdisplay &&
+ am_vout_modes[i].height == mode->vdisplay &&
+ am_vout_modes[i].vrefresh == mode->vrefresh &&
+ am_vout_modes[i].flags ==
+ (mode->flags & DRM_MODE_FLAG_INTERLACE))
+ return am_vout_modes[i].name;
+ }
+ return NULL;
+}
+
+void am_meson_crtc_handle_vsync(struct am_meson_crtc *amcrtc)
+{
+ unsigned long flags;
+ struct drm_crtc *crtc;
+
+ crtc = &amcrtc->base;
+ drm_crtc_handle_vblank(crtc);
+
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ if (amcrtc->event) {
+ drm_crtc_send_vblank_event(crtc, amcrtc->event);
+ drm_crtc_vblank_put(crtc);
+ amcrtc->event = NULL;
+ }
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+}
+
+void am_meson_crtc_irq(struct meson_drm *priv)
+{
+ unsigned long flags;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(priv->crtc);
+
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ if (amcrtc->vblank_enable) {
+ osd_drm_vsync_isr_handler();
+ am_meson_crtc_handle_vsync(amcrtc);
+ }
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+}
+
+static irqreturn_t am_meson_vpu_irq(int irq, void *arg)
+{
+ struct drm_device *dev = arg;
+ struct meson_drm *priv = dev->dev_private;
+
+ am_meson_crtc_irq(priv);
+
+ return IRQ_HANDLED;
+}
+
+static void mem_free_work(struct work_struct *work)
+{
+ if (logo_memsize > 0) {
+#ifdef CONFIG_CMA
+ pr_info("%s, free memory: addr:0x%x\n",
+ __func__, logo_memsize);
+
+ dma_release_from_contiguous(&gp_dev->dev,
+ logo_page,
+ logo_memsize >> PAGE_SHIFT);
+#endif
+ }
+}
+
+static int am_meson_vpu_bind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm_dev = data;
+ struct meson_drm *private = drm_dev->dev_private;
+ struct meson_vpu_pipeline *pipeline = private->pipeline;
+ struct am_meson_crtc *amcrtc;
+#ifdef CONFIG_CMA
+ struct cma *cma;
+#endif
+ int ret, irq;
+
+ /* Allocate crtc struct */
+ DRM_DEBUG("%s\n", __func__);
+ pr_info("[%s] in\n", __func__);
+ amcrtc = devm_kzalloc(dev, sizeof(*amcrtc),
+ GFP_KERNEL);
+ if (!amcrtc)
+ return -ENOMEM;
+
+ amcrtc->priv = private;
+ amcrtc->dev = dev;
+ amcrtc->drm_dev = drm_dev;
+
+ dev_set_drvdata(dev, amcrtc);
+
+ /* init reserved memory */
+ ret = of_reserved_mem_device_init(&pdev->dev);
+ if (ret != 0) {
+ dev_err(dev, "failed to init reserved memory\n");
+#ifdef CONFIG_CMA
+ gp_dev = pdev;
+ cma = dev_get_cma_area(&pdev->dev);
+ if (cma) {
+ logo_memsize = cma_get_size(cma);
+ pr_info("reserved memory base:0x%x, size:0x%x\n",
+ (u32)cma_get_base(cma), logo_memsize);
+ if (logo_memsize > 0) {
+ logo_page =
+ dma_alloc_from_contiguous(&pdev->dev,
+ logo_memsize >>
+ PAGE_SHIFT,
+ 0);
+ if (!logo_page) {
+ pr_err("allocate buffer failed:%d\n",
+ logo_memsize);
+ }
+ }
+ } else {
+ pr_info("------ NO CMA\n");
+ }
+#endif
+ } else {
+ dma_declare_coherent_memory(drm_dev->dev, gem_mem_start,
+ gem_mem_start, gem_mem_size,
+ DMA_MEMORY_EXCLUSIVE);
+ pr_info("meson drm mem_start = 0x%x, size = 0x%x\n",
+ (u32)gem_mem_start, (u32)gem_mem_size);
+ }
+
+ ret = am_meson_plane_create(private);
+ if (ret)
+ return ret;
+
+ ret = am_meson_crtc_create(amcrtc);
+ if (ret)
+ return ret;
+
+ am_meson_register_crtc_funcs(private->crtc, &meson_private_crtc_funcs);
+
+ ret = of_property_read_u8(dev->of_node,
+ "osd_ver", &pipeline->osd_version);
+ vpu_pipeline_init(pipeline);
+
+ /*vsync irq.*/
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "cannot find irq for vpu\n");
+ return irq;
+ }
+ amcrtc->vblank_irq = (unsigned int)irq;
+
+ spin_lock_init(&amcrtc->vblank_irq_lock);
+ amcrtc->vblank_enable = false;
+
+ ret = devm_request_irq(dev, amcrtc->vblank_irq, am_meson_vpu_irq,
+ IRQF_SHARED, dev_name(dev), drm_dev);
+ if (ret)
+ return ret;
+
+ disable_irq(amcrtc->vblank_irq);
+
+ INIT_DELAYED_WORK(&osd_dwork, mem_free_work);
+ schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000));
+ pr_info("[%s] out\n", __func__);
+ return 0;
+}
+
+static void am_meson_vpu_unbind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct drm_device *drm_dev = data;
+ struct meson_drm *private = drm_dev->dev_private;
+
+ am_meson_unregister_crtc_funcs(private->crtc);
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ amvecm_drm_gamma_disable(0);
+ am_meson_ctm_disable();
+#endif
+ osd_drm_debugfs_exit();
+}
+
+static const struct component_ops am_meson_vpu_component_ops = {
+ .bind = am_meson_vpu_bind,
+ .unbind = am_meson_vpu_unbind,
+};
+
+static const struct of_device_id am_meson_vpu_driver_dt_match[] = {
+ { .compatible = "amlogic,meson-gxbb-vpu",
+ .data = &osd_gxbb, },
+ { .compatible = "amlogic,meson-gxl-vpu",
+ .data = &osd_gxl, },
+ { .compatible = "amlogic,meson-gxm-vpu",
+ .data = &osd_gxm, },
+ { .compatible = "amlogic,meson-txl-vpu",
+ .data = &osd_txl, },
+ { .compatible = "amlogic,meson-txlx-vpu",
+ .data = &osd_txlx, },
+ { .compatible = "amlogic,meson-axg-vpu",
+ .data = &osd_axg, },
+ { .compatible = "amlogic,meson-g12a-vpu",
+ .data = &osd_g12a, },
+ { .compatible = "amlogic,meson-g12b-vpu",
+ .data = &osd_g12b, },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, am_meson_vpu_driver_dt_match);
+
+static int am_meson_vpu_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const void *vpu_data;
+ int ret;
+
+ pr_info("[%s] in\n", __func__);
+ if (!dev->of_node) {
+ dev_err(dev, "can't find vpu devices\n");
+ return -ENODEV;
+ }
+
+ vpu_data = of_device_get_match_data(dev);
+ if (vpu_data) {
+ ret = am_meson_crtc_dts_info_set(vpu_data);
+ if (ret < 0)
+ return -ENODEV;
+ } else {
+ dev_err(dev, "%s NOT match\n", __func__);
+ return -ENODEV;
+ }
+ pr_info("[%s] out\n", __func__);
+ return component_add(dev, &am_meson_vpu_component_ops);
+}
+
+static int am_meson_vpu_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &am_meson_vpu_component_ops);
+
+ return 0;
+}
+
+static struct platform_driver am_meson_vpu_platform_driver = {
+ .probe = am_meson_vpu_probe,
+ .remove = am_meson_vpu_remove,
+ .driver = {
+ .name = "meson-vpu",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(am_meson_vpu_driver_dt_match),
+ },
+};
+
+static int gem_mem_device_init(struct reserved_mem *rmem, struct device *dev)
+{
+ s32 ret = 0;
+
+ if (!rmem) {
+ pr_info("Can't get reverse mem!\n");
+ ret = -EFAULT;
+ return ret;
+ }
+ gem_mem_start = rmem->base;
+ gem_mem_size = rmem->size;
+ pr_info("init gem memsource addr:0x%x size:0x%x\n",
+ (u32)gem_mem_start, (u32)gem_mem_size);
+
+ return 0;
+}
+
+static const struct reserved_mem_ops rmem_gem_ops = {
+ .device_init = gem_mem_device_init,
+};
+
+static int __init gem_mem_setup(struct reserved_mem *rmem)
+{
+ rmem->ops = &rmem_gem_ops;
+ pr_info("gem mem setup\n");
+ return 0;
+}
+
+RESERVEDMEM_OF_DECLARE(gem, "amlogic, gem_memory", gem_mem_setup);
+
+module_platform_driver(am_meson_vpu_platform_driver);
+
+MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>");
+MODULE_DESCRIPTION("Amlogic Meson Drm VPU driver");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_vpu.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AM_MESON_VPU_H
+#define __AM_MESON_VPU_H
+
+#include <linux/amlogic/media/vout/vout_notify.h>
+
+struct am_meson_vpu_data {
+ u32 version;
+};
+
+struct am_vout_mode {
+ char name[DRM_DISPLAY_MODE_LEN];
+ enum vmode_e mode;
+ int width, height, vrefresh;
+ unsigned int flags;
+};
+
+extern struct osd_device_data_s osd_meson_dev;
+char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode);
+
+#endif /* __AM_MESON_VPU_H */
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_vpu_pipeline.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <dt-bindings/display/meson-drm-ids.h>
+
+#include "meson_vpu_pipeline.h"
+#include "meson_drv.h"
+
+#define MAX_LINKS 5
+#define MAX_PORTS 6
+#define MAX_PORT_ID 32
+
+static struct meson_vpu_block **vpu_blocks;
+static int num_blocks;
+
+struct meson_vpu_link_para {
+ u8 id;
+ u8 port;
+};
+
+struct meson_vpu_block_para {
+ char *name;
+ u8 id;
+ u8 index;
+ u8 type;
+ u8 num_inputs;
+ u8 num_outputs;
+ struct meson_vpu_link_para inputs[MESON_BLOCK_MAX_INPUTS];
+ struct meson_vpu_link_para outputs[MESON_BLOCK_MAX_OUTPUTS];
+ u64 inputs_mask;
+ u64 outputs_mask;
+};
+
+static struct meson_vpu_block *create_block(size_t blk_sz,
+ struct meson_vpu_block_para *para,
+ struct meson_vpu_block_ops *ops,
+ struct meson_vpu_pipeline *pipeline)
+{
+ struct meson_vpu_block *mvb;
+ int i;
+
+ mvb = kzalloc(blk_sz, GFP_KERNEL);
+ if (!mvb)
+ return NULL;
+
+ snprintf(mvb->name, MESON_BLOCK_MAX_NAME_LEN, "%s", para->name);
+ mvb->id = para->id;
+ mvb->type = para->type;
+ mvb->index = para->index;
+ mvb->avail_inputs = para->num_inputs;
+ mvb->avail_outputs = para->num_outputs;
+ mvb->max_inputs = para->num_inputs * 2;
+ mvb->max_outputs = para->num_outputs * 2;
+ mvb->inputs_mask = para->inputs_mask;
+ mvb->outputs_mask = para->outputs_mask;
+
+ for (i = 0; i < mvb->avail_inputs; i++) {
+ mvb->inputs[i].port = para->inputs[i].port;
+ mvb->inputs[i].id = para->inputs[i].id;
+ mvb->inputs[i].edges_active = 1;
+ mvb->inputs[i].edges_visited = 0;
+ }
+
+ for (i = 0; i < mvb->avail_outputs; i++) {
+ mvb->outputs[i].port = para->outputs[i].port;
+ mvb->outputs[i].id = para->outputs[i].id;
+ mvb->outputs[i].edges_active = 1;
+ mvb->outputs[i].edges_visited = 0;
+ }
+
+ mvb->ops = ops;
+ mvb->pipeline = pipeline;
+
+ return mvb;
+}
+
+static void parse_vpu_node(struct device_node *child_node,
+ struct meson_vpu_block_para *para)
+{
+ int i, j, ret, size;
+ u8 id;
+ struct device_node *link;
+ const __be32 *list, *phandle;
+ u64 in_mask, out_mask;
+
+ in_mask = 0;
+ out_mask = 0;
+ ret = of_property_read_u8(child_node, "id", ¶->id);
+ if (ret)
+ para->id = 0;
+ ret = of_property_read_u8(child_node, "index", ¶->index);
+ if (ret)
+ para->index = 0;
+ ret = of_property_read_u8(child_node, "type", ¶->type);
+ if (ret)
+ para->type = 0;
+ ret = of_property_read_u8(child_node, "num_in_links",
+ ¶->num_inputs);
+ if (ret)
+ para->num_inputs = 0;
+ ret = of_property_read_u8(child_node, "num_out_links",
+ ¶->num_outputs);
+ if (ret)
+ para->num_outputs = 0;
+ ret = of_property_read_string(child_node, "block_name",
+ (const char **)¶->name);
+ if (ret)
+ para->name = NULL;
+
+ list = of_get_property(child_node, "in_links", &size);
+ if (list) {
+ size /= sizeof(*list);
+ if (!size || size % 2) {
+ DRM_ERROR("wrong in_links config\n");
+ //return -EINVAL;
+ }
+ for (i = 0, j = 0; i < size; i += 2, j++) {
+ para->inputs[j].port = be32_to_cpu(*list++);
+ phandle = list++;
+ link = of_find_node_by_phandle(be32_to_cpup(phandle));
+ of_property_read_u8(link, "id", &id);
+ para->inputs[j].id = id;
+ in_mask |= 1 << id;
+ }
+ para->inputs_mask = in_mask;
+ }
+
+ list = of_get_property(child_node, "out_links", &size);
+ if (list) {
+ size /= sizeof(*list);
+ if (!size || size % 2) {
+ DRM_ERROR("wrong out_links config\n");
+ //return -EINVAL;
+ }
+ for (i = 0, j = 0; i < size; i += 2, j++) {
+ para->outputs[j].port = be32_to_cpu(*list++);
+ phandle = list++;
+ link = of_find_node_by_phandle(be32_to_cpup(phandle));
+ of_property_read_u8(link, "id", &id);
+ para->outputs[j].id = id;
+ out_mask |= 1 << id;
+ }
+ para->outputs_mask = out_mask;
+ }
+ DRM_INFO("id=%d,index=%d,num_in_links=%d,num_out_links=%d\n",
+ para->id, para->index,
+ para->num_inputs, para->num_outputs);
+ DRM_INFO("in_mask=0x%llx,out_mask=0x%llx\n", in_mask, out_mask);
+}
+
+static struct meson_vpu_block *
+meson_vpu_create_block(struct meson_vpu_block_para *para,
+ struct meson_vpu_pipeline *pipeline)
+{
+ struct meson_vpu_block *mvb;
+ size_t blk_size;
+
+ switch (para->type) {
+ case MESON_BLK_OSD:
+ blk_size = sizeof(struct meson_vpu_osd);
+ mvb = create_block(blk_size, para, &osd_ops, pipeline);
+
+ pipeline->osds[mvb->index] = to_osd_block(mvb);
+ pipeline->num_osds++;
+ break;
+ case MESON_BLK_AFBC:
+ blk_size = sizeof(struct meson_vpu_afbc);
+ mvb = create_block(blk_size, para, &afbc_ops, pipeline);
+
+ pipeline->afbc_osds[mvb->index] = to_afbc_block(mvb);
+ pipeline->num_afbc_osds++;
+ break;
+ case MESON_BLK_SCALER:
+ blk_size = sizeof(struct meson_vpu_scaler);
+ mvb = create_block(blk_size, para, &scaler_ops, pipeline);
+
+ pipeline->scalers[mvb->index] = to_scaler_block(mvb);
+ pipeline->num_scalers++;
+ break;
+ case MESON_BLK_OSDBLEND:
+ blk_size = sizeof(struct meson_vpu_osdblend);
+ mvb = create_block(blk_size, para, &osdblend_ops, pipeline);
+
+ pipeline->osdblend = to_osdblend_block(mvb);
+ break;
+ case MESON_BLK_HDR:
+ blk_size = sizeof(struct meson_vpu_hdr);
+ mvb = create_block(blk_size, para, &hdr_ops, pipeline);
+
+ pipeline->hdr = to_hdr_block(mvb);
+ break;
+ case MESON_BLK_DOVI:
+ blk_size = sizeof(struct meson_vpu_dolby);
+ mvb = create_block(blk_size, para, &dolby_ops, pipeline);
+
+ pipeline->dolby = to_dolby_block(mvb);
+ break;
+ case MESON_BLK_VPPBLEND:
+ blk_size = sizeof(struct meson_vpu_postblend);
+ mvb = create_block(blk_size, para, &postblend_ops, pipeline);
+
+ pipeline->postblend = to_postblend_block(mvb);
+ break;
+ default:
+ return NULL;
+ }
+
+ return mvb;
+}
+
+static void populate_block_link(void)
+{
+ int i, j, id;
+ struct meson_vpu_block *mvb;
+
+ for (i = 0; i < num_blocks; i++) {
+ mvb = vpu_blocks[i];
+
+ if (!mvb)
+ continue;
+
+ for (j = 0; j < mvb->avail_inputs; j++) {
+ id = mvb->inputs[j].id;
+ mvb->inputs[j].link = vpu_blocks[id];
+ }
+
+ for (j = 0; j < mvb->avail_outputs; j++) {
+ id = mvb->outputs[j].id;
+ mvb->outputs[j].link = vpu_blocks[id];
+ }
+ }
+}
+
+static int populate_vpu_pipeline(struct device_node *vpu_block_node,
+ struct meson_vpu_pipeline *pipeline)
+{
+ struct device_node *child_node;
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_block_para para;
+
+ num_blocks = of_get_child_count(vpu_block_node);
+ if (num_blocks <= 0)
+ return -ENODEV;
+
+ vpu_blocks = kcalloc(num_blocks, sizeof(*vpu_blocks), GFP_KERNEL);
+ if (!vpu_blocks)
+ return -ENOMEM;
+
+ for_each_child_of_node(vpu_block_node, child_node) {
+ parse_vpu_node(child_node, ¶);
+
+ mvb = meson_vpu_create_block(¶, pipeline);
+
+ if (!mvb)
+ return -ENOMEM;
+ vpu_blocks[mvb->id] = mvb;
+ }
+
+ populate_block_link();
+
+ return 0;
+}
+
+void VPU_PIPELINE_HW_INIT(struct meson_vpu_block *mvb)
+{
+ if (mvb->ops->init)
+ mvb->ops->init(mvb);
+}
+
+static void vpu_pipeline_planes_calc(struct meson_vpu_pipeline *pipeline,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ u8 i;
+
+ mvps->num_plane = 0;
+ mvps->enable_blocks = 0;
+ for (i = 0; i < pipeline->num_osds; i++) {
+ if (mvps->plane_info[i].enable) {
+ if (mvps->plane_info[i].src_w >
+ MESON_OSD_INPUT_W_LIMIT ||
+ mvps->plane_info[i].dst_w == 0) {
+ mvps->plane_info[i].enable = 0;
+ continue;
+ }
+ mvps->num_plane++;
+ }
+ }
+ DRM_DEBUG("num_plane=%d.\n", mvps->num_plane);
+}
+
+int vpu_pipeline_check(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *state)
+{
+ int ret;
+ struct meson_vpu_pipeline_state *mvps;
+
+ mvps = meson_vpu_pipeline_get_state(pipeline, state);
+
+ vpu_pipeline_planes_calc(pipeline, mvps);
+
+ ret = vpu_pipeline_traverse(mvps, state);
+ DRM_DEBUG("check done--num_plane=%d.\n", mvps->num_plane);
+
+ return ret;
+}
+
+void vpu_pipeline_init(struct meson_vpu_pipeline *pipeline)
+{
+ int i;
+
+ for (i = 0; i < pipeline->num_osds; i++)
+ VPU_PIPELINE_HW_INIT(&pipeline->osds[i]->base);
+
+ for (i = 0; i < pipeline->num_afbc_osds; i++)
+ VPU_PIPELINE_HW_INIT(&pipeline->afbc_osds[i]->base);
+
+ for (i = 0; i < pipeline->num_scalers; i++)
+ VPU_PIPELINE_HW_INIT(&pipeline->scalers[i]->base);
+
+ VPU_PIPELINE_HW_INIT(&pipeline->osdblend->base);
+
+ VPU_PIPELINE_HW_INIT(&pipeline->hdr->base);
+
+ VPU_PIPELINE_HW_INIT(&pipeline->postblend->base);
+}
+
+/* maybe use graph traverse is a good choice */
+int vpu_pipeline_update(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *old_state)
+{
+ unsigned long id;
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_block_state *mvbs;
+ struct meson_vpu_pipeline_state *old_mvps, *new_mvps;
+ unsigned long affected_blocks = 0;
+
+ old_mvps = meson_vpu_pipeline_get_state(pipeline, old_state);
+ new_mvps = priv_to_pipeline_state(pipeline->obj.state);
+
+ DRM_DEBUG("old_enable_blocks: 0x%llx, new_enable_blocks: 0x%llx.\n",
+ old_mvps->enable_blocks, new_mvps->enable_blocks);
+
+ #ifdef MESON_DRM_VERSION_V0
+ meson_vpu_pipeline_atomic_backup_state(new_mvps);
+ #endif
+ affected_blocks = old_mvps->enable_blocks | new_mvps->enable_blocks;
+ for_each_set_bit(id, &affected_blocks, 32) {
+ mvb = vpu_blocks[id];
+ mvbs = priv_to_block_state(mvb->obj.state);
+
+ if (new_mvps->enable_blocks & BIT(id)) {
+ mvb->ops->update_state(mvb, mvbs);
+ mvb->ops->enable(mvb);
+ } else {
+ mvb->ops->disable(mvb);
+ }
+ }
+
+ return 0;
+}
+
+int vpu_topology_init(struct platform_device *pdev, struct meson_drm *priv)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *child, *vpu_block_node;
+ struct meson_vpu_pipeline *pipeline;
+
+ child = of_get_child_by_name(np, "vpu_topology");
+ if (!child)
+ return -ENODEV;
+
+ vpu_block_node = of_get_child_by_name(child, "vpu_blocks");
+ if (!vpu_block_node) {
+ of_node_put(child);
+ return -ENODEV;
+ }
+
+ pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL);
+ if (!pipeline)
+ return -ENOMEM;
+
+ populate_vpu_pipeline(vpu_block_node, pipeline);
+ priv->pipeline = pipeline;
+ of_node_put(vpu_block_node);
+ of_node_put(child);
+
+ return 0;
+}
+EXPORT_SYMBOL(vpu_topology_init);
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_vpu_pipeline.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_VPU_TOPOLOGY_H
+#define __MESON_VPU_TOPOLOGY_H
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <dt-bindings/display/meson-drm-ids.h>
+#include "meson_vpu_reg.h"
+#include "meson_drv.h"
+#include "meson_vpu_util.h"
+
+#define MESON_OSD1 0
+#define MESON_OSD2 1
+#define MESON_OSD3 2
+#define MESON_MAX_OSDS 4
+#define MESON_MAX_OSD_BLEND 3
+#define MESON_MAX_OSD_TO_VPP 2
+#define MESON_MAX_SCALERS 4
+#define MESON_MAX_VIDEO 2
+#define MESON_MAX_BLOCKS 32
+#define MESON_BLOCK_MAX_INPUTS 6
+#define MESON_BLOCK_MAX_OUTPUTS 3
+#define MESON_BLOCK_MAX_NAME_LEN 32
+/*ratio base for scaler calc;maybe need bigger than 1000*/
+#define RATIO_BASE 1000
+#define MESON_OSD_INPUT_W_LIMIT 1920
+
+#define MAX_DIN_NUM 4
+#define MAX_DOUT_NUM 2
+
+#define MAX_DFS_PATH_NUM 2
+/*
+ *according to reg description,scale down limit shold be 4bits=16
+ *but test result is 10,it will display abnormal if bigger than 10.xx
+ *have not get more info from others,so config it as 10 right now.
+ *Todo:if you make sure and test okay,you can rechange it.
+ */
+#define MESON_OSD_SCLAE_DOWN_LIMIT 10
+#define MESON_OSD_SCLAE_UP_LIMIT ((1 << 24) - 1)
+/*
+ *MESON_DRM_VERSION_V0:support modetest and atomictest,
+ *backup last commit state
+ *MESON_DRM_VERSION_V1:support atomictest,
+ *don't support modetest,don't backup last commit state
+ */
+#define MESON_DRM_VERSION_V0 0
+
+#define SCALER_RATIO_X_CALC_DONE BIT(0)
+#define SCALER_RATIO_Y_CALC_DONE BIT(1)
+#define SCALER_IN_W_CALC_DONE BIT(2)
+#define SCALER_IN_H_CALC_DONE BIT(3)
+#define SCALER_OUT_W_CALC_DONE BIT(4)
+#define SCALER_OUT_H_CALC_DONE BIT(5)
+
+#define SCALER_INPUT_WIDTH_CHANGED BIT(0)
+#define SCALER_INPUT_HEIGHT_CHANGED BIT(1)
+#define SCALER_OUTPUT_WIDTH_CHANGED BIT(2)
+#define SCALER_OUTPUT_HEIGHT_CHANGED BIT(3)
+#define SCALER_OUTPUT_SCAN_MODE_CHANGED BIT(4)
+
+enum meson_vpu_blk_type {
+ MESON_BLK_OSD = 0,
+ MESON_BLK_AFBC,
+ MESON_BLK_SCALER,
+ MESON_BLK_OSDBLEND,
+ MESON_BLK_HDR,
+ MESON_BLK_DOVI,
+ MESON_BLK_VPPBLEND,
+};
+
+struct meson_vpu_pipeline;
+struct meson_vpu_block;
+struct meson_vpu_block_state;
+struct meson_vpu_pipeline_state;
+
+/* vpu block ops */
+struct meson_vpu_block_ops {
+ int (*check_state)(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps);
+ void (*update_state)(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state);
+ void (*enable)(struct meson_vpu_block *vblk);
+ void (*disable)(struct meson_vpu_block *vblk);
+ void (*init)(struct meson_vpu_block *vblk);
+};
+
+struct meson_vpu_block_link {
+ struct meson_vpu_block *link;
+ u8 id;
+ u8 port;
+ int edges_active;
+ int edges_visited;
+};
+
+/* vpu block */
+struct meson_vpu_block {
+ struct drm_private_obj obj;
+ char name[MESON_BLOCK_MAX_NAME_LEN];
+
+ enum meson_vpu_blk_type type;
+ u8 id;
+ u8 index;
+ u8 max_inputs;
+ u8 max_outputs;
+ u8 avail_inputs;
+ u8 avail_outputs;
+ unsigned long inputs_mask;
+ unsigned long outputs_mask;
+ struct meson_vpu_block_link inputs[MESON_BLOCK_MAX_INPUTS];
+ struct meson_vpu_block_link outputs[MESON_BLOCK_MAX_OUTPUTS];
+ struct meson_vpu_block_ops *ops;
+ struct meson_vpu_pipeline *pipeline;
+};
+
+struct meson_vpu_block_state {
+ struct drm_private_state obj;
+ struct meson_vpu_block *pblk;
+ u32 inputs_mask;
+
+ u32 inputs_changed;
+ u32 outputs_changed;
+ u32 checked;
+
+ u32 state_changed;
+
+ struct meson_vpu_block_link inputs[MESON_BLOCK_MAX_INPUTS];
+ struct meson_vpu_block_link outputs[MESON_BLOCK_MAX_OUTPUTS];
+ int in_stack;
+ int active;
+
+
+};
+
+struct meson_vpu_osd_layer_info {
+ u32 src_x;
+ u32 src_y;
+ u32 src_w;
+ u32 src_h;
+ u32 dst_w;
+ u32 dst_h;
+ int dst_x;
+ int dst_y;
+ u32 zorder;
+ u32 byte_stride;
+ u32 pixel_format;
+ u32 phy_addr;
+ u32 plane_index;
+ u32 enable;
+ u32 ratio_x;/*input_w/output_w*/
+ u32 afbc_inter_format;
+ u32 afbc_en;
+};
+
+struct meson_vpu_osd {
+ struct meson_vpu_block base;
+ struct osd_mif_reg_s *reg;
+};
+
+struct meson_vpu_osd_state {
+ struct meson_vpu_block_state base;
+
+ u32 index;
+ u32 enable;
+ u32 color_key_enable;
+ u32 dimm_enable;
+ u32 mode_3d_enable;
+
+ u32 color_key;
+ u32 alpha;
+ u32 global_alpha;
+ u32 dimm_color;
+ u32 phy_addr;
+ u32 pixel_format;
+ u32 zorder;
+ u32 byte_stride;
+ u32 src_x;
+ u32 src_y;
+ u32 src_w;
+ u32 src_h;
+ u32 dst_w;
+ u32 dst_h;
+ int dst_x;
+ int dst_y;
+ int s_mode;
+ int r_mode;
+ u32 plane_index;
+};
+
+struct meson_vpu_afbc {
+ struct meson_vpu_block base;
+
+};
+
+struct meson_vpu_afbc_state {
+ struct meson_vpu_block_state base;
+
+ u32 format;
+ u32 inter_format;
+ union afbc_osd_reg regs;
+};
+
+struct meson_vpu_scaler {
+ struct meson_vpu_block base;
+ struct osd_scaler_reg_s *reg;
+ u32 linebuffer;/*base pixel*/
+ u32 bank_length;/*base line*/
+};
+
+struct meson_vpu_scaler_state {
+ struct meson_vpu_block_state base;
+
+ u32 free_scale_mode;
+ u32 input_width;
+ u32 input_height;
+ u32 output_width;
+ u32 output_height;
+ u32 ratio_x;
+ u32 ratio_y;
+ u32 scan_mode_out;
+ u32 state_changed;
+ u32 free_scale_enable;
+};
+
+struct meson_vpu_scaler_param {
+ u32 input_width;
+ u32 input_height;
+ u32 output_width;
+ u32 output_height;
+ u32 ratio_x;
+ u32 ratio_y;
+ /*calc_done_mask:
+ *bit0:ratio_x,
+ *bit1:ratio_y
+ *bit2:input_width
+ *bit3:input_height
+ *bit4:output_width
+ *bit5:output_height
+ */
+ u32 calc_done_mask;
+ /*
+ *bit0:plane0
+ *bit1:plane1
+ *bit2:plane2
+ *bit*:plane*
+ */
+ u32 plane_mask;
+ u32 enable;
+ u32 before_osdblend;
+};
+
+struct meson_vpu_osdblend {
+ struct meson_vpu_block base;
+ struct osdblend_reg_s *reg;
+};
+
+struct meson_vpu_osdblend_state {
+ struct meson_vpu_block_state base;
+
+ u32 input_num;
+ /*bit0/bit1/bit2-->osd0/osd1/osd2*/
+ u32 input_osd_mask;
+ /*Din mask:bit0:DIN0;bit1:DIN1;bit2:DIN2;bit3:DIN3*/
+ u32 input_mask;
+ /*Din0~3 select which input channel or osd(0/1/2)*/
+ u32 din_channel_mux[MAX_DIN_NUM];
+ /*osd(0/1/2) go through osdblend to dout0 or dout1*/
+ u32 dout_mux[MAX_DIN_NUM];
+ /*scope position before mux,tied with osd0/osd1/osd2*/
+ struct osd_scope_s din_channel_scope[MAX_DIN_NUM];
+ /*sub-blend0 and sub-blend1 size*/
+ u32 input_width[MESON_MAX_OSD_BLEND];
+ u32 input_height[MESON_MAX_OSD_BLEND];
+ /*0:din0-->blend0;1:din0-->Dout0,bypass OsdBlend*/
+ u32 din0_switch;
+ /*0:din3-->blend1;1:din3-->Dout1,bypass OsdBlend*/
+ u32 din3_switch;
+ /*0:blend1-->blend2;1:blend1-->Dout1,bypass Blend2*/
+ u32 blend1_switch;
+
+};
+
+struct meson_vpu_hdr {
+ struct meson_vpu_block base;
+
+};
+
+struct meson_vpu_hdr_state {
+ struct meson_vpu_block_state base;
+};
+
+struct meson_vpu_dolby {
+ struct meson_vpu_block base;
+};
+
+struct meson_vpu_dolby_state {
+ struct meson_vpu_block_state base;
+};
+
+struct meson_vpu_postblend {
+ struct meson_vpu_block base;
+ struct postblend_reg_s *reg;
+};
+
+struct meson_vpu_postblend_state {
+ struct meson_vpu_block_state base;
+ struct osd_scope_s postblend_scope[MESON_MAX_OSD_TO_VPP];
+};
+
+/* vpu pipeline */
+struct meson_vpu_pipeline {
+ struct drm_private_obj obj;
+ struct drm_display_mode mode;
+ struct meson_vpu_osd *osds[MESON_MAX_OSDS];
+ struct meson_vpu_afbc *afbc_osds[MESON_MAX_OSDS];
+ struct meson_vpu_scaler *scalers[MESON_MAX_SCALERS];
+ struct meson_vpu_osdblend *osdblend;
+ struct meson_vpu_hdr *hdr;
+ struct meson_vpu_dolby *dolby;
+ struct meson_vpu_postblend *postblend;
+ struct meson_vpu_pipeline_state *state;
+ u32 num_osds;
+ u32 num_afbc_osds;
+ u32 num_scalers;
+ u8 osd_version;
+};
+
+struct meson_vpu_common_state {
+ u32 color_format;
+ u64 block_mask;
+};
+
+struct meson_vpu_stack {
+ int num_blocks;
+ int top;
+ struct meson_vpu_block *stack[MESON_MAX_BLOCKS];
+};
+
+struct meson_vpu_traverse {
+ struct meson_vpu_block *path[MAX_DFS_PATH_NUM][MESON_MAX_BLOCKS];
+ int num_path;
+};
+
+struct meson_vpu_pipeline_state {
+ struct drm_private_state obj;
+ struct meson_vpu_common_state common_cfg;
+ struct meson_vpu_pipeline *pipeline;
+ u64 enable_blocks;
+ struct meson_vpu_osd_layer_info plane_info[MESON_MAX_OSDS];
+ u32 num_plane;
+ /*min --> max*/
+ u32 zorder_plane_index[MESON_MAX_OSDS];
+ u32 ratio_plane_index[MESON_MAX_OSDS];
+ struct meson_vpu_scaler_param scaler_param[MESON_MAX_SCALERS];
+ /*pre_osd_scope is before DIN*/
+ struct osd_scope_s osd_scope_pre[MAX_DIN_NUM];
+
+ /*some traverse help structure*/
+ struct meson_vpu_stack osd_stack[MESON_MAX_OSDS];
+
+ /*store traverse result for every path*/
+ struct meson_vpu_traverse osd_traverse[MESON_MAX_OSDS];
+
+ u32 plane_index[MESON_MAX_OSDS];
+ u32 din_index[MAX_DIN_NUM];
+ u32 dout_index[MAX_DIN_NUM];
+ u32 scaler_cnt[MAX_DIN_NUM];
+ struct meson_vpu_block *scale_blk[MESON_MAX_OSDS][MESON_MAX_SCALERS];
+ u32 dout_zorder[MAX_DOUT_NUM];
+};
+
+#define to_osd_block(x) container_of(x, struct meson_vpu_osd, base)
+#define to_afbc_block(x) container_of(x, struct meson_vpu_afbc, base)
+#define to_scaler_block(x) container_of(x, struct meson_vpu_scaler, base)
+#define to_osdblend_block(x) container_of(x, struct meson_vpu_osdblend, base)
+#define to_hdr_block(x) container_of(x, struct meson_vpu_hdr, base)
+#define to_dolby_block(x) container_of(x, struct meson_vpu_dolby, base)
+#define to_postblend_block(x) container_of(x, struct meson_vpu_postblend, base)
+
+#define to_osd_state(x) container_of(x, struct meson_vpu_osd_state, base)
+#define to_afbc_state(x) container_of(x, struct meson_vpu_afbc_state, base)
+#define to_scaler_state(x) container_of(x, struct meson_vpu_scaler_state, base)
+#define to_osdblend_state(x) container_of(x, \
+ struct meson_vpu_osdblend_state, base)
+#define to_hdr_state(x) container_of(x, struct meson_vpu_hdr_state, base)
+#define to_dolby_state(x) container_of(x, struct meson_vpu_dolby_state, base)
+#define to_postblend_state(x) container_of(x, \
+ struct meson_vpu_postblend_state, base)
+
+#define priv_to_block(x) container_of(x, struct meson_vpu_block, obj)
+#define priv_to_block_state(x) container_of(x, \
+ struct meson_vpu_block_state, obj)
+#define priv_to_pipeline(x) container_of(x, struct meson_vpu_pipeline, obj)
+#define priv_to_pipeline_state(x) container_of(x, \
+ struct meson_vpu_pipeline_state, obj)
+
+int vpu_topology_init(struct platform_device *pdev, struct meson_drm *private);
+int vpu_pipeline_check(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *state);
+int vpu_pipeline_update(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *old_state);
+void vpu_pipeline_init(struct meson_vpu_pipeline *pipeline);
+
+/* meson_vpu_pipeline_private.c */
+struct meson_vpu_block_state *
+meson_vpu_block_get_state(struct meson_vpu_block *block,
+ struct drm_atomic_state *state);
+struct meson_vpu_pipeline_state *
+meson_vpu_pipeline_get_state(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *state);
+int meson_vpu_block_state_init(struct meson_drm *private,
+ struct meson_vpu_pipeline *pipeline);
+#ifdef MESON_DRM_VERSION_V0
+void meson_vpu_pipeline_atomic_backup_state(
+ struct meson_vpu_pipeline_state *mvps);
+#endif
+
+int combination_traverse(struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state);
+int vpu_pipeline_traverse(struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state);
+int vpu_pipeline_check_osdblend(u32 *out_port, int num_planes,
+ struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state);
+
+extern struct meson_vpu_block_ops osd_ops;
+extern struct meson_vpu_block_ops afbc_ops;
+extern struct meson_vpu_block_ops scaler_ops;
+extern struct meson_vpu_block_ops osdblend_ops;
+extern struct meson_vpu_block_ops hdr_ops;
+extern struct meson_vpu_block_ops dolby_ops;
+extern struct meson_vpu_block_ops postblend_ops;
+
+
+ #endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_vpu_pipeline_private.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include "meson_vpu_pipeline.h"
+#include "meson_drv.h"
+
+static inline void
+vpu_pipeline_state_set(struct meson_vpu_block *pblk,
+ struct meson_vpu_block_state *state)
+{
+ u8 i;
+
+ for (i = 0; i < pblk->avail_inputs; i++) {
+ memcpy(&state->inputs[i], &pblk->inputs[i],
+ sizeof(struct meson_vpu_block_link));
+ }
+ for (i = 0; i < pblk->avail_outputs; i++) {
+ memcpy(&state->outputs[i], &pblk->outputs[i],
+ sizeof(struct meson_vpu_block_link));
+ }
+ state->in_stack = 0;
+ state->active = 1;
+}
+
+static struct drm_private_state *
+meson_vpu_osd_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_osd_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void meson_vpu_osd_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_osd_state *mvos = to_osd_state(mvbs);
+
+ DRM_DEBUG("%s id=%d,index=%d\n",
+ mvbs->pblk->name, mvbs->pblk->id, mvbs->pblk->index);
+ kfree(mvos);
+}
+
+static const struct drm_private_state_funcs meson_vpu_osd_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_osd_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_osd_atomic_destroy_state,
+};
+
+static int meson_vpu_osd_state_init(struct meson_drm *private,
+ struct meson_vpu_osd *osd)
+{
+ struct meson_vpu_osd_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &osd->base;
+ drm_atomic_private_obj_init(&osd->base.obj,
+ &state->base.obj,
+ &meson_vpu_osd_obj_funcs);
+
+ return 0;
+}
+
+static struct drm_private_state *
+meson_vpu_afbc_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_afbc_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void
+meson_vpu_afbc_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_afbc_state *mvas = to_afbc_state(mvbs);
+
+ kfree(mvas);
+}
+
+static const struct drm_private_state_funcs meson_vpu_afbc_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_afbc_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_afbc_atomic_destroy_state,
+};
+
+static int meson_vpu_afbc_state_init(struct meson_drm *private,
+ struct meson_vpu_afbc *afbc)
+{
+ struct meson_vpu_afbc_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &afbc->base;
+ drm_atomic_private_obj_init(&afbc->base.obj,
+ &state->base.obj,
+ &meson_vpu_afbc_obj_funcs);
+
+ return 0;
+}
+
+/*afbc block state ops end
+ */
+
+/*scaler block state ops start
+ */
+
+static struct drm_private_state *
+meson_vpu_scaler_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_scaler_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void
+meson_vpu_scaler_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_scaler_state *mvss = to_scaler_state(mvbs);
+
+ kfree(mvss);
+}
+
+static const struct drm_private_state_funcs meson_vpu_scaler_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_scaler_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_scaler_atomic_destroy_state,
+};
+
+static int meson_vpu_scaler_state_init(struct meson_drm *private,
+ struct meson_vpu_scaler *scaler)
+{
+ struct meson_vpu_scaler_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &scaler->base;
+ drm_atomic_private_obj_init(&scaler->base.obj,
+ &state->base.obj,
+ &meson_vpu_scaler_obj_funcs);
+
+ return 0;
+}
+
+static struct drm_private_state *
+meson_vpu_osdblend_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_osdblend_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void
+meson_vpu_osdblend_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_osdblend_state *mvos = to_osdblend_state(mvbs);
+
+ kfree(mvos);
+}
+
+static const struct drm_private_state_funcs meson_vpu_osdblend_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_osdblend_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_osdblend_atomic_destroy_state,
+};
+
+static int meson_vpu_osdblend_state_init(struct meson_drm *private,
+ struct meson_vpu_osdblend *osdblend)
+{
+ struct meson_vpu_osdblend_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &osdblend->base;
+ drm_atomic_private_obj_init(&osdblend->base.obj,
+ &state->base.obj,
+ &meson_vpu_osdblend_obj_funcs);
+
+ return 0;
+}
+
+static struct drm_private_state *
+meson_vpu_hdr_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_hdr_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void meson_vpu_hdr_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_hdr_state *mvhs = to_hdr_state(mvbs);
+
+ kfree(mvhs);
+}
+
+static const struct drm_private_state_funcs meson_vpu_hdr_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_hdr_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_hdr_atomic_destroy_state,
+};
+
+static int meson_vpu_hdr_state_init(struct meson_drm *private,
+ struct meson_vpu_hdr *hdr)
+{
+ struct meson_vpu_hdr_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &hdr->base;
+ drm_atomic_private_obj_init(&hdr->base.obj,
+ &state->base.obj,
+ &meson_vpu_hdr_obj_funcs);
+
+ return 0;
+}
+
+/*hdr block state ops end
+ */
+
+/*postblend block state ops start
+ */
+
+static struct drm_private_state *
+meson_vpu_postblend_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_postblend_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void
+meson_vpu_postblend_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_postblend_state *mvas = to_postblend_state(mvbs);
+
+ kfree(mvas);
+}
+
+static const struct drm_private_state_funcs meson_vpu_postblend_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_postblend_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_postblend_atomic_destroy_state,
+};
+
+static int
+meson_vpu_postblend_state_init(struct meson_drm *private,
+ struct meson_vpu_postblend *postblend)
+{
+ struct meson_vpu_postblend_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &postblend->base;
+ drm_atomic_private_obj_init(&postblend->base.obj,
+ &state->base.obj,
+ &meson_vpu_postblend_obj_funcs);
+ return 0;
+}
+
+/*postblend block state ops end
+ */
+#ifdef MESON_DRM_VERSION_V0
+static struct meson_vpu_pipeline_state last_mvps;
+#endif
+static struct drm_private_state *
+meson_vpu_pipeline_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_pipeline_state *state;
+ struct meson_vpu_pipeline *pipeline = priv_to_pipeline(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ #ifdef MESON_DRM_VERSION_V0
+ memcpy(state, &last_mvps, sizeof(*state));
+ #endif
+ state->pipeline = pipeline;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->obj);
+
+ return &state->obj;
+}
+
+static void meson_vpu_pipeline_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_pipeline_state *mvps = priv_to_pipeline_state(state);
+
+ kfree(mvps);
+}
+
+#ifdef MESON_DRM_VERSION_V0
+void meson_vpu_pipeline_atomic_backup_state(
+ struct meson_vpu_pipeline_state *mvps)
+{
+ memcpy(&last_mvps, mvps, sizeof(*mvps));
+}
+#endif
+
+static const struct drm_private_state_funcs meson_vpu_pipeline_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_pipeline_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_pipeline_atomic_destroy_state,
+};
+
+static int meson_vpu_pipeline_state_init(struct meson_drm *private,
+ struct meson_vpu_pipeline *pipeline)
+{
+ struct meson_vpu_pipeline_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->pipeline = pipeline;
+ drm_atomic_private_obj_init(&pipeline->obj, &state->obj,
+ &meson_vpu_pipeline_obj_funcs);
+
+ return 0;
+}
+
+struct meson_vpu_block_state *
+meson_vpu_block_get_state(struct meson_vpu_block *block,
+ struct drm_atomic_state *state)
+{
+ struct drm_private_state *dps;
+ struct meson_vpu_block_state *mvbs;
+
+ dps = drm_atomic_get_private_obj_state(state, &block->obj);
+ if (dps) {
+ mvbs = priv_to_block_state(dps);
+ return mvbs;
+ }
+
+ return NULL;
+}
+
+struct meson_vpu_pipeline_state *
+meson_vpu_pipeline_get_state(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *state)
+{
+ struct drm_private_state *dps;
+
+ dps = drm_atomic_get_private_obj_state(state, &pipeline->obj);
+ if (dps) {
+ dps->state = state;
+ return priv_to_pipeline_state(dps);
+ }
+
+ return NULL;
+}
+
+int meson_vpu_block_state_init(struct meson_drm *private,
+ struct meson_vpu_pipeline *pipeline)
+{
+ int i, ret;
+
+ ret = meson_vpu_pipeline_state_init(private, pipeline);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < pipeline->num_osds; i++) {
+ ret = meson_vpu_osd_state_init(private, pipeline->osds[i]);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < pipeline->num_afbc_osds; i++) {
+ ret = meson_vpu_afbc_state_init(private,
+ pipeline->afbc_osds[i]);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < pipeline->num_scalers; i++) {
+ ret = meson_vpu_scaler_state_init(private,
+ pipeline->scalers[i]);
+ if (ret)
+ return ret;
+ }
+
+
+ ret = meson_vpu_osdblend_state_init(private, pipeline->osdblend);
+ if (ret)
+ return ret;
+
+ ret = meson_vpu_hdr_state_init(private, pipeline->hdr);
+ if (ret)
+ return ret;
+
+ ret = meson_vpu_postblend_state_init(private, pipeline->postblend);
+ if (ret)
+ return ret;
+
+ return 0;
+}
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_vpu_pipeline_traverse.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <dt-bindings/display/meson-drm-ids.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include "meson_vpu_pipeline.h"
+#include "meson_drv.h"
+
+static void stack_init(struct meson_vpu_stack *mvs)
+{
+ mvs->top = 0;
+ memset(mvs->stack, 0, sizeof(struct meson_vpu_block *) *
+ MESON_MAX_BLOCKS);
+}
+
+static void stack_push(struct meson_vpu_stack *mvs, struct meson_vpu_block *mvb)
+{
+ mvs->stack[mvs->top++] = mvb;
+}
+
+static struct meson_vpu_block *stack_pop(struct meson_vpu_stack *mvs)
+{
+ struct meson_vpu_block *mvb;
+
+ mvb = mvs->stack[--mvs->top];
+ mvs->stack[mvs->top] = NULL;
+ return mvb;
+}
+
+static struct meson_vpu_block *neighbour(struct meson_vpu_block_state *mvbs,
+ int *index,
+ struct drm_atomic_state *state)
+{
+ int i;
+ struct meson_vpu_block_link *mvbl;
+ struct meson_vpu_block_state *next_state;
+
+ for (i = 0; i < MESON_BLOCK_MAX_OUTPUTS; i++) {
+ mvbl = &mvbs->outputs[i];
+
+ if (!mvbl->link)
+ continue;
+ next_state = meson_vpu_block_get_state(mvbl->link, state);
+ if (next_state->in_stack) {
+ //printk("%s already in stack.\n", mvbl->link->name);
+ continue;
+ }
+ if (!next_state->active) {
+ //printk("%s is not active.\n", mvbl->link->name);
+ continue;
+ }
+ if (!mvbl->edges_active) {
+ //printk("edges is not active.\n");
+ continue;
+ }
+ if (mvbl->edges_visited) {
+ //printk("edges is already visited.\n");
+ continue;
+ }
+
+ *index = i;
+ return mvbl->link;
+ }
+
+ return NULL;
+}
+
+static void pipeline_visit_clean(struct meson_vpu_block_state *curr_state)
+{
+ int index;
+
+ for (index = 0; index < MESON_BLOCK_MAX_OUTPUTS; index++)
+ curr_state->outputs[index].edges_visited = 0;
+}
+
+/**
+ * pipeline_dfs - dfs algorithm to search path
+ * @osd_index: osd layer index
+ * @start: the start block of the dfs
+ * @end: the end block of the dfs
+ *
+ * use the non-recursive dfs algorithm to search all paths from the start block
+ * to the end block, the result will be saved to the meson_vpu_traverse struct.
+ *
+ */
+static void pipeline_dfs(int osd_index, struct meson_vpu_pipeline_state *mvps,
+ struct meson_vpu_block *start,
+ struct meson_vpu_block *end,
+ struct drm_atomic_state *state)
+{
+ struct meson_vpu_block *curr, *next, *prev;
+ struct meson_vpu_block_state *curr_state, *next_state, *prev_state;
+ int i, j, index;
+
+ struct meson_vpu_stack *mvs = &mvps->osd_stack[osd_index];
+ struct meson_vpu_traverse *mvt = &mvps->osd_traverse[osd_index];
+
+ stack_init(mvs);
+ stack_push(mvs, start);
+ mvt->num_path = 0;
+ j = 0;
+
+ while (mvs->top) {
+ if (mvs->stack[mvs->top - 1] == end) {
+ for (i = 0; i < mvs->top; i++) {
+ mvt->path[j][i] = mvs->stack[i];
+ DRM_DEBUG("%s->\n", mvs->stack[i]->name);
+ }
+ j++;
+ mvt->num_path++;
+ DRM_DEBUG("\n");
+ prev = stack_pop(mvs);
+ prev_state = meson_vpu_block_get_state(prev, state);
+ prev_state->in_stack = 0;
+ } else {
+ curr = mvs->stack[mvs->top - 1];
+ curr_state = meson_vpu_block_get_state(curr, state);
+ next = neighbour(curr_state, &index, state);
+
+ if (next) {
+ curr_state->outputs[index].edges_visited = 1;
+ next_state =
+ meson_vpu_block_get_state(next, state);
+ stack_push(mvs, next);
+ next_state->in_stack = 1;
+ } else {
+ stack_pop(mvs);
+ curr_state->in_stack = 0;
+ pipeline_visit_clean(curr_state);
+ }
+ }
+ }
+}
+
+static u8 find_out_port(struct meson_vpu_block *in,
+ struct meson_vpu_block *out)
+{
+ int i;
+ struct meson_vpu_block_link *mvbl;
+
+ for (i = 0; i < out->avail_inputs; i++) {
+ mvbl = &out->inputs[i];
+ if (mvbl->link == in)
+ return mvbl->port;
+ }
+ return 0;
+}
+
+void vpu_pipeline_scaler_scope_size_calc(u8 index, u8 osd_index,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ u8 m, i;
+ u32 ratio_x[MESON_MAX_SCALERS], ratio_y[MESON_MAX_SCALERS];
+ struct meson_vpu_scaler_param *scaler_param, *scaler_param_1;
+
+ i = index;
+ if (mvps->scaler_cnt[i] == 0) {
+ /*scope size calc*/
+ mvps->osd_scope_pre[osd_index].h_start =
+ mvps->plane_info[osd_index].src_x;
+ mvps->osd_scope_pre[osd_index].v_start =
+ mvps->plane_info[osd_index].src_y;
+ mvps->osd_scope_pre[osd_index].h_end =
+ mvps->osd_scope_pre[osd_index].h_start
+ + mvps->plane_info[osd_index].src_w - 1;
+ mvps->osd_scope_pre[osd_index].v_end =
+ mvps->osd_scope_pre[osd_index].v_start
+ + mvps->plane_info[osd_index].src_h - 1;
+ } else if (mvps->scaler_cnt[i] == 1) {
+ m = mvps->scale_blk[i][0]->index;
+ scaler_param = &mvps->scaler_param[m];
+ scaler_param->ratio_x =
+ (mvps->plane_info[osd_index].src_w *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_w;
+ scaler_param->ratio_y =
+ (mvps->plane_info[osd_index].src_h *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_h;
+ scaler_param->calc_done_mask |=
+ SCALER_RATIO_X_CALC_DONE |
+ SCALER_RATIO_Y_CALC_DONE;
+ if (scaler_param->before_osdblend) {
+ /*scale size calc firstly*/
+ scaler_param->input_width =
+ mvps->plane_info[osd_index].src_w;
+ scaler_param->input_height =
+ mvps->plane_info[osd_index].src_h;
+ scaler_param->output_width =
+ mvps->plane_info[osd_index].dst_w;
+ scaler_param->output_height =
+ mvps->plane_info[osd_index].dst_h;
+ scaler_param->calc_done_mask |=
+ SCALER_IN_W_CALC_DONE |
+ SCALER_IN_H_CALC_DONE |
+ SCALER_OUT_W_CALC_DONE |
+ SCALER_OUT_H_CALC_DONE;
+ /*scope size calc*/
+ mvps->osd_scope_pre[osd_index].h_start =
+ mvps->plane_info[osd_index].dst_x;
+ mvps->osd_scope_pre[osd_index].v_start =
+ mvps->plane_info[osd_index].dst_y;
+ mvps->osd_scope_pre[osd_index].h_end =
+ mvps->osd_scope_pre[osd_index].h_start
+ + scaler_param->output_width - 1;
+ mvps->osd_scope_pre[osd_index].v_end =
+ mvps->osd_scope_pre[osd_index].v_start
+ + scaler_param->output_height - 1;
+ } else {/*scaler position is after osdlend*/
+ /*scope size calc firstly*/
+ mvps->osd_scope_pre[osd_index].h_start =
+ mvps->plane_info[osd_index].src_x;
+ mvps->osd_scope_pre[osd_index].v_start =
+ mvps->plane_info[osd_index].src_y;
+ mvps->osd_scope_pre[osd_index].h_end =
+ mvps->osd_scope_pre[osd_index].h_start
+ + mvps->plane_info[osd_index].src_w - 1;
+ mvps->osd_scope_pre[osd_index].v_end =
+ mvps->osd_scope_pre[osd_index].v_start
+ + mvps->plane_info[osd_index].src_h - 1;
+ /*scaler size calc*/
+ scaler_param->input_width =
+ mvps->osd_scope_pre[osd_index].h_end + 1;
+ scaler_param->input_height =
+ mvps->osd_scope_pre[osd_index].v_end + 1;
+ scaler_param->output_width =
+ mvps->plane_info[osd_index].dst_x +
+ mvps->plane_info[osd_index].dst_w;
+ scaler_param->output_height =
+ mvps->plane_info[osd_index].dst_y +
+ mvps->plane_info[osd_index].dst_h;
+ scaler_param->calc_done_mask |=
+ SCALER_IN_W_CALC_DONE |
+ SCALER_IN_H_CALC_DONE |
+ SCALER_OUT_W_CALC_DONE |
+ SCALER_OUT_H_CALC_DONE;
+ }
+ } else if (mvps->scaler_cnt[i] == 2) {
+ m = mvps->scale_blk[i][0]->index;
+ scaler_param = &mvps->scaler_param[m];
+ m = mvps->scale_blk[i][1]->index;
+ scaler_param_1 = &mvps->scaler_param[m];
+ if (scaler_param_1->calc_done_mask &
+ SCALER_RATIO_X_CALC_DONE) {/*TODO*/
+ ratio_x[1] = scaler_param_1->ratio_x;
+ ratio_y[1] = scaler_param_1->ratio_y;
+ /*recheck scaler size*/
+ } else {/*TODO*/
+ ratio_x[1] = RATIO_BASE;
+ ratio_y[1] = RATIO_BASE;
+ scaler_param_1->calc_done_mask |=
+ SCALER_RATIO_X_CALC_DONE |
+ SCALER_RATIO_Y_CALC_DONE;
+ }
+ /*calculate scaler input/output size and scope*/
+ if (scaler_param->before_osdblend) {
+ scaler_param->input_width =
+ mvps->plane_info[osd_index].src_w;
+ scaler_param->input_height =
+ mvps->plane_info[osd_index].src_h;
+ scaler_param->output_width =
+ mvps->plane_info[osd_index].dst_w *
+ ratio_x[1] / RATIO_BASE;
+ scaler_param->output_height =
+ mvps->plane_info[osd_index].dst_h *
+ ratio_y[1] / RATIO_BASE;
+ scaler_param->calc_done_mask |=
+ SCALER_IN_W_CALC_DONE |
+ SCALER_IN_H_CALC_DONE |
+ SCALER_OUT_W_CALC_DONE |
+ SCALER_OUT_H_CALC_DONE;
+ /*scope size calc*/
+ mvps->osd_scope_pre[osd_index].h_start =
+ mvps->plane_info[osd_index].dst_x *
+ ratio_x[1] / RATIO_BASE;
+ mvps->osd_scope_pre[osd_index].v_start =
+ mvps->plane_info[osd_index].dst_y *
+ ratio_y[1] / RATIO_BASE;
+ mvps->osd_scope_pre[osd_index].h_end =
+ mvps->osd_scope_pre[osd_index].h_start
+ + scaler_param->output_width - 1;
+ mvps->osd_scope_pre[osd_index].v_end =
+ mvps->osd_scope_pre[osd_index].v_start
+ + scaler_param->output_height - 1;
+ } else {
+ /*TODO*/
+ }
+ /*reclac second scaler size*/
+ /*scaler_param_1->before_osdblend == 0*/
+ if (scaler_param_1->input_width <
+ mvps->osd_scope_pre[osd_index].h_end + 1) {
+ scaler_param_1->input_width =
+ mvps->osd_scope_pre[osd_index].h_end + 1;
+ scaler_param_1->output_width =
+ mvps->plane_info[osd_index].dst_x +
+ mvps->plane_info[osd_index].dst_w;
+ }
+ if (scaler_param_1->input_height <
+ mvps->osd_scope_pre[osd_index].v_end + 1) {
+ scaler_param_1->input_height =
+ mvps->osd_scope_pre[osd_index].v_end + 1;
+ scaler_param_1->output_height =
+ mvps->plane_info[osd_index].dst_y +
+ mvps->plane_info[osd_index].dst_h;
+ }
+ }
+}
+static void vpu_osd_shift_recalc(struct meson_vpu_pipeline_state *state)
+{
+ u8 i;
+
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ state->osd_scope_pre[i].v_start += 1;
+ state->osd_scope_pre[i].v_end += 1;
+ }
+ state->scaler_param[0].input_height += 1;
+}
+int vpu_pipeline_scaler_check(int *combination, int num_planes,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ int i, j, osd_index, ret, m;
+ struct meson_vpu_traverse *mvt;
+ struct meson_vpu_block **mvb;
+ struct meson_vpu_block *block;
+ struct meson_vpu_scaler_param *scaler_param, *scaler_param_1;
+ u32 ratio_x[MESON_MAX_SCALERS], ratio_y[MESON_MAX_SCALERS];
+ bool have_blend;
+
+ ret = 0;
+ /*clean up scaler and scope size before check & calc*/
+ memset(mvps->scaler_param, 0,
+ MESON_MAX_SCALERS * sizeof(struct meson_vpu_scaler_param));
+ memset(mvps->osd_scope_pre, 0,
+ MESON_MAX_OSDS * sizeof(struct osd_scope_s));
+ for (i = 0; i < MESON_MAX_OSDS && !ret; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ mvt = &mvps->osd_traverse[osd_index];
+ mvb = mvt->path[combination[i]];
+ mvps->scaler_cnt[i] = 0;
+ have_blend = 0;
+
+ for (j = 0; j < MESON_MAX_BLOCKS; j++) {
+ block = mvb[j];
+ if (!block)
+ continue;
+ if (block->type == MESON_BLK_OSDBLEND)
+ have_blend = 1;
+ if (block->type == MESON_BLK_SCALER) {
+ m = mvps->scaler_cnt[i];
+ mvps->scale_blk[i][m] = block;
+ mvps->scaler_cnt[i]++;
+ m = block->index;
+ mvps->scaler_param[m].plane_mask |=
+ BIT(osd_index);
+ mvps->scaler_param[m].before_osdblend =
+ have_blend ? 0:1;
+ }
+ }
+
+ if (mvps->scaler_cnt[i] == 0) {
+ ratio_x[0] = (mvps->plane_info[osd_index].src_w *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_w;
+ ratio_y[0] = (mvps->plane_info[osd_index].src_h *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_h;
+ if (ratio_x[0] != RATIO_BASE ||
+ ratio_y[0] != RATIO_BASE) {
+ ret = -1;
+ break;
+ }
+ vpu_pipeline_scaler_scope_size_calc(i,
+ osd_index, mvps);
+ } else if (mvps->scaler_cnt[i] == 1) {
+ vpu_pipeline_scaler_scope_size_calc(i,
+ osd_index, mvps);
+ } else if (mvps->scaler_cnt[i] == 2) {
+ /*
+ *check second scaler firstly,
+ *if second scaler have not check,
+ *disable the second scaler.only use first scale.
+ */
+ m = mvps->scale_blk[i][1]->index;
+ scaler_param_1 = &mvps->scaler_param[m];
+ if (scaler_param_1->calc_done_mask &
+ SCALER_RATIO_X_CALC_DONE) {/*TODO*/
+ ratio_x[1] = scaler_param_1->ratio_x;
+ ratio_y[1] = scaler_param_1->ratio_y;
+ /*recheck scaler size*/
+ } else {/*TODO*/
+ ratio_x[1] = RATIO_BASE;
+ ratio_y[1] = RATIO_BASE;
+ scaler_param_1->ratio_x = RATIO_BASE;
+ scaler_param_1->ratio_y = RATIO_BASE;
+ scaler_param_1->calc_done_mask |=
+ SCALER_RATIO_X_CALC_DONE |
+ SCALER_RATIO_Y_CALC_DONE;
+ }
+ ratio_x[0] = (mvps->plane_info[osd_index].src_w *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_w;
+ ratio_y[0] = (mvps->plane_info[osd_index].src_h *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_h;
+ m = mvps->scale_blk[i][0]->index;
+ scaler_param = &mvps->scaler_param[m];
+ scaler_param->ratio_x =
+ (ratio_x[0] * RATIO_BASE) / ratio_x[1];
+ scaler_param->ratio_y =
+ (ratio_y[0] * RATIO_BASE) / ratio_y[1];
+ scaler_param->calc_done_mask |=
+ SCALER_RATIO_X_CALC_DONE |
+ SCALER_RATIO_Y_CALC_DONE;
+ ratio_x[0] = scaler_param->ratio_x;
+ ratio_y[0] = scaler_param->ratio_y;
+
+ if ((ratio_x[0] > RATIO_BASE &&
+ ratio_x[1] < RATIO_BASE) ||
+ (ratio_y[0] > RATIO_BASE &&
+ ratio_y[1] < RATIO_BASE)) {
+ ret = -1;
+ break;
+ }
+ vpu_pipeline_scaler_scope_size_calc(i,
+ osd_index, mvps);
+ }
+ }
+ if (ret == 0 && mvps->num_plane > 0 &&
+ mvps->pipeline->osd_version <= OSD_V2)
+ vpu_osd_shift_recalc(mvps);
+ return ret;
+}
+
+/**
+ * vpu_pipeline_check_block: check pipeline block
+ * @combination: index array of every layer path
+ * @num_planes: the number of layer
+ *
+ * For some blocks that have multiple output port,
+ * call the ops->check interface to determain a valid path.
+ *
+ * RETURNS:
+ * 0 for the valid path or -1 for the invalid path
+ */
+int vpu_pipeline_check_block(int *combination, int num_planes,
+ struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state)
+{
+ int i, j, osd_index, ret;
+ struct meson_vpu_traverse *mvt;
+ struct meson_vpu_block **mvb;
+ struct meson_vpu_block *block;
+ struct meson_vpu_block *osdblend;
+ struct meson_vpu_block_state *mvbs;
+
+ osdblend = &mvps->pipeline->osdblend->base;
+ ret = vpu_pipeline_scaler_check(combination, num_planes, mvps);
+ if (ret)
+ return -1;
+
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ mvt = &mvps->osd_traverse[osd_index];
+ mvb = mvt->path[combination[i]];
+ mvps->scaler_cnt[i] = 0;
+
+ for (j = 0; j < MESON_MAX_BLOCKS; j++) {
+ block = mvb[j];
+ if (!block)
+ break;
+
+ if (block == osdblend) {
+ mvps->dout_index[i] =
+ find_out_port(block, mvb[j+1]);
+ DRM_DEBUG("osd-%d blend out port: %d.\n",
+ i, mvps->dout_index[i]);
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ mvt = &mvps->osd_traverse[osd_index];
+ mvb = mvt->path[combination[i]];
+
+ for (j = 0; j < MESON_MAX_BLOCKS; j++) {
+ block = mvb[j];
+ if (!block)
+ break;
+
+ if (block->ops && block->ops->check_state) {
+ mvbs = meson_vpu_block_get_state(block, state);
+ ret = block->ops->check_state(block,
+ mvbs, mvps);
+
+ if (ret) {
+ DRM_ERROR("%s block check error.\n",
+ block->name);
+ return ret;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+void vpu_pipeline_enable_block(int *combination, int num_planes,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ int i, j, osd_index;
+ struct meson_vpu_traverse *mvt;
+ struct meson_vpu_block **mvb;
+ struct meson_vpu_block *block;
+
+ mvps->enable_blocks = 0;
+
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ mvt = &mvps->osd_traverse[osd_index];
+ mvb = mvt->path[combination[i]];
+
+ for (j = 0; j < MESON_MAX_BLOCKS; j++) {
+ block = mvb[j];
+ if (!block)
+ break;
+ mvps->enable_blocks |= BIT(block->id);
+ }
+ }
+}
+
+/**
+ * combinate_layer_path - combinate every found layer path
+ * @path_num_array: the number of every layer's found path
+ * @num_planes: the number of layer
+ *
+ * use combination algorithm to check whether the path is valid
+ *
+ * RETURNS:
+ * 0 for the valid path or -1 for the invalid path
+ */
+int combinate_layer_path(int *path_num_array, int num_planes,
+ struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state)
+{
+ int i, j, ret;
+ bool is_continue = false;
+ int combination[MESON_MAX_OSDS] = {0};
+
+ i = 0;
+ ret = -1;
+
+ do {
+ // sum the combination result to check osd blend block
+ ret = vpu_pipeline_check_block(combination,
+ num_planes, mvps, state);
+ if (!ret)
+ break;
+
+ i++;
+ combination[num_planes-1] = i;
+
+ for (j = num_planes - 1; j >= 0; j--) {
+ if (combination[j] >= path_num_array[j]) {
+ combination[j] = 0;
+ i = 0;
+ if ((j - 1) >= 0)
+ combination[j - 1] =
+ combination[j - 1] + 1;
+ }
+ }
+
+ is_continue = false;
+
+ for (j = 0; j < num_planes; j++) {
+ if (combination[j] != 0)
+ is_continue = true;
+ }
+ } while (is_continue);
+ if (!ret)
+ vpu_pipeline_enable_block(combination, num_planes, mvps);
+ return ret;
+}
+
+/**
+ * find every layer's path(from start block to the end block) through
+ * pipeline_dfs, combinate every found path of every layer
+ * and check whether the combination is a valid path
+ * that can meet the requirement of hardware limites.
+ *
+ * RETURNS:
+ * 0 for the valid path or -1 for the invalid path
+ */
+int vpu_pipeline_traverse(struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state)
+{
+ int i, osd_index, ret;
+ int num_planes;
+ struct meson_vpu_block *start, *end;
+ int path[MESON_MAX_OSDS] = {0};
+ struct meson_vpu_pipeline *mvp = mvps->pipeline;
+
+ end = &mvp->postblend->base;
+ num_planes = mvps->num_plane;
+
+ if (!num_planes)
+ return 0;
+
+ DRM_DEBUG("traverse num: %d %p.\n", num_planes, mvps);
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ start = &mvp->osds[osd_index]->base;
+ DRM_DEBUG("do pipeline_dfs: OSD%d.\n", (osd_index + 1));
+ pipeline_dfs(osd_index, mvps, start, end, state);
+ }
+
+ // start to combination every layer case
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ path[i] = mvps->osd_traverse[osd_index].num_path;
+ DRM_DEBUG("osd%d traverse path num: %d\n",
+ (osd_index + 1), path[i]);
+ }
+
+ ret = combinate_layer_path(path, num_planes, mvps, state);
+ if (ret)
+ DRM_ERROR("can't find a valid path.\n");
+
+ return ret;
+}
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_vpu_util.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_vpu_util.h"
+
+/*****drm reg access by rdma*****/
+
+u32 meson_drm_rdma_read_reg(u32 addr)
+{
+ return VSYNCOSD_RD_MPEG_REG(addr);
+}
+
+int meson_drm_rdma_write_reg(u32 addr, u32 val)
+{
+ return VSYNCOSD_WR_MPEG_REG(addr, val);
+}
+
+int meson_drm_rdma_write_reg_bits(u32 addr, u32 val, u32 start, u32 len)
+{
+ return VSYNCOSD_WR_MPEG_REG(addr, val, start, len);
+}
+
+int meson_drm_rdma_set_reg_mask(u32 addr, u32 mask)
+{
+ return VSYNCOSD_SET_MPEG_REG_MASK(addr, mask);
+}
+
+int meson_drm_rdma_clr_reg_mask(u32 addr, u32 mask)
+{
+ return VSYNCOSD_CLR_MPEG_REG_MASK(addr, mask);
+}
+
+int meson_drm_rdma_irq_write_reg(u32 addr, u32 val)
+{
+ return VSYNCOSD_IRQ_WR_MPEG_REG(addr, val);
+}
+
+/** reg direct access without rdma **/
+
+u32 meson_drm_read_reg(u32 addr)
+{
+ int ret;
+ u32 val;
+
+ ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &val);
+
+ if (ret) {
+ pr_err("read vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return val;
+}
+
+int meson_drm_write_reg(u32 addr, u32 val)
+{
+ int ret;
+
+ ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, val);
+
+ if (ret) {
+ pr_err("write vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int meson_drm_write_reg_bits(u32 addr, u32 val, u32 start, u32 len)
+{
+ int ret;
+ u32 raw_val;
+
+ ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &raw_val);
+ if (ret) {
+ pr_err("read vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+
+ raw_val |= val & GENMASK(start, start + len);
+
+ ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, raw_val);
+ if (ret) {
+ pr_err("write vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int meson_drm_set_reg_mask(u32 addr, u32 mask)
+{
+ int ret;
+ u32 raw_val;
+
+ ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &raw_val);
+ if (ret) {
+ pr_err("read vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+
+ raw_val |= mask;
+
+ ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, raw_val);
+ if (ret) {
+ pr_err("write vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int meson_drm_clr_reg_mask(u32 addr, u32 mask)
+{
+ int ret;
+ u32 raw_val;
+
+ ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &raw_val);
+ if (ret) {
+ pr_err("read vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+
+ raw_val &= ~mask;
+
+ ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, raw_val);
+ if (ret) {
+ pr_err("write vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return 0;
+}
+
+/** canvas config **/
+
+void meson_drm_canvas_config(u32 index, unsigned long addr, u32 width,
+ u32 height, u32 wrap, u32 blkmode)
+{
+ canvas_config(index, addr, width, height, wrap, blkmode, 0);
+}
+
+int meson_drm_canvas_pool_alloc_table(const char *owner, u32 *table, int size,
+ enum canvas_map_type_e type)
+{
+ return canvas_pool_alloc_canvas_table(owner, table, size, type);
+}
+
+/** vpu clk and block power domain **/
+unsigned int meson_drm_vpu_get_clk(void)
+{
+ return get_vpu_clk();
+}
+
+unsigned int meson_drm_vpu_get_hwblk_clk(unsigned int vmode)
+{
+ return get_vpu_clk_vmode(vmode);
+}
+
+void meson_drm_vpu_set_hwblk_pd(unsigned int vmode, int flag)
+{
+ switch_vpu_mem_pd_vmode(vmode, flag);
+}
+
+int meson_drm_vpu_get_hwblk_pd(unsigned int vmode)
+{
+ return get_vpu_mem_pd_vmode(vmode);
+}
--- /dev/null
+/*
+ * drivers/amlogic/drm/meson_vpu_util.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_VPU_UTIL_H
+#define __MESON_VPU_UTIL_H
+
+#include <linux/types.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/canvas/canvas_mgr.h>
+#include <linux/amlogic/media/vpu/vpu.h>
+#include "osd_rdma.h"
+#include "osd.h"
+
+/*osd internal channel*/
+enum din_channel_e {
+ DIN0 = 0,
+ DIN1,
+ DIN2,
+ DIN3
+};
+
+struct osd_scope_s {
+ u32 h_start;
+ u32 h_end;
+ u32 v_start;
+ u32 v_end;
+};
+
+u32 meson_util_rdma_read_reg(u32 addr);
+int meson_util_rdma_write_reg(u32 addr, u32 val);
+int meson_util_rdma_write_reg_bits(u32 addr, u32 val, u32 start, u32 len);
+int meson_util_rdma_set_reg_mask(u32 addr, u32 mask);
+int meson_util_rdma_clr_reg_mask(u32 addr, u32 mask);
+int meson_util_rdma_irq_write_reg(u32 addr, u32 val);
+
+void meson_util_canvas_config(u32 index, unsigned long addr, u32 width,
+ u32 height, u32 wrap, u32 blkmode);
+int meson_util_canvas_pool_alloc_table(const char *owner, u32 *table, int size,
+ enum canvas_map_type_e type);
+
+unsigned int meson_util_vpu_get_clk(void);
+unsigned int meson_util_vpu_get_hwblk_clk(unsigned int vmode);
+void meson_util_vpu_set_hwblk_pd(unsigned int vmode, int flag);
+int meson_util_vpu_get_hwblk_pd(unsigned int vmode);
+
+extern const struct color_bit_define_s default_color_format_array_1[];
+
+#endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_reg.h"
+#include "meson_vpu_util.h"
+#include "osd.h"
+
+/* osd_mafbc_irq_clear& irq_mask */
+#define OSD_MAFBC_SURFACES_COMPLETED BIT(0)
+#define OSD_MAFBC_CONFI_SWAPPED BIT(1)
+#define OSD_MAFBC_DECODE_ERROR BIT(2)
+#define OSD_MAFBC_DETILING_ERROR BIT(3)
+#define OSD_MAFBC_AXI_ERROR BIT(4)
+#define OSD_MAFBC_SECURE_ID_ERROR BIT(5)
+
+/* osd_mafbc_command */
+#define OSD_MAFBC_DIRECT_SWAP
+#define OSD_MAFBC_PENDING_SWAP
+
+/* osd_mafbc_surface_cfg */
+#define OSD_MAFBC_S0_ENABLE BIT(0)
+#define OSD_MAFBC_S1_ENABLE BIT(1)
+#define OSD_MAFBC_S2_ENABLE BIT(2)
+#define OSD_MAFBC_S3_ENABLE BIT(3)
+#define OSD_MAFBC_DECODE_ENABLE BIT(16)
+
+/* osd_mafbc_axi_cfg */
+#define OSD_MAFBC_AXI_QOS(val) FIELD_PREP(GENMASK(3, 0), val)
+#define OSD_MAFBC_AXI_CACHE(val) FIELD_PREP(GENMASK(7, 4), val)
+
+/* osd_mafbc_format_specifier */
+#define OSD_MAFBC_PIXEL_FORMAT(val) FIELD_PREP(GENMASK(3, 0), val)
+#define OSD_MAFBC_YUV_TRANSFORM BIT(8)
+#define OSD_MAFBC_BLOCK_SPLIT BIT(9)
+#define OSD_MAFBC_SUPER_BLOCK_ASPECT(val) \
+ FIELD_PREP(GENMASK(17, 16), val)
+#define OSD_MAFBC_TILED_HEADER_EN BIT(18)
+#define OSD_MAFBC_PAYLOAD_LIMIT_EN BIT(19)
+
+/* osd_mafbc_prefetch_cfg */
+#define OSD_MAFBC_PREFETCH_READ_DIR_X BIT(0)
+#define OSD_MAFBC_PREFETCH_READ_DIR_Y BIT(1)
+
+static int afbc_pix_format(u32 fmt_mode)
+{
+ u32 pix_format = RGBA8888;
+
+ switch (fmt_mode) {
+ case COLOR_INDEX_YUV_422:
+ pix_format = YUV422_8B;
+ break;
+ case COLOR_INDEX_16_565:
+ pix_format = RGB565;
+ break;
+ case COLOR_INDEX_16_1555_A:
+ pix_format = RGBA5551;
+ break;
+ case COLOR_INDEX_16_4444_R:
+ case COLOR_INDEX_16_4444_A:
+ pix_format = RGBA4444;
+ break;
+ case COLOR_INDEX_32_BGRX:
+ case COLOR_INDEX_32_XBGR:
+ case COLOR_INDEX_32_RGBX:
+ case COLOR_INDEX_32_XRGB:
+ case COLOR_INDEX_32_BGRA:
+ case COLOR_INDEX_32_ABGR:
+ case COLOR_INDEX_32_RGBA:
+ case COLOR_INDEX_32_ARGB:
+ pix_format = RGBA8888;
+ break;
+ case COLOR_INDEX_24_888_B:
+ case COLOR_INDEX_24_RGB:
+ pix_format = RGB888;
+ break;
+ case COLOR_INDEX_RGBA_1010102:
+ pix_format = RGBA1010102;
+ break;
+ default:
+ osd_log_err("unsupport fmt:%x\n", fmt_mode);
+ break;
+ }
+ return pix_format;
+}
+
+static u32 line_stride_calc_afbc(
+ u32 fmt_mode,
+ u32 hsize,
+ u32 stride_align_32bytes)
+{
+ u32 line_stride = 0;
+
+ switch (fmt_mode) {
+ case R8:
+ line_stride = ((hsize << 3) + 127) >> 7;
+ break;
+ case YUV422_8B:
+ case RGB565:
+ case RGBA5551:
+ case RGBA4444:
+ line_stride = ((hsize << 4) + 127) >> 7;
+ break;
+ case RGBA8888:
+ case RGB888:
+ case YUV422_10B:
+ case RGBA1010102:
+ line_stride = ((hsize << 5) + 127) >> 7;
+ break;
+ }
+ /* need wr ddr is 32bytes aligned */
+ if (stride_align_32bytes)
+ line_stride = ((line_stride+1) >> 1) << 1;
+ else
+ line_stride = line_stride;
+ return line_stride;
+}
+
+static void osd_afbc_enable(u32 osd_index, bool flag)
+{
+ if (flag) {
+
+ VSYNCOSD_WR_MPEG_REG_BITS(
+ VPU_MAFBC_SURFACE_CFG,
+ 1, osd_index, 1);
+ VSYNCOSD_WR_MPEG_REG(
+ VPU_MAFBC_IRQ_MASK, 0xf);
+ } else
+ VSYNCOSD_WR_MPEG_REG_BITS(
+ VPU_MAFBC_SURFACE_CFG,
+ 0, osd_index, 1);
+}
+
+static int afbc_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_afbc *afbc = to_afbc_block(vblk);
+
+ //vpu_block_check_input(vblk, state, mvps);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ DRM_DEBUG("%s check_state called.\n", afbc->base.name);
+
+ return 0;
+}
+
+static void osd1_afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ u32 pixel_format, line_stride, output_stride;
+ u32 plane_index, osd_index;
+ u64 header_addr, out_addr;
+ u32 aligned_32, afbc_color_reorder;
+ unsigned int depth;
+ int bpp;
+ struct meson_vpu_afbc *afbc;
+ struct meson_vpu_afbc_state *afbc_state;
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+
+ afbc = to_afbc_block(vblk);
+ afbc_state = to_afbc_state(state);
+ pipeline = vblk->pipeline;
+ osd_index = vblk->index;
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ plane_index = pipeline_state->ratio_plane_index[osd_index];
+ plane_info = &pipeline_state->plane_info[plane_index];
+
+ if (!plane_info->afbc_en)
+ return;
+
+ osd_afbc_enable(0, 1);
+
+ aligned_32 = 1;
+ afbc_color_reorder = 0x1234;
+ pixel_format = afbc_pix_format(plane_info->pixel_format);
+ drm_fb_get_bpp_depth(plane_info->pixel_format, &depth, &bpp);
+ header_addr = plane_info->phy_addr;
+
+ line_stride = line_stride_calc_afbc(pixel_format,
+ plane_info->src_w, aligned_32);
+
+ output_stride = plane_info->src_w * bpp;
+
+ header_addr = plane_info->phy_addr;
+ out_addr = ((u64)(vblk->index + 1)) << 24;
+
+ /* set osd path misc ctrl */
+ VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1);
+
+ /* set linear addr */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT, 0x1, 2, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT2, 1, 1, 1);
+
+ /* set read from mali */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK0_CFG_W0, 0x1, 30, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK0_CFG_W0, 0, 15, 1);
+
+ /* set line_stride */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK2_CFG_W4, line_stride, 0, 12);
+
+ /* set frame addr */
+ VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK1_CFG_W4, out_addr & 0xffffffff);
+
+ /* set afbc color reorder and mali src*/
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_MALI_UNPACK_CTRL,
+ afbc_color_reorder, 0, 16);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_MALI_UNPACK_CTRL, 0x1, 31, 1);
+
+ /* set header addr */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0,
+ header_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0,
+ (header_addr >> 32) & 0xffffffff);
+
+ /* set format specifier */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_FORMAT_SPECIFIER_S0,
+ plane_info->afbc_inter_format | (pixel_format & 0x0f));
+
+ /* set pic size */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_WIDTH_S0, plane_info->src_w);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_HEIGHT_S0, plane_info->src_h);
+
+ /* set buf stride */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_STRIDE_S0, output_stride);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set bounding box */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_START_S0,
+ plane_info->src_x);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_END_S0,
+ (plane_info->src_x + plane_info->src_w - 1));
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_START_S0,
+ plane_info->src_y);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_END_S0,
+ (plane_info->src_y + plane_info->src_h - 1));
+
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1);
+
+ DRM_DEBUG("%s set_state called.\n", afbc->base.name);
+}
+
+static void osd2_afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ u32 pixel_format, line_stride, output_stride;
+ u32 plane_index, osd_index;
+ u64 header_addr, out_addr;
+ u32 aligned_32, afbc_color_reorder;
+ unsigned int depth;
+ int bpp;
+ struct meson_vpu_afbc *afbc;
+ struct meson_vpu_afbc_state *afbc_state;
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+
+ afbc = to_afbc_block(vblk);
+ afbc_state = to_afbc_state(state);
+ pipeline = vblk->pipeline;
+ osd_index = vblk->index;
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ plane_index = pipeline_state->ratio_plane_index[osd_index];
+ plane_info = &pipeline_state->plane_info[plane_index];
+
+ if (!plane_info->afbc_en)
+ return;
+
+ osd_afbc_enable(1, 1);
+
+ aligned_32 = 1;
+ afbc_color_reorder = 0x1234;
+ pixel_format = afbc_pix_format(plane_info->pixel_format);
+ drm_fb_get_bpp_depth(plane_info->pixel_format, &depth, &bpp);
+ header_addr = plane_info->phy_addr;
+
+ line_stride = line_stride_calc_afbc(pixel_format,
+ plane_info->src_w, aligned_32);
+
+ output_stride = plane_info->src_w * bpp;
+
+ header_addr = plane_info->phy_addr;
+ out_addr = ((u64)(vblk->index + 1)) << 24;
+
+ /* set osd path misc ctrl */
+ VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1);
+
+ /* set linear addr */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_CTRL_STAT, 0x1, 2, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_CTRL_STAT2, 1, 1, 1);
+
+ /* set read from mali */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK0_CFG_W0, 0x1, 30, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK0_CFG_W0, 0, 15, 1);
+
+ /* set line_stride */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK2_CFG_W4, line_stride, 0, 12);
+
+ /* set frame addr */
+ VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK1_CFG_W4, out_addr & 0xffffffff);
+
+ /* set afbc color reorder and mali src*/
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_MALI_UNPACK_CTRL,
+ afbc_color_reorder, 0, 16);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_MALI_UNPACK_CTRL, 0x1, 31, 1);
+
+ /* set header addr */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1,
+ header_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1,
+ (header_addr >> 32) & 0xffffffff);
+
+ /* set format specifier */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_FORMAT_SPECIFIER_S1,
+ plane_info->afbc_inter_format | (pixel_format & 0x0f));
+
+ /* set pic size */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_WIDTH_S1, plane_info->src_w);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_HEIGHT_S1, plane_info->src_h);
+
+ /* set buf stride */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_STRIDE_S1, output_stride);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set bounding box */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_START_S1,
+ plane_info->src_x);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_END_S1,
+ (plane_info->src_x + plane_info->src_w - 1));
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_START_S1,
+ plane_info->src_y);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_END_S1,
+ (plane_info->src_y + plane_info->src_h - 1));
+
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1);
+
+ DRM_DEBUG("%s set_state called.\n", afbc->base.name);
+}
+
+static void osd3_afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ u32 pixel_format, line_stride, output_stride;
+ u32 plane_index, osd_index;
+ u64 header_addr, out_addr;
+ u32 aligned_32, afbc_color_reorder;
+ unsigned int depth;
+ int bpp;
+ struct meson_vpu_afbc *afbc;
+ struct meson_vpu_afbc_state *afbc_state;
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+
+ afbc = to_afbc_block(vblk);
+ afbc_state = to_afbc_state(state);
+ pipeline = vblk->pipeline;
+ osd_index = vblk->index;
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ plane_index = pipeline_state->ratio_plane_index[osd_index];
+ plane_info = &pipeline_state->plane_info[plane_index];
+
+ if (!plane_info->afbc_en)
+ return;
+
+ osd_afbc_enable(2, 1);
+
+ aligned_32 = 1;
+ afbc_color_reorder = 0x1234;
+ pixel_format = afbc_pix_format(plane_info->pixel_format);
+ drm_fb_get_bpp_depth(plane_info->pixel_format, &depth, &bpp);
+ header_addr = plane_info->phy_addr;
+
+ line_stride = line_stride_calc_afbc(pixel_format,
+ plane_info->src_w, aligned_32);
+
+ output_stride = plane_info->src_w * bpp;
+
+ header_addr = plane_info->phy_addr;
+ out_addr = ((u64)(vblk->index + 1)) << 24;
+
+ /* set osd path misc ctrl */
+ VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1);
+
+ /* set linear addr */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_CTRL_STAT, 0x1, 2, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_CTRL_STAT2, 1, 1, 1);
+
+ /* set read from mali */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_BLK0_CFG_W0, 0x1, 30, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_BLK0_CFG_W0, 0, 15, 1);
+
+ /* set line_stride */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_BLK2_CFG_W4, line_stride, 0, 12);
+
+ /* set frame addr */
+ VSYNCOSD_WR_MPEG_REG(VIU_OSD3_BLK1_CFG_W4, out_addr & 0xffffffff);
+
+ /* set afbc color reorder and mali src*/
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_MALI_UNPACK_CTRL,
+ afbc_color_reorder, 0, 16);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_MALI_UNPACK_CTRL, 0x1, 31, 1);
+
+ /* set header addr */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2,
+ header_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2,
+ (header_addr >> 32) & 0xffffffff);
+
+ /* set format specifier */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_FORMAT_SPECIFIER_S2,
+ plane_info->afbc_inter_format | (pixel_format & 0x0f));
+
+ /* set pic size */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_WIDTH_S2, plane_info->src_w);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_HEIGHT_S2, plane_info->src_h);
+
+ /* set buf stride */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_STRIDE_S2, output_stride);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set bounding box */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_START_S2,
+ plane_info->src_x);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_END_S2,
+ (plane_info->src_x + plane_info->src_w - 1));
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_START_S2,
+ plane_info->src_y);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_END_S2,
+ (plane_info->src_y + plane_info->src_h - 1));
+
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1);
+
+ DRM_DEBUG("%s set_state called.\n", afbc->base.name);
+}
+
+#if 0
+static void osd_afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ u32 bpp, pixel_format, line_stride, output_stride;
+ u32 plane_index, osd_index;
+ u64 header_addr, out_addr;
+ const struct color_bit_define_s *color_info;
+ struct meson_vpu_afbc *afbc;
+ struct meson_vpu_afbc_state *afbc_state;
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+ struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index];
+
+ afbc = to_afbc_block(vblk);
+ afbc_state = to_afbc_state(state);
+ pipeline = vblk->pipeline;
+ osd_index = vblk->index;
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ plane_index = pipeline_state->ratio_plane_index[osd_index];
+ plane_info = pipeline_state->plane_info[plane_index];
+
+ u32 aligned_32 = 1;
+ u32 afbc_color_reorder = 0x1234;
+
+ pixel_format = afbc_pix_format(plane_info->pixel_format);
+ color_info = convert_panel_format(pixel_format);
+ header_addr = plane_info->phy_addr;
+
+ bpp = color_info->bpp >> 3;
+ line_stride = line_stride_calc_afbc(pixel_format,
+ plane_info->src_w, aligned_32);
+
+ output_stride = plane_info->src_w * bpp;
+
+ header_addr = plane_info->phy_addr;
+ out_addr = ((u64)(vblk->index + 1)) << 24;
+
+ /* set osd path misc ctrl */
+ VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1);
+
+ /* set linear addr */
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_ctrl_stat, 0x1, 2, 1);
+
+ /* set read from mali */
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_blk0_cfg_w0, 0x1, 30, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_blk0_cfg_w0, 0, 15, 1);
+
+ /* set line_stride */
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_blk2_cfg_w4, line_stride, 0, 12);
+
+ /* set frame addr */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->osd_blk1_cfg_w4, out_addr & 0xffffffff);
+
+ /* set afbc color reorder and mali src*/
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_mali_unpack_ctrl,
+ afbc_color_reorder, 0, 16);
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_mali_unpack_ctrl, 0x1, 31, 1);
+
+ /* set header addr */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_header_buf_addr_low_s,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_header_buf_addr_high_s,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set format specifier */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_format_specifier_s,
+ plane_info->inter_format | (pixel_format & 0x0f));
+
+ /* set pic size */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_buffer_width_s, plane_info->src_w);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_buffer_hight_s, plane_info->src_h);
+
+ /* set buf stride */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_output_buf_stride_s, output_stride);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_output_buf_addr_low_s,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_output_buf_addr_high_s,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set bounding box */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_x_start_s,
+ plane_info->src_x);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_x_end_s,
+ (palne_info->src_x + plane_info->src_w - 1));
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_y_start_s,
+ plane_info->src_y);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_y_end_s,
+ (plane_info->src_y + plane_info->src_h - 1));
+
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1);
+
+ DRM_DEBUG("%s set_state called.\n", afbc->base.name);
+}
+#endif
+
+static void afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+#if 0
+ osd_afbc_set_state(vblk, state);
+#else
+ switch (vblk->index) {
+ case 0:
+ osd1_afbc_set_state(vblk, state);
+ break;
+ case 1:
+ osd2_afbc_set_state(vblk, state);
+ break;
+ case 2:
+ osd3_afbc_set_state(vblk, state);
+ break;
+ default:
+ break;
+ }
+#endif
+
+}
+
+static void afbc_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_afbc *afbc = to_afbc_block(vblk);
+ u32 osd_index = vblk->index;
+
+ osd_afbc_enable(osd_index, 1);
+
+ DRM_DEBUG("%s enable called.\n", afbc->base.name);
+}
+
+static void afbc_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_afbc *afbc = to_afbc_block(vblk);
+ u32 osd_index = vblk->index;
+
+ osd_afbc_enable(osd_index, 0);
+
+ DRM_DEBUG("%s disable called.\n", afbc->base.name);
+}
+
+static void afbc_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_afbc *afbc = to_afbc_block(vblk);
+
+ switch_vpu_mem_pd_vmod(VPU_MAIL_AFBCD,
+ VPU_MEM_POWER_ON);
+ /* disable osd1 afbc */
+ osd_afbc_enable(0, 0);
+ osd_afbc_enable(1, 0);
+ osd_afbc_enable(2, 0);
+
+ DRM_DEBUG("%s hw_init called.\n", afbc->base.name);
+}
+
+struct meson_vpu_block_ops afbc_ops = {
+ .check_state = afbc_check_state,
+ .update_state = afbc_set_state,
+ .enable = afbc_hw_enable,
+ .disable = afbc_hw_disable,
+ .init = afbc_hw_init,
+};
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_reg.h"
+#include "meson_vpu_util.h"
+#include "meson_osd_scaler.h"
+
+static struct osd_scaler_reg_s osd_scaler_reg[HW_OSD_SCALER_NUM] = {
+ {
+ VPP_OSD_SCALE_COEF_IDX,
+ VPP_OSD_SCALE_COEF,
+ VPP_OSD_VSC_PHASE_STEP,
+ VPP_OSD_VSC_INI_PHASE,
+ VPP_OSD_VSC_CTRL0,
+ VPP_OSD_HSC_PHASE_STEP,
+ VPP_OSD_HSC_INI_PHASE,
+ VPP_OSD_HSC_CTRL0,
+ VPP_OSD_HSC_INI_PAT_CTRL,
+ VPP_OSD_SC_DUMMY_DATA,
+ VPP_OSD_SC_CTRL0,
+ VPP_OSD_SCI_WH_M1,
+ VPP_OSD_SCO_H_START_END,
+ VPP_OSD_SCO_V_START_END,
+ },
+ {
+ OSD2_SCALE_COEF_IDX,
+ OSD2_SCALE_COEF,
+ OSD2_VSC_PHASE_STEP,
+ OSD2_VSC_INI_PHASE,
+ OSD2_VSC_CTRL0,
+ OSD2_HSC_PHASE_STEP,
+ OSD2_HSC_INI_PHASE,
+ OSD2_HSC_CTRL0,
+ OSD2_HSC_INI_PAT_CTRL,
+ OSD2_SC_DUMMY_DATA,
+ OSD2_SC_CTRL0,
+ OSD2_SCI_WH_M1,
+ OSD2_SCO_H_START_END,
+ OSD2_SCO_V_START_END,
+ },
+ {
+ OSD34_SCALE_COEF_IDX,
+ OSD34_SCALE_COEF,
+ OSD34_VSC_PHASE_STEP,
+ OSD34_VSC_INI_PHASE,
+ OSD34_VSC_CTRL0,
+ OSD34_HSC_PHASE_STEP,
+ OSD34_HSC_INI_PHASE,
+ OSD34_HSC_CTRL0,
+ OSD34_HSC_INI_PAT_CTRL,
+ OSD34_SC_DUMMY_DATA,
+ OSD34_SC_CTRL0,
+ OSD34_SCI_WH_M1,
+ OSD34_SCO_H_START_END,
+ OSD34_SCO_V_START_END,
+ }
+};
+
+static unsigned int __osd_filter_coefs_bicubic[] = { /* bicubic coef0 */
+ 0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300, 0xfd7e0500, 0xfc7e0600,
+ 0xfb7d0800, 0xfb7c0900, 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
+ 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe, 0xf76f1dfd, 0xf76d1ffd,
+ 0xf76b21fd, 0xf76824fd, 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
+ 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa, 0xf8523cfa, 0xf8503ff9,
+ 0xf84d42f9, 0xf84a45f9, 0xf84848f8
+};
+
+/*********vsc config begin**********/
+/*vsc phase_step=(v_in << 20)/v_out */
+void osd_vsc_phase_step_set(struct osd_scaler_reg_s *reg, u32 phase_step)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_phase_step,
+ phase_step, 0, 28);
+}
+/*vsc init phase*/
+void osd_vsc_init_phase_set(struct osd_scaler_reg_s *reg,
+ u32 bottom_init_phase, u32 top_init_phase)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_vsc_ini_phase,
+ (bottom_init_phase << 16) |
+ (top_init_phase << 0));
+}
+/*vsc control*/
+/*vsc enable last line repeate*/
+void osd_vsc_repate_last_line_enable_set(
+ struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 25, 1);
+}
+/*vsc enable*/
+void osd_vsc_enable_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 24, 1);
+}
+/*vsc input Interlaced or Progressive:0->P;1->I*/
+void osd_vsc_output_format_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 23, 1);
+}
+/*
+ *vsc double line mode
+ *bit0:change line buffer becomes 2 lines
+ *bit1:double input width and half input height
+ */
+void osd_vsc_double_line_mode_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 21, 2);
+}
+/*vsc phase always on*/
+void osd_vsc_phase_always_on_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 20, 1);
+}
+/*vsc nearest en*/
+void osd_vsc_nearest_en_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 19, 1);
+}
+/*vsc repeate bottom field line0 num*/
+void osd_vsc_bot_rpt_l0_num_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 16, 2);
+}
+/*vsc bottom field init receive num??*/
+void osd_vsc_bot_ini_rcv_num_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 11, 4);
+}
+/*vsc repeate top field line0 num*/
+void osd_vsc_top_rpt_l0_num_set(struct osd_scaler_reg_s *reg, u32 flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 8, 2);
+}
+/*vsc top field init receive num??*/
+void osd_vsc_top_ini_rcv_num_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 3, 4);
+}
+/*vsc bank length??*/
+void osd_vsc_bank_length_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 0, 2);
+}
+/*********vsc config end**********/
+
+/*********hsc config begin**********/
+/*hsc phase_step=(v_in << 20)/v_out */
+void osd_hsc_phase_step_set(struct osd_scaler_reg_s *reg, u32 phase_step)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_phase_step,
+ phase_step, 0, 28);
+}
+/*vsc init phase*/
+void osd_hsc_init_phase_set(struct osd_scaler_reg_s *reg,
+ u32 init_phase0, u32 init_phase1)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_hsc_ini_phase,
+ (init_phase1 << 16) | (init_phase0 << 0));
+}
+/*hsc control*/
+/*hsc enable*/
+void osd_hsc_enable_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 22, 1);
+}
+/* hsc double pixel mode */
+void osd_hsc_double_line_mode_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 21, 1);
+}
+/*hsc phase always on*/
+void osd_hsc_phase_always_on_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 20, 1);
+}
+/*hsc nearest en*/
+void osd_hsc_nearest_en_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 19, 1);
+}
+/*hsc repeate pixel0 num1??*/
+void osd_hsc_rpt_p0_num1_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 16, 2);
+}
+/*hsc init receive num1*/
+void osd_vsc_ini_rcv_num1_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 11, 4);
+}
+/*hsc repeate pixel0 num0*/
+void osd_hsc_rpt_p0_num0_set(struct osd_scaler_reg_s *reg, u32 flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 8, 2);
+}
+/*hsc init receive num0*/
+void osd_hsc_ini_rcv_num0_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 3, 4);
+}
+/*hsc bank length*/
+void osd_hsc_bank_length_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 0, 2);
+}
+/*
+ *hsc init pattern
+ *[15:8]pattern
+ *[6:4]pattern start
+ *[2:0]pattern end
+ */
+void osd_hsc_ini_pat_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_hsc_ini_pat_ctrl, data);
+}
+/*********hsc config end**********/
+
+/*********sc top ctrl start**********/
+/*
+ *dummy data:
+ *[31:24]componet0
+ *[23:16]componet1
+ *[15:8]componet2
+ *[7:0]alpha
+ */
+void osd_sc_dummy_data_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_sc_dummy_data, data);
+}
+/*sc gate clock*/
+void osd_sc_gclk_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, data, 16, 12);
+}
+/*
+ *sc input data alpha mode
+ *0:(alpha>=128)?alpha-1:alpha
+ *1:(alpha>=1)?alpha-1:alpha
+ */
+void osd_sc_din_alpha_mode_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 13, 1);
+}
+/*
+ *sc output data alpha mode
+ *0:(alpha>=128)?alpha+1:alpha
+ *1:(alpha>=1)?alpha+1:alpha
+ */
+void osd_sc_dout_alpha_mode_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 12, 1);
+}
+/*sc alpha*/
+void osd_sc_alpha_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, data, 4, 8);
+}
+/*sc path en*/
+void osd_sc_path_en_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 3, 1);
+}
+/*sc en*/
+void osd_sc_en_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 2, 1);
+}
+/*sc input width minus 1*/
+void osd_sc_in_w_set(struct osd_scaler_reg_s *reg, u32 size)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sci_wh_m1, (size - 1), 16, 13);
+}
+/*sc input height minus 1*/
+void osd_sc_in_h_set(struct osd_scaler_reg_s *reg, u32 size)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sci_wh_m1, (size - 1), 0, 13);
+}
+/*sc output horizontal size = end - start + 1*/
+void osd_sc_out_horz_set(struct osd_scaler_reg_s *reg, u32 start, u32 end)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_sco_h_start_end,
+ (start & 0xfff << 16) | (end & 0xfff));
+}
+
+/*sc output vertical size = end - start + 1*/
+void osd_sc_out_vert_set(struct osd_scaler_reg_s *reg, u32 start, u32 end)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_sco_v_start_end,
+ (start & 0xfff << 16) | (end & 0xfff));
+}
+
+/*
+ *sc h/v coef
+ *1:config horizontal coef
+ *0:config vertical coef
+ */
+void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ u8 i;
+
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef_idx,
+ (0 << 15) |/*index increment. 1bits*/
+ (0 << 14) |/*read coef enable, 1bits*/
+ (0 << 9) |/*coef bit mode 8 or 9. 1bits*/
+ (flag << 8) |
+ (0 << 0)/*coef index 7bits*/);
+ for (i = 0; i < 33; i++)
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef,
+ __osd_filter_coefs_bicubic[i]);
+}
+/*********sc top ctrl end************/
+static void f2v_get_vertical_phase(
+ u32 zoom_ratio, enum f2v_vphase_type_e type,
+ u8 bank_length, struct f2v_vphase_s *vphase)
+{
+ u8 f2v_420_in_pos_luma[F2V_TYPE_MAX] = {
+ 0, 2, 0, 2, 0, 0, 0, 2, 0};
+ u8 f2v_420_out_pos[F2V_TYPE_MAX] = {
+ 0, 2, 2, 0, 0, 2, 0, 0, 0};
+ s32 offset_in, offset_out;
+
+ /* luma */
+ offset_in = f2v_420_in_pos_luma[type]
+ << OSD_PHASE_BITS;
+ offset_out = (f2v_420_out_pos[type] * zoom_ratio)
+ >> (OSD_ZOOM_HEIGHT_BITS - OSD_PHASE_BITS);
+
+ vphase->rcv_num = bank_length;
+ if (bank_length == 4 || bank_length == 3)
+ vphase->rpt_num = 1;
+ else
+ vphase->rpt_num = 0;
+
+ if (offset_in > offset_out) {
+ vphase->rpt_num = vphase->rpt_num + 1;
+ vphase->phase =
+ ((4 << OSD_PHASE_BITS) + offset_out - offset_in)
+ >> 2;
+ } else {
+ while ((offset_in + (4 << OSD_PHASE_BITS))
+ <= offset_out) {
+ if (vphase->rpt_num == 1)
+ vphase->rpt_num = 0;
+ else
+ vphase->rcv_num++;
+ offset_in += 4 << OSD_PHASE_BITS;
+ }
+ vphase->phase = (offset_out - offset_in) >> 2;
+ }
+}
+void osd_scaler_config(struct osd_scaler_reg_s *reg,
+ struct meson_vpu_scaler_state *scaler_state,
+ struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+ u32 phase_step_v, phase_step_h, vsc_top_init_rec_num, vsc_bank_length;
+ u32 hsc_init_rec_num, hsc_init_rpt_p0_num, hsc_bank_length;
+ u32 vsc_bot_init_rec_num, vsc_top_rpt_l0_num, vsc_bot_rpt_l0_num;
+ u32 vsc_top_init_phase, vsc_bot_init_phase;
+ struct f2v_vphase_s vphase;
+ u8 version = vblk->pipeline->osd_version;
+ u32 linebuffer = scaler->linebuffer;
+ u32 bank_length = scaler->bank_length;
+ u32 width_in = scaler_state->input_width;
+ u32 height_in = scaler_state->input_height;
+ u32 width_out = scaler_state->output_width;
+ u32 height_out = scaler_state->output_height;
+ u32 scan_mode_out = scaler_state->scan_mode_out;
+ bool scaler_enable;
+
+ if (width_in == width_out && height_in == height_out &&
+ version > OSD_V2)
+ scaler_enable = false;
+ else
+ scaler_enable = true;
+
+ if (width_out > linebuffer)
+ vsc_bank_length = bank_length >> 1;
+ else
+ vsc_bank_length = bank_length;
+ hsc_init_rec_num = bank_length;
+ hsc_bank_length = bank_length;
+ hsc_init_rpt_p0_num = bank_length / 2 - 1;
+
+ if (version <= OSD_V2)
+ phase_step_v = ((height_in - 1) << OSD_ZOOM_HEIGHT_BITS) /
+ height_out;
+ else
+ phase_step_v =
+ (height_in << OSD_ZOOM_HEIGHT_BITS) / height_out;
+ if (scan_mode_out) {
+ f2v_get_vertical_phase(phase_step_v, F2V_P2IT,
+ vsc_bank_length, &vphase);
+ vsc_top_init_rec_num = vphase.rcv_num;
+ vsc_top_rpt_l0_num = vphase.rpt_num;
+ vsc_top_init_phase = vphase.phase;
+ f2v_get_vertical_phase(phase_step_v, F2V_P2IB,
+ vsc_bank_length, &vphase);
+ vsc_bot_init_rec_num = vphase.rcv_num;
+ vsc_bot_rpt_l0_num = vphase.rpt_num;
+ vsc_bot_init_phase = vphase.phase;
+ } else {
+ f2v_get_vertical_phase(
+ phase_step_v, F2V_P2P,
+ vsc_bank_length, &vphase);
+ vsc_top_init_rec_num = vphase.rcv_num;
+ vsc_top_rpt_l0_num = vphase.rpt_num;
+ vsc_top_init_phase = vphase.phase;
+ vsc_bot_init_rec_num = 0;
+ vsc_bot_rpt_l0_num = 0;
+ vsc_bot_init_phase = 0;
+ }
+ if (version <= OSD_V2)
+ vsc_top_init_rec_num++;
+ if (version <= OSD_V2 && scan_mode_out)
+ vsc_bot_init_rec_num++;
+ phase_step_v <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_HEIGHT_BITS);
+ phase_step_h = (width_in << OSD_ZOOM_WIDTH_BITS) / width_out;
+ phase_step_h <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_WIDTH_BITS);
+
+ /*input size config*/
+ osd_sc_in_h_set(reg, height_in);
+ osd_sc_in_w_set(reg, width_in);
+
+ /*output size config*/
+ osd_sc_out_horz_set(reg, 0, width_out - 1);
+ osd_sc_out_vert_set(reg, 0, height_out - 1);
+
+ /*phase step config*/
+ osd_vsc_phase_step_set(reg, phase_step_v);
+ osd_hsc_phase_step_set(reg, phase_step_h);
+
+ /*dummy data config*/
+ osd_sc_dummy_data_set(reg, 0x80808080);
+
+ /*h/v coef config*/
+ osd_sc_coef_set(reg, 1);
+ osd_sc_coef_set(reg, 0);
+
+ /*init recv line num*/
+ osd_vsc_top_ini_rcv_num_set(reg, vsc_top_init_rec_num);
+ osd_vsc_bot_ini_rcv_num_set(reg, vsc_bot_init_rec_num);
+ osd_hsc_ini_rcv_num0_set(reg, hsc_init_rec_num);
+
+ /*repeate line0 num*/
+ osd_vsc_top_rpt_l0_num_set(reg, vsc_top_rpt_l0_num);
+ osd_vsc_bot_rpt_l0_num_set(reg, vsc_bot_rpt_l0_num);
+ osd_hsc_rpt_p0_num0_set(reg, hsc_init_rpt_p0_num);
+
+ /*init phase*/
+ osd_vsc_init_phase_set(reg, vsc_bot_init_phase, vsc_top_init_phase);
+ osd_hsc_init_phase_set(reg, 0, 0);
+
+ /*vsc bank length*/
+ osd_vsc_bank_length_set(reg, vsc_bank_length);
+ osd_hsc_bank_length_set(reg, hsc_bank_length);
+
+ /*out scan mode*/
+ osd_vsc_output_format_set(reg, scan_mode_out ? 1:0);
+
+ /*repeate last line*/
+ if (version >= OSD_V2)
+ osd_vsc_repate_last_line_enable_set(reg, 1);
+
+ /*eanble sc*/
+ osd_vsc_enable_set(reg, scaler_enable);
+ osd_hsc_enable_set(reg, scaler_enable);
+ osd_sc_en_set(reg, scaler_enable);
+ osd_sc_path_en_set(reg, scaler_enable);
+}
+
+static void scaler_size_check(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_pipeline *pipeline = vblk->pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+ struct meson_vpu_scaler_state *scaler_state = to_scaler_state(state);
+
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ if (!pipeline_state) {
+ DRM_DEBUG("pipeline_state is NULL!!\n");
+ return;
+ }
+ if (scaler_state->input_width !=
+ pipeline_state->scaler_param[vblk->index].input_width) {
+ scaler_state->input_width =
+ pipeline_state->scaler_param[vblk->index].input_width;
+ scaler_state->state_changed |= SCALER_INPUT_WIDTH_CHANGED;
+ }
+ if (scaler_state->input_height !=
+ pipeline_state->scaler_param[vblk->index].input_height) {
+ scaler_state->input_height =
+ pipeline_state->scaler_param[vblk->index].input_height;
+ scaler_state->state_changed |= SCALER_INPUT_HEIGHT_CHANGED;
+ }
+ if (scaler_state->output_width !=
+ pipeline_state->scaler_param[vblk->index].output_width) {
+ scaler_state->output_width =
+ pipeline_state->scaler_param[vblk->index].output_width;
+ scaler_state->state_changed |= SCALER_OUTPUT_WIDTH_CHANGED;
+ }
+ if (scaler_state->output_height !=
+ pipeline_state->scaler_param[vblk->index].output_height) {
+ scaler_state->output_height =
+ pipeline_state->scaler_param[vblk->index].output_height;
+ scaler_state->state_changed |= SCALER_OUTPUT_HEIGHT_CHANGED;
+ }
+}
+
+void scan_mode_check(struct meson_vpu_pipeline *pipeline,
+ struct meson_vpu_scaler_state *scaler_state)
+{
+ u32 scan_mode_out = pipeline->mode.flags & DRM_MODE_FLAG_INTERLACE;
+
+ if (scaler_state->scan_mode_out != scan_mode_out) {
+ scaler_state->scan_mode_out = scan_mode_out;
+ scaler_state->state_changed |=
+ SCALER_OUTPUT_SCAN_MODE_CHANGED;
+ }
+}
+
+static int scaler_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+ DRM_DEBUG("%s check_state called.\n", scaler->base.name);
+
+ return 0;
+}
+
+static void scaler_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+ struct meson_vpu_scaler_state *scaler_state = to_scaler_state(state);
+ struct osd_scaler_reg_s *reg = scaler->reg;
+
+ if (!scaler_state) {
+ DRM_DEBUG("scaler or scaler_state is NULL!!\n");
+ return;
+ }
+ scaler_size_check(vblk, state);
+ scan_mode_check(vblk->pipeline, scaler_state);
+ DRM_DEBUG("scaler_state=0x%x\n", scaler_state->state_changed);
+ if (scaler_state->state_changed) {
+ osd_scaler_config(reg, scaler_state, vblk);
+ scaler_state->state_changed = 0;
+ }
+ DRM_DEBUG("scaler%d input/output w/h[%d, %d, %d, %d].\n",
+ scaler->base.index,
+ scaler_state->input_width, scaler_state->input_height,
+ scaler_state->output_width, scaler_state->output_height);
+}
+
+static void scaler_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+ struct osd_scaler_reg_s *reg = scaler->reg;
+
+ osd_sc_en_set(reg, 1);
+ osd_sc_path_en_set(reg, 1);
+ DRM_DEBUG("%s enable done.\n", scaler->base.name);
+}
+
+static void scaler_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+ struct osd_scaler_reg_s *reg = scaler->reg;
+
+ /*disable sc*/
+ osd_sc_en_set(reg, 0);
+ osd_sc_path_en_set(reg, 0);
+ DRM_DEBUG("%s disable called.\n", scaler->base.name);
+}
+
+static void scaler_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+
+ scaler->reg = &osd_scaler_reg[vblk->index];
+ scaler->linebuffer = OSD_SCALE_LINEBUFFER;
+ scaler->bank_length = OSD_SCALE_BANK_LENGTH;
+ /*disable sc*/
+ osd_sc_en_set(scaler->reg, 0);
+ osd_sc_path_en_set(scaler->reg, 0);
+ DRM_DEBUG("%s hw_init called.\n", scaler->base.name);
+}
+
+struct meson_vpu_block_ops scaler_ops = {
+ .check_state = scaler_check_state,
+ .update_state = scaler_set_state,
+ .enable = scaler_hw_enable,
+ .disable = scaler_hw_disable,
+ .init = scaler_hw_init,
+};
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _MESON_OSD_SCALER_H_
+#define _MESON_OSD_SCALER_H_
+
+#define HW_OSD_SCALER_NUM 3
+
+/*vpp osd scaler*/
+#define VPP_OSD_VSC_PHASE_STEP 0x1dc0
+#define VPP_OSD_VSC_INI_PHASE 0x1dc1
+#define VPP_OSD_VSC_CTRL0 0x1dc2
+#define VPP_OSD_HSC_PHASE_STEP 0x1dc3
+#define VPP_OSD_HSC_INI_PHASE 0x1dc4
+#define VPP_OSD_HSC_CTRL0 0x1dc5
+#define VPP_OSD_HSC_INI_PAT_CTRL 0x1dc6
+#define VPP_OSD_SC_DUMMY_DATA 0x1dc7
+#define VPP_OSD_SC_CTRL0 0x1dc8
+#define VPP_OSD_SCI_WH_M1 0x1dc9
+#define VPP_OSD_SCO_H_START_END 0x1dca
+#define VPP_OSD_SCO_V_START_END 0x1dcb
+#define VPP_OSD_SCALE_COEF_IDX 0x1dcc
+#define VPP_OSD_SCALE_COEF 0x1dcd
+
+/* vpp osd2 scaler */
+#define OSD2_VSC_PHASE_STEP 0x3d00
+#define OSD2_VSC_INI_PHASE 0x3d01
+#define OSD2_VSC_CTRL0 0x3d02
+#define OSD2_HSC_PHASE_STEP 0x3d03
+#define OSD2_HSC_INI_PHASE 0x3d04
+#define OSD2_HSC_CTRL0 0x3d05
+#define OSD2_HSC_INI_PAT_CTRL 0x3d06
+#define OSD2_SC_DUMMY_DATA 0x3d07
+#define OSD2_SC_CTRL0 0x3d08
+#define OSD2_SCI_WH_M1 0x3d09
+#define OSD2_SCO_H_START_END 0x3d0a
+#define OSD2_SCO_V_START_END 0x3d0b
+#define OSD2_SCALE_COEF_IDX 0x3d18
+#define OSD2_SCALE_COEF 0x3d19
+
+/* vpp osd34 scaler */
+#define OSD34_VSC_PHASE_STEP 0x3d20
+#define OSD34_VSC_INI_PHASE 0x3d21
+#define OSD34_VSC_CTRL0 0x3d22
+#define OSD34_HSC_PHASE_STEP 0x3d23
+#define OSD34_HSC_INI_PHASE 0x3d24
+#define OSD34_HSC_CTRL0 0x3d25
+#define OSD34_HSC_INI_PAT_CTRL 0x3d26
+#define OSD34_SC_DUMMY_DATA 0x3d27
+#define OSD34_SC_CTRL0 0x3d28
+#define OSD34_SCI_WH_M1 0x3d29
+#define OSD34_SCO_H_START_END 0x3d2a
+#define OSD34_SCO_V_START_END 0x3d2b
+#define OSD34_SCALE_COEF_IDX 0x3d1e
+#define OSD34_SCALE_COEF 0x3d1f
+
+
+/*macro define for chip const*/
+/*bank length is related to scale fifo:4 line 1920??*/
+#define OSD_SCALE_BANK_LENGTH 4
+#define OSD_SCALE_LINEBUFFER 1920
+
+#define OSD_ZOOM_WIDTH_BITS 18
+#define OSD_ZOOM_HEIGHT_BITS 20
+#define OSD_ZOOM_TOTAL_BITS 24
+#define OSD_PHASE_BITS 16
+
+enum f2v_vphase_type_e {
+ F2V_IT2IT = 0,
+ F2V_IB2IB,
+ F2V_IT2IB,
+ F2V_IB2IT,
+ F2V_P2IT,
+ F2V_P2IB,
+ F2V_IT2P,
+ F2V_IB2P,
+ F2V_P2P,
+ F2V_TYPE_MAX
+};
+
+struct f2v_vphase_s {
+ u8 rcv_num;
+ u8 rpt_num;
+ u16 phase;
+};
+
+struct osd_scaler_reg_s {
+ u32 vpp_osd_scale_coef_idx;
+ u32 vpp_osd_scale_coef;
+ u32 vpp_osd_vsc_phase_step;
+ u32 vpp_osd_vsc_ini_phase;
+ u32 vpp_osd_vsc_ctrl0;
+ u32 vpp_osd_hsc_phase_step;
+ u32 vpp_osd_hsc_ini_phase;
+ u32 vpp_osd_hsc_ctrl0;
+ u32 vpp_osd_hsc_ini_pat_ctrl;
+ u32 vpp_osd_sc_dummy_data;
+ u32 vpp_osd_sc_ctrl0;
+ u32 vpp_osd_sci_wh_m1;
+ u32 vpp_osd_sco_h_start_end;
+ u32 vpp_osd_sco_v_start_end;
+};
+
+#endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+struct vpu_dev_func {
+ void (*hw_init)();
+ void (*hw_exit)();
+};
+
+static struct vpu_dev_func g12a = {
+ .hw_init = g12a_hw_init,
+ .hw_exit = g12a_hw_exit,
+};
+
+static struct vpu_dev_func g12b = {
+ .hw_init = g12b_hw_init,
+ .hw_exit = g12b_hw_exit,
+};
+
+static struct vpu_dev_func tl1 = {
+ .hw_init = tl1_hw_init,
+ .hw_exit = tl1_hw_exit,
+};
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_vpu_pipeline.h"
+
+static int hdr_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_hdr *hdr = to_hdr_block(vblk);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ //vpu_block_check_input(vblk, state, mvps);
+
+ DRM_DEBUG("%s set_state called.\n", hdr->base.name);
+ return 0;
+}
+
+static void hdr_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_hdr *hdr = to_hdr_block(vblk);
+ //struct meson_vpu_hdr_state *hdr_state = to_hdr_state(state);
+
+ DRM_DEBUG("%s set_state called.\n", hdr->base.name);
+}
+
+static void hdr_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_hdr *hdr = to_hdr_block(vblk);
+
+ DRM_DEBUG("%s enable called.\n", hdr->base.name);
+}
+
+static void hdr_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_hdr *hdr = to_hdr_block(vblk);
+
+ DRM_DEBUG("%s disable called.\n", hdr->base.name);
+}
+
+struct meson_vpu_block_ops hdr_ops = {
+ .check_state = hdr_check_state,
+ .update_state = hdr_set_state,
+ .enable = hdr_enable,
+ .disable = hdr_disable,
+};
+
+static int dolby_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_dolby *dolby = to_dolby_block(vblk);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ //vpu_block_check_input(vblk, state, mvps);
+
+ DRM_DEBUG("%s check_state called.\n", dolby->base.name);
+ return 0;
+}
+static void dolby_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_dolby *dolby = to_dolby_block(vblk);
+
+ DRM_DEBUG("%s set_state called.\n", dolby->base.name);
+}
+
+static void dolby_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_dolby *dolby = to_dolby_block(vblk);
+
+ DRM_DEBUG("%s enable called.\n", dolby->base.name);
+}
+
+static void dolby_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_dolby *dolby = to_dolby_block(vblk);
+
+ DRM_DEBUG("%s disable called.\n", dolby->base.name);
+}
+
+struct meson_vpu_block_ops dolby_ops = {
+ .check_state = dolby_check_state,
+ .update_state = dolby_set_state,
+ .enable = dolby_enable,
+ .disable = dolby_disable,
+};
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/canvas/canvas_mgr.h>
+#endif
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_reg.h"
+#include "meson_vpu_util.h"
+
+static struct osd_mif_reg_s osd_mif_reg[HW_OSD_MIF_NUM] = {
+ {
+ VIU_OSD1_CTRL_STAT,
+ VIU_OSD1_CTRL_STAT2,
+ VIU_OSD1_COLOR_ADDR,
+ VIU_OSD1_COLOR,
+ VIU_OSD1_TCOLOR_AG0,
+ VIU_OSD1_TCOLOR_AG1,
+ VIU_OSD1_TCOLOR_AG2,
+ VIU_OSD1_TCOLOR_AG3,
+ VIU_OSD1_BLK0_CFG_W0,
+ VIU_OSD1_BLK0_CFG_W1,
+ VIU_OSD1_BLK0_CFG_W2,
+ VIU_OSD1_BLK0_CFG_W3,
+ VIU_OSD1_BLK0_CFG_W4,
+ VIU_OSD1_BLK1_CFG_W4,
+ VIU_OSD1_BLK2_CFG_W4,
+ VIU_OSD1_FIFO_CTRL_STAT,
+ VIU_OSD1_TEST_RDDATA,
+ VIU_OSD1_PROT_CTRL,
+ VIU_OSD1_MALI_UNPACK_CTRL,
+ VIU_OSD1_DIMM_CTRL,
+ },
+ {
+ VIU_OSD2_CTRL_STAT,
+ VIU_OSD2_CTRL_STAT2,
+ VIU_OSD2_COLOR_ADDR,
+ VIU_OSD2_COLOR,
+ VIU_OSD2_TCOLOR_AG0,
+ VIU_OSD2_TCOLOR_AG1,
+ VIU_OSD2_TCOLOR_AG2,
+ VIU_OSD2_TCOLOR_AG3,
+ VIU_OSD2_BLK0_CFG_W0,
+ VIU_OSD2_BLK0_CFG_W1,
+ VIU_OSD2_BLK0_CFG_W2,
+ VIU_OSD2_BLK0_CFG_W3,
+ VIU_OSD2_BLK0_CFG_W4,
+ VIU_OSD2_BLK1_CFG_W4,
+ VIU_OSD2_BLK2_CFG_W4,
+ VIU_OSD2_FIFO_CTRL_STAT,
+ VIU_OSD2_TEST_RDDATA,
+ VIU_OSD2_PROT_CTRL,
+ VIU_OSD2_MALI_UNPACK_CTRL,
+ VIU_OSD2_DIMM_CTRL,
+ },
+ {
+ VIU_OSD3_CTRL_STAT,
+ VIU_OSD3_CTRL_STAT2,
+ VIU_OSD3_COLOR_ADDR,
+ VIU_OSD3_COLOR,
+ VIU_OSD3_TCOLOR_AG0,
+ VIU_OSD3_TCOLOR_AG1,
+ VIU_OSD3_TCOLOR_AG2,
+ VIU_OSD3_TCOLOR_AG3,
+ VIU_OSD3_BLK0_CFG_W0,
+ VIU_OSD3_BLK0_CFG_W1,
+ VIU_OSD3_BLK0_CFG_W2,
+ VIU_OSD3_BLK0_CFG_W3,
+ VIU_OSD3_BLK0_CFG_W4,
+ VIU_OSD3_BLK1_CFG_W4,
+ VIU_OSD3_BLK2_CFG_W4,
+ VIU_OSD3_FIFO_CTRL_STAT,
+ VIU_OSD3_TEST_RDDATA,
+ VIU_OSD3_PROT_CTRL,
+ VIU_OSD3_MALI_UNPACK_CTRL,
+ VIU_OSD3_DIMM_CTRL,
+ }
+};
+
+static unsigned int osd_canvas[3][2] = {
+ {0x41, 0x42}, {0x43, 0x44}, {0x45, 0x46} };
+static u32 osd_canvas_index[3] = {0, 0, 0};
+
+/*
+ * Internal function to query information for a given format. See
+ * meson_drm_format_info() for the public API.
+ */
+const struct meson_drm_format_info *__meson_drm_format_info(u32 format)
+{
+ static const struct meson_drm_format_info formats[] = {
+ { .format = DRM_FORMAT_XRGB8888,
+ .hw_blkmode = 5, .hw_colormat = 1, .alpha_replace = 1 },
+ { .format = DRM_FORMAT_XBGR8888,
+ .hw_blkmode = 5, .hw_colormat = 2, .alpha_replace = 1 },
+ { .format = DRM_FORMAT_RGBX8888,
+ .hw_blkmode = 5, .hw_colormat = 0, .alpha_replace = 1 },
+ { .format = DRM_FORMAT_BGRX8888,
+ .hw_blkmode = 5, .hw_colormat = 3, .alpha_replace = 1 },
+ { .format = DRM_FORMAT_ARGB8888,
+ .hw_blkmode = 5, .hw_colormat = 1, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_ABGR8888,
+ .hw_blkmode = 5, .hw_colormat = 2, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_RGBA8888,
+ .hw_blkmode = 5, .hw_colormat = 0, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_BGRA8888,
+ .hw_blkmode = 5, .hw_colormat = 3, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_RGB888,
+ .hw_blkmode = 7, .hw_colormat = 0, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_RGB565,
+ .hw_blkmode = 4, .hw_colormat = 4, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_ARGB1555,
+ .hw_blkmode = 4, .hw_colormat = 6, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_ARGB4444,
+ .hw_blkmode = 4, .hw_colormat = 5, .alpha_replace = 0 },
+ };
+
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+ if (formats[i].format == format)
+ return &formats[i];
+ }
+
+ return NULL;
+}
+/**
+ * meson_drm_format_info - query information for a given format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * The caller should only pass a supported pixel format to this function.
+ * Unsupported pixel formats will generate a warning in the kernel log.
+ *
+ * Returns:
+ * The instance of struct meson_drm_format_info that describes the
+ * pixel format, or NULL if the format is unsupported.
+ */
+const struct meson_drm_format_info *meson_drm_format_info(u32 format)
+{
+ const struct meson_drm_format_info *info;
+
+ info = __meson_drm_format_info(format);
+ WARN_ON(!info);
+ return info;
+}
+/**
+ * meson_drm_format_hw_blkmode - get the hw_blkmode for format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * Returns:
+ * The hw_blkmode match the specified pixel format.
+ */
+static u8 meson_drm_format_hw_blkmode(uint32_t format)
+{
+ const struct meson_drm_format_info *info;
+
+ info = meson_drm_format_info(format);
+ return info ? info->hw_blkmode : 0;
+}
+/**
+ * meson_drm_format_hw_colormat - get the hw_colormat for format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * Returns:
+ * The hw_colormat match the specified pixel format.
+ */
+static u8 meson_drm_format_hw_colormat(uint32_t format)
+{
+ const struct meson_drm_format_info *info;
+
+ info = meson_drm_format_info(format);
+ return info ? info->hw_colormat : 0;
+}
+/**
+ * meson_drm_format_alpha_replace - get the alpha replace for format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * Returns:
+ * The alpha_replace match the specified pixel format.
+ */
+static u8 meson_drm_format_alpha_replace(uint32_t format)
+{
+ const struct meson_drm_format_info *info;
+
+ info = meson_drm_format_info(format);
+ return info ? info->alpha_replace : 0;
+}
+/*osd input size config*/
+void osd_input_size_config(struct osd_mif_reg_s *reg, struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w1,
+ (scope.h_end << 16) |/*x_end pixels[13bits]*/
+ scope.h_start/*x_start pixels[13bits]*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w2,
+ (scope.v_end << 16) |/*y_end pixels[13bits]*/
+ scope.v_start/*y_start pixels[13bits]*/);
+}
+/*osd canvas config*/
+void osd_canvas_config(struct osd_mif_reg_s *reg, u32 canvas_index)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blk0_cfg_w0,
+ canvas_index, 16, 8);
+}
+/*osd mif enable*/
+void osd_block_enable(struct osd_mif_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_ctrl_stat, flag, 0, 1);
+}
+
+/*osd ctrl config*/
+void osd_ctrl_set(struct osd_mif_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_ctrl_stat,
+ (0 << 31) |/*osd_cfg_sync_en*/
+ (0 << 30) |/*Enable free_clk*/
+ (0x100 << 12) |/*global alpha*/
+ (0 << 11) |/*TEST_RD_EN*/
+ (0 << 2) |/*osd_mem_mode 0:canvas_addr*/
+ (0 << 1) |/*premult_en*/
+ (0 << 0)/*OSD_BLK_ENABLE*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_ctrl_stat2,
+ (1 << 14) |/*replaced_alpha_en*/
+ (0xff << 6) |/*replaced_alpha*/
+ (0 << 4) |/*hold fifo lines 2bit*/
+ (0 << 3) |/*output fullrange enable 1bit*/
+ (0 << 2)/*alpha 9bit mode 1bit*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag0,
+ (0xff << 24) |/*Y/R*/
+ (0xff << 16) |/*CB/G*/
+ (0xff << 24) |/*CR/B*/
+ (0xff << 24)/*ALPHA*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag1,
+ (0xff << 24) |/*Y/R*/
+ (0xff << 16) |/*CB/G*/
+ (0xff << 24) |/*CR/B*/
+ (0xff << 24)/*ALPHA*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag2,
+ (0xff << 24) |/*Y/R*/
+ (0xff << 16) |/*CB/G*/
+ (0xff << 24) |/*CR/B*/
+ (0xff << 24)/*ALPHA*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag3,
+ (0xff << 24) |/*Y/R*/
+ (0xff << 16) |/*CB/G*/
+ (0xff << 24) |/*CR/B*/
+ (0xff << 24)/*ALPHA*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w0,
+ (0 << 30) |/*read from ddr[0]/afbc[1]*/
+ (0 << 29) |/*y reverse disable*/
+ (0 << 28) |/*x reverse disable*/
+ (osd_canvas[0][0] << 16) |/*canvas index*/
+ (1 << 15) |/*little endian in ddr*/
+ (0 << 14) |/*no repeat display y pre line*/
+ (0 << 12) |/*no interpolation per pixel*/
+ (5 << 8) |/*read from ddr 32bit mode*/
+ (0 << 6) |/*TC_ALPHA_EN*/
+ (1 << 2) |/*ARGB format for 32bit mode*/
+ (0 << 1) |/*interlace en*/
+ (0 << 0)/*output odd/even lines sel*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w1,
+ (1919 << 16) |/*x_end pixels[13bits]*/
+ (0 << 0)/*x_start pixels[13bits]*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w2,
+ (1079 << 16) |/*y_end pixels[13bits]*/
+ (0 << 0)/*y_start pixels[13bits]*/);
+ /*frame addr in linear addr*/
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk1_cfg_w4, 0);
+ /*line_stride in linear addr*/
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk2_cfg_w4, 0);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_fifo_ctrl_stat,
+ (1 << 31) |/*BURSET_LEN_SEL[2]*/
+ (0 << 30) |/*no swap*/
+ (0 << 29) |/*div swap*/
+ (2 << 24) |/*Fifo_lim 5bits*/
+ (2 << 22) |/*Fifo_ctrl 2bits*/
+ (0x20 << 12) |/*FIFO_DEPATH_VAL 7bits*/
+ (1 << 10) |/*BURSET_LEN_SEL[1:0]*/
+ (4 << 5) |/*hold fifo lines 5bits*/
+ (0 << 4) |/*CLEAR_ERR*/
+ (0 << 3) |/*fifo_sync_rst*/
+ (0 << 1) |/*ENDIAN:no conversion*/
+ (1 << 0)/*urgent enable*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_mali_unpack_ctrl,
+ (0 << 31) |/*unpack normal src*/
+ (0 << 28) |/*alpha div en*/
+ (0 << 26) |/*dividor gating clk*/
+ (1 << 24) |/*alpha mapping mode 2bits*/
+ (0 << 16) |/*afbc swap 64bit 1bits*/
+ (1 << 12) |/*afbcd_r_reorder r 4bits*/
+ (2 << 8) |/*afbcd_r_reorder g 4bits*/
+ (3 << 4) |/*afbcd_r_reorder b 4bits*/
+ (4 << 0)/*afbcd_r_reorder alpha 4bits*/);
+}
+
+static void osd_color_config(struct osd_mif_reg_s *reg, u32 pixel_format)
+{
+ u8 blk_mode, colormat, alpha_replace;
+
+ blk_mode = meson_drm_format_hw_blkmode(pixel_format);
+ colormat = meson_drm_format_hw_colormat(pixel_format);
+ alpha_replace = meson_drm_format_alpha_replace(pixel_format);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blk0_cfg_w0,
+ blk_mode, 8, 4);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blk0_cfg_w0,
+ colormat, 2, 4);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_ctrl_stat2,
+ alpha_replace, 14, 1);
+}
+
+static int osd_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+ struct meson_vpu_osd_state *mvos = to_osd_state(state);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ if (!mvos || mvos->plane_index >= MESON_MAX_OSDS) {
+ DRM_INFO("mvos is NULL!\n");
+ return -1;
+ }
+ DRM_DEBUG("%s check_state called.\n", osd->base.name);
+ plane_info = &mvps->plane_info[vblk->index];
+ mvos->src_x = plane_info->src_x;
+ mvos->src_y = plane_info->src_y;
+ mvos->src_w = plane_info->src_w;
+ mvos->src_h = plane_info->src_h;
+ mvos->byte_stride = plane_info->byte_stride;
+ mvos->phy_addr = plane_info->phy_addr;
+ mvos->pixel_format = plane_info->pixel_format;
+ return 0;
+}
+
+static void osd_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+ struct meson_vpu_osd_state *mvos = to_osd_state(state);
+ u32 pixel_format, canvas_index, src_h, byte_stride, phy_addr;
+ struct osd_scope_s scope_src = {0, 1919, 0, 1079};
+ struct osd_mif_reg_s *reg = osd->reg;
+
+ if (!vblk) {
+ DRM_DEBUG("set_state break for NULL.\n");
+ return;
+ }
+ src_h = mvos->src_h;
+ byte_stride = mvos->byte_stride;
+ phy_addr = mvos->phy_addr;
+ scope_src.h_start = mvos->src_x;
+ scope_src.h_end = mvos->src_x + mvos->src_w - 1;
+ scope_src.v_start = mvos->src_y;
+ scope_src.v_end = mvos->src_y + mvos->src_h - 1;
+ pixel_format = mvos->pixel_format;
+ canvas_index = osd_canvas[vblk->index][osd_canvas_index[vblk->index]];
+ canvas_config(canvas_index, phy_addr, byte_stride, src_h,
+ CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
+ osd_canvas_index[vblk->index] ^= 1;
+ osd_canvas_config(reg, canvas_index);
+ osd_input_size_config(reg, scope_src);
+ osd_color_config(reg, pixel_format);
+ DRM_DEBUG("plane_index=%d,HW-OSD=%d\n",
+ mvos->plane_index, vblk->index);
+ DRM_DEBUG("canvas_index[%d]=0x%x,phy_addr=0x%x\n",
+ osd_canvas_index[vblk->index], canvas_index, phy_addr);
+ DRM_DEBUG("scope h/v start/end:[%d/%d/%d/%d]\n",
+ scope_src.h_start, scope_src.h_end,
+ scope_src.v_start, scope_src.v_end);
+ DRM_DEBUG("%s set_state done.\n", osd->base.name);
+}
+
+static void osd_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+ struct osd_mif_reg_s *reg = osd->reg;
+
+ if (!vblk) {
+ DRM_DEBUG("enable break for NULL.\n");
+ return;
+ }
+ osd_block_enable(reg, 1);
+ DRM_DEBUG("%s enable done.\n", osd->base.name);
+}
+
+static void osd_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+ struct osd_mif_reg_s *reg = osd->reg;
+
+ if (!vblk) {
+ DRM_DEBUG("disable break for NULL.\n");
+ return;
+ }
+ osd_block_enable(reg, 0);
+ DRM_DEBUG("%s disable done.\n", osd->base.name);
+}
+
+static void osd_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+
+ if (!vblk || !osd) {
+ DRM_DEBUG("hw_init break for NULL.\n");
+ return;
+ }
+ osd->reg = &osd_mif_reg[vblk->index];
+ osd_ctrl_set(osd->reg);
+ DRM_DEBUG("%s hw_init done.\n", osd->base.name);
+}
+
+struct meson_vpu_block_ops osd_ops = {
+ .check_state = osd_check_state,
+ .update_state = osd_set_state,
+ .enable = osd_hw_enable,
+ .disable = osd_hw_disable,
+ .init = osd_hw_init,
+};
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _MESON_VPU_OSD_MIF_H_
+#define _MESON_VPU_OSD_MIF_H_
+
+#define HW_OSD_MIF_NUM 3
+
+#define VIU_OSD1_CTRL_STAT 0x1a10
+#define VIU_OSD1_CTRL_STAT2 0x1a2d
+#define VIU_OSD1_COLOR_ADDR 0x1a11
+#define VIU_OSD1_COLOR 0x1a12
+#define VIU_OSD1_TCOLOR_AG0 0x1a17
+#define VIU_OSD1_TCOLOR_AG1 0x1a18
+#define VIU_OSD1_TCOLOR_AG2 0x1a19
+#define VIU_OSD1_TCOLOR_AG3 0x1a1a
+#define VIU_OSD1_BLK0_CFG_W0 0x1a1b
+#define VIU_OSD1_BLK1_CFG_W0 0x1a1f
+#define VIU_OSD1_BLK2_CFG_W0 0x1a23
+#define VIU_OSD1_BLK3_CFG_W0 0x1a27
+#define VIU_OSD1_BLK0_CFG_W1 0x1a1c
+#define VIU_OSD1_BLK1_CFG_W1 0x1a20
+#define VIU_OSD1_BLK2_CFG_W1 0x1a24
+#define VIU_OSD1_BLK3_CFG_W1 0x1a28
+#define VIU_OSD1_BLK0_CFG_W2 0x1a1d
+#define VIU_OSD1_BLK1_CFG_W2 0x1a21
+#define VIU_OSD1_BLK2_CFG_W2 0x1a25
+#define VIU_OSD1_BLK3_CFG_W2 0x1a29
+#define VIU_OSD1_BLK0_CFG_W3 0x1a1e
+#define VIU_OSD1_BLK1_CFG_W3 0x1a22
+#define VIU_OSD1_BLK2_CFG_W3 0x1a26
+#define VIU_OSD1_BLK3_CFG_W3 0x1a2a
+#define VIU_OSD1_BLK0_CFG_W4 0x1a13
+#define VIU_OSD1_BLK1_CFG_W4 0x1a14
+#define VIU_OSD1_BLK2_CFG_W4 0x1a15
+#define VIU_OSD1_BLK3_CFG_W4 0x1a16
+#define VIU_OSD1_FIFO_CTRL_STAT 0x1a2b
+#define VIU_OSD1_TEST_RDDATA 0x1a2c
+#define VIU_OSD1_PROT_CTRL 0x1a2e
+#define VIU_OSD1_MALI_UNPACK_CTRL 0x1a2f
+#define VIU_OSD1_DIMM_CTRL 0x1adf
+
+#define VIU_OSD2_CTRL_STAT 0x1a30
+#define VIU_OSD2_CTRL_STAT2 0x1a4d
+#define VIU_OSD2_COLOR_ADDR 0x1a31
+#define VIU_OSD2_COLOR 0x1a32
+#define VIU_OSD2_HL1_H_START_END 0x1a33
+#define VIU_OSD2_HL1_V_START_END 0x1a34
+#define VIU_OSD2_HL2_H_START_END 0x1a35
+#define VIU_OSD2_HL2_V_START_END 0x1a36
+#define VIU_OSD2_TCOLOR_AG0 0x1a37
+#define VIU_OSD2_TCOLOR_AG1 0x1a38
+#define VIU_OSD2_TCOLOR_AG2 0x1a39
+#define VIU_OSD2_TCOLOR_AG3 0x1a3a
+#define VIU_OSD2_BLK0_CFG_W0 0x1a3b
+#define VIU_OSD2_BLK1_CFG_W0 0x1a3f
+#define VIU_OSD2_BLK2_CFG_W0 0x1a43
+#define VIU_OSD2_BLK3_CFG_W0 0x1a47
+#define VIU_OSD2_BLK0_CFG_W1 0x1a3c
+#define VIU_OSD2_BLK1_CFG_W1 0x1a40
+#define VIU_OSD2_BLK2_CFG_W1 0x1a44
+#define VIU_OSD2_BLK3_CFG_W1 0x1a48
+#define VIU_OSD2_BLK0_CFG_W2 0x1a3d
+#define VIU_OSD2_BLK1_CFG_W2 0x1a41
+#define VIU_OSD2_BLK2_CFG_W2 0x1a45
+#define VIU_OSD2_BLK3_CFG_W2 0x1a49
+#define VIU_OSD2_BLK0_CFG_W3 0x1a3e
+#define VIU_OSD2_BLK1_CFG_W3 0x1a42
+#define VIU_OSD2_BLK2_CFG_W3 0x1a46
+#define VIU_OSD2_BLK3_CFG_W3 0x1a4a
+#define VIU_OSD2_BLK0_CFG_W4 0x1a64
+#define VIU_OSD2_BLK1_CFG_W4 0x1a65
+#define VIU_OSD2_BLK2_CFG_W4 0x1a66
+#define VIU_OSD2_BLK3_CFG_W4 0x1a67
+#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
+#define VIU_OSD2_TEST_RDDATA 0x1a4c
+#define VIU_OSD2_PROT_CTRL 0x1a4e
+#define VIU_OSD2_MALI_UNPACK_CTRL 0x1abd
+#define VIU_OSD2_DIMM_CTRL 0x1acf
+
+#define VIU_OSD3_CTRL_STAT 0x3d80
+#define VIU_OSD3_CTRL_STAT2 0x3d81
+#define VIU_OSD3_COLOR_ADDR 0x3d82
+#define VIU_OSD3_COLOR 0x3d83
+#define VIU_OSD3_TCOLOR_AG0 0x3d84
+#define VIU_OSD3_TCOLOR_AG1 0x3d85
+#define VIU_OSD3_TCOLOR_AG2 0x3d86
+#define VIU_OSD3_TCOLOR_AG3 0x3d87
+#define VIU_OSD3_BLK0_CFG_W0 0x3d88
+#define VIU_OSD3_BLK0_CFG_W1 0x3d8c
+#define VIU_OSD3_BLK0_CFG_W2 0x3d90
+#define VIU_OSD3_BLK0_CFG_W3 0x3d94
+#define VIU_OSD3_BLK0_CFG_W4 0x3d98
+#define VIU_OSD3_BLK1_CFG_W4 0x3d99
+#define VIU_OSD3_BLK2_CFG_W4 0x3d9a
+#define VIU_OSD3_FIFO_CTRL_STAT 0x3d9c
+#define VIU_OSD3_TEST_RDDATA 0x3d9d
+#define VIU_OSD3_PROT_CTRL 0x3d9e
+#define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f
+#define VIU_OSD3_DIMM_CTRL 0x3da0
+
+struct osd_mif_reg_s {
+ u32 viu_osd_ctrl_stat;
+ u32 viu_osd_ctrl_stat2;
+ u32 viu_osd_color_addr;
+ u32 viu_osd_color;
+ u32 viu_osd_tcolor_ag0;
+ u32 viu_osd_tcolor_ag1;
+ u32 viu_osd_tcolor_ag2;
+ u32 viu_osd_tcolor_ag3;
+ u32 viu_osd_blk0_cfg_w0;
+ u32 viu_osd_blk0_cfg_w1;
+ u32 viu_osd_blk0_cfg_w2;
+ u32 viu_osd_blk0_cfg_w3;
+ u32 viu_osd_blk0_cfg_w4;
+ u32 viu_osd_blk1_cfg_w4;
+ u32 viu_osd_blk2_cfg_w4;
+ u32 viu_osd_fifo_ctrl_stat;
+ u32 viu_osd_test_rddata;
+ u32 viu_osd_prot_ctrl;
+ u32 viu_osd_mali_unpack_ctrl;
+ u32 viu_osd_dimm_ctrl;
+};
+
+/**
+ * struct meson_drm_format_info - information about a DRM format
+ * @format: 4CC format identifier (DRM_FORMAT_*)
+ * @hw_blkmode: Define the OSD block’s input pixel format
+ * @hw_colormat: Applicable only to 16-bit color mode (OSD_BLK_MODE=4),
+ * 32-bit mode (OSD_BLK_MODE=5) and 24-bit mode (OSD_BLK_MODE=7),
+ * defines the bit-field allocation of the pixel data.
+ */
+struct meson_drm_format_info {
+ u32 format;
+ u8 hw_blkmode;
+ u8 hw_colormat;
+ u8 alpha_replace;
+};
+#endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+/* Amlogic Headers */
+#include <linux/amlogic/media/vout/vout_notify.h>
+
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_reg.h"
+#include "meson_vpu_util.h"
+#include "meson_vpu_osdblend.h"
+
+static struct osdblend_reg_s osdblend_reg = {
+ VIU_OSD_BLEND_CTRL,
+ VIU_OSD_BLEND_DIN0_SCOPE_H,
+ VIU_OSD_BLEND_DIN0_SCOPE_V,
+ VIU_OSD_BLEND_DIN1_SCOPE_H,
+ VIU_OSD_BLEND_DIN1_SCOPE_V,
+ VIU_OSD_BLEND_DIN2_SCOPE_H,
+ VIU_OSD_BLEND_DIN2_SCOPE_V,
+ VIU_OSD_BLEND_DIN3_SCOPE_H,
+ VIU_OSD_BLEND_DIN3_SCOPE_V,
+ VIU_OSD_BLEND_DUMMY_DATA0,
+ VIU_OSD_BLEND_DUMMY_ALPHA,
+ VIU_OSD_BLEND_BLEND0_SIZE,
+ VIU_OSD_BLEND_BLEND1_SIZE,
+ VIU_OSD_BLEND_CTRL1,
+};
+
+/*0:din0 go through blend0,1:bypass blend0,dirct to Dout0*/
+static void osd_din0_switch_set(struct osdblend_reg_s *reg,
+ bool bypass_state)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ bypass_state, 26, 1);
+}
+/*0:blend1 out to blend2,1:blend1 out to Dout1*/
+static void osd_blend1_dout_switch_set(struct osdblend_reg_s *reg,
+ bool bypass_state)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ bypass_state, 25, 1);
+}
+/*0:din3 pass through blend1,1:bypass blend1,direct to Dout1*/
+static void osd_din3_switch_set(struct osdblend_reg_s *reg,
+ bool bypass_state)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ bypass_state, 24, 1);
+}
+#if 0
+/*0:din0/1/2/3 input disable,1:enable*/
+static void osd_din_input_enable_set(struct osdblend_reg_s *reg,
+ bool enable, enum din_channel_e din_channel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, enable,
+ (20 + din_channel), 1);
+}
+#endif
+/*0:din0 input disable,1:din0 input enable*/
+static void osd_din0_input_enable_set(struct osdblend_reg_s *reg,
+ bool input_enable)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ input_enable, 20, 1);
+}
+/*0:din1 input disable,1:din1 input enable*/
+static void osd_din1_input_enable_set(struct osdblend_reg_s *reg,
+ bool input_enable)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ input_enable, 21, 1);
+}
+/*0:din2 input disable,1:din2 input enable*/
+static void osd_din2_input_enable_set(struct osdblend_reg_s *reg,
+ bool input_enable)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ input_enable, 22, 1);
+}
+/*0:din3 input disable,1:din3 input enable*/
+static void osd_din3_input_enable_set(struct osdblend_reg_s *reg,
+ bool input_enable)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ input_enable, 23, 1);
+}
+#if 0
+/*0:din0/1/2/3 premult disable,1:enable*/
+static void osd_din_premult_enable_set(struct osdblend_reg_s *reg,
+ bool enable, enum din_channel_e din_channel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, enable,
+ (16 + din_channel), 1);
+}
+#endif
+/*1/2/3:din0/1/2/3 select osd1/osd2/osd3,else select null*/
+static void osd_din_channel_mux_set(struct osdblend_reg_s *reg,
+ enum osd_channel_e osd_channel,
+ enum din_channel_e din_channel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, osd_channel,
+ (0 + din_channel*4), 4);
+}
+/*din0 scope config*/
+static void osd_din0_scope_set(struct osdblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_h,
+ scope.h_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_h,
+ scope.h_end, 16, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_v,
+ scope.v_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_v,
+ scope.v_end, 16, 13);
+}
+/*din1 scope config*/
+static void osd_din1_scope_set(struct osdblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_h,
+ scope.h_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_h,
+ scope.h_end, 16, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_v,
+ scope.v_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_v,
+ scope.v_end, 16, 13);
+}
+/*din2 scope config*/
+static void osd_din2_scope_set(struct osdblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_h,
+ scope.h_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_h,
+ scope.h_end, 16, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_v,
+ scope.v_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_v,
+ scope.v_end, 16, 13);
+}
+/*din3 scope config*/
+static void osd_din3_scope_set(struct osdblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_h,
+ scope.h_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_h,
+ scope.h_end, 16, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_v,
+ scope.v_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_v,
+ scope.v_end, 16, 13);
+}
+/*osd blend dummy data config*/
+static void osd_blend_dummy_data_set(struct osdblend_reg_s *reg,
+ struct osd_dummy_data_s dummy_data)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blend_dummy_data0,
+ ((dummy_data.channel0 & 0xff) << 16) |
+ ((dummy_data.channel1 & 0xff) << 8) |
+ (dummy_data.channel2 & 0xff));
+}
+/*osd blend0 dummy data alpha config*/
+static void osd_blend0_dummy_alpha_set(struct osdblend_reg_s *reg,
+ unsigned int dummy_alpha)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_dummy_alpha,
+ dummy_alpha, 20, 9);
+}
+/*osd blend1 dummy data alpha config*/
+static void osd_blend1_dummy_alpha_set(struct osdblend_reg_s *reg,
+ unsigned int dummy_alpha)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_dummy_alpha,
+ dummy_alpha, 11, 9);
+}
+/*osd blend2 dummy data alpha config*/
+static void osd_blend2_dummy_alpha_set(struct osdblend_reg_s *reg,
+ unsigned int dummy_alpha)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_dummy_alpha,
+ dummy_alpha, 0, 9);
+}
+/*osd blend0 size config*/
+static void osd_blend0_size_set(struct osdblend_reg_s *reg,
+ unsigned int h_size, unsigned int v_size)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blend0_size,
+ (v_size << 16) | h_size);
+}
+/*osd blend1 size config*/
+static void osd_blend1_size_set(struct osdblend_reg_s *reg,
+ unsigned int h_size, unsigned int v_size)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blend1_size,
+ (v_size << 16) | h_size);
+}
+/*osd blend0 & blend1 4 din inputs premult flag config as 0 default*/
+void osd_blend01_premult_config(struct osdblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, 0, 16, 4);
+}
+/*osd blend2 2 inputs premult flag config as 1 default*/
+void osd_blend2_premult_config(struct osdblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, 3, 27, 2);
+}
+/*osd blend dout0 output div en config as 1,alpha 9bit default*/
+void osd_blend_dout0_div_config(struct osdblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 3, 4, 2);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 1, 0, 1);
+}
+/*osd blend dout1 output div en config as 1,alpha 9bit default*/
+void osd_blend_dout1_div_config(struct osdblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 3, 16, 2);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 1, 12, 1);
+}
+/*osd blend premult config*/
+void osdblend_premult_config(struct osdblend_reg_s *reg)
+{
+ osd_blend01_premult_config(reg);
+ osd_blend2_premult_config(reg);
+ osd_blend_dout0_div_config(reg);
+ osd_blend_dout1_div_config(reg);
+}
+
+enum osd_channel_e osd2channel(u8 osd_index)
+{
+ u8 din_channel_seq[MAX_DIN_NUM] = {OSD_CHANNEL1, OSD_CHANNEL2,
+ OSD_CHANNEL3, OSD_CHANNEL_NUM};
+
+ if (osd_index >= MAX_DIN_NUM) {
+ DRM_DEBUG("osd_index:%d overflow!!.\n", osd_index);
+ return OSD_CHANNEL_NUM;
+ }
+ return din_channel_seq[osd_index];
+}
+
+static void osdblend_hw_update(struct osdblend_reg_s *reg,
+ struct meson_vpu_osdblend_state *mvobs)
+{
+ struct osd_dummy_data_s dummy_data = {0, 0, 0};
+
+ /*din channel mux config*/
+ osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN0], DIN0);
+ osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN1], DIN1);
+ osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN2], DIN2);
+ osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN3], DIN3);
+
+ /*dummy data config*/
+ osd_blend_dummy_data_set(reg, dummy_data);
+
+ /*alpha config*/
+ osd_blend0_dummy_alpha_set(reg, 0x1ff);
+ osd_blend1_dummy_alpha_set(reg, 0);
+ osd_blend2_dummy_alpha_set(reg, 0x1ff);
+
+ /*internal channel disable default*/
+ osd_din0_input_enable_set(reg, (mvobs->input_mask >> DIN0) & 0x1);
+ osd_din1_input_enable_set(reg, (mvobs->input_mask >> DIN1) & 0x1);
+ osd_din2_input_enable_set(reg, (mvobs->input_mask >> DIN2) & 0x1);
+ osd_din3_input_enable_set(reg, (mvobs->input_mask >> DIN3) & 0x1);
+
+ /*blend switch config*/
+ osd_din0_switch_set(reg, mvobs->din0_switch);
+ osd_din3_switch_set(reg, mvobs->din3_switch);
+ osd_blend1_dout_switch_set(reg, mvobs->blend1_switch);
+
+ /*scope config*/
+ osd_din0_scope_set(reg, mvobs->din_channel_scope[DIN0]);
+ osd_din1_scope_set(reg, mvobs->din_channel_scope[DIN1]);
+ osd_din2_scope_set(reg, mvobs->din_channel_scope[DIN2]);
+ osd_din3_scope_set(reg, mvobs->din_channel_scope[DIN3]);
+
+ /*premult config*/
+ osdblend_premult_config(reg);
+
+ /*blend0/blend1 size config*/
+ osd_blend0_size_set(reg, mvobs->input_width[OSD_SUB_BLEND0],
+ mvobs->input_height[OSD_SUB_BLEND0]);
+ osd_blend1_size_set(reg, mvobs->input_width[OSD_SUB_BLEND1],
+ mvobs->input_height[OSD_SUB_BLEND1]);
+}
+
+static int osdblend_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ int ret, num_planes;
+ u32 *out_port;
+ u32 i, j, m, n, num_plane_port0, num_plane_port1;
+ u32 plane_index_port0[MAX_DIN_NUM], plane_index_port1[MAX_DIN_NUM];
+ struct meson_vpu_osdblend_state *mvobs;
+ u32 zorder[MAX_DIN_NUM], max_height = 0, max_width = 0;
+ int delta_zorder[MAX_DIN_NUM] = {0};
+ bool delta_zorder_flag;
+ struct osd_scope_s scope_default = {0xffff, 0xffff, 0xffff, 0xffff};
+
+ mvobs = to_osdblend_state(state);
+ num_planes = mvps->num_plane;
+ out_port = mvps->dout_index;
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ ret = 0;
+ num_plane_port0 = 0;
+ num_plane_port1 = 0;
+ DRM_DEBUG("%s check_state called.\n", vblk->name);
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable) {
+ mvobs->input_osd_mask &= ~BIT(i);
+ continue;
+ }
+ mvobs->input_osd_mask |= BIT(i);
+ if (out_port[i] == OSD_LEND_OUT_PORT1) {
+ plane_index_port1[num_plane_port1] =
+ mvps->plane_index[i];
+ num_plane_port1++;
+ } else {
+ plane_index_port0[num_plane_port0] =
+ mvps->plane_index[i];
+ num_plane_port0++;
+ }
+ }
+ /*check the unsupport case firstly*/
+ if (num_plane_port0 > OSD_LEND_MAX_IN_NUM_PORT0 ||
+ num_plane_port1 > OSD_LEND_MAX_IN_NUM_PORT1)
+ return -1;
+ if (mvps->pipeline->osd_version <= OSD_V2 &&
+ num_plane_port1)
+ return -1;
+ /*zorder check for one dout-port with multi plane*/
+ for (i = 0; i < num_plane_port1; i++) {
+ m = plane_index_port1[i];
+ for (j = 0; j < num_plane_port0; j++) {
+ n = plane_index_port0[j];
+ delta_zorder[0] = mvps->plane_info[m].zorder -
+ mvps->plane_info[n].zorder;
+ delta_zorder_flag = ((delta_zorder[0] < 0) !=
+ (delta_zorder[1] < 0));
+ if (num_plane_port0 >= 2 && j > 0 &&
+ delta_zorder_flag)
+ return -1;
+ delta_zorder[1] = delta_zorder[0];
+ /*find the max zorder as dout port zorder*/
+ if (mvps->dout_zorder[OSD_LEND_OUT_PORT0] <
+ mvps->plane_info[n].zorder)
+ mvps->dout_zorder[OSD_LEND_OUT_PORT0] =
+ mvps->plane_info[n].zorder;
+ }
+ delta_zorder[2] = delta_zorder[0];
+ delta_zorder_flag = ((delta_zorder[2] < 0) !=
+ (delta_zorder[3] < 0));
+ if (num_plane_port1 >= 2 && i > 0 && delta_zorder_flag)
+ return -1;
+ delta_zorder[3] = delta_zorder[2];
+ if (mvps->dout_zorder[OSD_LEND_OUT_PORT1] <
+ mvps->plane_info[m].zorder)
+ mvps->dout_zorder[OSD_LEND_OUT_PORT1] =
+ mvps->plane_info[m].zorder;
+ }
+ /*
+ *confirm the Din enable and channel mux and sub blend input size
+ *according to input zorder and dout sel
+ */
+ mvobs->input_mask = 0;
+ for (i = 0; i < num_plane_port0; i++) {
+ mvobs->input_mask |= 1 << i;
+ j = plane_index_port0[i];
+ mvobs->din_channel_mux[i] = osd2channel(j);
+ zorder[i] = mvps->plane_info[j].zorder;
+ /*blend size calc*/
+ if (max_width < mvps->osd_scope_pre[j].h_end + 1)
+ max_width = mvps->osd_scope_pre[j].h_end + 1;
+ if (max_height < mvps->osd_scope_pre[j].v_end + 1)
+ max_height = mvps->osd_scope_pre[j].v_end + 1;
+ }
+ for (i = 0; i < num_plane_port0; i++) {
+ for (j = 1; j < num_plane_port0; j++) {
+ if (zorder[i] > zorder[j]) {
+ swap(zorder[i], zorder[j]);
+ swap(mvobs->din_channel_mux[i],
+ mvobs->din_channel_mux[j]);
+ }
+ }
+ }
+ for (i = 0; i < num_plane_port1; i++) {
+ m = MAX_DIN_NUM - i - 1;
+ mvobs->input_mask |= 1 << m;
+ j = plane_index_port1[i];
+ mvobs->din_channel_mux[m] = osd2channel(j);
+ zorder[i] = mvps->plane_info[j].zorder;
+ /*blend size calc*/
+ if (max_width < mvps->osd_scope_pre[j].h_end + 1)
+ max_width = mvps->osd_scope_pre[j].h_end + 1;
+ if (max_height < mvps->osd_scope_pre[j].v_end + 1)
+ max_height = mvps->osd_scope_pre[j].v_end + 1;
+ }
+ for (i = 0; i < num_plane_port1; i++) {
+ for (j = 1; j < num_plane_port1; j++) {
+ if (zorder[i] > zorder[j]) {
+ swap(zorder[i], zorder[j]);
+ swap(mvobs->din_channel_mux[i],
+ mvobs->din_channel_mux[j]);
+ }
+ }
+ }
+ for (i = 0; i < MAX_DIN_NUM; i++) {
+ if (!mvobs->din_channel_mux[i])
+ mvobs->din_channel_mux[i] = OSD_CHANNEL_NUM;
+ }
+ /*osdblend switch check*/
+ mvobs->din0_switch = 0;
+ if ((mvobs->input_mask & (BIT(DIN2) | BIT(DIN3))) &&
+ num_plane_port0 == 3 && num_plane_port1 == 1)
+ mvobs->din3_switch = 1;
+ else
+ mvobs->din3_switch = 0;
+ if ((mvobs->input_mask & BIT(DIN2)) &&
+ num_plane_port1 == 2)
+ mvobs->blend1_switch = 1;
+ else
+ mvobs->blend1_switch = 0;
+ /*scope check*/
+ for (i = 0; i < MAX_DIN_NUM; i++) {
+ if (mvobs->input_osd_mask & BIT(i))
+ memcpy(&mvobs->din_channel_scope[i],
+ &mvps->osd_scope_pre[i],
+ sizeof(struct osd_scope_s));
+ else
+ memcpy(&mvobs->din_channel_scope[i],
+ &scope_default,
+ sizeof(struct osd_scope_s));
+ }
+ /*sub blend size check*/
+ mvobs->input_width[OSD_SUB_BLEND0] = max_width;
+ mvobs->input_width[OSD_SUB_BLEND1] = max_width;
+ mvobs->input_height[OSD_SUB_BLEND0] = max_height;
+ mvobs->input_height[OSD_SUB_BLEND1] = max_height;
+ DRM_DEBUG("%s check done.\n", vblk->name);
+ return ret;
+}
+
+static void osdblend_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk);
+ struct meson_vpu_pipeline *pipeline = osdblend->base.pipeline;
+ struct meson_vpu_osdblend_state *mvobs;
+ struct meson_vpu_pipeline_state *pipeline_state;
+ struct osdblend_reg_s *reg = osdblend->reg;
+
+ DRM_DEBUG("%s set_state called.\n", osdblend->base.name);
+ mvobs = to_osdblend_state(state);
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ if (!pipeline_state) {
+ DRM_DEBUG("pipeline_state is NULL!!\n");
+ return;
+ }
+
+ #ifdef OSDBLEND_CHECK_METHOD_COMBINATION
+ osdblend_layer_set(reg, osdblend, pipeline_state);
+ #else
+ osdblend_hw_update(reg, mvobs);
+ #endif
+
+ DRM_DEBUG("%s set_state done.\n", osdblend->base.name);
+}
+
+static void osdblend_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk);
+
+ DRM_DEBUG("%s enable called.\n", osdblend->base.name);
+}
+
+static void osdblend_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk);
+
+ DRM_DEBUG("%s disable called.\n", osdblend->base.name);
+}
+
+static void osdblend_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk);
+
+ osdblend->reg = &osdblend_reg;
+ DRM_DEBUG("%s hw_init called.\n", osdblend->base.name);
+}
+
+struct meson_vpu_block_ops osdblend_ops = {
+ .check_state = osdblend_check_state,
+ .update_state = osdblend_set_state,
+ .enable = osdblend_hw_enable,
+ .disable = osdblend_hw_disable,
+ .init = osdblend_hw_init,
+};
+
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _MESON_VPU_OSDBLEND_H_
+#define _MESON_VPU_OSDBLEND_H_
+
+#define OSD_LEND_OUT_PORT0 0
+#define OSD_LEND_OUT_PORT1 1
+#define OSD_SUB_BLEND0 0
+#define OSD_SUB_BLEND1 1
+#define OSD_LEND_MAX_IN_NUM_PORT0 4
+#define OSD_LEND_MAX_IN_NUM_PORT1 2
+
+#define VIU_OSD_BLEND_CTRL 0x39b0
+#define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1
+#define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2
+#define VIU_OSD_BLEND_DIN1_SCOPE_H 0x39b3
+#define VIU_OSD_BLEND_DIN1_SCOPE_V 0x39b4
+#define VIU_OSD_BLEND_DIN2_SCOPE_H 0x39b5
+#define VIU_OSD_BLEND_DIN2_SCOPE_V 0x39b6
+#define VIU_OSD_BLEND_DIN3_SCOPE_H 0x39b7
+#define VIU_OSD_BLEND_DIN3_SCOPE_V 0x39b8
+#define VIU_OSD_BLEND_DUMMY_DATA0 0x39b9
+#define VIU_OSD_BLEND_DUMMY_ALPHA 0x39ba
+#define VIU_OSD_BLEND_BLEND0_SIZE 0x39bb
+#define VIU_OSD_BLEND_BLEND1_SIZE 0x39bc
+#define VIU_OSD_BLEND_RO_CURRENT_XY 0x39bf
+#define VIU_OSD_BLEND_CTRL1 0x39c0
+
+struct osdblend_reg_s {
+ u32 viu_osd_blend_ctrl;
+ u32 viu_osd_blend_din0_scope_h;
+ u32 viu_osd_blend_din0_scope_v;
+ u32 viu_osd_blend_din1_scope_h;
+ u32 viu_osd_blend_din1_scope_v;
+ u32 viu_osd_blend_din2_scope_h;
+ u32 viu_osd_blend_din2_scope_v;
+ u32 viu_osd_blend_din3_scope_h;
+ u32 viu_osd_blend_din3_scope_v;
+ u32 viu_osd_blend_dummy_data0;
+ u32 viu_osd_blend_dummy_alpha;
+ u32 viu_osd_blend0_size;
+ u32 viu_osd_blend1_size;
+ u32 viu_osd_blend_ctrl1;
+};
+
+/*input mif channel*/
+enum osd_channel_e {
+ OSD_CHANNEL1 = 1,
+ OSD_CHANNEL2,
+ OSD_CHANNEL3,
+ OSD_CHANNEL_NUM
+};
+
+struct osd_dummy_data_s {
+ unsigned int channel0;/*y*/
+ unsigned int channel1;/*cb*/
+ unsigned int channel2;/*cr*/
+};
+#endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+/* Amlogic Headers */
+#include <linux/amlogic/media/vout/vout_notify.h>
+
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_util.h"
+#include "meson_vpu_postblend.h"
+
+static struct postblend_reg_s postblend_reg = {
+ VPP_OSD1_BLD_H_SCOPE,
+ VPP_OSD1_BLD_V_SCOPE,
+ VPP_OSD2_BLD_H_SCOPE,
+ VPP_OSD2_BLD_V_SCOPE,
+ VD1_BLEND_SRC_CTRL,
+ VD2_BLEND_SRC_CTRL,
+ OSD1_BLEND_SRC_CTRL,
+ OSD2_BLEND_SRC_CTRL,
+};
+
+/*vpp post&post blend for osd1 premult flag config as 0 default*/
+static void osd1_blend_premult_set(struct postblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, 0, 4, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, 0, 16, 1);
+}
+
+/*vpp pre&post blend for osd2 premult flag config as 0 default*/
+static void osd2_blend_premult_set(struct postblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, 0, 4, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, 0, 16, 1);
+}
+
+/*vpp osd1 blend sel*/
+static void osd1_blend_switch_set(struct postblend_reg_s *reg,
+ enum vpp_blend_e blend_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, blend_sel, 20, 1);
+}
+
+/*vpp osd2 blend sel*/
+static void osd2_blend_switch_set(struct postblend_reg_s *reg,
+ enum vpp_blend_e blend_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, blend_sel, 20, 1);
+}
+
+/*vpp osd1 preblend mux sel*/
+static void vpp_osd1_preblend_mux_set(struct postblend_reg_s *reg,
+ enum vpp_blend_src_e src_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, src_sel, 0, 4);
+}
+
+/*vpp osd2 preblend mux sel*/
+static void vpp_osd2_preblend_mux_set(struct postblend_reg_s *reg,
+ enum vpp_blend_src_e src_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, src_sel, 0, 4);
+}
+
+/*vpp osd1 postblend mux sel*/
+static void vpp_osd1_postblend_mux_set(struct postblend_reg_s *reg,
+ enum vpp_blend_src_e src_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, src_sel, 8, 4);
+}
+/*vpp osd2 postblend mux sel*/
+static void vpp_osd2_postblend_mux_set(struct postblend_reg_s *reg,
+ enum vpp_blend_src_e src_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, src_sel, 8, 4);
+}
+/*vpp osd1 blend scope set*/
+static void vpp_osd1_blend_scope_set(struct postblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd1_bld_h_scope,
+ (scope.h_start << 16) | scope.h_end);
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd1_bld_v_scope,
+ (scope.v_start << 16) | scope.v_end);
+}
+/*vpp osd2 blend scope set*/
+static void vpp_osd2_blend_scope_set(struct postblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd2_bld_h_scope,
+ (scope.h_start << 16) | scope.h_end);
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd2_bld_v_scope,
+ (scope.v_start << 16) | scope.v_end);
+}
+
+static int postblend_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ DRM_DEBUG("%s check_state called.\n", postblend->base.name);
+ return 0;
+}
+
+static void postblend_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+ struct osd_scope_s scope = {0, 1919, 0, 1079};
+ struct meson_vpu_pipeline *pipeline = postblend->base.pipeline;
+ struct postblend_reg_s *reg = postblend->reg;
+ struct meson_vpu_pipeline_state *mvps;
+
+ DRM_DEBUG("%s set_state called.\n", postblend->base.name);
+ mvps = priv_to_pipeline_state(pipeline->obj.state);
+ scope.h_start = 0;
+ scope.h_end = mvps->scaler_param[0].output_width - 1;
+ scope.v_start = 0;
+ scope.v_end = mvps->scaler_param[0].output_height - 1;
+ vpp_osd1_blend_scope_set(reg, scope);
+ if (0)
+ vpp_osd2_blend_scope_set(reg, scope);
+ osd1_blend_premult_set(reg);
+ osd2_blend_premult_set(reg);
+ DRM_DEBUG("scope h/v start/end [%d,%d,%d,%d].\n",
+ scope.h_start, scope.h_end, scope.v_start, scope.v_end);
+}
+
+static void postblend_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+
+ DRM_DEBUG("%s enable called.\n", postblend->base.name);
+}
+
+static void postblend_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+
+ DRM_DEBUG("%s disable called.\n", postblend->base.name);
+}
+
+static void postblend_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+
+ postblend->reg = &postblend_reg;
+ /*dout switch config*/
+ osd1_blend_switch_set(postblend->reg, VPP_POSTBLEND);
+ osd2_blend_switch_set(postblend->reg, VPP_POSTBLEND);
+ /*vpp input config*/
+ vpp_osd1_preblend_mux_set(postblend->reg, VPP_NULL);
+ vpp_osd2_preblend_mux_set(postblend->reg, VPP_NULL);
+ vpp_osd1_postblend_mux_set(postblend->reg, VPP_OSD1);
+ vpp_osd2_postblend_mux_set(postblend->reg, VPP_NULL);
+ DRM_DEBUG("%s hw_init called.\n", postblend->base.name);
+}
+
+struct meson_vpu_block_ops postblend_ops = {
+ .check_state = postblend_check_state,
+ .update_state = postblend_set_state,
+ .enable = postblend_hw_enable,
+ .disable = postblend_hw_disable,
+ .init = postblend_hw_init,
+};
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _MESON_VPU_POSTBLEND_H_
+#define _MESON_VPU_POSTBLEND_H_
+
+#define VPP_OSD1_IN_SIZE 0x1df1
+#define VPP_OSD1_BLD_H_SCOPE 0x1df5
+#define VPP_OSD1_BLD_V_SCOPE 0x1df6
+#define VPP_OSD2_BLD_H_SCOPE 0x1df7
+#define VPP_OSD2_BLD_V_SCOPE 0x1df8
+
+#define VD1_BLEND_SRC_CTRL 0x1dfb
+#define VD2_BLEND_SRC_CTRL 0x1dfc
+#define OSD1_BLEND_SRC_CTRL 0x1dfd
+#define OSD2_BLEND_SRC_CTRL 0x1dfe
+
+#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968
+#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969
+
+struct postblend_reg_s {
+ u32 vpp_osd1_bld_h_scope;
+ u32 vpp_osd1_bld_v_scope;
+ u32 vpp_osd2_bld_h_scope;
+ u32 vpp_osd2_bld_v_scope;
+ u32 vd1_blend_src_ctrl;
+ u32 vd2_blend_src_ctrl;
+ u32 osd1_blend_src_ctrl;
+ u32 osd2_blend_src_ctrl;
+ u32 vpp_osd1_in_size;
+};
+
+enum vpp_blend_e {
+ VPP_PREBLEND = 0,
+ VPP_POSTBLEND,
+};
+
+enum vpp_blend_src_e {
+ VPP_NULL = 0,
+ VPP_VD1,
+ VPP_VD2,
+ VPP_OSD1,
+ VPP_OSD2
+};
+#endif
--- /dev/null
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_VPU_REG_H
+#define __MESON_VPU_REG_H
+
+#include "meson_osd_scaler.h"
+#include "meson_vpu_osd_mif.h"
+#include "meson_vpu_osdblend.h"
+
+/* vpp2 */
+#define VPP2_MISC 0x1e26
+#define VPP2_OFIFO_SIZE 0x1e27
+#define VPP2_INT_LINE_NUM 0x1e20
+#define VPP2_OFIFO_URG_CTRL 0x1e21
+#define VPP2_POSTBLEND_H_SIZE 0x1921
+
+/* viu */
+#define VIU_ADDR_START 0x1a00
+#define VIU_ADDR_END 0x1aff
+#define VIU_SW_RESET 0x1a01
+#define VIU_MISC_CTRL0 0x1a06
+#define D2D3_INTF_LENGTH 0x1a08
+#define D2D3_INTF_CTRL0 0x1a09
+
+
+#define VD1_IF0_GEN_REG 0x1a50
+#define VD1_IF0_CANVAS0 0x1a51
+#define VD1_IF0_CANVAS1 0x1a52
+#define VD1_IF0_LUMA_X0 0x1a53
+#define VD1_IF0_LUMA_Y0 0x1a54
+#define VD1_IF0_CHROMA_X0 0x1a55
+#define VD1_IF0_CHROMA_Y0 0x1a56
+#define VD1_IF0_LUMA_X1 0x1a57
+#define VD1_IF0_LUMA_Y1 0x1a58
+#define VD1_IF0_CHROMA_X1 0x1a59
+#define VD1_IF0_CHROMA_Y1 0x1a5a
+#define VD1_IF0_RPT_LOOP 0x1a5b
+#define VD1_IF0_LUMA0_RPT_PAT 0x1a5c
+#define VD1_IF0_CHROMA0_RPT_PAT 0x1a5d
+#define VD1_IF0_LUMA1_RPT_PAT 0x1a5e
+#define VD1_IF0_CHROMA1_RPT_PAT 0x1a5f
+#define VD1_IF0_LUMA_PSEL 0x1a60
+#define VD1_IF0_CHROMA_PSEL 0x1a61
+#define VD1_IF0_DUMMY_PIXEL 0x1a62
+#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63
+#define VD1_IF0_RANGE_MAP_Y 0x1a6a
+#define VD1_IF0_RANGE_MAP_CB 0x1a6b
+#define VD1_IF0_RANGE_MAP_CR 0x1a6c
+#define VD1_IF0_GEN_REG2 0x1a6d
+#define VD1_IF0_PROT_CNTL 0x1a6e
+#define VIU_VD1_FMT_CTRL 0x1a68
+#define VIU_VD1_FMT_W 0x1a69
+#define VD2_IF0_GEN_REG 0x1a70
+#define VD2_IF0_CANVAS0 0x1a71
+#define VD2_IF0_CANVAS1 0x1a72
+#define VD2_IF0_LUMA_X0 0x1a73
+#define VD2_IF0_LUMA_Y0 0x1a74
+#define VD2_IF0_CHROMA_X0 0x1a75
+#define VD2_IF0_CHROMA_Y0 0x1a76
+#define VD2_IF0_LUMA_X1 0x1a77
+#define VD2_IF0_LUMA_Y1 0x1a78
+#define VD2_IF0_CHROMA_X1 0x1a79
+#define VD2_IF0_CHROMA_Y1 0x1a7a
+#define VD2_IF0_RPT_LOOP 0x1a7b
+#define VD2_IF0_LUMA0_RPT_PAT 0x1a7c
+#define VD2_IF0_CHROMA0_RPT_PAT 0x1a7d
+#define VD2_IF0_LUMA1_RPT_PAT 0x1a7e
+#define VD2_IF0_CHROMA1_RPT_PAT 0x1a7f
+#define VD2_IF0_LUMA_PSEL 0x1a80
+#define VD2_IF0_CHROMA_PSEL 0x1a81
+#define VD2_IF0_DUMMY_PIXEL 0x1a82
+#define VD2_IF0_LUMA_FIFO_SIZE 0x1a83
+#define VD2_IF0_RANGE_MAP_Y 0x1a8a
+#define VD2_IF0_RANGE_MAP_CB 0x1a8b
+#define VD2_IF0_RANGE_MAP_CR 0x1a8c
+#define VD2_IF0_GEN_REG2 0x1a8d
+#define VD2_IF0_PROT_CNTL 0x1a8e
+#define VIU_VD2_FMT_CTRL 0x1a88
+#define VIU_VD2_FMT_W 0x1a89
+
+#define VIU_OSD1_MATRIX_CTRL 0x1a90
+#define VIU_OSD1_MATRIX_COEF00_01 0x1a91
+#define VIU_OSD1_MATRIX_COEF02_10 0x1a92
+#define VIU_OSD1_MATRIX_COEF11_12 0x1a93
+#define VIU_OSD1_MATRIX_COEF20_21 0x1a94
+#define VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95
+#define VIU_OSD1_MATRIX_OFFSET0_1 0x1a96
+#define VIU_OSD1_MATRIX_OFFSET2 0x1a97
+#define VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98
+#define VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99
+#define VIU_OSD1_MATRIX_COEF22_30 0x1a9d
+#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
+#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
+
+#define VIU_OSD_BLENDO_H_START_END 0x1aa9
+#define VIU_OSD_BLENDO_V_START_END 0x1aaa
+#define VIU_OSD_BLEND_GEN_CTRL0 0x1aab
+#define VIU_OSD_BLEND_GEN_CTRL1 0x1aac
+#define VIU_OSD_BLEND_DUMMY_DATA 0x1aad
+#define VIU_OSD_BLEND_CURRENT_XY 0x1aae
+
+#define VIU_OSD2_MATRIX_CTRL 0x1ab0
+#define VIU_OSD2_MATRIX_COEF00_01 0x1ab1
+#define VIU_OSD2_MATRIX_COEF02_10 0x1ab2
+#define VIU_OSD2_MATRIX_COEF11_12 0x1ab3
+#define VIU_OSD2_MATRIX_COEF20_21 0x1ab4
+#define VIU_OSD2_MATRIX_COEF22 0x1ab5
+#define VIU_OSD2_MATRIX_OFFSET0_1 0x1ab6
+#define VIU_OSD2_MATRIX_OFFSET2 0x1ab7
+#define VIU_OSD2_MATRIX_PRE_OFFSET0_1 0x1ab8
+#define VIU_OSD2_MATRIX_PRE_OFFSET2 0x1ab9
+#define VIU_OSD2_MATRIX_PROBE_COLOR 0x1aba
+#define VIU_OSD2_MATRIX_HL_COLOR 0x1abb
+#define VIU_OSD2_MATRIX_PROBE_POS 0x1abc
+#define VIU_OSD1_EOTF_CTL 0x1ad4
+#define VIU_OSD1_EOTF_COEF00_01 0x1ad5
+#define VIU_OSD1_EOTF_COEF02_10 0x1ad6
+#define VIU_OSD1_EOTF_COEF11_12 0x1ad7
+#define VIU_OSD1_EOTF_COEF20_21 0x1ad8
+#define VIU_OSD1_EOTF_COEF22_RS 0x1ad9
+#define VIU_OSD1_EOTF_LUT_ADDR_PORT 0x1ada
+#define VIU_OSD1_EOTF_LUT_DATA_PORT 0x1adb
+#define VIU_OSD1_OETF_CTL 0x1adc
+#define VIU_OSD1_OETF_LUT_ADDR_PORT 0x1add
+#define VIU_OSD1_OETF_LUT_DATA_PORT 0x1ade
+
+/* vpp */
+#define VPP_DUMMY_DATA 0x1d00
+#define VPP_LINE_IN_LENGTH 0x1d01
+#define VPP_PIC_IN_HEIGHT 0x1d02
+#define VPP_SCALE_COEF_IDX 0x1d03
+#define VPP_SCALE_COEF 0x1d04
+#define VPP_VSC_REGION12_STARTP 0x1d05
+#define VPP_VSC_REGION34_STARTP 0x1d06
+#define VPP_VSC_REGION4_ENDP 0x1d07
+#define VPP_VSC_START_PHASE_STEP 0x1d08
+#define VPP_VSC_REGION0_PHASE_SLOPE 0x1d09
+#define VPP_VSC_REGION1_PHASE_SLOPE 0x1d0a
+#define VPP_VSC_REGION3_PHASE_SLOPE 0x1d0b
+#define VPP_VSC_REGION4_PHASE_SLOPE 0x1d0c
+#define VPP_VSC_PHASE_CTRL 0x1d0d
+#define VPP_VSC_INI_PHASE 0x1d0e
+#define VPP_HSC_REGION12_STARTP 0x1d10
+#define VPP_HSC_REGION34_STARTP 0x1d11
+#define VPP_HSC_REGION4_ENDP 0x1d12
+#define VPP_HSC_START_PHASE_STEP 0x1d13
+#define VPP_HSC_REGION0_PHASE_SLOPE 0x1d14
+#define VPP_HSC_REGION1_PHASE_SLOPE 0x1d15
+#define VPP_HSC_REGION3_PHASE_SLOPE 0x1d16
+#define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17
+#define VPP_HSC_PHASE_CTRL 0x1d18
+#define VPP_SC_MISC 0x1d19
+#define VPP_PREBLEND_VD1_H_START_END 0x1d1a
+#define VPP_PREBLEND_VD1_V_START_END 0x1d1b
+#define VPP_POSTBLEND_VD1_H_START_END 0x1d1c
+#define VPP_POSTBLEND_VD1_V_START_END 0x1d1d
+#define VPP_BLEND_VD2_H_START_END 0x1d1e
+#define VPP_BLEND_VD2_V_START_END 0x1d1f
+#define VPP_PREBLEND_H_SIZE 0x1d20
+#define VPP_POSTBLEND_H_SIZE 0x1d21
+#define VPP_HOLD_LINES 0x1d22
+#define VPP_BLEND_ONECOLOR_CTRL 0x1d23
+#define VPP_PREBLEND_CURRENT_XY 0x1d24
+#define VPP_POSTBLEND_CURRENT_XY 0x1d25
+#define VPP_MISC 0x1d26
+#define VPP_OFIFO_SIZE 0x1d27
+#define VPP_FIFO_STATUS 0x1d28
+#define VPP_SMOKE_CTRL 0x1d29
+#define VPP_SMOKE1_VAL 0x1d2a
+#define VPP_SMOKE2_VAL 0x1d2b
+#define VPP_SMOKE3_VAL 0x1d2c
+#define VPP_SMOKE1_H_START_END 0x1d2d
+#define VPP_SMOKE1_V_START_END 0x1d2e
+#define VPP_SMOKE2_H_START_END 0x1d2f
+#define VPP_SMOKE2_V_START_END 0x1d30
+#define VPP_SMOKE3_H_START_END 0x1d31
+#define VPP_SMOKE3_V_START_END 0x1d32
+#define VPP_SCO_FIFO_CTRL 0x1d33
+#define VPP_HSC_PHASE_CTRL1 0x1d34
+#define VPP_HSC_INI_PAT_CTRL 0x1d35
+#define VPP_VADJ_CTRL 0x1d40
+#define VPP_VADJ1_Y 0x1d41
+#define VPP_VADJ1_MA_MB 0x1d42
+#define VPP_VADJ1_MC_MD 0x1d43
+#define VPP_VADJ2_Y 0x1d44
+#define VPP_VADJ2_MA_MB 0x1d45
+#define VPP_VADJ2_MC_MD 0x1d46
+#define VPP_HSHARP_CTRL 0x1d50
+#define VPP_HSHARP_LUMA_THRESH01 0x1d51
+#define VPP_HSHARP_LUMA_THRESH23 0x1d52
+#define VPP_HSHARP_CHROMA_THRESH01 0x1d53
+#define VPP_HSHARP_CHROMA_THRESH23 0x1d54
+#define VPP_HSHARP_LUMA_GAIN 0x1d55
+#define VPP_HSHARP_CHROMA_GAIN 0x1d56
+#define VPP_MATRIX_PROBE_COLOR 0x1d5c
+#define VPP_MATRIX_HL_COLOR 0x1d5d
+#define VPP_MATRIX_PROBE_POS 0x1d5e
+#define VPP_MATRIX_CTRL 0x1d5f
+#define VPP_MATRIX_COEF00_01 0x1d60
+#define VPP_MATRIX_COEF02_10 0x1d61
+#define VPP_MATRIX_COEF11_12 0x1d62
+#define VPP_MATRIX_COEF20_21 0x1d63
+#define VPP_MATRIX_COEF22 0x1d64
+#define VPP_MATRIX_OFFSET0_1 0x1d65
+#define VPP_MATRIX_OFFSET2 0x1d66
+#define VPP_MATRIX_PRE_OFFSET0_1 0x1d67
+#define VPP_MATRIX_PRE_OFFSET2 0x1d68
+#define VPP_DUMMY_DATA1 0x1d69
+#define VPP_GAINOFF_CTRL0 0x1d6a
+#define VPP_GAINOFF_CTRL1 0x1d6b
+#define VPP_GAINOFF_CTRL2 0x1d6c
+#define VPP_GAINOFF_CTRL3 0x1d6d
+#define VPP_GAINOFF_CTRL4 0x1d6e
+#define VPP_CHROMA_ADDR_PORT 0x1d70
+#define VPP_CHROMA_DATA_PORT 0x1d71
+#define VPP_GCLK_CTRL0 0x1d72
+#define VPP_GCLK_CTRL1 0x1d73
+#define VPP_SC_GCLK_CTRL 0x1d74
+#define VPP_MISC1 0x1d76
+#define VPP_BLACKEXT_CTRL 0x1d80
+#define VPP_DNLP_CTRL_00 0x1d81
+#define VPP_DNLP_CTRL_01 0x1d82
+#define VPP_DNLP_CTRL_02 0x1d83
+#define VPP_DNLP_CTRL_03 0x1d84
+#define VPP_DNLP_CTRL_04 0x1d85
+#define VPP_DNLP_CTRL_05 0x1d86
+#define VPP_DNLP_CTRL_06 0x1d87
+#define VPP_DNLP_CTRL_07 0x1d88
+#define VPP_DNLP_CTRL_08 0x1d89
+#define VPP_DNLP_CTRL_09 0x1d8a
+#define VPP_DNLP_CTRL_10 0x1d8b
+#define VPP_DNLP_CTRL_11 0x1d8c
+#define VPP_DNLP_CTRL_12 0x1d8d
+#define VPP_DNLP_CTRL_13 0x1d8e
+#define VPP_DNLP_CTRL_14 0x1d8f
+#define VPP_DNLP_CTRL_15 0x1d90
+#define VPP_PEAKING_HGAIN 0x1d91
+#define VPP_PEAKING_VGAIN 0x1d92
+#define VPP_PEAKING_NLP_1 0x1d93
+#define VPP_PEAKING_NLP_2 0x1d94
+#define VPP_PEAKING_NLP_3 0x1d95
+#define VPP_PEAKING_NLP_4 0x1d96
+#define VPP_PEAKING_NLP_5 0x1d97
+#define VPP_SHARP_LIMIT 0x1d98
+#define VPP_VLTI_CTRL 0x1d99
+#define VPP_HLTI_CTRL 0x1d9a
+#define VPP_CTI_CTRL 0x1d9b
+#define VPP_BLUE_STRETCH_1 0x1d9c
+#define VPP_BLUE_STRETCH_2 0x1d9d
+#define VPP_BLUE_STRETCH_3 0x1d9e
+#define VPP_CCORING_CTRL 0x1da0
+#define VPP_VE_ENABLE_CTRL 0x1da1
+#define VPP_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x1da2
+#define VPP_VE_DEMO_CENTER_BAR 0x1da3
+#define VPP_VE_H_V_SIZE 0x1da4
+#define VPP_VDO_MEAS_CTRL 0x1da8
+#define VPP_VDO_MEAS_VS_COUNT_HI 0x1da9
+#define VPP_VDO_MEAS_VS_COUNT_LO 0x1daa
+#define VPP_INPUT_CTRL 0x1dab
+#define VPP_CTI_CTRL2 0x1dac
+#define VPP_PEAKING_SAT_THD1 0x1dad
+#define VPP_PEAKING_SAT_THD2 0x1dae
+#define VPP_PEAKING_SAT_THD3 0x1daf
+#define VPP_PEAKING_SAT_THD4 0x1db0
+#define VPP_PEAKING_SAT_THD5 0x1db1
+#define VPP_PEAKING_SAT_THD6 0x1db2
+#define VPP_PEAKING_SAT_THD7 0x1db3
+#define VPP_PEAKING_SAT_THD8 0x1db4
+#define VPP_PEAKING_SAT_THD9 0x1db5
+#define VPP_PEAKING_GAIN_ADD1 0x1db6
+#define VPP_PEAKING_GAIN_ADD2 0x1db7
+#define VPP_PEAKING_DNLP 0x1db8
+#define VPP_SHARP_DEMO_WIN_CTRL1 0x1db9
+#define VPP_SHARP_DEMO_WIN_CTRL2 0x1dba
+#define VPP_FRONT_HLTI_CTRL 0x1dbb
+#define VPP_FRONT_CTI_CTRL 0x1dbc
+#define VPP_FRONT_CTI_CTRL2 0x1dbd
+#define VPP_INT_LINE_NUM 0x1dce
+
+/* viu2 */
+#define VIU2_ADDR_START 0x1e00
+#define VIU2_ADDR_END 0x1eff
+#define VIU2_SW_RESET 0x1e01
+#define VIU2_SW_RESET0 0x1e02
+#define VIU2_SECURE_REG 0x1e05
+#define VIU2_MISC_CTRL0 0x1e06
+#define VIU2_OSD1_CTRL_STAT 0x1e30
+#define VIU2_OSD1_CTRL_STAT2 0x1e4d
+#define VIU2_OSD1_COLOR_ADDR 0x1e31
+#define VIU2_OSD1_COLOR 0x1e32
+#define VIU2_OSD1_HL1_H_START_END 0x1e33
+#define VIU2_OSD1_HL1_V_START_END 0x1e34
+#define VIU2_OSD1_HL2_H_START_END 0x1e35
+#define VIU2_OSD1_HL2_V_START_END 0x1e36
+#define VIU2_OSD1_TCOLOR_AG0 0x1e37
+#define VIU2_OSD1_TCOLOR_AG1 0x1e38
+#define VIU2_OSD1_TCOLOR_AG2 0x1e39
+#define VIU2_OSD1_TCOLOR_AG3 0x1e3a
+#define VIU2_OSD1_BLK0_CFG_W0 0x1e3b
+#define VIU2_OSD1_BLK1_CFG_W0 0x1e3f
+#define VIU2_OSD1_BLK2_CFG_W0 0x1e43
+#define VIU2_OSD1_BLK3_CFG_W0 0x1e47
+#define VIU2_OSD1_BLK0_CFG_W1 0x1e3c
+#define VIU2_OSD1_BLK1_CFG_W1 0x1e40
+#define VIU2_OSD1_BLK2_CFG_W1 0x1e44
+#define VIU2_OSD1_BLK3_CFG_W1 0x1e48
+#define VIU2_OSD1_BLK0_CFG_W2 0x1e3d
+#define VIU2_OSD1_BLK1_CFG_W2 0x1e41
+#define VIU2_OSD1_BLK2_CFG_W2 0x1e45
+#define VIU2_OSD1_BLK3_CFG_W2 0x1e49
+#define VIU2_OSD1_BLK0_CFG_W3 0x1e3e
+#define VIU2_OSD1_BLK1_CFG_W3 0x1e42
+#define VIU2_OSD1_BLK2_CFG_W3 0x1e46
+#define VIU2_OSD1_BLK3_CFG_W3 0x1e4a
+#define VIU2_OSD1_BLK0_CFG_W4 0x1e64
+#define VIU2_OSD1_BLK1_CFG_W4 0x1e65
+#define VIU2_OSD1_BLK2_CFG_W4 0x1e66
+#define VIU2_OSD1_BLK3_CFG_W4 0x1e67
+#define VIU2_OSD1_FIFO_CTRL_STAT 0x1e4b
+#define VIU2_OSD1_TEST_RDDATA 0x1e4c
+#define VIU2_OSD1_PROT_CTRL 0x1e4e
+#define VIU2_OSD1_MALI_UNPACK_CTRL 0x1e4f
+#define VIU2_OSD1_DIMM_CTRL 0x1e50
+#define VIU2_OSD1_UNSUPPORT VIU_OSD2_TCOLOR_AG3
+/* viu2 rotate */
+#define VIU2_RMIF_CTRL1 0x1e81
+#define VIU2_RMIF_SCOPE_X 0x1e83
+#define VIU2_RMIF_SCOPE_Y 0x1e84
+#define VIU2_ROT_BLK_SIZE 0x1e85
+#define VIU2_ROT_LBUF_SIZE 0x1e86
+#define VIU2_ROT_FMT_CTRL 0x1e87
+#define VIU2_ROT_OUT_VCROP 0x1e89
+
+/* encode */
+#define ENCP_VFIFO2VD_CTL 0x1b58
+#define ENCP_VFIFO2VD_PIXEL_START 0x1b59
+#define ENCP_VFIFO2VD_PIXEL_END 0x1b5a
+#define ENCP_VFIFO2VD_LINE_TOP_START 0x1b5b
+#define ENCP_VFIFO2VD_LINE_TOP_END 0x1b5c
+#define ENCP_VFIFO2VD_LINE_BOT_START 0x1b5d
+#define ENCP_VFIFO2VD_LINE_BOT_END 0x1b5e
+#define VENC_SYNC_ROUTE 0x1b60
+#define VENC_VIDEO_EXSRC 0x1b61
+#define VENC_DVI_SETTING 0x1b62
+#define VENC_C656_CTRL 0x1b63
+#define VENC_UPSAMPLE_CTRL0 0x1b64
+#define VENC_UPSAMPLE_CTRL1 0x1b65
+#define VENC_UPSAMPLE_CTRL2 0x1b66
+#define TCON_INVERT_CTL 0x1b67
+#define VENC_VIDEO_PROG_MODE 0x1b68
+#define VENC_ENCI_LINE 0x1b69
+#define VENC_ENCI_PIXEL 0x1b6a
+#define VENC_ENCP_LINE 0x1b6b
+#define VENC_ENCP_PIXEL 0x1b6c
+#define VENC_STATA 0x1b6d
+#define VENC_INTCTRL 0x1b6e
+#define VENC_INTFLAG 0x1b6f
+#define VENC_VIDEO_TST_EN 0x1b70
+#define VENC_VIDEO_TST_MDSEL 0x1b71
+#define VENC_VIDEO_TST_Y 0x1b72
+#define VENC_VIDEO_TST_CB 0x1b73
+#define VENC_VIDEO_TST_CR 0x1b74
+#define VENC_VIDEO_TST_CLRBAR_STRT 0x1b75
+#define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76
+#define VENC_VIDEO_TST_VDCNT_STSET 0x1b77
+#define VENC_VDAC_DACSEL0 0x1b78
+#define VENC_VDAC_DACSEL1 0x1b79
+#define VENC_VDAC_DACSEL2 0x1b7a
+#define VENC_VDAC_DACSEL3 0x1b7b
+#define VENC_VDAC_DACSEL4 0x1b7c
+#define VENC_VDAC_DACSEL5 0x1b7d
+#define VENC_VDAC_SETTING 0x1b7e
+#define VENC_VDAC_TST_VAL 0x1b7f
+#define VENC_VDAC_DAC0_GAINCTRL 0x1bf0
+#define VENC_VDAC_DAC0_OFFSET 0x1bf1
+#define VENC_VDAC_DAC1_GAINCTRL 0x1bf2
+#define VENC_VDAC_DAC1_OFFSET 0x1bf3
+#define VENC_VDAC_DAC2_GAINCTRL 0x1bf4
+#define VENC_VDAC_DAC2_OFFSET 0x1bf5
+#define VENC_VDAC_DAC3_GAINCTRL 0x1bf6
+#define VENC_VDAC_DAC3_OFFSET 0x1bf7
+#define VENC_VDAC_DAC4_GAINCTRL 0x1bf8
+#define VENC_VDAC_DAC4_OFFSET 0x1bf9
+#define VENC_VDAC_DAC5_GAINCTRL 0x1bfa
+#define VENC_VDAC_DAC5_OFFSET 0x1bfb
+#define VENC_VDAC_FIFO_CTRL 0x1bfc
+#define ENCL_TCON_INVERT_CTL 0x1bfd
+#define ENCP_VIDEO_EN 0x1b80
+#define ENCP_VIDEO_SYNC_MODE 0x1b81
+#define ENCP_MACV_EN 0x1b82
+#define ENCP_VIDEO_Y_SCL 0x1b83
+#define ENCP_VIDEO_PB_SCL 0x1b84
+#define ENCP_VIDEO_PR_SCL 0x1b85
+#define ENCP_VIDEO_SYNC_SCL 0x1b86
+#define ENCP_VIDEO_MACV_SCL 0x1b87
+#define ENCP_VIDEO_Y_OFFST 0x1b88
+#define ENCP_VIDEO_PB_OFFST 0x1b89
+#define ENCP_VIDEO_PR_OFFST 0x1b8a
+#define ENCP_VIDEO_SYNC_OFFST 0x1b8b
+#define ENCP_VIDEO_MACV_OFFST 0x1b8c
+#define ENCP_VIDEO_MODE 0x1b8d
+#define ENCP_VIDEO_MODE_ADV 0x1b8e
+#define ENCP_DBG_PX_RST 0x1b90
+#define ENCP_DBG_LN_RST 0x1b91
+#define ENCP_DBG_PX_INT 0x1b92
+#define ENCP_DBG_LN_INT 0x1b93
+#define ENCP_VIDEO_YFP1_HTIME 0x1b94
+#define ENCP_VIDEO_YFP2_HTIME 0x1b95
+#define ENCP_VIDEO_YC_DLY 0x1b96
+#define ENCP_VIDEO_MAX_PXCNT 0x1b97
+#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98
+#define ENCP_VIDEO_HSPULS_END 0x1b99
+#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a
+#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b
+#define ENCP_VIDEO_VSPULS_END 0x1b9c
+#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d
+#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e
+#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f
+#define ENCP_VIDEO_EQPULS_END 0x1ba0
+#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1
+#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2
+#define ENCP_VIDEO_HAVON_END 0x1ba3
+#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4
+#define ENCP_VIDEO_VAVON_ELINE 0x1baf
+#define ENCP_VIDEO_VAVON_BLINE 0x1ba6
+#define ENCP_VIDEO_HSO_BEGIN 0x1ba7
+#define ENCP_VIDEO_HSO_END 0x1ba8
+#define ENCP_VIDEO_VSO_BEGIN 0x1ba9
+#define ENCP_VIDEO_VSO_END 0x1baa
+#define ENCP_VIDEO_VSO_BLINE 0x1bab
+#define ENCP_VIDEO_VSO_ELINE 0x1bac
+#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad
+#define ENCP_VIDEO_MAX_LNCNT 0x1bae
+#define ENCP_VIDEO_SY_VAL 0x1bb0
+#define ENCP_VIDEO_SY2_VAL 0x1bb1
+#define ENCP_VIDEO_BLANKY_VAL 0x1bb2
+#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3
+#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4
+#define ENCP_VIDEO_HOFFST 0x1bb5
+#define ENCP_VIDEO_VOFFST 0x1bb6
+#define ENCP_VIDEO_RGB_CTRL 0x1bb7
+#define ENCP_VIDEO_FILT_CTRL 0x1bb8
+#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9
+#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba
+#define ENCP_VIDEO_MATRIX_CB 0x1bbb
+#define ENCP_VIDEO_MATRIX_CR 0x1bbc
+#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd
+#define ENCP_MACV_BLANKY_VAL 0x1bc0
+#define ENCP_MACV_MAXY_VAL 0x1bc1
+#define ENCP_MACV_1ST_PSSYNC_STRT 0x1bc2
+#define ENCP_MACV_PSSYNC_STRT 0x1bc3
+#define ENCP_MACV_AGC_STRT 0x1bc4
+#define ENCP_MACV_AGC_END 0x1bc5
+#define ENCP_MACV_WAVE_END 0x1bc6
+#define ENCP_MACV_STRTLINE 0x1bc7
+#define ENCP_MACV_ENDLINE 0x1bc8
+#define ENCP_MACV_TS_CNT_MAX_L 0x1bc9
+#define ENCP_MACV_TS_CNT_MAX_H 0x1bca
+#define ENCP_MACV_TIME_DOWN 0x1bcb
+#define ENCP_MACV_TIME_LO 0x1bcc
+#define ENCP_MACV_TIME_UP 0x1bcd
+#define ENCP_MACV_TIME_RST 0x1bce
+#define ENCP_VBI_CTRL 0x1bd0
+#define ENCP_VBI_SETTING 0x1bd1
+#define ENCP_VBI_BEGIN 0x1bd2
+#define ENCP_VBI_WIDTH 0x1bd3
+#define ENCP_VBI_HVAL 0x1bd4
+#define ENCP_VBI_DATA0 0x1bd5
+#define ENCP_VBI_DATA1 0x1bd6
+#define C656_HS_ST 0x1be0
+#define C656_HS_ED 0x1be1
+#define C656_VS_LNST_E 0x1be2
+#define C656_VS_LNST_O 0x1be3
+#define C656_VS_LNED_E 0x1be4
+#define C656_VS_LNED_O 0x1be5
+#define C656_FS_LNST 0x1be6
+#define C656_FS_LNED 0x1be7
+#define ENCI_VIDEO_MODE 0x1b00
+#define ENCI_VIDEO_MODE_ADV 0x1b01
+#define ENCI_VIDEO_FSC_ADJ 0x1b02
+#define ENCI_VIDEO_BRIGHT 0x1b03
+#define ENCI_VIDEO_CONT 0x1b04
+#define ENCI_VIDEO_SAT 0x1b05
+#define ENCI_VIDEO_HUE 0x1b06
+#define ENCI_VIDEO_SCH 0x1b07
+#define ENCI_SYNC_MODE 0x1b08
+#define ENCI_SYNC_CTRL 0x1b09
+#define ENCI_SYNC_HSO_BEGIN 0x1b0a
+#define ENCI_SYNC_HSO_END 0x1b0b
+#define ENCI_SYNC_VSO_EVN 0x1b0c
+#define ENCI_SYNC_VSO_ODD 0x1b0d
+#define ENCI_SYNC_VSO_EVNLN 0x1b0e
+#define ENCI_SYNC_VSO_ODDLN 0x1b0f
+#define ENCI_SYNC_HOFFST 0x1b10
+#define ENCI_SYNC_VOFFST 0x1b11
+#define ENCI_SYNC_ADJ 0x1b12
+#define ENCI_RGB_SETTING 0x1b13
+#define ENCI_DE_H_BEGIN 0x1b16
+#define ENCI_DE_H_END 0x1b17
+#define ENCI_DE_V_BEGIN_EVEN 0x1b18
+#define ENCI_DE_V_END_EVEN 0x1b19
+#define ENCI_DE_V_BEGIN_ODD 0x1b1a
+#define ENCI_DE_V_END_ODD 0x1b1b
+#define ENCI_VBI_SETTING 0x1b20
+#define ENCI_VBI_CCDT_EVN 0x1b21
+#define ENCI_VBI_CCDT_ODD 0x1b22
+#define ENCI_VBI_CC525_LN 0x1b23
+#define ENCI_VBI_CC625_LN 0x1b24
+#define ENCI_VBI_WSSDT 0x1b25
+#define ENCI_VBI_WSS_LN 0x1b26
+#define ENCI_VBI_CGMSDT_L 0x1b27
+#define ENCI_VBI_CGMSDT_H 0x1b28
+#define ENCI_VBI_CGMS_LN 0x1b29
+#define ENCI_VBI_TTX_HTIME 0x1b2a
+#define ENCI_VBI_TTX_LN 0x1b2b
+#define ENCI_VBI_TTXDT0 0x1b2c
+#define ENCI_VBI_TTXDT1 0x1b2d
+#define ENCI_VBI_TTXDT2 0x1b2e
+#define ENCI_VBI_TTXDT3 0x1b2f
+#define ENCI_MACV_N0 0x1b30
+#define ENCI_MACV_N1 0x1b31
+#define ENCI_MACV_N2 0x1b32
+#define ENCI_MACV_N3 0x1b33
+#define ENCI_MACV_N4 0x1b34
+#define ENCI_MACV_N5 0x1b35
+#define ENCI_MACV_N6 0x1b36
+#define ENCI_MACV_N7 0x1b37
+#define ENCI_MACV_N8 0x1b38
+#define ENCI_MACV_N9 0x1b39
+#define ENCI_MACV_N10 0x1b3a
+#define ENCI_MACV_N11 0x1b3b
+#define ENCI_MACV_N12 0x1b3c
+#define ENCI_MACV_N13 0x1b3d
+#define ENCI_MACV_N14 0x1b3e
+#define ENCI_MACV_N15 0x1b3f
+#define ENCI_MACV_N16 0x1b40
+#define ENCI_MACV_N17 0x1b41
+#define ENCI_MACV_N18 0x1b42
+#define ENCI_MACV_N19 0x1b43
+#define ENCI_MACV_N20 0x1b44
+#define ENCI_MACV_N21 0x1b45
+#define ENCI_MACV_N22 0x1b46
+#define ENCI_DBG_PX_RST 0x1b48
+#define ENCI_DBG_FLDLN_RST 0x1b49
+#define ENCI_DBG_PX_INT 0x1b4a
+#define ENCI_DBG_FLDLN_INT 0x1b4b
+#define ENCI_DBG_MAXPX 0x1b4c
+#define ENCI_DBG_MAXLN 0x1b4d
+#define ENCI_MACV_MAX_AMP 0x1b50
+#define ENCI_MACV_PULSE_LO 0x1b51
+#define ENCI_MACV_PULSE_HI 0x1b52
+#define ENCI_MACV_BKP_MAX 0x1b53
+#define ENCI_CFILT_CTRL 0x1b54
+#define ENCI_CFILT7 0x1b55
+#define ENCI_YC_DELAY 0x1b56
+#define ENCI_VIDEO_EN 0x1b57
+#define ENCI_DVI_HSO_BEGIN 0x1c00
+#define ENCI_DVI_HSO_END 0x1c01
+#define ENCI_DVI_VSO_BLINE_EVN 0x1c02
+#define ENCI_DVI_VSO_BLINE_ODD 0x1c03
+#define ENCI_DVI_VSO_ELINE_EVN 0x1c04
+#define ENCI_DVI_VSO_ELINE_ODD 0x1c05
+#define ENCI_DVI_VSO_BEGIN_EVN 0x1c06
+#define ENCI_DVI_VSO_BEGIN_ODD 0x1c07
+#define ENCI_DVI_VSO_END_EVN 0x1c08
+#define ENCI_DVI_VSO_END_ODD 0x1c09
+#define ENCI_CFILT_CTRL2 0x1c0a
+#define ENCI_DACSEL_0 0x1c0b
+#define ENCI_DACSEL_1 0x1c0c
+#define ENCP_DACSEL_0 0x1c0d
+#define ENCP_DACSEL_1 0x1c0e
+#define ENCP_MAX_LINE_SWITCH_POINT 0x1c0f
+#define ENCI_TST_EN 0x1c10
+#define ENCI_TST_MDSEL 0x1c11
+#define ENCI_TST_Y 0x1c12
+#define ENCI_TST_CB 0x1c13
+#define ENCI_TST_CR 0x1c14
+#define ENCI_TST_CLRBAR_STRT 0x1c15
+#define ENCI_TST_CLRBAR_WIDTH 0x1c16
+#define ENCI_TST_VDCNT_STSET 0x1c17
+#define ENCI_VFIFO2VD_CTL 0x1c18
+#define ENCI_VFIFO2VD_PIXEL_START 0x1c19
+#define ENCI_VFIFO2VD_PIXEL_END 0x1c1a
+#define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b
+#define ENCI_VFIFO2VD_LINE_TOP_END 0x1c1c
+#define ENCI_VFIFO2VD_LINE_BOT_START 0x1c1d
+#define ENCI_VFIFO2VD_LINE_BOT_END 0x1c1e
+#define ENCI_VFIFO2VD_CTL2 0x1c1f
+#define ENCT_VFIFO2VD_CTL 0x1c20
+#define ENCT_VFIFO2VD_PIXEL_START 0x1c21
+#define ENCT_VFIFO2VD_PIXEL_END 0x1c22
+#define ENCT_VFIFO2VD_LINE_TOP_START 0x1c23
+#define ENCT_VFIFO2VD_LINE_TOP_END 0x1c24
+#define ENCT_VFIFO2VD_LINE_BOT_START 0x1c25
+#define ENCT_VFIFO2VD_LINE_BOT_END 0x1c26
+#define ENCT_VFIFO2VD_CTL2 0x1c27
+#define ENCT_TST_EN 0x1c28
+#define ENCT_TST_MDSEL 0x1c29
+#define ENCT_TST_Y 0x1c2a
+#define ENCT_TST_CB 0x1c2b
+#define ENCT_TST_CR 0x1c2c
+#define ENCT_TST_CLRBAR_STRT 0x1c2d
+#define ENCT_TST_CLRBAR_WIDTH 0x1c2e
+#define ENCT_TST_VDCNT_STSET 0x1c2f
+#define ENCP_DVI_HSO_BEGIN 0x1c30
+#define ENCP_DVI_HSO_END 0x1c31
+#define ENCP_DVI_VSO_BLINE_EVN 0x1c32
+#define ENCP_DVI_VSO_BLINE_ODD 0x1c33
+#define ENCP_DVI_VSO_ELINE_EVN 0x1c34
+#define ENCP_DVI_VSO_ELINE_ODD 0x1c35
+#define ENCP_DVI_VSO_BEGIN_EVN 0x1c36
+#define ENCP_DVI_VSO_BEGIN_ODD 0x1c37
+#define ENCP_DVI_VSO_END_EVN 0x1c38
+#define ENCP_DVI_VSO_END_ODD 0x1c39
+#define ENCP_DE_H_BEGIN 0x1c3a
+#define ENCP_DE_H_END 0x1c3b
+#define ENCP_DE_V_BEGIN_EVEN 0x1c3c
+#define ENCP_DE_V_END_EVEN 0x1c3d
+#define ENCP_DE_V_BEGIN_ODD 0x1c3e
+#define ENCP_DE_V_END_ODD 0x1c3f
+#define ENCI_SYNC_LINE_LENGTH 0x1c40
+#define ENCI_SYNC_PIXEL_EN 0x1c41
+#define ENCI_SYNC_TO_LINE_EN 0x1c42
+#define ENCI_SYNC_TO_PIXEL 0x1c43
+#define ENCP_SYNC_LINE_LENGTH 0x1c44
+#define ENCP_SYNC_PIXEL_EN 0x1c45
+#define ENCP_SYNC_TO_LINE_EN 0x1c46
+#define ENCP_SYNC_TO_PIXEL 0x1c47
+#define ENCT_SYNC_LINE_LENGTH 0x1c48
+#define ENCT_SYNC_PIXEL_EN 0x1c49
+#define ENCT_SYNC_TO_LINE_EN 0x1c4a
+#define ENCT_SYNC_TO_PIXEL 0x1c4b
+#define ENCL_SYNC_LINE_LENGTH 0x1c4c
+#define ENCL_SYNC_PIXEL_EN 0x1c4d
+#define ENCL_SYNC_TO_LINE_EN 0x1c4e
+#define ENCL_SYNC_TO_PIXEL 0x1c4f
+#define ENCP_VFIFO2VD_CTL2 0x1c50
+#define VENC_DVI_SETTING_MORE 0x1c51
+#define VENC_VDAC_DAC4_FILT_CTRL0 0x1c54
+#define VENC_VDAC_DAC4_FILT_CTRL1 0x1c55
+#define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56
+#define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57
+#define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58
+#define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59
+#define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a
+#define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b
+#define VENC_VDAC_DAC2_FILT_CTRL0 0x1c5c
+#define VENC_VDAC_DAC2_FILT_CTRL1 0x1c5d
+#define VENC_VDAC_DAC3_FILT_CTRL0 0x1c5e
+#define VENC_VDAC_DAC3_FILT_CTRL1 0x1c5f
+#define ENCT_VIDEO_EN 0x1c60
+#define ENCT_VIDEO_Y_SCL 0x1c61
+#define ENCT_VIDEO_PB_SCL 0x1c62
+#define ENCT_VIDEO_PR_SCL 0x1c63
+#define ENCT_VIDEO_Y_OFFST 0x1c64
+#define ENCT_VIDEO_PB_OFFST 0x1c65
+#define ENCT_VIDEO_PR_OFFST 0x1c66
+#define ENCT_VIDEO_MODE 0x1c67
+#define ENCT_VIDEO_MODE_ADV 0x1c68
+#define ENCT_DBG_PX_RST 0x1c69
+#define ENCT_DBG_LN_RST 0x1c6a
+#define ENCT_DBG_PX_INT 0x1c6b
+#define ENCT_DBG_LN_INT 0x1c6c
+#define ENCT_VIDEO_YFP1_HTIME 0x1c6d
+#define ENCT_VIDEO_YFP2_HTIME 0x1c6e
+#define ENCT_VIDEO_YC_DLY 0x1c6f
+#define ENCT_VIDEO_MAX_PXCNT 0x1c70
+#define ENCT_VIDEO_HAVON_END 0x1c71
+#define ENCT_VIDEO_HAVON_BEGIN 0x1c72
+#define ENCT_VIDEO_VAVON_ELINE 0x1c73
+#define ENCT_VIDEO_VAVON_BLINE 0x1c74
+#define ENCT_VIDEO_HSO_BEGIN 0x1c75
+#define ENCT_VIDEO_HSO_END 0x1c76
+#define ENCT_VIDEO_VSO_BEGIN 0x1c77
+#define ENCT_VIDEO_VSO_END 0x1c78
+#define ENCT_VIDEO_VSO_BLINE 0x1c79
+#define ENCT_VIDEO_VSO_ELINE 0x1c7a
+#define ENCT_VIDEO_MAX_LNCNT 0x1c7b
+#define ENCT_VIDEO_BLANKY_VAL 0x1c7c
+#define ENCT_VIDEO_BLANKPB_VAL 0x1c7d
+#define ENCT_VIDEO_BLANKPR_VAL 0x1c7e
+#define ENCT_VIDEO_HOFFST 0x1c7f
+#define ENCT_VIDEO_VOFFST 0x1c80
+#define ENCT_VIDEO_RGB_CTRL 0x1c81
+#define ENCT_VIDEO_FILT_CTRL 0x1c82
+#define ENCT_VIDEO_OFLD_VPEQ_OFST 0x1c83
+#define ENCT_VIDEO_OFLD_VOAV_OFST 0x1c84
+#define ENCT_VIDEO_MATRIX_CB 0x1c85
+#define ENCT_VIDEO_MATRIX_CR 0x1c86
+#define ENCT_VIDEO_RGBIN_CTRL 0x1c87
+#define ENCT_MAX_LINE_SWITCH_POINT 0x1c88
+#define ENCT_DACSEL_0 0x1c89
+#define ENCT_DACSEL_1 0x1c8a
+#define ENCL_VFIFO2VD_CTL 0x1c90
+#define ENCL_VFIFO2VD_PIXEL_START 0x1c91
+#define ENCL_VFIFO2VD_PIXEL_END 0x1c92
+#define ENCL_VFIFO2VD_LINE_TOP_START 0x1c93
+#define ENCL_VFIFO2VD_LINE_TOP_END 0x1c94
+#define ENCL_VFIFO2VD_LINE_BOT_START 0x1c95
+#define ENCL_VFIFO2VD_LINE_BOT_END 0x1c96
+#define ENCL_VFIFO2VD_CTL2 0x1c97
+#define ENCL_TST_EN 0x1c98
+#define ENCL_TST_MDSEL 0x1c99
+#define ENCL_TST_Y 0x1c9a
+#define ENCL_TST_CB 0x1c9b
+#define ENCL_TST_CR 0x1c9c
+#define ENCL_TST_CLRBAR_STRT 0x1c9d
+#define ENCL_TST_CLRBAR_WIDTH 0x1c9e
+#define ENCL_TST_VDCNT_STSET 0x1c9f
+#define ENCL_VIDEO_EN 0x1ca0
+#define ENCL_VIDEO_Y_SCL 0x1ca1
+#define ENCL_VIDEO_PB_SCL 0x1ca2
+#define ENCL_VIDEO_PR_SCL 0x1ca3
+#define ENCL_VIDEO_Y_OFFST 0x1ca4
+#define ENCL_VIDEO_PB_OFFST 0x1ca5
+#define ENCL_VIDEO_PR_OFFST 0x1ca6
+#define ENCL_VIDEO_MODE 0x1ca7
+#define ENCL_VIDEO_MODE_ADV 0x1ca8
+#define ENCL_DBG_PX_RST 0x1ca9
+#define ENCL_DBG_LN_RST 0x1caa
+#define ENCL_DBG_PX_INT 0x1cab
+#define ENCL_DBG_LN_INT 0x1cac
+#define ENCL_VIDEO_YFP1_HTIME 0x1cad
+#define ENCL_VIDEO_YFP2_HTIME 0x1cae
+#define ENCL_VIDEO_YC_DLY 0x1caf
+#define ENCL_VIDEO_MAX_PXCNT 0x1cb0
+#define ENCL_VIDEO_HAVON_END 0x1cb1
+#define ENCL_VIDEO_HAVON_BEGIN 0x1cb2
+#define ENCL_VIDEO_VAVON_ELINE 0x1cb3
+#define ENCL_VIDEO_VAVON_BLINE 0x1cb4
+#define ENCL_VIDEO_HSO_BEGIN 0x1cb5
+#define ENCL_VIDEO_HSO_END 0x1cb6
+#define ENCL_VIDEO_VSO_BEGIN 0x1cb7
+#define ENCL_VIDEO_VSO_END 0x1cb8
+#define ENCL_VIDEO_VSO_BLINE 0x1cb9
+#define ENCL_VIDEO_VSO_ELINE 0x1cba
+#define ENCL_VIDEO_MAX_LNCNT 0x1cbb
+#define ENCL_VIDEO_BLANKY_VAL 0x1cbc
+#define ENCL_VIDEO_BLANKPB_VAL 0x1cbd
+#define ENCL_VIDEO_BLANKPR_VAL 0x1cbe
+#define ENCL_VIDEO_HOFFST 0x1cbf
+#define ENCL_VIDEO_VOFFST 0x1cc0
+#define ENCL_VIDEO_RGB_CTRL 0x1cc1
+#define ENCL_VIDEO_FILT_CTRL 0x1cc2
+#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3
+#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4
+#define ENCL_VIDEO_MATRIX_CB 0x1cc5
+#define ENCL_VIDEO_MATRIX_CR 0x1cc6
+#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7
+#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8
+#define ENCL_DACSEL_0 0x1cc9
+#define ENCL_DACSEL_1 0x1cca
+#define RDMA_AHB_START_ADDR_MAN 0x1100
+#define RDMA_AHB_END_ADDR_MAN 0x1101
+#define RDMA_AHB_START_ADDR_1 0x1102
+#define RDMA_AHB_END_ADDR_1 0x1103
+#define RDMA_AHB_START_ADDR_2 0x1104
+#define RDMA_AHB_END_ADDR_2 0x1105
+#define RDMA_AHB_START_ADDR_3 0x1106
+#define RDMA_AHB_END_ADDR_3 0x1107
+#define RDMA_AHB_START_ADDR_4 0x1108
+#define RDMA_AHB_END_ADDR_4 0x1109
+#define RDMA_AHB_START_ADDR_5 0x110a
+#define RDMA_AHB_END_ADDR_5 0x110b
+#define RDMA_AHB_START_ADDR_6 0x110c
+#define RDMA_AHB_END_ADDR_6 0x110d
+#define RDMA_AHB_START_ADDR_7 0x110e
+#define RDMA_AHB_END_ADDR_7 0x110f
+#define RDMA_ACCESS_AUTO 0x1110
+#define RDMA_ACCESS_AUTO2 0x1111
+#define RDMA_ACCESS_AUTO3 0x1112
+#define RDMA_ACCESS_MAN 0x1113
+#define RDMA_CTRL 0x1114
+#define RDMA_STATUS 0x1115
+#define RDMA_STATUS2 0x1116
+#define RDMA_STATUS3 0x1117
+#define L_GAMMA_CNTL_PORT 0x1400
+#define L_GAMMA_DATA_PORT 0x1401
+#define L_GAMMA_ADDR_PORT 0x1402
+#define L_GAMMA_VCOM_HSWITCH_ADDR 0x1403
+#define L_RGB_BASE_ADDR 0x1405
+#define L_RGB_COEFF_ADDR 0x1406
+#define L_POL_CNTL_ADDR 0x1407
+#define L_DITH_CNTL_ADDR 0x1408
+#define L_GAMMA_PROBE_CTRL 0x1409
+#define L_GAMMA_PROBE_COLOR_L 0x140a
+#define L_GAMMA_PROBE_COLOR_H 0x140b
+#define L_GAMMA_PROBE_HL_COLOR 0x140c
+#define L_GAMMA_PROBE_POS_X 0x140d
+#define L_GAMMA_PROBE_POS_Y 0x140e
+#define L_STH1_HS_ADDR 0x1410
+#define L_STH1_HE_ADDR 0x1411
+#define L_STH1_VS_ADDR 0x1412
+#define L_STH1_VE_ADDR 0x1413
+#define L_STH2_HS_ADDR 0x1414
+#define L_STH2_HE_ADDR 0x1415
+#define L_STH2_VS_ADDR 0x1416
+#define L_STH2_VE_ADDR 0x1417
+#define L_OEH_HS_ADDR 0x1418
+#define L_OEH_HE_ADDR 0x1419
+#define L_OEH_VS_ADDR 0x141a
+#define L_OEH_VE_ADDR 0x141b
+#define L_VCOM_HSWITCH_ADDR 0x141c
+#define L_VCOM_VS_ADDR 0x141d
+#define L_VCOM_VE_ADDR 0x141e
+#define L_CPV1_HS_ADDR 0x141f
+#define L_CPV1_HE_ADDR 0x1420
+#define L_CPV1_VS_ADDR 0x1421
+#define L_CPV1_VE_ADDR 0x1422
+#define L_CPV2_HS_ADDR 0x1423
+#define L_CPV2_HE_ADDR 0x1424
+#define L_CPV2_VS_ADDR 0x1425
+#define L_CPV2_VE_ADDR 0x1426
+#define L_STV1_HS_ADDR 0x1427
+#define L_STV1_HE_ADDR 0x1428
+#define L_STV1_VS_ADDR 0x1429
+#define L_STV1_VE_ADDR 0x142a
+#define L_STV2_HS_ADDR 0x142b
+#define L_STV2_HE_ADDR 0x142c
+#define L_STV2_VS_ADDR 0x142d
+#define L_STV2_VE_ADDR 0x142e
+#define L_OEV1_HS_ADDR 0x142f
+#define L_OEV1_HE_ADDR 0x1430
+#define L_OEV1_VS_ADDR 0x1431
+#define L_OEV1_VE_ADDR 0x1432
+#define L_OEV2_HS_ADDR 0x1433
+#define L_OEV2_HE_ADDR 0x1434
+#define L_OEV2_VS_ADDR 0x1435
+#define L_OEV2_VE_ADDR 0x1436
+#define L_OEV3_HS_ADDR 0x1437
+#define L_OEV3_HE_ADDR 0x1438
+#define L_OEV3_VS_ADDR 0x1439
+#define L_OEV3_VE_ADDR 0x143a
+#define L_LCD_PWR_ADDR 0x143b
+#define L_LCD_PWM0_LO_ADDR 0x143c
+#define L_LCD_PWM0_HI_ADDR 0x143d
+#define L_LCD_PWM1_LO_ADDR 0x143e
+#define L_LCD_PWM1_HI_ADDR 0x143f
+#define L_INV_CNT_ADDR 0x1440
+#define L_TCON_MISC_SEL_ADDR 0x1441
+#define L_DUAL_PORT_CNTL_ADDR 0x1442
+#define MLVDS_CLK_CTL1_HI 0x1443
+#define MLVDS_CLK_CTL1_LO 0x1444
+#define L_TCON_DOUBLE_CTL 0x1449
+#define L_TCON_PATTERN_HI 0x144a
+#define L_TCON_PATTERN_LO 0x144b
+#define LDIM_BL_ADDR_PORT 0x144e
+#define LDIM_BL_DATA_PORT 0x144f
+#define L_DE_HS_ADDR 0x1451
+#define L_DE_HE_ADDR 0x1452
+#define L_DE_VS_ADDR 0x1453
+#define L_DE_VE_ADDR 0x1454
+#define L_HSYNC_HS_ADDR 0x1455
+#define L_HSYNC_HE_ADDR 0x1456
+#define L_HSYNC_VS_ADDR 0x1457
+#define L_HSYNC_VE_ADDR 0x1458
+#define L_VSYNC_HS_ADDR 0x1459
+#define L_VSYNC_HE_ADDR 0x145a
+#define L_VSYNC_VS_ADDR 0x145b
+#define L_VSYNC_VE_ADDR 0x145c
+#define L_LCD_MCU_CTL 0x145d
+#define DUAL_MLVDS_CTL 0x1460
+#define DUAL_MLVDS_LINE_START 0x1461
+#define DUAL_MLVDS_LINE_END 0x1462
+#define DUAL_MLVDS_PIXEL_W_START_L 0x1463
+#define DUAL_MLVDS_PIXEL_W_END_L 0x1464
+#define DUAL_MLVDS_PIXEL_W_START_R 0x1465
+#define DUAL_MLVDS_PIXEL_W_END_R 0x1466
+#define DUAL_MLVDS_PIXEL_R_START_L 0x1467
+#define DUAL_MLVDS_PIXEL_R_CNT_L 0x1468
+#define DUAL_MLVDS_PIXEL_R_START_R 0x1469
+#define DUAL_MLVDS_PIXEL_R_CNT_R 0x146a
+#define V_INVERSION_PIXEL 0x1470
+#define V_INVERSION_LINE 0x1471
+#define V_INVERSION_CONTROL 0x1472
+#define MLVDS2_CONTROL 0x1474
+#define MLVDS2_CONFIG_HI 0x1475
+#define MLVDS2_CONFIG_LO 0x1476
+#define MLVDS2_DUAL_GATE_WR_START 0x1477
+#define MLVDS2_DUAL_GATE_WR_END 0x1478
+#define MLVDS2_DUAL_GATE_RD_START 0x1479
+#define MLVDS2_DUAL_GATE_RD_END 0x147a
+#define MLVDS2_SECOND_RESET_CTL 0x147b
+#define MLVDS2_DUAL_GATE_CTL_HI 0x147c
+#define MLVDS2_DUAL_GATE_CTL_LO 0x147d
+#define MLVDS2_RESET_CONFIG_HI 0x147e
+#define MLVDS2_RESET_CONFIG_LO 0x147f
+#define GAMMA_CNTL_PORT 0x1480
+#define GAMMA_DATA_PORT 0x1481
+#define GAMMA_ADDR_PORT 0x1482
+#define GAMMA_VCOM_HSWITCH_ADDR 0x1483
+#define RGB_BASE_ADDR 0x1485
+#define RGB_COEFF_ADDR 0x1486
+#define POL_CNTL_ADDR 0x1487
+#define DITH_CNTL_ADDR 0x1488
+#define GAMMA_PROBE_CTRL 0x1489
+#define GAMMA_PROBE_COLOR_L 0x148a
+#define GAMMA_PROBE_COLOR_H 0x148b
+#define GAMMA_PROBE_HL_COLOR 0x148c
+#define GAMMA_PROBE_POS_X 0x148d
+#define GAMMA_PROBE_POS_Y 0x148e
+#define STH1_HS_ADDR 0x1490
+#define STH1_HE_ADDR 0x1491
+#define STH1_VS_ADDR 0x1492
+#define STH1_VE_ADDR 0x1493
+#define STH2_HS_ADDR 0x1494
+#define STH2_HE_ADDR 0x1495
+#define STH2_VS_ADDR 0x1496
+#define STH2_VE_ADDR 0x1497
+#define OEH_HS_ADDR 0x1498
+#define OEH_HE_ADDR 0x1499
+#define OEH_VS_ADDR 0x149a
+#define OEH_VE_ADDR 0x149b
+#define VCOM_HSWITCH_ADDR 0x149c
+#define VCOM_VS_ADDR 0x149d
+#define VCOM_VE_ADDR 0x149e
+#define CPV1_HS_ADDR 0x149f
+#define CPV1_HE_ADDR 0x14a0
+#define CPV1_VS_ADDR 0x14a1
+#define CPV1_VE_ADDR 0x14a2
+#define CPV2_HS_ADDR 0x14a3
+#define CPV2_HE_ADDR 0x14a4
+#define CPV2_VS_ADDR 0x14a5
+#define CPV2_VE_ADDR 0x14a6
+#define STV1_HS_ADDR 0x14a7
+#define STV1_HE_ADDR 0x14a8
+#define STV1_VS_ADDR 0x14a9
+#define STV1_VE_ADDR 0x14aa
+#define STV2_HS_ADDR 0x14ab
+#define STV2_HE_ADDR 0x14ac
+#define STV2_VS_ADDR 0x14ad
+#define STV2_VE_ADDR 0x14ae
+#define OEV1_HS_ADDR 0x14af
+#define OEV1_HE_ADDR 0x14b0
+#define OEV1_VS_ADDR 0x14b1
+#define OEV1_VE_ADDR 0x14b2
+#define OEV2_HS_ADDR 0x14b3
+#define OEV2_HE_ADDR 0x14b4
+#define OEV2_VS_ADDR 0x14b5
+#define OEV2_VE_ADDR 0x14b6
+#define OEV3_HS_ADDR 0x14b7
+#define OEV3_HE_ADDR 0x14b8
+#define OEV3_VS_ADDR 0x14b9
+#define OEV3_VE_ADDR 0x14ba
+#define LCD_PWR_ADDR 0x14bb
+#define LCD_PWM0_LO_ADDR 0x14bc
+#define LCD_PWM0_HI_ADDR 0x14bd
+#define LCD_PWM1_LO_ADDR 0x14be
+#define LCD_PWM1_HI_ADDR 0x14bf
+#define INV_CNT_ADDR 0x14c0
+#define TCON_MISC_SEL_ADDR 0x14c1
+#define DUAL_PORT_CNTL_ADDR 0x14c2
+#define MLVDS_CONTROL 0x14c3
+#define MLVDS_RESET_PATTERN_HI 0x14c4
+#define MLVDS_RESET_PATTERN_LO 0x14c5
+#define MLVDS_RESET_PATTERN_EXT 0x14c6
+#define MLVDS_CONFIG_HI 0x14c7
+#define MLVDS_CONFIG_LO 0x14c8
+#define TCON_DOUBLE_CTL 0x14c9
+#define TCON_PATTERN_HI 0x14ca
+#define TCON_PATTERN_LO 0x14cb
+#define TCON_CONTROL_HI 0x14cc
+#define TCON_CONTROL_LO 0x14cd
+#define LVDS_BLANK_DATA_HI 0x14ce
+#define LVDS_BLANK_DATA_LO 0x14cf
+#define LVDS_PACK_CNTL_ADDR 0x14d0
+#define DE_HS_ADDR 0x14d1
+#define DE_HE_ADDR 0x14d2
+#define DE_VS_ADDR 0x14d3
+#define DE_VE_ADDR 0x14d4
+#define HSYNC_HS_ADDR 0x14d5
+#define HSYNC_HE_ADDR 0x14d6
+#define HSYNC_VS_ADDR 0x14d7
+#define HSYNC_VE_ADDR 0x14d8
+#define VSYNC_HS_ADDR 0x14d9
+#define VSYNC_HE_ADDR 0x14da
+#define VSYNC_VS_ADDR 0x14db
+#define VSYNC_VE_ADDR 0x14dc
+#define LCD_MCU_CTL 0x14dd
+#define LCD_MCU_DATA_0 0x14de
+#define LCD_MCU_DATA_1 0x14df
+#define LVDS_GEN_CNTL 0x14e0
+#define LVDS_PHY_CNTL0 0x14e1
+#define LVDS_PHY_CNTL1 0x14e2
+#define LVDS_PHY_CNTL2 0x14e3
+#define LVDS_PHY_CNTL3 0x14e4
+#define LVDS_PHY_CNTL4 0x14e5
+#define LVDS_PHY_CNTL5 0x14e6
+#define LVDS_SRG_TEST 0x14e8
+#define LVDS_BIST_MUX0 0x14e9
+#define LVDS_BIST_MUX1 0x14ea
+#define LVDS_BIST_FIXED0 0x14eb
+#define LVDS_BIST_FIXED1 0x14ec
+#define LVDS_BIST_CNTL0 0x14ed
+#define LVDS_CLKB_CLKA 0x14ee
+#define LVDS_PHY_CLK_CNTL 0x14ef
+#define LVDS_SER_EN 0x14f0
+#define LVDS_PHY_CNTL6 0x14f1
+#define LVDS_PHY_CNTL7 0x14f2
+#define LVDS_PHY_CNTL8 0x14f3
+#define MLVDS_CLK_CTL0_HI 0x14f4
+#define MLVDS_CLK_CTL0_LO 0x14f5
+#define MLVDS_DUAL_GATE_WR_START 0x14f6
+#define MLVDS_DUAL_GATE_WR_END 0x14f7
+#define MLVDS_DUAL_GATE_RD_START 0x14f8
+#define MLVDS_DUAL_GATE_RD_END 0x14f9
+#define MLVDS_SECOND_RESET_CTL 0x14fa
+#define MLVDS_DUAL_GATE_CTL_HI 0x14fb
+#define MLVDS_DUAL_GATE_CTL_LO 0x14fc
+#define MLVDS_RESET_CONFIG_HI 0x14fd
+#define MLVDS_RESET_CONFIG_LO 0x14fe
+#define VPU_OSD1_MMC_CTRL 0x2701
+#define VPU_OSD2_MMC_CTRL 0x2702
+#define VPU_VD1_MMC_CTRL 0x2703
+#define VPU_VD2_MMC_CTRL 0x2704
+#define VPU_DI_IF1_MMC_CTRL 0x2705
+#define VPU_DI_MEM_MMC_CTRL 0x2706
+#define VPU_DI_INP_MMC_CTRL 0x2707
+#define VPU_DI_MTNRD_MMC_CTRL 0x2708
+#define VPU_DI_CHAN2_MMC_CTRL 0x2709
+#define VPU_DI_MTNWR_MMC_CTRL 0x270a
+#define VPU_DI_NRWR_MMC_CTRL 0x270b
+#define VPU_DI_DIWR_MMC_CTRL 0x270c
+#define VPU_VDIN0_MMC_CTRL 0x270d
+#define VPU_VDIN1_MMC_CTRL 0x270e
+#define VPU_BT656_MMC_CTRL 0x270f
+#define VPU_TVD3D_MMC_CTRL 0x2710
+#define VPU_TVDVBI_MMC_CTRL 0x2711
+#define VPU_TVDVBI_VSLATCH_ADDR 0x2712
+#define VPU_TVDVBI_WRRSP_ADDR 0x2713
+#define VPU_VDIN_PRE_ARB_CTRL 0x2714
+#define VPU_VDISP_PRE_ARB_CTRL 0x2715
+#define VPU_VPUARB2_PRE_ARB_CTRL 0x2716
+#define VPU_OSD3_MMC_CTRL 0x2717
+#define VPU_OSD4_MMC_CTRL 0x2718
+#define VPU_VD3_MMC_CTRL 0x2719
+#define VPU_VIU_VENC_MUX_CTRL 0x271a
+#define VPU_HDMI_SETTING 0x271b
+#define ENCI_INFO_READ 0x271c
+#define ENCP_INFO_READ 0x271d
+#define ENCT_INFO_READ 0x271e
+#define ENCL_INFO_READ 0x271f
+#define VPU_SW_RESET 0x2720
+#define VPU_D2D3_MMC_CTRL 0x2721
+#define VPU_CONT_MMC_CTRL 0x2722
+#define VPU_CLK_GATE 0x2723
+#define VPU_RDMA_MMC_CTRL 0x2724
+#define VPU_MEM_PD_REG0 0x2725
+#define VPU_MEM_PD_REG1 0x2726
+#define VPU_HDMI_DATA_OVR 0x2727
+#define VPU_PROT1_MMC_CTRL 0x2728
+#define VPU_PROT2_MMC_CTRL 0x2729
+#define VPU_PROT3_MMC_CTRL 0x272a
+#define VPU_ARB4_V1_MMC_CTRL 0x272b
+#define VPU_ARB4_V2_MMC_CTRL 0x272c
+#define VPU_VPU_PWM_V0 0x2730
+#define VPU_VPU_PWM_V1 0x2731
+#define VPU_VPU_PWM_V2 0x2732
+#define VPU_VPU_PWM_V3 0x2733
+#define VPU_VPU_PWM_H0 0x2734
+#define VPU_VPU_PWM_H1 0x2735
+#define VPU_VPU_PWM_H2 0x2736
+#define VPU_VPU_PWM_H3 0x2737
+#define VPU_MISC_CTRL 0x2740
+#define VPU_ISP_GCLK_CTRL0 0x2741
+#define VPU_ISP_GCLK_CTRL1 0x2742
+#define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743
+#define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744
+#define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745
+
+#define VPU_PROT1_CLK_GATE 0x2750
+#define VPU_PROT1_GEN_CNTL 0x2751
+#define VPU_PROT1_X_START_END 0x2752
+#define VPU_PROT1_Y_START_END 0x2753
+#define VPU_PROT1_Y_LEN_STEP 0x2754
+#define VPU_PROT1_RPT_LOOP 0x2755
+#define VPU_PROT1_RPT_PAT 0x2756
+#define VPU_PROT1_DDR 0x2757
+#define VPU_PROT1_RBUF_ROOM 0x2758
+#define VPU_PROT1_STAT_0 0x2759
+#define VPU_PROT1_STAT_1 0x275a
+#define VPU_PROT1_STAT_2 0x275b
+#define VPU_PROT1_REQ_ONOFF 0x275c
+#define VPU_PROT2_CLK_GATE 0x2760
+#define VPU_PROT2_GEN_CNTL 0x2761
+#define VPU_PROT2_X_START_END 0x2762
+#define VPU_PROT2_Y_START_END 0x2763
+#define VPU_PROT2_Y_LEN_STEP 0x2764
+#define VPU_PROT2_RPT_LOOP 0x2765
+#define VPU_PROT2_RPT_PAT 0x2766
+#define VPU_PROT2_DDR 0x2767
+#define VPU_PROT2_RBUF_ROOM 0x2768
+#define VPU_PROT2_STAT_0 0x2769
+#define VPU_PROT2_STAT_1 0x276a
+#define VPU_PROT2_STAT_2 0x276b
+#define VPU_PROT2_REQ_ONOFF 0x276c
+#define VPU_PROT3_CLK_GATE 0x2770
+#define VPU_PROT3_GEN_CNTL 0x2771
+#define VPU_PROT3_X_START_END 0x2772
+#define VPU_PROT3_Y_START_END 0x2773
+#define VPU_PROT3_Y_LEN_STEP 0x2774
+#define VPU_PROT3_RPT_LOOP 0x2775
+#define VPU_PROT3_RPT_PAT 0x2776
+#define VPU_PROT3_DDR 0x2777
+#define VPU_PROT3_RBUF_ROOM 0x2778
+#define VPU_PROT3_STAT_0 0x2779
+#define VPU_PROT3_STAT_1 0x277a
+#define VPU_PROT3_STAT_2 0x277b
+#define VPU_PROT3_REQ_ONOFF 0x277c
+#define VPU_RDARB_MODE_L1C2 0x2799
+
+/* osd afbcd on gxtvbb */
+#define OSD1_AFBCD_ENABLE 0x31a0
+#define OSD1_AFBCD_MODE 0x31a1
+#define OSD1_AFBCD_SIZE_IN 0x31a2
+#define OSD1_AFBCD_HDR_PTR 0x31a3
+#define OSD1_AFBCD_FRAME_PTR 0x31a4
+#define OSD1_AFBCD_CHROMA_PTR 0x31a5
+#define OSD1_AFBCD_CONV_CTRL 0x31a6
+#define OSD1_AFBCD_STATUS 0x31a8
+#define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9
+#define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa
+#define VIU_MISC_CTRL1 0x1a07
+
+
+/* add for gxm and 962e dv core2 */
+#define DOLBY_CORE2A_SWAP_CTRL1 0x3434
+#define DOLBY_CORE2A_SWAP_CTRL2 0x3435
+
+/* osd afbc on g12a */
+#define VPU_MAFBC_BLOCK_ID 0x3a00
+#define VPU_MAFBC_IRQ_RAW_STATUS 0x3a01
+#define VPU_MAFBC_IRQ_CLEAR 0x3a02
+#define VPU_MAFBC_IRQ_MASK 0x3a03
+#define VPU_MAFBC_IRQ_STATUS 0x3a04
+#define VPU_MAFBC_COMMAND 0x3a05
+#define VPU_MAFBC_STATUS 0x3a06
+#define VPU_MAFBC_SURFACE_CFG 0x3a07
+
+/* osd afbc on g12a */
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11
+#define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12
+#define VPU_MAFBC_BUFFER_WIDTH_S0 0x3a13
+#define VPU_MAFBC_BUFFER_HEIGHT_S0 0x3a14
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S0 0x3a15
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S0 0x3a16
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S0 0x3a17
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S0 0x3a18
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0 0x3a19
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0 0x3a1a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S0 0x3a1b
+#define VPU_MAFBC_PREFETCH_CFG_S0 0x3a1c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1 0x3a30
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1 0x3a31
+#define VPU_MAFBC_FORMAT_SPECIFIER_S1 0x3a32
+#define VPU_MAFBC_BUFFER_WIDTH_S1 0x3a33
+#define VPU_MAFBC_BUFFER_HEIGHT_S1 0x3a34
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S1 0x3a35
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S1 0x3a36
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S1 0x3a37
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S1 0x3a38
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1 0x3a39
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1 0x3a3a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S1 0x3a3b
+#define VPU_MAFBC_PREFETCH_CFG_S1 0x3a3c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2 0x3a50
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2 0x3a51
+#define VPU_MAFBC_FORMAT_SPECIFIER_S2 0x3a52
+#define VPU_MAFBC_BUFFER_WIDTH_S2 0x3a53
+#define VPU_MAFBC_BUFFER_HEIGHT_S2 0x3a54
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S2 0x3a55
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S2 0x3a56
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S2 0x3a57
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S2 0x3a58
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2 0x3a59
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2 0x3a5a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S2 0x3a5b
+#define VPU_MAFBC_PREFETCH_CFG_S2 0x3a5c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S3 0x3a70
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S3 0x3a71
+#define VPU_MAFBC_FORMAT_SPECIFIER_S3 0x3a72
+#define VPU_MAFBC_BUFFER_WIDTH_S3 0x3a73
+#define VPU_MAFBC_BUFFER_HEIGHT_S3 0x3a74
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S3 0x3a75
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S3 0x3a76
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S3 0x3a77
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S3 0x3a78
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S3 0x3a79
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S3 0x3a7a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S3 0x3a7b
+#define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c
+
+#define DOLBY_PATH_CTRL 0x1a0c
+#define OSD_PATH_MISC_CTRL 0x1a0e
+#define MALI_AFBCD_TOP_CTRL 0x1a0f
+
+#define VPP_OUT_H_V_SIZE 0x1da5
+
+#define VPP_VD2_HDR_IN_SIZE 0x1df0
+#define VPP_GCLK_CTRL2 0x1df2
+#define VD2_PPS_DUMMY_DATA 0x1df4
+#define VPP_WRBAK_CTRL 0x1df9
+#define VPP_SLEEP_CTRL 0x1dfa
+
+#define VPP_RDARB_MODE 0x3978
+#define VPP_RDARB_REQEN_SLV 0x3979
+#define VPU_RDARB_MODE_L2C1 0x279d
+
+/*VIU2 osd1 reg*/
+#define VIU2_OSD1_MATRIX_COEF00_01 0x1e70
+#define VIU2_OSD1_MATRIX_COEF02_10 0x1e71
+#define VIU2_OSD1_MATRIX_COEF11_12 0x1e72
+#define VIU2_OSD1_MATRIX_COEF20_21 0x1e73
+#define VIU2_OSD1_MATRIX_COEF22 0x1e74
+#define VIU2_OSD1_MATRIX_COEF13_14 0x1e75
+#define VIU2_OSD1_MATRIX_COEF23_24 0x1e76
+#define VIU2_OSD1_MATRIX_COEF15_25 0x1e77
+#define VIU2_OSD1_MATRIX_CLIP 0x1e78
+#define VIU2_OSD1_MATRIX_OFFSET0_1 0x1e79
+#define VIU2_OSD1_MATRIX_OFFSET2 0x1e7a
+#define VIU2_OSD1_MATRIX_PRE_OFFSET0_1 0x1e7b
+#define VIU2_OSD1_MATRIX_PRE_OFFSET2 0x1e7c
+#define VIU2_OSD1_MATRIX_EN_CTRL 0x1e7d
+
+/* reg definition */
+
+struct afbc_osd1_reg {
+ u32 vpu_mafbc_header_buf_addr_low_s0;
+ u32 vpu_mafbc_header_buf_addr_high_s0;
+ u32 vpu_mafbc_format_specifier_s0;
+ u32 vpu_mafbc_buffer_width_s0;
+ u32 vpu_mafbc_buffer_height_s0;
+ u32 vpu_mafbc_bounding_box_x_start_s0;
+ u32 vpu_mafbc_bounding_box_x_end_s0;
+ u32 vpu_mafbc_bounding_box_y_start_s0;
+ u32 vpu_mafbc_bounding_box_y_end_s0;
+ u32 vpu_mafbc_output_buf_addr_low_s0;
+ u32 vpu_mafbc_output_buf_addr_high_s0;
+ u32 vpu_mafbc_output_buf_stride_s0;
+ u32 vpu_mafbc_prefetch_cfg_s0;
+ u32 vpu_mafbc_payload_min_low_s0;
+ u32 vpu_mafbc_payload_min_high_s0;
+ u32 vpu_mafbc_payload_max_low_s0;
+ u32 vpu_mafbc_payload_max_high_s0;
+};
+
+struct afbc_osd2_reg {
+ u32 vpu_mafbc_header_buf_addr_low_s1;
+ u32 vpu_mafbc_header_buf_addr_high_s1;
+ u32 vpu_mafbc_format_specifier_s1;
+ u32 vpu_mafbc_buffer_width_s1;
+ u32 vpu_mafbc_buffer_height_s1;
+ u32 vpu_mafbc_bounding_box_x_start_s1;
+ u32 vpu_mafbc_bounding_box_x_end_s1;
+ u32 vpu_mafbc_bounding_box_y_start_s1;
+ u32 vpu_mafbc_bounding_box_y_end_s1;
+ u32 vpu_mafbc_output_buf_addr_low_s1;
+ u32 vpu_mafbc_output_buf_addr_high_s1;
+ u32 vpu_mafbc_output_buf_stride_s1;
+ u32 vpu_mafbc_prefetch_cfg_s1;
+ u32 vpu_mafbc_payload_min_low_s1;
+ u32 vpu_mafbc_payload_min_high_s1;
+ u32 vpu_mafbc_payload_max_low_s1;
+ u32 vpu_mafbc_payload_max_high_s1;
+};
+
+struct afbc_osd3_reg {
+ u32 vpu_mafbc_header_buf_addr_low_s2;
+ u32 vpu_mafbc_header_buf_addr_high_s2;
+ u32 vpu_mafbc_format_specifier_s2;
+ u32 vpu_mafbc_buffer_width_s2;
+ u32 vpu_mafbc_buffer_height_s2;
+ u32 vpu_mafbc_bounding_box_x_start_s2;
+ u32 vpu_mafbc_bounding_box_x_end_s2;
+ u32 vpu_mafbc_bounding_box_y_start_s2;
+ u32 vpu_mafbc_bounding_box_y_end_s2;
+ u32 vpu_mafbc_output_buf_addr_low_s2;
+ u32 vpu_mafbc_output_buf_addr_high_s2;
+ u32 vpu_mafbc_output_buf_stride_s2;
+ u32 vpu_mafbc_prefetch_cfg_s2;
+ u32 vpu_mafbc_payload_min_low_s2;
+ u32 vpu_mafbc_payload_min_high_s2;
+ u32 vpu_mafbc_payload_max_low_s2;
+ u32 vpu_mafbc_payload_max_high_s2;
+};
+
+struct afbc_status_reg {
+ u32 vpu_mafbc_block_id;
+ u32 vpu_mafbc_irq_raw_status;
+ u32 vpu_mafbc_irq_clear;
+ u32 vpu_mafbc_irq_mask;
+ u32 vpu_mafbc_irq_status;
+ u32 vpu_mafbc_command;
+ u32 vpu_mafbc_status;
+ u32 vpu_mafbc_surface_cfg;
+};
+
+union afbc_osd_reg {
+ struct afbc_osd1_reg afbc_osd1;
+ struct afbc_osd2_reg afbc_osd2;
+ struct afbc_osd3_reg afbc_osd3;
+};
+
+#endif
--- /dev/null
+#ifndef _MESON_DRM_IDS_H_
+#define _MESON_DRM_IDS_H_
+
+#define OSD1_BLOCK 0
+#define OSD2_BLOCK 1
+#define OSD3_BLOCK 2
+#define AFBC_OSD1_BLOCK 3
+#define AFBC_OSD2_BLOCK 4
+#define AFBC_OSD3_BLOCK 5
+#define SCALER_OSD1_BLOCK 6
+#define SCALER_OSD2_BLOCK 7
+#define SCALER_OSD3_BLOCK 8
+#define OSD_BLEND_BLOCK 9
+#define OSD1_HDR_BLOCK 10
+#define VPP_POSTBLEND_BLOCK 11
+
+#define OSD1_PORT 0
+#define OSD2_PORT 1
+#define OSD3_PORT 2
+#define AFBC_OSD1_PORT 3
+#define AFBC_OSD2_PORT 4
+#define AFBC_OSD3_PORT 5
+#define SCALER_OSD1_PORT 6
+#define SCALER_OSD2_PORT 7
+#define SCALER_OSD3_PORT 8
+#define OSDBLEND_DIN1_PORT 9
+#define OSDBLEND_DIN2_PORT 10
+#define OSDBLEND_DIN3_PORT 11
+#define OSDBLEND_DOUT1_PORT 12
+#define OSDBLEND_DOUT2_PORT 13
+#define OSD1_HDR_PORT 14
+#define OSD1_DOLBY_PORT 15
+#define VPP_POSTBLEND_OSD1_IN_PORT 16
+#define VPP_POSTBLEND_OSD2_IN_PORT 17
+#define VPP_POSTBLEND_OUT_PORT 18
+
+/*
+ *OSD VERSION
+ *V1:G12A
+ *V2:G12B-revA:base G12A,add repeate last line function
+ *V3:G12B-RevB:add line interrupt support
+ *V4:TL1:base G12A,fix shift issue,delete osd3
+ *V5:SM1:base G12A,fix shift issue
+ *V6:TM2,base G12A,fix shift issue,add mux for osd1-sr
+ */
+#define OSD_V1 1
+#define OSD_V2 2
+#define OSD_V3 3
+#define OSD_V4 4
+#define OSD_V5 5
+#define OSD_V6 6
+
+#endif
+++ /dev/null
-/*
- * include/uapi/drm/meson_drm.h
- *
- * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef _MESON_DRM_H
-#define _MESON_DRM_H
-
-#include <drm/drm.h>
-
-/* memory type definitions. */
-enum drm_meson_gem_mem_type {
- /* Physically Continuous memory. */
- MESON_BO_CONTIG = 1 << 0,
- /* cachable mapping. */
- MESON_BO_CACHABLE = 1 << 1,
- /* write-combine mapping. */
- MESON_BO_WC = 1 << 2,
- MESON_BO_SECURE = 1 << 3,
- MESON_BO_MASK = MESON_BO_CONTIG | MESON_BO_CACHABLE |
- MESON_BO_WC
-};
-
-/* Use flags */
-#define BO_USE_NONE 0
-#define BO_USE_SCANOUT (1ull << 0)
-#define BO_USE_CURSOR (1ull << 1)
-#define BO_USE_CURSOR_64X64 BO_USE_CURSOR
-#define BO_USE_RENDERING (1ull << 2)
-#define BO_USE_LINEAR (1ull << 3)
-#define BO_USE_SW_READ_NEVER (1ull << 4)
-#define BO_USE_SW_READ_RARELY (1ull << 5)
-#define BO_USE_SW_READ_OFTEN (1ull << 6)
-#define BO_USE_SW_WRITE_NEVER (1ull << 7)
-#define BO_USE_SW_WRITE_RARELY (1ull << 8)
-#define BO_USE_SW_WRITE_OFTEN (1ull << 9)
-#define BO_USE_EXTERNAL_DISP (1ull << 10)
-#define BO_USE_PROTECTED (1ull << 11)
-#define BO_USE_HW_VIDEO_ENCODER (1ull << 12)
-#define BO_USE_CAMERA_WRITE (1ull << 13)
-#define BO_USE_CAMERA_READ (1ull << 14)
-#define BO_USE_RENDERSCRIPT (1ull << 16)
-#define BO_USE_TEXTURE (1ull << 17)
-
-
-/**
- * User-desired buffer creation information structure.
- *
- * @size: user-desired memory allocation size.
- * @flags: user request for setting memory type or cache attributes.
- * @handle: returned a handle to created gem object.
- * - this handle will be set by gem module of kernel side.
- */
-struct drm_meson_gem_create {
- uint64_t size;
- uint32_t flags;
- uint32_t handle;
-};
-
-#define DRM_MESON_GEM_CREATE 0x00
-
-#define DRM_IOCTL_MESON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
- DRM_MESON_GEM_CREATE, struct drm_meson_gem_create)
-
-#endif /* _MESON_DRM_H */
-
#define DRM_FORMAT_MOD_VENDOR_NV 0x03
#define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04
#define DRM_FORMAT_MOD_VENDOR_QCOM 0x05
+#define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x09
/* add more to the end as needed */
#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
*/
#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
+#define DRM_FORMAT_MOD_MESON_AFBC fourcc_mod_code(AMLOGIC, 1)
+#define DRM_FORMAT_MOD_MESON_AFBC_WB fourcc_mod_code(AMLOGIC, 2)
+
#if defined(__cplusplus)
}
#endif
--- /dev/null
+/*
+ * include/uapi/drm/meson_drm.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _MESON_DRM_H
+#define _MESON_DRM_H
+
+#include <drm/drm.h>
+
+/* Use flags */
+#define MESON_USE_NONE 0
+#define MESON_USE_SCANOUT (1ull << 0)
+#define MESON_USE_CURSOR (1ull << 1)
+#define MESON_USE_RENDERING (1ull << 2)
+#define MESON_USE_LINEAR (1ull << 3)
+#define MESON_USE_PROTECTED (1ull << 11)
+#define MESON_USE_HW_VIDEO_ENCODER (1ull << 12)
+#define MESON_USE_CAMERA_WRITE (1ull << 13)
+#define MESON_USE_CAMERA_READ (1ull << 14)
+#define MESON_USE_TEXTURE (1ull << 17)
+
+
+/**
+ * User-desired buffer creation information structure.
+ *
+ * @size: user-desired memory allocation size.
+ * @flags: user request for setting memory type or cache attributes.
+ * @handle: returned a handle to created gem object.
+ * - this handle will be set by gem module of kernel side.
+ */
+struct drm_meson_gem_create {
+ __u64 size;
+ __u32 flags;
+ __u32 handle;
+};
+
+#define DRM_MESON_GEM_CREATE 0x00
+
+#define DRM_IOCTL_MESON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_MESON_GEM_CREATE, struct drm_meson_gem_create)
+
+#endif /* _MESON_DRM_H */