author | Dezhi Kong <dezhi.kong@amlogic.com> | 2019-06-11 12:29:40 (GMT) |
---|---|---|
committer | Dezhi Kong <dezhi.kong@amlogic.com> | 2019-07-11 02:10:57 (GMT) |
commit | 1f1efcfdd85da5a5948432c21e9a2295e65905f5 (patch) | |
tree | bfa210afd6f010ae0845c2536a7da59c2b630e02 | |
parent | 069f36f89710c343e46f7160cf6e8069c8412111 (diff) | |
download | common-1f1efcfdd85da5a5948432c21e9a2295e65905f5.zip common-1f1efcfdd85da5a5948432c21e9a2295e65905f5.tar.gz common-1f1efcfdd85da5a5948432c21e9a2295e65905f5.tar.bz2 |
drm: add multi-layer support [1/1]
PD#SWPL-9646
Problem:
unsupport multi-layer
Solution:
add multi-layer support
Verify:
verify by w400 with modetest command
Change-Id: I5cd50761d2ab9cfff0f80d38e20455044c7a33fd
Signed-off-by: Dezhi Kong <dezhi.kong@amlogic.com>
77 files changed, 12117 insertions, 325 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 0f36a16..5f1d410 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15046,3 +15046,31 @@ M: Cheng Wang <cheng.wang@amlogic.com> F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h +AMLOGIC DRM +M: Ao Xu <ao.xu@amlogic.com> +M: Dezhi Kong <dezhi.kong@amlogic.com> +F: include/linux/meson_ion.h +F: include/uapi/drm/meson_drm.h +F: include/uapi/drm/drm_fourcc.c +F: drivers/gpu/Makefile +F: drivers/amlogic/Kconfig +F: drivers/amlogic/Makefile +F: drivers/amlogic/drm/* +F: drivers/staging/android/ion/ion.h +F: drivers/staging/android/ion/ion_cma_heap.c +F: drivers/amlogic/media/osd/osd_fb.c +F: drivers/amlogic/media/common/ion_dev/dev_ion.c +F: drivers/amlogic/media/common/ion_dev/dev_ion.h +F: arch/arm/boot/dts/amlogic/meson-g12a-u200.dts +F: arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi +F: arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts +F: arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts +F: arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts +F: arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi +F: arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts +F: arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts +F: arch/arm/configs/meson64_a32_defconfig +F: arch/arm64/configs/meson64_a64_defconfig +F: arch/arm/boot/dts/amlogic/Makefile +F: arch/arm64/boot/dts/amlogic/Makefile + diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index 7b40c1c..c816c8f 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -819,6 +819,7 @@ &drm_vpu { status = "okay"; logo_addr = "0x7f800000"; + osd_ver = /bits/ 8 <OSD_V1>; }; &drm_amhdmitx { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts index 320f0aa..d9a3ed0 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -19,7 +19,7 @@ #include "mesong12b.dtsi" #include "mesong12b_skt-panel.dtsi" -#include "mesong12a_drm.dtsi" +#include "mesong12b_drm.dtsi" / { model = "Amlogic"; @@ -1515,6 +1515,7 @@ status = "okay"; compatible = "amlogic,meson-g12b-vpu"; logo_addr = "0x7f800000"; + osd_ver = /bits/ 8 <OSD_V3>; }; &drm_amhdmitx { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts index f21d6de..e889c247 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts @@ -1481,6 +1481,7 @@ status = "okay"; compatible = "amlogic,meson-g12b-vpu"; logo_addr = "0x7f800000"; + osd_ver = /bits/ 8 <OSD_V2>; }; &drm_amhdmitx { diff --git a/arch/arm/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts new file mode 100644 index 0000000..3e069bc --- a/dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts @@ -0,0 +1,1469 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" +#include "mesong12b_drm.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x1f000000>; + alignment = <0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x03000000>; + alignment = <0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶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"; +}; diff --git a/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi b/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi index 00beafa..ceb5725 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi @@ -14,11 +14,12 @@ * more details. * */ +#include <dt-bindings/display/meson-drm-ids.h> / { venc-cvbs { status = "okay"; - compatible = "amlogic,meson-gxbb-cvbs"; + compatible = "amlogic, meson-g12a-cvbs"; ports { #address-cells = <1>; @@ -104,6 +105,138 @@ status = "okay"; compatible = "amlogic,drm-subsystem"; ports = <&vpu_out>; + + vpu_topology: vpu_topology { + vpu_blocks { + osd1_block: block@0 { + id = /bits/ 8 <OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <0>; + block_name = "osd1_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd1_block>; + }; + osd2_block: block@1 { + id = /bits/ 8 <OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <0>; + block_name = "osd2_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd2_block>; + }; + osd3_block: block@2 { + id = /bits/ 8 <OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <0>; + block_name = "osd3_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd3_block>; + }; + afbc_osd1_block: block@3 { + id = /bits/ 8 <AFBC_OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <1>; + block_name = "afbc_osd1_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd1_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &osd_blend_block>; + }; + afbc_osd2_block: block@4 { + id = /bits/ 8 <AFBC_OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <1>; + block_name = "afbc_osd2_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd2_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd2_block>; + }; + afbc_osd3_block: block@5 { + id = /bits/ 8 <AFBC_OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <1>; + block_name = "afbc_osd3_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd3_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd3_block>; + }; + scaler_osd1_block: block@6 { + id = /bits/ 8 <SCALER_OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <2>; + block_name = "scaler_osd1_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd1_hdr_dolby_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &vpp_postblend_block>; + }; + scaler_osd2_block: block@7 { + id = /bits/ 8 <SCALER_OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <2>; + block_name = "scaler_osd2_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &afbc_osd2_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <2 &osd_blend_block>; + }; + scaler_osd3_block: block@8 { + id = /bits/ 8 <SCALER_OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <2>; + block_name = "scaler_osd3_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &afbc_osd3_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <3 &osd_blend_block>; + }; + osd_blend_block: block@9 { + id = /bits/ 8 <OSD_BLEND_BLOCK>; + block_name = "osd_blend_block"; + type = /bits/ 8 <3>; + num_in_links = /bits/ 8 <0x3>; + in_links = <0 &afbc_osd1_block>, + <0 &scaler_osd2_block>, + <0 &scaler_osd3_block>; + num_out_links = /bits/ 8 <0x2>; + out_links = <0 &osd1_hdr_dolby_block>, + <1 &vpp_postblend_block>; + }; + osd1_hdr_dolby_block: block@10 { + id = /bits/ 8 <OSD1_HDR_BLOCK>; + block_name = "osd1_hdr_dolby_block"; + type = /bits/ 8 <4>; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd_blend_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd1_block>; + }; + vpp_postblend_block: block@12 { + id = /bits/ 8 <VPP_POSTBLEND_BLOCK>; + block_name = "vpp_postblend_block"; + type = /bits/ 8 <6>; + num_in_links = /bits/ 8 <0x2>; + in_links = <0 &scaler_osd1_block>, + <1 &osd_blend_block>; + num_out_links = <0x0>; + }; + }; + }; + + vpu_hw_para: vpu_hw_para@0 { + osd_ver = /bits/ 8 <0x2>; + afbc_type = /bits/ 8 <0x2>; + has_deband = /bits/ 8 <0x1>; + has_lut = /bits/ 8 <0x1>; + has_rdma = /bits/ 8 <0x1>; + osd_fifo_len = /bits/ 8 <64>; + vpp_fifo_len = /bits/ 32 <0xfff>; + }; }; }; diff --git a/arch/arm/boot/dts/amlogic/mesong12b_drm.dtsi b/arch/arm/boot/dts/amlogic/mesong12b_drm.dtsi new file mode 100644 index 0000000..48794f9d --- a/dev/null +++ b/arch/arm/boot/dts/amlogic/mesong12b_drm.dtsi @@ -0,0 +1,241 @@ +/* + * arch/arm/boot/dts/amlogic/meson_drm.dtsi + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ +#include <dt-bindings/display/meson-drm-ids.h> + +/ { + venc-cvbs { + status = "okay"; + compatible = "amlogic, meson-g12b-cvbs"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + enc_cvbs_in: port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + //venc_cvbs_in_vpu: endpoint@0 { + // reg = <0>; + // remote-endpoint = <&vpu_out_venc_cvbs>; + //}; + }; + }; + }; + + drm_amhdmitx: drm-amhdmitx { + status = "disabled"; + hdcp = "disabled"; + compatible = "amlogic,drm-amhdmitx"; + dev_name = "meson-amhdmitx"; + interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>; + ports { + port { + #address-cells = <1>; + #size-cells = <0>; + hdmi_in_vpu: endpoint@0 { + reg = <0>; + remote-endpoint = <&vpu_out_hdmi>; + }; + }; + }; + }; + + drm_lcd: drm-lcd { + status = "disabled"; + compatible = "amlogic,drm-lcd"; + dev_name = "meson-lcd"; + ports { + port { + #address-cells = <1>; + #size-cells = <0>; + lcd_in_vpu: endpoint@0 { + reg = <0>; + remote-endpoint = <&vpu_out_lcd>; + }; + }; + }; + }; + + drm_vpu: drm-vpu@0xff900000 { + status = "disabled"; + compatible = "amlogic,meson-g12b-vpu"; + memory-region = <&logo_reserved>; + reg = <0xff900000 0x40000>, + <0xff63c000 0x2000>, + <0xff638000 0x2000>; + reg-names = "base", "hhi", "dmc"; + interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 56 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "viu-vsync", "viu2-vsync"; + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + dma-coherent; + vpu_out: port { + #address-cells = <1>; + #size-cells = <0>; + + vpu_out_hdmi: endpoint@0 { + reg = <0>; + remote-endpoint = <&hdmi_in_vpu>; + }; + vpu_out_lcd: endpoint@1 { + reg = <1>; + remote-endpoint = <&lcd_in_vpu>; + }; + }; + }; + + drm_subsystem: drm-subsystem { + status = "okay"; + compatible = "amlogic,drm-subsystem"; + ports = <&vpu_out>; + + vpu_topology: vpu_topology { + vpu_blocks { + osd1_block: block@0 { + id = /bits/ 8 <OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <0>; + block_name = "osd1_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd1_block>; + }; + osd2_block: block@1 { + id = /bits/ 8 <OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <0>; + block_name = "osd2_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd2_block>; + }; + osd3_block: block@2 { + id = /bits/ 8 <OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <0>; + block_name = "osd3_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd3_block>; + }; + afbc_osd1_block: block@3 { + id = /bits/ 8 <AFBC_OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <1>; + block_name = "afbc_osd1_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd1_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &osd_blend_block>; + }; + afbc_osd2_block: block@4 { + id = /bits/ 8 <AFBC_OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <1>; + block_name = "afbc_osd2_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd2_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd2_block>; + }; + afbc_osd3_block: block@5 { + id = /bits/ 8 <AFBC_OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <1>; + block_name = "afbc_osd3_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd3_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd3_block>; + }; + scaler_osd1_block: block@6 { + id = /bits/ 8 <SCALER_OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <2>; + block_name = "scaler_osd1_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd1_hdr_dolby_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &vpp_postblend_block>; + }; + scaler_osd2_block: block@7 { + id = /bits/ 8 <SCALER_OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <2>; + block_name = "scaler_osd2_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &afbc_osd2_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <2 &osd_blend_block>; + }; + scaler_osd3_block: block@8 { + id = /bits/ 8 <SCALER_OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <2>; + block_name = "scaler_osd3_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &afbc_osd3_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <3 &osd_blend_block>; + }; + osd_blend_block: block@9 { + id = /bits/ 8 <OSD_BLEND_BLOCK>; + block_name = "osd_blend_block"; + type = /bits/ 8 <3>; + num_in_links = /bits/ 8 <0x3>; + in_links = <0 &afbc_osd1_block>, + <0 &scaler_osd2_block>, + <0 &scaler_osd3_block>; + num_out_links = /bits/ 8 <0x2>; + out_links = <0 &osd1_hdr_dolby_block>, + <1 &vpp_postblend_block>; + }; + osd1_hdr_dolby_block: block@10 { + id = /bits/ 8 <OSD1_HDR_BLOCK>; + block_name = "osd1_hdr_dolby_block"; + type = /bits/ 8 <4>; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd_blend_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd1_block>; + }; + vpp_postblend_block: block@12 { + id = /bits/ 8 <VPP_POSTBLEND_BLOCK>; + block_name = "vpp_postblend_block"; + type = /bits/ 8 <6>; + num_in_links = /bits/ 8 <0x2>; + in_links = <0 &scaler_osd1_block>, + <1 &osd_blend_block>; + num_out_links = <0x0>; + }; + }; + }; + + vpu_hw_para: vpu_hw_para@0 { + osd_ver = /bits/ 8 <0x2>; + afbc_type = /bits/ 8 <0x2>; + has_deband = /bits/ 8 <0x1>; + has_lut = /bits/ 8 <0x1>; + has_rdma = /bits/ 8 <0x1>; + osd_fifo_len = /bits/ 8 <64>; + vpp_fifo_len = /bits/ 32 <0xfff>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index 380ba94..b43feaf 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -820,6 +820,7 @@ &drm_vpu { status = "okay"; logo_addr = "0x7f800000"; + osd_ver = /bits/ 8 <OSD_V1>; }; &drm_amhdmitx { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts index 512f9f5..adff020 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -19,7 +19,7 @@ #include "mesong12b.dtsi" #include "mesong12b_skt-panel.dtsi" -#include "mesong12a_drm.dtsi" +#include "mesong12b_drm.dtsi" / { model = "Amlogic"; @@ -903,6 +903,7 @@ status = "okay"; compatible = "amlogic,meson-g12b-vpu"; logo_addr = "0x7f800000"; + osd_ver = /bits/ 8 <OSD_V3>; }; &drm_amhdmitx { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts index b7c2bbf..109a044 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts @@ -870,6 +870,7 @@ status = "okay"; compatible = "amlogic,meson-g12b-vpu"; logo_addr = "0x7f800000"; + osd_ver = /bits/ 8 <OSD_V2>; }; &drm_amhdmitx { diff --git a/arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts new file mode 100644 index 0000000..207a2da --- a/dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts @@ -0,0 +1,1473 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" +#include "mesong12b_drm.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x0>; + pmsg-size = <0x8000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x10000000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x03000000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶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>; +}; diff --git a/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi index 60c3cff..175af58 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi @@ -13,12 +13,13 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * -*/ + */ +#include <dt-bindings/display/meson-drm-ids.h> / { venc-cvbs { status = "okay"; - compatible = "amlogic,meson-gxbb-cvbs"; + compatible = "amlogic, meson-g12a-cvbs"; ports { #address-cells = <1>; @@ -104,6 +105,138 @@ status = "okay"; compatible = "amlogic,drm-subsystem"; ports = <&vpu_out>; + + vpu_topology: vpu_topology { + vpu_blocks { + osd1_block: block@0 { + id = /bits/ 8 <OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <0>; + block_name = "osd1_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd1_block>; + }; + osd2_block: block@1 { + id = /bits/ 8 <OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <0>; + block_name = "osd2_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd2_block>; + }; + osd3_block: block@2 { + id = /bits/ 8 <OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <0>; + block_name = "osd3_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd3_block>; + }; + afbc_osd1_block: block@3 { + id = /bits/ 8 <AFBC_OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <1>; + block_name = "afbc_osd1_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd1_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &osd_blend_block>; + }; + afbc_osd2_block: block@4 { + id = /bits/ 8 <AFBC_OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <1>; + block_name = "afbc_osd2_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd2_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd2_block>; + }; + afbc_osd3_block: block@5 { + id = /bits/ 8 <AFBC_OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <1>; + block_name = "afbc_osd3_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd3_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd3_block>; + }; + scaler_osd1_block: block@6 { + id = /bits/ 8 <SCALER_OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <2>; + block_name = "scaler_osd1_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd1_hdr_dolby_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &vpp_postblend_block>; + }; + scaler_osd2_block: block@7 { + id = /bits/ 8 <SCALER_OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <2>; + block_name = "scaler_osd2_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &afbc_osd2_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <2 &osd_blend_block>; + }; + scaler_osd3_block: block@8 { + id = /bits/ 8 <SCALER_OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <2>; + block_name = "scaler_osd3_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &afbc_osd3_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <3 &osd_blend_block>; + }; + osd_blend_block: block@9 { + id = /bits/ 8 <OSD_BLEND_BLOCK>; + block_name = "osd_blend_block"; + type = /bits/ 8 <3>; + num_in_links = /bits/ 8 <0x3>; + in_links = <0 &afbc_osd1_block>, + <0 &scaler_osd2_block>, + <0 &scaler_osd3_block>; + num_out_links = /bits/ 8 <0x2>; + out_links = <0 &osd1_hdr_dolby_block>, + <1 &vpp_postblend_block>; + }; + osd1_hdr_dolby_block: block@10 { + id = /bits/ 8 <OSD1_HDR_BLOCK>; + block_name = "osd1_hdr_dolby_block"; + type = /bits/ 8 <4>; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd_blend_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd1_block>; + }; + vpp_postblend_block: block@12 { + id = /bits/ 8 <VPP_POSTBLEND_BLOCK>; + block_name = "vpp_postblend_block"; + type = /bits/ 8 <6>; + num_in_links = /bits/ 8 <0x2>; + in_links = <0 &scaler_osd1_block>, + <1 &osd_blend_block>; + num_out_links = <0x0>; + }; + }; + }; + + vpu_hw_para: vpu_hw_para@0 { + osd_ver = /bits/ 8 <0x2>; + afbc_type = /bits/ 8 <0x2>; + has_deband = /bits/ 8 <0x1>; + has_lut = /bits/ 8 <0x1>; + has_rdma = /bits/ 8 <0x1>; + osd_fifo_len = /bits/ 8 <64>; + vpp_fifo_len = /bits/ 32 <0xfff>; + }; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_drm.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_drm.dtsi new file mode 100644 index 0000000..04e6f48 --- a/dev/null +++ b/arch/arm64/boot/dts/amlogic/mesong12b_drm.dtsi @@ -0,0 +1,241 @@ +/* + * arch/arm64/boot/dts/amlogic/meson_drm.dtsi + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ +#include <dt-bindings/display/meson-drm-ids.h> + +/ { + venc-cvbs { + status = "okay"; + compatible = "amlogic, meson-g12b-cvbs"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + enc_cvbs_in: port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + //venc_cvbs_in_vpu: endpoint@0 { + // reg = <0>; + // remote-endpoint = <&vpu_out_venc_cvbs>; + //}; + }; + }; + }; + + drm_amhdmitx: drm-amhdmitx { + status = "disabled"; + hdcp = "disabled"; + compatible = "amlogic,drm-amhdmitx"; + dev_name = "meson-amhdmitx"; + interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>; + ports { + port { + #address-cells = <1>; + #size-cells = <0>; + hdmi_in_vpu: endpoint@0 { + reg = <0>; + remote-endpoint = <&vpu_out_hdmi>; + }; + }; + }; + }; + + drm_lcd: drm-lcd { + status = "disabled"; + compatible = "amlogic,drm-lcd"; + dev_name = "meson-lcd"; + ports { + port { + #address-cells = <1>; + #size-cells = <0>; + lcd_in_vpu: endpoint@0 { + reg = <0>; + remote-endpoint = <&vpu_out_lcd>; + }; + }; + }; + }; + + drm_vpu: drm-vpu@0xff900000 { + status = "disabled"; + compatible = "amlogic,meson-g12b-vpu"; + memory-region = <&logo_reserved>; + reg = <0x0 0xff900000 0x0 0x40000>, + <0x0 0xff63c000 0x0 0x2000>, + <0x0 0xff638000 0x0 0x2000>; + reg-names = "base", "hhi", "dmc"; + interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 56 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "viu-vsync", "viu2-vsync"; + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + dma-coherent; + vpu_out: port { + #address-cells = <1>; + #size-cells = <0>; + + vpu_out_hdmi: endpoint@0 { + reg = <0>; + remote-endpoint = <&hdmi_in_vpu>; + }; + vpu_out_lcd: endpoint@1 { + reg = <1>; + remote-endpoint = <&lcd_in_vpu>; + }; + }; + }; + + drm_subsystem: drm-subsystem { + status = "okay"; + compatible = "amlogic,drm-subsystem"; + ports = <&vpu_out>; + + vpu_topology: vpu_topology { + vpu_blocks { + osd1_block: block@0 { + id = /bits/ 8 <OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <0>; + block_name = "osd1_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd1_block>; + }; + osd2_block: block@1 { + id = /bits/ 8 <OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <0>; + block_name = "osd2_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd2_block>; + }; + osd3_block: block@2 { + id = /bits/ 8 <OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <0>; + block_name = "osd3_block"; + num_in_links = /bits/ 8 <0x0>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &afbc_osd3_block>; + }; + afbc_osd1_block: block@3 { + id = /bits/ 8 <AFBC_OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <1>; + block_name = "afbc_osd1_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd1_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &osd_blend_block>; + }; + afbc_osd2_block: block@4 { + id = /bits/ 8 <AFBC_OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <1>; + block_name = "afbc_osd2_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd2_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd2_block>; + }; + afbc_osd3_block: block@5 { + id = /bits/ 8 <AFBC_OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <1>; + block_name = "afbc_osd3_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd3_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd3_block>; + }; + scaler_osd1_block: block@6 { + id = /bits/ 8 <SCALER_OSD1_BLOCK>; + index = /bits/ 8 <0>; + type = /bits/ 8 <2>; + block_name = "scaler_osd1_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd1_hdr_dolby_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &vpp_postblend_block>; + }; + scaler_osd2_block: block@7 { + id = /bits/ 8 <SCALER_OSD2_BLOCK>; + index = /bits/ 8 <1>; + type = /bits/ 8 <2>; + block_name = "scaler_osd2_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &afbc_osd2_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <2 &osd_blend_block>; + }; + scaler_osd3_block: block@8 { + id = /bits/ 8 <SCALER_OSD3_BLOCK>; + index = /bits/ 8 <2>; + type = /bits/ 8 <2>; + block_name = "scaler_osd3_block"; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &afbc_osd3_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <3 &osd_blend_block>; + }; + osd_blend_block: block@9 { + id = /bits/ 8 <OSD_BLEND_BLOCK>; + block_name = "osd_blend_block"; + type = /bits/ 8 <3>; + num_in_links = /bits/ 8 <0x3>; + in_links = <0 &afbc_osd1_block>, + <0 &scaler_osd2_block>, + <0 &scaler_osd3_block>; + num_out_links = /bits/ 8 <0x2>; + out_links = <0 &osd1_hdr_dolby_block>, + <1 &vpp_postblend_block>; + }; + osd1_hdr_dolby_block: block@10 { + id = /bits/ 8 <OSD1_HDR_BLOCK>; + block_name = "osd1_hdr_dolby_block"; + type = /bits/ 8 <4>; + num_in_links = /bits/ 8 <0x1>; + in_links = <0 &osd_blend_block>; + num_out_links = /bits/ 8 <0x1>; + out_links = <0 &scaler_osd1_block>; + }; + vpp_postblend_block: block@12 { + id = /bits/ 8 <VPP_POSTBLEND_BLOCK>; + block_name = "vpp_postblend_block"; + type = /bits/ 8 <6>; + num_in_links = /bits/ 8 <0x2>; + in_links = <0 &scaler_osd1_block>, + <1 &osd_blend_block>; + num_out_links = <0x0>; + }; + }; + }; + + vpu_hw_para: vpu_hw_para@0 { + osd_ver = /bits/ 8 <0x2>; + afbc_type = /bits/ 8 <0x2>; + has_deband = /bits/ 8 <0x1>; + has_lut = /bits/ 8 <0x1>; + has_rdma = /bits/ 8 <0x1>; + osd_fifo_len = /bits/ 8 <64>; + vpp_fifo_len = /bits/ 32 <0xfff>; + }; + }; +}; diff --git a/drivers/amlogic/Makefile b/drivers/amlogic/Makefile index fec14e2..c8d62eb 100644 --- a/drivers/amlogic/Makefile +++ b/drivers/amlogic/Makefile @@ -116,7 +116,7 @@ obj-$(CONFIG_AMLOGIC_IIO) += iio/ obj-$(CONFIG_AMLOGIC_DDR_TOOL) += ddr_tool/ -obj-$(CONFIG_DRM_MESON) += drm/ +obj-$(CONFIG_AMLOGIC_DRM) += drm/ obj-$(CONFIG_AMLOGIC_M8B_SM) += secure_monitor/ diff --git a/drivers/amlogic/drm/Kconfig b/drivers/amlogic/drm/Kconfig index 6298cde..999b650 100644 --- a/drivers/amlogic/drm/Kconfig +++ b/drivers/amlogic/drm/Kconfig @@ -1,11 +1,41 @@ +menuconfig AMLOGIC_DRM + bool "Amlogic drm support" + depends on AMLOGIC_DRIVER && DRM + default n + help + amlogic drm driver provide drm support on Amlogic + SOC chips. +choice + prompt "meson drm driver type" + depends on AMLOGIC_DRM + default DRM_MESON + config DRM_MESON - tristate "DRM Support for Amlogic Meson Display Controller" + tristate "DRM Support for Amlogic new Display Controller" + depends on DRM && OF && (ARM || ARM64) + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER + select VIDEOMODE_HELPERS + select REGMAP_MMIO + help + amlogic new soc display controller + use the pipeline and modularized + +config DRM_MESON_V0 + tristate "DRM Support for Amlogic old Display Controller" depends on DRM && OF && (ARM || ARM64) select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER select VIDEOMODE_HELPERS select REGMAP_MMIO + help + amlogic old soc display controller + use the osd driver +endchoice + +if DRM_MESON config DRM_MESON_VPU tristate "support drm vpu function for meson drm display." @@ -59,3 +89,10 @@ config DRM_MESON_EMULATE_FBDEV depends on DRM_MESON && DRM_MESON_USE_ION help Emulate framebuffer device for device which need use fbdev api. +endif + +if DRM_MESON_V0 + +source "drivers/amlogic/drm/drm-v0/Kconfig" + +endif diff --git a/drivers/amlogic/drm/Makefile b/drivers/amlogic/drm/Makefile index 2446575..bdbcd79 100644 --- a/drivers/amlogic/drm/Makefile +++ b/drivers/amlogic/drm/Makefile @@ -1,28 +1,38 @@ -meson_drv-y += am_meson_drv.o -ccflags-y += -Idrivers/amlogic/media/osd/ - ifeq ($(CONFIG_DRM_MESON_USE_ION),y) - meson_drv-y += am_meson_gem.o am_meson_fb.o - ccflags-y += -Idrivers/staging/android/ + meson-drm-y += meson_gem.o meson_fb.o + ccflags-y += -Idrivers/staging/android/ endif ifeq ($(CONFIG_DRM_MESON_EMULATE_FBDEV),y) - meson_drv-y += am_meson_fbdev.o + meson-drm-y += meson_fbdev.o endif ifneq ($(CONFIG_DRM_MESON_VPU),) - meson_vpu-y += am_meson_vpu.o + meson-drm-y += meson_vpu.o endif ifneq ($(CONFIG_DRM_MESON_HDMI),) - meson_hdmi-y += am_meson_hdmi.o am_meson_hdcp.o + meson-drm-y += meson_hdmi.o meson_hdcp.o endif ifneq ($(CONFIG_DRM_MESON_PANEL),) - meson_lcd-y += am_meson_lcd.o + meson-drm-y += meson_lcd.o endif -obj-$(CONFIG_DRM_MESON) += meson_drv.o -obj-$(CONFIG_DRM_MESON_VPU) += meson_vpu.o -obj-$(CONFIG_DRM_MESON_HDMI) += meson_hdmi.o -obj-$(CONFIG_DRM_MESON_PANEL) += meson_lcd.o +meson-drm-y += meson_drv.o meson_plane.o meson_vpu_pipeline_traverse.o \ + meson_crtc.o meson_vpu_pipeline.o meson_vpu_pipeline_private.o \ + +meson-drm-y += \ + vpu-hw/meson_vpu_osd_mif.o \ + vpu-hw/meson_osd_afbc.o \ + vpu-hw/meson_osd_scaler.o \ + vpu-hw/meson_vpu_osdblend.o \ + vpu-hw/meson_vpu_hdr_dv.o \ + vpu-hw/meson_vpu_postblend.o + +ifneq ($(CONFIG_DRM_MESON_V0), y) + ccflags-y += -Idrivers/amlogic/media/osd/ -I$(src)/vpu-hw -I$(src) + obj-y += meson-drm.o +else + obj-y += drm-v0/ +endif diff --git a/drivers/amlogic/drm/am_meson_fbdev.h b/drivers/amlogic/drm/am_meson_fbdev.h deleted file mode 100644 index 218ddca..0000000 --- a/drivers/amlogic/drm/am_meson_fbdev.h +++ b/dev/null @@ -1,24 +0,0 @@ -/* - * drivers/amlogic/drm/am_meson_fbdev.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __AM_MESON_FBDEV_H -#define __AM_MESON_FBDEV_H - -#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV -int am_meson_drm_fbdev_init(struct drm_device *dev); -void am_meson_drm_fbdev_fini(struct drm_device *dev); -#endif - -#endif /* __AM_MESON_FBDEV_H */ diff --git a/drivers/amlogic/drm/drm-v0/Kconfig b/drivers/amlogic/drm/drm-v0/Kconfig new file mode 100644 index 0000000..c463c64 --- a/dev/null +++ b/drivers/amlogic/drm/drm-v0/Kconfig @@ -0,0 +1,52 @@ +config DRM_MESON_VPU + tristate "support drm vpu function for meson drm display." + default y + depends on DRM_MESON_V0 + help + add drm vpu support. + Choose this option if you have a aMLOGIC soc chipset. + This driver provides KMS. + This driver also provides crtcs and planes management. + +config DRM_MESON_HDMI + tristate "support drm hdmi function for meson drm display." + default y + depends on DRM_MESON_V0 + depends on AMLOGIC_HDMITX + help + add drm hdmi support. + use internal amlogic media vout hdmi driver. + We should confirm AMLOGIC_HDMITX is configured if + DRM_MESON_HDMI is selected. + +config DRM_MESON_PANEL + tristate "support drm panel function for meson drm display." + default y + depends on DRM_MESON_V0 + depends on AMLOGIC_LCD + select DRM_PANEL + select DRM_MIPI_DSI + help + add drm panel support. + use internal amlogic media vout lcd driver. + We should confirm AMLOGIC_LCD is configured if + DRM_MESON_PANEL is selected. + +config DRM_MESON_USE_ION + bool "gem use ion to alloc/free graphic buffer." + default y + depends on DRM_MESON_V0 + help + MESON DRM use CMA HELPER to manage framebuffer. + It need reserve memory in CMA pool. + We implement GEM to allocate/free framebuffer from ion. + For dumb used by displaycontrol we alloc from the ION CMA HEAP. + For dumb used by app, we can alloc from the ION. + SYSTEM HEAP which dont need reserve memory. + +config DRM_MESON_EMULATE_FBDEV + bool "emulate framebuffer dev by drm." + default n + depends on DRM_MESON_V0 && DRM_MESON_USE_ION + help + Emulate framebuffer device for device which need use fbdev api. diff --git a/drivers/amlogic/drm/drm-v0/Makefile b/drivers/amlogic/drm/drm-v0/Makefile new file mode 100644 index 0000000..dd06060 --- a/dev/null +++ b/drivers/amlogic/drm/drm-v0/Makefile @@ -0,0 +1,28 @@ +meson_drv-y += am_meson_drv.o +ccflags-y += -Idrivers/amlogic/media/osd/ + +ifeq ($(CONFIG_DRM_MESON_USE_ION),y) + meson_drv-y += am_meson_gem.o am_meson_fb.o + ccflags-y += -Idrivers/staging/android/ +endif + +ifeq ($(CONFIG_DRM_MESON_EMULATE_FBDEV),y) + meson_drv-y += am_meson_fbdev.o +endif + +ifneq ($(CONFIG_DRM_MESON_VPU),) + meson_vpu-y += am_meson_vpu.o +endif + +ifneq ($(CONFIG_DRM_MESON_HDMI),) + meson_hdmi-y += am_meson_hdmi.o am_meson_hdcp.o +endif + +ifneq ($(CONFIG_DRM_MESON_PANEL),) + meson_lcd-y += am_meson_lcd.o +endif + +obj-y += meson_drv.o +obj-$(CONFIG_DRM_MESON_VPU) += meson_vpu.o +obj-$(CONFIG_DRM_MESON_HDMI) += meson_hdmi.o +obj-$(CONFIG_DRM_MESON_PANEL) += meson_lcd.o diff --git a/drivers/amlogic/drm/am_meson_drv.c b/drivers/amlogic/drm/drm-v0/am_meson_drv.c index 190cba3..2880b1c 100644 --- a/drivers/amlogic/drm/am_meson_drv.c +++ b/drivers/amlogic/drm/drm-v0/am_meson_drv.c @@ -1,23 +1,18 @@ /* - * Copyright (C) 2016 BayLibre, SAS - * Author: Neil Armstrong <narmstrong@baylibre.com> - * Copyright (C) 2014 Endless Mobile + * drivers/amlogic/drm/drm-v0/am_meson_drv.c * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * Written by: - * Jasper St. Pierre <jstpierre@mecheye.net> */ #include <linux/kernel.h> diff --git a/drivers/amlogic/drm/am_meson_drv.h b/drivers/amlogic/drm/drm-v0/am_meson_drv.h index 77279a5..c935d91 100644 --- a/drivers/amlogic/drm/am_meson_drv.h +++ b/drivers/amlogic/drm/drm-v0/am_meson_drv.h @@ -1,19 +1,18 @@ /* - * Copyright (C) 2016 BayLibre, SAS - * Author: Neil Armstrong <narmstrong@baylibre.com> + * drivers/amlogic/drm/drm-v0/am_meson_drv.h * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #ifndef __AM_MESON_DRV_H diff --git a/drivers/amlogic/drm/am_meson_fb.c b/drivers/amlogic/drm/drm-v0/am_meson_fb.c index 095f7ac..5ecd9e4 100644 --- a/drivers/amlogic/drm/am_meson_fb.c +++ b/drivers/amlogic/drm/drm-v0/am_meson_fb.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_fb.c + * drivers/amlogic/drm/drm-v0/am_meson_fb.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,6 +14,7 @@ * more details. * */ + #include <drm/drm_atomic_helper.h> #include "am_meson_fb.h" diff --git a/drivers/amlogic/drm/am_meson_fb.h b/drivers/amlogic/drm/drm-v0/am_meson_fb.h index faf0fce0..1751f79 100644 --- a/drivers/amlogic/drm/am_meson_fb.h +++ b/drivers/amlogic/drm/drm-v0/am_meson_fb.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_fb.h + * drivers/amlogic/drm/drm-v0/am_meson_fb.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * diff --git a/drivers/amlogic/drm/am_meson_fbdev.c b/drivers/amlogic/drm/drm-v0/am_meson_fbdev.c index 610f3ca..1998697 100644 --- a/drivers/amlogic/drm/am_meson_fbdev.c +++ b/drivers/amlogic/drm/drm-v0/am_meson_fbdev.c @@ -1,16 +1,18 @@ /* - * drivers/amlogic/drm/am_meson_fbdev.c + * drivers/amlogic/drm/drm-v0/am_meson_fbdev.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <drm/drm.h> diff --git a/drivers/amlogic/drm/am_meson_lcd.h b/drivers/amlogic/drm/drm-v0/am_meson_fbdev.h index 565f8eb..c446f98 100644 --- a/drivers/amlogic/drm/am_meson_lcd.h +++ b/drivers/amlogic/drm/drm-v0/am_meson_fbdev.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_lcd.h + * drivers/amlogic/drm/drm-v0/am_meson_fbdev.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -15,10 +15,12 @@ * */ -#ifndef __AM_DRM_LCD_H -#define __AM_DRM_LCD_H - -#include "am_meson_drv.h" +#ifndef __AM_MESON_FBDEV_H +#define __AM_MESON_FBDEV_H +#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV +int am_meson_drm_fbdev_init(struct drm_device *dev); +void am_meson_drm_fbdev_fini(struct drm_device *dev); #endif +#endif /* __AM_MESON_FBDEV_H */ diff --git a/drivers/amlogic/drm/am_meson_gem.c b/drivers/amlogic/drm/drm-v0/am_meson_gem.c index 9d731b8..b06d104 100644 --- a/drivers/amlogic/drm/am_meson_gem.c +++ b/drivers/amlogic/drm/drm-v0/am_meson_gem.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_gem.c + * drivers/amlogic/drm/drm-v0/am_meson_gem.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,6 +14,7 @@ * more details. * */ + #include <drm/drmP.h> #include <drm/drm_gem.h> #include <drm/drm_vma_manager.h> @@ -44,12 +45,11 @@ static int am_meson_gem_alloc_ion_buff( //check flags to set different ion heap type. //if flags is set to 0, need to use ion dma buffer. - if (((flags & (BO_USE_SCANOUT | BO_USE_CURSOR)) != 0) + if (((flags & (MESON_USE_SCANOUT | MESON_USE_CURSOR)) != 0) || (flags == 0)) { handle = ion_alloc(client, meson_gem_obj->base.size, 0, (1 << ION_HEAP_TYPE_DMA), 0); - } - else { + } else { handle = ion_alloc(client, meson_gem_obj->base.size, 0, (1 << ION_HEAP_TYPE_SYSTEM), 0); bscatter = true; @@ -415,10 +415,9 @@ struct sg_table *am_meson_gem_prime_get_sg_table( } return dst_table; } - else { - DRM_ERROR("Not support import buffer from other driver.\n"); - return NULL; - } + + DRM_ERROR("Not support import buffer from other driver.\n"); + return NULL; } struct drm_gem_object *am_meson_gem_prime_import_sg_table( diff --git a/drivers/amlogic/drm/am_meson_gem.h b/drivers/amlogic/drm/drm-v0/am_meson_gem.h index f6dcc7e..166a73c 100644 --- a/drivers/amlogic/drm/am_meson_gem.h +++ b/drivers/amlogic/drm/drm-v0/am_meson_gem.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_gem.h + * drivers/amlogic/drm/drm-v0/am_meson_gem.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -18,7 +18,7 @@ #ifndef __AM_MESON_GEM_H #define __AM_MESON_GEM_H #include <drm/drm_gem.h> -#include <linux/amlogic/meson_drm.h> +#include <uapi/drm/meson_drm.h> #include <ion/ion_priv.h> #include "am_meson_drv.h" diff --git a/drivers/amlogic/drm/am_meson_hdcp.c b/drivers/amlogic/drm/drm-v0/am_meson_hdcp.c index 3c45c26..6e2f176 100644 --- a/drivers/amlogic/drm/am_meson_hdcp.c +++ b/drivers/amlogic/drm/drm-v0/am_meson_hdcp.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_hdcp.c + * drivers/amlogic/drm/drm-v0/am_meson_hdcp.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * diff --git a/drivers/amlogic/drm/am_meson_hdcp.h b/drivers/amlogic/drm/drm-v0/am_meson_hdcp.h index f95d13f..accf846 100644 --- a/drivers/amlogic/drm/am_meson_hdcp.h +++ b/drivers/amlogic/drm/drm-v0/am_meson_hdcp.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_hdcp.h + * drivers/amlogic/drm/drm-v0/am_meson_hdcp.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * diff --git a/drivers/amlogic/drm/am_meson_hdmi.c b/drivers/amlogic/drm/drm-v0/am_meson_hdmi.c index a2efd9c..7e1a3ee 100644 --- a/drivers/amlogic/drm/am_meson_hdmi.c +++ b/drivers/amlogic/drm/drm-v0/am_meson_hdmi.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_hdmi.c + * drivers/amlogic/drm/drm-v0/am_meson_hdmi.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,6 +14,7 @@ * more details. * */ + #include <drm/drm_modeset_helper.h> #include <drm/drmP.h> #include <drm/drm_edid.h> diff --git a/drivers/amlogic/drm/am_meson_hdmi.h b/drivers/amlogic/drm/drm-v0/am_meson_hdmi.h index 37542dc..82a7bf0 100644 --- a/drivers/amlogic/drm/am_meson_hdmi.h +++ b/drivers/amlogic/drm/drm-v0/am_meson_hdmi.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_hdmi.h + * drivers/amlogic/drm/drm-v0/am_meson_hdmi.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,6 +14,7 @@ * more details. * */ + #ifndef __AM_MESON_HDMI_H #define __AM_MESON_HDMI_H diff --git a/drivers/amlogic/drm/am_meson_lcd.c b/drivers/amlogic/drm/drm-v0/am_meson_lcd.c index 462338f..7613cf6 100644 --- a/drivers/amlogic/drm/am_meson_lcd.c +++ b/drivers/amlogic/drm/drm-v0/am_meson_lcd.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_lcd.c + * drivers/amlogic/drm/drm-v0/am_meson_lcd.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -685,8 +685,6 @@ static void am_meson_lcd_unbind(struct device *dev, struct device *master, drm_panel_remove(&am_drm_lcd->panel); pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); - - return; } static const struct component_ops am_meson_lcd_ops = { diff --git a/drivers/amlogic/drm/am_meson_lcd.h b/drivers/amlogic/drm/drm-v0/am_meson_lcd.h index 565f8eb..39ab4d4 100644 --- a/drivers/amlogic/drm/am_meson_lcd.h +++ b/drivers/amlogic/drm/drm-v0/am_meson_lcd.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_lcd.h + * drivers/amlogic/drm/drm-v0/am_meson_lcd.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * diff --git a/drivers/amlogic/drm/am_meson_vpu.c b/drivers/amlogic/drm/drm-v0/am_meson_vpu.c index 9c7850b..f44cbb3 100644 --- a/drivers/amlogic/drm/am_meson_vpu.c +++ b/drivers/amlogic/drm/drm-v0/am_meson_vpu.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_vpu.c + * drivers/amlogic/drm/drm-v0/am_meson_vpu.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,6 +14,7 @@ * more details. * */ + #include <drm/drmP.h> #include <drm/drm_plane.h> #include <drm/drm_atomic.h> diff --git a/drivers/amlogic/drm/am_meson_vpu.h b/drivers/amlogic/drm/drm-v0/am_meson_vpu.h index 03adbbe..5f94006 100644 --- a/drivers/amlogic/drm/am_meson_vpu.h +++ b/drivers/amlogic/drm/drm-v0/am_meson_vpu.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_vpu.h + * drivers/amlogic/drm/drm-v0/am_meson_vpu.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,6 +14,7 @@ * more details. * */ + #ifndef __AM_MESON_VPU_H #define __AM_MESON_VPU_H diff --git a/drivers/amlogic/drm/meson_crtc.c b/drivers/amlogic/drm/meson_crtc.c new file mode 100644 index 0000000..f9a24d6 --- a/dev/null +++ b/drivers/amlogic/drm/meson_crtc.c @@ -0,0 +1,270 @@ +/* + * drivers/amlogic/drm/meson_crtc.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "meson_crtc.h" +#include "meson_vpu_pipeline.h" +#include "osd_drm.h" + +static int meson_crtc_set_mode(struct drm_mode_set *set) +{ + struct am_meson_crtc *amcrtc; + int ret; + + DRM_DEBUG_DRIVER("%s\n", __func__); + amcrtc = to_am_meson_crtc(set->crtc); + ret = drm_atomic_helper_set_config(set); + + return ret; +} + +static void meson_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct am_meson_crtc_state *meson_crtc_state; + + meson_crtc_state = to_am_meson_crtc_state(state); + __drm_atomic_helper_crtc_destroy_state(&meson_crtc_state->base); + kfree(meson_crtc_state); +} + +static struct drm_crtc_state *meson_crtc_duplicate_state(struct drm_crtc *crtc) +{ + struct am_meson_crtc_state *meson_crtc_state, *old_crtc_state; + + old_crtc_state = to_am_meson_crtc_state(crtc->state); + + meson_crtc_state = kmemdup(old_crtc_state, sizeof(*old_crtc_state), + GFP_KERNEL); + if (!meson_crtc_state) + return NULL; + + __drm_atomic_helper_crtc_duplicate_state(crtc, &meson_crtc_state->base); + return &meson_crtc_state->base; +} + +static int meson_crtc_atomic_get_property(struct drm_crtc *crtc, + const struct drm_crtc_state *state, + struct drm_property *property, + uint64_t *val) +{ + + return 0; +} + +static int meson_crtc_atomic_set_property(struct drm_crtc *crtc, + struct drm_crtc_state *state, + struct drm_property *property, + uint64_t val) +{ + return 0; +} + +static const struct drm_crtc_funcs am_meson_crtc_funcs = { + .atomic_destroy_state = meson_crtc_destroy_state, + .atomic_duplicate_state = meson_crtc_duplicate_state, + .destroy = drm_crtc_cleanup, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .set_config = meson_crtc_set_mode, + .atomic_get_property = meson_crtc_atomic_get_property, + .atomic_set_property = meson_crtc_atomic_set_property, +}; + +static bool am_meson_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) +{ + //DRM_INFO("%s !!\n", __func__); + + return true; +} + +static void am_meson_crtc_enable(struct drm_crtc *crtc) +{ + unsigned long flags; + char *name; + enum vmode_e mode; + struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; + struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc); + struct meson_vpu_pipeline *pipeline = amcrtc->pipeline; + + DRM_INFO("%s\n", __func__); + if (!adjusted_mode) { + DRM_ERROR("meson_crtc_enable fail, unsupport mode:%s\n", + adjusted_mode->name); + return; + } + DRM_INFO("%s: %s\n", __func__, adjusted_mode->name); + + name = am_meson_crtc_get_voutmode(adjusted_mode); + mode = validate_vmode(name); + if (mode == VMODE_MAX) { + DRM_ERROR("no matched vout mode\n"); + return; + } + if (is_meson_g12b_cpu() && is_meson_rev_b()) + set_reset_rdma_trigger_line(); + set_vout_init(mode); + update_vout_viu(); + memcpy(&pipeline->mode, adjusted_mode, + sizeof(struct drm_display_mode)); + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + amcrtc->vblank_enable = 1; + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); + enable_irq(amcrtc->vblank_irq); +} + +static void am_meson_crtc_disable(struct drm_crtc *crtc) +{ + struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc); + unsigned long flags; + + DRM_INFO("%s\n", __func__); + if (crtc->state->event && !crtc->state->active) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + spin_unlock_irq(&crtc->dev->event_lock); + crtc->state->event = NULL; + } + + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + amcrtc->vblank_enable = 0; + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); + + disable_irq(amcrtc->vblank_irq); +} + +static void am_meson_crtc_commit(struct drm_crtc *crtc) +{ + //DRM_INFO("%s\n", __func__); +} + +static int am_meson_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state) +{ + struct am_meson_crtc *amcrtc; + struct meson_vpu_pipeline *pipeline; + struct drm_atomic_state *state = crtc_state->state; + + amcrtc = to_am_meson_crtc(crtc); + pipeline = amcrtc->pipeline; + + return vpu_pipeline_check(pipeline, state); + +} + +static void am_meson_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + struct am_meson_crtc *amcrtc; + unsigned long flags; + + amcrtc = to_am_meson_crtc(crtc); + + if (crtc->state->event) { + WARN_ON(drm_crtc_vblank_get(crtc) != 0); + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + amcrtc->event = crtc->state->event; + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + crtc->state->event = NULL; + } +} + +static void am_meson_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct drm_color_ctm *ctm; + struct drm_color_lut *lut; + struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc); + struct drm_atomic_state *old_atomic_state = old_state->state; + + struct meson_vpu_pipeline *pipeline = amcrtc->pipeline; + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT + int gamma_lut_size = 0; + #endif + + if (crtc->state->color_mgmt_changed) { + DRM_INFO("%s color_mgmt_changed!\n", __func__); + if (crtc->state->ctm) { + DRM_INFO("%s color_mgmt_changed 1!\n", __func__); + ctm = (struct drm_color_ctm *) + crtc->state->ctm->data; + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT + am_meson_ctm_set(0, ctm); + #endif + } + if (crtc->state->gamma_lut) { + DRM_INFO("%s color_mgmt_changed 2!\n", __func__); + lut = (struct drm_color_lut *) + crtc->state->gamma_lut->data; + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT + gamma_lut_size = amvecm_drm_get_gamma_size(0); + amvecm_drm_gamma_set(0, lut, gamma_lut_size); + #endif + } + } + + vpu_pipeline_update(pipeline, old_atomic_state); +} + +static const struct drm_crtc_helper_funcs am_crtc_helper_funcs = { + .enable = am_meson_crtc_enable, + .disable = am_meson_crtc_disable, + .commit = am_meson_crtc_commit, + .mode_fixup = am_meson_crtc_mode_fixup, + .atomic_check = am_meson_atomic_check, + .atomic_begin = am_meson_crtc_atomic_begin, + .atomic_flush = am_meson_crtc_atomic_flush, +}; + +int am_meson_crtc_create(struct am_meson_crtc *amcrtc) +{ + struct meson_drm *priv = amcrtc->priv; + struct drm_crtc *crtc = &amcrtc->base; + struct meson_vpu_pipeline *pipeline = priv->pipeline; + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT + int gamma_lut_size = 0; + #endif + int ret; + + DRM_INFO("%s\n", __func__); + ret = drm_crtc_init_with_planes(priv->drm, crtc, + priv->primary_plane, priv->cursor_plane, + &am_meson_crtc_funcs, "amlogic vpu"); + if (ret) { + dev_err(amcrtc->dev, "Failed to init CRTC\n"); + return ret; + } + + drm_crtc_helper_add(crtc, &am_crtc_helper_funcs); + osd_drm_init(&osd_meson_dev); + + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT + amvecm_drm_init(0); + amvecm_drm_gamma_enable(0); + gamma_lut_size = amvecm_drm_get_gamma_size(0); + drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size); + drm_crtc_enable_color_mgmt(crtc, 0, true, gamma_lut_size); + #endif + + amcrtc->pipeline = pipeline; + priv->crtc = crtc; + priv->crtcs[priv->num_crtcs++] = amcrtc; + return 0; +} + diff --git a/drivers/amlogic/drm/meson_crtc.h b/drivers/amlogic/drm/meson_crtc.h new file mode 100644 index 0000000..c02ff85 --- a/dev/null +++ b/drivers/amlogic/drm/meson_crtc.h @@ -0,0 +1,65 @@ +/* + * drivers/amlogic/drm/meson_crtc.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __MESON_CRTC_H +#define __MESON_CRTC_H + +#include <linux/kernel.h> +#include <drm/drmP.h> +#include <drm/drm_plane.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <linux/amlogic/media/vout/vout_notify.h> +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT +#include <linux/amlogic/media/amvecm/amvecm.h> +#endif +#include "osd.h" +#include "osd_drm.h" +#include "meson_vpu.h" +#include "meson_drv.h" +#include "meson_fb.h" + +struct am_meson_crtc_state { + struct drm_crtc_state base; +}; + +struct am_meson_crtc { + struct drm_crtc base; + struct device *dev; + struct drm_device *drm_dev; + + struct meson_drm *priv; + + struct drm_pending_vblank_event *event; + + unsigned int vblank_irq; + spinlock_t vblank_irq_lock;/*atomic*/ + u32 vblank_enable; + + struct dentry *crtc_debugfs_dir; + + struct meson_vpu_pipeline *pipeline; +}; + +#define to_am_meson_crtc(x) container_of(x, \ + struct am_meson_crtc, base) +#define to_am_meson_crtc_state(x) container_of(x, \ + struct am_meson_crtc_state, base) + +int am_meson_crtc_create(struct am_meson_crtc *amcrtc); + +#endif diff --git a/drivers/amlogic/drm/am_meson_drv.c b/drivers/amlogic/drm/meson_drv.c index 190cba3..eecde0e 100644 --- a/drivers/amlogic/drm/am_meson_drv.c +++ b/drivers/amlogic/drm/meson_drv.c @@ -1,23 +1,18 @@ /* - * Copyright (C) 2016 BayLibre, SAS - * Author: Neil Armstrong <narmstrong@baylibre.com> - * Copyright (C) 2014 Endless Mobile + * drivers/amlogic/drm/meson_drv.c * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * Written by: - * Jasper St. Pierre <jstpierre@mecheye.net> */ #include <linux/kernel.h> @@ -39,18 +34,18 @@ #include <drm/drm_rect.h> #include <drm/drm_fb_helper.h> -#include "am_meson_fbdev.h" +#include "meson_fbdev.h" #ifdef CONFIG_DRM_MESON_USE_ION -#include "am_meson_gem.h" -#include "am_meson_fb.h" +#include "meson_gem.h" +#include "meson_fb.h" #endif -#include "am_meson_drv.h" +#include "meson_drv.h" +#include "meson_vpu_pipeline.h" #define DRIVER_NAME "meson" #define DRIVER_DESC "Amlogic Meson DRM driver" - static void am_meson_fb_output_poll_changed(struct drm_device *dev) { #ifdef CONFIG_DRM_MESON_EMULATE_FBDEV @@ -102,20 +97,21 @@ static int am_meson_enable_vblank(struct drm_device *dev, unsigned int crtc) { struct meson_drm *priv = dev->dev_private; - if (crtc > MESON_MAX_CRTC) + if (crtc >= MESON_MAX_CRTC) return -EBADFD; - return priv->crtc_funcs[crtc]->enable_vblank(priv->crtc); + priv->crtc_funcs[crtc]->enable_vblank(priv->crtc); + return 0; } static void am_meson_disable_vblank(struct drm_device *dev, unsigned int crtc) { struct meson_drm *priv = dev->dev_private; - if (crtc > MESON_MAX_CRTC) + if (crtc >= MESON_MAX_CRTC) return; - return priv->crtc_funcs[crtc]->disable_vblank(priv->crtc); + priv->crtc_funcs[crtc]->disable_vblank(priv->crtc); } static void am_meson_load(struct drm_device *dev) @@ -224,6 +220,7 @@ static int am_meson_drm_bind(struct device *dev) { struct meson_drm *priv; struct drm_device *drm; + struct platform_device *pdev = to_platform_device(dev); int ret = 0; meson_driver.driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | @@ -250,6 +247,9 @@ static int am_meson_drm_bind(struct device *dev) goto err_free2; #endif + vpu_topology_init(pdev, priv); + meson_vpu_block_state_init(priv, priv->pipeline); + drm_mode_config_init(drm); /* Try to bind all sub drivers. */ @@ -263,9 +263,10 @@ static int am_meson_drm_bind(struct device *dev) goto err_unbind_all; drm_mode_config_reset(drm); - drm->mode_config.max_width = 8192; - drm->mode_config.max_height = 8192; + drm->mode_config.max_width = 4096; + drm->mode_config.max_height = 4096; drm->mode_config.funcs = &meson_mode_config_funcs; + drm->mode_config.allow_fb_modifiers = true; /* * irq will init in each crtc, just mark the enable flag here. */ @@ -279,9 +280,7 @@ static int am_meson_drm_bind(struct device *dev) ret = am_meson_drm_fbdev_init(drm); if (ret) goto err_poll_fini; - drm->mode_config.allow_fb_modifiers = true; #endif - ret = drm_dev_register(drm, 0); if (ret) goto err_fbdev_fini; diff --git a/drivers/amlogic/drm/am_meson_drv.h b/drivers/amlogic/drm/meson_drv.h index 77279a5..40ca261 100644 --- a/drivers/amlogic/drm/am_meson_drv.h +++ b/drivers/amlogic/drm/meson_drv.h @@ -1,19 +1,18 @@ /* - * Copyright (C) 2016 BayLibre, SAS - * Author: Neil Armstrong <narmstrong@baylibre.com> + * drivers/amlogic/drm/meson_drv.h * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #ifndef __AM_MESON_DRV_H @@ -27,6 +26,7 @@ #endif #define MESON_MAX_CRTC 2 +#define MESON_MAX_OSD 4 /* * Amlogic drm private crtc funcs. @@ -55,6 +55,15 @@ struct meson_drm { #ifdef CONFIG_DRM_MESON_USE_ION struct ion_client *gem_client; #endif + + struct meson_vpu_pipeline *pipeline; + struct meson_vpu_funcs *funcs; + + u32 num_crtcs; + struct am_meson_crtc *crtcs[MESON_MAX_CRTC]; + + u32 num_planes; + struct am_osd_plane *planes[MESON_MAX_OSD]; }; static inline int meson_vpu_is_compatible(struct meson_drm *priv, diff --git a/drivers/amlogic/drm/am_meson_fb.c b/drivers/amlogic/drm/meson_fb.c index 095f7ac..1c364da 100644 --- a/drivers/amlogic/drm/am_meson_fb.c +++ b/drivers/amlogic/drm/meson_fb.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_fb.c + * drivers/amlogic/drm/meson_fb.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,9 +14,10 @@ * more details. * */ + #include <drm/drm_atomic_helper.h> -#include "am_meson_fb.h" +#include "meson_fb.h" #define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base) diff --git a/drivers/amlogic/drm/am_meson_fb.h b/drivers/amlogic/drm/meson_fb.h index faf0fce0..9c76d2e 100644 --- a/drivers/amlogic/drm/am_meson_fb.h +++ b/drivers/amlogic/drm/meson_fb.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_fb.h + * drivers/amlogic/drm/meson_fb.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -22,7 +22,7 @@ #include <drm/drm_framebuffer.h> #include <drm/drm_modeset_helper.h> -#include "am_meson_gem.h" +#include "meson_gem.h" struct am_meson_fb { struct drm_framebuffer base; diff --git a/drivers/amlogic/drm/am_meson_fbdev.c b/drivers/amlogic/drm/meson_fbdev.c index 610f3ca..b43788f 100644 --- a/drivers/amlogic/drm/am_meson_fbdev.c +++ b/drivers/amlogic/drm/meson_fbdev.c @@ -1,16 +1,18 @@ /* - * drivers/amlogic/drm/am_meson_fbdev.c + * drivers/amlogic/drm/meson_fbdev.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <drm/drm.h> @@ -18,10 +20,10 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_crtc_helper.h> -#include "am_meson_drv.h" -#include "am_meson_gem.h" -#include "am_meson_fb.h" -#include "am_meson_fbdev.h" +#include "meson_drv.h" +#include "meson_gem.h" +#include "meson_fb.h" +#include "meson_fbdev.h" #define PREFERRED_BPP 32 #define MESON_DRM_MAX_CONNECTOR 2 diff --git a/drivers/amlogic/drm/am_meson_lcd.h b/drivers/amlogic/drm/meson_fbdev.h index 565f8eb..898c262 100644 --- a/drivers/amlogic/drm/am_meson_lcd.h +++ b/drivers/amlogic/drm/meson_fbdev.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_lcd.h + * drivers/amlogic/drm/meson_fbdev.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -15,10 +15,12 @@ * */ -#ifndef __AM_DRM_LCD_H -#define __AM_DRM_LCD_H - -#include "am_meson_drv.h" +#ifndef __AM_MESON_FBDEV_H +#define __AM_MESON_FBDEV_H +#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV +int am_meson_drm_fbdev_init(struct drm_device *dev); +void am_meson_drm_fbdev_fini(struct drm_device *dev); #endif +#endif /* __AM_MESON_FBDEV_H */ diff --git a/drivers/amlogic/drm/am_meson_gem.c b/drivers/amlogic/drm/meson_gem.c index 9d731b8..051cfce 100644 --- a/drivers/amlogic/drm/am_meson_gem.c +++ b/drivers/amlogic/drm/meson_gem.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_gem.c + * drivers/amlogic/drm/meson_gem.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,6 +14,7 @@ * more details. * */ + #include <drm/drmP.h> #include <drm/drm_gem.h> #include <drm/drm_vma_manager.h> @@ -24,7 +25,7 @@ #include <linux/meson_ion.h> #include <ion/ion.h> -#include "am_meson_gem.h" +#include "meson_gem.h" #define to_am_meson_gem_obj(x) container_of(x, struct am_meson_gem_object, base) @@ -44,12 +45,11 @@ static int am_meson_gem_alloc_ion_buff( //check flags to set different ion heap type. //if flags is set to 0, need to use ion dma buffer. - if (((flags & (BO_USE_SCANOUT | BO_USE_CURSOR)) != 0) + if (((flags & (MESON_USE_SCANOUT | MESON_USE_CURSOR)) != 0) || (flags == 0)) { handle = ion_alloc(client, meson_gem_obj->base.size, 0, (1 << ION_HEAP_TYPE_DMA), 0); - } - else { + } else { handle = ion_alloc(client, meson_gem_obj->base.size, 0, (1 << ION_HEAP_TYPE_SYSTEM), 0); bscatter = true; @@ -100,8 +100,6 @@ struct am_meson_gem_object *am_meson_gem_object_create( } size = roundup(size, PAGE_SIZE); - if (size == 0) - return ERR_PTR(-EINVAL); meson_gem_obj = kzalloc(sizeof(*meson_gem_obj), GFP_KERNEL); if (!meson_gem_obj) return ERR_PTR(-ENOMEM); @@ -415,10 +413,8 @@ struct sg_table *am_meson_gem_prime_get_sg_table( } return dst_table; } - else { - DRM_ERROR("Not support import buffer from other driver.\n"); - return NULL; - } + DRM_ERROR("Not support import buffer from other driver.\n"); + return NULL; } struct drm_gem_object *am_meson_gem_prime_import_sg_table( diff --git a/drivers/amlogic/drm/am_meson_gem.h b/drivers/amlogic/drm/meson_gem.h index f6dcc7e..212a6aa 100644 --- a/drivers/amlogic/drm/am_meson_gem.h +++ b/drivers/amlogic/drm/meson_gem.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_gem.h + * drivers/amlogic/drm/meson_gem.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -18,10 +18,10 @@ #ifndef __AM_MESON_GEM_H #define __AM_MESON_GEM_H #include <drm/drm_gem.h> -#include <linux/amlogic/meson_drm.h> +#include <uapi/drm/meson_drm.h> #include <ion/ion_priv.h> -#include "am_meson_drv.h" +#include "meson_drv.h" struct am_meson_gem_object { struct drm_gem_object base; diff --git a/drivers/amlogic/drm/am_meson_hdcp.c b/drivers/amlogic/drm/meson_hdcp.c index 3c45c26..ab098fb 100644 --- a/drivers/amlogic/drm/am_meson_hdcp.c +++ b/drivers/amlogic/drm/meson_hdcp.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_hdcp.c + * drivers/amlogic/drm/meson_hdcp.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -31,8 +31,8 @@ #include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h> #include <linux/arm-smccc.h> -#include "am_meson_hdmi.h" -#include "am_meson_hdcp.h" +#include "meson_hdmi.h" +#include "meson_hdcp.h" static int hdcp_topo_st = -1; static int hdmitx_hdcp_opr(unsigned int val) diff --git a/drivers/amlogic/drm/am_meson_hdcp.h b/drivers/amlogic/drm/meson_hdcp.h index f95d13f..9e4ede0 100644 --- a/drivers/amlogic/drm/am_meson_hdcp.h +++ b/drivers/amlogic/drm/meson_hdcp.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_hdcp.h + * drivers/amlogic/drm/meson_hdcp.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * diff --git a/drivers/amlogic/drm/am_meson_hdmi.c b/drivers/amlogic/drm/meson_hdmi.c index a2efd9c..896444a 100644 --- a/drivers/amlogic/drm/am_meson_hdmi.c +++ b/drivers/amlogic/drm/meson_hdmi.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_hdmi.c + * drivers/amlogic/drm/meson_hdmi.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,6 +14,7 @@ * more details. * */ + #include <drm/drm_modeset_helper.h> #include <drm/drmP.h> #include <drm/drm_edid.h> @@ -32,8 +33,8 @@ #include <linux/workqueue.h> #include <linux/amlogic/media/vout/vout_notify.h> #include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h> -#include "am_meson_hdmi.h" -#include "am_meson_hdcp.h" +#include "meson_hdmi.h" +#include "meson_hdcp.h" #define DEVICE_NAME "amhdmitx" struct am_hdmi_tx am_hdmi_info; @@ -77,11 +78,11 @@ char *am_meson_hdmi_get_voutmode(struct drm_display_mode *mode) int i; for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) { - if ((am_vout_modes[i].width == mode->hdisplay) - && (am_vout_modes[i].height == mode->vdisplay) - && (am_vout_modes[i].vrefresh == mode->vrefresh) - && (am_vout_modes[i].flags == - (mode->flags&DRM_MODE_FLAG_INTERLACE))) + if (am_vout_modes[i].width == mode->hdisplay && + am_vout_modes[i].height == mode->vdisplay && + am_vout_modes[i].vrefresh == mode->vrefresh && + am_vout_modes[i].flags == + (mode->flags & DRM_MODE_FLAG_INTERLACE)) return am_vout_modes[i].name; } return NULL; @@ -253,9 +254,9 @@ void am_hdmi_encoder_mode_set(struct drm_encoder *encoder, DRM_INFO("the hdmi mode vic : %d\n", am_hdmi->hdmi_info.vic); /* Store the display mode for plugin/DPMS poweron events */ memcpy(&am_hdmi->previous_mode, adjusted_mode, - sizeof(am_hdmi->previous_mode)); - if ((vic == 96) || (vic == 97) || (vic == 101) || (vic == 102) - || (vic == 106) || (vic == 107)) + sizeof(am_hdmi->previous_mode)); + if (vic == 96 || vic == 97 || vic == 101 || vic == 102 || + vic == 106 || vic == 107) setup_attr(attr2); else setup_attr(attr1); @@ -268,9 +269,9 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder) struct drm_connector_state *state = am_hdmi->connector.state; if (vmode == VMODE_HDMI) - DRM_INFO("am_hdmi_encoder_enable\n"); + DRM_INFO("enable\n"); else - DRM_INFO("am_hdmi_encoder_enable fail! vmode:%d\n", vmode); + DRM_INFO("enable fail! vmode:%d\n", vmode); vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode); set_vout_vmode(vmode); @@ -281,9 +282,11 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder) if (am_hdmi->hdcp_tx_type) { am_hdmi->hdcp_stop_flag = 0; am_hdmi->hdcp_work = kthread_run(am_hdcp_work, - (void *)am_hdmi, "kthread_hdcp_task"); - } else + (void *)am_hdmi, + "kthread_hdcp_task"); + } else { DRM_INFO("hdmitx doesn't has hdcp key\n"); + } } } @@ -344,7 +347,7 @@ static int am_hdmi_i2c_write(struct am_hdmi_tx *am_hdmi, i2c->slave_reg = buf[0]; length--; buf++; - i2c->is_regaddr = true; + i2c->is_regaddr = 1; } while (length--) { @@ -374,7 +377,7 @@ static int am_hdmi_i2c_read(struct am_hdmi_tx *am_hdmi, if (!i2c->is_regaddr) { dev_dbg(am_hdmi->dev, "set read register address to 0\n"); i2c->slave_reg = 0x00; - i2c->is_regaddr = true; + i2c->is_regaddr = 1; } while (length--) { @@ -396,7 +399,7 @@ static int am_hdmi_i2c_read(struct am_hdmi_tx *am_hdmi, *buf++ = hdmitx_rd_reg(HDMITX_DWC_I2CM_DATAI); } - i2c->is_segment = false; + i2c->is_segment = 0; return 0; } @@ -432,16 +435,16 @@ static int am_hdmi_i2c_xfer(struct i2c_adapter *adap, hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, addr); /* Set slave device register address on transfer */ - i2c->is_regaddr = false; + i2c->is_regaddr = 0; /* Set segment pointer for I2C extended read mode operation */ - i2c->is_segment = false; + i2c->is_segment = 0; for (i = 0; i < num; i++) { dev_dbg(am_hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n", i + 1, num, msgs[i].len, msgs[i].flags); if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) { - i2c->is_segment = true; + i2c->is_segment = 1; hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGADDR, DDC_SEGMENT_ADDR); hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGPTR, *msgs[i].buf); @@ -558,10 +561,10 @@ static int amhdmitx_get_dt_info(struct am_hdmi_tx *am_hdmi) hdcp_node = of_find_node_by_path("/drm-amhdmitx"); if (hdcp_node) { ret = of_property_read_string(hdcp_node, "hdcp", - (const char **)&(hdcp_status)); - if (ret) + (const char **)&(hdcp_status)); + if (ret) { DRM_INFO("not find hdcp_feature\n"); - else { + } else { if (memcmp(hdcp_status, "okay", 4) == 0) am_hdmi->hdcp_feature = 1; else diff --git a/drivers/amlogic/drm/am_meson_hdmi.h b/drivers/amlogic/drm/meson_hdmi.h index 37542dc..d4bea37 100644 --- a/drivers/amlogic/drm/am_meson_hdmi.h +++ b/drivers/amlogic/drm/meson_hdmi.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_hdmi.h + * drivers/amlogic/drm/meson_hdmi.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,18 +14,19 @@ * more details. * */ + #ifndef __AM_MESON_HDMI_H #define __AM_MESON_HDMI_H -#include "am_meson_drv.h" +#include "meson_drv.h" #define DDC_SEGMENT_ADDR 0x30 #define VIC_MAX_NUM 512 #define DRM_HDMITX_VER "20180705" struct am_hdmi_data { unsigned int vic; - bool sink_is_hdmi; - bool sink_has_audio; + u8 sink_is_hdmi; + u8 sink_has_audio; unsigned int colorimetry; unsigned int cd; /* cd8, cd10 or cd12 */ unsigned int cs; /* rgb, y444, y422, y420 */ @@ -45,8 +46,8 @@ struct am_hdmi_i2c { u8 segment_addr; u8 slave_reg; u8 stat; - bool is_regaddr; - bool is_segment; + u8 is_regaddr; + u8 is_segment; }; struct am_hdmi_tx { @@ -85,9 +86,9 @@ struct am_hdmi_tx { #define BASE_REG_OFFSET 24 #define HDMITX_SEC_REG_ADDR(reg) \ - ((HDMITX_SEC_REG_IDX << BASE_REG_OFFSET) + (reg << 2)) + ((HDMITX_SEC_REG_IDX << BASE_REG_OFFSET) + ((reg) << 2)) #define HDMITX_REG_ADDR(reg) \ - ((HDMITX_REG_IDX << BASE_REG_OFFSET) + (reg << 2)) + ((HDMITX_REG_IDX << BASE_REG_OFFSET) + ((reg) << 2)) /* TOP-level wrapper registers addresses * bit24: 1 means secure access diff --git a/drivers/amlogic/drm/am_meson_lcd.c b/drivers/amlogic/drm/meson_lcd.c index 462338f..89f6556 100644 --- a/drivers/amlogic/drm/am_meson_lcd.c +++ b/drivers/amlogic/drm/meson_lcd.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_lcd.c + * drivers/amlogic/drm/meson_lcd.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -26,7 +26,7 @@ #include <linux/amlogic/media/vout/lcd/lcd_vout.h> #include <linux/amlogic/media/vout/lcd/lcd_notify.h> -#include "am_meson_lcd.h" +#include "meson_lcd.h" struct am_drm_lcd_s { struct drm_panel panel; @@ -262,9 +262,9 @@ static void am_lcd_encoder_enable(struct drm_encoder *encoder) return; if (vmode == VMODE_LCD) - DRM_INFO("am_lcd_encoder_enable\n"); + DRM_INFO("enable\n"); else - DRM_INFO("am_lcd_encoder_enable fail! vmode:%d\n", vmode); + DRM_INFO("enable fail! vmode:%d\n", vmode); pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode); @@ -341,14 +341,10 @@ static int am_lcd_disable(struct drm_panel *panel) if (!lcd->lcd_drv) return -ENODEV; - pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); - mutex_lock(&lcd->lcd_drv->power_mutex); aml_lcd_notifier_call_chain(LCD_EVENT_DISABLE, NULL); mutex_unlock(&lcd->lcd_drv->power_mutex); - pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); - return 0; } @@ -361,14 +357,10 @@ static int am_lcd_unprepare(struct drm_panel *panel) if (!lcd->lcd_drv) return -ENODEV; - pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); - mutex_lock(&lcd->lcd_drv->power_mutex); aml_lcd_notifier_call_chain(LCD_EVENT_UNPREPARE, NULL); mutex_unlock(&lcd->lcd_drv->power_mutex); - pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); - return 0; } @@ -381,14 +373,10 @@ static int am_lcd_prepare(struct drm_panel *panel) if (!lcd->lcd_drv) return -ENODEV; - pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); - mutex_lock(&lcd->lcd_drv->power_mutex); aml_lcd_notifier_call_chain(LCD_EVENT_PREPARE, NULL); mutex_unlock(&lcd->lcd_drv->power_mutex); - pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); - return 0; } @@ -424,12 +412,8 @@ static int am_lcd_get_modes(struct drm_panel *panel) return 0; mode = drm_mode_duplicate(drm, lcd->mode); - if (!mode) { - pr_err("error: am_drm_lcd: failed to add mode %ux%u@%u\n", - mode->hdisplay, mode->vdisplay, mode->vrefresh); - } - - pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); + if (!mode) + return 0; mode->type |= DRM_MODE_TYPE_DRIVER; mode->type |= DRM_MODE_TYPE_PREFERRED; @@ -463,8 +447,6 @@ static int am_lcd_get_timings(struct drm_panel *panel, pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); - num_timings = 1; - if (timings) memcpy(&timings[0], lcd->timing, sizeof(struct display_timing)); @@ -685,8 +667,6 @@ static void am_meson_lcd_unbind(struct device *dev, struct device *master, drm_panel_remove(&am_drm_lcd->panel); pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__); - - return; } static const struct component_ops am_meson_lcd_ops = { diff --git a/drivers/amlogic/drm/am_meson_lcd.h b/drivers/amlogic/drm/meson_lcd.h index 565f8eb..32be56b 100644 --- a/drivers/amlogic/drm/am_meson_lcd.h +++ b/drivers/amlogic/drm/meson_lcd.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_lcd.h + * drivers/amlogic/drm/meson_lcd.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -18,7 +18,7 @@ #ifndef __AM_DRM_LCD_H #define __AM_DRM_LCD_H -#include "am_meson_drv.h" +#include "meson_drv.h" #endif diff --git a/drivers/amlogic/drm/meson_plane.c b/drivers/amlogic/drm/meson_plane.c new file mode 100644 index 0000000..4e84a69 --- a/dev/null +++ b/drivers/amlogic/drm/meson_plane.c @@ -0,0 +1,498 @@ +/* + * drivers/amlogic/drm/meson_plane.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "meson_plane.h" +#include "meson_crtc.h" +#include "meson_vpu.h" +#include "meson_drv.h" +#include "meson_vpu_pipeline.h" + +static const u32 supported_drm_formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBX8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_BGRA8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB565, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ARGB4444, +}; + +static u64 afbc_wb_modifier[] = { + DRM_FORMAT_MOD_MESON_AFBC_WB, + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + +static void meson_plane_position_calc( + struct meson_vpu_osd_layer_info *plane_info, + struct drm_plane_state *state, + struct drm_display_mode *mode) +{ + u32 dst_w, dst_h, src_w, src_h, scan_mode_out; + + scan_mode_out = mode->flags & DRM_MODE_FLAG_INTERLACE; + plane_info->src_x = state->src_x; + plane_info->src_y = state->src_y; + plane_info->src_w = (state->src_w >> 16) & 0xffff; + plane_info->src_h = (state->src_h >> 16) & 0xffff; + + plane_info->dst_x = state->crtc_x; + plane_info->dst_y = state->crtc_y; + plane_info->dst_w = state->crtc_w; + plane_info->dst_h = state->crtc_h; + if (scan_mode_out) { + plane_info->dst_y >>= 1; + plane_info->dst_h >>= 1; + } + /*negative position process*/ + if (state->crtc_x < 0) { + dst_w = state->crtc_w + state->crtc_x; + if (dst_w > 0) { + src_w = plane_info->src_w * dst_w / state->crtc_w; + plane_info->src_x = plane_info->src_w - src_w; + plane_info->src_w = src_w; + plane_info->dst_w = dst_w; + plane_info->dst_x = 0; + } else { + plane_info->enable = 0; + } + } + if (state->crtc_y < 0) { + dst_h = state->crtc_h + state->crtc_y; + if (dst_h > 0) { + src_h = plane_info->src_h * dst_h / state->crtc_h; + plane_info->src_y = plane_info->src_h - src_h; + plane_info->src_h = src_h; + plane_info->dst_h = dst_h; + plane_info->dst_y = 0; + } else { + plane_info->enable = 0; + } + } + /*overdisplay process*/ + if ((plane_info->dst_x + plane_info->dst_w) > mode->hdisplay) { + if (plane_info->dst_x >= mode->hdisplay) + plane_info->enable = 0; + else + plane_info->dst_w = + mode->hdisplay - plane_info->dst_x; + } + if ((plane_info->dst_y + plane_info->dst_h) > mode->vdisplay) { + if (plane_info->dst_y >= mode->vdisplay) + plane_info->enable = 0; + else + plane_info->dst_h = mode->vdisplay - plane_info->dst_y; + } +} + +static int +meson_plane_check_size_range(struct meson_vpu_osd_layer_info *plane_info) +{ + u32 dst_w, dst_h, src_w, src_h, ratio_x, ratio_y; + int ret; + + src_w = plane_info->src_w; + src_h = plane_info->src_h; + dst_w = plane_info->dst_w; + dst_h = plane_info->dst_h; + ratio_x = 0; + ratio_y = 0; + ret = 0; + + if (src_w > dst_w) + ratio_x = (src_w + dst_w - 1) / dst_w; + if (src_h > dst_h) + ratio_y = (src_h + dst_h - 1) / dst_h; + if (ratio_x > MESON_OSD_SCLAE_DOWN_LIMIT || + ratio_y > MESON_OSD_SCLAE_DOWN_LIMIT) + ret = -EDOM; + if (src_w < dst_w) + ratio_x = (dst_w + src_w - 1) / src_w; + if (src_h < dst_h) + ratio_y = (dst_h + src_h - 1) / src_h; + if (ratio_x > MESON_OSD_SCLAE_UP_LIMIT || + ratio_y > MESON_OSD_SCLAE_UP_LIMIT) + ret = -EDOM; + return ret; +} + +static int meson_plane_fb_check(struct drm_plane *plane, + struct drm_plane_state *new_state, + struct meson_vpu_osd_layer_info *plane_info) +{ + struct drm_framebuffer *fb = new_state->fb; + #ifdef CONFIG_DRM_MESON_USE_ION + struct am_osd_plane *osd_plane = to_am_osd_plane(plane); + struct meson_drm *drv = osd_plane->drv; + struct am_meson_fb *meson_fb; + #else + struct drm_gem_cma_object *gem; + #endif + dma_addr_t phyaddr; + + #ifdef CONFIG_DRM_MESON_USE_ION + meson_fb = container_of(fb, struct am_meson_fb, base); + if (!meson_fb) { + DRM_INFO("meson_fb is NULL!\n"); + return -EINVAL; + } + phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp); + if (meson_fb->bufp->bscatter) + DRM_ERROR("am_meson_plane meet a scatter framebuffer.\n"); + #else + if (!fb) { + DRM_INFO("fb is NULL!\n"); + return -EINVAL; + } + /* Update Canvas with buffer address */ + gem = drm_fb_cma_get_gem_obj(fb, 0); + if (!gem) { + DRM_INFO("gem is NULL!\n"); + return -EINVAL; + } + phyaddr = gem->paddr; + #endif + plane_info->phy_addr = phyaddr; + return 0; +} + +static int meson_plane_get_fb_info(struct drm_plane *plane, + struct drm_plane_state *new_state, + struct meson_vpu_osd_layer_info *plane_info) +{ + struct am_osd_plane *osd_plane = to_am_osd_plane(plane); + struct drm_framebuffer *fb = new_state->fb; + struct meson_drm *drv = osd_plane->drv; + #ifdef CONFIG_DRM_MESON_USE_ION + struct am_meson_fb *meson_fb; + #else + struct drm_gem_cma_object *gem; + #endif + dma_addr_t phyaddr; + + if (!drv) { + DRM_INFO("%s new_state/meson_drm is NULL!\n", __func__); + return -EINVAL; + } + if (osd_plane->plane_index >= MESON_MAX_OSDS) { + DRM_INFO("%s invalid plane_index!\n", __func__); + return -EINVAL; + } + + #ifdef CONFIG_DRM_MESON_USE_ION + meson_fb = container_of(fb, struct am_meson_fb, base); + if (!meson_fb) { + DRM_INFO("meson_fb is NULL!\n"); + return 0; + } + phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp); + if (meson_fb->bufp->bscatter) + DRM_ERROR("ERROR:am_meson_plane meet a scatter framebuffer.\n"); + #else + if (!fb) { + DRM_INFO("fb is NULL!\n"); + return -EINVAL; + } + /* Update Canvas with buffer address */ + gem = drm_fb_cma_get_gem_obj(fb, 0); + phyaddr = gem->paddr; + #endif + + plane_info->pixel_format = fb->pixel_format; + plane_info->phy_addr = phyaddr; + plane_info->byte_stride = fb->pitches[0]; + + /*setup afbc info*/ + switch (fb->modifier) { + case DRM_FORMAT_MOD_MESON_AFBC: + plane_info->afbc_en = 1; + plane_info->afbc_inter_format = AFBC_EN; + break; + case DRM_FORMAT_MOD_MESON_AFBC_WB: + plane_info->afbc_en = 1; + plane_info->afbc_inter_format = AFBC_EN | + YUV_TRANSFORM | BLOCK_SPLIT | + SUPER_BLOCK_ASPECT; + break; + case DRM_FORMAT_MOD_INVALID: + case DRM_FORMAT_MOD_LINEAR: + default: + plane_info->afbc_en = 0; + plane_info->afbc_inter_format = 0; + break; + }; + + DRM_DEBUG("flags:%d pixel_format:%d,modifer=%llu\n", + fb->flags, fb->pixel_format, + fb->modifier); + DRM_DEBUG("plane afbc_en=%u, afbc_inter_format=%x\n", + plane_info->afbc_en, plane_info->afbc_inter_format); + + DRM_DEBUG("phy_addr=0x%x,byte_stride=%d,pixel_format=%d\n", + plane_info->phy_addr, plane_info->byte_stride, + plane_info->pixel_format); + DRM_DEBUG("plane_index %d.\n", osd_plane->plane_index); + return 0; +} + +static int meson_plane_atomic_get_property(struct drm_plane *plane, + const struct drm_plane_state *state, + struct drm_property *property, + uint64_t *val) +{ + return 0; +} + +static int meson_plane_atomic_set_property(struct drm_plane *plane, + struct drm_plane_state *state, + struct drm_property *property, + uint64_t val) +{ + return 0; +} + +static struct drm_plane_state * +meson_plane_duplicate_state(struct drm_plane *plane) +{ + struct am_meson_plane_state *meson_plane_state, *old_plane_state; + + if (WARN_ON(!plane->state)) + return NULL; + + old_plane_state = to_am_meson_plane_state(plane->state); + meson_plane_state = kmemdup(old_plane_state, + sizeof(*meson_plane_state), GFP_KERNEL); + if (!meson_plane_state) + return NULL; + + __drm_atomic_helper_plane_duplicate_state(plane, + &meson_plane_state->base); + + return &meson_plane_state->base; +} + +static void meson_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct am_meson_plane_state *amps; + + amps = to_am_meson_plane_state(state); + __drm_atomic_helper_plane_destroy_state(state); + kfree(amps); +} + +bool am_meson_vpu_check_format_mod(struct drm_plane *plane, + u32 format, u64 modifier) +{ + bool ret = false; + + switch (modifier) { + case DRM_FORMAT_MOD_LINEAR: + ret = true; + break; + case DRM_FORMAT_MOD_MESON_AFBC: + if (osd_meson_dev.afbc_type == MESON_AFBC && + plane->type == DRM_PLANE_TYPE_PRIMARY) + ret = true; + break; + case DRM_FORMAT_MOD_MESON_AFBC_WB: + if (osd_meson_dev.afbc_type == MALI_AFBC && + plane->type == DRM_PLANE_TYPE_PRIMARY) { + if (format == DRM_FORMAT_BGR565) + ret = false; + else + ret = true; + } + break; + }; + + DRM_DEBUG("modifier %llu return %d", + modifier, ret); + return ret; +} + +static const struct drm_plane_funcs am_osd_plane_funs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = meson_plane_duplicate_state, + .atomic_destroy_state = meson_plane_destroy_state, + .atomic_set_property = meson_plane_atomic_set_property, + .atomic_get_property = meson_plane_atomic_get_property, + .format_mod_supported = am_meson_vpu_check_format_mod, +}; + +static int meson_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + return 0; +} + +static void meson_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct am_osd_plane *osd_plane = to_am_osd_plane(plane); + + DRM_DEBUG("%s osd %d.\n", __func__, osd_plane->plane_index); +} + +static void meson_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + DRM_DEBUG("plane atomic_update.\n"); +} + +static int meson_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct meson_vpu_osd_layer_info *plane_info; + struct meson_vpu_pipeline_state *mvps; + struct am_osd_plane *osd_plane = to_am_osd_plane(plane); + struct meson_drm *drv = osd_plane->drv; + int ret; + + if (!state || !drv) { + DRM_INFO("%s state/meson_drm is NULL!\n", __func__); + return -EINVAL; + } + mvps = meson_vpu_pipeline_get_state(drv->pipeline, state->state); + if (!mvps || osd_plane->plane_index >= MESON_MAX_OSDS) { + DRM_INFO("%s mvps/osd_plane is NULL!\n", __func__); + return -EINVAL; + } + plane_info = &mvps->plane_info[osd_plane->plane_index]; + plane_info->plane_index = osd_plane->plane_index; + plane_info->zorder = state->zpos; + + mvps->plane_index[osd_plane->plane_index] = osd_plane->plane_index; + meson_plane_position_calc(plane_info, state, &mvps->pipeline->mode); + ret = meson_plane_check_size_range(plane_info); + if (ret < 0) { + plane_info->enable = 0; + DRM_INFO("plane%d size check unsupport!!!\n", + plane_info->plane_index); + return ret; + } + ret = meson_plane_fb_check(plane, state, plane_info); + if (ret < 0) { + plane_info->enable = 0; + DRM_DEBUG("plane%d fb is NULL,disable the plane!\n", + plane_info->plane_index); + return 0; + } + ret = meson_plane_get_fb_info(plane, state, plane_info); + if (ret < 0 || plane_info->src_w > MESON_OSD_INPUT_W_LIMIT || + plane_info->src_w == 0) { + plane_info->enable = 0; + return ret; + } + + plane_info->enable = 1; + DRM_DEBUG("index=%d, zorder=%d\n", + plane_info->plane_index, plane_info->zorder); + DRM_DEBUG("src_x/y/w/h=%d/%d/%d/%d\n", + plane_info->src_x, plane_info->src_y, + plane_info->src_w, plane_info->src_h); + DRM_DEBUG("dst_x/y/w/h=%d/%d/%d/%d\n", + plane_info->dst_x, plane_info->dst_y, + plane_info->dst_w, plane_info->dst_h); + return 0; +} + +static void meson_plane_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct am_osd_plane *osd_plane = to_am_osd_plane(plane); + + DRM_DEBUG("%s osd %d.\n", __func__, osd_plane->plane_index); +} + +static const struct drm_plane_helper_funcs am_osd_helper_funcs = { + .prepare_fb = meson_plane_prepare_fb, + .cleanup_fb = meson_plane_cleanup_fb, + .atomic_update = meson_plane_atomic_update, + .atomic_check = meson_plane_atomic_check, + .atomic_disable = meson_plane_atomic_disable, +}; + +static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i) +{ + struct am_osd_plane *osd_plane; + struct drm_plane *plane; + u32 type = 0; + char plane_name[8]; + const u64 *format_modifiers = afbc_wb_modifier; + + osd_plane = devm_kzalloc(priv->drm->dev, sizeof(*osd_plane), + GFP_KERNEL); + if (!osd_plane) + return 0; + + if (i == 0) + type = DRM_PLANE_TYPE_PRIMARY; + else + type = DRM_PLANE_TYPE_OVERLAY; + + osd_plane->drv = priv; + osd_plane->plane_index = i; + + plane = &osd_plane->base; + sprintf(plane_name, "osd%d", i); + + drm_universal_plane_init(priv->drm, plane, 0xFF, + &am_osd_plane_funs, + supported_drm_formats, + ARRAY_SIZE(supported_drm_formats), + format_modifiers, + type, plane_name); + + drm_plane_helper_add(plane, &am_osd_helper_funcs); + osd_drm_debugfs_add(&osd_plane->plane_debugfs_dir, + plane_name, osd_plane->plane_index); + return osd_plane; +} + +int am_meson_plane_create(struct meson_drm *priv) +{ + struct am_osd_plane *plane; + struct meson_vpu_pipeline *pipeline = priv->pipeline; + int i, osd_index; + + + for (i = 0; i < pipeline->num_osds; i++) { + osd_index = pipeline->osds[i]->base.index; + plane = am_plane_create(priv, osd_index); + + if (!plane) + return -ENOMEM; + + if (i == 0) + priv->primary_plane = &plane->base; + + priv->planes[priv->num_planes++] = plane; + } + + DRM_DEBUG("%s. enter\n", __func__); + + return 0; +} diff --git a/drivers/amlogic/drm/meson_plane.h b/drivers/amlogic/drm/meson_plane.h new file mode 100644 index 0000000..a1e6f4b --- a/dev/null +++ b/drivers/amlogic/drm/meson_plane.h @@ -0,0 +1,50 @@ +/* + * drivers/amlogic/drm/meson_plane.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __MESON_PLANE_H +#define __MESON_PLANE_H + +#include <linux/kernel.h> +#include <drm/drmP.h> +#include <drm/drm_plane.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <linux/amlogic/media/vout/vout_notify.h> + +#include "osd.h" +#include "osd_drm.h" +#include "meson_fb.h" + +struct am_meson_plane_state { + struct drm_plane_state base; +}; + +struct am_osd_plane { + struct drm_plane base; //must be first element. + struct meson_drm *drv; //point to struct parent. + struct dentry *plane_debugfs_dir; + int plane_index; +}; + +#define to_am_osd_plane(x) container_of(x, \ + struct am_osd_plane, base) +#define to_am_meson_plane_state(x) container_of(x, \ + struct am_meson_plane_state, base) + +int am_meson_plane_create(struct meson_drm *priv); + +#endif diff --git a/drivers/amlogic/drm/meson_vpu.c b/drivers/amlogic/drm/meson_vpu.c new file mode 100644 index 0000000..31ea494 --- a/dev/null +++ b/drivers/amlogic/drm/meson_vpu.c @@ -0,0 +1,573 @@ +/* + * drivers/amlogic/drm/meson_vpu.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include <drm/drmP.h> +#include <drm/drm_plane.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_gem_cma_helper.h> + +#include <linux/platform_device.h> +#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/component.h> +#include <linux/of_reserved_mem.h> +#include <linux/dma-contiguous.h> +#include <linux/cma.h> +#ifdef CONFIG_DRM_MESON_USE_ION +#include <ion/ion_priv.h> +#endif + +/* Amlogic Headers */ +#include <linux/amlogic/media/vout/vout_notify.h> +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT +#include <linux/amlogic/media/amvecm/amvecm.h> +#endif +#include "osd.h" +#include "osd_drm.h" +#ifdef CONFIG_DRM_MESON_USE_ION +#include "meson_fb.h" +#endif +#include "meson_vpu.h" +#include "meson_plane.h" +#include "meson_crtc.h" +#include "meson_vpu_pipeline.h" + +struct vpu_device_data_s { + enum cpuid_type_e cpu_id; + enum osd_ver_e osd_ver; + enum osd_afbc_e afbc_type; + u8 osd_count; + u8 has_deband; + u8 has_lut; + u8 has_rdma; + u8 osd_fifo_len; + u32 vpp_fifo_len; + u32 dummy_data; + u32 has_viu2; + u32 viu1_osd_count; + struct clk *vpu_clkc; +}; + +static struct am_vout_mode am_vout_modes[] = { + { "1080p60hz", VMODE_HDMI, 1920, 1080, 60, 0}, + { "1080p30hz", VMODE_HDMI, 1920, 1080, 30, 0}, + { "1080p50hz", VMODE_HDMI, 1920, 1080, 50, 0}, + { "1080p25hz", VMODE_HDMI, 1920, 1080, 25, 0}, + { "1080p24hz", VMODE_HDMI, 1920, 1080, 24, 0}, + { "2160p30hz", VMODE_HDMI, 3840, 2160, 30, 0}, + { "2160p60hz", VMODE_HDMI, 3840, 2160, 60, 0}, + { "2160p50hz", VMODE_HDMI, 3840, 2160, 50, 0}, + { "2160p25hz", VMODE_HDMI, 3840, 2160, 25, 0}, + { "2160p24hz", VMODE_HDMI, 3840, 2160, 24, 0}, + { "1080i60hz", VMODE_HDMI, 1920, 1080, 60, DRM_MODE_FLAG_INTERLACE}, + { "1080i50hz", VMODE_HDMI, 1920, 1080, 50, DRM_MODE_FLAG_INTERLACE}, + { "720p60hz", VMODE_HDMI, 1280, 720, 60, 0}, + { "720p50hz", VMODE_HDMI, 1280, 720, 50, 0}, + { "480p60hz", VMODE_HDMI, 720, 480, 60, 0}, + { "480i60hz", VMODE_HDMI, 720, 480, 60, DRM_MODE_FLAG_INTERLACE}, + { "576p50hz", VMODE_HDMI, 720, 576, 50, 0}, + { "576i50hz", VMODE_HDMI, 720, 576, 50, DRM_MODE_FLAG_INTERLACE}, + { "480p60hz", VMODE_HDMI, 720, 480, 60, 0}, +}; + + +static struct osd_device_data_s osd_gxbb = { + .cpu_id = __MESON_CPU_MAJOR_ID_GXBB, + .osd_ver = OSD_NORMAL, + .afbc_type = NO_AFBC, + .osd_count = 2, + .has_deband = 0, + .has_lut = 0, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 32, + .vpp_fifo_len = 0x77f, + .dummy_data = 0x00808000, + .has_viu2 = 0, +}; + +static struct osd_device_data_s osd_gxl = { + .cpu_id = __MESON_CPU_MAJOR_ID_GXL, + .osd_ver = OSD_NORMAL, + .afbc_type = NO_AFBC, + .osd_count = 2, + .has_deband = 0, + .has_lut = 0, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 32, + .vpp_fifo_len = 0x77f, + .dummy_data = 0x00808000, + .has_viu2 = 0, +}; + +static struct osd_device_data_s osd_gxm = { + .cpu_id = __MESON_CPU_MAJOR_ID_GXM, + .osd_ver = OSD_NORMAL, + .afbc_type = MESON_AFBC, + .osd_count = 2, + .has_deband = 0, + .has_lut = 0, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 32, + .vpp_fifo_len = 0xfff, + .dummy_data = 0x00202000,/* dummy data is different */ + .has_viu2 = 0, +}; + +static struct osd_device_data_s osd_txl = { + .cpu_id = __MESON_CPU_MAJOR_ID_TXL, + .osd_ver = OSD_NORMAL, + .afbc_type = NO_AFBC, + .osd_count = 2, + .has_deband = 0, + .has_lut = 0, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 64, + .vpp_fifo_len = 0x77f, + .dummy_data = 0x00808000, + .has_viu2 = 0, +}; + +static struct osd_device_data_s osd_txlx = { + .cpu_id = __MESON_CPU_MAJOR_ID_TXLX, + .osd_ver = OSD_NORMAL, + .afbc_type = NO_AFBC, + .osd_count = 2, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 1, + .has_dolby_vision = 1, + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0x77f, + .dummy_data = 0x00808000, + .has_viu2 = 0, +}; + +static struct osd_device_data_s osd_axg = { + .cpu_id = __MESON_CPU_MAJOR_ID_AXG, + .osd_ver = OSD_SIMPLE, + .afbc_type = NO_AFBC, + .osd_count = 1, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 0, + .has_dolby_vision = 0, + /* use iomap its self, no rdma, no canvas, no freescale */ + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0x400, + .dummy_data = 0x00808000, + .has_viu2 = 0, +}; + +static struct osd_device_data_s osd_g12a = { + .cpu_id = __MESON_CPU_MAJOR_ID_G12A, + .osd_ver = OSD_HIGH_ONE, + .afbc_type = MALI_AFBC, + .osd_count = 4, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0xfff,/* 2048 */ + .dummy_data = 0x00808000, + .has_viu2 = 1, +}; + +static struct osd_device_data_s osd_g12b = { + .cpu_id = __MESON_CPU_MAJOR_ID_G12B, + .osd_ver = OSD_HIGH_ONE, + .afbc_type = MALI_AFBC, + .osd_count = 4, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0xfff,/* 2048 */ + .dummy_data = 0x00808000, + .has_viu2 = 1, +}; + +struct osd_device_data_s osd_meson_dev; +static u32 logo_memsize; +static struct page *logo_page; +static struct delayed_work osd_dwork; +static struct platform_device *gp_dev; +static unsigned long gem_mem_start, gem_mem_size; + +int am_meson_crtc_dts_info_set(const void *dt_match_data) +{ + struct osd_device_data_s *osd_meson; + + osd_meson = (struct osd_device_data_s *)dt_match_data; + if (osd_meson) { + memcpy(&osd_meson_dev, osd_meson, + sizeof(struct osd_device_data_s)); + osd_meson_dev.viu1_osd_count = osd_meson_dev.osd_count; + if (osd_meson_dev.has_viu2) { + /* set viu1 osd count */ + osd_meson_dev.viu1_osd_count--; + osd_meson_dev.viu2_index = osd_meson_dev.viu1_osd_count; + } + } else { + DRM_ERROR("%s data NOT match\n", __func__); + return -1; + } + + return 0; +} + +static int am_meson_crtc_loader_protect(struct drm_crtc *crtc, bool on) +{ + struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc); + + DRM_INFO("%s %d\n", __func__, on); + + if (on) { + enable_irq(amcrtc->vblank_irq); + drm_crtc_vblank_on(crtc); + } else { + disable_irq(amcrtc->vblank_irq); + drm_crtc_vblank_off(crtc); + } + + return 0; +} + +static int am_meson_crtc_enable_vblank(struct drm_crtc *crtc) +{ + unsigned long flags; + struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc); + + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + amcrtc->vblank_enable = true; + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); + + return 0; +} + +static void am_meson_crtc_disable_vblank(struct drm_crtc *crtc) +{ + unsigned long flags; + struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc); + + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + amcrtc->vblank_enable = false; + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); +} + +const struct meson_crtc_funcs meson_private_crtc_funcs = { + .loader_protect = am_meson_crtc_loader_protect, + .enable_vblank = am_meson_crtc_enable_vblank, + .disable_vblank = am_meson_crtc_disable_vblank, +}; + +char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode) +{ + int i; + + if (!strcmp(mode->name, "panel")) + return "panel"; + + for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) { + if (am_vout_modes[i].width == mode->hdisplay && + am_vout_modes[i].height == mode->vdisplay && + am_vout_modes[i].vrefresh == mode->vrefresh && + am_vout_modes[i].flags == + (mode->flags & DRM_MODE_FLAG_INTERLACE)) + return am_vout_modes[i].name; + } + return NULL; +} + +void am_meson_crtc_handle_vsync(struct am_meson_crtc *amcrtc) +{ + unsigned long flags; + struct drm_crtc *crtc; + + crtc = &amcrtc->base; + drm_crtc_handle_vblank(crtc); + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + if (amcrtc->event) { + drm_crtc_send_vblank_event(crtc, amcrtc->event); + drm_crtc_vblank_put(crtc); + amcrtc->event = NULL; + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); +} + +void am_meson_crtc_irq(struct meson_drm *priv) +{ + unsigned long flags; + struct am_meson_crtc *amcrtc = to_am_meson_crtc(priv->crtc); + + spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags); + if (amcrtc->vblank_enable) { + osd_drm_vsync_isr_handler(); + am_meson_crtc_handle_vsync(amcrtc); + } + spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags); +} + +static irqreturn_t am_meson_vpu_irq(int irq, void *arg) +{ + struct drm_device *dev = arg; + struct meson_drm *priv = dev->dev_private; + + am_meson_crtc_irq(priv); + + return IRQ_HANDLED; +} + +static void mem_free_work(struct work_struct *work) +{ + if (logo_memsize > 0) { +#ifdef CONFIG_CMA + pr_info("%s, free memory: addr:0x%x\n", + __func__, logo_memsize); + + dma_release_from_contiguous(&gp_dev->dev, + logo_page, + logo_memsize >> PAGE_SHIFT); +#endif + } +} + +static int am_meson_vpu_bind(struct device *dev, + struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm_dev = data; + struct meson_drm *private = drm_dev->dev_private; + struct meson_vpu_pipeline *pipeline = private->pipeline; + struct am_meson_crtc *amcrtc; +#ifdef CONFIG_CMA + struct cma *cma; +#endif + int ret, irq; + + /* Allocate crtc struct */ + DRM_DEBUG("%s\n", __func__); + pr_info("[%s] in\n", __func__); + amcrtc = devm_kzalloc(dev, sizeof(*amcrtc), + GFP_KERNEL); + if (!amcrtc) + return -ENOMEM; + + amcrtc->priv = private; + amcrtc->dev = dev; + amcrtc->drm_dev = drm_dev; + + dev_set_drvdata(dev, amcrtc); + + /* init reserved memory */ + ret = of_reserved_mem_device_init(&pdev->dev); + if (ret != 0) { + dev_err(dev, "failed to init reserved memory\n"); +#ifdef CONFIG_CMA + gp_dev = pdev; + cma = dev_get_cma_area(&pdev->dev); + if (cma) { + logo_memsize = cma_get_size(cma); + pr_info("reserved memory base:0x%x, size:0x%x\n", + (u32)cma_get_base(cma), logo_memsize); + if (logo_memsize > 0) { + logo_page = + dma_alloc_from_contiguous(&pdev->dev, + logo_memsize >> + PAGE_SHIFT, + 0); + if (!logo_page) { + pr_err("allocate buffer failed:%d\n", + logo_memsize); + } + } + } else { + pr_info("------ NO CMA\n"); + } +#endif + } else { + dma_declare_coherent_memory(drm_dev->dev, gem_mem_start, + gem_mem_start, gem_mem_size, + DMA_MEMORY_EXCLUSIVE); + pr_info("meson drm mem_start = 0x%x, size = 0x%x\n", + (u32)gem_mem_start, (u32)gem_mem_size); + } + + ret = am_meson_plane_create(private); + if (ret) + return ret; + + ret = am_meson_crtc_create(amcrtc); + if (ret) + return ret; + + am_meson_register_crtc_funcs(private->crtc, &meson_private_crtc_funcs); + + ret = of_property_read_u8(dev->of_node, + "osd_ver", &pipeline->osd_version); + vpu_pipeline_init(pipeline); + + /*vsync irq.*/ + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "cannot find irq for vpu\n"); + return irq; + } + amcrtc->vblank_irq = (unsigned int)irq; + + spin_lock_init(&amcrtc->vblank_irq_lock); + amcrtc->vblank_enable = false; + + ret = devm_request_irq(dev, amcrtc->vblank_irq, am_meson_vpu_irq, + IRQF_SHARED, dev_name(dev), drm_dev); + if (ret) + return ret; + + disable_irq(amcrtc->vblank_irq); + + INIT_DELAYED_WORK(&osd_dwork, mem_free_work); + schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000)); + pr_info("[%s] out\n", __func__); + return 0; +} + +static void am_meson_vpu_unbind(struct device *dev, + struct device *master, void *data) +{ + struct drm_device *drm_dev = data; + struct meson_drm *private = drm_dev->dev_private; + + am_meson_unregister_crtc_funcs(private->crtc); +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT + amvecm_drm_gamma_disable(0); + am_meson_ctm_disable(); +#endif + osd_drm_debugfs_exit(); +} + +static const struct component_ops am_meson_vpu_component_ops = { + .bind = am_meson_vpu_bind, + .unbind = am_meson_vpu_unbind, +}; + +static const struct of_device_id am_meson_vpu_driver_dt_match[] = { + { .compatible = "amlogic,meson-gxbb-vpu", + .data = &osd_gxbb, }, + { .compatible = "amlogic,meson-gxl-vpu", + .data = &osd_gxl, }, + { .compatible = "amlogic,meson-gxm-vpu", + .data = &osd_gxm, }, + { .compatible = "amlogic,meson-txl-vpu", + .data = &osd_txl, }, + { .compatible = "amlogic,meson-txlx-vpu", + .data = &osd_txlx, }, + { .compatible = "amlogic,meson-axg-vpu", + .data = &osd_axg, }, + { .compatible = "amlogic,meson-g12a-vpu", + .data = &osd_g12a, }, + { .compatible = "amlogic,meson-g12b-vpu", + .data = &osd_g12b, }, + {}, +}; + +MODULE_DEVICE_TABLE(of, am_meson_vpu_driver_dt_match); + +static int am_meson_vpu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const void *vpu_data; + int ret; + + pr_info("[%s] in\n", __func__); + if (!dev->of_node) { + dev_err(dev, "can't find vpu devices\n"); + return -ENODEV; + } + + vpu_data = of_device_get_match_data(dev); + if (vpu_data) { + ret = am_meson_crtc_dts_info_set(vpu_data); + if (ret < 0) + return -ENODEV; + } else { + dev_err(dev, "%s NOT match\n", __func__); + return -ENODEV; + } + pr_info("[%s] out\n", __func__); + return component_add(dev, &am_meson_vpu_component_ops); +} + +static int am_meson_vpu_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &am_meson_vpu_component_ops); + + return 0; +} + +static struct platform_driver am_meson_vpu_platform_driver = { + .probe = am_meson_vpu_probe, + .remove = am_meson_vpu_remove, + .driver = { + .name = "meson-vpu", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(am_meson_vpu_driver_dt_match), + }, +}; + +static int gem_mem_device_init(struct reserved_mem *rmem, struct device *dev) +{ + s32 ret = 0; + + if (!rmem) { + pr_info("Can't get reverse mem!\n"); + ret = -EFAULT; + return ret; + } + gem_mem_start = rmem->base; + gem_mem_size = rmem->size; + pr_info("init gem memsource addr:0x%x size:0x%x\n", + (u32)gem_mem_start, (u32)gem_mem_size); + + return 0; +} + +static const struct reserved_mem_ops rmem_gem_ops = { + .device_init = gem_mem_device_init, +}; + +static int __init gem_mem_setup(struct reserved_mem *rmem) +{ + rmem->ops = &rmem_gem_ops; + pr_info("gem mem setup\n"); + return 0; +} + +RESERVEDMEM_OF_DECLARE(gem, "amlogic, gem_memory", gem_mem_setup); + +module_platform_driver(am_meson_vpu_platform_driver); + +MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>"); +MODULE_DESCRIPTION("Amlogic Meson Drm VPU driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/drm/am_meson_vpu.h b/drivers/amlogic/drm/meson_vpu.h index 03adbbe..e288a33 100644 --- a/drivers/amlogic/drm/am_meson_vpu.h +++ b/drivers/amlogic/drm/meson_vpu.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_vpu.h + * drivers/amlogic/drm/meson_vpu.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,11 +14,24 @@ * more details. * */ + #ifndef __AM_MESON_VPU_H #define __AM_MESON_VPU_H +#include <linux/amlogic/media/vout/vout_notify.h> + struct am_meson_vpu_data { - uint32_t version; + u32 version; }; +struct am_vout_mode { + char name[DRM_DISPLAY_MODE_LEN]; + enum vmode_e mode; + int width, height, vrefresh; + unsigned int flags; +}; + +extern struct osd_device_data_s osd_meson_dev; +char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode); + #endif /* __AM_MESON_VPU_H */ diff --git a/drivers/amlogic/drm/meson_vpu_pipeline.c b/drivers/amlogic/drm/meson_vpu_pipeline.c new file mode 100644 index 0000000..aef3b8d --- a/dev/null +++ b/drivers/amlogic/drm/meson_vpu_pipeline.c @@ -0,0 +1,410 @@ +/* + * drivers/amlogic/drm/meson_vpu_pipeline.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/of_device.h> +#include <linux/slab.h> +#include <dt-bindings/display/meson-drm-ids.h> + +#include "meson_vpu_pipeline.h" +#include "meson_drv.h" + +#define MAX_LINKS 5 +#define MAX_PORTS 6 +#define MAX_PORT_ID 32 + +static struct meson_vpu_block **vpu_blocks; +static int num_blocks; + +struct meson_vpu_link_para { + u8 id; + u8 port; +}; + +struct meson_vpu_block_para { + char *name; + u8 id; + u8 index; + u8 type; + u8 num_inputs; + u8 num_outputs; + struct meson_vpu_link_para inputs[MESON_BLOCK_MAX_INPUTS]; + struct meson_vpu_link_para outputs[MESON_BLOCK_MAX_OUTPUTS]; + u64 inputs_mask; + u64 outputs_mask; +}; + +static struct meson_vpu_block *create_block(size_t blk_sz, + struct meson_vpu_block_para *para, + struct meson_vpu_block_ops *ops, + struct meson_vpu_pipeline *pipeline) +{ + struct meson_vpu_block *mvb; + int i; + + mvb = kzalloc(blk_sz, GFP_KERNEL); + if (!mvb) + return NULL; + + snprintf(mvb->name, MESON_BLOCK_MAX_NAME_LEN, "%s", para->name); + mvb->id = para->id; + mvb->type = para->type; + mvb->index = para->index; + mvb->avail_inputs = para->num_inputs; + mvb->avail_outputs = para->num_outputs; + mvb->max_inputs = para->num_inputs * 2; + mvb->max_outputs = para->num_outputs * 2; + mvb->inputs_mask = para->inputs_mask; + mvb->outputs_mask = para->outputs_mask; + + for (i = 0; i < mvb->avail_inputs; i++) { + mvb->inputs[i].port = para->inputs[i].port; + mvb->inputs[i].id = para->inputs[i].id; + mvb->inputs[i].edges_active = 1; + mvb->inputs[i].edges_visited = 0; + } + + for (i = 0; i < mvb->avail_outputs; i++) { + mvb->outputs[i].port = para->outputs[i].port; + mvb->outputs[i].id = para->outputs[i].id; + mvb->outputs[i].edges_active = 1; + mvb->outputs[i].edges_visited = 0; + } + + mvb->ops = ops; + mvb->pipeline = pipeline; + + return mvb; +} + +static void parse_vpu_node(struct device_node *child_node, + struct meson_vpu_block_para *para) +{ + int i, j, ret, size; + u8 id; + struct device_node *link; + const __be32 *list, *phandle; + u64 in_mask, out_mask; + + in_mask = 0; + out_mask = 0; + ret = of_property_read_u8(child_node, "id", ¶->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); diff --git a/drivers/amlogic/drm/meson_vpu_pipeline.h b/drivers/amlogic/drm/meson_vpu_pipeline.h new file mode 100644 index 0000000..258f8e9 --- a/dev/null +++ b/drivers/amlogic/drm/meson_vpu_pipeline.h @@ -0,0 +1,451 @@ +/* + * drivers/amlogic/drm/meson_vpu_pipeline.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __MESON_VPU_TOPOLOGY_H +#define __MESON_VPU_TOPOLOGY_H + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <dt-bindings/display/meson-drm-ids.h> +#include "meson_vpu_reg.h" +#include "meson_drv.h" +#include "meson_vpu_util.h" + +#define MESON_OSD1 0 +#define MESON_OSD2 1 +#define MESON_OSD3 2 +#define MESON_MAX_OSDS 4 +#define MESON_MAX_OSD_BLEND 3 +#define MESON_MAX_OSD_TO_VPP 2 +#define MESON_MAX_SCALERS 4 +#define MESON_MAX_VIDEO 2 +#define MESON_MAX_BLOCKS 32 +#define MESON_BLOCK_MAX_INPUTS 6 +#define MESON_BLOCK_MAX_OUTPUTS 3 +#define MESON_BLOCK_MAX_NAME_LEN 32 +/*ratio base for scaler calc;maybe need bigger than 1000*/ +#define RATIO_BASE 1000 +#define MESON_OSD_INPUT_W_LIMIT 1920 + +#define MAX_DIN_NUM 4 +#define MAX_DOUT_NUM 2 + +#define MAX_DFS_PATH_NUM 2 +/* + *according to reg description,scale down limit shold be 4bits=16 + *but test result is 10,it will display abnormal if bigger than 10.xx + *have not get more info from others,so config it as 10 right now. + *Todo:if you make sure and test okay,you can rechange it. + */ +#define MESON_OSD_SCLAE_DOWN_LIMIT 10 +#define MESON_OSD_SCLAE_UP_LIMIT ((1 << 24) - 1) +/* + *MESON_DRM_VERSION_V0:support modetest and atomictest, + *backup last commit state + *MESON_DRM_VERSION_V1:support atomictest, + *don't support modetest,don't backup last commit state + */ +#define MESON_DRM_VERSION_V0 0 + +#define SCALER_RATIO_X_CALC_DONE BIT(0) +#define SCALER_RATIO_Y_CALC_DONE BIT(1) +#define SCALER_IN_W_CALC_DONE BIT(2) +#define SCALER_IN_H_CALC_DONE BIT(3) +#define SCALER_OUT_W_CALC_DONE BIT(4) +#define SCALER_OUT_H_CALC_DONE BIT(5) + +#define SCALER_INPUT_WIDTH_CHANGED BIT(0) +#define SCALER_INPUT_HEIGHT_CHANGED BIT(1) +#define SCALER_OUTPUT_WIDTH_CHANGED BIT(2) +#define SCALER_OUTPUT_HEIGHT_CHANGED BIT(3) +#define SCALER_OUTPUT_SCAN_MODE_CHANGED BIT(4) + +enum meson_vpu_blk_type { + MESON_BLK_OSD = 0, + MESON_BLK_AFBC, + MESON_BLK_SCALER, + MESON_BLK_OSDBLEND, + MESON_BLK_HDR, + MESON_BLK_DOVI, + MESON_BLK_VPPBLEND, +}; + +struct meson_vpu_pipeline; +struct meson_vpu_block; +struct meson_vpu_block_state; +struct meson_vpu_pipeline_state; + +/* vpu block ops */ +struct meson_vpu_block_ops { + int (*check_state)(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state, + struct meson_vpu_pipeline_state *mvps); + void (*update_state)(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state); + void (*enable)(struct meson_vpu_block *vblk); + void (*disable)(struct meson_vpu_block *vblk); + void (*init)(struct meson_vpu_block *vblk); +}; + +struct meson_vpu_block_link { + struct meson_vpu_block *link; + u8 id; + u8 port; + int edges_active; + int edges_visited; +}; + +/* vpu block */ +struct meson_vpu_block { + struct drm_private_obj obj; + char name[MESON_BLOCK_MAX_NAME_LEN]; + + enum meson_vpu_blk_type type; + u8 id; + u8 index; + u8 max_inputs; + u8 max_outputs; + u8 avail_inputs; + u8 avail_outputs; + unsigned long inputs_mask; + unsigned long outputs_mask; + struct meson_vpu_block_link inputs[MESON_BLOCK_MAX_INPUTS]; + struct meson_vpu_block_link outputs[MESON_BLOCK_MAX_OUTPUTS]; + struct meson_vpu_block_ops *ops; + struct meson_vpu_pipeline *pipeline; +}; + +struct meson_vpu_block_state { + struct drm_private_state obj; + struct meson_vpu_block *pblk; + u32 inputs_mask; + + u32 inputs_changed; + u32 outputs_changed; + u32 checked; + + u32 state_changed; + + struct meson_vpu_block_link inputs[MESON_BLOCK_MAX_INPUTS]; + struct meson_vpu_block_link outputs[MESON_BLOCK_MAX_OUTPUTS]; + int in_stack; + int active; + + +}; + +struct meson_vpu_osd_layer_info { + u32 src_x; + u32 src_y; + u32 src_w; + u32 src_h; + u32 dst_w; + u32 dst_h; + int dst_x; + int dst_y; + u32 zorder; + u32 byte_stride; + u32 pixel_format; + u32 phy_addr; + u32 plane_index; + u32 enable; + u32 ratio_x;/*input_w/output_w*/ + u32 afbc_inter_format; + u32 afbc_en; +}; + +struct meson_vpu_osd { + struct meson_vpu_block base; + struct osd_mif_reg_s *reg; +}; + +struct meson_vpu_osd_state { + struct meson_vpu_block_state base; + + u32 index; + u32 enable; + u32 color_key_enable; + u32 dimm_enable; + u32 mode_3d_enable; + + u32 color_key; + u32 alpha; + u32 global_alpha; + u32 dimm_color; + u32 phy_addr; + u32 pixel_format; + u32 zorder; + u32 byte_stride; + u32 src_x; + u32 src_y; + u32 src_w; + u32 src_h; + u32 dst_w; + u32 dst_h; + int dst_x; + int dst_y; + int s_mode; + int r_mode; + u32 plane_index; +}; + +struct meson_vpu_afbc { + struct meson_vpu_block base; + +}; + +struct meson_vpu_afbc_state { + struct meson_vpu_block_state base; + + u32 format; + u32 inter_format; + union afbc_osd_reg regs; +}; + +struct meson_vpu_scaler { + struct meson_vpu_block base; + struct osd_scaler_reg_s *reg; + u32 linebuffer;/*base pixel*/ + u32 bank_length;/*base line*/ +}; + +struct meson_vpu_scaler_state { + struct meson_vpu_block_state base; + + u32 free_scale_mode; + u32 input_width; + u32 input_height; + u32 output_width; + u32 output_height; + u32 ratio_x; + u32 ratio_y; + u32 scan_mode_out; + u32 state_changed; + u32 free_scale_enable; +}; + +struct meson_vpu_scaler_param { + u32 input_width; + u32 input_height; + u32 output_width; + u32 output_height; + u32 ratio_x; + u32 ratio_y; + /*calc_done_mask: + *bit0:ratio_x, + *bit1:ratio_y + *bit2:input_width + *bit3:input_height + *bit4:output_width + *bit5:output_height + */ + u32 calc_done_mask; + /* + *bit0:plane0 + *bit1:plane1 + *bit2:plane2 + *bit*:plane* + */ + u32 plane_mask; + u32 enable; + u32 before_osdblend; +}; + +struct meson_vpu_osdblend { + struct meson_vpu_block base; + struct osdblend_reg_s *reg; +}; + +struct meson_vpu_osdblend_state { + struct meson_vpu_block_state base; + + u32 input_num; + /*bit0/bit1/bit2-->osd0/osd1/osd2*/ + u32 input_osd_mask; + /*Din mask:bit0:DIN0;bit1:DIN1;bit2:DIN2;bit3:DIN3*/ + u32 input_mask; + /*Din0~3 select which input channel or osd(0/1/2)*/ + u32 din_channel_mux[MAX_DIN_NUM]; + /*osd(0/1/2) go through osdblend to dout0 or dout1*/ + u32 dout_mux[MAX_DIN_NUM]; + /*scope position before mux,tied with osd0/osd1/osd2*/ + struct osd_scope_s din_channel_scope[MAX_DIN_NUM]; + /*sub-blend0 and sub-blend1 size*/ + u32 input_width[MESON_MAX_OSD_BLEND]; + u32 input_height[MESON_MAX_OSD_BLEND]; + /*0:din0-->blend0;1:din0-->Dout0,bypass OsdBlend*/ + u32 din0_switch; + /*0:din3-->blend1;1:din3-->Dout1,bypass OsdBlend*/ + u32 din3_switch; + /*0:blend1-->blend2;1:blend1-->Dout1,bypass Blend2*/ + u32 blend1_switch; + +}; + +struct meson_vpu_hdr { + struct meson_vpu_block base; + +}; + +struct meson_vpu_hdr_state { + struct meson_vpu_block_state base; +}; + +struct meson_vpu_dolby { + struct meson_vpu_block base; +}; + +struct meson_vpu_dolby_state { + struct meson_vpu_block_state base; +}; + +struct meson_vpu_postblend { + struct meson_vpu_block base; + struct postblend_reg_s *reg; +}; + +struct meson_vpu_postblend_state { + struct meson_vpu_block_state base; + struct osd_scope_s postblend_scope[MESON_MAX_OSD_TO_VPP]; +}; + +/* vpu pipeline */ +struct meson_vpu_pipeline { + struct drm_private_obj obj; + struct drm_display_mode mode; + struct meson_vpu_osd *osds[MESON_MAX_OSDS]; + struct meson_vpu_afbc *afbc_osds[MESON_MAX_OSDS]; + struct meson_vpu_scaler *scalers[MESON_MAX_SCALERS]; + struct meson_vpu_osdblend *osdblend; + struct meson_vpu_hdr *hdr; + struct meson_vpu_dolby *dolby; + struct meson_vpu_postblend *postblend; + struct meson_vpu_pipeline_state *state; + u32 num_osds; + u32 num_afbc_osds; + u32 num_scalers; + u8 osd_version; +}; + +struct meson_vpu_common_state { + u32 color_format; + u64 block_mask; +}; + +struct meson_vpu_stack { + int num_blocks; + int top; + struct meson_vpu_block *stack[MESON_MAX_BLOCKS]; +}; + +struct meson_vpu_traverse { + struct meson_vpu_block *path[MAX_DFS_PATH_NUM][MESON_MAX_BLOCKS]; + int num_path; +}; + +struct meson_vpu_pipeline_state { + struct drm_private_state obj; + struct meson_vpu_common_state common_cfg; + struct meson_vpu_pipeline *pipeline; + u64 enable_blocks; + struct meson_vpu_osd_layer_info plane_info[MESON_MAX_OSDS]; + u32 num_plane; + /*min --> max*/ + u32 zorder_plane_index[MESON_MAX_OSDS]; + u32 ratio_plane_index[MESON_MAX_OSDS]; + struct meson_vpu_scaler_param scaler_param[MESON_MAX_SCALERS]; + /*pre_osd_scope is before DIN*/ + struct osd_scope_s osd_scope_pre[MAX_DIN_NUM]; + + /*some traverse help structure*/ + struct meson_vpu_stack osd_stack[MESON_MAX_OSDS]; + + /*store traverse result for every path*/ + struct meson_vpu_traverse osd_traverse[MESON_MAX_OSDS]; + + u32 plane_index[MESON_MAX_OSDS]; + u32 din_index[MAX_DIN_NUM]; + u32 dout_index[MAX_DIN_NUM]; + u32 scaler_cnt[MAX_DIN_NUM]; + struct meson_vpu_block *scale_blk[MESON_MAX_OSDS][MESON_MAX_SCALERS]; + u32 dout_zorder[MAX_DOUT_NUM]; +}; + +#define to_osd_block(x) container_of(x, struct meson_vpu_osd, base) +#define to_afbc_block(x) container_of(x, struct meson_vpu_afbc, base) +#define to_scaler_block(x) container_of(x, struct meson_vpu_scaler, base) +#define to_osdblend_block(x) container_of(x, struct meson_vpu_osdblend, base) +#define to_hdr_block(x) container_of(x, struct meson_vpu_hdr, base) +#define to_dolby_block(x) container_of(x, struct meson_vpu_dolby, base) +#define to_postblend_block(x) container_of(x, struct meson_vpu_postblend, base) + +#define to_osd_state(x) container_of(x, struct meson_vpu_osd_state, base) +#define to_afbc_state(x) container_of(x, struct meson_vpu_afbc_state, base) +#define to_scaler_state(x) container_of(x, struct meson_vpu_scaler_state, base) +#define to_osdblend_state(x) container_of(x, \ + struct meson_vpu_osdblend_state, base) +#define to_hdr_state(x) container_of(x, struct meson_vpu_hdr_state, base) +#define to_dolby_state(x) container_of(x, struct meson_vpu_dolby_state, base) +#define to_postblend_state(x) container_of(x, \ + struct meson_vpu_postblend_state, base) + +#define priv_to_block(x) container_of(x, struct meson_vpu_block, obj) +#define priv_to_block_state(x) container_of(x, \ + struct meson_vpu_block_state, obj) +#define priv_to_pipeline(x) container_of(x, struct meson_vpu_pipeline, obj) +#define priv_to_pipeline_state(x) container_of(x, \ + struct meson_vpu_pipeline_state, obj) + +int vpu_topology_init(struct platform_device *pdev, struct meson_drm *private); +int vpu_pipeline_check(struct meson_vpu_pipeline *pipeline, + struct drm_atomic_state *state); +int vpu_pipeline_update(struct meson_vpu_pipeline *pipeline, + struct drm_atomic_state *old_state); +void vpu_pipeline_init(struct meson_vpu_pipeline *pipeline); + +/* meson_vpu_pipeline_private.c */ +struct meson_vpu_block_state * +meson_vpu_block_get_state(struct meson_vpu_block *block, + struct drm_atomic_state *state); +struct meson_vpu_pipeline_state * +meson_vpu_pipeline_get_state(struct meson_vpu_pipeline *pipeline, + struct drm_atomic_state *state); +int meson_vpu_block_state_init(struct meson_drm *private, + struct meson_vpu_pipeline *pipeline); +#ifdef MESON_DRM_VERSION_V0 +void meson_vpu_pipeline_atomic_backup_state( + struct meson_vpu_pipeline_state *mvps); +#endif + +int combination_traverse(struct meson_vpu_pipeline_state *mvps, + struct drm_atomic_state *state); +int vpu_pipeline_traverse(struct meson_vpu_pipeline_state *mvps, + struct drm_atomic_state *state); +int vpu_pipeline_check_osdblend(u32 *out_port, int num_planes, + struct meson_vpu_pipeline_state *mvps, + struct drm_atomic_state *state); + +extern struct meson_vpu_block_ops osd_ops; +extern struct meson_vpu_block_ops afbc_ops; +extern struct meson_vpu_block_ops scaler_ops; +extern struct meson_vpu_block_ops osdblend_ops; +extern struct meson_vpu_block_ops hdr_ops; +extern struct meson_vpu_block_ops dolby_ops; +extern struct meson_vpu_block_ops postblend_ops; + + + #endif diff --git a/drivers/amlogic/drm/meson_vpu_pipeline_private.c b/drivers/amlogic/drm/meson_vpu_pipeline_private.c new file mode 100644 index 0000000..a4ecb0e --- a/dev/null +++ b/drivers/amlogic/drm/meson_vpu_pipeline_private.c @@ -0,0 +1,480 @@ +/* + * drivers/amlogic/drm/meson_vpu_pipeline_private.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include "meson_vpu_pipeline.h" +#include "meson_drv.h" + +static inline void +vpu_pipeline_state_set(struct meson_vpu_block *pblk, + struct meson_vpu_block_state *state) +{ + u8 i; + + for (i = 0; i < pblk->avail_inputs; i++) { + memcpy(&state->inputs[i], &pblk->inputs[i], + sizeof(struct meson_vpu_block_link)); + } + for (i = 0; i < pblk->avail_outputs; i++) { + memcpy(&state->outputs[i], &pblk->outputs[i], + sizeof(struct meson_vpu_block_link)); + } + state->in_stack = 0; + state->active = 1; +} + +static struct drm_private_state * +meson_vpu_osd_atomic_duplicate_state(struct drm_private_obj *obj) +{ + struct meson_vpu_block *mvb; + struct meson_vpu_osd_state *state; + + mvb = priv_to_block(obj); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + state->base.pblk = mvb; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj); + vpu_pipeline_state_set(mvb, &state->base); + + return &state->base.obj; +} + +static void meson_vpu_osd_atomic_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct meson_vpu_block_state *mvbs = priv_to_block_state(state); + struct meson_vpu_osd_state *mvos = to_osd_state(mvbs); + + DRM_DEBUG("%s id=%d,index=%d\n", + mvbs->pblk->name, mvbs->pblk->id, mvbs->pblk->index); + kfree(mvos); +} + +static const struct drm_private_state_funcs meson_vpu_osd_obj_funcs = { + .atomic_duplicate_state = meson_vpu_osd_atomic_duplicate_state, + .atomic_destroy_state = meson_vpu_osd_atomic_destroy_state, +}; + +static int meson_vpu_osd_state_init(struct meson_drm *private, + struct meson_vpu_osd *osd) +{ + struct meson_vpu_osd_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->base.pblk = &osd->base; + drm_atomic_private_obj_init(&osd->base.obj, + &state->base.obj, + &meson_vpu_osd_obj_funcs); + + return 0; +} + +static struct drm_private_state * +meson_vpu_afbc_atomic_duplicate_state(struct drm_private_obj *obj) +{ + struct meson_vpu_block *mvb; + struct meson_vpu_afbc_state *state; + + mvb = priv_to_block(obj); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + state->base.pblk = mvb; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj); + vpu_pipeline_state_set(mvb, &state->base); + + return &state->base.obj; +} + +static void +meson_vpu_afbc_atomic_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct meson_vpu_block_state *mvbs = priv_to_block_state(state); + struct meson_vpu_afbc_state *mvas = to_afbc_state(mvbs); + + kfree(mvas); +} + +static const struct drm_private_state_funcs meson_vpu_afbc_obj_funcs = { + .atomic_duplicate_state = meson_vpu_afbc_atomic_duplicate_state, + .atomic_destroy_state = meson_vpu_afbc_atomic_destroy_state, +}; + +static int meson_vpu_afbc_state_init(struct meson_drm *private, + struct meson_vpu_afbc *afbc) +{ + struct meson_vpu_afbc_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->base.pblk = &afbc->base; + drm_atomic_private_obj_init(&afbc->base.obj, + &state->base.obj, + &meson_vpu_afbc_obj_funcs); + + return 0; +} + +/*afbc block state ops end + */ + +/*scaler block state ops start + */ + +static struct drm_private_state * +meson_vpu_scaler_atomic_duplicate_state(struct drm_private_obj *obj) +{ + struct meson_vpu_block *mvb; + struct meson_vpu_scaler_state *state; + + mvb = priv_to_block(obj); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + state->base.pblk = mvb; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj); + vpu_pipeline_state_set(mvb, &state->base); + + return &state->base.obj; +} + +static void +meson_vpu_scaler_atomic_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct meson_vpu_block_state *mvbs = priv_to_block_state(state); + struct meson_vpu_scaler_state *mvss = to_scaler_state(mvbs); + + kfree(mvss); +} + +static const struct drm_private_state_funcs meson_vpu_scaler_obj_funcs = { + .atomic_duplicate_state = meson_vpu_scaler_atomic_duplicate_state, + .atomic_destroy_state = meson_vpu_scaler_atomic_destroy_state, +}; + +static int meson_vpu_scaler_state_init(struct meson_drm *private, + struct meson_vpu_scaler *scaler) +{ + struct meson_vpu_scaler_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->base.pblk = &scaler->base; + drm_atomic_private_obj_init(&scaler->base.obj, + &state->base.obj, + &meson_vpu_scaler_obj_funcs); + + return 0; +} + +static struct drm_private_state * +meson_vpu_osdblend_atomic_duplicate_state(struct drm_private_obj *obj) +{ + struct meson_vpu_block *mvb; + struct meson_vpu_osdblend_state *state; + + mvb = priv_to_block(obj); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + state->base.pblk = mvb; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj); + vpu_pipeline_state_set(mvb, &state->base); + + return &state->base.obj; +} + +static void +meson_vpu_osdblend_atomic_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct meson_vpu_block_state *mvbs = priv_to_block_state(state); + struct meson_vpu_osdblend_state *mvos = to_osdblend_state(mvbs); + + kfree(mvos); +} + +static const struct drm_private_state_funcs meson_vpu_osdblend_obj_funcs = { + .atomic_duplicate_state = meson_vpu_osdblend_atomic_duplicate_state, + .atomic_destroy_state = meson_vpu_osdblend_atomic_destroy_state, +}; + +static int meson_vpu_osdblend_state_init(struct meson_drm *private, + struct meson_vpu_osdblend *osdblend) +{ + struct meson_vpu_osdblend_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->base.pblk = &osdblend->base; + drm_atomic_private_obj_init(&osdblend->base.obj, + &state->base.obj, + &meson_vpu_osdblend_obj_funcs); + + return 0; +} + +static struct drm_private_state * +meson_vpu_hdr_atomic_duplicate_state(struct drm_private_obj *obj) +{ + struct meson_vpu_block *mvb; + struct meson_vpu_hdr_state *state; + + mvb = priv_to_block(obj); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + state->base.pblk = mvb; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj); + vpu_pipeline_state_set(mvb, &state->base); + + return &state->base.obj; +} + +static void meson_vpu_hdr_atomic_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct meson_vpu_block_state *mvbs = priv_to_block_state(state); + struct meson_vpu_hdr_state *mvhs = to_hdr_state(mvbs); + + kfree(mvhs); +} + +static const struct drm_private_state_funcs meson_vpu_hdr_obj_funcs = { + .atomic_duplicate_state = meson_vpu_hdr_atomic_duplicate_state, + .atomic_destroy_state = meson_vpu_hdr_atomic_destroy_state, +}; + +static int meson_vpu_hdr_state_init(struct meson_drm *private, + struct meson_vpu_hdr *hdr) +{ + struct meson_vpu_hdr_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->base.pblk = &hdr->base; + drm_atomic_private_obj_init(&hdr->base.obj, + &state->base.obj, + &meson_vpu_hdr_obj_funcs); + + return 0; +} + +/*hdr block state ops end + */ + +/*postblend block state ops start + */ + +static struct drm_private_state * +meson_vpu_postblend_atomic_duplicate_state(struct drm_private_obj *obj) +{ + struct meson_vpu_block *mvb; + struct meson_vpu_postblend_state *state; + + mvb = priv_to_block(obj); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + state->base.pblk = mvb; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj); + vpu_pipeline_state_set(mvb, &state->base); + + return &state->base.obj; +} + +static void +meson_vpu_postblend_atomic_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct meson_vpu_block_state *mvbs = priv_to_block_state(state); + struct meson_vpu_postblend_state *mvas = to_postblend_state(mvbs); + + kfree(mvas); +} + +static const struct drm_private_state_funcs meson_vpu_postblend_obj_funcs = { + .atomic_duplicate_state = meson_vpu_postblend_atomic_duplicate_state, + .atomic_destroy_state = meson_vpu_postblend_atomic_destroy_state, +}; + +static int +meson_vpu_postblend_state_init(struct meson_drm *private, + struct meson_vpu_postblend *postblend) +{ + struct meson_vpu_postblend_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->base.pblk = &postblend->base; + drm_atomic_private_obj_init(&postblend->base.obj, + &state->base.obj, + &meson_vpu_postblend_obj_funcs); + return 0; +} + +/*postblend block state ops end + */ +#ifdef MESON_DRM_VERSION_V0 +static struct meson_vpu_pipeline_state last_mvps; +#endif +static struct drm_private_state * +meson_vpu_pipeline_atomic_duplicate_state(struct drm_private_obj *obj) +{ + struct meson_vpu_pipeline_state *state; + struct meson_vpu_pipeline *pipeline = priv_to_pipeline(obj); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + #ifdef MESON_DRM_VERSION_V0 + memcpy(state, &last_mvps, sizeof(*state)); + #endif + state->pipeline = pipeline; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->obj); + + return &state->obj; +} + +static void meson_vpu_pipeline_atomic_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct meson_vpu_pipeline_state *mvps = priv_to_pipeline_state(state); + + kfree(mvps); +} + +#ifdef MESON_DRM_VERSION_V0 +void meson_vpu_pipeline_atomic_backup_state( + struct meson_vpu_pipeline_state *mvps) +{ + memcpy(&last_mvps, mvps, sizeof(*mvps)); +} +#endif + +static const struct drm_private_state_funcs meson_vpu_pipeline_obj_funcs = { + .atomic_duplicate_state = meson_vpu_pipeline_atomic_duplicate_state, + .atomic_destroy_state = meson_vpu_pipeline_atomic_destroy_state, +}; + +static int meson_vpu_pipeline_state_init(struct meson_drm *private, + struct meson_vpu_pipeline *pipeline) +{ + struct meson_vpu_pipeline_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->pipeline = pipeline; + drm_atomic_private_obj_init(&pipeline->obj, &state->obj, + &meson_vpu_pipeline_obj_funcs); + + return 0; +} + +struct meson_vpu_block_state * +meson_vpu_block_get_state(struct meson_vpu_block *block, + struct drm_atomic_state *state) +{ + struct drm_private_state *dps; + struct meson_vpu_block_state *mvbs; + + dps = drm_atomic_get_private_obj_state(state, &block->obj); + if (dps) { + mvbs = priv_to_block_state(dps); + return mvbs; + } + + return NULL; +} + +struct meson_vpu_pipeline_state * +meson_vpu_pipeline_get_state(struct meson_vpu_pipeline *pipeline, + struct drm_atomic_state *state) +{ + struct drm_private_state *dps; + + dps = drm_atomic_get_private_obj_state(state, &pipeline->obj); + if (dps) { + dps->state = state; + return priv_to_pipeline_state(dps); + } + + return NULL; +} + +int meson_vpu_block_state_init(struct meson_drm *private, + struct meson_vpu_pipeline *pipeline) +{ + int i, ret; + + ret = meson_vpu_pipeline_state_init(private, pipeline); + if (ret) + return ret; + + for (i = 0; i < pipeline->num_osds; i++) { + ret = meson_vpu_osd_state_init(private, pipeline->osds[i]); + if (ret) + return ret; + } + + for (i = 0; i < pipeline->num_afbc_osds; i++) { + ret = meson_vpu_afbc_state_init(private, + pipeline->afbc_osds[i]); + if (ret) + return ret; + } + + for (i = 0; i < pipeline->num_scalers; i++) { + ret = meson_vpu_scaler_state_init(private, + pipeline->scalers[i]); + if (ret) + return ret; + } + + + ret = meson_vpu_osdblend_state_init(private, pipeline->osdblend); + if (ret) + return ret; + + ret = meson_vpu_hdr_state_init(private, pipeline->hdr); + if (ret) + return ret; + + ret = meson_vpu_postblend_state_init(private, pipeline->postblend); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/amlogic/drm/meson_vpu_pipeline_traverse.c b/drivers/amlogic/drm/meson_vpu_pipeline_traverse.c new file mode 100644 index 0000000..2f3b211 --- a/dev/null +++ b/drivers/amlogic/drm/meson_vpu_pipeline_traverse.c @@ -0,0 +1,658 @@ +/* + * drivers/amlogic/drm/meson_vpu_pipeline_traverse.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include <dt-bindings/display/meson-drm-ids.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include "meson_vpu_pipeline.h" +#include "meson_drv.h" + +static void stack_init(struct meson_vpu_stack *mvs) +{ + mvs->top = 0; + memset(mvs->stack, 0, sizeof(struct meson_vpu_block *) * + MESON_MAX_BLOCKS); +} + +static void stack_push(struct meson_vpu_stack *mvs, struct meson_vpu_block *mvb) +{ + mvs->stack[mvs->top++] = mvb; +} + +static struct meson_vpu_block *stack_pop(struct meson_vpu_stack *mvs) +{ + struct meson_vpu_block *mvb; + + mvb = mvs->stack[--mvs->top]; + mvs->stack[mvs->top] = NULL; + return mvb; +} + +static struct meson_vpu_block *neighbour(struct meson_vpu_block_state *mvbs, + int *index, + struct drm_atomic_state *state) +{ + int i; + struct meson_vpu_block_link *mvbl; + struct meson_vpu_block_state *next_state; + + for (i = 0; i < MESON_BLOCK_MAX_OUTPUTS; i++) { + mvbl = &mvbs->outputs[i]; + + if (!mvbl->link) + continue; + next_state = meson_vpu_block_get_state(mvbl->link, state); + if (next_state->in_stack) { + //printk("%s already in stack.\n", mvbl->link->name); + continue; + } + if (!next_state->active) { + //printk("%s is not active.\n", mvbl->link->name); + continue; + } + if (!mvbl->edges_active) { + //printk("edges is not active.\n"); + continue; + } + if (mvbl->edges_visited) { + //printk("edges is already visited.\n"); + continue; + } + + *index = i; + return mvbl->link; + } + + return NULL; +} + +static void pipeline_visit_clean(struct meson_vpu_block_state *curr_state) +{ + int index; + + for (index = 0; index < MESON_BLOCK_MAX_OUTPUTS; index++) + curr_state->outputs[index].edges_visited = 0; +} + +/** + * pipeline_dfs - dfs algorithm to search path + * @osd_index: osd layer index + * @start: the start block of the dfs + * @end: the end block of the dfs + * + * use the non-recursive dfs algorithm to search all paths from the start block + * to the end block, the result will be saved to the meson_vpu_traverse struct. + * + */ +static void pipeline_dfs(int osd_index, struct meson_vpu_pipeline_state *mvps, + struct meson_vpu_block *start, + struct meson_vpu_block *end, + struct drm_atomic_state *state) +{ + struct meson_vpu_block *curr, *next, *prev; + struct meson_vpu_block_state *curr_state, *next_state, *prev_state; + int i, j, index; + + struct meson_vpu_stack *mvs = &mvps->osd_stack[osd_index]; + struct meson_vpu_traverse *mvt = &mvps->osd_traverse[osd_index]; + + stack_init(mvs); + stack_push(mvs, start); + mvt->num_path = 0; + j = 0; + + while (mvs->top) { + if (mvs->stack[mvs->top - 1] == end) { + for (i = 0; i < mvs->top; i++) { + mvt->path[j][i] = mvs->stack[i]; + DRM_DEBUG("%s->\n", mvs->stack[i]->name); + } + j++; + mvt->num_path++; + DRM_DEBUG("\n"); + prev = stack_pop(mvs); + prev_state = meson_vpu_block_get_state(prev, state); + prev_state->in_stack = 0; + } else { + curr = mvs->stack[mvs->top - 1]; + curr_state = meson_vpu_block_get_state(curr, state); + next = neighbour(curr_state, &index, state); + + if (next) { + curr_state->outputs[index].edges_visited = 1; + next_state = + meson_vpu_block_get_state(next, state); + stack_push(mvs, next); + next_state->in_stack = 1; + } else { + stack_pop(mvs); + curr_state->in_stack = 0; + pipeline_visit_clean(curr_state); + } + } + } +} + +static u8 find_out_port(struct meson_vpu_block *in, + struct meson_vpu_block *out) +{ + int i; + struct meson_vpu_block_link *mvbl; + + for (i = 0; i < out->avail_inputs; i++) { + mvbl = &out->inputs[i]; + if (mvbl->link == in) + return mvbl->port; + } + return 0; +} + +void vpu_pipeline_scaler_scope_size_calc(u8 index, u8 osd_index, + struct meson_vpu_pipeline_state *mvps) +{ + u8 m, i; + u32 ratio_x[MESON_MAX_SCALERS], ratio_y[MESON_MAX_SCALERS]; + struct meson_vpu_scaler_param *scaler_param, *scaler_param_1; + + i = index; + if (mvps->scaler_cnt[i] == 0) { + /*scope size calc*/ + mvps->osd_scope_pre[osd_index].h_start = + mvps->plane_info[osd_index].src_x; + mvps->osd_scope_pre[osd_index].v_start = + mvps->plane_info[osd_index].src_y; + mvps->osd_scope_pre[osd_index].h_end = + mvps->osd_scope_pre[osd_index].h_start + + mvps->plane_info[osd_index].src_w - 1; + mvps->osd_scope_pre[osd_index].v_end = + mvps->osd_scope_pre[osd_index].v_start + + mvps->plane_info[osd_index].src_h - 1; + } else if (mvps->scaler_cnt[i] == 1) { + m = mvps->scale_blk[i][0]->index; + scaler_param = &mvps->scaler_param[m]; + scaler_param->ratio_x = + (mvps->plane_info[osd_index].src_w * + RATIO_BASE) / + mvps->plane_info[osd_index].dst_w; + scaler_param->ratio_y = + (mvps->plane_info[osd_index].src_h * + RATIO_BASE) / + mvps->plane_info[osd_index].dst_h; + scaler_param->calc_done_mask |= + SCALER_RATIO_X_CALC_DONE | + SCALER_RATIO_Y_CALC_DONE; + if (scaler_param->before_osdblend) { + /*scale size calc firstly*/ + scaler_param->input_width = + mvps->plane_info[osd_index].src_w; + scaler_param->input_height = + mvps->plane_info[osd_index].src_h; + scaler_param->output_width = + mvps->plane_info[osd_index].dst_w; + scaler_param->output_height = + mvps->plane_info[osd_index].dst_h; + scaler_param->calc_done_mask |= + SCALER_IN_W_CALC_DONE | + SCALER_IN_H_CALC_DONE | + SCALER_OUT_W_CALC_DONE | + SCALER_OUT_H_CALC_DONE; + /*scope size calc*/ + mvps->osd_scope_pre[osd_index].h_start = + mvps->plane_info[osd_index].dst_x; + mvps->osd_scope_pre[osd_index].v_start = + mvps->plane_info[osd_index].dst_y; + mvps->osd_scope_pre[osd_index].h_end = + mvps->osd_scope_pre[osd_index].h_start + + scaler_param->output_width - 1; + mvps->osd_scope_pre[osd_index].v_end = + mvps->osd_scope_pre[osd_index].v_start + + scaler_param->output_height - 1; + } else {/*scaler position is after osdlend*/ + /*scope size calc firstly*/ + mvps->osd_scope_pre[osd_index].h_start = + mvps->plane_info[osd_index].src_x; + mvps->osd_scope_pre[osd_index].v_start = + mvps->plane_info[osd_index].src_y; + mvps->osd_scope_pre[osd_index].h_end = + mvps->osd_scope_pre[osd_index].h_start + + mvps->plane_info[osd_index].src_w - 1; + mvps->osd_scope_pre[osd_index].v_end = + mvps->osd_scope_pre[osd_index].v_start + + mvps->plane_info[osd_index].src_h - 1; + /*scaler size calc*/ + scaler_param->input_width = + mvps->osd_scope_pre[osd_index].h_end + 1; + scaler_param->input_height = + mvps->osd_scope_pre[osd_index].v_end + 1; + scaler_param->output_width = + mvps->plane_info[osd_index].dst_x + + mvps->plane_info[osd_index].dst_w; + scaler_param->output_height = + mvps->plane_info[osd_index].dst_y + + mvps->plane_info[osd_index].dst_h; + scaler_param->calc_done_mask |= + SCALER_IN_W_CALC_DONE | + SCALER_IN_H_CALC_DONE | + SCALER_OUT_W_CALC_DONE | + SCALER_OUT_H_CALC_DONE; + } + } else if (mvps->scaler_cnt[i] == 2) { + m = mvps->scale_blk[i][0]->index; + scaler_param = &mvps->scaler_param[m]; + m = mvps->scale_blk[i][1]->index; + scaler_param_1 = &mvps->scaler_param[m]; + if (scaler_param_1->calc_done_mask & + SCALER_RATIO_X_CALC_DONE) {/*TODO*/ + ratio_x[1] = scaler_param_1->ratio_x; + ratio_y[1] = scaler_param_1->ratio_y; + /*recheck scaler size*/ + } else {/*TODO*/ + ratio_x[1] = RATIO_BASE; + ratio_y[1] = RATIO_BASE; + scaler_param_1->calc_done_mask |= + SCALER_RATIO_X_CALC_DONE | + SCALER_RATIO_Y_CALC_DONE; + } + /*calculate scaler input/output size and scope*/ + if (scaler_param->before_osdblend) { + scaler_param->input_width = + mvps->plane_info[osd_index].src_w; + scaler_param->input_height = + mvps->plane_info[osd_index].src_h; + scaler_param->output_width = + mvps->plane_info[osd_index].dst_w * + ratio_x[1] / RATIO_BASE; + scaler_param->output_height = + mvps->plane_info[osd_index].dst_h * + ratio_y[1] / RATIO_BASE; + scaler_param->calc_done_mask |= + SCALER_IN_W_CALC_DONE | + SCALER_IN_H_CALC_DONE | + SCALER_OUT_W_CALC_DONE | + SCALER_OUT_H_CALC_DONE; + /*scope size calc*/ + mvps->osd_scope_pre[osd_index].h_start = + mvps->plane_info[osd_index].dst_x * + ratio_x[1] / RATIO_BASE; + mvps->osd_scope_pre[osd_index].v_start = + mvps->plane_info[osd_index].dst_y * + ratio_y[1] / RATIO_BASE; + mvps->osd_scope_pre[osd_index].h_end = + mvps->osd_scope_pre[osd_index].h_start + + scaler_param->output_width - 1; + mvps->osd_scope_pre[osd_index].v_end = + mvps->osd_scope_pre[osd_index].v_start + + scaler_param->output_height - 1; + } else { + /*TODO*/ + } + /*reclac second scaler size*/ + /*scaler_param_1->before_osdblend == 0*/ + if (scaler_param_1->input_width < + mvps->osd_scope_pre[osd_index].h_end + 1) { + scaler_param_1->input_width = + mvps->osd_scope_pre[osd_index].h_end + 1; + scaler_param_1->output_width = + mvps->plane_info[osd_index].dst_x + + mvps->plane_info[osd_index].dst_w; + } + if (scaler_param_1->input_height < + mvps->osd_scope_pre[osd_index].v_end + 1) { + scaler_param_1->input_height = + mvps->osd_scope_pre[osd_index].v_end + 1; + scaler_param_1->output_height = + mvps->plane_info[osd_index].dst_y + + mvps->plane_info[osd_index].dst_h; + } + } +} +static void vpu_osd_shift_recalc(struct meson_vpu_pipeline_state *state) +{ + u8 i; + + for (i = 0; i < MESON_MAX_OSDS; i++) { + state->osd_scope_pre[i].v_start += 1; + state->osd_scope_pre[i].v_end += 1; + } + state->scaler_param[0].input_height += 1; +} +int vpu_pipeline_scaler_check(int *combination, int num_planes, + struct meson_vpu_pipeline_state *mvps) +{ + int i, j, osd_index, ret, m; + struct meson_vpu_traverse *mvt; + struct meson_vpu_block **mvb; + struct meson_vpu_block *block; + struct meson_vpu_scaler_param *scaler_param, *scaler_param_1; + u32 ratio_x[MESON_MAX_SCALERS], ratio_y[MESON_MAX_SCALERS]; + bool have_blend; + + ret = 0; + /*clean up scaler and scope size before check & calc*/ + memset(mvps->scaler_param, 0, + MESON_MAX_SCALERS * sizeof(struct meson_vpu_scaler_param)); + memset(mvps->osd_scope_pre, 0, + MESON_MAX_OSDS * sizeof(struct osd_scope_s)); + for (i = 0; i < MESON_MAX_OSDS && !ret; i++) { + if (!mvps->plane_info[i].enable) + continue; + osd_index = mvps->plane_index[i]; + mvt = &mvps->osd_traverse[osd_index]; + mvb = mvt->path[combination[i]]; + mvps->scaler_cnt[i] = 0; + have_blend = 0; + + for (j = 0; j < MESON_MAX_BLOCKS; j++) { + block = mvb[j]; + if (!block) + continue; + if (block->type == MESON_BLK_OSDBLEND) + have_blend = 1; + if (block->type == MESON_BLK_SCALER) { + m = mvps->scaler_cnt[i]; + mvps->scale_blk[i][m] = block; + mvps->scaler_cnt[i]++; + m = block->index; + mvps->scaler_param[m].plane_mask |= + BIT(osd_index); + mvps->scaler_param[m].before_osdblend = + have_blend ? 0:1; + } + } + + if (mvps->scaler_cnt[i] == 0) { + ratio_x[0] = (mvps->plane_info[osd_index].src_w * + RATIO_BASE) / + mvps->plane_info[osd_index].dst_w; + ratio_y[0] = (mvps->plane_info[osd_index].src_h * + RATIO_BASE) / + mvps->plane_info[osd_index].dst_h; + if (ratio_x[0] != RATIO_BASE || + ratio_y[0] != RATIO_BASE) { + ret = -1; + break; + } + vpu_pipeline_scaler_scope_size_calc(i, + osd_index, mvps); + } else if (mvps->scaler_cnt[i] == 1) { + vpu_pipeline_scaler_scope_size_calc(i, + osd_index, mvps); + } else if (mvps->scaler_cnt[i] == 2) { + /* + *check second scaler firstly, + *if second scaler have not check, + *disable the second scaler.only use first scale. + */ + m = mvps->scale_blk[i][1]->index; + scaler_param_1 = &mvps->scaler_param[m]; + if (scaler_param_1->calc_done_mask & + SCALER_RATIO_X_CALC_DONE) {/*TODO*/ + ratio_x[1] = scaler_param_1->ratio_x; + ratio_y[1] = scaler_param_1->ratio_y; + /*recheck scaler size*/ + } else {/*TODO*/ + ratio_x[1] = RATIO_BASE; + ratio_y[1] = RATIO_BASE; + scaler_param_1->ratio_x = RATIO_BASE; + scaler_param_1->ratio_y = RATIO_BASE; + scaler_param_1->calc_done_mask |= + SCALER_RATIO_X_CALC_DONE | + SCALER_RATIO_Y_CALC_DONE; + } + ratio_x[0] = (mvps->plane_info[osd_index].src_w * + RATIO_BASE) / + mvps->plane_info[osd_index].dst_w; + ratio_y[0] = (mvps->plane_info[osd_index].src_h * + RATIO_BASE) / + mvps->plane_info[osd_index].dst_h; + m = mvps->scale_blk[i][0]->index; + scaler_param = &mvps->scaler_param[m]; + scaler_param->ratio_x = + (ratio_x[0] * RATIO_BASE) / ratio_x[1]; + scaler_param->ratio_y = + (ratio_y[0] * RATIO_BASE) / ratio_y[1]; + scaler_param->calc_done_mask |= + SCALER_RATIO_X_CALC_DONE | + SCALER_RATIO_Y_CALC_DONE; + ratio_x[0] = scaler_param->ratio_x; + ratio_y[0] = scaler_param->ratio_y; + + if ((ratio_x[0] > RATIO_BASE && + ratio_x[1] < RATIO_BASE) || + (ratio_y[0] > RATIO_BASE && + ratio_y[1] < RATIO_BASE)) { + ret = -1; + break; + } + vpu_pipeline_scaler_scope_size_calc(i, + osd_index, mvps); + } + } + if (ret == 0 && mvps->num_plane > 0 && + mvps->pipeline->osd_version <= OSD_V2) + vpu_osd_shift_recalc(mvps); + return ret; +} + +/** + * vpu_pipeline_check_block: check pipeline block + * @combination: index array of every layer path + * @num_planes: the number of layer + * + * For some blocks that have multiple output port, + * call the ops->check interface to determain a valid path. + * + * RETURNS: + * 0 for the valid path or -1 for the invalid path + */ +int vpu_pipeline_check_block(int *combination, int num_planes, + struct meson_vpu_pipeline_state *mvps, + struct drm_atomic_state *state) +{ + int i, j, osd_index, ret; + struct meson_vpu_traverse *mvt; + struct meson_vpu_block **mvb; + struct meson_vpu_block *block; + struct meson_vpu_block *osdblend; + struct meson_vpu_block_state *mvbs; + + osdblend = &mvps->pipeline->osdblend->base; + ret = vpu_pipeline_scaler_check(combination, num_planes, mvps); + if (ret) + return -1; + + for (i = 0; i < MESON_MAX_OSDS; i++) { + if (!mvps->plane_info[i].enable) + continue; + osd_index = mvps->plane_index[i]; + mvt = &mvps->osd_traverse[osd_index]; + mvb = mvt->path[combination[i]]; + mvps->scaler_cnt[i] = 0; + + for (j = 0; j < MESON_MAX_BLOCKS; j++) { + block = mvb[j]; + if (!block) + break; + + if (block == osdblend) { + mvps->dout_index[i] = + find_out_port(block, mvb[j+1]); + DRM_DEBUG("osd-%d blend out port: %d.\n", + i, mvps->dout_index[i]); + break; + } + } + } + + for (i = 0; i < MESON_MAX_OSDS; i++) { + if (!mvps->plane_info[i].enable) + continue; + osd_index = mvps->plane_index[i]; + mvt = &mvps->osd_traverse[osd_index]; + mvb = mvt->path[combination[i]]; + + for (j = 0; j < MESON_MAX_BLOCKS; j++) { + block = mvb[j]; + if (!block) + break; + + if (block->ops && block->ops->check_state) { + mvbs = meson_vpu_block_get_state(block, state); + ret = block->ops->check_state(block, + mvbs, mvps); + + if (ret) { + DRM_ERROR("%s block check error.\n", + block->name); + return ret; + } + } + } + } + + return ret; +} + +void vpu_pipeline_enable_block(int *combination, int num_planes, + struct meson_vpu_pipeline_state *mvps) +{ + int i, j, osd_index; + struct meson_vpu_traverse *mvt; + struct meson_vpu_block **mvb; + struct meson_vpu_block *block; + + mvps->enable_blocks = 0; + + for (i = 0; i < MESON_MAX_OSDS; i++) { + if (!mvps->plane_info[i].enable) + continue; + osd_index = mvps->plane_index[i]; + mvt = &mvps->osd_traverse[osd_index]; + mvb = mvt->path[combination[i]]; + + for (j = 0; j < MESON_MAX_BLOCKS; j++) { + block = mvb[j]; + if (!block) + break; + mvps->enable_blocks |= BIT(block->id); + } + } +} + +/** + * combinate_layer_path - combinate every found layer path + * @path_num_array: the number of every layer's found path + * @num_planes: the number of layer + * + * use combination algorithm to check whether the path is valid + * + * RETURNS: + * 0 for the valid path or -1 for the invalid path + */ +int combinate_layer_path(int *path_num_array, int num_planes, + struct meson_vpu_pipeline_state *mvps, + struct drm_atomic_state *state) +{ + int i, j, ret; + bool is_continue = false; + int combination[MESON_MAX_OSDS] = {0}; + + i = 0; + ret = -1; + + do { + // sum the combination result to check osd blend block + ret = vpu_pipeline_check_block(combination, + num_planes, mvps, state); + if (!ret) + break; + + i++; + combination[num_planes-1] = i; + + for (j = num_planes - 1; j >= 0; j--) { + if (combination[j] >= path_num_array[j]) { + combination[j] = 0; + i = 0; + if ((j - 1) >= 0) + combination[j - 1] = + combination[j - 1] + 1; + } + } + + is_continue = false; + + for (j = 0; j < num_planes; j++) { + if (combination[j] != 0) + is_continue = true; + } + } while (is_continue); + if (!ret) + vpu_pipeline_enable_block(combination, num_planes, mvps); + return ret; +} + +/** + * find every layer's path(from start block to the end block) through + * pipeline_dfs, combinate every found path of every layer + * and check whether the combination is a valid path + * that can meet the requirement of hardware limites. + * + * RETURNS: + * 0 for the valid path or -1 for the invalid path + */ +int vpu_pipeline_traverse(struct meson_vpu_pipeline_state *mvps, + struct drm_atomic_state *state) +{ + int i, osd_index, ret; + int num_planes; + struct meson_vpu_block *start, *end; + int path[MESON_MAX_OSDS] = {0}; + struct meson_vpu_pipeline *mvp = mvps->pipeline; + + end = &mvp->postblend->base; + num_planes = mvps->num_plane; + + if (!num_planes) + return 0; + + DRM_DEBUG("traverse num: %d %p.\n", num_planes, mvps); + for (i = 0; i < MESON_MAX_OSDS; i++) { + if (!mvps->plane_info[i].enable) + continue; + osd_index = mvps->plane_index[i]; + start = &mvp->osds[osd_index]->base; + DRM_DEBUG("do pipeline_dfs: OSD%d.\n", (osd_index + 1)); + pipeline_dfs(osd_index, mvps, start, end, state); + } + + // start to combination every layer case + for (i = 0; i < MESON_MAX_OSDS; i++) { + if (!mvps->plane_info[i].enable) + continue; + osd_index = mvps->plane_index[i]; + path[i] = mvps->osd_traverse[osd_index].num_path; + DRM_DEBUG("osd%d traverse path num: %d\n", + (osd_index + 1), path[i]); + } + + ret = combinate_layer_path(path, num_planes, mvps, state); + if (ret) + DRM_ERROR("can't find a valid path.\n"); + + return ret; +} diff --git a/drivers/amlogic/drm/meson_vpu_util.c b/drivers/amlogic/drm/meson_vpu_util.c new file mode 100644 index 0000000..652af8f --- a/dev/null +++ b/drivers/amlogic/drm/meson_vpu_util.c @@ -0,0 +1,177 @@ +/* + * drivers/amlogic/drm/meson_vpu_util.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "meson_vpu_util.h" + +/*****drm reg access by rdma*****/ + +u32 meson_drm_rdma_read_reg(u32 addr) +{ + return VSYNCOSD_RD_MPEG_REG(addr); +} + +int meson_drm_rdma_write_reg(u32 addr, u32 val) +{ + return VSYNCOSD_WR_MPEG_REG(addr, val); +} + +int meson_drm_rdma_write_reg_bits(u32 addr, u32 val, u32 start, u32 len) +{ + return VSYNCOSD_WR_MPEG_REG(addr, val, start, len); +} + +int meson_drm_rdma_set_reg_mask(u32 addr, u32 mask) +{ + return VSYNCOSD_SET_MPEG_REG_MASK(addr, mask); +} + +int meson_drm_rdma_clr_reg_mask(u32 addr, u32 mask) +{ + return VSYNCOSD_CLR_MPEG_REG_MASK(addr, mask); +} + +int meson_drm_rdma_irq_write_reg(u32 addr, u32 val) +{ + return VSYNCOSD_IRQ_WR_MPEG_REG(addr, val); +} + +/** reg direct access without rdma **/ + +u32 meson_drm_read_reg(u32 addr) +{ + int ret; + u32 val; + + ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &val); + + if (ret) { + pr_err("read vcbus reg %x error %d\n", addr, ret); + return -1; + } + return val; +} + +int meson_drm_write_reg(u32 addr, u32 val) +{ + int ret; + + ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, val); + + if (ret) { + pr_err("write vcbus reg %x error %d\n", addr, ret); + return -1; + } + return 0; +} + +int meson_drm_write_reg_bits(u32 addr, u32 val, u32 start, u32 len) +{ + int ret; + u32 raw_val; + + ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &raw_val); + if (ret) { + pr_err("read vcbus reg %x error %d\n", addr, ret); + return -1; + } + + raw_val |= val & GENMASK(start, start + len); + + ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, raw_val); + if (ret) { + pr_err("write vcbus reg %x error %d\n", addr, ret); + return -1; + } + return 0; +} + +int meson_drm_set_reg_mask(u32 addr, u32 mask) +{ + int ret; + u32 raw_val; + + ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &raw_val); + if (ret) { + pr_err("read vcbus reg %x error %d\n", addr, ret); + return -1; + } + + raw_val |= mask; + + ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, raw_val); + if (ret) { + pr_err("write vcbus reg %x error %d\n", addr, ret); + return -1; + } + return 0; +} + +int meson_drm_clr_reg_mask(u32 addr, u32 mask) +{ + int ret; + u32 raw_val; + + ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &raw_val); + if (ret) { + pr_err("read vcbus reg %x error %d\n", addr, ret); + return -1; + } + + raw_val &= ~mask; + + ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, raw_val); + if (ret) { + pr_err("write vcbus reg %x error %d\n", addr, ret); + return -1; + } + return 0; +} + +/** canvas config **/ + +void meson_drm_canvas_config(u32 index, unsigned long addr, u32 width, + u32 height, u32 wrap, u32 blkmode) +{ + canvas_config(index, addr, width, height, wrap, blkmode, 0); +} + +int meson_drm_canvas_pool_alloc_table(const char *owner, u32 *table, int size, + enum canvas_map_type_e type) +{ + return canvas_pool_alloc_canvas_table(owner, table, size, type); +} + +/** vpu clk and block power domain **/ +unsigned int meson_drm_vpu_get_clk(void) +{ + return get_vpu_clk(); +} + +unsigned int meson_drm_vpu_get_hwblk_clk(unsigned int vmode) +{ + return get_vpu_clk_vmode(vmode); +} + +void meson_drm_vpu_set_hwblk_pd(unsigned int vmode, int flag) +{ + switch_vpu_mem_pd_vmode(vmode, flag); +} + +int meson_drm_vpu_get_hwblk_pd(unsigned int vmode) +{ + return get_vpu_mem_pd_vmode(vmode); +} diff --git a/drivers/amlogic/drm/meson_vpu_util.h b/drivers/amlogic/drm/meson_vpu_util.h new file mode 100644 index 0000000..8c52df5 --- a/dev/null +++ b/drivers/amlogic/drm/meson_vpu_util.h @@ -0,0 +1,62 @@ +/* + * drivers/amlogic/drm/meson_vpu_util.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __MESON_VPU_UTIL_H +#define __MESON_VPU_UTIL_H + +#include <linux/types.h> +#include <linux/amlogic/media/canvas/canvas.h> +#include <linux/amlogic/media/canvas/canvas_mgr.h> +#include <linux/amlogic/media/vpu/vpu.h> +#include "osd_rdma.h" +#include "osd.h" + +/*osd internal channel*/ +enum din_channel_e { + DIN0 = 0, + DIN1, + DIN2, + DIN3 +}; + +struct osd_scope_s { + u32 h_start; + u32 h_end; + u32 v_start; + u32 v_end; +}; + +u32 meson_util_rdma_read_reg(u32 addr); +int meson_util_rdma_write_reg(u32 addr, u32 val); +int meson_util_rdma_write_reg_bits(u32 addr, u32 val, u32 start, u32 len); +int meson_util_rdma_set_reg_mask(u32 addr, u32 mask); +int meson_util_rdma_clr_reg_mask(u32 addr, u32 mask); +int meson_util_rdma_irq_write_reg(u32 addr, u32 val); + +void meson_util_canvas_config(u32 index, unsigned long addr, u32 width, + u32 height, u32 wrap, u32 blkmode); +int meson_util_canvas_pool_alloc_table(const char *owner, u32 *table, int size, + enum canvas_map_type_e type); + +unsigned int meson_util_vpu_get_clk(void); +unsigned int meson_util_vpu_get_hwblk_clk(unsigned int vmode); +void meson_util_vpu_set_hwblk_pd(unsigned int vmode, int flag); +int meson_util_vpu_get_hwblk_pd(unsigned int vmode); + +extern const struct color_bit_define_s default_color_format_array_1[]; + +#endif diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c b/drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c new file mode 100644 index 0000000..6fbec27 --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c @@ -0,0 +1,626 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "meson_vpu_pipeline.h" +#include "meson_vpu_reg.h" +#include "meson_vpu_util.h" +#include "osd.h" + +/* osd_mafbc_irq_clear& irq_mask */ +#define OSD_MAFBC_SURFACES_COMPLETED BIT(0) +#define OSD_MAFBC_CONFI_SWAPPED BIT(1) +#define OSD_MAFBC_DECODE_ERROR BIT(2) +#define OSD_MAFBC_DETILING_ERROR BIT(3) +#define OSD_MAFBC_AXI_ERROR BIT(4) +#define OSD_MAFBC_SECURE_ID_ERROR BIT(5) + +/* osd_mafbc_command */ +#define OSD_MAFBC_DIRECT_SWAP +#define OSD_MAFBC_PENDING_SWAP + +/* osd_mafbc_surface_cfg */ +#define OSD_MAFBC_S0_ENABLE BIT(0) +#define OSD_MAFBC_S1_ENABLE BIT(1) +#define OSD_MAFBC_S2_ENABLE BIT(2) +#define OSD_MAFBC_S3_ENABLE BIT(3) +#define OSD_MAFBC_DECODE_ENABLE BIT(16) + +/* osd_mafbc_axi_cfg */ +#define OSD_MAFBC_AXI_QOS(val) FIELD_PREP(GENMASK(3, 0), val) +#define OSD_MAFBC_AXI_CACHE(val) FIELD_PREP(GENMASK(7, 4), val) + +/* osd_mafbc_format_specifier */ +#define OSD_MAFBC_PIXEL_FORMAT(val) FIELD_PREP(GENMASK(3, 0), val) +#define OSD_MAFBC_YUV_TRANSFORM BIT(8) +#define OSD_MAFBC_BLOCK_SPLIT BIT(9) +#define OSD_MAFBC_SUPER_BLOCK_ASPECT(val) \ + FIELD_PREP(GENMASK(17, 16), val) +#define OSD_MAFBC_TILED_HEADER_EN BIT(18) +#define OSD_MAFBC_PAYLOAD_LIMIT_EN BIT(19) + +/* osd_mafbc_prefetch_cfg */ +#define OSD_MAFBC_PREFETCH_READ_DIR_X BIT(0) +#define OSD_MAFBC_PREFETCH_READ_DIR_Y BIT(1) + +static int afbc_pix_format(u32 fmt_mode) +{ + u32 pix_format = RGBA8888; + + switch (fmt_mode) { + case COLOR_INDEX_YUV_422: + pix_format = YUV422_8B; + break; + case COLOR_INDEX_16_565: + pix_format = RGB565; + break; + case COLOR_INDEX_16_1555_A: + pix_format = RGBA5551; + break; + case COLOR_INDEX_16_4444_R: + case COLOR_INDEX_16_4444_A: + pix_format = RGBA4444; + break; + case COLOR_INDEX_32_BGRX: + case COLOR_INDEX_32_XBGR: + case COLOR_INDEX_32_RGBX: + case COLOR_INDEX_32_XRGB: + case COLOR_INDEX_32_BGRA: + case COLOR_INDEX_32_ABGR: + case COLOR_INDEX_32_RGBA: + case COLOR_INDEX_32_ARGB: + pix_format = RGBA8888; + break; + case COLOR_INDEX_24_888_B: + case COLOR_INDEX_24_RGB: + pix_format = RGB888; + break; + case COLOR_INDEX_RGBA_1010102: + pix_format = RGBA1010102; + break; + default: + osd_log_err("unsupport fmt:%x\n", fmt_mode); + break; + } + return pix_format; +} + +static u32 line_stride_calc_afbc( + u32 fmt_mode, + u32 hsize, + u32 stride_align_32bytes) +{ + u32 line_stride = 0; + + switch (fmt_mode) { + case R8: + line_stride = ((hsize << 3) + 127) >> 7; + break; + case YUV422_8B: + case RGB565: + case RGBA5551: + case RGBA4444: + line_stride = ((hsize << 4) + 127) >> 7; + break; + case RGBA8888: + case RGB888: + case YUV422_10B: + case RGBA1010102: + line_stride = ((hsize << 5) + 127) >> 7; + break; + } + /* need wr ddr is 32bytes aligned */ + if (stride_align_32bytes) + line_stride = ((line_stride+1) >> 1) << 1; + else + line_stride = line_stride; + return line_stride; +} + +static void osd_afbc_enable(u32 osd_index, bool flag) +{ + if (flag) { + + VSYNCOSD_WR_MPEG_REG_BITS( + VPU_MAFBC_SURFACE_CFG, + 1, osd_index, 1); + VSYNCOSD_WR_MPEG_REG( + VPU_MAFBC_IRQ_MASK, 0xf); + } else + VSYNCOSD_WR_MPEG_REG_BITS( + VPU_MAFBC_SURFACE_CFG, + 0, osd_index, 1); +} + +static int afbc_check_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state, + struct meson_vpu_pipeline_state *mvps) +{ + struct meson_vpu_afbc *afbc = to_afbc_block(vblk); + + //vpu_block_check_input(vblk, state, mvps); + + if (state->checked) + return 0; + + state->checked = true; + + DRM_DEBUG("%s check_state called.\n", afbc->base.name); + + return 0; +} + +static void osd1_afbc_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + u32 pixel_format, line_stride, output_stride; + u32 plane_index, osd_index; + u64 header_addr, out_addr; + u32 aligned_32, afbc_color_reorder; + unsigned int depth; + int bpp; + struct meson_vpu_afbc *afbc; + struct meson_vpu_afbc_state *afbc_state; + struct meson_vpu_osd_layer_info *plane_info; + struct meson_vpu_pipeline *pipeline; + struct meson_vpu_pipeline_state *pipeline_state; + + afbc = to_afbc_block(vblk); + afbc_state = to_afbc_state(state); + pipeline = vblk->pipeline; + osd_index = vblk->index; + pipeline_state = priv_to_pipeline_state(pipeline->obj.state); + plane_index = pipeline_state->ratio_plane_index[osd_index]; + plane_info = &pipeline_state->plane_info[plane_index]; + + if (!plane_info->afbc_en) + return; + + osd_afbc_enable(0, 1); + + aligned_32 = 1; + afbc_color_reorder = 0x1234; + pixel_format = afbc_pix_format(plane_info->pixel_format); + drm_fb_get_bpp_depth(plane_info->pixel_format, &depth, &bpp); + header_addr = plane_info->phy_addr; + + line_stride = line_stride_calc_afbc(pixel_format, + plane_info->src_w, aligned_32); + + output_stride = plane_info->src_w * bpp; + + header_addr = plane_info->phy_addr; + out_addr = ((u64)(vblk->index + 1)) << 24; + + /* set osd path misc ctrl */ + VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1); + + /* set linear addr */ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT, 0x1, 2, 1); + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT2, 1, 1, 1); + + /* set read from mali */ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK0_CFG_W0, 0x1, 30, 1); + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK0_CFG_W0, 0, 15, 1); + + /* set line_stride */ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK2_CFG_W4, line_stride, 0, 12); + + /* set frame addr */ + VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK1_CFG_W4, out_addr & 0xffffffff); + + /* set afbc color reorder and mali src*/ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_MALI_UNPACK_CTRL, + afbc_color_reorder, 0, 16); + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_MALI_UNPACK_CTRL, 0x1, 31, 1); + + /* set header addr */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0, + header_addr & 0xffffffff); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0, + (header_addr >> 32) & 0xffffffff); + + /* set format specifier */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_FORMAT_SPECIFIER_S0, + plane_info->afbc_inter_format | (pixel_format & 0x0f)); + + /* set pic size */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_WIDTH_S0, plane_info->src_w); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_HEIGHT_S0, plane_info->src_h); + + /* set buf stride */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_STRIDE_S0, output_stride); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0, + out_addr & 0xffffffff); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0, + (out_addr >> 32) & 0xffffffff); + + /* set bounding box */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_START_S0, + plane_info->src_x); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_END_S0, + (plane_info->src_x + plane_info->src_w - 1)); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_START_S0, + plane_info->src_y); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_END_S0, + (plane_info->src_y + plane_info->src_h - 1)); + + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1); + + DRM_DEBUG("%s set_state called.\n", afbc->base.name); +} + +static void osd2_afbc_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + u32 pixel_format, line_stride, output_stride; + u32 plane_index, osd_index; + u64 header_addr, out_addr; + u32 aligned_32, afbc_color_reorder; + unsigned int depth; + int bpp; + struct meson_vpu_afbc *afbc; + struct meson_vpu_afbc_state *afbc_state; + struct meson_vpu_osd_layer_info *plane_info; + struct meson_vpu_pipeline *pipeline; + struct meson_vpu_pipeline_state *pipeline_state; + + afbc = to_afbc_block(vblk); + afbc_state = to_afbc_state(state); + pipeline = vblk->pipeline; + osd_index = vblk->index; + pipeline_state = priv_to_pipeline_state(pipeline->obj.state); + plane_index = pipeline_state->ratio_plane_index[osd_index]; + plane_info = &pipeline_state->plane_info[plane_index]; + + if (!plane_info->afbc_en) + return; + + osd_afbc_enable(1, 1); + + aligned_32 = 1; + afbc_color_reorder = 0x1234; + pixel_format = afbc_pix_format(plane_info->pixel_format); + drm_fb_get_bpp_depth(plane_info->pixel_format, &depth, &bpp); + header_addr = plane_info->phy_addr; + + line_stride = line_stride_calc_afbc(pixel_format, + plane_info->src_w, aligned_32); + + output_stride = plane_info->src_w * bpp; + + header_addr = plane_info->phy_addr; + out_addr = ((u64)(vblk->index + 1)) << 24; + + /* set osd path misc ctrl */ + VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1); + + /* set linear addr */ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_CTRL_STAT, 0x1, 2, 1); + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_CTRL_STAT2, 1, 1, 1); + + /* set read from mali */ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK0_CFG_W0, 0x1, 30, 1); + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK0_CFG_W0, 0, 15, 1); + + /* set line_stride */ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK2_CFG_W4, line_stride, 0, 12); + + /* set frame addr */ + VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK1_CFG_W4, out_addr & 0xffffffff); + + /* set afbc color reorder and mali src*/ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_MALI_UNPACK_CTRL, + afbc_color_reorder, 0, 16); + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_MALI_UNPACK_CTRL, 0x1, 31, 1); + + /* set header addr */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1, + header_addr & 0xffffffff); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1, + (header_addr >> 32) & 0xffffffff); + + /* set format specifier */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_FORMAT_SPECIFIER_S1, + plane_info->afbc_inter_format | (pixel_format & 0x0f)); + + /* set pic size */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_WIDTH_S1, plane_info->src_w); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_HEIGHT_S1, plane_info->src_h); + + /* set buf stride */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_STRIDE_S1, output_stride); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1, + out_addr & 0xffffffff); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1, + (out_addr >> 32) & 0xffffffff); + + /* set bounding box */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_START_S1, + plane_info->src_x); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_END_S1, + (plane_info->src_x + plane_info->src_w - 1)); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_START_S1, + plane_info->src_y); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_END_S1, + (plane_info->src_y + plane_info->src_h - 1)); + + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1); + + DRM_DEBUG("%s set_state called.\n", afbc->base.name); +} + +static void osd3_afbc_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + u32 pixel_format, line_stride, output_stride; + u32 plane_index, osd_index; + u64 header_addr, out_addr; + u32 aligned_32, afbc_color_reorder; + unsigned int depth; + int bpp; + struct meson_vpu_afbc *afbc; + struct meson_vpu_afbc_state *afbc_state; + struct meson_vpu_osd_layer_info *plane_info; + struct meson_vpu_pipeline *pipeline; + struct meson_vpu_pipeline_state *pipeline_state; + + afbc = to_afbc_block(vblk); + afbc_state = to_afbc_state(state); + pipeline = vblk->pipeline; + osd_index = vblk->index; + pipeline_state = priv_to_pipeline_state(pipeline->obj.state); + plane_index = pipeline_state->ratio_plane_index[osd_index]; + plane_info = &pipeline_state->plane_info[plane_index]; + + if (!plane_info->afbc_en) + return; + + osd_afbc_enable(2, 1); + + aligned_32 = 1; + afbc_color_reorder = 0x1234; + pixel_format = afbc_pix_format(plane_info->pixel_format); + drm_fb_get_bpp_depth(plane_info->pixel_format, &depth, &bpp); + header_addr = plane_info->phy_addr; + + line_stride = line_stride_calc_afbc(pixel_format, + plane_info->src_w, aligned_32); + + output_stride = plane_info->src_w * bpp; + + header_addr = plane_info->phy_addr; + out_addr = ((u64)(vblk->index + 1)) << 24; + + /* set osd path misc ctrl */ + VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1); + + /* set linear addr */ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_CTRL_STAT, 0x1, 2, 1); + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_CTRL_STAT2, 1, 1, 1); + + /* set read from mali */ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_BLK0_CFG_W0, 0x1, 30, 1); + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_BLK0_CFG_W0, 0, 15, 1); + + /* set line_stride */ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_BLK2_CFG_W4, line_stride, 0, 12); + + /* set frame addr */ + VSYNCOSD_WR_MPEG_REG(VIU_OSD3_BLK1_CFG_W4, out_addr & 0xffffffff); + + /* set afbc color reorder and mali src*/ + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_MALI_UNPACK_CTRL, + afbc_color_reorder, 0, 16); + VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_MALI_UNPACK_CTRL, 0x1, 31, 1); + + /* set header addr */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2, + header_addr & 0xffffffff); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2, + (header_addr >> 32) & 0xffffffff); + + /* set format specifier */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_FORMAT_SPECIFIER_S2, + plane_info->afbc_inter_format | (pixel_format & 0x0f)); + + /* set pic size */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_WIDTH_S2, plane_info->src_w); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_HEIGHT_S2, plane_info->src_h); + + /* set buf stride */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_STRIDE_S2, output_stride); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2, + out_addr & 0xffffffff); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2, + (out_addr >> 32) & 0xffffffff); + + /* set bounding box */ + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_START_S2, + plane_info->src_x); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_END_S2, + (plane_info->src_x + plane_info->src_w - 1)); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_START_S2, + plane_info->src_y); + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_END_S2, + (plane_info->src_y + plane_info->src_h - 1)); + + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1); + + DRM_DEBUG("%s set_state called.\n", afbc->base.name); +} + +#if 0 +static void osd_afbc_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + u32 bpp, pixel_format, line_stride, output_stride; + u32 plane_index, osd_index; + u64 header_addr, out_addr; + const struct color_bit_define_s *color_info; + struct meson_vpu_afbc *afbc; + struct meson_vpu_afbc_state *afbc_state; + struct meson_vpu_osd_layer_info *plane_info; + struct meson_vpu_pipeline *pipeline; + struct meson_vpu_pipeline_state *pipeline_state; + struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index]; + + afbc = to_afbc_block(vblk); + afbc_state = to_afbc_state(state); + pipeline = vblk->pipeline; + osd_index = vblk->index; + pipeline_state = priv_to_pipeline_state(pipeline->obj.state); + plane_index = pipeline_state->ratio_plane_index[osd_index]; + plane_info = pipeline_state->plane_info[plane_index]; + + u32 aligned_32 = 1; + u32 afbc_color_reorder = 0x1234; + + pixel_format = afbc_pix_format(plane_info->pixel_format); + color_info = convert_panel_format(pixel_format); + header_addr = plane_info->phy_addr; + + bpp = color_info->bpp >> 3; + line_stride = line_stride_calc_afbc(pixel_format, + plane_info->src_w, aligned_32); + + output_stride = plane_info->src_w * bpp; + + header_addr = plane_info->phy_addr; + out_addr = ((u64)(vblk->index + 1)) << 24; + + /* set osd path misc ctrl */ + VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1); + + /* set linear addr */ + VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_ctrl_stat, 0x1, 2, 1); + + /* set read from mali */ + VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_blk0_cfg_w0, 0x1, 30, 1); + VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_blk0_cfg_w0, 0, 15, 1); + + /* set line_stride */ + VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_blk2_cfg_w4, line_stride, 0, 12); + + /* set frame addr */ + VSYNCOSD_WR_MPEG_REG(osd_reg->osd_blk1_cfg_w4, out_addr & 0xffffffff); + + /* set afbc color reorder and mali src*/ + VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_mali_unpack_ctrl, + afbc_color_reorder, 0, 16); + VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_mali_unpack_ctrl, 0x1, 31, 1); + + /* set header addr */ + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_header_buf_addr_low_s, + out_addr & 0xffffffff); + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_header_buf_addr_high_s, + (out_addr >> 32) & 0xffffffff); + + /* set format specifier */ + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_format_specifier_s, + plane_info->inter_format | (pixel_format & 0x0f)); + + /* set pic size */ + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_buffer_width_s, plane_info->src_w); + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_buffer_hight_s, plane_info->src_h); + + /* set buf stride */ + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_output_buf_stride_s, output_stride); + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_output_buf_addr_low_s, + out_addr & 0xffffffff); + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_output_buf_addr_high_s, + (out_addr >> 32) & 0xffffffff); + + /* set bounding box */ + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_x_start_s, + plane_info->src_x); + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_x_end_s, + (palne_info->src_x + plane_info->src_w - 1)); + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_y_start_s, + plane_info->src_y); + VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_y_end_s, + (plane_info->src_y + plane_info->src_h - 1)); + + VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1); + + DRM_DEBUG("%s set_state called.\n", afbc->base.name); +} +#endif + +static void afbc_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ +#if 0 + osd_afbc_set_state(vblk, state); +#else + switch (vblk->index) { + case 0: + osd1_afbc_set_state(vblk, state); + break; + case 1: + osd2_afbc_set_state(vblk, state); + break; + case 2: + osd3_afbc_set_state(vblk, state); + break; + default: + break; + } +#endif + +} + +static void afbc_hw_enable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_afbc *afbc = to_afbc_block(vblk); + u32 osd_index = vblk->index; + + osd_afbc_enable(osd_index, 1); + + DRM_DEBUG("%s enable called.\n", afbc->base.name); +} + +static void afbc_hw_disable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_afbc *afbc = to_afbc_block(vblk); + u32 osd_index = vblk->index; + + osd_afbc_enable(osd_index, 0); + + DRM_DEBUG("%s disable called.\n", afbc->base.name); +} + +static void afbc_hw_init(struct meson_vpu_block *vblk) +{ + struct meson_vpu_afbc *afbc = to_afbc_block(vblk); + + switch_vpu_mem_pd_vmod(VPU_MAIL_AFBCD, + VPU_MEM_POWER_ON); + /* disable osd1 afbc */ + osd_afbc_enable(0, 0); + osd_afbc_enable(1, 0); + osd_afbc_enable(2, 0); + + DRM_DEBUG("%s hw_init called.\n", afbc->base.name); +} + +struct meson_vpu_block_ops afbc_ops = { + .check_state = afbc_check_state, + .update_state = afbc_set_state, + .enable = afbc_hw_enable, + .disable = afbc_hw_disable, + .init = afbc_hw_init, +}; diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c new file mode 100644 index 0000000..64eadf8 --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c @@ -0,0 +1,616 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "meson_vpu_pipeline.h" +#include "meson_vpu_reg.h" +#include "meson_vpu_util.h" +#include "meson_osd_scaler.h" + +static struct osd_scaler_reg_s osd_scaler_reg[HW_OSD_SCALER_NUM] = { + { + VPP_OSD_SCALE_COEF_IDX, + VPP_OSD_SCALE_COEF, + VPP_OSD_VSC_PHASE_STEP, + VPP_OSD_VSC_INI_PHASE, + VPP_OSD_VSC_CTRL0, + VPP_OSD_HSC_PHASE_STEP, + VPP_OSD_HSC_INI_PHASE, + VPP_OSD_HSC_CTRL0, + VPP_OSD_HSC_INI_PAT_CTRL, + VPP_OSD_SC_DUMMY_DATA, + VPP_OSD_SC_CTRL0, + VPP_OSD_SCI_WH_M1, + VPP_OSD_SCO_H_START_END, + VPP_OSD_SCO_V_START_END, + }, + { + OSD2_SCALE_COEF_IDX, + OSD2_SCALE_COEF, + OSD2_VSC_PHASE_STEP, + OSD2_VSC_INI_PHASE, + OSD2_VSC_CTRL0, + OSD2_HSC_PHASE_STEP, + OSD2_HSC_INI_PHASE, + OSD2_HSC_CTRL0, + OSD2_HSC_INI_PAT_CTRL, + OSD2_SC_DUMMY_DATA, + OSD2_SC_CTRL0, + OSD2_SCI_WH_M1, + OSD2_SCO_H_START_END, + OSD2_SCO_V_START_END, + }, + { + OSD34_SCALE_COEF_IDX, + OSD34_SCALE_COEF, + OSD34_VSC_PHASE_STEP, + OSD34_VSC_INI_PHASE, + OSD34_VSC_CTRL0, + OSD34_HSC_PHASE_STEP, + OSD34_HSC_INI_PHASE, + OSD34_HSC_CTRL0, + OSD34_HSC_INI_PAT_CTRL, + OSD34_SC_DUMMY_DATA, + OSD34_SC_CTRL0, + OSD34_SCI_WH_M1, + OSD34_SCO_H_START_END, + OSD34_SCO_V_START_END, + } +}; + +static unsigned int __osd_filter_coefs_bicubic[] = { /* bicubic coef0 */ + 0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300, 0xfd7e0500, 0xfc7e0600, + 0xfb7d0800, 0xfb7c0900, 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff, + 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe, 0xf76f1dfd, 0xf76d1ffd, + 0xf76b21fd, 0xf76824fd, 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb, + 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa, 0xf8523cfa, 0xf8503ff9, + 0xf84d42f9, 0xf84a45f9, 0xf84848f8 +}; + +/*********vsc config begin**********/ +/*vsc phase_step=(v_in << 20)/v_out */ +void osd_vsc_phase_step_set(struct osd_scaler_reg_s *reg, u32 phase_step) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_phase_step, + phase_step, 0, 28); +} +/*vsc init phase*/ +void osd_vsc_init_phase_set(struct osd_scaler_reg_s *reg, + u32 bottom_init_phase, u32 top_init_phase) +{ + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_vsc_ini_phase, + (bottom_init_phase << 16) | + (top_init_phase << 0)); +} +/*vsc control*/ +/*vsc enable last line repeate*/ +void osd_vsc_repate_last_line_enable_set( + struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 25, 1); +} +/*vsc enable*/ +void osd_vsc_enable_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 24, 1); +} +/*vsc input Interlaced or Progressive:0->P;1->I*/ +void osd_vsc_output_format_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 23, 1); +} +/* + *vsc double line mode + *bit0:change line buffer becomes 2 lines + *bit1:double input width and half input height + */ +void osd_vsc_double_line_mode_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 21, 2); +} +/*vsc phase always on*/ +void osd_vsc_phase_always_on_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 20, 1); +} +/*vsc nearest en*/ +void osd_vsc_nearest_en_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 19, 1); +} +/*vsc repeate bottom field line0 num*/ +void osd_vsc_bot_rpt_l0_num_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 16, 2); +} +/*vsc bottom field init receive num??*/ +void osd_vsc_bot_ini_rcv_num_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 11, 4); +} +/*vsc repeate top field line0 num*/ +void osd_vsc_top_rpt_l0_num_set(struct osd_scaler_reg_s *reg, u32 flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 8, 2); +} +/*vsc top field init receive num??*/ +void osd_vsc_top_ini_rcv_num_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 3, 4); +} +/*vsc bank length??*/ +void osd_vsc_bank_length_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 0, 2); +} +/*********vsc config end**********/ + +/*********hsc config begin**********/ +/*hsc phase_step=(v_in << 20)/v_out */ +void osd_hsc_phase_step_set(struct osd_scaler_reg_s *reg, u32 phase_step) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_phase_step, + phase_step, 0, 28); +} +/*vsc init phase*/ +void osd_hsc_init_phase_set(struct osd_scaler_reg_s *reg, + u32 init_phase0, u32 init_phase1) +{ + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_hsc_ini_phase, + (init_phase1 << 16) | (init_phase0 << 0)); +} +/*hsc control*/ +/*hsc enable*/ +void osd_hsc_enable_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 22, 1); +} +/* hsc double pixel mode */ +void osd_hsc_double_line_mode_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 21, 1); +} +/*hsc phase always on*/ +void osd_hsc_phase_always_on_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 20, 1); +} +/*hsc nearest en*/ +void osd_hsc_nearest_en_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 19, 1); +} +/*hsc repeate pixel0 num1??*/ +void osd_hsc_rpt_p0_num1_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 16, 2); +} +/*hsc init receive num1*/ +void osd_vsc_ini_rcv_num1_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 11, 4); +} +/*hsc repeate pixel0 num0*/ +void osd_hsc_rpt_p0_num0_set(struct osd_scaler_reg_s *reg, u32 flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 8, 2); +} +/*hsc init receive num0*/ +void osd_hsc_ini_rcv_num0_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 3, 4); +} +/*hsc bank length*/ +void osd_hsc_bank_length_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 0, 2); +} +/* + *hsc init pattern + *[15:8]pattern + *[6:4]pattern start + *[2:0]pattern end + */ +void osd_hsc_ini_pat_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_hsc_ini_pat_ctrl, data); +} +/*********hsc config end**********/ + +/*********sc top ctrl start**********/ +/* + *dummy data: + *[31:24]componet0 + *[23:16]componet1 + *[15:8]componet2 + *[7:0]alpha + */ +void osd_sc_dummy_data_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_sc_dummy_data, data); +} +/*sc gate clock*/ +void osd_sc_gclk_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, data, 16, 12); +} +/* + *sc input data alpha mode + *0:(alpha>=128)?alpha-1:alpha + *1:(alpha>=1)?alpha-1:alpha + */ +void osd_sc_din_alpha_mode_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 13, 1); +} +/* + *sc output data alpha mode + *0:(alpha>=128)?alpha+1:alpha + *1:(alpha>=1)?alpha+1:alpha + */ +void osd_sc_dout_alpha_mode_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 12, 1); +} +/*sc alpha*/ +void osd_sc_alpha_set(struct osd_scaler_reg_s *reg, u32 data) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, data, 4, 8); +} +/*sc path en*/ +void osd_sc_path_en_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 3, 1); +} +/*sc en*/ +void osd_sc_en_set(struct osd_scaler_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 2, 1); +} +/*sc input width minus 1*/ +void osd_sc_in_w_set(struct osd_scaler_reg_s *reg, u32 size) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sci_wh_m1, (size - 1), 16, 13); +} +/*sc input height minus 1*/ +void osd_sc_in_h_set(struct osd_scaler_reg_s *reg, u32 size) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sci_wh_m1, (size - 1), 0, 13); +} +/*sc output horizontal size = end - start + 1*/ +void osd_sc_out_horz_set(struct osd_scaler_reg_s *reg, u32 start, u32 end) +{ + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_sco_h_start_end, + (start & 0xfff << 16) | (end & 0xfff)); +} + +/*sc output vertical size = end - start + 1*/ +void osd_sc_out_vert_set(struct osd_scaler_reg_s *reg, u32 start, u32 end) +{ + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_sco_v_start_end, + (start & 0xfff << 16) | (end & 0xfff)); +} + +/* + *sc h/v coef + *1:config horizontal coef + *0:config vertical coef + */ +void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag) +{ + u8 i; + + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef_idx, + (0 << 15) |/*index increment. 1bits*/ + (0 << 14) |/*read coef enable, 1bits*/ + (0 << 9) |/*coef bit mode 8 or 9. 1bits*/ + (flag << 8) | + (0 << 0)/*coef index 7bits*/); + for (i = 0; i < 33; i++) + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef, + __osd_filter_coefs_bicubic[i]); +} +/*********sc top ctrl end************/ +static void f2v_get_vertical_phase( + u32 zoom_ratio, enum f2v_vphase_type_e type, + u8 bank_length, struct f2v_vphase_s *vphase) +{ + u8 f2v_420_in_pos_luma[F2V_TYPE_MAX] = { + 0, 2, 0, 2, 0, 0, 0, 2, 0}; + u8 f2v_420_out_pos[F2V_TYPE_MAX] = { + 0, 2, 2, 0, 0, 2, 0, 0, 0}; + s32 offset_in, offset_out; + + /* luma */ + offset_in = f2v_420_in_pos_luma[type] + << OSD_PHASE_BITS; + offset_out = (f2v_420_out_pos[type] * zoom_ratio) + >> (OSD_ZOOM_HEIGHT_BITS - OSD_PHASE_BITS); + + vphase->rcv_num = bank_length; + if (bank_length == 4 || bank_length == 3) + vphase->rpt_num = 1; + else + vphase->rpt_num = 0; + + if (offset_in > offset_out) { + vphase->rpt_num = vphase->rpt_num + 1; + vphase->phase = + ((4 << OSD_PHASE_BITS) + offset_out - offset_in) + >> 2; + } else { + while ((offset_in + (4 << OSD_PHASE_BITS)) + <= offset_out) { + if (vphase->rpt_num == 1) + vphase->rpt_num = 0; + else + vphase->rcv_num++; + offset_in += 4 << OSD_PHASE_BITS; + } + vphase->phase = (offset_out - offset_in) >> 2; + } +} +void osd_scaler_config(struct osd_scaler_reg_s *reg, + struct meson_vpu_scaler_state *scaler_state, + struct meson_vpu_block *vblk) +{ + struct meson_vpu_scaler *scaler = to_scaler_block(vblk); + u32 phase_step_v, phase_step_h, vsc_top_init_rec_num, vsc_bank_length; + u32 hsc_init_rec_num, hsc_init_rpt_p0_num, hsc_bank_length; + u32 vsc_bot_init_rec_num, vsc_top_rpt_l0_num, vsc_bot_rpt_l0_num; + u32 vsc_top_init_phase, vsc_bot_init_phase; + struct f2v_vphase_s vphase; + u8 version = vblk->pipeline->osd_version; + u32 linebuffer = scaler->linebuffer; + u32 bank_length = scaler->bank_length; + u32 width_in = scaler_state->input_width; + u32 height_in = scaler_state->input_height; + u32 width_out = scaler_state->output_width; + u32 height_out = scaler_state->output_height; + u32 scan_mode_out = scaler_state->scan_mode_out; + bool scaler_enable; + + if (width_in == width_out && height_in == height_out && + version > OSD_V2) + scaler_enable = false; + else + scaler_enable = true; + + if (width_out > linebuffer) + vsc_bank_length = bank_length >> 1; + else + vsc_bank_length = bank_length; + hsc_init_rec_num = bank_length; + hsc_bank_length = bank_length; + hsc_init_rpt_p0_num = bank_length / 2 - 1; + + if (version <= OSD_V2) + phase_step_v = ((height_in - 1) << OSD_ZOOM_HEIGHT_BITS) / + height_out; + else + phase_step_v = + (height_in << OSD_ZOOM_HEIGHT_BITS) / height_out; + if (scan_mode_out) { + f2v_get_vertical_phase(phase_step_v, F2V_P2IT, + vsc_bank_length, &vphase); + vsc_top_init_rec_num = vphase.rcv_num; + vsc_top_rpt_l0_num = vphase.rpt_num; + vsc_top_init_phase = vphase.phase; + f2v_get_vertical_phase(phase_step_v, F2V_P2IB, + vsc_bank_length, &vphase); + vsc_bot_init_rec_num = vphase.rcv_num; + vsc_bot_rpt_l0_num = vphase.rpt_num; + vsc_bot_init_phase = vphase.phase; + } else { + f2v_get_vertical_phase( + phase_step_v, F2V_P2P, + vsc_bank_length, &vphase); + vsc_top_init_rec_num = vphase.rcv_num; + vsc_top_rpt_l0_num = vphase.rpt_num; + vsc_top_init_phase = vphase.phase; + vsc_bot_init_rec_num = 0; + vsc_bot_rpt_l0_num = 0; + vsc_bot_init_phase = 0; + } + if (version <= OSD_V2) + vsc_top_init_rec_num++; + if (version <= OSD_V2 && scan_mode_out) + vsc_bot_init_rec_num++; + phase_step_v <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_HEIGHT_BITS); + phase_step_h = (width_in << OSD_ZOOM_WIDTH_BITS) / width_out; + phase_step_h <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_WIDTH_BITS); + + /*input size config*/ + osd_sc_in_h_set(reg, height_in); + osd_sc_in_w_set(reg, width_in); + + /*output size config*/ + osd_sc_out_horz_set(reg, 0, width_out - 1); + osd_sc_out_vert_set(reg, 0, height_out - 1); + + /*phase step config*/ + osd_vsc_phase_step_set(reg, phase_step_v); + osd_hsc_phase_step_set(reg, phase_step_h); + + /*dummy data config*/ + osd_sc_dummy_data_set(reg, 0x80808080); + + /*h/v coef config*/ + osd_sc_coef_set(reg, 1); + osd_sc_coef_set(reg, 0); + + /*init recv line num*/ + osd_vsc_top_ini_rcv_num_set(reg, vsc_top_init_rec_num); + osd_vsc_bot_ini_rcv_num_set(reg, vsc_bot_init_rec_num); + osd_hsc_ini_rcv_num0_set(reg, hsc_init_rec_num); + + /*repeate line0 num*/ + osd_vsc_top_rpt_l0_num_set(reg, vsc_top_rpt_l0_num); + osd_vsc_bot_rpt_l0_num_set(reg, vsc_bot_rpt_l0_num); + osd_hsc_rpt_p0_num0_set(reg, hsc_init_rpt_p0_num); + + /*init phase*/ + osd_vsc_init_phase_set(reg, vsc_bot_init_phase, vsc_top_init_phase); + osd_hsc_init_phase_set(reg, 0, 0); + + /*vsc bank length*/ + osd_vsc_bank_length_set(reg, vsc_bank_length); + osd_hsc_bank_length_set(reg, hsc_bank_length); + + /*out scan mode*/ + osd_vsc_output_format_set(reg, scan_mode_out ? 1:0); + + /*repeate last line*/ + if (version >= OSD_V2) + osd_vsc_repate_last_line_enable_set(reg, 1); + + /*eanble sc*/ + osd_vsc_enable_set(reg, scaler_enable); + osd_hsc_enable_set(reg, scaler_enable); + osd_sc_en_set(reg, scaler_enable); + osd_sc_path_en_set(reg, scaler_enable); +} + +static void scaler_size_check(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + struct meson_vpu_pipeline *pipeline = vblk->pipeline; + struct meson_vpu_pipeline_state *pipeline_state; + struct meson_vpu_scaler_state *scaler_state = to_scaler_state(state); + + pipeline_state = priv_to_pipeline_state(pipeline->obj.state); + if (!pipeline_state) { + DRM_DEBUG("pipeline_state is NULL!!\n"); + return; + } + if (scaler_state->input_width != + pipeline_state->scaler_param[vblk->index].input_width) { + scaler_state->input_width = + pipeline_state->scaler_param[vblk->index].input_width; + scaler_state->state_changed |= SCALER_INPUT_WIDTH_CHANGED; + } + if (scaler_state->input_height != + pipeline_state->scaler_param[vblk->index].input_height) { + scaler_state->input_height = + pipeline_state->scaler_param[vblk->index].input_height; + scaler_state->state_changed |= SCALER_INPUT_HEIGHT_CHANGED; + } + if (scaler_state->output_width != + pipeline_state->scaler_param[vblk->index].output_width) { + scaler_state->output_width = + pipeline_state->scaler_param[vblk->index].output_width; + scaler_state->state_changed |= SCALER_OUTPUT_WIDTH_CHANGED; + } + if (scaler_state->output_height != + pipeline_state->scaler_param[vblk->index].output_height) { + scaler_state->output_height = + pipeline_state->scaler_param[vblk->index].output_height; + scaler_state->state_changed |= SCALER_OUTPUT_HEIGHT_CHANGED; + } +} + +void scan_mode_check(struct meson_vpu_pipeline *pipeline, + struct meson_vpu_scaler_state *scaler_state) +{ + u32 scan_mode_out = pipeline->mode.flags & DRM_MODE_FLAG_INTERLACE; + + if (scaler_state->scan_mode_out != scan_mode_out) { + scaler_state->scan_mode_out = scan_mode_out; + scaler_state->state_changed |= + SCALER_OUTPUT_SCAN_MODE_CHANGED; + } +} + +static int scaler_check_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state, + struct meson_vpu_pipeline_state *mvps) +{ + struct meson_vpu_scaler *scaler = to_scaler_block(vblk); + + if (state->checked) + return 0; + + state->checked = true; + DRM_DEBUG("%s check_state called.\n", scaler->base.name); + + return 0; +} + +static void scaler_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + struct meson_vpu_scaler *scaler = to_scaler_block(vblk); + struct meson_vpu_scaler_state *scaler_state = to_scaler_state(state); + struct osd_scaler_reg_s *reg = scaler->reg; + + if (!scaler_state) { + DRM_DEBUG("scaler or scaler_state is NULL!!\n"); + return; + } + scaler_size_check(vblk, state); + scan_mode_check(vblk->pipeline, scaler_state); + DRM_DEBUG("scaler_state=0x%x\n", scaler_state->state_changed); + if (scaler_state->state_changed) { + osd_scaler_config(reg, scaler_state, vblk); + scaler_state->state_changed = 0; + } + DRM_DEBUG("scaler%d input/output w/h[%d, %d, %d, %d].\n", + scaler->base.index, + scaler_state->input_width, scaler_state->input_height, + scaler_state->output_width, scaler_state->output_height); +} + +static void scaler_hw_enable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_scaler *scaler = to_scaler_block(vblk); + struct osd_scaler_reg_s *reg = scaler->reg; + + osd_sc_en_set(reg, 1); + osd_sc_path_en_set(reg, 1); + DRM_DEBUG("%s enable done.\n", scaler->base.name); +} + +static void scaler_hw_disable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_scaler *scaler = to_scaler_block(vblk); + struct osd_scaler_reg_s *reg = scaler->reg; + + /*disable sc*/ + osd_sc_en_set(reg, 0); + osd_sc_path_en_set(reg, 0); + DRM_DEBUG("%s disable called.\n", scaler->base.name); +} + +static void scaler_hw_init(struct meson_vpu_block *vblk) +{ + struct meson_vpu_scaler *scaler = to_scaler_block(vblk); + + scaler->reg = &osd_scaler_reg[vblk->index]; + scaler->linebuffer = OSD_SCALE_LINEBUFFER; + scaler->bank_length = OSD_SCALE_BANK_LENGTH; + /*disable sc*/ + osd_sc_en_set(scaler->reg, 0); + osd_sc_path_en_set(scaler->reg, 0); + DRM_DEBUG("%s hw_init called.\n", scaler->base.name); +} + +struct meson_vpu_block_ops scaler_ops = { + .check_state = scaler_check_state, + .update_state = scaler_set_state, + .enable = scaler_hw_enable, + .disable = scaler_hw_disable, + .init = scaler_hw_init, +}; diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h new file mode 100644 index 0000000..34ebb03 --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h @@ -0,0 +1,118 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _MESON_OSD_SCALER_H_ +#define _MESON_OSD_SCALER_H_ + +#define HW_OSD_SCALER_NUM 3 + +/*vpp osd scaler*/ +#define VPP_OSD_VSC_PHASE_STEP 0x1dc0 +#define VPP_OSD_VSC_INI_PHASE 0x1dc1 +#define VPP_OSD_VSC_CTRL0 0x1dc2 +#define VPP_OSD_HSC_PHASE_STEP 0x1dc3 +#define VPP_OSD_HSC_INI_PHASE 0x1dc4 +#define VPP_OSD_HSC_CTRL0 0x1dc5 +#define VPP_OSD_HSC_INI_PAT_CTRL 0x1dc6 +#define VPP_OSD_SC_DUMMY_DATA 0x1dc7 +#define VPP_OSD_SC_CTRL0 0x1dc8 +#define VPP_OSD_SCI_WH_M1 0x1dc9 +#define VPP_OSD_SCO_H_START_END 0x1dca +#define VPP_OSD_SCO_V_START_END 0x1dcb +#define VPP_OSD_SCALE_COEF_IDX 0x1dcc +#define VPP_OSD_SCALE_COEF 0x1dcd + +/* vpp osd2 scaler */ +#define OSD2_VSC_PHASE_STEP 0x3d00 +#define OSD2_VSC_INI_PHASE 0x3d01 +#define OSD2_VSC_CTRL0 0x3d02 +#define OSD2_HSC_PHASE_STEP 0x3d03 +#define OSD2_HSC_INI_PHASE 0x3d04 +#define OSD2_HSC_CTRL0 0x3d05 +#define OSD2_HSC_INI_PAT_CTRL 0x3d06 +#define OSD2_SC_DUMMY_DATA 0x3d07 +#define OSD2_SC_CTRL0 0x3d08 +#define OSD2_SCI_WH_M1 0x3d09 +#define OSD2_SCO_H_START_END 0x3d0a +#define OSD2_SCO_V_START_END 0x3d0b +#define OSD2_SCALE_COEF_IDX 0x3d18 +#define OSD2_SCALE_COEF 0x3d19 + +/* vpp osd34 scaler */ +#define OSD34_VSC_PHASE_STEP 0x3d20 +#define OSD34_VSC_INI_PHASE 0x3d21 +#define OSD34_VSC_CTRL0 0x3d22 +#define OSD34_HSC_PHASE_STEP 0x3d23 +#define OSD34_HSC_INI_PHASE 0x3d24 +#define OSD34_HSC_CTRL0 0x3d25 +#define OSD34_HSC_INI_PAT_CTRL 0x3d26 +#define OSD34_SC_DUMMY_DATA 0x3d27 +#define OSD34_SC_CTRL0 0x3d28 +#define OSD34_SCI_WH_M1 0x3d29 +#define OSD34_SCO_H_START_END 0x3d2a +#define OSD34_SCO_V_START_END 0x3d2b +#define OSD34_SCALE_COEF_IDX 0x3d1e +#define OSD34_SCALE_COEF 0x3d1f + + +/*macro define for chip const*/ +/*bank length is related to scale fifo:4 line 1920??*/ +#define OSD_SCALE_BANK_LENGTH 4 +#define OSD_SCALE_LINEBUFFER 1920 + +#define OSD_ZOOM_WIDTH_BITS 18 +#define OSD_ZOOM_HEIGHT_BITS 20 +#define OSD_ZOOM_TOTAL_BITS 24 +#define OSD_PHASE_BITS 16 + +enum f2v_vphase_type_e { + F2V_IT2IT = 0, + F2V_IB2IB, + F2V_IT2IB, + F2V_IB2IT, + F2V_P2IT, + F2V_P2IB, + F2V_IT2P, + F2V_IB2P, + F2V_P2P, + F2V_TYPE_MAX +}; + +struct f2v_vphase_s { + u8 rcv_num; + u8 rpt_num; + u16 phase; +}; + +struct osd_scaler_reg_s { + u32 vpp_osd_scale_coef_idx; + u32 vpp_osd_scale_coef; + u32 vpp_osd_vsc_phase_step; + u32 vpp_osd_vsc_ini_phase; + u32 vpp_osd_vsc_ctrl0; + u32 vpp_osd_hsc_phase_step; + u32 vpp_osd_hsc_ini_phase; + u32 vpp_osd_hsc_ctrl0; + u32 vpp_osd_hsc_ini_pat_ctrl; + u32 vpp_osd_sc_dummy_data; + u32 vpp_osd_sc_ctrl0; + u32 vpp_osd_sci_wh_m1; + u32 vpp_osd_sco_h_start_end; + u32 vpp_osd_sco_v_start_end; +}; + +#endif diff --git a/drivers/amlogic/drm/am_meson_vpu.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c index 03adbbe..e279690 100644 --- a/drivers/amlogic/drm/am_meson_vpu.h +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/drm/am_meson_vpu.h + * drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -14,11 +14,23 @@ * more details. * */ -#ifndef __AM_MESON_VPU_H -#define __AM_MESON_VPU_H -struct am_meson_vpu_data { - uint32_t version; +struct vpu_dev_func { + void (*hw_init)(); + void (*hw_exit)(); }; -#endif /* __AM_MESON_VPU_H */ +static struct vpu_dev_func g12a = { + .hw_init = g12a_hw_init, + .hw_exit = g12a_hw_exit, +}; + +static struct vpu_dev_func g12b = { + .hw_init = g12b_hw_init, + .hw_exit = g12b_hw_exit, +}; + +static struct vpu_dev_func tl1 = { + .hw_init = tl1_hw_init, + .hw_exit = tl1_hw_exit, +}; diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c new file mode 100644 index 0000000..39563bf --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c @@ -0,0 +1,110 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "meson_vpu_pipeline.h" + +static int hdr_check_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state, + struct meson_vpu_pipeline_state *mvps) +{ + struct meson_vpu_hdr *hdr = to_hdr_block(vblk); + + if (state->checked) + return 0; + + state->checked = true; + + //vpu_block_check_input(vblk, state, mvps); + + DRM_DEBUG("%s set_state called.\n", hdr->base.name); + return 0; +} + +static void hdr_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + struct meson_vpu_hdr *hdr = to_hdr_block(vblk); + //struct meson_vpu_hdr_state *hdr_state = to_hdr_state(state); + + DRM_DEBUG("%s set_state called.\n", hdr->base.name); +} + +static void hdr_enable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_hdr *hdr = to_hdr_block(vblk); + + DRM_DEBUG("%s enable called.\n", hdr->base.name); +} + +static void hdr_disable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_hdr *hdr = to_hdr_block(vblk); + + DRM_DEBUG("%s disable called.\n", hdr->base.name); +} + +struct meson_vpu_block_ops hdr_ops = { + .check_state = hdr_check_state, + .update_state = hdr_set_state, + .enable = hdr_enable, + .disable = hdr_disable, +}; + +static int dolby_check_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state, + struct meson_vpu_pipeline_state *mvps) +{ + struct meson_vpu_dolby *dolby = to_dolby_block(vblk); + + if (state->checked) + return 0; + + state->checked = true; + + //vpu_block_check_input(vblk, state, mvps); + + DRM_DEBUG("%s check_state called.\n", dolby->base.name); + return 0; +} +static void dolby_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + struct meson_vpu_dolby *dolby = to_dolby_block(vblk); + + DRM_DEBUG("%s set_state called.\n", dolby->base.name); +} + +static void dolby_enable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_dolby *dolby = to_dolby_block(vblk); + + DRM_DEBUG("%s enable called.\n", dolby->base.name); +} + +static void dolby_disable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_dolby *dolby = to_dolby_block(vblk); + + DRM_DEBUG("%s disable called.\n", dolby->base.name); +} + +struct meson_vpu_block_ops dolby_ops = { + .check_state = dolby_check_state, + .update_state = dolby_set_state, + .enable = dolby_enable, + .disable = dolby_disable, +}; diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c new file mode 100644 index 0000000..ddc9bc2 --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c @@ -0,0 +1,436 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS +#include <linux/amlogic/media/canvas/canvas.h> +#include <linux/amlogic/media/canvas/canvas_mgr.h> +#endif +#include "meson_vpu_pipeline.h" +#include "meson_vpu_reg.h" +#include "meson_vpu_util.h" + +static struct osd_mif_reg_s osd_mif_reg[HW_OSD_MIF_NUM] = { + { + VIU_OSD1_CTRL_STAT, + VIU_OSD1_CTRL_STAT2, + VIU_OSD1_COLOR_ADDR, + VIU_OSD1_COLOR, + VIU_OSD1_TCOLOR_AG0, + VIU_OSD1_TCOLOR_AG1, + VIU_OSD1_TCOLOR_AG2, + VIU_OSD1_TCOLOR_AG3, + VIU_OSD1_BLK0_CFG_W0, + VIU_OSD1_BLK0_CFG_W1, + VIU_OSD1_BLK0_CFG_W2, + VIU_OSD1_BLK0_CFG_W3, + VIU_OSD1_BLK0_CFG_W4, + VIU_OSD1_BLK1_CFG_W4, + VIU_OSD1_BLK2_CFG_W4, + VIU_OSD1_FIFO_CTRL_STAT, + VIU_OSD1_TEST_RDDATA, + VIU_OSD1_PROT_CTRL, + VIU_OSD1_MALI_UNPACK_CTRL, + VIU_OSD1_DIMM_CTRL, + }, + { + VIU_OSD2_CTRL_STAT, + VIU_OSD2_CTRL_STAT2, + VIU_OSD2_COLOR_ADDR, + VIU_OSD2_COLOR, + VIU_OSD2_TCOLOR_AG0, + VIU_OSD2_TCOLOR_AG1, + VIU_OSD2_TCOLOR_AG2, + VIU_OSD2_TCOLOR_AG3, + VIU_OSD2_BLK0_CFG_W0, + VIU_OSD2_BLK0_CFG_W1, + VIU_OSD2_BLK0_CFG_W2, + VIU_OSD2_BLK0_CFG_W3, + VIU_OSD2_BLK0_CFG_W4, + VIU_OSD2_BLK1_CFG_W4, + VIU_OSD2_BLK2_CFG_W4, + VIU_OSD2_FIFO_CTRL_STAT, + VIU_OSD2_TEST_RDDATA, + VIU_OSD2_PROT_CTRL, + VIU_OSD2_MALI_UNPACK_CTRL, + VIU_OSD2_DIMM_CTRL, + }, + { + VIU_OSD3_CTRL_STAT, + VIU_OSD3_CTRL_STAT2, + VIU_OSD3_COLOR_ADDR, + VIU_OSD3_COLOR, + VIU_OSD3_TCOLOR_AG0, + VIU_OSD3_TCOLOR_AG1, + VIU_OSD3_TCOLOR_AG2, + VIU_OSD3_TCOLOR_AG3, + VIU_OSD3_BLK0_CFG_W0, + VIU_OSD3_BLK0_CFG_W1, + VIU_OSD3_BLK0_CFG_W2, + VIU_OSD3_BLK0_CFG_W3, + VIU_OSD3_BLK0_CFG_W4, + VIU_OSD3_BLK1_CFG_W4, + VIU_OSD3_BLK2_CFG_W4, + VIU_OSD3_FIFO_CTRL_STAT, + VIU_OSD3_TEST_RDDATA, + VIU_OSD3_PROT_CTRL, + VIU_OSD3_MALI_UNPACK_CTRL, + VIU_OSD3_DIMM_CTRL, + } +}; + +static unsigned int osd_canvas[3][2] = { + {0x41, 0x42}, {0x43, 0x44}, {0x45, 0x46} }; +static u32 osd_canvas_index[3] = {0, 0, 0}; + +/* + * Internal function to query information for a given format. See + * meson_drm_format_info() for the public API. + */ +const struct meson_drm_format_info *__meson_drm_format_info(u32 format) +{ + static const struct meson_drm_format_info formats[] = { + { .format = DRM_FORMAT_XRGB8888, + .hw_blkmode = 5, .hw_colormat = 1, .alpha_replace = 1 }, + { .format = DRM_FORMAT_XBGR8888, + .hw_blkmode = 5, .hw_colormat = 2, .alpha_replace = 1 }, + { .format = DRM_FORMAT_RGBX8888, + .hw_blkmode = 5, .hw_colormat = 0, .alpha_replace = 1 }, + { .format = DRM_FORMAT_BGRX8888, + .hw_blkmode = 5, .hw_colormat = 3, .alpha_replace = 1 }, + { .format = DRM_FORMAT_ARGB8888, + .hw_blkmode = 5, .hw_colormat = 1, .alpha_replace = 0 }, + { .format = DRM_FORMAT_ABGR8888, + .hw_blkmode = 5, .hw_colormat = 2, .alpha_replace = 0 }, + { .format = DRM_FORMAT_RGBA8888, + .hw_blkmode = 5, .hw_colormat = 0, .alpha_replace = 0 }, + { .format = DRM_FORMAT_BGRA8888, + .hw_blkmode = 5, .hw_colormat = 3, .alpha_replace = 0 }, + { .format = DRM_FORMAT_RGB888, + .hw_blkmode = 7, .hw_colormat = 0, .alpha_replace = 0 }, + { .format = DRM_FORMAT_RGB565, + .hw_blkmode = 4, .hw_colormat = 4, .alpha_replace = 0 }, + { .format = DRM_FORMAT_ARGB1555, + .hw_blkmode = 4, .hw_colormat = 6, .alpha_replace = 0 }, + { .format = DRM_FORMAT_ARGB4444, + .hw_blkmode = 4, .hw_colormat = 5, .alpha_replace = 0 }, + }; + + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (formats[i].format == format) + return &formats[i]; + } + + return NULL; +} +/** + * meson_drm_format_info - query information for a given format + * @format: pixel format (DRM_FORMAT_*) + * + * The caller should only pass a supported pixel format to this function. + * Unsupported pixel formats will generate a warning in the kernel log. + * + * Returns: + * The instance of struct meson_drm_format_info that describes the + * pixel format, or NULL if the format is unsupported. + */ +const struct meson_drm_format_info *meson_drm_format_info(u32 format) +{ + const struct meson_drm_format_info *info; + + info = __meson_drm_format_info(format); + WARN_ON(!info); + return info; +} +/** + * meson_drm_format_hw_blkmode - get the hw_blkmode for format + * @format: pixel format (DRM_FORMAT_*) + * + * Returns: + * The hw_blkmode match the specified pixel format. + */ +static u8 meson_drm_format_hw_blkmode(uint32_t format) +{ + const struct meson_drm_format_info *info; + + info = meson_drm_format_info(format); + return info ? info->hw_blkmode : 0; +} +/** + * meson_drm_format_hw_colormat - get the hw_colormat for format + * @format: pixel format (DRM_FORMAT_*) + * + * Returns: + * The hw_colormat match the specified pixel format. + */ +static u8 meson_drm_format_hw_colormat(uint32_t format) +{ + const struct meson_drm_format_info *info; + + info = meson_drm_format_info(format); + return info ? info->hw_colormat : 0; +} +/** + * meson_drm_format_alpha_replace - get the alpha replace for format + * @format: pixel format (DRM_FORMAT_*) + * + * Returns: + * The alpha_replace match the specified pixel format. + */ +static u8 meson_drm_format_alpha_replace(uint32_t format) +{ + const struct meson_drm_format_info *info; + + info = meson_drm_format_info(format); + return info ? info->alpha_replace : 0; +} +/*osd input size config*/ +void osd_input_size_config(struct osd_mif_reg_s *reg, struct osd_scope_s scope) +{ + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w1, + (scope.h_end << 16) |/*x_end pixels[13bits]*/ + scope.h_start/*x_start pixels[13bits]*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w2, + (scope.v_end << 16) |/*y_end pixels[13bits]*/ + scope.v_start/*y_start pixels[13bits]*/); +} +/*osd canvas config*/ +void osd_canvas_config(struct osd_mif_reg_s *reg, u32 canvas_index) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blk0_cfg_w0, + canvas_index, 16, 8); +} +/*osd mif enable*/ +void osd_block_enable(struct osd_mif_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_ctrl_stat, flag, 0, 1); +} + +/*osd ctrl config*/ +void osd_ctrl_set(struct osd_mif_reg_s *reg) +{ + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_ctrl_stat, + (0 << 31) |/*osd_cfg_sync_en*/ + (0 << 30) |/*Enable free_clk*/ + (0x100 << 12) |/*global alpha*/ + (0 << 11) |/*TEST_RD_EN*/ + (0 << 2) |/*osd_mem_mode 0:canvas_addr*/ + (0 << 1) |/*premult_en*/ + (0 << 0)/*OSD_BLK_ENABLE*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_ctrl_stat2, + (1 << 14) |/*replaced_alpha_en*/ + (0xff << 6) |/*replaced_alpha*/ + (0 << 4) |/*hold fifo lines 2bit*/ + (0 << 3) |/*output fullrange enable 1bit*/ + (0 << 2)/*alpha 9bit mode 1bit*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag0, + (0xff << 24) |/*Y/R*/ + (0xff << 16) |/*CB/G*/ + (0xff << 24) |/*CR/B*/ + (0xff << 24)/*ALPHA*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag1, + (0xff << 24) |/*Y/R*/ + (0xff << 16) |/*CB/G*/ + (0xff << 24) |/*CR/B*/ + (0xff << 24)/*ALPHA*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag2, + (0xff << 24) |/*Y/R*/ + (0xff << 16) |/*CB/G*/ + (0xff << 24) |/*CR/B*/ + (0xff << 24)/*ALPHA*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag3, + (0xff << 24) |/*Y/R*/ + (0xff << 16) |/*CB/G*/ + (0xff << 24) |/*CR/B*/ + (0xff << 24)/*ALPHA*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w0, + (0 << 30) |/*read from ddr[0]/afbc[1]*/ + (0 << 29) |/*y reverse disable*/ + (0 << 28) |/*x reverse disable*/ + (osd_canvas[0][0] << 16) |/*canvas index*/ + (1 << 15) |/*little endian in ddr*/ + (0 << 14) |/*no repeat display y pre line*/ + (0 << 12) |/*no interpolation per pixel*/ + (5 << 8) |/*read from ddr 32bit mode*/ + (0 << 6) |/*TC_ALPHA_EN*/ + (1 << 2) |/*ARGB format for 32bit mode*/ + (0 << 1) |/*interlace en*/ + (0 << 0)/*output odd/even lines sel*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w1, + (1919 << 16) |/*x_end pixels[13bits]*/ + (0 << 0)/*x_start pixels[13bits]*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w2, + (1079 << 16) |/*y_end pixels[13bits]*/ + (0 << 0)/*y_start pixels[13bits]*/); + /*frame addr in linear addr*/ + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk1_cfg_w4, 0); + /*line_stride in linear addr*/ + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk2_cfg_w4, 0); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_fifo_ctrl_stat, + (1 << 31) |/*BURSET_LEN_SEL[2]*/ + (0 << 30) |/*no swap*/ + (0 << 29) |/*div swap*/ + (2 << 24) |/*Fifo_lim 5bits*/ + (2 << 22) |/*Fifo_ctrl 2bits*/ + (0x20 << 12) |/*FIFO_DEPATH_VAL 7bits*/ + (1 << 10) |/*BURSET_LEN_SEL[1:0]*/ + (4 << 5) |/*hold fifo lines 5bits*/ + (0 << 4) |/*CLEAR_ERR*/ + (0 << 3) |/*fifo_sync_rst*/ + (0 << 1) |/*ENDIAN:no conversion*/ + (1 << 0)/*urgent enable*/); + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_mali_unpack_ctrl, + (0 << 31) |/*unpack normal src*/ + (0 << 28) |/*alpha div en*/ + (0 << 26) |/*dividor gating clk*/ + (1 << 24) |/*alpha mapping mode 2bits*/ + (0 << 16) |/*afbc swap 64bit 1bits*/ + (1 << 12) |/*afbcd_r_reorder r 4bits*/ + (2 << 8) |/*afbcd_r_reorder g 4bits*/ + (3 << 4) |/*afbcd_r_reorder b 4bits*/ + (4 << 0)/*afbcd_r_reorder alpha 4bits*/); +} + +static void osd_color_config(struct osd_mif_reg_s *reg, u32 pixel_format) +{ + u8 blk_mode, colormat, alpha_replace; + + blk_mode = meson_drm_format_hw_blkmode(pixel_format); + colormat = meson_drm_format_hw_colormat(pixel_format); + alpha_replace = meson_drm_format_alpha_replace(pixel_format); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blk0_cfg_w0, + blk_mode, 8, 4); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blk0_cfg_w0, + colormat, 2, 4); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_ctrl_stat2, + alpha_replace, 14, 1); +} + +static int osd_check_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state, + struct meson_vpu_pipeline_state *mvps) +{ + struct meson_vpu_osd_layer_info *plane_info; + struct meson_vpu_osd *osd = to_osd_block(vblk); + struct meson_vpu_osd_state *mvos = to_osd_state(state); + + if (state->checked) + return 0; + + state->checked = true; + + if (!mvos || mvos->plane_index >= MESON_MAX_OSDS) { + DRM_INFO("mvos is NULL!\n"); + return -1; + } + DRM_DEBUG("%s check_state called.\n", osd->base.name); + plane_info = &mvps->plane_info[vblk->index]; + mvos->src_x = plane_info->src_x; + mvos->src_y = plane_info->src_y; + mvos->src_w = plane_info->src_w; + mvos->src_h = plane_info->src_h; + mvos->byte_stride = plane_info->byte_stride; + mvos->phy_addr = plane_info->phy_addr; + mvos->pixel_format = plane_info->pixel_format; + return 0; +} + +static void osd_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + struct meson_vpu_osd *osd = to_osd_block(vblk); + struct meson_vpu_osd_state *mvos = to_osd_state(state); + u32 pixel_format, canvas_index, src_h, byte_stride, phy_addr; + struct osd_scope_s scope_src = {0, 1919, 0, 1079}; + struct osd_mif_reg_s *reg = osd->reg; + + if (!vblk) { + DRM_DEBUG("set_state break for NULL.\n"); + return; + } + src_h = mvos->src_h; + byte_stride = mvos->byte_stride; + phy_addr = mvos->phy_addr; + scope_src.h_start = mvos->src_x; + scope_src.h_end = mvos->src_x + mvos->src_w - 1; + scope_src.v_start = mvos->src_y; + scope_src.v_end = mvos->src_y + mvos->src_h - 1; + pixel_format = mvos->pixel_format; + canvas_index = osd_canvas[vblk->index][osd_canvas_index[vblk->index]]; + canvas_config(canvas_index, phy_addr, byte_stride, src_h, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + osd_canvas_index[vblk->index] ^= 1; + osd_canvas_config(reg, canvas_index); + osd_input_size_config(reg, scope_src); + osd_color_config(reg, pixel_format); + DRM_DEBUG("plane_index=%d,HW-OSD=%d\n", + mvos->plane_index, vblk->index); + DRM_DEBUG("canvas_index[%d]=0x%x,phy_addr=0x%x\n", + osd_canvas_index[vblk->index], canvas_index, phy_addr); + DRM_DEBUG("scope h/v start/end:[%d/%d/%d/%d]\n", + scope_src.h_start, scope_src.h_end, + scope_src.v_start, scope_src.v_end); + DRM_DEBUG("%s set_state done.\n", osd->base.name); +} + +static void osd_hw_enable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_osd *osd = to_osd_block(vblk); + struct osd_mif_reg_s *reg = osd->reg; + + if (!vblk) { + DRM_DEBUG("enable break for NULL.\n"); + return; + } + osd_block_enable(reg, 1); + DRM_DEBUG("%s enable done.\n", osd->base.name); +} + +static void osd_hw_disable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_osd *osd = to_osd_block(vblk); + struct osd_mif_reg_s *reg = osd->reg; + + if (!vblk) { + DRM_DEBUG("disable break for NULL.\n"); + return; + } + osd_block_enable(reg, 0); + DRM_DEBUG("%s disable done.\n", osd->base.name); +} + +static void osd_hw_init(struct meson_vpu_block *vblk) +{ + struct meson_vpu_osd *osd = to_osd_block(vblk); + + if (!vblk || !osd) { + DRM_DEBUG("hw_init break for NULL.\n"); + return; + } + osd->reg = &osd_mif_reg[vblk->index]; + osd_ctrl_set(osd->reg); + DRM_DEBUG("%s hw_init done.\n", osd->base.name); +} + +struct meson_vpu_block_ops osd_ops = { + .check_state = osd_check_state, + .update_state = osd_set_state, + .enable = osd_hw_enable, + .disable = osd_hw_disable, + .init = osd_hw_init, +}; diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h new file mode 100644 index 0000000..2a37316 --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h @@ -0,0 +1,153 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _MESON_VPU_OSD_MIF_H_ +#define _MESON_VPU_OSD_MIF_H_ + +#define HW_OSD_MIF_NUM 3 + +#define VIU_OSD1_CTRL_STAT 0x1a10 +#define VIU_OSD1_CTRL_STAT2 0x1a2d +#define VIU_OSD1_COLOR_ADDR 0x1a11 +#define VIU_OSD1_COLOR 0x1a12 +#define VIU_OSD1_TCOLOR_AG0 0x1a17 +#define VIU_OSD1_TCOLOR_AG1 0x1a18 +#define VIU_OSD1_TCOLOR_AG2 0x1a19 +#define VIU_OSD1_TCOLOR_AG3 0x1a1a +#define VIU_OSD1_BLK0_CFG_W0 0x1a1b +#define VIU_OSD1_BLK1_CFG_W0 0x1a1f +#define VIU_OSD1_BLK2_CFG_W0 0x1a23 +#define VIU_OSD1_BLK3_CFG_W0 0x1a27 +#define VIU_OSD1_BLK0_CFG_W1 0x1a1c +#define VIU_OSD1_BLK1_CFG_W1 0x1a20 +#define VIU_OSD1_BLK2_CFG_W1 0x1a24 +#define VIU_OSD1_BLK3_CFG_W1 0x1a28 +#define VIU_OSD1_BLK0_CFG_W2 0x1a1d +#define VIU_OSD1_BLK1_CFG_W2 0x1a21 +#define VIU_OSD1_BLK2_CFG_W2 0x1a25 +#define VIU_OSD1_BLK3_CFG_W2 0x1a29 +#define VIU_OSD1_BLK0_CFG_W3 0x1a1e +#define VIU_OSD1_BLK1_CFG_W3 0x1a22 +#define VIU_OSD1_BLK2_CFG_W3 0x1a26 +#define VIU_OSD1_BLK3_CFG_W3 0x1a2a +#define VIU_OSD1_BLK0_CFG_W4 0x1a13 +#define VIU_OSD1_BLK1_CFG_W4 0x1a14 +#define VIU_OSD1_BLK2_CFG_W4 0x1a15 +#define VIU_OSD1_BLK3_CFG_W4 0x1a16 +#define VIU_OSD1_FIFO_CTRL_STAT 0x1a2b +#define VIU_OSD1_TEST_RDDATA 0x1a2c +#define VIU_OSD1_PROT_CTRL 0x1a2e +#define VIU_OSD1_MALI_UNPACK_CTRL 0x1a2f +#define VIU_OSD1_DIMM_CTRL 0x1adf + +#define VIU_OSD2_CTRL_STAT 0x1a30 +#define VIU_OSD2_CTRL_STAT2 0x1a4d +#define VIU_OSD2_COLOR_ADDR 0x1a31 +#define VIU_OSD2_COLOR 0x1a32 +#define VIU_OSD2_HL1_H_START_END 0x1a33 +#define VIU_OSD2_HL1_V_START_END 0x1a34 +#define VIU_OSD2_HL2_H_START_END 0x1a35 +#define VIU_OSD2_HL2_V_START_END 0x1a36 +#define VIU_OSD2_TCOLOR_AG0 0x1a37 +#define VIU_OSD2_TCOLOR_AG1 0x1a38 +#define VIU_OSD2_TCOLOR_AG2 0x1a39 +#define VIU_OSD2_TCOLOR_AG3 0x1a3a +#define VIU_OSD2_BLK0_CFG_W0 0x1a3b +#define VIU_OSD2_BLK1_CFG_W0 0x1a3f +#define VIU_OSD2_BLK2_CFG_W0 0x1a43 +#define VIU_OSD2_BLK3_CFG_W0 0x1a47 +#define VIU_OSD2_BLK0_CFG_W1 0x1a3c +#define VIU_OSD2_BLK1_CFG_W1 0x1a40 +#define VIU_OSD2_BLK2_CFG_W1 0x1a44 +#define VIU_OSD2_BLK3_CFG_W1 0x1a48 +#define VIU_OSD2_BLK0_CFG_W2 0x1a3d +#define VIU_OSD2_BLK1_CFG_W2 0x1a41 +#define VIU_OSD2_BLK2_CFG_W2 0x1a45 +#define VIU_OSD2_BLK3_CFG_W2 0x1a49 +#define VIU_OSD2_BLK0_CFG_W3 0x1a3e +#define VIU_OSD2_BLK1_CFG_W3 0x1a42 +#define VIU_OSD2_BLK2_CFG_W3 0x1a46 +#define VIU_OSD2_BLK3_CFG_W3 0x1a4a +#define VIU_OSD2_BLK0_CFG_W4 0x1a64 +#define VIU_OSD2_BLK1_CFG_W4 0x1a65 +#define VIU_OSD2_BLK2_CFG_W4 0x1a66 +#define VIU_OSD2_BLK3_CFG_W4 0x1a67 +#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b +#define VIU_OSD2_TEST_RDDATA 0x1a4c +#define VIU_OSD2_PROT_CTRL 0x1a4e +#define VIU_OSD2_MALI_UNPACK_CTRL 0x1abd +#define VIU_OSD2_DIMM_CTRL 0x1acf + +#define VIU_OSD3_CTRL_STAT 0x3d80 +#define VIU_OSD3_CTRL_STAT2 0x3d81 +#define VIU_OSD3_COLOR_ADDR 0x3d82 +#define VIU_OSD3_COLOR 0x3d83 +#define VIU_OSD3_TCOLOR_AG0 0x3d84 +#define VIU_OSD3_TCOLOR_AG1 0x3d85 +#define VIU_OSD3_TCOLOR_AG2 0x3d86 +#define VIU_OSD3_TCOLOR_AG3 0x3d87 +#define VIU_OSD3_BLK0_CFG_W0 0x3d88 +#define VIU_OSD3_BLK0_CFG_W1 0x3d8c +#define VIU_OSD3_BLK0_CFG_W2 0x3d90 +#define VIU_OSD3_BLK0_CFG_W3 0x3d94 +#define VIU_OSD3_BLK0_CFG_W4 0x3d98 +#define VIU_OSD3_BLK1_CFG_W4 0x3d99 +#define VIU_OSD3_BLK2_CFG_W4 0x3d9a +#define VIU_OSD3_FIFO_CTRL_STAT 0x3d9c +#define VIU_OSD3_TEST_RDDATA 0x3d9d +#define VIU_OSD3_PROT_CTRL 0x3d9e +#define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f +#define VIU_OSD3_DIMM_CTRL 0x3da0 + +struct osd_mif_reg_s { + u32 viu_osd_ctrl_stat; + u32 viu_osd_ctrl_stat2; + u32 viu_osd_color_addr; + u32 viu_osd_color; + u32 viu_osd_tcolor_ag0; + u32 viu_osd_tcolor_ag1; + u32 viu_osd_tcolor_ag2; + u32 viu_osd_tcolor_ag3; + u32 viu_osd_blk0_cfg_w0; + u32 viu_osd_blk0_cfg_w1; + u32 viu_osd_blk0_cfg_w2; + u32 viu_osd_blk0_cfg_w3; + u32 viu_osd_blk0_cfg_w4; + u32 viu_osd_blk1_cfg_w4; + u32 viu_osd_blk2_cfg_w4; + u32 viu_osd_fifo_ctrl_stat; + u32 viu_osd_test_rddata; + u32 viu_osd_prot_ctrl; + u32 viu_osd_mali_unpack_ctrl; + u32 viu_osd_dimm_ctrl; +}; + +/** + * struct meson_drm_format_info - information about a DRM format + * @format: 4CC format identifier (DRM_FORMAT_*) + * @hw_blkmode: Define the OSD block’s input pixel format + * @hw_colormat: Applicable only to 16-bit color mode (OSD_BLK_MODE=4), + * 32-bit mode (OSD_BLK_MODE=5) and 24-bit mode (OSD_BLK_MODE=7), + * defines the bit-field allocation of the pixel data. + */ +struct meson_drm_format_info { + u32 format; + u8 hw_blkmode; + u8 hw_colormat; + u8 alpha_replace; +}; +#endif diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c new file mode 100644 index 0000000..f6aa7e8 --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c @@ -0,0 +1,520 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/* Amlogic Headers */ +#include <linux/amlogic/media/vout/vout_notify.h> + +#include "meson_vpu_pipeline.h" +#include "meson_vpu_reg.h" +#include "meson_vpu_util.h" +#include "meson_vpu_osdblend.h" + +static struct osdblend_reg_s osdblend_reg = { + VIU_OSD_BLEND_CTRL, + VIU_OSD_BLEND_DIN0_SCOPE_H, + VIU_OSD_BLEND_DIN0_SCOPE_V, + VIU_OSD_BLEND_DIN1_SCOPE_H, + VIU_OSD_BLEND_DIN1_SCOPE_V, + VIU_OSD_BLEND_DIN2_SCOPE_H, + VIU_OSD_BLEND_DIN2_SCOPE_V, + VIU_OSD_BLEND_DIN3_SCOPE_H, + VIU_OSD_BLEND_DIN3_SCOPE_V, + VIU_OSD_BLEND_DUMMY_DATA0, + VIU_OSD_BLEND_DUMMY_ALPHA, + VIU_OSD_BLEND_BLEND0_SIZE, + VIU_OSD_BLEND_BLEND1_SIZE, + VIU_OSD_BLEND_CTRL1, +}; + +/*0:din0 go through blend0,1:bypass blend0,dirct to Dout0*/ +static void osd_din0_switch_set(struct osdblend_reg_s *reg, + bool bypass_state) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, + bypass_state, 26, 1); +} +/*0:blend1 out to blend2,1:blend1 out to Dout1*/ +static void osd_blend1_dout_switch_set(struct osdblend_reg_s *reg, + bool bypass_state) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, + bypass_state, 25, 1); +} +/*0:din3 pass through blend1,1:bypass blend1,direct to Dout1*/ +static void osd_din3_switch_set(struct osdblend_reg_s *reg, + bool bypass_state) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, + bypass_state, 24, 1); +} +#if 0 +/*0:din0/1/2/3 input disable,1:enable*/ +static void osd_din_input_enable_set(struct osdblend_reg_s *reg, + bool enable, enum din_channel_e din_channel) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, enable, + (20 + din_channel), 1); +} +#endif +/*0:din0 input disable,1:din0 input enable*/ +static void osd_din0_input_enable_set(struct osdblend_reg_s *reg, + bool input_enable) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, + input_enable, 20, 1); +} +/*0:din1 input disable,1:din1 input enable*/ +static void osd_din1_input_enable_set(struct osdblend_reg_s *reg, + bool input_enable) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, + input_enable, 21, 1); +} +/*0:din2 input disable,1:din2 input enable*/ +static void osd_din2_input_enable_set(struct osdblend_reg_s *reg, + bool input_enable) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, + input_enable, 22, 1); +} +/*0:din3 input disable,1:din3 input enable*/ +static void osd_din3_input_enable_set(struct osdblend_reg_s *reg, + bool input_enable) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, + input_enable, 23, 1); +} +#if 0 +/*0:din0/1/2/3 premult disable,1:enable*/ +static void osd_din_premult_enable_set(struct osdblend_reg_s *reg, + bool enable, enum din_channel_e din_channel) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, enable, + (16 + din_channel), 1); +} +#endif +/*1/2/3:din0/1/2/3 select osd1/osd2/osd3,else select null*/ +static void osd_din_channel_mux_set(struct osdblend_reg_s *reg, + enum osd_channel_e osd_channel, + enum din_channel_e din_channel) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, osd_channel, + (0 + din_channel*4), 4); +} +/*din0 scope config*/ +static void osd_din0_scope_set(struct osdblend_reg_s *reg, + struct osd_scope_s scope) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_h, + scope.h_start, 0, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_h, + scope.h_end, 16, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_v, + scope.v_start, 0, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_v, + scope.v_end, 16, 13); +} +/*din1 scope config*/ +static void osd_din1_scope_set(struct osdblend_reg_s *reg, + struct osd_scope_s scope) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_h, + scope.h_start, 0, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_h, + scope.h_end, 16, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_v, + scope.v_start, 0, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_v, + scope.v_end, 16, 13); +} +/*din2 scope config*/ +static void osd_din2_scope_set(struct osdblend_reg_s *reg, + struct osd_scope_s scope) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_h, + scope.h_start, 0, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_h, + scope.h_end, 16, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_v, + scope.v_start, 0, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_v, + scope.v_end, 16, 13); +} +/*din3 scope config*/ +static void osd_din3_scope_set(struct osdblend_reg_s *reg, + struct osd_scope_s scope) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_h, + scope.h_start, 0, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_h, + scope.h_end, 16, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_v, + scope.v_start, 0, 13); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_v, + scope.v_end, 16, 13); +} +/*osd blend dummy data config*/ +static void osd_blend_dummy_data_set(struct osdblend_reg_s *reg, + struct osd_dummy_data_s dummy_data) +{ + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blend_dummy_data0, + ((dummy_data.channel0 & 0xff) << 16) | + ((dummy_data.channel1 & 0xff) << 8) | + (dummy_data.channel2 & 0xff)); +} +/*osd blend0 dummy data alpha config*/ +static void osd_blend0_dummy_alpha_set(struct osdblend_reg_s *reg, + unsigned int dummy_alpha) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_dummy_alpha, + dummy_alpha, 20, 9); +} +/*osd blend1 dummy data alpha config*/ +static void osd_blend1_dummy_alpha_set(struct osdblend_reg_s *reg, + unsigned int dummy_alpha) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_dummy_alpha, + dummy_alpha, 11, 9); +} +/*osd blend2 dummy data alpha config*/ +static void osd_blend2_dummy_alpha_set(struct osdblend_reg_s *reg, + unsigned int dummy_alpha) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_dummy_alpha, + dummy_alpha, 0, 9); +} +/*osd blend0 size config*/ +static void osd_blend0_size_set(struct osdblend_reg_s *reg, + unsigned int h_size, unsigned int v_size) +{ + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blend0_size, + (v_size << 16) | h_size); +} +/*osd blend1 size config*/ +static void osd_blend1_size_set(struct osdblend_reg_s *reg, + unsigned int h_size, unsigned int v_size) +{ + VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blend1_size, + (v_size << 16) | h_size); +} +/*osd blend0 & blend1 4 din inputs premult flag config as 0 default*/ +void osd_blend01_premult_config(struct osdblend_reg_s *reg) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, 0, 16, 4); +} +/*osd blend2 2 inputs premult flag config as 1 default*/ +void osd_blend2_premult_config(struct osdblend_reg_s *reg) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, 3, 27, 2); +} +/*osd blend dout0 output div en config as 1,alpha 9bit default*/ +void osd_blend_dout0_div_config(struct osdblend_reg_s *reg) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 3, 4, 2); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 1, 0, 1); +} +/*osd blend dout1 output div en config as 1,alpha 9bit default*/ +void osd_blend_dout1_div_config(struct osdblend_reg_s *reg) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 3, 16, 2); + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 1, 12, 1); +} +/*osd blend premult config*/ +void osdblend_premult_config(struct osdblend_reg_s *reg) +{ + osd_blend01_premult_config(reg); + osd_blend2_premult_config(reg); + osd_blend_dout0_div_config(reg); + osd_blend_dout1_div_config(reg); +} + +enum osd_channel_e osd2channel(u8 osd_index) +{ + u8 din_channel_seq[MAX_DIN_NUM] = {OSD_CHANNEL1, OSD_CHANNEL2, + OSD_CHANNEL3, OSD_CHANNEL_NUM}; + + if (osd_index >= MAX_DIN_NUM) { + DRM_DEBUG("osd_index:%d overflow!!.\n", osd_index); + return OSD_CHANNEL_NUM; + } + return din_channel_seq[osd_index]; +} + +static void osdblend_hw_update(struct osdblend_reg_s *reg, + struct meson_vpu_osdblend_state *mvobs) +{ + struct osd_dummy_data_s dummy_data = {0, 0, 0}; + + /*din channel mux config*/ + osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN0], DIN0); + osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN1], DIN1); + osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN2], DIN2); + osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN3], DIN3); + + /*dummy data config*/ + osd_blend_dummy_data_set(reg, dummy_data); + + /*alpha config*/ + osd_blend0_dummy_alpha_set(reg, 0x1ff); + osd_blend1_dummy_alpha_set(reg, 0); + osd_blend2_dummy_alpha_set(reg, 0x1ff); + + /*internal channel disable default*/ + osd_din0_input_enable_set(reg, (mvobs->input_mask >> DIN0) & 0x1); + osd_din1_input_enable_set(reg, (mvobs->input_mask >> DIN1) & 0x1); + osd_din2_input_enable_set(reg, (mvobs->input_mask >> DIN2) & 0x1); + osd_din3_input_enable_set(reg, (mvobs->input_mask >> DIN3) & 0x1); + + /*blend switch config*/ + osd_din0_switch_set(reg, mvobs->din0_switch); + osd_din3_switch_set(reg, mvobs->din3_switch); + osd_blend1_dout_switch_set(reg, mvobs->blend1_switch); + + /*scope config*/ + osd_din0_scope_set(reg, mvobs->din_channel_scope[DIN0]); + osd_din1_scope_set(reg, mvobs->din_channel_scope[DIN1]); + osd_din2_scope_set(reg, mvobs->din_channel_scope[DIN2]); + osd_din3_scope_set(reg, mvobs->din_channel_scope[DIN3]); + + /*premult config*/ + osdblend_premult_config(reg); + + /*blend0/blend1 size config*/ + osd_blend0_size_set(reg, mvobs->input_width[OSD_SUB_BLEND0], + mvobs->input_height[OSD_SUB_BLEND0]); + osd_blend1_size_set(reg, mvobs->input_width[OSD_SUB_BLEND1], + mvobs->input_height[OSD_SUB_BLEND1]); +} + +static int osdblend_check_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state, + struct meson_vpu_pipeline_state *mvps) +{ + int ret, num_planes; + u32 *out_port; + u32 i, j, m, n, num_plane_port0, num_plane_port1; + u32 plane_index_port0[MAX_DIN_NUM], plane_index_port1[MAX_DIN_NUM]; + struct meson_vpu_osdblend_state *mvobs; + u32 zorder[MAX_DIN_NUM], max_height = 0, max_width = 0; + int delta_zorder[MAX_DIN_NUM] = {0}; + bool delta_zorder_flag; + struct osd_scope_s scope_default = {0xffff, 0xffff, 0xffff, 0xffff}; + + mvobs = to_osdblend_state(state); + num_planes = mvps->num_plane; + out_port = mvps->dout_index; + + if (state->checked) + return 0; + + state->checked = true; + + ret = 0; + num_plane_port0 = 0; + num_plane_port1 = 0; + DRM_DEBUG("%s check_state called.\n", vblk->name); + for (i = 0; i < MESON_MAX_OSDS; i++) { + if (!mvps->plane_info[i].enable) { + mvobs->input_osd_mask &= ~BIT(i); + continue; + } + mvobs->input_osd_mask |= BIT(i); + if (out_port[i] == OSD_LEND_OUT_PORT1) { + plane_index_port1[num_plane_port1] = + mvps->plane_index[i]; + num_plane_port1++; + } else { + plane_index_port0[num_plane_port0] = + mvps->plane_index[i]; + num_plane_port0++; + } + } + /*check the unsupport case firstly*/ + if (num_plane_port0 > OSD_LEND_MAX_IN_NUM_PORT0 || + num_plane_port1 > OSD_LEND_MAX_IN_NUM_PORT1) + return -1; + if (mvps->pipeline->osd_version <= OSD_V2 && + num_plane_port1) + return -1; + /*zorder check for one dout-port with multi plane*/ + for (i = 0; i < num_plane_port1; i++) { + m = plane_index_port1[i]; + for (j = 0; j < num_plane_port0; j++) { + n = plane_index_port0[j]; + delta_zorder[0] = mvps->plane_info[m].zorder - + mvps->plane_info[n].zorder; + delta_zorder_flag = ((delta_zorder[0] < 0) != + (delta_zorder[1] < 0)); + if (num_plane_port0 >= 2 && j > 0 && + delta_zorder_flag) + return -1; + delta_zorder[1] = delta_zorder[0]; + /*find the max zorder as dout port zorder*/ + if (mvps->dout_zorder[OSD_LEND_OUT_PORT0] < + mvps->plane_info[n].zorder) + mvps->dout_zorder[OSD_LEND_OUT_PORT0] = + mvps->plane_info[n].zorder; + } + delta_zorder[2] = delta_zorder[0]; + delta_zorder_flag = ((delta_zorder[2] < 0) != + (delta_zorder[3] < 0)); + if (num_plane_port1 >= 2 && i > 0 && delta_zorder_flag) + return -1; + delta_zorder[3] = delta_zorder[2]; + if (mvps->dout_zorder[OSD_LEND_OUT_PORT1] < + mvps->plane_info[m].zorder) + mvps->dout_zorder[OSD_LEND_OUT_PORT1] = + mvps->plane_info[m].zorder; + } + /* + *confirm the Din enable and channel mux and sub blend input size + *according to input zorder and dout sel + */ + mvobs->input_mask = 0; + for (i = 0; i < num_plane_port0; i++) { + mvobs->input_mask |= 1 << i; + j = plane_index_port0[i]; + mvobs->din_channel_mux[i] = osd2channel(j); + zorder[i] = mvps->plane_info[j].zorder; + /*blend size calc*/ + if (max_width < mvps->osd_scope_pre[j].h_end + 1) + max_width = mvps->osd_scope_pre[j].h_end + 1; + if (max_height < mvps->osd_scope_pre[j].v_end + 1) + max_height = mvps->osd_scope_pre[j].v_end + 1; + } + for (i = 0; i < num_plane_port0; i++) { + for (j = 1; j < num_plane_port0; j++) { + if (zorder[i] > zorder[j]) { + swap(zorder[i], zorder[j]); + swap(mvobs->din_channel_mux[i], + mvobs->din_channel_mux[j]); + } + } + } + for (i = 0; i < num_plane_port1; i++) { + m = MAX_DIN_NUM - i - 1; + mvobs->input_mask |= 1 << m; + j = plane_index_port1[i]; + mvobs->din_channel_mux[m] = osd2channel(j); + zorder[i] = mvps->plane_info[j].zorder; + /*blend size calc*/ + if (max_width < mvps->osd_scope_pre[j].h_end + 1) + max_width = mvps->osd_scope_pre[j].h_end + 1; + if (max_height < mvps->osd_scope_pre[j].v_end + 1) + max_height = mvps->osd_scope_pre[j].v_end + 1; + } + for (i = 0; i < num_plane_port1; i++) { + for (j = 1; j < num_plane_port1; j++) { + if (zorder[i] > zorder[j]) { + swap(zorder[i], zorder[j]); + swap(mvobs->din_channel_mux[i], + mvobs->din_channel_mux[j]); + } + } + } + for (i = 0; i < MAX_DIN_NUM; i++) { + if (!mvobs->din_channel_mux[i]) + mvobs->din_channel_mux[i] = OSD_CHANNEL_NUM; + } + /*osdblend switch check*/ + mvobs->din0_switch = 0; + if ((mvobs->input_mask & (BIT(DIN2) | BIT(DIN3))) && + num_plane_port0 == 3 && num_plane_port1 == 1) + mvobs->din3_switch = 1; + else + mvobs->din3_switch = 0; + if ((mvobs->input_mask & BIT(DIN2)) && + num_plane_port1 == 2) + mvobs->blend1_switch = 1; + else + mvobs->blend1_switch = 0; + /*scope check*/ + for (i = 0; i < MAX_DIN_NUM; i++) { + if (mvobs->input_osd_mask & BIT(i)) + memcpy(&mvobs->din_channel_scope[i], + &mvps->osd_scope_pre[i], + sizeof(struct osd_scope_s)); + else + memcpy(&mvobs->din_channel_scope[i], + &scope_default, + sizeof(struct osd_scope_s)); + } + /*sub blend size check*/ + mvobs->input_width[OSD_SUB_BLEND0] = max_width; + mvobs->input_width[OSD_SUB_BLEND1] = max_width; + mvobs->input_height[OSD_SUB_BLEND0] = max_height; + mvobs->input_height[OSD_SUB_BLEND1] = max_height; + DRM_DEBUG("%s check done.\n", vblk->name); + return ret; +} + +static void osdblend_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk); + struct meson_vpu_pipeline *pipeline = osdblend->base.pipeline; + struct meson_vpu_osdblend_state *mvobs; + struct meson_vpu_pipeline_state *pipeline_state; + struct osdblend_reg_s *reg = osdblend->reg; + + DRM_DEBUG("%s set_state called.\n", osdblend->base.name); + mvobs = to_osdblend_state(state); + pipeline_state = priv_to_pipeline_state(pipeline->obj.state); + if (!pipeline_state) { + DRM_DEBUG("pipeline_state is NULL!!\n"); + return; + } + + #ifdef OSDBLEND_CHECK_METHOD_COMBINATION + osdblend_layer_set(reg, osdblend, pipeline_state); + #else + osdblend_hw_update(reg, mvobs); + #endif + + DRM_DEBUG("%s set_state done.\n", osdblend->base.name); +} + +static void osdblend_hw_enable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk); + + DRM_DEBUG("%s enable called.\n", osdblend->base.name); +} + +static void osdblend_hw_disable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk); + + DRM_DEBUG("%s disable called.\n", osdblend->base.name); +} + +static void osdblend_hw_init(struct meson_vpu_block *vblk) +{ + struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk); + + osdblend->reg = &osdblend_reg; + DRM_DEBUG("%s hw_init called.\n", osdblend->base.name); +} + +struct meson_vpu_block_ops osdblend_ops = { + .check_state = osdblend_check_state, + .update_state = osdblend_set_state, + .enable = osdblend_hw_enable, + .disable = osdblend_hw_disable, + .init = osdblend_hw_init, +}; + diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h new file mode 100644 index 0000000..3c1f3a6 --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h @@ -0,0 +1,74 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _MESON_VPU_OSDBLEND_H_ +#define _MESON_VPU_OSDBLEND_H_ + +#define OSD_LEND_OUT_PORT0 0 +#define OSD_LEND_OUT_PORT1 1 +#define OSD_SUB_BLEND0 0 +#define OSD_SUB_BLEND1 1 +#define OSD_LEND_MAX_IN_NUM_PORT0 4 +#define OSD_LEND_MAX_IN_NUM_PORT1 2 + +#define VIU_OSD_BLEND_CTRL 0x39b0 +#define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1 +#define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2 +#define VIU_OSD_BLEND_DIN1_SCOPE_H 0x39b3 +#define VIU_OSD_BLEND_DIN1_SCOPE_V 0x39b4 +#define VIU_OSD_BLEND_DIN2_SCOPE_H 0x39b5 +#define VIU_OSD_BLEND_DIN2_SCOPE_V 0x39b6 +#define VIU_OSD_BLEND_DIN3_SCOPE_H 0x39b7 +#define VIU_OSD_BLEND_DIN3_SCOPE_V 0x39b8 +#define VIU_OSD_BLEND_DUMMY_DATA0 0x39b9 +#define VIU_OSD_BLEND_DUMMY_ALPHA 0x39ba +#define VIU_OSD_BLEND_BLEND0_SIZE 0x39bb +#define VIU_OSD_BLEND_BLEND1_SIZE 0x39bc +#define VIU_OSD_BLEND_RO_CURRENT_XY 0x39bf +#define VIU_OSD_BLEND_CTRL1 0x39c0 + +struct osdblend_reg_s { + u32 viu_osd_blend_ctrl; + u32 viu_osd_blend_din0_scope_h; + u32 viu_osd_blend_din0_scope_v; + u32 viu_osd_blend_din1_scope_h; + u32 viu_osd_blend_din1_scope_v; + u32 viu_osd_blend_din2_scope_h; + u32 viu_osd_blend_din2_scope_v; + u32 viu_osd_blend_din3_scope_h; + u32 viu_osd_blend_din3_scope_v; + u32 viu_osd_blend_dummy_data0; + u32 viu_osd_blend_dummy_alpha; + u32 viu_osd_blend0_size; + u32 viu_osd_blend1_size; + u32 viu_osd_blend_ctrl1; +}; + +/*input mif channel*/ +enum osd_channel_e { + OSD_CHANNEL1 = 1, + OSD_CHANNEL2, + OSD_CHANNEL3, + OSD_CHANNEL_NUM +}; + +struct osd_dummy_data_s { + unsigned int channel0;/*y*/ + unsigned int channel1;/*cb*/ + unsigned int channel2;/*cr*/ +}; +#endif diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c new file mode 100644 index 0000000..71ea0aa --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c @@ -0,0 +1,184 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/* Amlogic Headers */ +#include <linux/amlogic/media/vout/vout_notify.h> + +#include "meson_vpu_pipeline.h" +#include "meson_vpu_util.h" +#include "meson_vpu_postblend.h" + +static struct postblend_reg_s postblend_reg = { + VPP_OSD1_BLD_H_SCOPE, + VPP_OSD1_BLD_V_SCOPE, + VPP_OSD2_BLD_H_SCOPE, + VPP_OSD2_BLD_V_SCOPE, + VD1_BLEND_SRC_CTRL, + VD2_BLEND_SRC_CTRL, + OSD1_BLEND_SRC_CTRL, + OSD2_BLEND_SRC_CTRL, +}; + +/*vpp post&post blend for osd1 premult flag config as 0 default*/ +static void osd1_blend_premult_set(struct postblend_reg_s *reg) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, 0, 4, 1); + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, 0, 16, 1); +} + +/*vpp pre&post blend for osd2 premult flag config as 0 default*/ +static void osd2_blend_premult_set(struct postblend_reg_s *reg) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, 0, 4, 1); + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, 0, 16, 1); +} + +/*vpp osd1 blend sel*/ +static void osd1_blend_switch_set(struct postblend_reg_s *reg, + enum vpp_blend_e blend_sel) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, blend_sel, 20, 1); +} + +/*vpp osd2 blend sel*/ +static void osd2_blend_switch_set(struct postblend_reg_s *reg, + enum vpp_blend_e blend_sel) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, blend_sel, 20, 1); +} + +/*vpp osd1 preblend mux sel*/ +static void vpp_osd1_preblend_mux_set(struct postblend_reg_s *reg, + enum vpp_blend_src_e src_sel) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, src_sel, 0, 4); +} + +/*vpp osd2 preblend mux sel*/ +static void vpp_osd2_preblend_mux_set(struct postblend_reg_s *reg, + enum vpp_blend_src_e src_sel) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, src_sel, 0, 4); +} + +/*vpp osd1 postblend mux sel*/ +static void vpp_osd1_postblend_mux_set(struct postblend_reg_s *reg, + enum vpp_blend_src_e src_sel) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, src_sel, 8, 4); +} +/*vpp osd2 postblend mux sel*/ +static void vpp_osd2_postblend_mux_set(struct postblend_reg_s *reg, + enum vpp_blend_src_e src_sel) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, src_sel, 8, 4); +} +/*vpp osd1 blend scope set*/ +static void vpp_osd1_blend_scope_set(struct postblend_reg_s *reg, + struct osd_scope_s scope) +{ + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd1_bld_h_scope, + (scope.h_start << 16) | scope.h_end); + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd1_bld_v_scope, + (scope.v_start << 16) | scope.v_end); +} +/*vpp osd2 blend scope set*/ +static void vpp_osd2_blend_scope_set(struct postblend_reg_s *reg, + struct osd_scope_s scope) +{ + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd2_bld_h_scope, + (scope.h_start << 16) | scope.h_end); + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd2_bld_v_scope, + (scope.v_start << 16) | scope.v_end); +} + +static int postblend_check_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state, + struct meson_vpu_pipeline_state *mvps) +{ + struct meson_vpu_postblend *postblend = to_postblend_block(vblk); + + if (state->checked) + return 0; + + state->checked = true; + + DRM_DEBUG("%s check_state called.\n", postblend->base.name); + return 0; +} + +static void postblend_set_state(struct meson_vpu_block *vblk, + struct meson_vpu_block_state *state) +{ + struct meson_vpu_postblend *postblend = to_postblend_block(vblk); + struct osd_scope_s scope = {0, 1919, 0, 1079}; + struct meson_vpu_pipeline *pipeline = postblend->base.pipeline; + struct postblend_reg_s *reg = postblend->reg; + struct meson_vpu_pipeline_state *mvps; + + DRM_DEBUG("%s set_state called.\n", postblend->base.name); + mvps = priv_to_pipeline_state(pipeline->obj.state); + scope.h_start = 0; + scope.h_end = mvps->scaler_param[0].output_width - 1; + scope.v_start = 0; + scope.v_end = mvps->scaler_param[0].output_height - 1; + vpp_osd1_blend_scope_set(reg, scope); + if (0) + vpp_osd2_blend_scope_set(reg, scope); + osd1_blend_premult_set(reg); + osd2_blend_premult_set(reg); + DRM_DEBUG("scope h/v start/end [%d,%d,%d,%d].\n", + scope.h_start, scope.h_end, scope.v_start, scope.v_end); +} + +static void postblend_hw_enable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_postblend *postblend = to_postblend_block(vblk); + + DRM_DEBUG("%s enable called.\n", postblend->base.name); +} + +static void postblend_hw_disable(struct meson_vpu_block *vblk) +{ + struct meson_vpu_postblend *postblend = to_postblend_block(vblk); + + DRM_DEBUG("%s disable called.\n", postblend->base.name); +} + +static void postblend_hw_init(struct meson_vpu_block *vblk) +{ + struct meson_vpu_postblend *postblend = to_postblend_block(vblk); + + postblend->reg = &postblend_reg; + /*dout switch config*/ + osd1_blend_switch_set(postblend->reg, VPP_POSTBLEND); + osd2_blend_switch_set(postblend->reg, VPP_POSTBLEND); + /*vpp input config*/ + vpp_osd1_preblend_mux_set(postblend->reg, VPP_NULL); + vpp_osd2_preblend_mux_set(postblend->reg, VPP_NULL); + vpp_osd1_postblend_mux_set(postblend->reg, VPP_OSD1); + vpp_osd2_postblend_mux_set(postblend->reg, VPP_NULL); + DRM_DEBUG("%s hw_init called.\n", postblend->base.name); +} + +struct meson_vpu_block_ops postblend_ops = { + .check_state = postblend_check_state, + .update_state = postblend_set_state, + .enable = postblend_hw_enable, + .disable = postblend_hw_disable, + .init = postblend_hw_init, +}; diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h new file mode 100644 index 0000000..9100074 --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h @@ -0,0 +1,59 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _MESON_VPU_POSTBLEND_H_ +#define _MESON_VPU_POSTBLEND_H_ + +#define VPP_OSD1_IN_SIZE 0x1df1 +#define VPP_OSD1_BLD_H_SCOPE 0x1df5 +#define VPP_OSD1_BLD_V_SCOPE 0x1df6 +#define VPP_OSD2_BLD_H_SCOPE 0x1df7 +#define VPP_OSD2_BLD_V_SCOPE 0x1df8 + +#define VD1_BLEND_SRC_CTRL 0x1dfb +#define VD2_BLEND_SRC_CTRL 0x1dfc +#define OSD1_BLEND_SRC_CTRL 0x1dfd +#define OSD2_BLEND_SRC_CTRL 0x1dfe + +#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968 +#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969 + +struct postblend_reg_s { + u32 vpp_osd1_bld_h_scope; + u32 vpp_osd1_bld_v_scope; + u32 vpp_osd2_bld_h_scope; + u32 vpp_osd2_bld_v_scope; + u32 vd1_blend_src_ctrl; + u32 vd2_blend_src_ctrl; + u32 osd1_blend_src_ctrl; + u32 osd2_blend_src_ctrl; + u32 vpp_osd1_in_size; +}; + +enum vpp_blend_e { + VPP_PREBLEND = 0, + VPP_POSTBLEND, +}; + +enum vpp_blend_src_e { + VPP_NULL = 0, + VPP_VD1, + VPP_VD2, + VPP_OSD1, + VPP_OSD2 +}; +#endif diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h new file mode 100644 index 0000000..6825636 --- a/dev/null +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h @@ -0,0 +1,1323 @@ +/* + * drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __MESON_VPU_REG_H +#define __MESON_VPU_REG_H + +#include "meson_osd_scaler.h" +#include "meson_vpu_osd_mif.h" +#include "meson_vpu_osdblend.h" + +/* vpp2 */ +#define VPP2_MISC 0x1e26 +#define VPP2_OFIFO_SIZE 0x1e27 +#define VPP2_INT_LINE_NUM 0x1e20 +#define VPP2_OFIFO_URG_CTRL 0x1e21 +#define VPP2_POSTBLEND_H_SIZE 0x1921 + +/* viu */ +#define VIU_ADDR_START 0x1a00 +#define VIU_ADDR_END 0x1aff +#define VIU_SW_RESET 0x1a01 +#define VIU_MISC_CTRL0 0x1a06 +#define D2D3_INTF_LENGTH 0x1a08 +#define D2D3_INTF_CTRL0 0x1a09 + + +#define VD1_IF0_GEN_REG 0x1a50 +#define VD1_IF0_CANVAS0 0x1a51 +#define VD1_IF0_CANVAS1 0x1a52 +#define VD1_IF0_LUMA_X0 0x1a53 +#define VD1_IF0_LUMA_Y0 0x1a54 +#define VD1_IF0_CHROMA_X0 0x1a55 +#define VD1_IF0_CHROMA_Y0 0x1a56 +#define VD1_IF0_LUMA_X1 0x1a57 +#define VD1_IF0_LUMA_Y1 0x1a58 +#define VD1_IF0_CHROMA_X1 0x1a59 +#define VD1_IF0_CHROMA_Y1 0x1a5a +#define VD1_IF0_RPT_LOOP 0x1a5b +#define VD1_IF0_LUMA0_RPT_PAT 0x1a5c +#define VD1_IF0_CHROMA0_RPT_PAT 0x1a5d +#define VD1_IF0_LUMA1_RPT_PAT 0x1a5e +#define VD1_IF0_CHROMA1_RPT_PAT 0x1a5f +#define VD1_IF0_LUMA_PSEL 0x1a60 +#define VD1_IF0_CHROMA_PSEL 0x1a61 +#define VD1_IF0_DUMMY_PIXEL 0x1a62 +#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63 +#define VD1_IF0_RANGE_MAP_Y 0x1a6a +#define VD1_IF0_RANGE_MAP_CB 0x1a6b +#define VD1_IF0_RANGE_MAP_CR 0x1a6c +#define VD1_IF0_GEN_REG2 0x1a6d +#define VD1_IF0_PROT_CNTL 0x1a6e +#define VIU_VD1_FMT_CTRL 0x1a68 +#define VIU_VD1_FMT_W 0x1a69 +#define VD2_IF0_GEN_REG 0x1a70 +#define VD2_IF0_CANVAS0 0x1a71 +#define VD2_IF0_CANVAS1 0x1a72 +#define VD2_IF0_LUMA_X0 0x1a73 +#define VD2_IF0_LUMA_Y0 0x1a74 +#define VD2_IF0_CHROMA_X0 0x1a75 +#define VD2_IF0_CHROMA_Y0 0x1a76 +#define VD2_IF0_LUMA_X1 0x1a77 +#define VD2_IF0_LUMA_Y1 0x1a78 +#define VD2_IF0_CHROMA_X1 0x1a79 +#define VD2_IF0_CHROMA_Y1 0x1a7a +#define VD2_IF0_RPT_LOOP 0x1a7b +#define VD2_IF0_LUMA0_RPT_PAT 0x1a7c +#define VD2_IF0_CHROMA0_RPT_PAT 0x1a7d +#define VD2_IF0_LUMA1_RPT_PAT 0x1a7e +#define VD2_IF0_CHROMA1_RPT_PAT 0x1a7f +#define VD2_IF0_LUMA_PSEL 0x1a80 +#define VD2_IF0_CHROMA_PSEL 0x1a81 +#define VD2_IF0_DUMMY_PIXEL 0x1a82 +#define VD2_IF0_LUMA_FIFO_SIZE 0x1a83 +#define VD2_IF0_RANGE_MAP_Y 0x1a8a +#define VD2_IF0_RANGE_MAP_CB 0x1a8b +#define VD2_IF0_RANGE_MAP_CR 0x1a8c +#define VD2_IF0_GEN_REG2 0x1a8d +#define VD2_IF0_PROT_CNTL 0x1a8e +#define VIU_VD2_FMT_CTRL 0x1a88 +#define VIU_VD2_FMT_W 0x1a89 + +#define VIU_OSD1_MATRIX_CTRL 0x1a90 +#define VIU_OSD1_MATRIX_COEF00_01 0x1a91 +#define VIU_OSD1_MATRIX_COEF02_10 0x1a92 +#define VIU_OSD1_MATRIX_COEF11_12 0x1a93 +#define VIU_OSD1_MATRIX_COEF20_21 0x1a94 +#define VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95 +#define VIU_OSD1_MATRIX_OFFSET0_1 0x1a96 +#define VIU_OSD1_MATRIX_OFFSET2 0x1a97 +#define VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98 +#define VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99 +#define VIU_OSD1_MATRIX_COEF22_30 0x1a9d +#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e +#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f + +#define VIU_OSD_BLENDO_H_START_END 0x1aa9 +#define VIU_OSD_BLENDO_V_START_END 0x1aaa +#define VIU_OSD_BLEND_GEN_CTRL0 0x1aab +#define VIU_OSD_BLEND_GEN_CTRL1 0x1aac +#define VIU_OSD_BLEND_DUMMY_DATA 0x1aad +#define VIU_OSD_BLEND_CURRENT_XY 0x1aae + +#define VIU_OSD2_MATRIX_CTRL 0x1ab0 +#define VIU_OSD2_MATRIX_COEF00_01 0x1ab1 +#define VIU_OSD2_MATRIX_COEF02_10 0x1ab2 +#define VIU_OSD2_MATRIX_COEF11_12 0x1ab3 +#define VIU_OSD2_MATRIX_COEF20_21 0x1ab4 +#define VIU_OSD2_MATRIX_COEF22 0x1ab5 +#define VIU_OSD2_MATRIX_OFFSET0_1 0x1ab6 +#define VIU_OSD2_MATRIX_OFFSET2 0x1ab7 +#define VIU_OSD2_MATRIX_PRE_OFFSET0_1 0x1ab8 +#define VIU_OSD2_MATRIX_PRE_OFFSET2 0x1ab9 +#define VIU_OSD2_MATRIX_PROBE_COLOR 0x1aba +#define VIU_OSD2_MATRIX_HL_COLOR 0x1abb +#define VIU_OSD2_MATRIX_PROBE_POS 0x1abc +#define VIU_OSD1_EOTF_CTL 0x1ad4 +#define VIU_OSD1_EOTF_COEF00_01 0x1ad5 +#define VIU_OSD1_EOTF_COEF02_10 0x1ad6 +#define VIU_OSD1_EOTF_COEF11_12 0x1ad7 +#define VIU_OSD1_EOTF_COEF20_21 0x1ad8 +#define VIU_OSD1_EOTF_COEF22_RS 0x1ad9 +#define VIU_OSD1_EOTF_LUT_ADDR_PORT 0x1ada +#define VIU_OSD1_EOTF_LUT_DATA_PORT 0x1adb +#define VIU_OSD1_OETF_CTL 0x1adc +#define VIU_OSD1_OETF_LUT_ADDR_PORT 0x1add +#define VIU_OSD1_OETF_LUT_DATA_PORT 0x1ade + +/* vpp */ +#define VPP_DUMMY_DATA 0x1d00 +#define VPP_LINE_IN_LENGTH 0x1d01 +#define VPP_PIC_IN_HEIGHT 0x1d02 +#define VPP_SCALE_COEF_IDX 0x1d03 +#define VPP_SCALE_COEF 0x1d04 +#define VPP_VSC_REGION12_STARTP 0x1d05 +#define VPP_VSC_REGION34_STARTP 0x1d06 +#define VPP_VSC_REGION4_ENDP 0x1d07 +#define VPP_VSC_START_PHASE_STEP 0x1d08 +#define VPP_VSC_REGION0_PHASE_SLOPE 0x1d09 +#define VPP_VSC_REGION1_PHASE_SLOPE 0x1d0a +#define VPP_VSC_REGION3_PHASE_SLOPE 0x1d0b +#define VPP_VSC_REGION4_PHASE_SLOPE 0x1d0c +#define VPP_VSC_PHASE_CTRL 0x1d0d +#define VPP_VSC_INI_PHASE 0x1d0e +#define VPP_HSC_REGION12_STARTP 0x1d10 +#define VPP_HSC_REGION34_STARTP 0x1d11 +#define VPP_HSC_REGION4_ENDP 0x1d12 +#define VPP_HSC_START_PHASE_STEP 0x1d13 +#define VPP_HSC_REGION0_PHASE_SLOPE 0x1d14 +#define VPP_HSC_REGION1_PHASE_SLOPE 0x1d15 +#define VPP_HSC_REGION3_PHASE_SLOPE 0x1d16 +#define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17 +#define VPP_HSC_PHASE_CTRL 0x1d18 +#define VPP_SC_MISC 0x1d19 +#define VPP_PREBLEND_VD1_H_START_END 0x1d1a +#define VPP_PREBLEND_VD1_V_START_END 0x1d1b +#define VPP_POSTBLEND_VD1_H_START_END 0x1d1c +#define VPP_POSTBLEND_VD1_V_START_END 0x1d1d +#define VPP_BLEND_VD2_H_START_END 0x1d1e +#define VPP_BLEND_VD2_V_START_END 0x1d1f +#define VPP_PREBLEND_H_SIZE 0x1d20 +#define VPP_POSTBLEND_H_SIZE 0x1d21 +#define VPP_HOLD_LINES 0x1d22 +#define VPP_BLEND_ONECOLOR_CTRL 0x1d23 +#define VPP_PREBLEND_CURRENT_XY 0x1d24 +#define VPP_POSTBLEND_CURRENT_XY 0x1d25 +#define VPP_MISC 0x1d26 +#define VPP_OFIFO_SIZE 0x1d27 +#define VPP_FIFO_STATUS 0x1d28 +#define VPP_SMOKE_CTRL 0x1d29 +#define VPP_SMOKE1_VAL 0x1d2a +#define VPP_SMOKE2_VAL 0x1d2b +#define VPP_SMOKE3_VAL 0x1d2c +#define VPP_SMOKE1_H_START_END 0x1d2d +#define VPP_SMOKE1_V_START_END 0x1d2e +#define VPP_SMOKE2_H_START_END 0x1d2f +#define VPP_SMOKE2_V_START_END 0x1d30 +#define VPP_SMOKE3_H_START_END 0x1d31 +#define VPP_SMOKE3_V_START_END 0x1d32 +#define VPP_SCO_FIFO_CTRL 0x1d33 +#define VPP_HSC_PHASE_CTRL1 0x1d34 +#define VPP_HSC_INI_PAT_CTRL 0x1d35 +#define VPP_VADJ_CTRL 0x1d40 +#define VPP_VADJ1_Y 0x1d41 +#define VPP_VADJ1_MA_MB 0x1d42 +#define VPP_VADJ1_MC_MD 0x1d43 +#define VPP_VADJ2_Y 0x1d44 +#define VPP_VADJ2_MA_MB 0x1d45 +#define VPP_VADJ2_MC_MD 0x1d46 +#define VPP_HSHARP_CTRL 0x1d50 +#define VPP_HSHARP_LUMA_THRESH01 0x1d51 +#define VPP_HSHARP_LUMA_THRESH23 0x1d52 +#define VPP_HSHARP_CHROMA_THRESH01 0x1d53 +#define VPP_HSHARP_CHROMA_THRESH23 0x1d54 +#define VPP_HSHARP_LUMA_GAIN 0x1d55 +#define VPP_HSHARP_CHROMA_GAIN 0x1d56 +#define VPP_MATRIX_PROBE_COLOR 0x1d5c +#define VPP_MATRIX_HL_COLOR 0x1d5d +#define VPP_MATRIX_PROBE_POS 0x1d5e +#define VPP_MATRIX_CTRL 0x1d5f +#define VPP_MATRIX_COEF00_01 0x1d60 +#define VPP_MATRIX_COEF02_10 0x1d61 +#define VPP_MATRIX_COEF11_12 0x1d62 +#define VPP_MATRIX_COEF20_21 0x1d63 +#define VPP_MATRIX_COEF22 0x1d64 +#define VPP_MATRIX_OFFSET0_1 0x1d65 +#define VPP_MATRIX_OFFSET2 0x1d66 +#define VPP_MATRIX_PRE_OFFSET0_1 0x1d67 +#define VPP_MATRIX_PRE_OFFSET2 0x1d68 +#define VPP_DUMMY_DATA1 0x1d69 +#define VPP_GAINOFF_CTRL0 0x1d6a +#define VPP_GAINOFF_CTRL1 0x1d6b +#define VPP_GAINOFF_CTRL2 0x1d6c +#define VPP_GAINOFF_CTRL3 0x1d6d +#define VPP_GAINOFF_CTRL4 0x1d6e +#define VPP_CHROMA_ADDR_PORT 0x1d70 +#define VPP_CHROMA_DATA_PORT 0x1d71 +#define VPP_GCLK_CTRL0 0x1d72 +#define VPP_GCLK_CTRL1 0x1d73 +#define VPP_SC_GCLK_CTRL 0x1d74 +#define VPP_MISC1 0x1d76 +#define VPP_BLACKEXT_CTRL 0x1d80 +#define VPP_DNLP_CTRL_00 0x1d81 +#define VPP_DNLP_CTRL_01 0x1d82 +#define VPP_DNLP_CTRL_02 0x1d83 +#define VPP_DNLP_CTRL_03 0x1d84 +#define VPP_DNLP_CTRL_04 0x1d85 +#define VPP_DNLP_CTRL_05 0x1d86 +#define VPP_DNLP_CTRL_06 0x1d87 +#define VPP_DNLP_CTRL_07 0x1d88 +#define VPP_DNLP_CTRL_08 0x1d89 +#define VPP_DNLP_CTRL_09 0x1d8a +#define VPP_DNLP_CTRL_10 0x1d8b +#define VPP_DNLP_CTRL_11 0x1d8c +#define VPP_DNLP_CTRL_12 0x1d8d +#define VPP_DNLP_CTRL_13 0x1d8e +#define VPP_DNLP_CTRL_14 0x1d8f +#define VPP_DNLP_CTRL_15 0x1d90 +#define VPP_PEAKING_HGAIN 0x1d91 +#define VPP_PEAKING_VGAIN 0x1d92 +#define VPP_PEAKING_NLP_1 0x1d93 +#define VPP_PEAKING_NLP_2 0x1d94 +#define VPP_PEAKING_NLP_3 0x1d95 +#define VPP_PEAKING_NLP_4 0x1d96 +#define VPP_PEAKING_NLP_5 0x1d97 +#define VPP_SHARP_LIMIT 0x1d98 +#define VPP_VLTI_CTRL 0x1d99 +#define VPP_HLTI_CTRL 0x1d9a +#define VPP_CTI_CTRL 0x1d9b +#define VPP_BLUE_STRETCH_1 0x1d9c +#define VPP_BLUE_STRETCH_2 0x1d9d +#define VPP_BLUE_STRETCH_3 0x1d9e +#define VPP_CCORING_CTRL 0x1da0 +#define VPP_VE_ENABLE_CTRL 0x1da1 +#define VPP_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x1da2 +#define VPP_VE_DEMO_CENTER_BAR 0x1da3 +#define VPP_VE_H_V_SIZE 0x1da4 +#define VPP_VDO_MEAS_CTRL 0x1da8 +#define VPP_VDO_MEAS_VS_COUNT_HI 0x1da9 +#define VPP_VDO_MEAS_VS_COUNT_LO 0x1daa +#define VPP_INPUT_CTRL 0x1dab +#define VPP_CTI_CTRL2 0x1dac +#define VPP_PEAKING_SAT_THD1 0x1dad +#define VPP_PEAKING_SAT_THD2 0x1dae +#define VPP_PEAKING_SAT_THD3 0x1daf +#define VPP_PEAKING_SAT_THD4 0x1db0 +#define VPP_PEAKING_SAT_THD5 0x1db1 +#define VPP_PEAKING_SAT_THD6 0x1db2 +#define VPP_PEAKING_SAT_THD7 0x1db3 +#define VPP_PEAKING_SAT_THD8 0x1db4 +#define VPP_PEAKING_SAT_THD9 0x1db5 +#define VPP_PEAKING_GAIN_ADD1 0x1db6 +#define VPP_PEAKING_GAIN_ADD2 0x1db7 +#define VPP_PEAKING_DNLP 0x1db8 +#define VPP_SHARP_DEMO_WIN_CTRL1 0x1db9 +#define VPP_SHARP_DEMO_WIN_CTRL2 0x1dba +#define VPP_FRONT_HLTI_CTRL 0x1dbb +#define VPP_FRONT_CTI_CTRL 0x1dbc +#define VPP_FRONT_CTI_CTRL2 0x1dbd +#define VPP_INT_LINE_NUM 0x1dce + +/* viu2 */ +#define VIU2_ADDR_START 0x1e00 +#define VIU2_ADDR_END 0x1eff +#define VIU2_SW_RESET 0x1e01 +#define VIU2_SW_RESET0 0x1e02 +#define VIU2_SECURE_REG 0x1e05 +#define VIU2_MISC_CTRL0 0x1e06 +#define VIU2_OSD1_CTRL_STAT 0x1e30 +#define VIU2_OSD1_CTRL_STAT2 0x1e4d +#define VIU2_OSD1_COLOR_ADDR 0x1e31 +#define VIU2_OSD1_COLOR 0x1e32 +#define VIU2_OSD1_HL1_H_START_END 0x1e33 +#define VIU2_OSD1_HL1_V_START_END 0x1e34 +#define VIU2_OSD1_HL2_H_START_END 0x1e35 +#define VIU2_OSD1_HL2_V_START_END 0x1e36 +#define VIU2_OSD1_TCOLOR_AG0 0x1e37 +#define VIU2_OSD1_TCOLOR_AG1 0x1e38 +#define VIU2_OSD1_TCOLOR_AG2 0x1e39 +#define VIU2_OSD1_TCOLOR_AG3 0x1e3a +#define VIU2_OSD1_BLK0_CFG_W0 0x1e3b +#define VIU2_OSD1_BLK1_CFG_W0 0x1e3f +#define VIU2_OSD1_BLK2_CFG_W0 0x1e43 +#define VIU2_OSD1_BLK3_CFG_W0 0x1e47 +#define VIU2_OSD1_BLK0_CFG_W1 0x1e3c +#define VIU2_OSD1_BLK1_CFG_W1 0x1e40 +#define VIU2_OSD1_BLK2_CFG_W1 0x1e44 +#define VIU2_OSD1_BLK3_CFG_W1 0x1e48 +#define VIU2_OSD1_BLK0_CFG_W2 0x1e3d +#define VIU2_OSD1_BLK1_CFG_W2 0x1e41 +#define VIU2_OSD1_BLK2_CFG_W2 0x1e45 +#define VIU2_OSD1_BLK3_CFG_W2 0x1e49 +#define VIU2_OSD1_BLK0_CFG_W3 0x1e3e +#define VIU2_OSD1_BLK1_CFG_W3 0x1e42 +#define VIU2_OSD1_BLK2_CFG_W3 0x1e46 +#define VIU2_OSD1_BLK3_CFG_W3 0x1e4a +#define VIU2_OSD1_BLK0_CFG_W4 0x1e64 +#define VIU2_OSD1_BLK1_CFG_W4 0x1e65 +#define VIU2_OSD1_BLK2_CFG_W4 0x1e66 +#define VIU2_OSD1_BLK3_CFG_W4 0x1e67 +#define VIU2_OSD1_FIFO_CTRL_STAT 0x1e4b +#define VIU2_OSD1_TEST_RDDATA 0x1e4c +#define VIU2_OSD1_PROT_CTRL 0x1e4e +#define VIU2_OSD1_MALI_UNPACK_CTRL 0x1e4f +#define VIU2_OSD1_DIMM_CTRL 0x1e50 +#define VIU2_OSD1_UNSUPPORT VIU_OSD2_TCOLOR_AG3 +/* viu2 rotate */ +#define VIU2_RMIF_CTRL1 0x1e81 +#define VIU2_RMIF_SCOPE_X 0x1e83 +#define VIU2_RMIF_SCOPE_Y 0x1e84 +#define VIU2_ROT_BLK_SIZE 0x1e85 +#define VIU2_ROT_LBUF_SIZE 0x1e86 +#define VIU2_ROT_FMT_CTRL 0x1e87 +#define VIU2_ROT_OUT_VCROP 0x1e89 + +/* encode */ +#define ENCP_VFIFO2VD_CTL 0x1b58 +#define ENCP_VFIFO2VD_PIXEL_START 0x1b59 +#define ENCP_VFIFO2VD_PIXEL_END 0x1b5a +#define ENCP_VFIFO2VD_LINE_TOP_START 0x1b5b +#define ENCP_VFIFO2VD_LINE_TOP_END 0x1b5c +#define ENCP_VFIFO2VD_LINE_BOT_START 0x1b5d +#define ENCP_VFIFO2VD_LINE_BOT_END 0x1b5e +#define VENC_SYNC_ROUTE 0x1b60 +#define VENC_VIDEO_EXSRC 0x1b61 +#define VENC_DVI_SETTING 0x1b62 +#define VENC_C656_CTRL 0x1b63 +#define VENC_UPSAMPLE_CTRL0 0x1b64 +#define VENC_UPSAMPLE_CTRL1 0x1b65 +#define VENC_UPSAMPLE_CTRL2 0x1b66 +#define TCON_INVERT_CTL 0x1b67 +#define VENC_VIDEO_PROG_MODE 0x1b68 +#define VENC_ENCI_LINE 0x1b69 +#define VENC_ENCI_PIXEL 0x1b6a +#define VENC_ENCP_LINE 0x1b6b +#define VENC_ENCP_PIXEL 0x1b6c +#define VENC_STATA 0x1b6d +#define VENC_INTCTRL 0x1b6e +#define VENC_INTFLAG 0x1b6f +#define VENC_VIDEO_TST_EN 0x1b70 +#define VENC_VIDEO_TST_MDSEL 0x1b71 +#define VENC_VIDEO_TST_Y 0x1b72 +#define VENC_VIDEO_TST_CB 0x1b73 +#define VENC_VIDEO_TST_CR 0x1b74 +#define VENC_VIDEO_TST_CLRBAR_STRT 0x1b75 +#define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76 +#define VENC_VIDEO_TST_VDCNT_STSET 0x1b77 +#define VENC_VDAC_DACSEL0 0x1b78 +#define VENC_VDAC_DACSEL1 0x1b79 +#define VENC_VDAC_DACSEL2 0x1b7a +#define VENC_VDAC_DACSEL3 0x1b7b +#define VENC_VDAC_DACSEL4 0x1b7c +#define VENC_VDAC_DACSEL5 0x1b7d +#define VENC_VDAC_SETTING 0x1b7e +#define VENC_VDAC_TST_VAL 0x1b7f +#define VENC_VDAC_DAC0_GAINCTRL 0x1bf0 +#define VENC_VDAC_DAC0_OFFSET 0x1bf1 +#define VENC_VDAC_DAC1_GAINCTRL 0x1bf2 +#define VENC_VDAC_DAC1_OFFSET 0x1bf3 +#define VENC_VDAC_DAC2_GAINCTRL 0x1bf4 +#define VENC_VDAC_DAC2_OFFSET 0x1bf5 +#define VENC_VDAC_DAC3_GAINCTRL 0x1bf6 +#define VENC_VDAC_DAC3_OFFSET 0x1bf7 +#define VENC_VDAC_DAC4_GAINCTRL 0x1bf8 +#define VENC_VDAC_DAC4_OFFSET 0x1bf9 +#define VENC_VDAC_DAC5_GAINCTRL 0x1bfa +#define VENC_VDAC_DAC5_OFFSET 0x1bfb +#define VENC_VDAC_FIFO_CTRL 0x1bfc +#define ENCL_TCON_INVERT_CTL 0x1bfd +#define ENCP_VIDEO_EN 0x1b80 +#define ENCP_VIDEO_SYNC_MODE 0x1b81 +#define ENCP_MACV_EN 0x1b82 +#define ENCP_VIDEO_Y_SCL 0x1b83 +#define ENCP_VIDEO_PB_SCL 0x1b84 +#define ENCP_VIDEO_PR_SCL 0x1b85 +#define ENCP_VIDEO_SYNC_SCL 0x1b86 +#define ENCP_VIDEO_MACV_SCL 0x1b87 +#define ENCP_VIDEO_Y_OFFST 0x1b88 +#define ENCP_VIDEO_PB_OFFST 0x1b89 +#define ENCP_VIDEO_PR_OFFST 0x1b8a +#define ENCP_VIDEO_SYNC_OFFST 0x1b8b +#define ENCP_VIDEO_MACV_OFFST 0x1b8c +#define ENCP_VIDEO_MODE 0x1b8d +#define ENCP_VIDEO_MODE_ADV 0x1b8e +#define ENCP_DBG_PX_RST 0x1b90 +#define ENCP_DBG_LN_RST 0x1b91 +#define ENCP_DBG_PX_INT 0x1b92 +#define ENCP_DBG_LN_INT 0x1b93 +#define ENCP_VIDEO_YFP1_HTIME 0x1b94 +#define ENCP_VIDEO_YFP2_HTIME 0x1b95 +#define ENCP_VIDEO_YC_DLY 0x1b96 +#define ENCP_VIDEO_MAX_PXCNT 0x1b97 +#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98 +#define ENCP_VIDEO_HSPULS_END 0x1b99 +#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a +#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b +#define ENCP_VIDEO_VSPULS_END 0x1b9c +#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d +#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e +#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f +#define ENCP_VIDEO_EQPULS_END 0x1ba0 +#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1 +#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2 +#define ENCP_VIDEO_HAVON_END 0x1ba3 +#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4 +#define ENCP_VIDEO_VAVON_ELINE 0x1baf +#define ENCP_VIDEO_VAVON_BLINE 0x1ba6 +#define ENCP_VIDEO_HSO_BEGIN 0x1ba7 +#define ENCP_VIDEO_HSO_END 0x1ba8 +#define ENCP_VIDEO_VSO_BEGIN 0x1ba9 +#define ENCP_VIDEO_VSO_END 0x1baa +#define ENCP_VIDEO_VSO_BLINE 0x1bab +#define ENCP_VIDEO_VSO_ELINE 0x1bac +#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad +#define ENCP_VIDEO_MAX_LNCNT 0x1bae +#define ENCP_VIDEO_SY_VAL 0x1bb0 +#define ENCP_VIDEO_SY2_VAL 0x1bb1 +#define ENCP_VIDEO_BLANKY_VAL 0x1bb2 +#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3 +#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4 +#define ENCP_VIDEO_HOFFST 0x1bb5 +#define ENCP_VIDEO_VOFFST 0x1bb6 +#define ENCP_VIDEO_RGB_CTRL 0x1bb7 +#define ENCP_VIDEO_FILT_CTRL 0x1bb8 +#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9 +#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba +#define ENCP_VIDEO_MATRIX_CB 0x1bbb +#define ENCP_VIDEO_MATRIX_CR 0x1bbc +#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd +#define ENCP_MACV_BLANKY_VAL 0x1bc0 +#define ENCP_MACV_MAXY_VAL 0x1bc1 +#define ENCP_MACV_1ST_PSSYNC_STRT 0x1bc2 +#define ENCP_MACV_PSSYNC_STRT 0x1bc3 +#define ENCP_MACV_AGC_STRT 0x1bc4 +#define ENCP_MACV_AGC_END 0x1bc5 +#define ENCP_MACV_WAVE_END 0x1bc6 +#define ENCP_MACV_STRTLINE 0x1bc7 +#define ENCP_MACV_ENDLINE 0x1bc8 +#define ENCP_MACV_TS_CNT_MAX_L 0x1bc9 +#define ENCP_MACV_TS_CNT_MAX_H 0x1bca +#define ENCP_MACV_TIME_DOWN 0x1bcb +#define ENCP_MACV_TIME_LO 0x1bcc +#define ENCP_MACV_TIME_UP 0x1bcd +#define ENCP_MACV_TIME_RST 0x1bce +#define ENCP_VBI_CTRL 0x1bd0 +#define ENCP_VBI_SETTING 0x1bd1 +#define ENCP_VBI_BEGIN 0x1bd2 +#define ENCP_VBI_WIDTH 0x1bd3 +#define ENCP_VBI_HVAL 0x1bd4 +#define ENCP_VBI_DATA0 0x1bd5 +#define ENCP_VBI_DATA1 0x1bd6 +#define C656_HS_ST 0x1be0 +#define C656_HS_ED 0x1be1 +#define C656_VS_LNST_E 0x1be2 +#define C656_VS_LNST_O 0x1be3 +#define C656_VS_LNED_E 0x1be4 +#define C656_VS_LNED_O 0x1be5 +#define C656_FS_LNST 0x1be6 +#define C656_FS_LNED 0x1be7 +#define ENCI_VIDEO_MODE 0x1b00 +#define ENCI_VIDEO_MODE_ADV 0x1b01 +#define ENCI_VIDEO_FSC_ADJ 0x1b02 +#define ENCI_VIDEO_BRIGHT 0x1b03 +#define ENCI_VIDEO_CONT 0x1b04 +#define ENCI_VIDEO_SAT 0x1b05 +#define ENCI_VIDEO_HUE 0x1b06 +#define ENCI_VIDEO_SCH 0x1b07 +#define ENCI_SYNC_MODE 0x1b08 +#define ENCI_SYNC_CTRL 0x1b09 +#define ENCI_SYNC_HSO_BEGIN 0x1b0a +#define ENCI_SYNC_HSO_END 0x1b0b +#define ENCI_SYNC_VSO_EVN 0x1b0c +#define ENCI_SYNC_VSO_ODD 0x1b0d +#define ENCI_SYNC_VSO_EVNLN 0x1b0e +#define ENCI_SYNC_VSO_ODDLN 0x1b0f +#define ENCI_SYNC_HOFFST 0x1b10 +#define ENCI_SYNC_VOFFST 0x1b11 +#define ENCI_SYNC_ADJ 0x1b12 +#define ENCI_RGB_SETTING 0x1b13 +#define ENCI_DE_H_BEGIN 0x1b16 +#define ENCI_DE_H_END 0x1b17 +#define ENCI_DE_V_BEGIN_EVEN 0x1b18 +#define ENCI_DE_V_END_EVEN 0x1b19 +#define ENCI_DE_V_BEGIN_ODD 0x1b1a +#define ENCI_DE_V_END_ODD 0x1b1b +#define ENCI_VBI_SETTING 0x1b20 +#define ENCI_VBI_CCDT_EVN 0x1b21 +#define ENCI_VBI_CCDT_ODD 0x1b22 +#define ENCI_VBI_CC525_LN 0x1b23 +#define ENCI_VBI_CC625_LN 0x1b24 +#define ENCI_VBI_WSSDT 0x1b25 +#define ENCI_VBI_WSS_LN 0x1b26 +#define ENCI_VBI_CGMSDT_L 0x1b27 +#define ENCI_VBI_CGMSDT_H 0x1b28 +#define ENCI_VBI_CGMS_LN 0x1b29 +#define ENCI_VBI_TTX_HTIME 0x1b2a +#define ENCI_VBI_TTX_LN 0x1b2b +#define ENCI_VBI_TTXDT0 0x1b2c +#define ENCI_VBI_TTXDT1 0x1b2d +#define ENCI_VBI_TTXDT2 0x1b2e +#define ENCI_VBI_TTXDT3 0x1b2f +#define ENCI_MACV_N0 0x1b30 +#define ENCI_MACV_N1 0x1b31 +#define ENCI_MACV_N2 0x1b32 +#define ENCI_MACV_N3 0x1b33 +#define ENCI_MACV_N4 0x1b34 +#define ENCI_MACV_N5 0x1b35 +#define ENCI_MACV_N6 0x1b36 +#define ENCI_MACV_N7 0x1b37 +#define ENCI_MACV_N8 0x1b38 +#define ENCI_MACV_N9 0x1b39 +#define ENCI_MACV_N10 0x1b3a +#define ENCI_MACV_N11 0x1b3b +#define ENCI_MACV_N12 0x1b3c +#define ENCI_MACV_N13 0x1b3d +#define ENCI_MACV_N14 0x1b3e +#define ENCI_MACV_N15 0x1b3f +#define ENCI_MACV_N16 0x1b40 +#define ENCI_MACV_N17 0x1b41 +#define ENCI_MACV_N18 0x1b42 +#define ENCI_MACV_N19 0x1b43 +#define ENCI_MACV_N20 0x1b44 +#define ENCI_MACV_N21 0x1b45 +#define ENCI_MACV_N22 0x1b46 +#define ENCI_DBG_PX_RST 0x1b48 +#define ENCI_DBG_FLDLN_RST 0x1b49 +#define ENCI_DBG_PX_INT 0x1b4a +#define ENCI_DBG_FLDLN_INT 0x1b4b +#define ENCI_DBG_MAXPX 0x1b4c +#define ENCI_DBG_MAXLN 0x1b4d +#define ENCI_MACV_MAX_AMP 0x1b50 +#define ENCI_MACV_PULSE_LO 0x1b51 +#define ENCI_MACV_PULSE_HI 0x1b52 +#define ENCI_MACV_BKP_MAX 0x1b53 +#define ENCI_CFILT_CTRL 0x1b54 +#define ENCI_CFILT7 0x1b55 +#define ENCI_YC_DELAY 0x1b56 +#define ENCI_VIDEO_EN 0x1b57 +#define ENCI_DVI_HSO_BEGIN 0x1c00 +#define ENCI_DVI_HSO_END 0x1c01 +#define ENCI_DVI_VSO_BLINE_EVN 0x1c02 +#define ENCI_DVI_VSO_BLINE_ODD 0x1c03 +#define ENCI_DVI_VSO_ELINE_EVN 0x1c04 +#define ENCI_DVI_VSO_ELINE_ODD 0x1c05 +#define ENCI_DVI_VSO_BEGIN_EVN 0x1c06 +#define ENCI_DVI_VSO_BEGIN_ODD 0x1c07 +#define ENCI_DVI_VSO_END_EVN 0x1c08 +#define ENCI_DVI_VSO_END_ODD 0x1c09 +#define ENCI_CFILT_CTRL2 0x1c0a +#define ENCI_DACSEL_0 0x1c0b +#define ENCI_DACSEL_1 0x1c0c +#define ENCP_DACSEL_0 0x1c0d +#define ENCP_DACSEL_1 0x1c0e +#define ENCP_MAX_LINE_SWITCH_POINT 0x1c0f +#define ENCI_TST_EN 0x1c10 +#define ENCI_TST_MDSEL 0x1c11 +#define ENCI_TST_Y 0x1c12 +#define ENCI_TST_CB 0x1c13 +#define ENCI_TST_CR 0x1c14 +#define ENCI_TST_CLRBAR_STRT 0x1c15 +#define ENCI_TST_CLRBAR_WIDTH 0x1c16 +#define ENCI_TST_VDCNT_STSET 0x1c17 +#define ENCI_VFIFO2VD_CTL 0x1c18 +#define ENCI_VFIFO2VD_PIXEL_START 0x1c19 +#define ENCI_VFIFO2VD_PIXEL_END 0x1c1a +#define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b +#define ENCI_VFIFO2VD_LINE_TOP_END 0x1c1c +#define ENCI_VFIFO2VD_LINE_BOT_START 0x1c1d +#define ENCI_VFIFO2VD_LINE_BOT_END 0x1c1e +#define ENCI_VFIFO2VD_CTL2 0x1c1f +#define ENCT_VFIFO2VD_CTL 0x1c20 +#define ENCT_VFIFO2VD_PIXEL_START 0x1c21 +#define ENCT_VFIFO2VD_PIXEL_END 0x1c22 +#define ENCT_VFIFO2VD_LINE_TOP_START 0x1c23 +#define ENCT_VFIFO2VD_LINE_TOP_END 0x1c24 +#define ENCT_VFIFO2VD_LINE_BOT_START 0x1c25 +#define ENCT_VFIFO2VD_LINE_BOT_END 0x1c26 +#define ENCT_VFIFO2VD_CTL2 0x1c27 +#define ENCT_TST_EN 0x1c28 +#define ENCT_TST_MDSEL 0x1c29 +#define ENCT_TST_Y 0x1c2a +#define ENCT_TST_CB 0x1c2b +#define ENCT_TST_CR 0x1c2c +#define ENCT_TST_CLRBAR_STRT 0x1c2d +#define ENCT_TST_CLRBAR_WIDTH 0x1c2e +#define ENCT_TST_VDCNT_STSET 0x1c2f +#define ENCP_DVI_HSO_BEGIN 0x1c30 +#define ENCP_DVI_HSO_END 0x1c31 +#define ENCP_DVI_VSO_BLINE_EVN 0x1c32 +#define ENCP_DVI_VSO_BLINE_ODD 0x1c33 +#define ENCP_DVI_VSO_ELINE_EVN 0x1c34 +#define ENCP_DVI_VSO_ELINE_ODD 0x1c35 +#define ENCP_DVI_VSO_BEGIN_EVN 0x1c36 +#define ENCP_DVI_VSO_BEGIN_ODD 0x1c37 +#define ENCP_DVI_VSO_END_EVN 0x1c38 +#define ENCP_DVI_VSO_END_ODD 0x1c39 +#define ENCP_DE_H_BEGIN 0x1c3a +#define ENCP_DE_H_END 0x1c3b +#define ENCP_DE_V_BEGIN_EVEN 0x1c3c +#define ENCP_DE_V_END_EVEN 0x1c3d +#define ENCP_DE_V_BEGIN_ODD 0x1c3e +#define ENCP_DE_V_END_ODD 0x1c3f +#define ENCI_SYNC_LINE_LENGTH 0x1c40 +#define ENCI_SYNC_PIXEL_EN 0x1c41 +#define ENCI_SYNC_TO_LINE_EN 0x1c42 +#define ENCI_SYNC_TO_PIXEL 0x1c43 +#define ENCP_SYNC_LINE_LENGTH 0x1c44 +#define ENCP_SYNC_PIXEL_EN 0x1c45 +#define ENCP_SYNC_TO_LINE_EN 0x1c46 +#define ENCP_SYNC_TO_PIXEL 0x1c47 +#define ENCT_SYNC_LINE_LENGTH 0x1c48 +#define ENCT_SYNC_PIXEL_EN 0x1c49 +#define ENCT_SYNC_TO_LINE_EN 0x1c4a +#define ENCT_SYNC_TO_PIXEL 0x1c4b +#define ENCL_SYNC_LINE_LENGTH 0x1c4c +#define ENCL_SYNC_PIXEL_EN 0x1c4d +#define ENCL_SYNC_TO_LINE_EN 0x1c4e +#define ENCL_SYNC_TO_PIXEL 0x1c4f +#define ENCP_VFIFO2VD_CTL2 0x1c50 +#define VENC_DVI_SETTING_MORE 0x1c51 +#define VENC_VDAC_DAC4_FILT_CTRL0 0x1c54 +#define VENC_VDAC_DAC4_FILT_CTRL1 0x1c55 +#define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56 +#define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57 +#define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58 +#define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59 +#define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a +#define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b +#define VENC_VDAC_DAC2_FILT_CTRL0 0x1c5c +#define VENC_VDAC_DAC2_FILT_CTRL1 0x1c5d +#define VENC_VDAC_DAC3_FILT_CTRL0 0x1c5e +#define VENC_VDAC_DAC3_FILT_CTRL1 0x1c5f +#define ENCT_VIDEO_EN 0x1c60 +#define ENCT_VIDEO_Y_SCL 0x1c61 +#define ENCT_VIDEO_PB_SCL 0x1c62 +#define ENCT_VIDEO_PR_SCL 0x1c63 +#define ENCT_VIDEO_Y_OFFST 0x1c64 +#define ENCT_VIDEO_PB_OFFST 0x1c65 +#define ENCT_VIDEO_PR_OFFST 0x1c66 +#define ENCT_VIDEO_MODE 0x1c67 +#define ENCT_VIDEO_MODE_ADV 0x1c68 +#define ENCT_DBG_PX_RST 0x1c69 +#define ENCT_DBG_LN_RST 0x1c6a +#define ENCT_DBG_PX_INT 0x1c6b +#define ENCT_DBG_LN_INT 0x1c6c +#define ENCT_VIDEO_YFP1_HTIME 0x1c6d +#define ENCT_VIDEO_YFP2_HTIME 0x1c6e +#define ENCT_VIDEO_YC_DLY 0x1c6f +#define ENCT_VIDEO_MAX_PXCNT 0x1c70 +#define ENCT_VIDEO_HAVON_END 0x1c71 +#define ENCT_VIDEO_HAVON_BEGIN 0x1c72 +#define ENCT_VIDEO_VAVON_ELINE 0x1c73 +#define ENCT_VIDEO_VAVON_BLINE 0x1c74 +#define ENCT_VIDEO_HSO_BEGIN 0x1c75 +#define ENCT_VIDEO_HSO_END 0x1c76 +#define ENCT_VIDEO_VSO_BEGIN 0x1c77 +#define ENCT_VIDEO_VSO_END 0x1c78 +#define ENCT_VIDEO_VSO_BLINE 0x1c79 +#define ENCT_VIDEO_VSO_ELINE 0x1c7a +#define ENCT_VIDEO_MAX_LNCNT 0x1c7b +#define ENCT_VIDEO_BLANKY_VAL 0x1c7c +#define ENCT_VIDEO_BLANKPB_VAL 0x1c7d +#define ENCT_VIDEO_BLANKPR_VAL 0x1c7e +#define ENCT_VIDEO_HOFFST 0x1c7f +#define ENCT_VIDEO_VOFFST 0x1c80 +#define ENCT_VIDEO_RGB_CTRL 0x1c81 +#define ENCT_VIDEO_FILT_CTRL 0x1c82 +#define ENCT_VIDEO_OFLD_VPEQ_OFST 0x1c83 +#define ENCT_VIDEO_OFLD_VOAV_OFST 0x1c84 +#define ENCT_VIDEO_MATRIX_CB 0x1c85 +#define ENCT_VIDEO_MATRIX_CR 0x1c86 +#define ENCT_VIDEO_RGBIN_CTRL 0x1c87 +#define ENCT_MAX_LINE_SWITCH_POINT 0x1c88 +#define ENCT_DACSEL_0 0x1c89 +#define ENCT_DACSEL_1 0x1c8a +#define ENCL_VFIFO2VD_CTL 0x1c90 +#define ENCL_VFIFO2VD_PIXEL_START 0x1c91 +#define ENCL_VFIFO2VD_PIXEL_END 0x1c92 +#define ENCL_VFIFO2VD_LINE_TOP_START 0x1c93 +#define ENCL_VFIFO2VD_LINE_TOP_END 0x1c94 +#define ENCL_VFIFO2VD_LINE_BOT_START 0x1c95 +#define ENCL_VFIFO2VD_LINE_BOT_END 0x1c96 +#define ENCL_VFIFO2VD_CTL2 0x1c97 +#define ENCL_TST_EN 0x1c98 +#define ENCL_TST_MDSEL 0x1c99 +#define ENCL_TST_Y 0x1c9a +#define ENCL_TST_CB 0x1c9b +#define ENCL_TST_CR 0x1c9c +#define ENCL_TST_CLRBAR_STRT 0x1c9d +#define ENCL_TST_CLRBAR_WIDTH 0x1c9e +#define ENCL_TST_VDCNT_STSET 0x1c9f +#define ENCL_VIDEO_EN 0x1ca0 +#define ENCL_VIDEO_Y_SCL 0x1ca1 +#define ENCL_VIDEO_PB_SCL 0x1ca2 +#define ENCL_VIDEO_PR_SCL 0x1ca3 +#define ENCL_VIDEO_Y_OFFST 0x1ca4 +#define ENCL_VIDEO_PB_OFFST 0x1ca5 +#define ENCL_VIDEO_PR_OFFST 0x1ca6 +#define ENCL_VIDEO_MODE 0x1ca7 +#define ENCL_VIDEO_MODE_ADV 0x1ca8 +#define ENCL_DBG_PX_RST 0x1ca9 +#define ENCL_DBG_LN_RST 0x1caa +#define ENCL_DBG_PX_INT 0x1cab +#define ENCL_DBG_LN_INT 0x1cac +#define ENCL_VIDEO_YFP1_HTIME 0x1cad +#define ENCL_VIDEO_YFP2_HTIME 0x1cae +#define ENCL_VIDEO_YC_DLY 0x1caf +#define ENCL_VIDEO_MAX_PXCNT 0x1cb0 +#define ENCL_VIDEO_HAVON_END 0x1cb1 +#define ENCL_VIDEO_HAVON_BEGIN 0x1cb2 +#define ENCL_VIDEO_VAVON_ELINE 0x1cb3 +#define ENCL_VIDEO_VAVON_BLINE 0x1cb4 +#define ENCL_VIDEO_HSO_BEGIN 0x1cb5 +#define ENCL_VIDEO_HSO_END 0x1cb6 +#define ENCL_VIDEO_VSO_BEGIN 0x1cb7 +#define ENCL_VIDEO_VSO_END 0x1cb8 +#define ENCL_VIDEO_VSO_BLINE 0x1cb9 +#define ENCL_VIDEO_VSO_ELINE 0x1cba +#define ENCL_VIDEO_MAX_LNCNT 0x1cbb +#define ENCL_VIDEO_BLANKY_VAL 0x1cbc +#define ENCL_VIDEO_BLANKPB_VAL 0x1cbd +#define ENCL_VIDEO_BLANKPR_VAL 0x1cbe +#define ENCL_VIDEO_HOFFST 0x1cbf +#define ENCL_VIDEO_VOFFST 0x1cc0 +#define ENCL_VIDEO_RGB_CTRL 0x1cc1 +#define ENCL_VIDEO_FILT_CTRL 0x1cc2 +#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3 +#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4 +#define ENCL_VIDEO_MATRIX_CB 0x1cc5 +#define ENCL_VIDEO_MATRIX_CR 0x1cc6 +#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7 +#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8 +#define ENCL_DACSEL_0 0x1cc9 +#define ENCL_DACSEL_1 0x1cca +#define RDMA_AHB_START_ADDR_MAN 0x1100 +#define RDMA_AHB_END_ADDR_MAN 0x1101 +#define RDMA_AHB_START_ADDR_1 0x1102 +#define RDMA_AHB_END_ADDR_1 0x1103 +#define RDMA_AHB_START_ADDR_2 0x1104 +#define RDMA_AHB_END_ADDR_2 0x1105 +#define RDMA_AHB_START_ADDR_3 0x1106 +#define RDMA_AHB_END_ADDR_3 0x1107 +#define RDMA_AHB_START_ADDR_4 0x1108 +#define RDMA_AHB_END_ADDR_4 0x1109 +#define RDMA_AHB_START_ADDR_5 0x110a +#define RDMA_AHB_END_ADDR_5 0x110b +#define RDMA_AHB_START_ADDR_6 0x110c +#define RDMA_AHB_END_ADDR_6 0x110d +#define RDMA_AHB_START_ADDR_7 0x110e +#define RDMA_AHB_END_ADDR_7 0x110f +#define RDMA_ACCESS_AUTO 0x1110 +#define RDMA_ACCESS_AUTO2 0x1111 +#define RDMA_ACCESS_AUTO3 0x1112 +#define RDMA_ACCESS_MAN 0x1113 +#define RDMA_CTRL 0x1114 +#define RDMA_STATUS 0x1115 +#define RDMA_STATUS2 0x1116 +#define RDMA_STATUS3 0x1117 +#define L_GAMMA_CNTL_PORT 0x1400 +#define L_GAMMA_DATA_PORT 0x1401 +#define L_GAMMA_ADDR_PORT 0x1402 +#define L_GAMMA_VCOM_HSWITCH_ADDR 0x1403 +#define L_RGB_BASE_ADDR 0x1405 +#define L_RGB_COEFF_ADDR 0x1406 +#define L_POL_CNTL_ADDR 0x1407 +#define L_DITH_CNTL_ADDR 0x1408 +#define L_GAMMA_PROBE_CTRL 0x1409 +#define L_GAMMA_PROBE_COLOR_L 0x140a +#define L_GAMMA_PROBE_COLOR_H 0x140b +#define L_GAMMA_PROBE_HL_COLOR 0x140c +#define L_GAMMA_PROBE_POS_X 0x140d +#define L_GAMMA_PROBE_POS_Y 0x140e +#define L_STH1_HS_ADDR 0x1410 +#define L_STH1_HE_ADDR 0x1411 +#define L_STH1_VS_ADDR 0x1412 +#define L_STH1_VE_ADDR 0x1413 +#define L_STH2_HS_ADDR 0x1414 +#define L_STH2_HE_ADDR 0x1415 +#define L_STH2_VS_ADDR 0x1416 +#define L_STH2_VE_ADDR 0x1417 +#define L_OEH_HS_ADDR 0x1418 +#define L_OEH_HE_ADDR 0x1419 +#define L_OEH_VS_ADDR 0x141a +#define L_OEH_VE_ADDR 0x141b +#define L_VCOM_HSWITCH_ADDR 0x141c +#define L_VCOM_VS_ADDR 0x141d +#define L_VCOM_VE_ADDR 0x141e +#define L_CPV1_HS_ADDR 0x141f +#define L_CPV1_HE_ADDR 0x1420 +#define L_CPV1_VS_ADDR 0x1421 +#define L_CPV1_VE_ADDR 0x1422 +#define L_CPV2_HS_ADDR 0x1423 +#define L_CPV2_HE_ADDR 0x1424 +#define L_CPV2_VS_ADDR 0x1425 +#define L_CPV2_VE_ADDR 0x1426 +#define L_STV1_HS_ADDR 0x1427 +#define L_STV1_HE_ADDR 0x1428 +#define L_STV1_VS_ADDR 0x1429 +#define L_STV1_VE_ADDR 0x142a +#define L_STV2_HS_ADDR 0x142b +#define L_STV2_HE_ADDR 0x142c +#define L_STV2_VS_ADDR 0x142d +#define L_STV2_VE_ADDR 0x142e +#define L_OEV1_HS_ADDR 0x142f +#define L_OEV1_HE_ADDR 0x1430 +#define L_OEV1_VS_ADDR 0x1431 +#define L_OEV1_VE_ADDR 0x1432 +#define L_OEV2_HS_ADDR 0x1433 +#define L_OEV2_HE_ADDR 0x1434 +#define L_OEV2_VS_ADDR 0x1435 +#define L_OEV2_VE_ADDR 0x1436 +#define L_OEV3_HS_ADDR 0x1437 +#define L_OEV3_HE_ADDR 0x1438 +#define L_OEV3_VS_ADDR 0x1439 +#define L_OEV3_VE_ADDR 0x143a +#define L_LCD_PWR_ADDR 0x143b +#define L_LCD_PWM0_LO_ADDR 0x143c +#define L_LCD_PWM0_HI_ADDR 0x143d +#define L_LCD_PWM1_LO_ADDR 0x143e +#define L_LCD_PWM1_HI_ADDR 0x143f +#define L_INV_CNT_ADDR 0x1440 +#define L_TCON_MISC_SEL_ADDR 0x1441 +#define L_DUAL_PORT_CNTL_ADDR 0x1442 +#define MLVDS_CLK_CTL1_HI 0x1443 +#define MLVDS_CLK_CTL1_LO 0x1444 +#define L_TCON_DOUBLE_CTL 0x1449 +#define L_TCON_PATTERN_HI 0x144a +#define L_TCON_PATTERN_LO 0x144b +#define LDIM_BL_ADDR_PORT 0x144e +#define LDIM_BL_DATA_PORT 0x144f +#define L_DE_HS_ADDR 0x1451 +#define L_DE_HE_ADDR 0x1452 +#define L_DE_VS_ADDR 0x1453 +#define L_DE_VE_ADDR 0x1454 +#define L_HSYNC_HS_ADDR 0x1455 +#define L_HSYNC_HE_ADDR 0x1456 +#define L_HSYNC_VS_ADDR 0x1457 +#define L_HSYNC_VE_ADDR 0x1458 +#define L_VSYNC_HS_ADDR 0x1459 +#define L_VSYNC_HE_ADDR 0x145a +#define L_VSYNC_VS_ADDR 0x145b +#define L_VSYNC_VE_ADDR 0x145c +#define L_LCD_MCU_CTL 0x145d +#define DUAL_MLVDS_CTL 0x1460 +#define DUAL_MLVDS_LINE_START 0x1461 +#define DUAL_MLVDS_LINE_END 0x1462 +#define DUAL_MLVDS_PIXEL_W_START_L 0x1463 +#define DUAL_MLVDS_PIXEL_W_END_L 0x1464 +#define DUAL_MLVDS_PIXEL_W_START_R 0x1465 +#define DUAL_MLVDS_PIXEL_W_END_R 0x1466 +#define DUAL_MLVDS_PIXEL_R_START_L 0x1467 +#define DUAL_MLVDS_PIXEL_R_CNT_L 0x1468 +#define DUAL_MLVDS_PIXEL_R_START_R 0x1469 +#define DUAL_MLVDS_PIXEL_R_CNT_R 0x146a +#define V_INVERSION_PIXEL 0x1470 +#define V_INVERSION_LINE 0x1471 +#define V_INVERSION_CONTROL 0x1472 +#define MLVDS2_CONTROL 0x1474 +#define MLVDS2_CONFIG_HI 0x1475 +#define MLVDS2_CONFIG_LO 0x1476 +#define MLVDS2_DUAL_GATE_WR_START 0x1477 +#define MLVDS2_DUAL_GATE_WR_END 0x1478 +#define MLVDS2_DUAL_GATE_RD_START 0x1479 +#define MLVDS2_DUAL_GATE_RD_END 0x147a +#define MLVDS2_SECOND_RESET_CTL 0x147b +#define MLVDS2_DUAL_GATE_CTL_HI 0x147c +#define MLVDS2_DUAL_GATE_CTL_LO 0x147d +#define MLVDS2_RESET_CONFIG_HI 0x147e +#define MLVDS2_RESET_CONFIG_LO 0x147f +#define GAMMA_CNTL_PORT 0x1480 +#define GAMMA_DATA_PORT 0x1481 +#define GAMMA_ADDR_PORT 0x1482 +#define GAMMA_VCOM_HSWITCH_ADDR 0x1483 +#define RGB_BASE_ADDR 0x1485 +#define RGB_COEFF_ADDR 0x1486 +#define POL_CNTL_ADDR 0x1487 +#define DITH_CNTL_ADDR 0x1488 +#define GAMMA_PROBE_CTRL 0x1489 +#define GAMMA_PROBE_COLOR_L 0x148a +#define GAMMA_PROBE_COLOR_H 0x148b +#define GAMMA_PROBE_HL_COLOR 0x148c +#define GAMMA_PROBE_POS_X 0x148d +#define GAMMA_PROBE_POS_Y 0x148e +#define STH1_HS_ADDR 0x1490 +#define STH1_HE_ADDR 0x1491 +#define STH1_VS_ADDR 0x1492 +#define STH1_VE_ADDR 0x1493 +#define STH2_HS_ADDR 0x1494 +#define STH2_HE_ADDR 0x1495 +#define STH2_VS_ADDR 0x1496 +#define STH2_VE_ADDR 0x1497 +#define OEH_HS_ADDR 0x1498 +#define OEH_HE_ADDR 0x1499 +#define OEH_VS_ADDR 0x149a +#define OEH_VE_ADDR 0x149b +#define VCOM_HSWITCH_ADDR 0x149c +#define VCOM_VS_ADDR 0x149d +#define VCOM_VE_ADDR 0x149e +#define CPV1_HS_ADDR 0x149f +#define CPV1_HE_ADDR 0x14a0 +#define CPV1_VS_ADDR 0x14a1 +#define CPV1_VE_ADDR 0x14a2 +#define CPV2_HS_ADDR 0x14a3 +#define CPV2_HE_ADDR 0x14a4 +#define CPV2_VS_ADDR 0x14a5 +#define CPV2_VE_ADDR 0x14a6 +#define STV1_HS_ADDR 0x14a7 +#define STV1_HE_ADDR 0x14a8 +#define STV1_VS_ADDR 0x14a9 +#define STV1_VE_ADDR 0x14aa +#define STV2_HS_ADDR 0x14ab +#define STV2_HE_ADDR 0x14ac +#define STV2_VS_ADDR 0x14ad +#define STV2_VE_ADDR 0x14ae +#define OEV1_HS_ADDR 0x14af +#define OEV1_HE_ADDR 0x14b0 +#define OEV1_VS_ADDR 0x14b1 +#define OEV1_VE_ADDR 0x14b2 +#define OEV2_HS_ADDR 0x14b3 +#define OEV2_HE_ADDR 0x14b4 +#define OEV2_VS_ADDR 0x14b5 +#define OEV2_VE_ADDR 0x14b6 +#define OEV3_HS_ADDR 0x14b7 +#define OEV3_HE_ADDR 0x14b8 +#define OEV3_VS_ADDR 0x14b9 +#define OEV3_VE_ADDR 0x14ba +#define LCD_PWR_ADDR 0x14bb +#define LCD_PWM0_LO_ADDR 0x14bc +#define LCD_PWM0_HI_ADDR 0x14bd +#define LCD_PWM1_LO_ADDR 0x14be +#define LCD_PWM1_HI_ADDR 0x14bf +#define INV_CNT_ADDR 0x14c0 +#define TCON_MISC_SEL_ADDR 0x14c1 +#define DUAL_PORT_CNTL_ADDR 0x14c2 +#define MLVDS_CONTROL 0x14c3 +#define MLVDS_RESET_PATTERN_HI 0x14c4 +#define MLVDS_RESET_PATTERN_LO 0x14c5 +#define MLVDS_RESET_PATTERN_EXT 0x14c6 +#define MLVDS_CONFIG_HI 0x14c7 +#define MLVDS_CONFIG_LO 0x14c8 +#define TCON_DOUBLE_CTL 0x14c9 +#define TCON_PATTERN_HI 0x14ca +#define TCON_PATTERN_LO 0x14cb +#define TCON_CONTROL_HI 0x14cc +#define TCON_CONTROL_LO 0x14cd +#define LVDS_BLANK_DATA_HI 0x14ce +#define LVDS_BLANK_DATA_LO 0x14cf +#define LVDS_PACK_CNTL_ADDR 0x14d0 +#define DE_HS_ADDR 0x14d1 +#define DE_HE_ADDR 0x14d2 +#define DE_VS_ADDR 0x14d3 +#define DE_VE_ADDR 0x14d4 +#define HSYNC_HS_ADDR 0x14d5 +#define HSYNC_HE_ADDR 0x14d6 +#define HSYNC_VS_ADDR 0x14d7 +#define HSYNC_VE_ADDR 0x14d8 +#define VSYNC_HS_ADDR 0x14d9 +#define VSYNC_HE_ADDR 0x14da +#define VSYNC_VS_ADDR 0x14db +#define VSYNC_VE_ADDR 0x14dc +#define LCD_MCU_CTL 0x14dd +#define LCD_MCU_DATA_0 0x14de +#define LCD_MCU_DATA_1 0x14df +#define LVDS_GEN_CNTL 0x14e0 +#define LVDS_PHY_CNTL0 0x14e1 +#define LVDS_PHY_CNTL1 0x14e2 +#define LVDS_PHY_CNTL2 0x14e3 +#define LVDS_PHY_CNTL3 0x14e4 +#define LVDS_PHY_CNTL4 0x14e5 +#define LVDS_PHY_CNTL5 0x14e6 +#define LVDS_SRG_TEST 0x14e8 +#define LVDS_BIST_MUX0 0x14e9 +#define LVDS_BIST_MUX1 0x14ea +#define LVDS_BIST_FIXED0 0x14eb +#define LVDS_BIST_FIXED1 0x14ec +#define LVDS_BIST_CNTL0 0x14ed +#define LVDS_CLKB_CLKA 0x14ee +#define LVDS_PHY_CLK_CNTL 0x14ef +#define LVDS_SER_EN 0x14f0 +#define LVDS_PHY_CNTL6 0x14f1 +#define LVDS_PHY_CNTL7 0x14f2 +#define LVDS_PHY_CNTL8 0x14f3 +#define MLVDS_CLK_CTL0_HI 0x14f4 +#define MLVDS_CLK_CTL0_LO 0x14f5 +#define MLVDS_DUAL_GATE_WR_START 0x14f6 +#define MLVDS_DUAL_GATE_WR_END 0x14f7 +#define MLVDS_DUAL_GATE_RD_START 0x14f8 +#define MLVDS_DUAL_GATE_RD_END 0x14f9 +#define MLVDS_SECOND_RESET_CTL 0x14fa +#define MLVDS_DUAL_GATE_CTL_HI 0x14fb +#define MLVDS_DUAL_GATE_CTL_LO 0x14fc +#define MLVDS_RESET_CONFIG_HI 0x14fd +#define MLVDS_RESET_CONFIG_LO 0x14fe +#define VPU_OSD1_MMC_CTRL 0x2701 +#define VPU_OSD2_MMC_CTRL 0x2702 +#define VPU_VD1_MMC_CTRL 0x2703 +#define VPU_VD2_MMC_CTRL 0x2704 +#define VPU_DI_IF1_MMC_CTRL 0x2705 +#define VPU_DI_MEM_MMC_CTRL 0x2706 +#define VPU_DI_INP_MMC_CTRL 0x2707 +#define VPU_DI_MTNRD_MMC_CTRL 0x2708 +#define VPU_DI_CHAN2_MMC_CTRL 0x2709 +#define VPU_DI_MTNWR_MMC_CTRL 0x270a +#define VPU_DI_NRWR_MMC_CTRL 0x270b +#define VPU_DI_DIWR_MMC_CTRL 0x270c +#define VPU_VDIN0_MMC_CTRL 0x270d +#define VPU_VDIN1_MMC_CTRL 0x270e +#define VPU_BT656_MMC_CTRL 0x270f +#define VPU_TVD3D_MMC_CTRL 0x2710 +#define VPU_TVDVBI_MMC_CTRL 0x2711 +#define VPU_TVDVBI_VSLATCH_ADDR 0x2712 +#define VPU_TVDVBI_WRRSP_ADDR 0x2713 +#define VPU_VDIN_PRE_ARB_CTRL 0x2714 +#define VPU_VDISP_PRE_ARB_CTRL 0x2715 +#define VPU_VPUARB2_PRE_ARB_CTRL 0x2716 +#define VPU_OSD3_MMC_CTRL 0x2717 +#define VPU_OSD4_MMC_CTRL 0x2718 +#define VPU_VD3_MMC_CTRL 0x2719 +#define VPU_VIU_VENC_MUX_CTRL 0x271a +#define VPU_HDMI_SETTING 0x271b +#define ENCI_INFO_READ 0x271c +#define ENCP_INFO_READ 0x271d +#define ENCT_INFO_READ 0x271e +#define ENCL_INFO_READ 0x271f +#define VPU_SW_RESET 0x2720 +#define VPU_D2D3_MMC_CTRL 0x2721 +#define VPU_CONT_MMC_CTRL 0x2722 +#define VPU_CLK_GATE 0x2723 +#define VPU_RDMA_MMC_CTRL 0x2724 +#define VPU_MEM_PD_REG0 0x2725 +#define VPU_MEM_PD_REG1 0x2726 +#define VPU_HDMI_DATA_OVR 0x2727 +#define VPU_PROT1_MMC_CTRL 0x2728 +#define VPU_PROT2_MMC_CTRL 0x2729 +#define VPU_PROT3_MMC_CTRL 0x272a +#define VPU_ARB4_V1_MMC_CTRL 0x272b +#define VPU_ARB4_V2_MMC_CTRL 0x272c +#define VPU_VPU_PWM_V0 0x2730 +#define VPU_VPU_PWM_V1 0x2731 +#define VPU_VPU_PWM_V2 0x2732 +#define VPU_VPU_PWM_V3 0x2733 +#define VPU_VPU_PWM_H0 0x2734 +#define VPU_VPU_PWM_H1 0x2735 +#define VPU_VPU_PWM_H2 0x2736 +#define VPU_VPU_PWM_H3 0x2737 +#define VPU_MISC_CTRL 0x2740 +#define VPU_ISP_GCLK_CTRL0 0x2741 +#define VPU_ISP_GCLK_CTRL1 0x2742 +#define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743 +#define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744 +#define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745 + +#define VPU_PROT1_CLK_GATE 0x2750 +#define VPU_PROT1_GEN_CNTL 0x2751 +#define VPU_PROT1_X_START_END 0x2752 +#define VPU_PROT1_Y_START_END 0x2753 +#define VPU_PROT1_Y_LEN_STEP 0x2754 +#define VPU_PROT1_RPT_LOOP 0x2755 +#define VPU_PROT1_RPT_PAT 0x2756 +#define VPU_PROT1_DDR 0x2757 +#define VPU_PROT1_RBUF_ROOM 0x2758 +#define VPU_PROT1_STAT_0 0x2759 +#define VPU_PROT1_STAT_1 0x275a +#define VPU_PROT1_STAT_2 0x275b +#define VPU_PROT1_REQ_ONOFF 0x275c +#define VPU_PROT2_CLK_GATE 0x2760 +#define VPU_PROT2_GEN_CNTL 0x2761 +#define VPU_PROT2_X_START_END 0x2762 +#define VPU_PROT2_Y_START_END 0x2763 +#define VPU_PROT2_Y_LEN_STEP 0x2764 +#define VPU_PROT2_RPT_LOOP 0x2765 +#define VPU_PROT2_RPT_PAT 0x2766 +#define VPU_PROT2_DDR 0x2767 +#define VPU_PROT2_RBUF_ROOM 0x2768 +#define VPU_PROT2_STAT_0 0x2769 +#define VPU_PROT2_STAT_1 0x276a +#define VPU_PROT2_STAT_2 0x276b +#define VPU_PROT2_REQ_ONOFF 0x276c +#define VPU_PROT3_CLK_GATE 0x2770 +#define VPU_PROT3_GEN_CNTL 0x2771 +#define VPU_PROT3_X_START_END 0x2772 +#define VPU_PROT3_Y_START_END 0x2773 +#define VPU_PROT3_Y_LEN_STEP 0x2774 +#define VPU_PROT3_RPT_LOOP 0x2775 +#define VPU_PROT3_RPT_PAT 0x2776 +#define VPU_PROT3_DDR 0x2777 +#define VPU_PROT3_RBUF_ROOM 0x2778 +#define VPU_PROT3_STAT_0 0x2779 +#define VPU_PROT3_STAT_1 0x277a +#define VPU_PROT3_STAT_2 0x277b +#define VPU_PROT3_REQ_ONOFF 0x277c +#define VPU_RDARB_MODE_L1C2 0x2799 + +/* osd afbcd on gxtvbb */ +#define OSD1_AFBCD_ENABLE 0x31a0 +#define OSD1_AFBCD_MODE 0x31a1 +#define OSD1_AFBCD_SIZE_IN 0x31a2 +#define OSD1_AFBCD_HDR_PTR 0x31a3 +#define OSD1_AFBCD_FRAME_PTR 0x31a4 +#define OSD1_AFBCD_CHROMA_PTR 0x31a5 +#define OSD1_AFBCD_CONV_CTRL 0x31a6 +#define OSD1_AFBCD_STATUS 0x31a8 +#define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9 +#define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa +#define VIU_MISC_CTRL1 0x1a07 + + +/* add for gxm and 962e dv core2 */ +#define DOLBY_CORE2A_SWAP_CTRL1 0x3434 +#define DOLBY_CORE2A_SWAP_CTRL2 0x3435 + +/* osd afbc on g12a */ +#define VPU_MAFBC_BLOCK_ID 0x3a00 +#define VPU_MAFBC_IRQ_RAW_STATUS 0x3a01 +#define VPU_MAFBC_IRQ_CLEAR 0x3a02 +#define VPU_MAFBC_IRQ_MASK 0x3a03 +#define VPU_MAFBC_IRQ_STATUS 0x3a04 +#define VPU_MAFBC_COMMAND 0x3a05 +#define VPU_MAFBC_STATUS 0x3a06 +#define VPU_MAFBC_SURFACE_CFG 0x3a07 + +/* osd afbc on g12a */ +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10 +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11 +#define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12 +#define VPU_MAFBC_BUFFER_WIDTH_S0 0x3a13 +#define VPU_MAFBC_BUFFER_HEIGHT_S0 0x3a14 +#define VPU_MAFBC_BOUNDING_BOX_X_START_S0 0x3a15 +#define VPU_MAFBC_BOUNDING_BOX_X_END_S0 0x3a16 +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S0 0x3a17 +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S0 0x3a18 +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0 0x3a19 +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0 0x3a1a +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S0 0x3a1b +#define VPU_MAFBC_PREFETCH_CFG_S0 0x3a1c + +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1 0x3a30 +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1 0x3a31 +#define VPU_MAFBC_FORMAT_SPECIFIER_S1 0x3a32 +#define VPU_MAFBC_BUFFER_WIDTH_S1 0x3a33 +#define VPU_MAFBC_BUFFER_HEIGHT_S1 0x3a34 +#define VPU_MAFBC_BOUNDING_BOX_X_START_S1 0x3a35 +#define VPU_MAFBC_BOUNDING_BOX_X_END_S1 0x3a36 +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S1 0x3a37 +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S1 0x3a38 +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1 0x3a39 +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1 0x3a3a +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S1 0x3a3b +#define VPU_MAFBC_PREFETCH_CFG_S1 0x3a3c + +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2 0x3a50 +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2 0x3a51 +#define VPU_MAFBC_FORMAT_SPECIFIER_S2 0x3a52 +#define VPU_MAFBC_BUFFER_WIDTH_S2 0x3a53 +#define VPU_MAFBC_BUFFER_HEIGHT_S2 0x3a54 +#define VPU_MAFBC_BOUNDING_BOX_X_START_S2 0x3a55 +#define VPU_MAFBC_BOUNDING_BOX_X_END_S2 0x3a56 +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S2 0x3a57 +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S2 0x3a58 +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2 0x3a59 +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2 0x3a5a +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S2 0x3a5b +#define VPU_MAFBC_PREFETCH_CFG_S2 0x3a5c + +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S3 0x3a70 +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S3 0x3a71 +#define VPU_MAFBC_FORMAT_SPECIFIER_S3 0x3a72 +#define VPU_MAFBC_BUFFER_WIDTH_S3 0x3a73 +#define VPU_MAFBC_BUFFER_HEIGHT_S3 0x3a74 +#define VPU_MAFBC_BOUNDING_BOX_X_START_S3 0x3a75 +#define VPU_MAFBC_BOUNDING_BOX_X_END_S3 0x3a76 +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S3 0x3a77 +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S3 0x3a78 +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S3 0x3a79 +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S3 0x3a7a +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S3 0x3a7b +#define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c + +#define DOLBY_PATH_CTRL 0x1a0c +#define OSD_PATH_MISC_CTRL 0x1a0e +#define MALI_AFBCD_TOP_CTRL 0x1a0f + +#define VPP_OUT_H_V_SIZE 0x1da5 + +#define VPP_VD2_HDR_IN_SIZE 0x1df0 +#define VPP_GCLK_CTRL2 0x1df2 +#define VD2_PPS_DUMMY_DATA 0x1df4 +#define VPP_WRBAK_CTRL 0x1df9 +#define VPP_SLEEP_CTRL 0x1dfa + +#define VPP_RDARB_MODE 0x3978 +#define VPP_RDARB_REQEN_SLV 0x3979 +#define VPU_RDARB_MODE_L2C1 0x279d + +/*VIU2 osd1 reg*/ +#define VIU2_OSD1_MATRIX_COEF00_01 0x1e70 +#define VIU2_OSD1_MATRIX_COEF02_10 0x1e71 +#define VIU2_OSD1_MATRIX_COEF11_12 0x1e72 +#define VIU2_OSD1_MATRIX_COEF20_21 0x1e73 +#define VIU2_OSD1_MATRIX_COEF22 0x1e74 +#define VIU2_OSD1_MATRIX_COEF13_14 0x1e75 +#define VIU2_OSD1_MATRIX_COEF23_24 0x1e76 +#define VIU2_OSD1_MATRIX_COEF15_25 0x1e77 +#define VIU2_OSD1_MATRIX_CLIP 0x1e78 +#define VIU2_OSD1_MATRIX_OFFSET0_1 0x1e79 +#define VIU2_OSD1_MATRIX_OFFSET2 0x1e7a +#define VIU2_OSD1_MATRIX_PRE_OFFSET0_1 0x1e7b +#define VIU2_OSD1_MATRIX_PRE_OFFSET2 0x1e7c +#define VIU2_OSD1_MATRIX_EN_CTRL 0x1e7d + +/* reg definition */ + +struct afbc_osd1_reg { + u32 vpu_mafbc_header_buf_addr_low_s0; + u32 vpu_mafbc_header_buf_addr_high_s0; + u32 vpu_mafbc_format_specifier_s0; + u32 vpu_mafbc_buffer_width_s0; + u32 vpu_mafbc_buffer_height_s0; + u32 vpu_mafbc_bounding_box_x_start_s0; + u32 vpu_mafbc_bounding_box_x_end_s0; + u32 vpu_mafbc_bounding_box_y_start_s0; + u32 vpu_mafbc_bounding_box_y_end_s0; + u32 vpu_mafbc_output_buf_addr_low_s0; + u32 vpu_mafbc_output_buf_addr_high_s0; + u32 vpu_mafbc_output_buf_stride_s0; + u32 vpu_mafbc_prefetch_cfg_s0; + u32 vpu_mafbc_payload_min_low_s0; + u32 vpu_mafbc_payload_min_high_s0; + u32 vpu_mafbc_payload_max_low_s0; + u32 vpu_mafbc_payload_max_high_s0; +}; + +struct afbc_osd2_reg { + u32 vpu_mafbc_header_buf_addr_low_s1; + u32 vpu_mafbc_header_buf_addr_high_s1; + u32 vpu_mafbc_format_specifier_s1; + u32 vpu_mafbc_buffer_width_s1; + u32 vpu_mafbc_buffer_height_s1; + u32 vpu_mafbc_bounding_box_x_start_s1; + u32 vpu_mafbc_bounding_box_x_end_s1; + u32 vpu_mafbc_bounding_box_y_start_s1; + u32 vpu_mafbc_bounding_box_y_end_s1; + u32 vpu_mafbc_output_buf_addr_low_s1; + u32 vpu_mafbc_output_buf_addr_high_s1; + u32 vpu_mafbc_output_buf_stride_s1; + u32 vpu_mafbc_prefetch_cfg_s1; + u32 vpu_mafbc_payload_min_low_s1; + u32 vpu_mafbc_payload_min_high_s1; + u32 vpu_mafbc_payload_max_low_s1; + u32 vpu_mafbc_payload_max_high_s1; +}; + +struct afbc_osd3_reg { + u32 vpu_mafbc_header_buf_addr_low_s2; + u32 vpu_mafbc_header_buf_addr_high_s2; + u32 vpu_mafbc_format_specifier_s2; + u32 vpu_mafbc_buffer_width_s2; + u32 vpu_mafbc_buffer_height_s2; + u32 vpu_mafbc_bounding_box_x_start_s2; + u32 vpu_mafbc_bounding_box_x_end_s2; + u32 vpu_mafbc_bounding_box_y_start_s2; + u32 vpu_mafbc_bounding_box_y_end_s2; + u32 vpu_mafbc_output_buf_addr_low_s2; + u32 vpu_mafbc_output_buf_addr_high_s2; + u32 vpu_mafbc_output_buf_stride_s2; + u32 vpu_mafbc_prefetch_cfg_s2; + u32 vpu_mafbc_payload_min_low_s2; + u32 vpu_mafbc_payload_min_high_s2; + u32 vpu_mafbc_payload_max_low_s2; + u32 vpu_mafbc_payload_max_high_s2; +}; + +struct afbc_status_reg { + u32 vpu_mafbc_block_id; + u32 vpu_mafbc_irq_raw_status; + u32 vpu_mafbc_irq_clear; + u32 vpu_mafbc_irq_mask; + u32 vpu_mafbc_irq_status; + u32 vpu_mafbc_command; + u32 vpu_mafbc_status; + u32 vpu_mafbc_surface_cfg; +}; + +union afbc_osd_reg { + struct afbc_osd1_reg afbc_osd1; + struct afbc_osd2_reg afbc_osd2; + struct afbc_osd3_reg afbc_osd3; +}; + +#endif diff --git a/include/dt-bindings/display/meson-drm-ids.h b/include/dt-bindings/display/meson-drm-ids.h new file mode 100644 index 0000000..b163eaa --- a/dev/null +++ b/include/dt-bindings/display/meson-drm-ids.h @@ -0,0 +1,53 @@ +#ifndef _MESON_DRM_IDS_H_ +#define _MESON_DRM_IDS_H_ + +#define OSD1_BLOCK 0 +#define OSD2_BLOCK 1 +#define OSD3_BLOCK 2 +#define AFBC_OSD1_BLOCK 3 +#define AFBC_OSD2_BLOCK 4 +#define AFBC_OSD3_BLOCK 5 +#define SCALER_OSD1_BLOCK 6 +#define SCALER_OSD2_BLOCK 7 +#define SCALER_OSD3_BLOCK 8 +#define OSD_BLEND_BLOCK 9 +#define OSD1_HDR_BLOCK 10 +#define VPP_POSTBLEND_BLOCK 11 + +#define OSD1_PORT 0 +#define OSD2_PORT 1 +#define OSD3_PORT 2 +#define AFBC_OSD1_PORT 3 +#define AFBC_OSD2_PORT 4 +#define AFBC_OSD3_PORT 5 +#define SCALER_OSD1_PORT 6 +#define SCALER_OSD2_PORT 7 +#define SCALER_OSD3_PORT 8 +#define OSDBLEND_DIN1_PORT 9 +#define OSDBLEND_DIN2_PORT 10 +#define OSDBLEND_DIN3_PORT 11 +#define OSDBLEND_DOUT1_PORT 12 +#define OSDBLEND_DOUT2_PORT 13 +#define OSD1_HDR_PORT 14 +#define OSD1_DOLBY_PORT 15 +#define VPP_POSTBLEND_OSD1_IN_PORT 16 +#define VPP_POSTBLEND_OSD2_IN_PORT 17 +#define VPP_POSTBLEND_OUT_PORT 18 + +/* + *OSD VERSION + *V1:G12A + *V2:G12B-revA:base G12A,add repeate last line function + *V3:G12B-RevB:add line interrupt support + *V4:TL1:base G12A,fix shift issue,delete osd3 + *V5:SM1:base G12A,fix shift issue + *V6:TM2,base G12A,fix shift issue,add mux for osd1-sr + */ +#define OSD_V1 1 +#define OSD_V2 2 +#define OSD_V3 3 +#define OSD_V4 4 +#define OSD_V5 5 +#define OSD_V6 6 + +#endif diff --git a/include/linux/amlogic/meson_drm.h b/include/linux/amlogic/meson_drm.h deleted file mode 100644 index cad57fe..0000000 --- a/include/linux/amlogic/meson_drm.h +++ b/dev/null @@ -1,72 +0,0 @@ -/* - * include/uapi/drm/meson_drm.h - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef _MESON_DRM_H -#define _MESON_DRM_H - -#include <drm/drm.h> - -/* memory type definitions. */ -enum drm_meson_gem_mem_type { - /* Physically Continuous memory. */ - MESON_BO_CONTIG = 1 << 0, - /* cachable mapping. */ - MESON_BO_CACHABLE = 1 << 1, - /* write-combine mapping. */ - MESON_BO_WC = 1 << 2, - MESON_BO_SECURE = 1 << 3, - MESON_BO_MASK = MESON_BO_CONTIG | MESON_BO_CACHABLE | - MESON_BO_WC -}; - -/* Use flags */ -#define BO_USE_NONE 0 -#define BO_USE_SCANOUT (1ull << 0) -#define BO_USE_CURSOR (1ull << 1) -#define BO_USE_CURSOR_64X64 BO_USE_CURSOR -#define BO_USE_RENDERING (1ull << 2) -#define BO_USE_LINEAR (1ull << 3) -#define BO_USE_SW_READ_NEVER (1ull << 4) -#define BO_USE_SW_READ_RARELY (1ull << 5) -#define BO_USE_SW_READ_OFTEN (1ull << 6) -#define BO_USE_SW_WRITE_NEVER (1ull << 7) -#define BO_USE_SW_WRITE_RARELY (1ull << 8) -#define BO_USE_SW_WRITE_OFTEN (1ull << 9) -#define BO_USE_EXTERNAL_DISP (1ull << 10) -#define BO_USE_PROTECTED (1ull << 11) -#define BO_USE_HW_VIDEO_ENCODER (1ull << 12) -#define BO_USE_CAMERA_WRITE (1ull << 13) -#define BO_USE_CAMERA_READ (1ull << 14) -#define BO_USE_RENDERSCRIPT (1ull << 16) -#define BO_USE_TEXTURE (1ull << 17) - - -/** - * User-desired buffer creation information structure. - * - * @size: user-desired memory allocation size. - * @flags: user request for setting memory type or cache attributes. - * @handle: returned a handle to created gem object. - * - this handle will be set by gem module of kernel side. - */ -struct drm_meson_gem_create { - uint64_t size; - uint32_t flags; - uint32_t handle; -}; - -#define DRM_MESON_GEM_CREATE 0x00 - -#define DRM_IOCTL_MESON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ - DRM_MESON_GEM_CREATE, struct drm_meson_gem_create) - -#endif /* _MESON_DRM_H */ - diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index fc0cac3..9f74715 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -160,6 +160,7 @@ extern "C" { #define DRM_FORMAT_MOD_VENDOR_NV 0x03 #define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04 #define DRM_FORMAT_MOD_VENDOR_QCOM 0x05 +#define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x09 /* add more to the end as needed */ #define DRM_FORMAT_RESERVED ((1ULL << 56) - 1) @@ -255,6 +256,9 @@ extern "C" { */ #define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1) +#define DRM_FORMAT_MOD_MESON_AFBC fourcc_mod_code(AMLOGIC, 1) +#define DRM_FORMAT_MOD_MESON_AFBC_WB fourcc_mod_code(AMLOGIC, 2) + #if defined(__cplusplus) } #endif diff --git a/include/uapi/drm/meson_drm.h b/include/uapi/drm/meson_drm.h new file mode 100644 index 0000000..5b12674 --- a/dev/null +++ b/include/uapi/drm/meson_drm.h @@ -0,0 +1,49 @@ +/* + * include/uapi/drm/meson_drm.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef _MESON_DRM_H +#define _MESON_DRM_H + +#include <drm/drm.h> + +/* Use flags */ +#define MESON_USE_NONE 0 +#define MESON_USE_SCANOUT (1ull << 0) +#define MESON_USE_CURSOR (1ull << 1) +#define MESON_USE_RENDERING (1ull << 2) +#define MESON_USE_LINEAR (1ull << 3) +#define MESON_USE_PROTECTED (1ull << 11) +#define MESON_USE_HW_VIDEO_ENCODER (1ull << 12) +#define MESON_USE_CAMERA_WRITE (1ull << 13) +#define MESON_USE_CAMERA_READ (1ull << 14) +#define MESON_USE_TEXTURE (1ull << 17) + + +/** + * User-desired buffer creation information structure. + * + * @size: user-desired memory allocation size. + * @flags: user request for setting memory type or cache attributes. + * @handle: returned a handle to created gem object. + * - this handle will be set by gem module of kernel side. + */ +struct drm_meson_gem_create { + __u64 size; + __u32 flags; + __u32 handle; +}; + +#define DRM_MESON_GEM_CREATE 0x00 + +#define DRM_IOCTL_MESON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ + DRM_MESON_GEM_CREATE, struct drm_meson_gem_create) + +#endif /* _MESON_DRM_H */ |