From 59aee35fdaf1d9b62dd9805eb6ea9ec5d172c9df Mon Sep 17 00:00:00 2001 From: "zhilei.wu" Date: Fri, 2 Mar 2018 15:43:21 +0800 Subject: [PATCH] dv: add dolby vision driver for g12a PD#156734: dv: add dolby vision driver for g12a Change-Id: I02490c69f6f834f491278403dfcc8923a3fcee77 Signed-off-by: zhilei.wu --- MAINTAINERS | 5 + arch/arm64/boot/dts/amlogic/g12a_skt.dts | 6 +- .../boot/dts/amlogic/g12a_skt_buildroot.dts | 6 +- arch/arm64/configs/meson64_defconfig | 1 + .../arm64/configs/meson64_smarthome_defconfig | 1 + drivers/amlogic/media/common/vfm/vfm.c | 4 +- drivers/amlogic/media/enhancement/Kconfig | 1 + drivers/amlogic/media/enhancement/Makefile | 1 + .../media/enhancement/amdolby_vision/Kconfig | 15 + .../media/enhancement/amdolby_vision/Makefile | 7 + .../amdolby_vision/amdolby_vision.c | 6042 +++++++++++++++++ .../amdolby_vision/amdolby_vision.h | 623 ++ .../amlogic/media/enhancement/amvecm/Makefile | 3 +- .../amlogic/media/enhancement/amvecm/amcm.c | 15 +- .../amlogic/media/enhancement/amvecm/amcsc.c | 93 +- .../media/enhancement/amvecm/amdolby_vision.c | 2086 ------ .../amlogic/media/enhancement/amvecm/amvecm.c | 77 +- .../amvecm/arch/vpp_dolbyvision_regs.h | 21 +- .../amvecm/dolby_vision/dolby_vision.h | 302 - drivers/amlogic/media/osd/osd_fb.c | 2 +- drivers/amlogic/media/osd/osd_hw.c | 22 + drivers/amlogic/media/video_sink/video.c | 147 +- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c | 192 +- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 377 +- .../vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c | 34 +- .../vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 12 + .../media/amdolbyvision/dolby_vision.h | 48 + include/linux/amlogic/media/amvecm/amvecm.h | 18 - .../media/vout/hdmi_tx/hdmi_tx_module.h | 1 + include/linux/amlogic/media/vout/vinfo.h | 103 +- 30 files changed, 7491 insertions(+), 2774 deletions(-) create mode 100644 drivers/amlogic/media/enhancement/amdolby_vision/Kconfig create mode 100644 drivers/amlogic/media/enhancement/amdolby_vision/Makefile create mode 100644 drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c create mode 100644 drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h delete mode 100644 drivers/amlogic/media/enhancement/amvecm/amdolby_vision.c delete mode 100644 drivers/amlogic/media/enhancement/amvecm/dolby_vision/dolby_vision.h create mode 100644 include/linux/amlogic/media/amdolbyvision/dolby_vision.h diff --git a/MAINTAINERS b/MAINTAINERS index 71a11ee63f40..8bc27774b9da 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14367,3 +14367,8 @@ F: sound/soc/amlogic/auge/* AMLOGIC G12A BL_EXTERN LP8556 DRIVER M: Weiming Liu F: drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c + +AMLOGIC G12A Dolby Vision DRIVER +M: Zhilei Wu +F: drivers/amlogic/media/enhancement/amdolby_vision* +F: include/linux/amlogic/media/amdolbyvision/* diff --git a/arch/arm64/boot/dts/amlogic/g12a_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_skt.dts index 596f1be31085..cb202a2bd8bb 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_skt.dts @@ -869,7 +869,11 @@ wb_en = <0>;/*1:enabel ;0:disable*/ cm_en = <0>;/*1:enabel ;0:disable*/ }; - + amdolby_vision { + compatible = "amlogic, aml_amdolby_vision_driver"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + }; meson-amvideom { compatible = "amlogic, amvideom"; dev_name = "amvideom"; diff --git a/arch/arm64/boot/dts/amlogic/g12a_skt_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_skt_buildroot.dts index 439443a7d600..083fd2340549 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_skt_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_skt_buildroot.dts @@ -980,7 +980,11 @@ wb_en = <0>;/*1:enabel ;0:disable*/ cm_en = <0>;/*1:enabel ;0:disable*/ }; - + amdolby_vision { + compatible = "amlogic, aml_amdolby_vision_driver"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + }; meson-amvideom { compatible = "amlogic, amvideom"; dev_name = "amvideom"; diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 74fb82f4b4dc..d6708a367767 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -309,6 +309,7 @@ CONFIG_AMLOGIC_IONVIDEO=y CONFIG_AMLOGIC_PIC_DEC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y CONFIG_AMLOGIC_VRTC=y diff --git a/arch/arm64/configs/meson64_smarthome_defconfig b/arch/arm64/configs/meson64_smarthome_defconfig index 8587ebef43d3..09aa6279ca12 100644 --- a/arch/arm64/configs/meson64_smarthome_defconfig +++ b/arch/arm64/configs/meson64_smarthome_defconfig @@ -278,6 +278,7 @@ CONFIG_AMLOGIC_VIDEOBUF2_ION=y CONFIG_AMLOGIC_IONVIDEO=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y CONFIG_AMLOGIC_VRTC=y diff --git a/drivers/amlogic/media/common/vfm/vfm.c b/drivers/amlogic/media/common/vfm/vfm.c index aca9bcac3d7f..f60eb1f2c8bd 100644 --- a/drivers/amlogic/media/common/vfm/vfm.c +++ b/drivers/amlogic/media/common/vfm/vfm.c @@ -397,7 +397,7 @@ static void vfm_init(void) char tvpath_chain[] = "vdin0 deinterlace amvideo"; #endif #endif /**/ -#ifdef CONFIG_AM_VDEC_DV +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION char def_dvbl_id[] = "dvblpath"; /* char def_dvbl_chain[] = "dvbldec dvbl amvideo";*/ char def_dvbl_chain[] = "dvbldec amvideo"; @@ -427,7 +427,7 @@ static void vfm_init(void) #ifdef CONFIG_AMLOGIC_V4L_VIDEO2 vfm_map_add(def_amlvideo2_id, def_amlvideo2_chain); #endif /**/ -#ifdef CONFIG_AM_VDEC_DV +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION vfm_map_add(def_dvbl_id, def_dvbl_chain); vfm_map_add(def_dvel_id, def_dvel_chain); #endif diff --git a/drivers/amlogic/media/enhancement/Kconfig b/drivers/amlogic/media/enhancement/Kconfig index 4934a963049a..d4c423730f77 100644 --- a/drivers/amlogic/media/enhancement/Kconfig +++ b/drivers/amlogic/media/enhancement/Kconfig @@ -11,6 +11,7 @@ config AMLOGIC_MEDIA_ENHANCEMENT if AMLOGIC_MEDIA_ENHANCEMENT source "drivers/amlogic/media/enhancement/amvecm/Kconfig" +source "drivers/amlogic/media/enhancement/amdolby_vision/Kconfig" endif endmenu diff --git a/drivers/amlogic/media/enhancement/Makefile b/drivers/amlogic/media/enhancement/Makefile index d7762a8f8be8..b5e365f74498 100644 --- a/drivers/amlogic/media/enhancement/Makefile +++ b/drivers/amlogic/media/enhancement/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) += amvecm/ +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION) += amdolby_vision/ \ No newline at end of file diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/Kconfig b/drivers/amlogic/media/enhancement/amdolby_vision/Kconfig new file mode 100644 index 000000000000..098d0ef551fd --- /dev/null +++ b/drivers/amlogic/media/enhancement/amdolby_vision/Kconfig @@ -0,0 +1,15 @@ +# +# AMLOGIC amdolby_vision devices configuration +# + +comment "Amlogic amdolby_vision Drivers" + +menu "Amlogic amdolby_vision Driver" + +config AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + bool "Amlogic amdolby_vision driver" + default n + help + "Amlogic amdolby_vision module init" + +endmenu diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/Makefile b/drivers/amlogic/media/enhancement/amdolby_vision/Makefile new file mode 100644 index 000000000000..4419ef3639bd --- /dev/null +++ b/drivers/amlogic/media/enhancement/amdolby_vision/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for amdolby_vision +# + +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION) += amdolby_vision.o + + diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c new file mode 100644 index 000000000000..f2a2001155f1 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -0,0 +1,6042 @@ +/* + * drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../amvecm/arch/vpp_regs.h" +#include "../amvecm/arch/vpp_hdr_regs.h" +#include "../amvecm/arch/vpp_dolbyvision_regs.h" +#include +#include +#include +#include +#include +#include +#include "amdolby_vision.h" + +#include +#include +#include +#include +#include +#include +#include +#include /* for parse_para_pq */ +#include + +DEFINE_SPINLOCK(dovi_lock); + +static const struct dolby_vision_func_s *p_funcs; + +#define AMDOLBY_VISION_NAME "amdolby_vision" +#define AMDOLBY_VISION_CLASS_NAME "amdolby_vision" + +struct amdolby_vision_dev_s { + dev_t devt; + struct cdev cdev; + dev_t devno; + struct device *dev; + struct class *clsp; +}; + +static struct amdolby_vision_dev_s amdolby_vision_dev; + +#define DOLBY_VISION_OUTPUT_MODE_IPT 0 +#define DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL 1 +#define DOLBY_VISION_OUTPUT_MODE_HDR10 2 +#define DOLBY_VISION_OUTPUT_MODE_SDR10 3 +#define DOLBY_VISION_OUTPUT_MODE_SDR8 4 +#define DOLBY_VISION_OUTPUT_MODE_BYPASS 5 +static unsigned int dolby_vision_mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; +module_param(dolby_vision_mode, uint, 0664); +MODULE_PARM_DESC(dolby_vision_mode, "\n dolby_vision_mode\n"); + +/* STB: if sink support DV, always output DV*/ +/* else always output SDR/HDR */ +/* TV: when source is DV, convert to SDR */ +#define DOLBY_VISION_FOLLOW_SINK 0 + +/* STB: output DV only if source is DV*/ +/* and sink support DV*/ +/* else always output SDR/HDR */ +/* TV: when source is DV or HDR, convert to SDR */ +#define DOLBY_VISION_FOLLOW_SOURCE 1 + +/* STB: always follow dolby_vision_mode */ +/* TV: if set dolby_vision_mode to SDR8,*/ +/* convert all format to SDR by TV core,*/ +/* else bypass Dolby Vision */ +#define DOLBY_VISION_FORCE_OUTPUT_MODE 2 + +static unsigned int dolby_vision_policy; +module_param(dolby_vision_policy, uint, 0664); +MODULE_PARM_DESC(dolby_vision_policy, "\n dolby_vision_policy\n"); + +/* bit0: 0: bypass hdr to vpp, 1: process hdr by dolby core */ +/* bit1: 0: output to sdr, 1: output to hdr if sink support hdr not dovi */ +static unsigned int dolby_vision_hdr10_policy; +module_param(dolby_vision_hdr10_policy, uint, 0664); +MODULE_PARM_DESC(dolby_vision_hdr10_policy, "\n dolby_vision_hdr10_policy\n"); + +static bool dolby_vision_enable; +module_param(dolby_vision_enable, bool, 0664); +MODULE_PARM_DESC(dolby_vision_enable, "\n dolby_vision_enable\n"); + +static bool force_stb_mode; + +static bool dolby_vision_efuse_bypass; +module_param(dolby_vision_efuse_bypass, bool, 0664); +MODULE_PARM_DESC(dolby_vision_efuse_bypass, "\n dolby_vision_efuse_bypass\n"); +static bool efuse_mode; + +static bool el_mode; +module_param(force_stb_mode, bool, 0664); +MODULE_PARM_DESC(force_stb_mode, "\n force_stb_mode\n"); + +static uint dolby_vision_mask = 7; +module_param(dolby_vision_mask, uint, 0664); +MODULE_PARM_DESC(dolby_vision_mask, "\n dolby_vision_mask\n"); + +#define BYPASS_PROCESS 0 +#define SDR_PROCESS 1 +#define HDR_PROCESS 2 +#define DV_PROCESS 3 +static uint dolby_vision_status; +module_param(dolby_vision_status, uint, 0664); +MODULE_PARM_DESC(dolby_vision_status, "\n dolby_vision_status\n"); + +/* delay before first frame toggle when core off->on */ +static uint dolby_vision_wait_delay; +module_param(dolby_vision_wait_delay, uint, 0664); +MODULE_PARM_DESC(dolby_vision_wait_delay, "\n dolby_vision_wait_delay\n"); +static int dolby_vision_wait_count; + +/* reset 1st fake frame (bit 0)*/ +/* and other fake frames (bit 1)*/ +/* and other toggle frames (bit 2) */ +static uint dolby_vision_reset = (1 << 1) | (1 << 0); +module_param(dolby_vision_reset, uint, 0664); +MODULE_PARM_DESC(dolby_vision_reset, "\n dolby_vision_reset\n"); + +/* force run mode */ +static uint dolby_vision_run_mode = 0xff; /* not force */ +module_param(dolby_vision_run_mode, uint, 0664); +MODULE_PARM_DESC(dolby_vision_run_mode, "\n dolby_vision_run_mode\n"); + +/* number of fake frame (run mode = 1) */ +#define RUN_MODE_DELAY 2 +static uint dolby_vision_run_mode_delay = RUN_MODE_DELAY; +module_param(dolby_vision_run_mode_delay, uint, 0664); +MODULE_PARM_DESC(dolby_vision_run_mode_delay, "\n dolby_vision_run_mode_delay\n"); + +/* reset control -- end << 8 | start */ +static uint dolby_vision_reset_delay = + (RUN_MODE_DELAY << 8) | RUN_MODE_DELAY; +module_param(dolby_vision_reset_delay, uint, 0664); +MODULE_PARM_DESC(dolby_vision_reset_delay, "\n dolby_vision_reset_delay\n"); + +static unsigned int dolby_vision_tunning_mode; +module_param(dolby_vision_tunning_mode, uint, 0664); +MODULE_PARM_DESC(dolby_vision_tunning_mode, "\n dolby_vision_tunning_mode\n"); + +#ifdef V2_4 +#define DV_LL_OUTPUT_BITS 12 +/* bit0 ~ bit7: output mode, bit8 ~ bit15: output bits */ +static unsigned int dv_ll_output_mode = + (DV_LL_OUTPUT_BITS << 8) | DOLBY_VISION_OUTPUT_MODE_HDR10; +module_param(dv_ll_output_mode, uint, 0664); +MODULE_PARM_DESC(dv_ll_output_mode, "\n dv_ll_output_mode\n"); + +#define DOLBY_VISION_LL_DISABLE 0 +#define DOLBY_VISION_LL_YUV422 1 +#define DOLBY_VISION_LL_RGB444 2 +static u32 dolby_vision_ll_policy = DOLBY_VISION_LL_DISABLE; +module_param(dolby_vision_ll_policy, uint, 0664); +MODULE_PARM_DESC(dolby_vision_ll_policy, "\n dolby_vision_ll_policy\n"); +static u32 last_dolby_vision_ll_policy = DOLBY_VISION_LL_DISABLE; +#endif + +static uint dolby_vision_on_count; + +#define FLAG_BYPASS_CVM 0x02 +#define FLAG_BYPASS_VPP 0x04 +#define FLAG_USE_SINK_MIN_MAX 0x08 +#define FLAG_CLKGATE_WHEN_LOAD_LUT 0x10 +#define FLAG_SINGLE_STEP 0x20 +#define FLAG_CERTIFICAION 0x40 +#define FLAG_CHANGE_SEQ_HEAD 0x80 +#define FLAG_DISABLE_COMPOSER 0x100 +#define FLAG_BYPASS_CSC 0x200 +#define FLAG_CHECK_ES_PTS 0x400 +#define FLAG_DISABE_CORE_SETTING 0x800 +#define FLAG_DISABLE_DMA_UPDATE 0x1000 +#define FLAG_DISABLE_DOVI_OUT 0x2000 +#define FLAG_FORCE_DOVI_LL 0x4000 +#define FLAG_FORCE_RGB_OUTPUT 0x8000 +/* #define FLAG_DOVI_LL_RGB_DESIRED 0x8000 */ +#define FLAG_DOVI2HDR10_NOMAPPING 0x100000 +#define FLAG_PRIORITY_GRAPHIC 0x200000 +#define FLAG_DISABLE_LOAD_VSVDB 0x400000 +#define FLAG_DISABLE_CRC 0x800000 +#define FLAG_TOGGLE_FRAME 0x80000000 + +#define FLAG_FRAME_DELAY_MASK 0xf +#define FLAG_FRAME_DELAY_SHIFT 16 + +static unsigned int dolby_vision_flags = FLAG_BYPASS_VPP; +module_param(dolby_vision_flags, uint, 0664); +MODULE_PARM_DESC(dolby_vision_flags, "\n dolby_vision_flags\n"); + +static unsigned int htotal_add = 0x140; +static unsigned int vtotal_add = 0x40; +static unsigned int vsize_add; +static unsigned int vwidth = 0x8; +static unsigned int hwidth = 0x8; +static unsigned int vpotch = 0x10; +static unsigned int hpotch = 0x8; +static unsigned int g_htotal_add = 0x40; +static unsigned int g_vtotal_add = 0x80; +static unsigned int g_vsize_add; +static unsigned int g_vwidth = 0x18; +static unsigned int g_hwidth = 0x10; +static unsigned int g_vpotch = 0x8; +static unsigned int g_hpotch = 0x10; +/*dma size:1877x2x64 bit = 30032 byte*/ +#define TV_DMA_TBL_SIZE 3754 +static unsigned int dma_size = 30032; +static dma_addr_t dma_paddr; +static void *dma_vaddr; +static unsigned int dma_start_line = 0x400; + +#define CRC_BUFF_SIZE (256 * 1024) +static char *crc_output_buf; +static u32 crc_outpuf_buff_off; +static u32 crc_count; +static u32 crc_bypass_count; +static u32 setting_update_count; +static s32 crc_read_delay; +static u32 core1_disp_hsize; +static u32 core1_disp_vsize; +static u32 vsync_count; +#define FLAG_VSYNC_CNT 10 + +module_param(vtotal_add, uint, 0664); +MODULE_PARM_DESC(vtotal_add, "\n vtotal_add\n"); +module_param(vpotch, uint, 0664); +MODULE_PARM_DESC(vpotch, "\n vpotch\n"); + +static unsigned int dolby_vision_target_min = 50; /* 0.0001 */ +#ifdef V2_4 +static unsigned int dolby_vision_target_max[3][3] = { + { 4000, 1000, 100 }, /* DOVI => DOVI/HDR/SDR */ + { 1000, 1000, 100 }, /* HDR => DOVI/HDR/SDR */ + { 600, 1000, 100 }, /* SDR => DOVI/HDR/SDR */ +}; +#else +static unsigned int dolby_vision_target_max[3][3] = { + { 4000, 4000, 100 }, /* DOVI => DOVI/HDR/SDR */ + { 1000, 1000, 100 }, /* HDR => DOVI/HDR/SDR */ + { 600, 1000, 100 }, /* SDR => DOVI/HDR/SDR */ +}; +#endif + +static unsigned int dolby_vision_default_max[3][3] = { + { 4000, 4000, 100 }, /* DOVI => DOVI/HDR/SDR */ + { 1000, 1000, 100 }, /* HDR => DOVI/HDR/SDR */ + { 600, 1000, 100 }, /* SDR => DOVI/HDR/SDR */ +}; + +static unsigned int dolby_vision_graphic_min = 50; /* 0.0001 */ +static unsigned int dolby_vision_graphic_max = 100; /* 1 */ +module_param(dolby_vision_graphic_min, uint, 0664); +MODULE_PARM_DESC(dolby_vision_graphic_min, "\n dolby_vision_graphic_min\n"); +module_param(dolby_vision_graphic_max, uint, 0664); +MODULE_PARM_DESC(dolby_vision_graphic_max, "\n dolby_vision_graphic_max\n"); + +static unsigned int dv_cert_graphic_width = 1920; +static unsigned int dv_cert_graphic_height = 1080; +module_param(dv_cert_graphic_width, uint, 0664); +MODULE_PARM_DESC(dv_cert_graphic_width, "\n dv_cert_graphic_width\n"); +module_param(dv_cert_graphic_height, uint, 0664); +MODULE_PARM_DESC(dv_cert_graphic_height, "\n dv_cert_graphic_height\n"); + +/* 0: video priority 1: graphic priority */ +static unsigned int dolby_vision_graphics_priority; +module_param(dolby_vision_graphics_priority, uint, 0664); +MODULE_PARM_DESC(dolby_vision_graphics_priority, "\n dolby_vision_graphics_priority\n"); + +uint16_t L2PQ_100_500[] = { + 2081, /* 100 */ + 2157, /* 120 */ + 2221, /* 140 */ + 2277, /* 160 */ + 2327, /* 180 */ + 2372, /* 200 */ + 2413, /* 220 */ + 2450, /* 240 */ + 2485, /* 260 */ + 2517, /* 280 */ + 2547, /* 300 */ + 2575, /* 320 */ + 2602, /* 340 */ + 2627, /* 360 */ + 2651, /* 380 */ + 2673, /* 400 */ + 2694, /* 420 */ + 2715, /* 440 */ + 2734, /* 460 */ + 2753, /* 480 */ + 2771, /* 500 */ +}; + +uint16_t L2PQ_500_4000[] = { + 2771, /* 500 */ + 2852, /* 600 */ + 2920, /* 700 */ + 2980, /* 800 */ + 3032, /* 900 */ + 3079, /* 1000 */ + 3122, /* 1100 */ + 3161, /* 1200 */ + 3197, /* 1300 */ + 3230, /* 1400 */ + 3261, /* 1500 */ + 3289, /* 1600 */ + 3317, /* 1700 */ + 3342, /* 1800 */ + 3366, /* 1900 */ + 3389, /* 2000 */ + 3411, /* 2100 */ + 3432, /* 2200 */ + 3451, /* 2300 */ + 3470, /* 2400 */ + 3489, /* 2500 */ + 3506, /* 2600 */ + 3523, /* 2700 */ + 3539, /* 2800 */ + 3554, /* 2900 */ + 3570, /* 3000 */ + 3584, /* 3100 */ + 3598, /* 3200 */ + 3612, /* 3300 */ + 3625, /* 3400 */ + 3638, /* 3500 */ + 3651, /* 3600 */ + 3662, /* 3700 */ + 3674, /* 3800 */ + 3686, /* 3900 */ + 3697, /* 4000 */ +}; + +static uint32_t tv_max_lin = 200; +static uint16_t tv_max_pq = 2372; + +static unsigned int panel_max_lumin; +module_param(panel_max_lumin, uint, 0664); +MODULE_PARM_DESC(panel_max_lumin, "\n panel_max_lumin\n"); + +#ifdef V1_5 +struct TargetDisplayConfig def_tgt_display_cfg = { + 4095, /* gain */ + 0, /* offset */ + 39322, /* gamma */ + 0, /* eotf */ + 12, /* bitDepth */ + 0, /* rangeSpec */ + 42, /* diagSize */ + 2771, /* maxPq */ + 62, /* minPq */ + 2048, /* mSWeight */ + 16380, /* mSEdgeWeight */ + 0, /* minPQBias */ + 0, /* midPQBias */ + 0, /* maxPQBias */ + 0, /* trimSlopeBias */ + 0, /* trimOffsetBias */ + 0, /* trimPowerBias */ + 0, /* msWeightBias */ + 0, /* brightness */ + 0, /* contrast */ + 0, /* chromaWeightBias */ + 0, /* saturationGainBias */ + 2048, /* chromaWeight */ + 2048, /* saturationGain */ + 655, /* crossTalk */ + 0, /* tuningMode */ + 0, /* reserved0 */ + 0, /* dbgExecParamsPrintPeriod */ + 0, /* dbgDmMdPrintPeriod */ + 0, /* dbgDmCfgPrintPeriod */ + 2771, /* maxPq_dupli */ + 62, /* minPq_dupli */ + 12288, /* keyWeight */ + 24576, /* intensityVectorWeight */ + 24576, /* chromaVectorWeight */ + 0, /* chip_fpga_lowcomplex */ + { + -245, + -208, + -171, + -130, + -93, + -56, + -19, + 20, + 57, + 94, + 131, + 172, + 209, + 246, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + -3685, + -3070, + -2456, + -1842, + -1228, + -613, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 1, /* gdEnable */ + 6553, /* gdWMin */ + 131072000, /* gdWMax */ + 26214400, /* gdWMm */ + 16579442, /* gdWDynRngSqrt */ + 4096, /* gdWeightMean */ + 4096, /* gdWeightStd */ + 0, /* gdDelayMilliSec_hdmi */ + 1, /* gdRgb2YuvExt */ + { + {5960, 20047, 2023}, + {-3286, -11052, 14336}, + {14336, -13022, -1316} + }, /* gdM33Rgb2Yuv[3][3] */ + 15, /* gdM33Rgb2YuvScale2P */ + 1, /* gdRgb2YuvOffExt */ + {2048, 16384, 16384},/* gdV3Rgb2YuvOff[3] */ + 2072430, /* gdUpBound */ + 414486, /* gdLowBound */ + 0, /* lastMaxPq */ + 137, /*gdWMinPq */ + 2771, /*gdWMaxPq */ + 2081, /*gdWMmPq */ + 0, /*gdTriggerPeriod */ + 0, /* gdTriggerLinThresh */ + 0, /* gdDelayMilliSec_ott */ +#ifdef V1_5 + {0, 0, 0, 0, 0, 0}, +#else + {0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + }, +#ifdef V1_5 + {0, 0, 0, 68, 124, 49, 230}, + {0, 0, 0, 0, 0}, +#endif + 1311, /* min_lin */ + 131072000, /* max_lin */ + 0, /* backlight_scaler */ + 1311, /* min_lin_dupli */ + 131072000, /* max_lin_dupli */ + { + /* lms2RgbMat[3][3] */ + { + {22416, -19015, 695}, + {-4609, 9392, -688}, + {122, -791, 4765} + }, + 12, /* lms2RgbMatScale */ + {128, 128, 128}, /* whitePoint */ + 7, /* whitePointScale */ + {0, 0, 0} /* reserved[3] */ + }, + 0, /* reserved00 */ + 0, /* brightnessPreservation */ + 81920, /* iintensityVectorWeight */ + 24576, /* ichromaVectorWeight */ + 0, /* isaturationGainBias */ + 0, /* chip_12b_ocsc */ + 0, /* chip_512_tonecurve */ + 0, /* chip_nolvl5 */ + {0, 0, 0, 0, 0, 0, 0, 0} /* padding[8] */ +}; +#else +struct TargetDisplayConfig def_tgt_display_cfg = { + 2048, /* gain */ + 4095, /* offset */ + 39322, /* gamma */ + 0, /* eotf */ + 12, /* bitDepth */ + 0, /* rangeSpec */ + 42, /* diagSize */ + 2372, /* maxPq */ + 62, /* minPq */ + 2048, /* mSWeight */ + 16380, /* mSEdgeWeight */ + 0, /* minPQBias */ + 0, /* midPQBias */ + 0, /* maxPQBias */ + 0, /* trimSlopeBias */ + 0, /* trimOffsetBias */ + 0, /* trimPowerBias */ + 0, /* msWeightBias */ + 0, /* brightness */ + 0, /* contrast */ + 0, /* chromaWeightBias */ + 0, /* saturationGainBias */ + 2048, /* chromaWeight */ + 2048, /* saturationGain */ + 655, /* crossTalk */ + 0, /* tuningMode */ + 0, /* reserved0 */ + 0, /* dbgExecParamsPrintPeriod */ + 0, /* dbgDmMdPrintPeriod */ + 0, /* dbgDmCfgPrintPeriod */ + 2372, /* maxPq_dupli */ + 62, /* minPq_dupli */ + 12288, /* keyWeight */ + 24576, /* intensityVectorWeight */ + 24576, /* chromaVectorWeight */ + 0, /* chip_fpga_lowcomplex */ + { + -245, + -207, + -169, + -131, + -94, + -56, + -18, + 19, + 57, + 95, + 132, + 170, + 208, + 246, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, /* gdEnable */ + 262, /* gdWMin */ + 131072000, /* gdWMax */ + 26214400, /* gdWMm */ + 82897211, /* gdWDynRngSqrt */ + 4096, /* gdWeightMean */ + 4096, /* gdWeightStd */ + 0, /* gdDelayMilliSec_hdmi */ + 1, /* gdRgb2YuvExt */ + { + {5960, 20047, 2023}, + {-3286, -11052, 14336}, + {14336, -13022, -1316} + }, /* gdM33Rgb2Yuv[3][3] */ + 15, /* gdM33Rgb2YuvScale2P */ + 1, /* gdRgb2YuvOffExt */ + {2048, 16384, 16384},/* gdV3Rgb2YuvOff[3] */ + 414486, /* gdUpBound */ + 82897, /* gdLowBound */ + 0, /* lastMaxPq */ + 26, /*gdWMinPq */ + 2771, /*gdWMaxPq */ + 2081, /*gdWMmPq */ + 0, /*gdTriggerPeriod */ + 0, /* gdTriggerLinThresh */ + 0, /* gdDelayMilliSec_ott */ +#ifdef V1_5 + {0, 0, 0, 0, 0, 0}, +#else + {0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + }, +#ifdef V1_5 + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, +#endif + 1311, /* min_lin */ + 200 << 18, /* max_lin 131072000 */ + 4096, /* backlight_scaler */ + 1311, /* min_lin_dupli */ + 200 << 18, /* max_lin_dupli 131072000 */ + { + /* lms2RgbMat[3][3] */ + { + {17507, -14019, 608}, + {-3765, 8450, -589}, + {285, -640, 4451} + }, + 12, /* lms2RgbMatScale */ + {128, 128, 128}, /* whitePoint */ + 7, /* whitePointScale */ + {0, 0, 0} /* reserved[3] */ + }, + 0, /* reserved00 */ + 0, /* brightnessPreservation */ + 81920, /* iintensityVectorWeight */ + 24576, /* ichromaVectorWeight */ + 0, /* isaturationGainBias */ + 0, /* chip_12b_ocsc */ + 0, /* chip_512_tonecurve */ + 0, /* chip_nolvl5 */ + {0, 0, 0, 0, 0, 0, 0, 0} /* padding[8] */ +}; +#endif + +static unsigned int debug_dolby; +module_param(debug_dolby, uint, 0664); +MODULE_PARM_DESC(debug_dolby, "\n debug_dolby\n"); + +static unsigned int debug_dolby_frame = 0xffff; +module_param(debug_dolby_frame, uint, 0664); +MODULE_PARM_DESC(debug_dolby_frame, "\n debug_dolby_frame\n"); + +#define pr_dolby_dbg(fmt, args...)\ + do {\ + if (debug_dolby)\ + pr_info("DOLBY: " fmt, ## args);\ + } while (0) +#define pr_dolby_error(fmt, args...)\ + pr_info("DOLBY ERROR: " fmt, ## args) +#define dump_enable \ + ((debug_dolby_frame >= 0xffff) || (debug_dolby_frame == frame_count)) +#define is_graphics_output_off() 0 + /*(!(READ_VPP_REG(VPP_MISC) & (1<<12)))*/ +#define single_step_enable \ + (((debug_dolby_frame >= 0xffff) || \ + ((debug_dolby_frame + 1) == frame_count)) && \ + (debug_dolby & 0x80)) + +static bool dolby_vision_on; +static bool dolby_vision_core1_on; +static bool dolby_vision_wait_on; +static bool dolby_vision_wait_init; +static unsigned int frame_count; +static struct hdr10_param_s hdr10_param; +static struct master_display_info_s hdr10_data; + +static char md_buf[1024]; +static char comp_buf[8196]; + +static struct dovi_setting_s dovi_setting; +static struct dovi_setting_s new_dovi_setting; + +void *pq_config_fake; +void *tv_dovi_setting; +static bool pq_config_set_flag; +struct ui_menu_params_s menu_param = {50, 50, 50}; +static bool tv_dovi_setting_change_flag; +static bool tv_dovi_setting_update_flag; +static bool dovi_setting_video_flag; +static struct platform_device *dovi_pdev; +static bool vsvdb_config_set_flag; + +/* general control config change */ +#define FLAG_CHANGE_CFG 0x000001 +/* general metadata change */ +#define FLAG_CHANGE_MDS 0x000002 +/* metadata config (below level 2) change */ +#define FLAG_CHANGE_MDS_CFG 0x000004 +/* global dimming change */ +#define FLAG_CHANGE_GD 0x000008 +/* tone curve lut change */ +#define FLAG_CHANGE_TC 0x000010 +/* 2nd tone curve (graphics) lut change */ +#define FLAG_CHANGE_TC2 0x000020 +/* L2NL lut change (for DM3.1) */ +#define FLAG_CHANGE_L2NL 0x000040 +/* 3D lut change (for DM2.12) */ +#define FLAG_CHANGE_3DLUT 0x000080 +/* 0xX00000 for other status */ +/* (video) tone mapping to a constant */ +#define FLAG_CONST_TC 0x100000 +/* 2nd tone mapping to a constant */ +#define FLAG_CONST_TC2 0x200000 +#define FLAG_CHANGE_ALL 0xffffffff +/* update all core */ +static u32 stb_core_setting_update_flag = FLAG_CHANGE_ALL; + +/* 256+(256*4+256*2)*4/8 64bit */ +#define STB_DMA_TBL_SIZE (256+(256*4+256*2)*4/8) +static uint64_t stb_core1_lut[STB_DMA_TBL_SIZE]; + +static void dump_tv_setting( + struct tv_dovi_setting_s *setting, + int frame_cnt, int debug_flag) +{ + int i; + uint64_t *p; + + if ((debug_flag & 0x10) && dump_enable) { + pr_info("\nreg\n"); + p = (uint64_t *)&setting->core1_reg_lut[0]; + for (i = 0; i < 222; i += 2) + pr_info("%016llx, %016llx,\n", p[i], p[i+1]); + } + if ((debug_flag & 0x20) && dump_enable) { + pr_info("\ng2l_lut\n"); + p = (uint64_t *)&setting->core1_reg_lut[0]; + for (i = 222; i < 222 + 256; i += 2) + pr_info("%016llx %016llx\n", p[i], p[i+1]); + } + if ((debug_flag & 0x40) && dump_enable) { + pr_info("\n3d_lut\n"); + p = (uint64_t *)&setting->core1_reg_lut[0]; + for (i = 222 + 256; i < 222 + 256 + 3276; i += 2) + pr_info("%016llx %016llx\n", p[i], p[i+1]); + pr_info("\n"); + } +} + +void dolby_vision_update_pq_config(char *pq_config_buf) +{ + memcpy((struct pq_config_s *)pq_config_fake, + pq_config_buf, sizeof(struct pq_config_s)); + pr_info("update_pq_config[%ld] %x %x %x %x\n", + sizeof(struct pq_config_s), + pq_config_buf[1], + pq_config_buf[2], + pq_config_buf[3], + pq_config_buf[4]); + pq_config_set_flag = true; +} + +void dolby_vision_update_vsvdb_config(char *vsvdb_buf, u32 tbl_size) +{ +#ifdef V2_4 + if (tbl_size > sizeof(new_dovi_setting.vsvdb_tbl)) { + pr_info( + "update_vsvdb_config tbl size overflow %d\n", tbl_size); + return; + } + memset(&new_dovi_setting.vsvdb_tbl[0], + 0, sizeof(new_dovi_setting.vsvdb_tbl)); + memcpy(&new_dovi_setting.vsvdb_tbl[0], + vsvdb_buf, tbl_size); + new_dovi_setting.vsvdb_len = tbl_size; + new_dovi_setting.vsvdb_changed = 1; + dolby_vision_set_toggle_flag(1); + if (tbl_size >= 8) + pr_info( + "update_vsvdb_config[%d] %x %x %x %x %x %x %x %x\n", + tbl_size, + vsvdb_buf[0], + vsvdb_buf[1], + vsvdb_buf[2], + vsvdb_buf[3], + vsvdb_buf[4], + vsvdb_buf[5], + vsvdb_buf[6], + vsvdb_buf[7]); +#endif + vsvdb_config_set_flag = true; +} + +static int prepare_stb_dolby_core1_reg( + uint32_t run_mode, + uint32_t *p_core1_dm_regs, + uint32_t *p_core1_comp_regs) +{ + int index = 0; + int i; + + /* 4 */ + stb_core1_lut[index++] = ((uint64_t)4 << 32) | 4; + stb_core1_lut[index++] = ((uint64_t)4 << 32) | 4; + stb_core1_lut[index++] = ((uint64_t)3 << 32) | 1; + stb_core1_lut[index++] = ((uint64_t)2 << 32) | 1; + + /* 1 + 14 + 10 + 1 */ + stb_core1_lut[index++] = ((uint64_t)1 << 32) | run_mode; + for (i = 0; i < 14; i++) + stb_core1_lut[index++] = + ((uint64_t)(6 + i) << 32) + | p_core1_dm_regs[i]; + for (i = 17; i < 27; i++) + stb_core1_lut[index++] = + ((uint64_t)(6 + i) << 32) + | p_core1_dm_regs[i-3]; + stb_core1_lut[index++] = ((uint64_t)(6 + 27) << 32) | 0; + + /* 173 + 1 */ + for (i = 0; i < 173; i++) + stb_core1_lut[index++] = + ((uint64_t)(6 + 44 + i) << 32) + | p_core1_comp_regs[i]; + stb_core1_lut[index++] = ((uint64_t)3 << 32) | 1; + + if (index & 1) { + pr_dolby_error("stb core1 reg tbl odd size\n"); + stb_core1_lut[index++] = ((uint64_t)3 << 32) | 1; + } + return index; +} + +static void prepare_stb_dolby_core1_lut(uint32_t base, uint32_t *p_core1_lut) +{ + uint32_t *p_lut; + int i; + + p_lut = &p_core1_lut[256*4]; /* g2l */ + for (i = 0; i < 128; i++) { + stb_core1_lut[base+i] = + stb_core1_lut[base+i+128] = + ((uint64_t)p_lut[1] << 32) | + ((uint64_t)p_lut[0] & 0xffffffff); + p_lut += 2; + } + p_lut = &p_core1_lut[0]; /* 4 lut */ + for (i = 256; i < 768; i++) { + stb_core1_lut[base+i] = + ((uint64_t)p_lut[1] << 32) | + ((uint64_t)p_lut[0] & 0xffffffff); + p_lut += 2; + } +} + +static int stb_dolby_core1_set( + uint32_t dm_count, + uint32_t comp_count, + uint32_t lut_count, + uint32_t *p_core1_dm_regs, + uint32_t *p_core1_comp_regs, + uint32_t *p_core1_lut, + int hsize, + int vsize, + int bl_enable, + int el_enable, + int el_41_mode, + int scramble_en, + bool dovi_src, + int lut_endian, + bool reset) +{ + uint32_t bypass_flag = 0; + int composer_enable = el_enable; + uint32_t run_mode = 0; + int reg_size = 0; + bool bypass_core1 = (!hsize || !vsize + || !(dolby_vision_mask & 1)); + + if (dolby_vision_on + && (dolby_vision_flags & + FLAG_DISABE_CORE_SETTING)) + return 0; + + WRITE_VPP_REG( + DOLBY_TV_CLKGATE_CTRL, 0x2800); + if (reset) { + VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); + VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + VSYNC_WR_MPEG_REG( + DOLBY_TV_CLKGATE_CTRL, 0x2800); + } + + if (!bl_enable) + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x446); + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, 0); + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, + ((hsize + 0x80) << 16) | (vsize + 0x40)); + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, + (hwidth << 16) | vwidth); + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, + (hpotch << 16) | vpotch); + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, + (hsize << 16) | vsize); + if (dolby_vision_flags & FLAG_CERTIFICAION) + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL6, 0xba000000); + else + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL6, 0xb8000000); + if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) + composer_enable = 0; + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, + /* el dly 3, bl dly 1 after de*/ + (el_41_mode ? (0x3 << 4) : (0x1 << 8)) | + bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); + + if (el_enable && (dolby_vision_mask & 1)) + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* vd2 to core1 */ + 0, 17, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* vd2 to vpp */ + 1, 17, 1); + if (dolby_vision_core1_on + && !bypass_core1) + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* enable core 1 */ + 0, 16, 1); + else if (dolby_vision_core1_on + && bypass_core1) + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* bypass core 1 */ + 1, 16, 1); + /* run mode = bypass, when fake frame */ + if (!bl_enable) + bypass_flag |= 1; + if (dolby_vision_flags & FLAG_BYPASS_CSC) + bypass_flag |= 1 << 12; /* bypass CSC */ + if (dolby_vision_flags & FLAG_BYPASS_CVM) + bypass_flag |= 1 << 13; /* bypass CVM */ + /* bypass composer to get 12bit when SDR and HDR source */ +#ifndef V2_4 + if (!dovi_src) + bypass_flag |= 1 << 14; /* bypass composer */ +#endif + if ((scramble_en) && !(dolby_vision_flags & FLAG_CERTIFICAION)) + bypass_flag |= 1 << 13; /* bypass CVM when tunnel out */ + + if (dolby_vision_run_mode != 0xff) + run_mode = dolby_vision_run_mode; + else { + run_mode = (0x7 << 6) | (el_41_mode << 3) | bypass_flag; + if (dolby_vision_on_count < dolby_vision_run_mode_delay) { + run_mode |= 1; + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + (0x200 << 10) | 0x200); + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + (0x200 << 10) | 0x200); + } else if (dolby_vision_on_count == + dolby_vision_run_mode_delay) { + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + (0x200 << 10) | 0x200); + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + (0x200 << 10) | 0x200); + } else { + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + (0x3ff << 20) | (0x3ff << 10) | 0x3ff); + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + 0); + } + } + if (reset) + VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); + + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x6); + + /* axi dma for reg table */ + reg_size = prepare_stb_dolby_core1_reg( + run_mode, p_core1_dm_regs, p_core1_comp_regs); + /* axi dma for lut table */ + prepare_stb_dolby_core1_lut(reg_size, p_core1_lut); + + if (!dolby_vision_on) { + /* dma1:11-0 tv_oo+g2l size, dma2:23-12 3d lut size */ + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL1, + 0x00000080 | (reg_size << 23)); + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + /* dma3:23-12 cvm size */ + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL3, + 0x80100000 | dma_start_line); + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + } + if (reset) { + /* dma1:11-0 tv_oo+g2l size, dma2:23-12 3d lut size */ + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, + 0x00000080 | (reg_size << 23)); + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + /* dma3:23-12 cvm size */ + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, + 0x80100000 | dma_start_line); + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + } + + tv_dovi_setting_update_flag = true; + return 0; +} + +static uint32_t tv_run_mode(int vsize, bool hdmi, bool hdr10, int el_41_mode) +{ + uint32_t run_mode = 1; + + if (hdmi) { + if (vsize > 1080) + run_mode = + 0x00000043; + else + run_mode = + 0x00000042; + } else { + if (hdr10) { + run_mode = + 0x0000004c; +#ifndef V1_5 + run_mode |= 1 << 14; /* bypass COMPOSER */ +#endif + } else { + if (el_41_mode) + run_mode = + 0x0000004c; + else + run_mode = + 0x00000044; + } + } + if (dolby_vision_flags & FLAG_BYPASS_CSC) + run_mode |= 1 << 12; /* bypass CSC */ + if (dolby_vision_flags & FLAG_BYPASS_CVM) + run_mode |= 1 << 13; /* bypass CVM */ + return run_mode; +} + +static int tv_dolby_core1_set( + uint64_t *dma_data, + int hsize, + int vsize, + int bl_enable, + int el_enable, + int el_41_mode, + int src_chroma_format, + bool hdmi, + bool hdr10, + bool reset) +{ + uint64_t run_mode; + int composer_enable = el_enable; + bool bypass_core1 = (!hsize || !vsize + || !(dolby_vision_mask & 1)); + if (dolby_vision_on + && (dolby_vision_flags & + FLAG_DISABE_CORE_SETTING)) + return 0; + + WRITE_VPP_REG( + DOLBY_TV_CLKGATE_CTRL, 0x2800); + + if (reset) { + VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); + VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + VSYNC_WR_MPEG_REG( + DOLBY_TV_CLKGATE_CTRL, 0x2800); + } + + if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) + composer_enable = 0; + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, + /* el dly 3, bl dly 1 after de*/ + (el_41_mode ? (0x3 << 4) : (0x1 << 8)) | + bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, + ((hsize + 0x80) << 16 | (vsize + 0x40))); + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); + VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); + /*0x2c2d0:5-4-1-3-2-0*/ + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0x2c2d0, 14, 18); + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0xa, 0, 4); + + if ((hdmi) && (!hdr10)) + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 1, 4, 1); + else + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0, 4, 1); + + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 20, 1); + /* bypass dither */ + if (dolby_vision_flags & FLAG_CERTIFICAION) + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 25, 1); + else + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 0, 25, 1); + if (src_chroma_format == 2) + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 29, 1); + else if (src_chroma_format == 1) + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 0, 29, 1); + /* input 12 or 10 bit */ + VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL7, 12, 0, 8); + + if (el_enable && (dolby_vision_mask & 1)) + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* vd2 to core1 */ + 0, 17, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* vd2 to vpp */ + 1, 17, 1); + + if (dolby_vision_core1_on + && !bypass_core1) + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* enable core 1 */ + 0, 16, 1); + else if (dolby_vision_core1_on + && bypass_core1) + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* bypass core 1 */ + 1, 16, 1); + + if (dolby_vision_run_mode != 0xff) + run_mode = dolby_vision_run_mode; + else { + run_mode = tv_run_mode(vsize, hdmi, hdr10, el_41_mode); + if (dolby_vision_on_count < dolby_vision_run_mode_delay) { + run_mode = (run_mode & 0xfffffffc) | 1; + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + (0x200 << 10) | 0x200); + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + (0x200 << 10) | 0x200); + } else if (dolby_vision_on_count == + dolby_vision_run_mode_delay) { + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + (0x200 << 10) | 0x200); + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + (0x200 << 10) | 0x200); + } else { + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + (0x3ff << 20) | (0x3ff << 10) | 0x3ff); + VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + 0); + } + } + ((struct tv_dovi_setting_s *)tv_dovi_setting)->core1_reg_lut[1] = + 0x0000000100000000 | run_mode; + if (reset) + VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); + + if (!dolby_vision_on) { + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL3, + 0x80000000 | dma_start_line); + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); + WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + } + if (reset) { + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, + 0x80000000 | dma_start_line); + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + } + + tv_dovi_setting_update_flag = true; + return 0; +} + +int dolby_vision_update_setting(void) +{ + uint64_t *dma_data; + uint32_t size = 0; + int i; + uint64_t *p; + + if (!p_funcs) + return -1; + if (!tv_dovi_setting_update_flag) + return 0; + if (dolby_vision_flags & + FLAG_DISABLE_DMA_UPDATE) { + tv_dovi_setting_update_flag = false; + setting_update_count++; + return -1; + } + if (efuse_mode == 1) { + tv_dovi_setting_update_flag = false; + setting_update_count++; + return -1; + } + if (is_meson_txlx_package_962X() && !force_stb_mode) { + dma_data = ((struct tv_dovi_setting_s *) + tv_dovi_setting)->core1_reg_lut; + size = 8 * TV_DMA_TBL_SIZE; + memcpy(dma_vaddr, dma_data, size); + } else if (is_meson_txlx_package_962E() || force_stb_mode) { + dma_data = stb_core1_lut; + size = 8 * STB_DMA_TBL_SIZE; + memcpy(dma_vaddr, dma_data, size); + } + if (size && (debug_dolby & 0x8)) { + p = (uint64_t *)dma_vaddr; + pr_info("dma size = %d\n", STB_DMA_TBL_SIZE); + for (i = 0; i < size / 8; i += 2) + pr_info("%016llx, %016llx\n", p[i], p[i+1]); + } + tv_dovi_setting_update_flag = false; + setting_update_count = frame_count; + return -1; +} +EXPORT_SYMBOL(dolby_vision_update_setting); + +static int dolby_core1_set( + uint32_t dm_count, + uint32_t comp_count, + uint32_t lut_count, + uint32_t *p_core1_dm_regs, + uint32_t *p_core1_comp_regs, + uint32_t *p_core1_lut, + int hsize, + int vsize, + int bl_enable, + int el_enable, + int el_41_mode, + int scramble_en, + bool dovi_src, + int lut_endian, + bool reset) +{ + uint32_t count; + uint32_t bypass_flag = 0; + int composer_enable = + bl_enable && el_enable && (dolby_vision_mask & 1); + int i; + bool set_lut = false; + uint32_t *last_dm = (uint32_t *)&dovi_setting.dm_reg1; + uint32_t *last_comp = (uint32_t *)&dovi_setting.comp_reg; + bool bypass_core1 = (!hsize || !vsize + || !(dolby_vision_mask & 1)); + if (dolby_vision_on + && (dolby_vision_flags & + FLAG_DISABE_CORE_SETTING)) + return 0; + + if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) + composer_enable = 0; + + if ((!dolby_vision_on || reset) && bl_enable) { + VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); + VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + reset = true; + } + + if ((dolby_vision_flags & FLAG_CERTIFICAION) + || (frame_count < 10)) + reset = true; + + if (stb_core_setting_update_flag & FLAG_CHANGE_TC) + set_lut = true; + + if (bl_enable && el_enable && (dolby_vision_mask & 1)) { + if (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + /* vd2 to core1 */ + 0, 1, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* vd2 to core1 */ + 0, 17, 1); + } else { + if (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + /* vd2 to core1 */ + 1, 1, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* vd2 to vpp */ + 1, 17, 1); + } + + VSYNC_WR_MPEG_REG(DOLBY_CORE1_CLKGATE_CTRL, 0); + /* VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, 0); */ + VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL1, + ((hsize + 0x80) << 16) | (vsize + 0x40)); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL3, (hwidth << 16) | vwidth); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL4, (hpotch << 16) | vpotch); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL2, (hsize << 16) | vsize); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL5, 0xa); + + VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x0); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 4, 4); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 2, 1); + + /* bypass composer to get 12bit when SDR and HDR source */ +#ifndef V2_4 + if (!dovi_src) + bypass_flag |= 1 << 0; +#endif + if (dolby_vision_flags & FLAG_BYPASS_CSC) + bypass_flag |= 1 << 1; + if (dolby_vision_flags & FLAG_BYPASS_CVM) + bypass_flag |= 1 << 2; + if (scramble_en) { + /* bypass CVM when dolby output */ + if (!(dolby_vision_flags & FLAG_CERTIFICAION)) + bypass_flag |= 1 << 2; + } + if (el_41_mode) + bypass_flag |= 1 << 3; + + VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, + 0x70 | bypass_flag); /* bypass CVM and/or CSC */ + VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, + 0x70 | bypass_flag); /* for delay */ + if (dm_count == 0) + count = 24; + else + count = dm_count; + for (i = 0; i < count; i++) + if (reset || + (p_core1_dm_regs[i] != + last_dm[i])) + VSYNC_WR_MPEG_REG( + DOLBY_CORE1_REG_START + 6 + i, + p_core1_dm_regs[i]); + + if (comp_count == 0) + count = 173; + else + count = comp_count; + for (i = 0; i < count; i++) + if (reset || + (p_core1_comp_regs[i] != + last_comp[i])) + VSYNC_WR_MPEG_REG( + DOLBY_CORE1_REG_START + 6 + 44 + i, + p_core1_comp_regs[i]); + + /* metadata program done */ + VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 3, 1); + + if (lut_count == 0) + count = 256 * 5; + else + count = lut_count; + if (count && (set_lut || reset)) { + if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) + VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, + 2, 2, 2); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x1401); + if (lut_endian) + for (i = 0; i < count; i += 4) { + VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + p_core1_lut[i+3]); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + p_core1_lut[i+2]); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + p_core1_lut[i+1]); + VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + p_core1_lut[i]); + } + else + for (i = 0; i < count; i++) + VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + p_core1_lut[i]); + if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) + VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, + 0, 2, 2); + } + + if (dolby_vision_on_count + < dolby_vision_run_mode_delay) { + VSYNC_WR_MPEG_REG( + VPP_VD1_CLIP_MISC0, + (0x200 << 10) | 0x200); + VSYNC_WR_MPEG_REG( + VPP_VD1_CLIP_MISC1, + (0x200 << 10) | 0x200); + if (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + 1, + 0, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 1, 16, 1); + } else { + VSYNC_WR_MPEG_REG( + VPP_VD1_CLIP_MISC0, + (0x3ff << 20) | + (0x3ff << 10) | + 0x3ff); + VSYNC_WR_MPEG_REG( + VPP_VD1_CLIP_MISC1, + 0); + if (dolby_vision_core1_on + && !bypass_core1) { + if (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + 0, + 0, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* enable core 1 */ + 0, 16, 1); + } else if (dolby_vision_core1_on + && bypass_core1) { + if (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + 1, + 0, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* bypass core 1 */ + 1, 16, 1); + } + } + /* enable core1 */ + VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, + bl_enable << 0 | + composer_enable << 1 | + el_41_mode << 2); + tv_dovi_setting_update_flag = true; + return 0; +} + +static int dolby_core2_set( + uint32_t dm_count, + uint32_t lut_count, + uint32_t *p_core2_dm_regs, + uint32_t *p_core2_lut, + int hsize, + int vsize, + int dolby_enable, + int lut_endian) +{ + uint32_t count; + int i; + bool set_lut = false; + bool reset = false; + uint32_t *last_dm = (uint32_t *)&dovi_setting.dm_reg2; + + if (dolby_vision_on + && (dolby_vision_flags & + FLAG_DISABE_CORE_SETTING)) + return 0; + if (!dolby_vision_on) { + VSYNC_WR_MPEG_REG(VIU_SW_RESET, (1 << 10)); + VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + reset = true; + } + + if ((dolby_vision_flags & FLAG_CERTIFICAION) + || (frame_count < 10)) + reset = true; + + if (stb_core_setting_update_flag & FLAG_CHANGE_TC2) + set_lut = true; + + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CLKGATE_CTRL, 0); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, 0); + if (is_meson_gxm_cpu() || + (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) || + (dolby_vision_flags & FLAG_CERTIFICAION)) { + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL1, + ((hsize + g_htotal_add) << 16) + | (vsize + g_vtotal_add + g_vsize_add)); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL2, + (hsize << 16) | (vsize + g_vsize_add)); + } + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL3, + (g_hwidth << 16) | g_vwidth); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL4, + (g_hpotch << 16) | g_vpotch); + if (is_meson_txlx_package_962E() || force_stb_mode) + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xf8000000); + else + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xa8000000); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x0); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, 2); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, 2); + + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); + + if (dm_count == 0) + count = 24; + else + count = dm_count; + for (i = 0; i < count; i++) + if (reset || + (p_core2_dm_regs[i] != + last_dm[i])) + VSYNC_WR_MPEG_REG( + DOLBY_CORE2A_REG_START + 6 + i, + p_core2_dm_regs[i]); + /* core2 metadata program done */ + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 3, 1); + + if (lut_count == 0) + count = 256 * 5; + else + count = lut_count; + if (count && (set_lut || reset)) { + if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) + VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE2A_CLKGATE_CTRL, + 2, 2, 2); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x1401); + if (lut_endian) + for (i = 0; i < count; i += 4) { + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + p_core2_lut[i+3]); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + p_core2_lut[i+2]); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + p_core2_lut[i+1]); + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + p_core2_lut[i]); + } + else + for (i = 0; i < count; i++) + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + p_core2_lut[i]); + /* core2 lookup table program done */ + if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) + VSYNC_WR_MPEG_REG_BITS( + DOLBY_CORE2A_CLKGATE_CTRL, 0, 2, 2); + } + + /* enable core2 */ + VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, dolby_enable << 0); + return 0; +} + +static int dolby_core3_set( + uint32_t dm_count, + uint32_t md_count, + uint32_t *p_core3_dm_regs, + uint32_t *p_core3_md_regs, + int hsize, + int vsize, + int dolby_enable, + int scramble_en) +{ + uint32_t count; + int i; + int vsize_hold = 0x10; + uint32_t diag_mode = 0; + uint32_t cur_dv_mode = dolby_vision_mode; + uint32_t *last_dm = (uint32_t *)&dovi_setting.dm_reg3; + bool reset = false; +#ifdef V2_4 + u32 diag_enable = 0; + bool reset_post_table = false; + + if (new_dovi_setting.diagnostic_enable + || new_dovi_setting.dovi_ll_enable) + diag_enable = 1; +#endif + if (dolby_vision_on + && (dolby_vision_flags & + FLAG_DISABE_CORE_SETTING)) + return 0; + + if (!dolby_vision_on) + reset = true; + + if ((dolby_vision_flags & FLAG_CERTIFICAION) + || (frame_count < 10)) + reset = true; +#ifdef V2_4 + if (((cur_dv_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) + || (cur_dv_mode == DOLBY_VISION_OUTPUT_MODE_IPT)) + && diag_enable) { + cur_dv_mode = dv_ll_output_mode & 0xff; + diag_mode = 3; + } + if (dolby_vision_on && + ((last_dolby_vision_ll_policy != + dolby_vision_ll_policy) || + new_dovi_setting.vsvdb_changed)) { + last_dolby_vision_ll_policy = + dolby_vision_ll_policy; + new_dovi_setting.vsvdb_changed = 0; + /* TODO: verify 962e case */ + if (is_meson_gxm_cpu() || + (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A)) { + if (new_dovi_setting.dovi_ll_enable && + new_dovi_setting.diagnostic_enable == 0) { + VSYNC_WR_MPEG_REG_BITS( + VPP_DOLBY_CTRL, + 3, 6, 2); /* post matrix */ + VSYNC_WR_MPEG_REG_BITS( + VPP_MATRIX_CTRL, + 1, 0, 1); /* post matrix */ + } else { + VSYNC_WR_MPEG_REG_BITS( + VPP_DOLBY_CTRL, + 0, 6, 2); /* post matrix */ + VSYNC_WR_MPEG_REG_BITS( + VPP_MATRIX_CTRL, + 0, 0, 1); /* post matrix */ + } + } else if (is_meson_txlx_package_962E() + || force_stb_mode) { + if (new_dovi_setting.dovi_ll_enable && + new_dovi_setting.diagnostic_enable == 0) { + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA1, + 0x8000800); + /* enable wm tp vks*/ + /* bypass gainoff to vks */ + VSYNC_WR_MPEG_REG_BITS( + VPP_DOLBY_CTRL, 1, 1, 2); + VSYNC_WR_MPEG_REG_BITS( + VPP_MATRIX_CTRL, + 1, 0, 1); /* post matrix */ + } else { + /* bypass wm tp vks*/ + /* bypass gainoff to vks */ + VSYNC_WR_MPEG_REG_BITS( + VPP_DOLBY_CTRL, 3, 1, 2); + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA1, + 0x20002000); + if (is_meson_txlx_package_962X()) + enable_rgb_to_yuv_matrix_for_dvll( + 0, NULL, 12); + else + VSYNC_WR_MPEG_REG_BITS( + VPP_MATRIX_CTRL, + 0, 0, 1); + } + } + reset_post_table = true; + } + /* flush post matrix table when ll mode on and setting changed */ + if (new_dovi_setting.dovi_ll_enable && + (new_dovi_setting.diagnostic_enable == 0) && + dolby_vision_on && + (reset_post_table || reset || + memcmp(&p_core3_dm_regs[18], + &last_dm[18], 32))) + enable_rgb_to_yuv_matrix_for_dvll( + 1, &p_core3_dm_regs[18], + (dv_ll_output_mode >> 8) & 0xff); +#endif + + VSYNC_WR_MPEG_REG(DOLBY_CORE3_CLKGATE_CTRL, 0); + VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL1, + ((hsize + htotal_add) << 16) + | (vsize + vtotal_add + vsize_add + vsize_hold * 2)); + VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL2, + (hsize << 16) | (vsize + vsize_add)); + VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL3, + (0x80 << 16) | vsize_hold); + VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL4, + (0x04 << 16) | vsize_hold); + VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL5, 0x0000); + if (cur_dv_mode != + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) + VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, 0); + else + VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, + 0x10000000); /* swap UV */ + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 5, 7); + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 4); + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 2); + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 2, 1); + /* Control Register, address 0x04 2:0 RW */ + /* Output_operating mode*/ + /* 00- IPT 12 bit 444 bypass Dolby Vision output*/ + /* 01- IPT 12 bit tunnelled over RGB 8 bit 444, dolby vision output*/ + /* 02- HDR10 output, RGB 10 bit 444 PQ*/ + /* 03- Deep color SDR, RGB 10 bit 444 Gamma*/ + /* 04- SDR, RGB 8 bit 444 Gamma*/ + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); + /* for delay */ + + if (dm_count == 0) + count = 26; + else + count = dm_count; + for (i = 0; i < count; i++) + if (reset || (p_core3_dm_regs[i] != + last_dm[i])) + VSYNC_WR_MPEG_REG( + DOLBY_CORE3_REG_START + 0x6 + i, + p_core3_dm_regs[i]); + /* from addr 0x18 */ + + count = md_count; + for (i = 0; i < count; i++) { +#ifdef FORCE_HDMI_META + if ((i == 20) && (p_core3_md_regs[i] == 0x5140a3e)) + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, + (p_core3_md_regs[i] & 0xffffff00) | 0x80); + else +#endif + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, + p_core3_md_regs[i]); + } + for (; i < 30; i++) + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, 0); + + /* from addr 0x90 */ + /* core3 metadata program done */ + VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 3, 1); + + VSYNC_WR_MPEG_REG( + DOLBY_CORE3_DIAG_CTRL, + diag_mode); + + if ((dolby_vision_flags & FLAG_CERTIFICAION) + && !(dolby_vision_flags & FLAG_DISABLE_CRC)) + VSYNC_WR_MPEG_REG(0x36fb, 1); + /* enable core3 */ + VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL0, (dolby_enable << 0)); + return 0; +} + +static void apply_stb_core_settings( + int enable, unsigned int mask, + bool reset, u32 frame_size) +{ + const struct vinfo_s *vinfo = get_current_vinfo(); + u32 h_size = (frame_size >> 16) & 0xffff; + u32 v_size = frame_size & 0xffff; +#ifdef V2_4 + u32 core1_dm_count = 27; +#else + u32 core1_dm_count = 24; +#endif + u32 graphics_w = 1920; + u32 graphics_h = 1080; + + if (is_dolby_vision_stb_mode() + && dolby_vision_flags & FLAG_CERTIFICAION) { + graphics_w = dv_cert_graphic_width; + graphics_h = dv_cert_graphic_height; + } + if (mask & 1) { + if (is_meson_txlx_package_962E() + || force_stb_mode) { + if ((vinfo->width >= 1920) && + (vinfo->height >= 1080) && + (vinfo->field_height >= 1080)) + dma_start_line = 0x400; + else + dma_start_line = 0x180; + stb_dolby_core1_set( + 27, 173, 256 * 5, + (uint32_t *)&new_dovi_setting.dm_reg1, + (uint32_t *)&new_dovi_setting.comp_reg, + (uint32_t *)&new_dovi_setting.dm_lut1, + h_size, + v_size, + /* BL enable */ + enable, + /* EL enable */ + enable && new_dovi_setting.el_flag, + new_dovi_setting.el_halfsize_flag, + dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL, + new_dovi_setting.src_format == FORMAT_DOVI, + 1, + reset); + } else + dolby_core1_set( + core1_dm_count, 173, 256 * 5, + (uint32_t *)&new_dovi_setting.dm_reg1, + (uint32_t *)&new_dovi_setting.comp_reg, + (uint32_t *)&new_dovi_setting.dm_lut1, + h_size, + v_size, + /* BL enable */ + enable, + /* EL enable */ + enable && new_dovi_setting.el_flag, + new_dovi_setting.el_halfsize_flag, + dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL, + new_dovi_setting.src_format == FORMAT_DOVI, + 1, + reset); + } + if (mask & 2) + dolby_core2_set( + 24, 256 * 5, + (uint32_t *)&new_dovi_setting.dm_reg2, + (uint32_t *)&new_dovi_setting.dm_lut2, + graphics_w, graphics_h, 1, 1); + v_size = vinfo->height; + if (((vinfo->width == 720) && + (vinfo->height == 480) && + (vinfo->height != vinfo->field_height)) || + ((vinfo->width == 720) && + (vinfo->height == 576) && + (vinfo->height != vinfo->field_height)) || + ((vinfo->width == 1920) && + (vinfo->height == 1080) && + (vinfo->height != vinfo->field_height)) || + ((vinfo->width == 1920) && + (vinfo->height == 1080) && + (vinfo->height != vinfo->field_height) && + (vinfo->sync_duration_num / vinfo->sync_duration_den == 50))) + v_size = v_size/2; + if (mask & 4) + dolby_core3_set( + 26, new_dovi_setting.md_reg3.size, + (uint32_t *)&new_dovi_setting.dm_reg3, + new_dovi_setting.md_reg3.raw_metadata, + vinfo->width, v_size, + 1, + dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL); +} + +static void osd_bypass(int bypass) +{ + static uint32_t osd_backup_ctrl; + static uint32_t osd_backup_eotf; + static uint32_t osd_backup_mtx; + + if (bypass) { + osd_backup_ctrl = VSYNC_RD_MPEG_REG(VIU_OSD1_CTRL_STAT); + osd_backup_eotf = VSYNC_RD_MPEG_REG(VIU_OSD1_EOTF_CTL); + osd_backup_mtx = VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); + VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_EOTF_CTL, 0, 31, 1); + VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT, 0, 3, 1); + VSYNC_WR_MPEG_REG_BITS(VPP_MATRIX_CTRL, 0, 7, 1); + } else { + VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, osd_backup_mtx); + VSYNC_WR_MPEG_REG(VIU_OSD1_CTRL_STAT, osd_backup_ctrl); + VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, osd_backup_eotf); + } +} + +static uint32_t viu_eotf_ctrl_backup; +static uint32_t xvycc_lut_ctrl_backup; +static uint32_t inv_lut_ctrl_backup; +static uint32_t vpp_vadj_backup; +static uint32_t vpp_gainoff_backup; +static uint32_t vpp_ve_enable_ctrl_backup; +static uint32_t xvycc_vd1_rgb_ctrst_backup; +static bool is_video_effect_bypass; + +static void video_effect_bypass(int bypass) +{ + if (bypass) { + if (!is_video_effect_bypass) { + viu_eotf_ctrl_backup = + VSYNC_RD_MPEG_REG(VIU_EOTF_CTL); + xvycc_lut_ctrl_backup = + VSYNC_RD_MPEG_REG(XVYCC_LUT_CTL); + inv_lut_ctrl_backup = + VSYNC_RD_MPEG_REG(XVYCC_INV_LUT_CTL); + vpp_vadj_backup = + VSYNC_RD_MPEG_REG(VPP_VADJ_CTRL); + vpp_gainoff_backup = + VSYNC_RD_MPEG_REG(VPP_GAINOFF_CTRL0); + vpp_ve_enable_ctrl_backup = + VSYNC_RD_MPEG_REG(VPP_VE_ENABLE_CTRL); + xvycc_vd1_rgb_ctrst_backup = + VSYNC_RD_MPEG_REG(XVYCC_VD1_RGB_CTRST); + is_video_effect_bypass = true; + } + VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, 0); + VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, 0); + VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, 0); + VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, 0); + VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, 0); + VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, 0); + VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, 0); + } else if (is_video_effect_bypass) { + VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, + viu_eotf_ctrl_backup); + VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, + xvycc_lut_ctrl_backup); + VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, + inv_lut_ctrl_backup); + VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, + vpp_vadj_backup); + VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, + vpp_gainoff_backup); + VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, + vpp_ve_enable_ctrl_backup); + VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, + xvycc_vd1_rgb_ctrst_backup); + } +} + +static void osd_path_enable(int on) +{ + u32 i = 0; + u32 addr_port; + u32 data_port; + struct hdr_osd_lut_s *lut = &hdr_osd_reg.lut_val; + + if (!on) { + enable_osd_path(0, 0); + VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, 0); + VSYNC_WR_MPEG_REG(VIU_OSD1_OETF_CTL, 0); + } else { + enable_osd_path(1, -1); + if ((hdr_osd_reg.viu_osd1_eotf_ctl & 0x80000000) != 0) { + addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT; + data_port = VIU_OSD1_EOTF_LUT_DATA_PORT; + VSYNC_WR_MPEG_REG( + addr_port, 0); + for (i = 0; i < 16; i++) + VSYNC_WR_MPEG_REG( + data_port, + lut->r_map[i * 2] + | (lut->r_map[i * 2 + 1] << 16)); + VSYNC_WR_MPEG_REG( + data_port, + lut->r_map[EOTF_LUT_SIZE - 1] + | (lut->g_map[0] << 16)); + for (i = 0; i < 16; i++) + VSYNC_WR_MPEG_REG( + data_port, + lut->g_map[i * 2 + 1] + | (lut->b_map[i * 2 + 2] << 16)); + for (i = 0; i < 16; i++) + VSYNC_WR_MPEG_REG( + data_port, + lut->b_map[i * 2] + | (lut->b_map[i * 2 + 1] << 16)); + VSYNC_WR_MPEG_REG( + data_port, lut->b_map[EOTF_LUT_SIZE - 1]); + + /* load eotf matrix */ + VSYNC_WR_MPEG_REG( + VIU_OSD1_EOTF_COEF00_01, + hdr_osd_reg.viu_osd1_eotf_coef00_01); + VSYNC_WR_MPEG_REG( + VIU_OSD1_EOTF_COEF02_10, + hdr_osd_reg.viu_osd1_eotf_coef02_10); + VSYNC_WR_MPEG_REG( + VIU_OSD1_EOTF_COEF11_12, + hdr_osd_reg.viu_osd1_eotf_coef11_12); + VSYNC_WR_MPEG_REG( + VIU_OSD1_EOTF_COEF20_21, + hdr_osd_reg.viu_osd1_eotf_coef20_21); + VSYNC_WR_MPEG_REG( + VIU_OSD1_EOTF_COEF22_RS, + hdr_osd_reg.viu_osd1_eotf_coef22_rs); + VSYNC_WR_MPEG_REG( + VIU_OSD1_EOTF_CTL, + hdr_osd_reg.viu_osd1_eotf_ctl); + } + /* restore oetf lut */ + if ((hdr_osd_reg.viu_osd1_oetf_ctl & 0xe0000000) != 0) { + addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT; + data_port = VIU_OSD1_OETF_LUT_DATA_PORT; + for (i = 0; i < 20; i++) { + VSYNC_WR_MPEG_REG( + addr_port, i); + VSYNC_WR_MPEG_REG( + data_port, + lut->or_map[i * 2] + | (lut->or_map[i * 2 + 1] << 16)); + } + VSYNC_WR_MPEG_REG( + addr_port, 20); + VSYNC_WR_MPEG_REG( + data_port, + lut->or_map[41 - 1] + | (lut->og_map[0] << 16)); + for (i = 0; i < 20; i++) { + VSYNC_WR_MPEG_REG( + addr_port, 21 + i); + VSYNC_WR_MPEG_REG( + data_port, + lut->og_map[i * 2 + 1] + | (lut->og_map[i * 2 + 2] << 16)); + } + for (i = 0; i < 20; i++) { + VSYNC_WR_MPEG_REG( + addr_port, 41 + i); + VSYNC_WR_MPEG_REG( + data_port, + lut->ob_map[i * 2] + | (lut->ob_map[i * 2 + 1] << 16)); + } + VSYNC_WR_MPEG_REG( + addr_port, 61); + VSYNC_WR_MPEG_REG( + data_port, + lut->ob_map[41 - 1]); + VSYNC_WR_MPEG_REG( + VIU_OSD1_OETF_CTL, + hdr_osd_reg.viu_osd1_oetf_ctl); + } + } + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_PRE_OFFSET0_1, + hdr_osd_reg.viu_osd1_matrix_pre_offset0_1); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_PRE_OFFSET2, + hdr_osd_reg.viu_osd1_matrix_pre_offset2); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_COEF00_01, + hdr_osd_reg.viu_osd1_matrix_coef00_01); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_COEF02_10, + hdr_osd_reg.viu_osd1_matrix_coef02_10); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_COEF11_12, + hdr_osd_reg.viu_osd1_matrix_coef11_12); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_COEF20_21, + hdr_osd_reg.viu_osd1_matrix_coef20_21); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_COEF22_30, + hdr_osd_reg.viu_osd1_matrix_coef22_30); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_COEF31_32, + hdr_osd_reg.viu_osd1_matrix_coef31_32); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_COEF40_41, + hdr_osd_reg.viu_osd1_matrix_coef40_41); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_COLMOD_COEF42, + hdr_osd_reg.viu_osd1_matrix_colmod_coef42); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_OFFSET0_1, + hdr_osd_reg.viu_osd1_matrix_offset0_1); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_OFFSET2, + hdr_osd_reg.viu_osd1_matrix_offset2); + VSYNC_WR_MPEG_REG( + VIU_OSD1_MATRIX_CTRL, + hdr_osd_reg.viu_osd1_matrix_ctrl); +} + +static uint32_t dolby_ctrl_backup; +static uint32_t viu_misc_ctrl_backup; +static uint32_t vpp_matrix_backup; +static uint32_t vpp_dummy1_backup; +static uint32_t vpp_data_conv_para0_backup; +static uint32_t vpp_data_conv_para1_backup; +void enable_dolby_vision(int enable) +{ + uint32_t size = 0; + uint64_t *dma_data = ((struct tv_dovi_setting_s *) + tv_dovi_setting)->core1_reg_lut; + + if (enable) { + if (!dolby_vision_on) { + dolby_ctrl_backup = + VSYNC_RD_MPEG_REG(VPP_DOLBY_CTRL); + viu_misc_ctrl_backup = + VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1); + vpp_matrix_backup = + VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); + vpp_dummy1_backup = + VSYNC_RD_MPEG_REG(VPP_DUMMY_DATA1); + if (is_meson_txlx_cpu()) { + vpp_data_conv_para0_backup = + VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA0); + vpp_data_conv_para1_backup = + VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA1); + setting_update_count = 0; + } + if (is_meson_txlx_package_962X() && !force_stb_mode) { + if (efuse_mode == 1) { + size = 8 * TV_DMA_TBL_SIZE; + memset(dma_vaddr, 0x0, size); + memcpy((uint64_t *)dma_vaddr + 1, + dma_data + 1, + 8); + } + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 0, + 16, 1); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 1, + 16, 1); /* core1 */ + dolby_vision_core1_on = false; + } + if (dolby_vision_flags & FLAG_CERTIFICAION) { + /* bypass dither/PPS/SR/CM, EO/OE */ + VSYNC_WR_MPEG_REG_BITS( + VPP_DOLBY_CTRL, 3, 0, 2); + /* bypass all video effect */ + video_effect_bypass(1); + /* 12 bit unsigned to sign*/ + /* before vadj1 */ + /* 12 bit sign to unsign*/ + /* before post blend */ + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA0, 0x08000800); + /* 12->10 before vadj2*/ + /* 10->12 after gainoff */ + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA1, 0x20002000); + WRITE_VPP_REG(0x33e7, 0xb); + } else { + /* bypass all video effect */ + if (dolby_vision_flags + & FLAG_BYPASS_VPP) + video_effect_bypass(1); + /* 12->10 before vadj1*/ + /* 10->12 before post blend */ + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA0, 0x20002000); + /* 12->10 before vadj2*/ + /* 10->12 after gainoff */ + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA1, 0x20002000); + } + VSYNC_WR_MPEG_REG( + VPP_DUMMY_DATA1, + 0x80200); + /* osd rgb to yuv, vpp out yuv to rgb */ + VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0x81); + pr_dolby_dbg("Dolby Vision TV core turn on\n"); + } else if (is_meson_txlx_package_962E() + || force_stb_mode) { + size = 8 * STB_DMA_TBL_SIZE; + if (efuse_mode == 1) + memset(dma_vaddr, 0x0, size); + osd_bypass(1); + if (dolby_vision_mask & 4) + VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + 1, 3, 1); /* core3 enable */ + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 0, + 16, 1); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 1, + 16, 1); /* core1 */ + dolby_vision_core1_on = false; + } + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + (((dolby_vision_mask & 1) + && dovi_setting_video_flag) + ? 0 : 1), + 16, 1); /* core1 */ + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + ((dolby_vision_mask & 2) ? 0 : 1), + 18, 1); /* core2 */ + if (dolby_vision_flags & FLAG_CERTIFICAION) { + /* bypass dither/PPS/SR/CM*/ + /* bypass EO/OE*/ + /* bypass vadj2/mtx/gainoff */ + VSYNC_WR_MPEG_REG_BITS( + VPP_DOLBY_CTRL, 7, 0, 3); + /* bypass all video effect */ + video_effect_bypass(1); + /* 12 bit unsigned to sign*/ + /* before vadj1 */ + /* 12 bit sign to unsign*/ + /* before post blend */ + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA0, 0x08000800); + /* 12->10 before vadj2*/ + /* 10->12 after gainoff */ + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA1, 0x20002000); + } else { + /* bypass all video effect */ + if (dolby_vision_flags + & FLAG_BYPASS_VPP) + video_effect_bypass(1); + /* 12->10 before vadj1*/ + /* 10->12 before post blend */ + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA0, 0x20002000); + /* 12->10 before vadj2*/ + /* 10->12 after gainoff */ + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA1, 0x20002000); + } + VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + 0x80200); + if (is_meson_txlx_package_962X()) + VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 1); + else + VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); +#ifdef V2_4 + if (((dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) + || (dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT)) && + (dovi_setting.diagnostic_enable == 0) && + dovi_setting.dovi_ll_enable) { + u32 *reg = + (u32 *)&dovi_setting.dm_reg3; + /* input u12 -0x800 to s12 */ + VSYNC_WR_MPEG_REG( + VPP_DAT_CONV_PARA1, 0x8000800); + /* bypass vadj */ + VSYNC_WR_MPEG_REG( + VPP_VADJ_CTRL, 0); + /* bypass gainoff */ + VSYNC_WR_MPEG_REG( + VPP_GAINOFF_CTRL0, 0); + /* enable wm tp vks*/ + /* bypass gainoff to vks */ + VSYNC_WR_MPEG_REG_BITS( + VPP_DOLBY_CTRL, 1, 1, 2); + enable_rgb_to_yuv_matrix_for_dvll( + 1, ®[18], + (dv_ll_output_mode >> 8) + & 0xff); + } else + enable_rgb_to_yuv_matrix_for_dvll( + 0, NULL, 12); + last_dolby_vision_ll_policy = + dolby_vision_ll_policy; +#endif + stb_core_setting_update_flag = FLAG_CHANGE_ALL; + pr_dolby_dbg("Dolby Vision STB cores turn on\n"); + } else if (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) { + VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, + /* cm_datx4_mode */ + (0x0<<21) | + /* reg_front_cti_bit_mode */ + (0x0<<20) | + /* vpp_clip_ext_mode 19:17 */ + (0x1<<17) | + /* vpp_dolby2_en core3 */ + (((dolby_vision_mask & 4) ? + (0 << 0) : (1 << 0)) << 16) | + /* mat_xvy_dat_mode */ + (0x1<<15) | + /* vpp_ve_din_mode */ + (0x1<<14) | + (0x1<<13) | + /* mat_vd2_dat_mode 13:12 */ + (0x1<<12) | + (0x1<<11) | + /* vpp_dpath_sel 10:8 */ + /* vpp_uns2s_mode 7:0 */ + 0xd7); + if (dolby_vision_mask & 4) + VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + 1, 3, 1); /* core3 enable */ + else + VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + 0, 3, 1); /* bypass core3 */ + VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, + 0x0); + if (dolby_vision_mask & 2) + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + 0, + 2, 1);/*core2 enable*/ + else + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + 1, + 2, 1);/*core2 bypass*/ + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + 0, + 0, 1); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + 1, + 0, 1); /* core1 */ + dolby_vision_core1_on = false; + } + /* bypass all video effect */ + if ((dolby_vision_flags & FLAG_BYPASS_VPP) + || (dolby_vision_flags & FLAG_CERTIFICAION)) + video_effect_bypass(1); + VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); + VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, 0x20000000); + /* disable osd effect and shadow mode */ + osd_path_enable(0); +#ifdef V2_4 + if (((dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) + || (dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT)) && + (dovi_setting.diagnostic_enable == 0) && + dovi_setting.dovi_ll_enable) { + u32 *reg = + (u32 *)&dovi_setting.dm_reg3; + VSYNC_WR_MPEG_REG_BITS( + VPP_DOLBY_CTRL, + 3, 6, 2); /* post matrix */ + enable_rgb_to_yuv_matrix_for_dvll( + 1, ®[18], + (dv_ll_output_mode >> 8) + & 0xff); + } else + enable_rgb_to_yuv_matrix_for_dvll( + 0, NULL, 12); + last_dolby_vision_ll_policy = + dolby_vision_ll_policy; +#endif + stb_core_setting_update_flag = FLAG_CHANGE_ALL; + pr_dolby_dbg("Dolby Vision G12a turn on\n"); + } else { + VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, + /* cm_datx4_mode */ + (0x0<<21) | + /* reg_front_cti_bit_mode */ + (0x0<<20) | + /* vpp_clip_ext_mode 19:17 */ + (0x0<<17) | + /* vpp_dolby2_en core3 */ + (((dolby_vision_mask & 4) ? + (1 << 0) : (0 << 0)) << 16) | + /* mat_xvy_dat_mode */ + (0x0<<15) | + /* vpp_ve_din_mode */ + (0x1<<14) | + /* mat_vd2_dat_mode 13:12 */ + (0x1<<12) | + /* vpp_dpath_sel 10:8 */ + (0x3<<8) | + /* vpp_uns2s_mode 7:0 */ + 0x1f); + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* 23-20 ext mode */ + (0 << 2) | + /* 19 osd2 enable */ + ((dolby_vision_flags + & FLAG_CERTIFICAION) + ? (0 << 1) : (1 << 1)) | + /* 18 core2 bypass */ + ((dolby_vision_mask & 2) ? + 0 : 1), + 18, 6); + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 0, + 16, 1); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 1, + 16, 1); /* core1 */ + dolby_vision_core1_on = false; + } + /* bypass all video effect */ + if ((dolby_vision_flags & FLAG_BYPASS_VPP) + || (dolby_vision_flags & FLAG_CERTIFICAION)) + video_effect_bypass(1); + VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); + VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, 0x20000000); + /* disable osd effect and shadow mode */ + osd_path_enable(0); +#ifdef V2_4 + if (((dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) + || (dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT)) && + (dovi_setting.diagnostic_enable == 0) && + dovi_setting.dovi_ll_enable) { + u32 *reg = + (u32 *)&dovi_setting.dm_reg3; + VSYNC_WR_MPEG_REG_BITS( + VPP_DOLBY_CTRL, + 3, 6, 2); /* post matrix */ + enable_rgb_to_yuv_matrix_for_dvll( + 1, ®[18], + (dv_ll_output_mode >> 8) + & 0xff); + } else + enable_rgb_to_yuv_matrix_for_dvll( + 0, NULL, 12); + last_dolby_vision_ll_policy = + dolby_vision_ll_policy; +#endif + stb_core_setting_update_flag = FLAG_CHANGE_ALL; + pr_dolby_dbg("Dolby Vision turn on\n"); + } + } else { + if (!dolby_vision_core1_on + && (dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 0, + 16, 1); /* core1 */ + dolby_vision_core1_on = true; + } else if (dolby_vision_core1_on + && (!(dolby_vision_mask & 1) + || !dovi_setting_video_flag)){ + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + 1, + 16, 1); /* core1 */ + dolby_vision_core1_on = false; + } + } + dolby_vision_on = true; + dolby_vision_wait_on = false; + dolby_vision_wait_init = false; + dolby_vision_wait_count = 0; + vsync_count = 0; + } else { + if (dolby_vision_on) { + if (is_meson_txlx_package_962X() && !force_stb_mode) { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + /* vd2 connect to vpp */ + (1 << 1) | + /* 16 core1 bl bypass */ + (1 << 0), + 16, 2); +#ifdef V1_5 + if (p_funcs) /* destroy ctx */ + p_funcs->tv_control_path( + FORMAT_INVALID, 0, + NULL, 0, + NULL, 0, + 0, 0, + SIG_RANGE_SMPTE, + NULL, NULL, + 0, + NULL, + NULL); +#endif + pr_dolby_dbg("Dolby Vision TV core turn off\n"); + } else if (is_meson_txlx_package_962E() + || force_stb_mode) { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + (1 << 2) | /* core2 bypass */ + (1 << 1) | /* vd2 connect to vpp */ + (1 << 0), /* core1 bl bypass */ + 16, 3); + VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + 0, 3, 1); /* core3 disable */ + osd_bypass(0); +#ifdef V2_4 + if (p_funcs) /* destroy ctx */ + p_funcs->control_path( + FORMAT_INVALID, 0, + comp_buf, 0, + md_buf, 0, + 0, 0, 0, SIG_RANGE_SMPTE, + 0, 0, 0, 0, + 0, + &hdr10_param, + &new_dovi_setting); + last_dolby_vision_ll_policy = + DOLBY_VISION_LL_DISABLE; +#endif + stb_core_setting_update_flag = FLAG_CHANGE_ALL; + memset(&dovi_setting, 0, sizeof(dovi_setting)); + pr_dolby_dbg("Dolby Vision STB cores turn off\n"); + } else if (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) { + VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, + 0x1); + VSYNC_WR_MPEG_REG_BITS( + DOLBY_PATH_CTRL, + (1 << 2) | /* core2 bypass */ + (1 << 1) | /* vd2 connect to vpp */ + (1 << 0), /* core1 bl bypass */ + 0, 3); + VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + 0, 3, 1); /* core3 disable */ + /* enable osd effect and*/ + /* use default shadow mode */ + osd_path_enable(1); +#ifdef V2_4 + if (p_funcs) /* destroy ctx */ + p_funcs->control_path( + FORMAT_INVALID, 0, + comp_buf, 0, + md_buf, 0, + 0, 0, 0, SIG_RANGE_SMPTE, + 0, 0, 0, 0, + 0, + &hdr10_param, + &new_dovi_setting); + last_dolby_vision_ll_policy = + DOLBY_VISION_LL_DISABLE; +#endif + stb_core_setting_update_flag = FLAG_CHANGE_ALL; + memset(&dovi_setting, 0, sizeof(dovi_setting)); + pr_dolby_dbg("Dolby Vision G12a turn off\n"); + } else { + VSYNC_WR_MPEG_REG_BITS( + VIU_MISC_CTRL1, + (1 << 2) | /* core2 bypass */ + (1 << 1) | /* vd2 connect to vpp */ + (1 << 0), /* core1 bl bypass */ + 16, 3); + VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + 0, 16, 1); /* core3 disable */ + /* enable osd effect and*/ + /* use default shadow mode */ + osd_path_enable(1); +#ifdef V2_4 + if (p_funcs) /* destroy ctx */ + p_funcs->control_path( + FORMAT_INVALID, 0, + comp_buf, 0, + md_buf, 0, + 0, 0, 0, SIG_RANGE_SMPTE, + 0, 0, 0, 0, + 0, + &hdr10_param, + &new_dovi_setting); + last_dolby_vision_ll_policy = + DOLBY_VISION_LL_DISABLE; +#endif + stb_core_setting_update_flag = FLAG_CHANGE_ALL; + memset(&dovi_setting, 0, sizeof(dovi_setting)); + pr_dolby_dbg("Dolby Vision turn off\n"); + } + VSYNC_WR_MPEG_REG(VIU_SW_RESET, 3 << 9); + VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + if (is_meson_txlx_cpu()) { + VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA0, + vpp_data_conv_para0_backup); + VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA1, + vpp_data_conv_para1_backup); + VSYNC_WR_MPEG_REG( + DOLBY_TV_CLKGATE_CTRL, + 0x2414); + VSYNC_WR_MPEG_REG( + DOLBY_CORE2A_CLKGATE_CTRL, + 0x4); + VSYNC_WR_MPEG_REG( + DOLBY_CORE3_CLKGATE_CTRL, + 0x414); + VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, + 0x01000042); + } + if (is_meson_gxm_cpu() || + (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A)) { + VSYNC_WR_MPEG_REG( + DOLBY_CORE1_CLKGATE_CTRL, + 0x55555555); + VSYNC_WR_MPEG_REG( + DOLBY_CORE2A_CLKGATE_CTRL, + 0x55555555); + VSYNC_WR_MPEG_REG( + DOLBY_CORE3_CLKGATE_CTRL, + 0x55555555); + } + VSYNC_WR_MPEG_REG( + VPP_VD1_CLIP_MISC0, + (0x3ff << 20) + | (0x3ff << 10) | 0x3ff); + VSYNC_WR_MPEG_REG( + VPP_VD1_CLIP_MISC1, + 0); + video_effect_bypass(0); + VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, + dolby_ctrl_backup); + /* always vd2 to vpp and bypass core 1 */ + viu_misc_ctrl_backup |= + (VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 2); + VSYNC_WR_MPEG_REG(VIU_MISC_CTRL1, + viu_misc_ctrl_backup + | (3 << 16)); + VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, + vpp_matrix_backup); + VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + vpp_dummy1_backup); + } + frame_count = 0; + core1_disp_hsize = 0; + core1_disp_vsize = 0; + dolby_vision_on = false; + dolby_vision_core1_on = false; + dolby_vision_wait_on = false; + dolby_vision_wait_init = false; + dolby_vision_wait_count = 0; + dolby_vision_status = BYPASS_PROCESS; + dolby_vision_on_count = 0; + } +} +EXPORT_SYMBOL(enable_dolby_vision); + +/* dolby vision enhanced layer receiver*/ + +#define DVEL_RECV_NAME "dvel" + +static inline void dvel_vf_put(struct vframe_s *vf) +{ + struct vframe_provider_s *vfp = vf_get_provider(DVEL_RECV_NAME); + int event = 0; + + if (vfp) { + vf_put(vf, DVEL_RECV_NAME); + event |= VFRAME_EVENT_RECEIVER_PUT; + vf_notify_provider(DVEL_RECV_NAME, event, NULL); + } +} + +static inline struct vframe_s *dvel_vf_peek(void) +{ + return vf_peek(DVEL_RECV_NAME); +} + +static inline struct vframe_s *dvel_vf_get(void) +{ + int event = 0; + struct vframe_s *vf = vf_get(DVEL_RECV_NAME); + + if (vf) { + event |= VFRAME_EVENT_RECEIVER_GET; + vf_notify_provider(DVEL_RECV_NAME, event, NULL); + } + return vf; +} + +static struct vframe_s *dv_vf[16][2]; +static void *metadata_parser; +static bool metadata_parser_reset_flag; +static char meta_buf[1024]; +static int dvel_receiver_event_fun(int type, void *data, void *arg) +{ + char *provider_name = (char *)data; + int i; + unsigned long flags; + + if (type == VFRAME_EVENT_PROVIDER_UNREG) { + pr_info("%s, provider %s unregistered\n", + __func__, provider_name); + spin_lock_irqsave(&dovi_lock, flags); + for (i = 0; i < 16; i++) { + if (dv_vf[i][0]) { + if (dv_vf[i][1]) + dvel_vf_put(dv_vf[i][1]); + dv_vf[i][1] = NULL; + } + dv_vf[i][0] = NULL; + } + /* if (metadata_parser && p_funcs) {*/ + /* p_funcs->metadata_parser_release();*/ + /* metadata_parser = NULL;*/ + /*} */ + new_dovi_setting.video_width = + new_dovi_setting.video_height = 0; + spin_unlock_irqrestore(&dovi_lock, flags); + memset(&hdr10_data, 0, sizeof(hdr10_data)); + memset(&hdr10_param, 0, sizeof(hdr10_param)); + frame_count = 0; + setting_update_count = 0; + crc_count = 0; + crc_bypass_count = 0; + return -1; + } else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) { + return RECEIVER_ACTIVE; + } else if (type == VFRAME_EVENT_PROVIDER_REG) { + pr_info("%s, provider %s registered\n", + __func__, provider_name); + spin_lock_irqsave(&dovi_lock, flags); + for (i = 0; i < 16; i++) + dv_vf[i][0] = dv_vf[i][1] = NULL; + new_dovi_setting.video_width = + new_dovi_setting.video_height = 0; + spin_unlock_irqrestore(&dovi_lock, flags); + memset(&hdr10_data, 0, sizeof(hdr10_data)); + memset(&hdr10_param, 0, sizeof(hdr10_param)); + frame_count = 0; + setting_update_count = 0; + crc_count = 0; + crc_bypass_count = 0; + } + return 0; +} + +static const struct vframe_receiver_op_s dvel_vf_receiver = { + .event_cb = dvel_receiver_event_fun +}; + +static struct vframe_receiver_s dvel_vf_recv; + +void dolby_vision_init_receiver(void *pdev) +{ + ulong alloc_size; + + pr_info("%s(%s)\n", __func__, DVEL_RECV_NAME); + vf_receiver_init(&dvel_vf_recv, DVEL_RECV_NAME, + &dvel_vf_receiver, &dvel_vf_recv); + vf_reg_receiver(&dvel_vf_recv); + pr_info("%s: %s\n", __func__, dvel_vf_recv.name); + dovi_pdev = (struct platform_device *)pdev; + alloc_size = dma_size; + alloc_size = (alloc_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + dma_vaddr = dma_alloc_coherent(&dovi_pdev->dev, + alloc_size, &dma_paddr, GFP_KERNEL); +} + +#define MAX_FILENAME_LENGTH 64 +static const char comp_file[] = "%s_comp.%04d.reg"; +static const char dm_reg_core1_file[] = "%s_dm_core1.%04d.reg"; +static const char dm_reg_core2_file[] = "%s_dm_core2.%04d.reg"; +static const char dm_reg_core3_file[] = "%s_dm_core3.%04d.reg"; +static const char dm_lut_core1_file[] = "%s_dm_core1.%04d.lut"; +static const char dm_lut_core2_file[] = "%s_dm_core2.%04d.lut"; + +static void dump_struct(void *structure, int struct_length, + const char file_string[], int frame_nr) +{ + char fn[MAX_FILENAME_LENGTH]; + struct file *fp; + loff_t pos = 0; + mm_segment_t old_fs = get_fs(); + + if (frame_nr == 0) + return; + set_fs(KERNEL_DS); + snprintf(fn, MAX_FILENAME_LENGTH, file_string, + "/data/tmp/tmp", frame_nr-1); + fp = filp_open(fn, O_RDWR|O_CREAT, 0666); + if (fp == NULL) + pr_info("Error open file for writing %s\n", fn); + vfs_write(fp, structure, struct_length, &pos); + vfs_fsync(fp, 0); + filp_close(fp, NULL); + set_fs(old_fs); +} + +void dolby_vision_dump_struct(void) +{ + dump_struct(&dovi_setting.dm_reg1, + sizeof(dovi_setting.dm_reg1), + dm_reg_core1_file, frame_count); + if (dovi_setting.el_flag) + dump_struct(&dovi_setting.comp_reg, + sizeof(dovi_setting.comp_reg), + comp_file, frame_count); + + if (!is_graphics_output_off()) + dump_struct(&dovi_setting.dm_reg2, + sizeof(dovi_setting.dm_reg2), + dm_reg_core2_file, frame_count); + + dump_struct(&dovi_setting.dm_reg3, + sizeof(dovi_setting.dm_reg3), + dm_reg_core3_file, frame_count); + + dump_struct(&dovi_setting.dm_lut1, + sizeof(dovi_setting.dm_lut1), + dm_lut_core1_file, frame_count); + if (!is_graphics_output_off()) + dump_struct(&dovi_setting.dm_lut2, + sizeof(dovi_setting.dm_lut2), + dm_lut_core2_file, frame_count); + pr_dolby_dbg("setting for frame %d dumped\n", frame_count); +} +EXPORT_SYMBOL(dolby_vision_dump_struct); + +static void dump_setting( + struct dovi_setting_s *setting, + int frame_cnt, int debug_flag) +{ + int i; + uint32_t *p; + + if ((debug_flag & 0x10) && dump_enable) { + pr_info("core1\n"); + p = (uint32_t *)&setting->dm_reg1; + for (i = 0; i < 27; i++) + pr_info("%08x\n", p[i]); + pr_info("\ncomposer\n"); + p = (uint32_t *)&setting->comp_reg; + for (i = 0; i < 173; i++) + pr_info("%08x\n", p[i]); + pr_info("core1 swap\n"); + for (i = DOLBY_CORE1_CLKGATE_CTRL; + i <= DOLBY_CORE1_DMA_PORT; i++) + pr_info("[0x%4x] = 0x%x\n", + i, READ_VPP_REG(i)); + pr_info("core1 real reg\n"); + for (i = DOLBY_CORE1_REG_START; + i <= DOLBY_CORE1_REG_START + 5; i++) + pr_info("[0x%4x] = 0x%x\n", + i, READ_VPP_REG(i)); + pr_info("core1 composer real reg\n"); + for (i = 0; i < 173 ; i++) + pr_info("%08x\n", + READ_VPP_REG( + DOLBY_CORE1_REG_START + + 50 + i)); + } + + if ((debug_flag & 0x20) && dump_enable) { + pr_info("\ncore1lut\n"); + p = (uint32_t *)&setting->dm_lut1.TmLutI; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + p = (uint32_t *)&setting->dm_lut1.TmLutS; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + p = (uint32_t *)&setting->dm_lut1.SmLutI; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + p = (uint32_t *)&setting->dm_lut1.SmLutS; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + p = (uint32_t *)&setting->dm_lut1.G2L; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + } + + if ((debug_flag & 0x10) && dump_enable && !is_graphics_output_off()) { + pr_info("core2\n"); + p = (uint32_t *)&setting->dm_reg2; + for (i = 0; i < 24; i++) + pr_info("%08x\n", p[i]); + pr_info("core2 swap\n"); + for (i = DOLBY_CORE2A_CLKGATE_CTRL; + i <= DOLBY_CORE2A_DMA_PORT; i++) + pr_info("[0x%4x] = 0x%x\n", + i, READ_VPP_REG(i)); + pr_info("core2 real reg\n"); + for (i = DOLBY_CORE2A_REG_START; + i <= DOLBY_CORE2A_REG_START + 5; i++) + pr_info("[0x%4x] = 0x%x\n", + i, READ_VPP_REG(i)); + } + + if ((debug_flag & 0x20) && dump_enable && !is_graphics_output_off()) { + pr_info("\ncore2lut\n"); + p = (uint32_t *)&setting->dm_lut2.TmLutI; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + p = (uint32_t *)&setting->dm_lut2.TmLutS; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + p = (uint32_t *)&setting->dm_lut2.SmLutI; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + p = (uint32_t *)&setting->dm_lut2.SmLutS; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + p = (uint32_t *)&setting->dm_lut2.G2L; + for (i = 0; i < 64; i++) + pr_info("%08x, %08x, %08x, %08x\n", + p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); + pr_info("\n"); + } + + if ((debug_flag & 0x10) && dump_enable) { + pr_info("core3\n"); + p = (uint32_t *)&setting->dm_reg3; + for (i = 0; i < 26; i++) + pr_info("%08x\n", p[i]); + pr_info("core3 swap\n"); + for (i = DOLBY_CORE3_CLKGATE_CTRL; + i <= DOLBY_CORE3_OUTPUT_CSC_CRC; i++) + pr_info("[0x%4x] = 0x%x\n", + i, READ_VPP_REG(i)); + pr_info("core3 real reg\n"); + for (i = DOLBY_CORE3_REG_START; + i <= DOLBY_CORE3_REG_START + 67; i++) + pr_info("[0x%4x] = 0x%x\n", + i, READ_VPP_REG(i)); + } + + if ((debug_flag & 0x40) && dump_enable + && (dolby_vision_mode <= DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL)) { + pr_info("\ncore3_meta %d\n", setting->md_reg3.size); + p = setting->md_reg3.raw_metadata; + for (i = 0; i < setting->md_reg3.size; i++) + pr_info("%08x\n", p[i]); + pr_info("\n"); + } +} + +void dolby_vision_dump_setting(int debug_flag) +{ + pr_dolby_dbg("\n====== setting for frame %d ======\n", frame_count); + if (is_meson_txlx_package_962X() && !force_stb_mode) + dump_tv_setting((struct tv_dovi_setting_s *)tv_dovi_setting, + frame_count, debug_flag); + else + dump_setting(&new_dovi_setting, frame_count, debug_flag); + pr_dolby_dbg("=== setting for frame %d dumped ===\n\n", frame_count); +} +EXPORT_SYMBOL(dolby_vision_dump_setting); + +static int sink_support_dolby_vision(const struct vinfo_s *vinfo) +{ + if (!vinfo || !vinfo->vout_device || !vinfo->vout_device->dv_info) + return 0; + if (vinfo->vout_device->dv_info->ieeeoui != 0x00d046) + return 0; + if (vinfo->vout_device->dv_info->block_flag != CORRECT) + return 0; + if (dolby_vision_flags & FLAG_DISABLE_DOVI_OUT) + return 0; +#if 0 + /* 2160p60 if TV support */ + if ((vinfo->vout_device->mode >= VMODE_4K2K_SMPTE_50HZ) + && (vinfo->vout_device->dv_info->sup_2160p60hz == 1)) + return 1; + /* 1080p~2160p30 if TV support */ + else if ((vinfo->vout_device->mode >= VMODE_1080P) + && (vinfo->vout_device->mode <= VMODE_4K2K_SMPTE_30HZ)) + return 1; + return 0; +#else + return 1; +#endif +} + +static int sink_support_hdr(const struct vinfo_s *vinfo) +{ +#define HDR_SUPPORT (1 << 2) + if (!vinfo) + return 0; + if (vinfo->hdr_info.hdr_support & HDR_SUPPORT) + return 1; + return 0; +} + +static int dolby_vision_policy_process( + int *mode, enum signal_format_e src_format) +{ + const struct vinfo_s *vinfo; + int mode_change = 0; + + if ((!dolby_vision_enable) || (!p_funcs)) + return mode_change; + + if (is_meson_txlx_package_962X() && !force_stb_mode) { + if (dolby_vision_policy == DOLBY_VISION_FORCE_OUTPUT_MODE) { + if (*mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_BYPASS) { + pr_dolby_dbg("dovi tv output mode change %d -> %d\n", + dolby_vision_mode, *mode); + mode_change = 1; + } + } else if (*mode == DOLBY_VISION_OUTPUT_MODE_SDR8) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_SDR8) { + pr_dolby_dbg("dovi tv output mode change %d -> %d\n", + dolby_vision_mode, *mode); + mode_change = 1; + } + } else { + pr_dolby_error( + "not support dovi output mode %d\n", + *mode); + return mode_change; + } + } else if (dolby_vision_policy == DOLBY_VISION_FOLLOW_SINK) { + /* bypass dv_mode with efuse */ + if ((efuse_mode == 1) && !dolby_vision_efuse_bypass) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_BYPASS) { + *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; + mode_change = 1; + } else + mode_change = 0; + return mode_change; + } + if ((src_format == FORMAT_DOVI) || + (src_format == FORMAT_DOVI_LL)) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_SDR8) { + pr_dolby_dbg("dovi tv output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_SDR8; + mode_change = 1; + } + } else { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_BYPASS) { + pr_dolby_dbg("dovi tv output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; + mode_change = 1; + } + } + } else if (dolby_vision_policy == DOLBY_VISION_FOLLOW_SOURCE) { + /* bypass dv_mode with efuse */ + if ((efuse_mode == 1) && !dolby_vision_efuse_bypass) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_BYPASS) { + *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; + mode_change = 1; + } else + mode_change = 0; + return mode_change; + } + if ((src_format == FORMAT_DOVI) || + (src_format == FORMAT_DOVI_LL) || + (src_format == FORMAT_HDR10)) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_SDR8) { + pr_dolby_dbg("dovi tv output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_SDR8; + mode_change = 1; + } + } else { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_BYPASS) { + pr_dolby_dbg("dovi tv output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; + mode_change = 1; + } + } + } + return mode_change; + } + + vinfo = get_current_vinfo(); + if (dolby_vision_policy == DOLBY_VISION_FOLLOW_SINK) { + /* bypass dv_mode with efuse */ + if ((efuse_mode == 1) && !dolby_vision_efuse_bypass) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_BYPASS) { + *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; + mode_change = 1; + } else + mode_change = 0; + return mode_change; + } + if (vinfo && sink_support_dolby_vision(vinfo)) { + /* TV support DOVI, All -> DOVI */ + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) { + pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL; + mode_change = 1; + } + } else if (vinfo && sink_support_hdr(vinfo) + && (dolby_vision_hdr10_policy & 2)) { + /* TV support HDR, All -> HDR */ + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_HDR10) { + pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_HDR10\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_HDR10; + mode_change = 1; + } + } else { + /* TV not support DOVI */ + if ((src_format == FORMAT_DOVI) || + (src_format == FORMAT_DOVI_LL)) { + /* DOVI to SDR */ + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_SDR8) { + pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_SDR8; + mode_change = 1; + } + } else if (src_format == FORMAT_HDR10 + && (dolby_vision_hdr10_policy & 1)) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_SDR8) { + /* HDR10 to SDR */ + pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_SDR8; + mode_change = 1; + } + } else if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_BYPASS) { + /* HDR/SDR bypass */ + pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; + mode_change = 1; + } + } + } else if (dolby_vision_policy == DOLBY_VISION_FOLLOW_SOURCE) { + /* bypass dv_mode with efuse */ + if ((efuse_mode == 1) && !dolby_vision_efuse_bypass) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_BYPASS) { + *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; + mode_change = 1; + } else + mode_change = 0; + return mode_change; + } + if ((src_format == FORMAT_DOVI) || + (src_format == FORMAT_DOVI_LL)) { + /* DOVI source */ + if (vinfo && sink_support_dolby_vision(vinfo)) { + /* TV support DOVI, DOVI -> DOVI */ + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) { + pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n"); + *mode = + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL; + mode_change = 1; + } + } else { + /* TV not support DOVI, DOVI -> SDR */ + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_SDR8) { + pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_SDR8; + mode_change = 1; + } + } + } else if (src_format == FORMAT_HDR10 + && (dolby_vision_hdr10_policy & 1)) { + if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_SDR8) { + /* HDR10 to SDR */ + pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n"); + *mode = DOLBY_VISION_OUTPUT_MODE_SDR8; + mode_change = 1; + } + } else if (dolby_vision_mode != + DOLBY_VISION_OUTPUT_MODE_BYPASS) { + /* HDR/SDR bypass */ + pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS"); + *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; + mode_change = 1; + } + } else if (dolby_vision_policy == DOLBY_VISION_FORCE_OUTPUT_MODE) { + if (dolby_vision_mode != *mode) { + pr_dolby_dbg("dovi output mode change %d -> %d\n", + dolby_vision_mode, *mode); + mode_change = 1; + } + } + return mode_change; +} + +static bool is_dovi_frame(struct vframe_s *vf) +{ + struct provider_aux_req_s req; + char *p; + unsigned int size = 0; + unsigned int type = 0; + + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + + if ((vf->source_type == VFRAME_SOURCE_TYPE_HDMI) + && is_meson_txlx_package_962X() && !force_stb_mode) { + vf_notify_provider_by_name("dv_vdin", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + if ((req.aux_buf && req.aux_size) || + (dolby_vision_flags & FLAG_FORCE_DOVI_LL)) + return 1; + else + return 0; + } else if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) { + vf_notify_provider_by_name("dvbldec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + if (req.dv_enhance_exist) + return true; + if (!req.aux_buf || !req.aux_size) + return 0; + p = req.aux_buf; + while (p < req.aux_buf + req.aux_size - 8) { + size = *p++; + size = (size << 8) | *p++; + size = (size << 8) | *p++; + size = (size << 8) | *p++; + type = *p++; + type = (type << 8) | *p++; + type = (type << 8) | *p++; + type = (type << 8) | *p++; + if (type == 0x01000000) + return true; + p += size; + } + } + return false; +} + +#define signal_color_primaries ((vf->signal_type >> 16) & 0xff) +#define signal_transfer_characteristic ((vf->signal_type >> 8) & 0xff) +static bool is_hdr10_frame(struct vframe_s *vf) +{ + if ((signal_transfer_characteristic == 16) + && ((signal_color_primaries == 9) + || (signal_color_primaries == 2))) + return true; + return false; +} + +int dolby_vision_check_hdr10(struct vframe_s *vf) +{ + int mode; + + if (is_hdr10_frame(vf) && !dolby_vision_on) { + /* dovi source, but dovi not enabled */ + mode = dolby_vision_mode; + if (dolby_vision_policy_process( + &mode, FORMAT_HDR10)) { + if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) + && (dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_BYPASS)) + dolby_vision_wait_on = true; + return 1; + } + } + return 0; +} +EXPORT_SYMBOL(dolby_vision_check_hdr10); + +void dolby_vision_vf_put(struct vframe_s *vf) +{ + int i; + + if (vf) + for (i = 0; i < 16; i++) { + if (dv_vf[i][0] == vf) { + if (dv_vf[i][1]) { + if (debug_dolby & 2) + pr_dolby_dbg("--- put bl(%p-%lld) with el(%p-%lld) ---\n", + vf, vf->pts_us64, + dv_vf[i][1], + dv_vf[i][1]->pts_us64); + dvel_vf_put(dv_vf[i][1]); + } else if (debug_dolby & 2) { + pr_dolby_dbg("--- put bl(%p-%lld) ---\n", + vf, vf->pts_us64); + } + dv_vf[i][0] = NULL; + dv_vf[i][1] = NULL; + } + } +} +EXPORT_SYMBOL(dolby_vision_vf_put); + +struct vframe_s *dolby_vision_vf_peek_el(struct vframe_s *vf) +{ + int i; + + if (dolby_vision_flags && p_funcs) { + for (i = 0; i < 16; i++) { + if (dv_vf[i][0] == vf) { + if (dv_vf[i][1] + && (dolby_vision_status == BYPASS_PROCESS) + && !is_dolby_vision_on()) + dv_vf[i][1]->type |= VIDTYPE_VD2; + return dv_vf[i][1]; + } + } + } + return NULL; +} +EXPORT_SYMBOL(dolby_vision_vf_peek_el); + +static void dolby_vision_vf_add(struct vframe_s *vf, struct vframe_s *el_vf) +{ + int i; + + for (i = 0; i < 16; i++) { + if (dv_vf[i][0] == NULL) { + dv_vf[i][0] = vf; + dv_vf[i][1] = el_vf; + break; + } + } +} + +static int dolby_vision_vf_check(struct vframe_s *vf) +{ + int i; + + for (i = 0; i < 16; i++) { + if (dv_vf[i][0] == vf) { + if (debug_dolby & 2) { + if (dv_vf[i][1]) + pr_dolby_dbg("=== bl(%p-%lld) with el(%p-%lld) toggled ===\n", + vf, + vf->pts_us64, + dv_vf[i][1], + dv_vf[i][1]->pts_us64); + else + pr_dolby_dbg("=== bl(%p-%lld) toggled ===\n", + vf, + vf->pts_us64); + } + return 0; + } + } + return 1; +} + +static int parse_sei_and_meta( + struct vframe_s *vf, + struct provider_aux_req_s *req, + int *total_comp_size, + int *total_md_size, + enum signal_format_e *src_format) +{ + int i; + char *p; + unsigned int size = 0; + unsigned int type = 0; + int md_size = 0; + int comp_size = 0; + int parser_ready = 0; + int ret = 2; + unsigned long flags; + bool parser_overflow = false; + + if ((req->aux_buf == NULL) + || (req->aux_size == 0)) + return 1; + + + p = req->aux_buf; + while (p < req->aux_buf + req->aux_size - 8) { + size = *p++; + size = (size << 8) | *p++; + size = (size << 8) | *p++; + size = (size << 8) | *p++; + type = *p++; + type = (type << 8) | *p++; + type = (type << 8) | *p++; + type = (type << 8) | *p++; + + if (type == 0x01000000) { + /* source is VS10 */ + *total_comp_size = 0; + *total_md_size = 0; + *src_format = FORMAT_DOVI; + if (size > (sizeof(meta_buf) - 3)) + size = (sizeof(meta_buf) - 3); + meta_buf[0] = meta_buf[1] = meta_buf[2] = 0; + memcpy(&meta_buf[3], p+1, size-1); + if ((debug_dolby & 4) && dump_enable) { + pr_dolby_dbg("metadata(%d):\n", size); + for (i = 0; i < size+2; i += 8) + pr_info("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", + meta_buf[i], + meta_buf[i+1], + meta_buf[i+2], + meta_buf[i+3], + meta_buf[i+4], + meta_buf[i+5], + meta_buf[i+6], + meta_buf[i+7]); + } + + if (!p_funcs) + return -1; + /* prepare metadata parser */ + spin_lock_irqsave(&dovi_lock, flags); + parser_ready = 0; + if (metadata_parser == NULL) { + metadata_parser = + p_funcs->metadata_parser_init( + dolby_vision_flags + & FLAG_CHANGE_SEQ_HEAD + ? 1 : 0); + p_funcs->metadata_parser_reset(1); + if (metadata_parser != NULL) { + parser_ready = 1; + if (debug_dolby & 1) + pr_dolby_dbg("metadata parser init OK\n"); + } + } else { + if (p_funcs->metadata_parser_reset + (metadata_parser_reset_flag) == 0) + metadata_parser_reset_flag = 0; + parser_ready = 1; + } + if (!parser_ready) { + spin_unlock_irqrestore(&dovi_lock, flags); + pr_dolby_error( + "meta(%d), pts(%lld) -> metadata parser init fail\n", + size, vf->pts_us64); + return 2; + } + + md_size = comp_size = 0; + if (p_funcs->metadata_parser_process( + meta_buf, size + 2, + comp_buf + *total_comp_size, + &comp_size, + md_buf + *total_md_size, + &md_size, + true)) { + pr_dolby_error( + "meta(%d), pts(%lld) -> metadata parser process fail\n", + size, vf->pts_us64); + ret = 2; + } else { + if (*total_comp_size + comp_size + < sizeof(comp_buf)) + *total_comp_size += comp_size; + else + parser_overflow = true; + + if (*total_md_size + md_size + < sizeof(md_buf)) + *total_md_size += md_size; + else + parser_overflow = true; + ret = 0; + } + spin_unlock_irqrestore(&dovi_lock, flags); + if (parser_overflow) { + ret = 2; + break; + } + } + p += size; + } + + if (*total_md_size) { + if (debug_dolby & 1) + pr_dolby_dbg( + "meta(%d), pts(%lld) -> md(%d), comp(%d)\n", + size, vf->pts_us64, + *total_md_size, *total_comp_size); + if ((debug_dolby & 4) && dump_enable) { + pr_dolby_dbg("parsed md(%d):\n", *total_md_size); + for (i = 0; i < *total_md_size + 7; i += 8) { + pr_info("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", + md_buf[i], + md_buf[i+1], + md_buf[i+2], + md_buf[i+3], + md_buf[i+4], + md_buf[i+5], + md_buf[i+6], + md_buf[i+7]); + } + } + } + return ret; +} + +#define INORM 50000 +static u32 bt2020_primaries[3][2] = { + {0.17 * INORM + 0.5, 0.797 * INORM + 0.5}, /* G */ + {0.131 * INORM + 0.5, 0.046 * INORM + 0.5}, /* B */ + {0.708 * INORM + 0.5, 0.292 * INORM + 0.5}, /* R */ +}; + +static u32 bt2020_white_point[2] = { + 0.3127 * INORM + 0.5, 0.3290 * INORM + 0.5 +}; + +static int check_primaries(struct vframe_master_display_colour_s *p_mdc) +{ + if (!p_mdc->present_flag) + return 0; + if ((p_mdc->primaries[0][1] > p_mdc->primaries[1][1]) + && (p_mdc->primaries[0][1] > p_mdc->primaries[2][1]) + && (p_mdc->primaries[2][0] > p_mdc->primaries[0][0]) + && (p_mdc->primaries[2][0] > p_mdc->primaries[1][0])) { + /* reasonable g,b,r */ + return 2; + } else if ((p_mdc->primaries[0][0] > p_mdc->primaries[1][0]) + && (p_mdc->primaries[0][0] > p_mdc->primaries[2][0]) + && (p_mdc->primaries[1][1] > p_mdc->primaries[0][1]) + && (p_mdc->primaries[1][1] > p_mdc->primaries[2][1])) { + /* reasonable r,g,b */ + return 1; + } + /* source not usable, use standard bt2020 */ + return 0; +} + +void prepare_hdr10_param( + struct vframe_master_display_colour_s *p_mdc, + struct hdr10_param_s *p_hdr10_param) +{ + struct vframe_content_light_level_s *p_cll = + &p_mdc->content_light_level; + uint8_t flag = 0; + uint32_t max_lum = 1000 * 10000; + uint32_t min_lum = 50; + int primaries_type = 0; + + if (dolby_vision_flags & FLAG_CERTIFICAION) { + p_hdr10_param-> + min_display_mastering_luminance + = min_lum; + p_hdr10_param-> + max_display_mastering_luminance + = max_lum; + p_hdr10_param->Rx + = bt2020_primaries[2][0]; + p_hdr10_param->Ry + = bt2020_primaries[2][1]; + p_hdr10_param->Gx + = bt2020_primaries[0][0]; + p_hdr10_param->Gy + = bt2020_primaries[0][1]; + p_hdr10_param->Bx + = bt2020_primaries[1][0]; + p_hdr10_param->By + = bt2020_primaries[1][1]; + p_hdr10_param->Wx + = bt2020_white_point[0]; + p_hdr10_param->Wy + = bt2020_white_point[1]; + p_hdr10_param->max_content_light_level = 0; + p_hdr10_param->max_pic_average_light_level = 0; + return; + } + + primaries_type = check_primaries(p_mdc); + if (primaries_type == 2) { + if ((p_hdr10_param-> + max_display_mastering_luminance + != p_mdc->luminance[0]) + || (p_hdr10_param-> + min_display_mastering_luminance + != p_mdc->luminance[1]) + || (p_hdr10_param->Rx + != p_mdc->primaries[2][0]) + || (p_hdr10_param->Ry + != p_mdc->primaries[2][1]) + || (p_hdr10_param->Gx + != p_mdc->primaries[0][0]) + || (p_hdr10_param->Gy + != p_mdc->primaries[0][1]) + || (p_hdr10_param->Bx + != p_mdc->primaries[1][0]) + || (p_hdr10_param->By + != p_mdc->primaries[1][1]) + || (p_hdr10_param->Wx + != p_mdc->white_point[0]) + || (p_hdr10_param->Wy + != p_mdc->white_point[1])) { + flag |= 1; + p_hdr10_param-> + max_display_mastering_luminance + = p_mdc->luminance[0]; + p_hdr10_param-> + min_display_mastering_luminance + = p_mdc->luminance[1]; + p_hdr10_param->Rx + = p_mdc->primaries[2][0]; + p_hdr10_param->Ry + = p_mdc->primaries[2][1]; + p_hdr10_param->Gx + = p_mdc->primaries[0][0]; + p_hdr10_param->Gy + = p_mdc->primaries[0][1]; + p_hdr10_param->Bx + = p_mdc->primaries[1][0]; + p_hdr10_param->By + = p_mdc->primaries[1][1]; + p_hdr10_param->Wx + = p_mdc->white_point[0]; + p_hdr10_param->Wy + = p_mdc->white_point[1]; + } + } else if (primaries_type == 1) { + if ((p_hdr10_param-> + max_display_mastering_luminance + != p_mdc->luminance[0]) + || (p_hdr10_param-> + min_display_mastering_luminance + != p_mdc->luminance[1]) + || (p_hdr10_param->Rx + != p_mdc->primaries[0][0]) + || (p_hdr10_param->Ry + != p_mdc->primaries[0][1]) + || (p_hdr10_param->Gx + != p_mdc->primaries[1][0]) + || (p_hdr10_param->Gy + != p_mdc->primaries[1][1]) + || (p_hdr10_param->Bx + != p_mdc->primaries[2][0]) + || (p_hdr10_param->By + != p_mdc->primaries[2][1]) + || (p_hdr10_param->Wx + != p_mdc->white_point[0]) + || (p_hdr10_param->Wy + != p_mdc->white_point[1])) { + flag |= 1; + p_hdr10_param-> + max_display_mastering_luminance + = p_mdc->luminance[0]; + p_hdr10_param-> + min_display_mastering_luminance + = p_mdc->luminance[1]; + p_hdr10_param->Rx + = p_mdc->primaries[0][0]; + p_hdr10_param->Ry + = p_mdc->primaries[0][1]; + p_hdr10_param->Gx + = p_mdc->primaries[1][0]; + p_hdr10_param->Gy + = p_mdc->primaries[1][1]; + p_hdr10_param->Bx + = p_mdc->primaries[2][0]; + p_hdr10_param->By + = p_mdc->primaries[2][1]; + p_hdr10_param->Wx + = p_mdc->white_point[0]; + p_hdr10_param->Wy + = p_mdc->white_point[1]; + } + } else { + if ((p_hdr10_param-> + min_display_mastering_luminance + != min_lum) + || (p_hdr10_param-> + max_display_mastering_luminance + != max_lum) + || (p_hdr10_param->Rx + != bt2020_primaries[2][0]) + || (p_hdr10_param->Ry + != bt2020_primaries[2][1]) + || (p_hdr10_param->Gx + != bt2020_primaries[0][0]) + || (p_hdr10_param->Gy + != bt2020_primaries[0][1]) + || (p_hdr10_param->Bx + != bt2020_primaries[1][0]) + || (p_hdr10_param->By + != bt2020_primaries[1][1]) + || (p_hdr10_param->Wx + != bt2020_white_point[0]) + || (p_hdr10_param->Wy + != bt2020_white_point[1])) { + flag |= 2; + p_hdr10_param-> + min_display_mastering_luminance + = min_lum; + p_hdr10_param-> + max_display_mastering_luminance + = max_lum; + p_hdr10_param->Rx + = bt2020_primaries[2][0]; + p_hdr10_param->Ry + = bt2020_primaries[2][1]; + p_hdr10_param->Gx + = bt2020_primaries[0][0]; + p_hdr10_param->Gy + = bt2020_primaries[0][1]; + p_hdr10_param->Bx + = bt2020_primaries[1][0]; + p_hdr10_param->By + = bt2020_primaries[1][1]; + p_hdr10_param->Wx + = bt2020_white_point[0]; + p_hdr10_param->Wy + = bt2020_white_point[1]; + } + } + + if (p_cll->present_flag) { + if ((p_hdr10_param->max_content_light_level + != p_cll->max_content) + || (p_hdr10_param->max_pic_average_light_level + != p_cll->max_pic_average)) + flag |= 4; + if (flag & 4) { + p_hdr10_param->max_content_light_level + = p_cll->max_content; + p_hdr10_param->max_pic_average_light_level + = p_cll->max_pic_average; + } + } else { + if ((p_hdr10_param->max_content_light_level != 0) + || (p_hdr10_param->max_pic_average_light_level != 0)) { + p_hdr10_param->max_content_light_level = 0; + p_hdr10_param->max_pic_average_light_level = 0; + flag |= 8; + } + } + + if (flag) { + pr_dolby_dbg("HDR10: primaries %d, maxcontent %d, flag %d\n", + p_mdc->present_flag, + p_cll->present_flag, + flag); + pr_dolby_dbg("\tR = %04x, %04x\n", + p_hdr10_param->Rx, + p_hdr10_param->Ry); + pr_dolby_dbg("\tG = %04x, %04x\n", + p_hdr10_param->Gx, + p_hdr10_param->Gy); + pr_dolby_dbg("\tB = %04x, %04x\n", + p_hdr10_param->Bx, + p_hdr10_param->By); + pr_dolby_dbg("\tW = %04x, %04x\n", + p_hdr10_param->Wx, + p_hdr10_param->Wy); + pr_dolby_dbg("\tMax = %d\n", + p_hdr10_param-> + max_display_mastering_luminance); + pr_dolby_dbg("\tMin = %d\n", + p_hdr10_param-> + min_display_mastering_luminance); + pr_dolby_dbg("\tMCLL = %d\n", + p_hdr10_param-> + max_content_light_level); + pr_dolby_dbg("\tMPALL = %d\n\n", + p_hdr10_param-> + max_pic_average_light_level); + } +} + +#ifdef V2_4 +static int prepare_vsif_pkt( + struct dv_vsif_para *vsif, + struct dovi_setting_s *setting, + const struct vinfo_s *vinfo) +{ + if (!vsif || !vinfo || !setting || + !vinfo->vout_device || !vinfo->vout_device->dv_info) + return -1; + vsif->vers.ver2.low_latency = + setting->dovi_ll_enable; + vsif->vers.ver2.dobly_vision_signal = 1; + if (vinfo->vout_device->dv_info + && vinfo->vout_device->dv_info->sup_backlight_control + && (setting->ext_md.available_level_mask + & EXT_MD_AVAIL_LEVEL_2)) { + vsif->vers.ver2.backlt_ctrl_MD_present = 1; + vsif->vers.ver2.eff_tmax_PQ_hi = + setting->ext_md.level_2.target_max_PQ_hi & 0xf; + vsif->vers.ver2.eff_tmax_PQ_low = + setting->ext_md.level_2.target_max_PQ_lo; + } else { + vsif->vers.ver2.backlt_ctrl_MD_present = 0; + vsif->vers.ver2.eff_tmax_PQ_hi = 0; + vsif->vers.ver2.eff_tmax_PQ_low = 0; + } + + if (setting->dovi_ll_enable + && (setting->ext_md.available_level_mask + & EXT_MD_AVAIL_LEVEL_255)) { + vsif->vers.ver2.auxiliary_MD_present = 1; + vsif->vers.ver2.auxiliary_runmode = + setting->ext_md.level_255.dm_run_mode; + vsif->vers.ver2.auxiliary_runversion = + setting->ext_md.level_255.dm_run_version; + vsif->vers.ver2.auxiliary_debug0 = + setting->ext_md.level_255.dm_debug0; + } else { + vsif->vers.ver2.auxiliary_MD_present = 0; + vsif->vers.ver2.auxiliary_runmode = 0; + vsif->vers.ver2.auxiliary_runversion = 0; + vsif->vers.ver2.auxiliary_debug0 = 0; + } + return 0; +} +#endif + +static bool send_hdmi_pkt( + enum signal_format_e dst_format, + const struct vinfo_s *vinfo) +{ + struct hdr_10_infoframe_s *p_hdr; + int i; + bool flag = false; + + if (dst_format == FORMAT_HDR10) { + p_hdr = &dovi_setting.hdr_info; + hdr10_data.features = + (1 << 29) /* video available */ + | (5 << 26) /* unspecified */ + | (0 << 25) /* limit */ + | (1 << 24) /* color available */ + | (9 << 16) /* bt2020 */ + | (0x10 << 8) /* bt2020-10 */ + | (10 << 0);/* bt2020c */ + if (hdr10_data.primaries[0][0] != + ((p_hdr->display_primaries_x_0_MSB << 8) + | p_hdr->display_primaries_x_0_LSB)) + flag = true; + hdr10_data.primaries[0][0] = + (p_hdr->display_primaries_x_0_MSB << 8) + | p_hdr->display_primaries_x_0_LSB; + + if (hdr10_data.primaries[0][1] != + ((p_hdr->display_primaries_y_0_MSB << 8) + | p_hdr->display_primaries_y_0_LSB)) + flag = true; + hdr10_data.primaries[0][1] = + (p_hdr->display_primaries_y_0_MSB << 8) + | p_hdr->display_primaries_y_0_LSB; + + if (hdr10_data.primaries[1][0] != + ((p_hdr->display_primaries_x_1_MSB << 8) + | p_hdr->display_primaries_x_1_LSB)) + flag = true; + hdr10_data.primaries[1][0] = + (p_hdr->display_primaries_x_1_MSB << 8) + | p_hdr->display_primaries_x_1_LSB; + + if (hdr10_data.primaries[1][1] != + ((p_hdr->display_primaries_y_1_MSB << 8) + | p_hdr->display_primaries_y_1_LSB)) + flag = true; + hdr10_data.primaries[1][1] = + (p_hdr->display_primaries_y_1_MSB << 8) + | p_hdr->display_primaries_y_1_LSB; + + if (hdr10_data.primaries[2][0] != + ((p_hdr->display_primaries_x_2_MSB << 8) + | p_hdr->display_primaries_x_2_LSB)) + flag = true; + hdr10_data.primaries[2][0] = + (p_hdr->display_primaries_x_2_MSB << 8) + | p_hdr->display_primaries_x_2_LSB; + + if (hdr10_data.primaries[2][1] != + ((p_hdr->display_primaries_y_2_MSB << 8) + | p_hdr->display_primaries_y_2_LSB)) + flag = true; + hdr10_data.primaries[2][1] = + (p_hdr->display_primaries_y_2_MSB << 8) + | p_hdr->display_primaries_y_2_LSB; + + if (hdr10_data.white_point[0] != + ((p_hdr->white_point_x_MSB << 8) + | p_hdr->white_point_x_LSB)) + flag = true; + hdr10_data.white_point[0] = + (p_hdr->white_point_x_MSB << 8) + | p_hdr->white_point_x_LSB; + + if (hdr10_data.white_point[1] != + ((p_hdr->white_point_y_MSB << 8) + | p_hdr->white_point_y_LSB)) + flag = true; + hdr10_data.white_point[1] = + (p_hdr->white_point_y_MSB << 8) + | p_hdr->white_point_y_LSB; + + if (hdr10_data.luminance[0] != + ((p_hdr->max_display_mastering_luminance_MSB << 8) + | p_hdr->max_display_mastering_luminance_LSB)) + flag = true; + hdr10_data.luminance[0] = + (p_hdr->max_display_mastering_luminance_MSB << 8) + | p_hdr->max_display_mastering_luminance_LSB; + + if (hdr10_data.luminance[1] != + ((p_hdr->min_display_mastering_luminance_MSB << 8) + | p_hdr->min_display_mastering_luminance_LSB)) + flag = true; + hdr10_data.luminance[1] = + (p_hdr->min_display_mastering_luminance_MSB << 8) + | p_hdr->min_display_mastering_luminance_LSB; + + if (hdr10_data.max_content != + ((p_hdr->max_content_light_level_MSB << 8) + | p_hdr->max_content_light_level_LSB)) + flag = true; + hdr10_data.max_content = + (p_hdr->max_content_light_level_MSB << 8) + | p_hdr->max_content_light_level_LSB; + + if (hdr10_data.max_frame_average != + ((p_hdr->max_frame_average_light_level_MSB << 8) + | p_hdr->max_frame_average_light_level_LSB)) + flag = true; + hdr10_data.max_frame_average = + (p_hdr->max_frame_average_light_level_MSB << 8) + | p_hdr->max_frame_average_light_level_LSB; + if (vinfo && vinfo->vout_device && + vinfo->vout_device->fresh_tx_hdr_pkt) + vinfo->vout_device->fresh_tx_hdr_pkt(&hdr10_data); + if (vinfo && vinfo->vout_device && + vinfo->vout_device->fresh_tx_vsif_pkt) + vinfo->vout_device->fresh_tx_vsif_pkt(0, 0, NULL); + + if (flag) { + pr_dolby_dbg("Info frame for hdr10 changed:\n"); + for (i = 0; i < 3; i++) + pr_dolby_dbg( + "\tprimaries[%1d] = %04x, %04x\n", + i, + hdr10_data.primaries[i][0], + hdr10_data.primaries[i][1]); + pr_dolby_dbg("\twhite_point = %04x, %04x\n", + hdr10_data.white_point[0], + hdr10_data.white_point[1]); + pr_dolby_dbg("\tMax = %d\n", + hdr10_data.luminance[0]); + pr_dolby_dbg("\tMin = %d\n", + hdr10_data.luminance[1]); + pr_dolby_dbg("\tMCLL = %d\n", + hdr10_data.max_content); + pr_dolby_dbg("\tMPALL = %d\n\n", + hdr10_data.max_frame_average); + } + } else if (dst_format == FORMAT_DOVI) { + struct dv_vsif_para vsif; + + memset(&vsif, 0, sizeof(vsif)); +#ifdef V2_4 + if (vinfo) + prepare_vsif_pkt( + &vsif, &dovi_setting, vinfo); +#endif + hdr10_data.features = + (1 << 29) /* video available */ + | (5 << 26) /* unspecified */ + | (0 << 25) /* limit */ + | (1 << 24) /* color available */ + | (1 << 16) /* bt709 */ + | (1 << 8) /* bt709 */ + | (1 << 0); /* bt709 */ + for (i = 0; i < 3; i++) { + hdr10_data.primaries[i][0] = 0; + hdr10_data.primaries[i][1] = 0; + } + hdr10_data.white_point[0] = 0; + hdr10_data.white_point[1] = 0; + hdr10_data.luminance[0] = 0; + hdr10_data.luminance[1] = 0; + hdr10_data.max_content = 0; + hdr10_data.max_frame_average = 0; + if (vinfo && vinfo->vout_device && + vinfo->vout_device->fresh_tx_hdr_pkt) + vinfo->vout_device->fresh_tx_hdr_pkt(&hdr10_data); + if (vinfo && vinfo->vout_device && + vinfo->vout_device->fresh_tx_vsif_pkt) { +#ifdef V2_4 + if (dovi_setting.dovi_ll_enable) + vinfo->vout_device->fresh_tx_vsif_pkt( + EOTF_T_LL_MODE, + dovi_setting.diagnostic_enable + ? RGB_10_12BIT : YUV422_BIT12, + &vsif); + else +#endif + vinfo->vout_device->fresh_tx_vsif_pkt( + EOTF_T_DOLBYVISION, + dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL + ? RGB_8BIT : YUV422_BIT12, &vsif); + } + } else { + hdr10_data.features = + (1 << 29) /* video available */ + | (5 << 26) /* unspecified */ + | (0 << 25) /* limit */ + | (1 << 24) /* color available */ + | (1 << 16) /* bt709 */ + | (1 << 8) /* bt709 */ + | (1 << 0); /* bt709 */ + for (i = 0; i < 3; i++) { + hdr10_data.primaries[i][0] = 0; + hdr10_data.primaries[i][1] = 0; + } + hdr10_data.white_point[0] = 0; + hdr10_data.white_point[1] = 0; + hdr10_data.luminance[0] = 0; + hdr10_data.luminance[1] = 0; + hdr10_data.max_content = 0; + hdr10_data.max_frame_average = 0; + if (vinfo && vinfo->vout_device && + vinfo->vout_device->fresh_tx_hdr_pkt) + vinfo->vout_device->fresh_tx_hdr_pkt(&hdr10_data); + if (vinfo && vinfo->vout_device && + vinfo->vout_device->fresh_tx_vsif_pkt) + vinfo->vout_device->fresh_tx_vsif_pkt(0, 0, NULL); + } + return flag; +} + +static uint32_t null_vf_cnt; +static bool video_off_handled; +static int is_video_output_off(struct vframe_s *vf) +{ + if ((READ_VPP_REG(VPP_MISC) & (1<<10)) == 0) { + /*Not reset frame0/1 clipping*/ + /*when core off to avoid green garbage*/ + if (is_meson_txlx_package_962X() && (vf == NULL) && + (dolby_vision_on_count <= dolby_vision_run_mode_delay)) + return 0; + if (vf == NULL) + null_vf_cnt++; + else + null_vf_cnt = 0; + if (null_vf_cnt > dolby_vision_wait_delay + 3) { + null_vf_cnt = 0; + return 1; + } + } else + video_off_handled = 0; + return 0; +} + +static void calculate_panel_max_pq( + const struct vinfo_s *vinfo, + struct TargetDisplayConfig *config) +{ + uint32_t max_lin = tv_max_lin; + uint16_t max_pq = tv_max_pq; + + if (dolby_vision_flags & FLAG_CERTIFICAION) + return; + if (panel_max_lumin) + max_lin = panel_max_lumin; + /*else if (vinfo->hdr_info.sink_flag)*/ + /* max_lin = vinfo->hdr_info.lumi_max;*/ + if (max_lin < 100) + max_lin = 100; + else if (max_lin > 4000) + max_lin = 4000; + if (max_lin != tv_max_lin) { + if (max_lin < 500) { + max_lin = max_lin - 100 + 10; + max_lin = (max_lin / 20) * 20 + 100; + max_pq = L2PQ_100_500[(max_lin - 100) / 20]; + } else { + max_lin = max_lin - 500 + 50; + max_lin = (max_lin / 100) * 100 + 500; + max_pq = L2PQ_100_500[(max_lin - 500) / 100]; + } + pr_info("panel max lumin changed from %d(%d) to %d(%d)\n", + tv_max_lin, tv_max_pq, max_lin, max_pq); + tv_max_lin = max_lin; + tv_max_pq = max_pq; + config->max_lin = + config->max_lin_dupli = + tv_max_lin << 18; + config->maxPq = + config->maxPq_dupli = + tv_max_pq; + } +} + +static u32 last_total_md_size; +static u32 last_total_comp_size; +/* toggle mode: 0: not toggle; 1: toggle frame; 2: use keep frame */ +int dolby_vision_parse_metadata( + struct vframe_s *vf, u8 toggle_mode, bool bypass_release) +{ + const struct vinfo_s *vinfo = get_current_vinfo(); + struct vframe_s *el_vf; + struct provider_aux_req_s req; + struct provider_aux_req_s el_req; + int flag; + enum signal_format_e src_format = FORMAT_SDR; + enum signal_format_e check_format; + enum signal_format_e dst_format; + int total_md_size = 0; + int total_comp_size = 0; + bool el_flag = 0; + bool el_halfsize_flag = 1; + uint32_t w = 3840; + uint32_t h = 2160; + int meta_flag_bl = 1; + int meta_flag_el = 1; + int src_chroma_format = 0; + int src_bdp = 12; + bool video_frame = false; + int i; + struct vframe_master_display_colour_s *p_mdc; + unsigned int current_mode = dolby_vision_mode; + uint32_t target_lumin_max = 0; + enum input_mode_e input_mode = INPUT_MODE_OTT; + enum priority_mode_e pri_mode = VIDEO_PRIORITY; + u32 graphic_min = 50; /* 0.0001 */ + u32 graphic_max = 100; /* 1 */ + + if (!dolby_vision_enable) + return -1; + + if (vf) { + video_frame = true; + w = (vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width; + h = (vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height; + } + + if (is_meson_txlx_package_962X() && !force_stb_mode && vf + && (vf->source_type == VFRAME_SOURCE_TYPE_HDMI)) { + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + req.low_latency = 0; + vf_notify_provider_by_name("dv_vdin", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + input_mode = INPUT_MODE_HDMI; + if (debug_dolby & 1) + pr_dolby_dbg("vdin0 get aux data %p %x, ll:%d\n", + req.aux_buf, req.aux_size, req.low_latency); + + if ((dolby_vision_flags & FLAG_FORCE_DOVI_LL) + || (req.low_latency == 1)) { + src_format = FORMAT_DOVI_LL; + src_chroma_format = 0; + memset(md_buf, 0, sizeof(md_buf)); + memset(comp_buf, 0, sizeof(comp_buf)); + req.aux_size = 0; + req.aux_buf = NULL; + } else if (req.aux_buf && req.aux_size) { + memcpy(md_buf, req.aux_buf, req.aux_size); + src_format = FORMAT_DOVI; + } else { + if (toggle_mode == 2) + src_format = ((struct tv_dovi_setting_s *) + tv_dovi_setting)->src_format; + if (vf->type & VIDTYPE_VIU_422) + src_chroma_format = 1; + p_mdc = &vf->prop.master_display_colour; + if (is_hdr10_frame(vf)) { + src_format = FORMAT_HDR10; + /* prepare parameter from hdmi for hdr10 */ + p_mdc->luminance[0] *= 10000; + prepare_hdr10_param( + p_mdc, &hdr10_param); + } + } + if (debug_dolby & 4) { + pr_dolby_dbg("metadata(%d):\n", req.aux_size); + for (i = 0; i < req.aux_size + 8; i += 8) + pr_info("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", + md_buf[i], + md_buf[i+1], + md_buf[i+2], + md_buf[i+3], + md_buf[i+4], + md_buf[i+5], + md_buf[i+6], + md_buf[i+7]); + } + + total_md_size = req.aux_size; + total_comp_size = 0; + meta_flag_bl = 0; + if (req.aux_buf && req.aux_size) { + last_total_md_size = total_md_size; + last_total_comp_size = total_comp_size; + } else if (toggle_mode == 2) { + total_md_size = last_total_md_size; + total_comp_size = last_total_comp_size; + } + if (debug_dolby & 1) + pr_dolby_dbg( + "frame %d pts %lld, format: %s\n", + frame_count, vf->pts_us64, + (src_format == FORMAT_HDR10) ? "HDR10" : + ((src_format == FORMAT_DOVI) ? "DOVI" : + ((src_format == FORMAT_DOVI_LL) ? "DOVI_LL" : "SDR"))); + + if (toggle_mode == 1) { + if (debug_dolby & 2) + pr_dolby_dbg( + "+++ get bl(%p-%lld) +++\n", + vf, vf->pts_us64); + dolby_vision_vf_add(vf, NULL); + } + } else if (vf && (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS)) { + /* check source format */ + input_mode = INPUT_MODE_OTT; + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + vf_notify_provider_by_name("dvbldec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + if (debug_dolby & 1 && req.aux_buf && req.aux_size) + pr_dolby_dbg("dvbldec get aux data %p %x\n", + req.aux_buf, req.aux_size); + /* parse meta in base layer */ + if (toggle_mode != 2) { + meta_flag_bl = + parse_sei_and_meta( + vf, &req, + &total_comp_size, + &total_md_size, + &src_format); + } else if (is_dolby_vision_stb_mode()) + src_format = dovi_setting.src_format; + else if (is_meson_txlx_package_962X()) + src_format = ((struct tv_dovi_setting_s *) + tv_dovi_setting)->src_format; + + if ((src_format != FORMAT_DOVI) + && is_hdr10_frame(vf)) { + src_format = FORMAT_HDR10; + /* prepare parameter from SEI for hdr10 */ + p_mdc = &vf->prop.master_display_colour; + prepare_hdr10_param(p_mdc, &hdr10_param); + /* for 962x with v1.4 or stb with v2.3 may use 12 bit */ + src_bdp = 10; + memset(&req, 0, sizeof(req)); + } +#ifdef V2_4 + /* TODO: need 962e ? */ + if ((src_format == FORMAT_SDR) + && is_dolby_vision_stb_mode() + && !req.dv_enhance_exist) + src_bdp = 10; +#endif + if (((debug_dolby & 1) + || (frame_count == 0)) + && (toggle_mode == 1)) + pr_info( + "DOLBY: frame %d pts %lld, src bdp: %d format: %s, aux_size:%d, enhance: %d\n", + frame_count, vf->pts_us64, src_bdp, + (src_format == FORMAT_HDR10) ? "HDR10" : + (src_format == FORMAT_DOVI ? "DOVI" : + (req.dv_enhance_exist ? "DOVI (el meta)" : "SDR")), + req.aux_size, req.dv_enhance_exist); + + if (req.dv_enhance_exist && + (toggle_mode == 1)) { + el_vf = dvel_vf_get(); + if (el_vf && + ((el_vf->pts_us64 == vf->pts_us64) + || !(dolby_vision_flags & FLAG_CHECK_ES_PTS))) { + if (debug_dolby & 2) + pr_dolby_dbg("+++ get bl(%p-%lld) with el(%p-%lld) +++\n", + vf, vf->pts_us64, + el_vf, el_vf->pts_us64); + if (meta_flag_bl) { + int el_md_size = 0; + int el_comp_size = 0; + + el_req.vf = el_vf; + el_req.bot_flag = 0; + el_req.aux_buf = NULL; + el_req.aux_size = 0; + vf_notify_provider_by_name("dveldec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&el_req); + if (el_req.aux_buf + && el_req.aux_size) { + meta_flag_el = + parse_sei_and_meta( + el_vf, &el_req, + &el_comp_size, + &el_md_size, + &src_format); + } + if (!meta_flag_el) { + total_comp_size = + el_comp_size; + total_md_size = + el_md_size; + src_bdp = 12; + } + /* force set format as DOVI*/ + /* when meta data error */ + if (meta_flag_el + && el_req.aux_buf + && el_req.aux_size) + src_format = FORMAT_DOVI; + if (debug_dolby & 2) + pr_dolby_dbg( + "meta data el mode: el_src_format: %d, meta_flag_el: %d\n", + src_format, + meta_flag_el); + if (meta_flag_el && frame_count == 0) + pr_info( + "DOVI el meta mode, but parser meta error, el vf %p, size:%d\n", + el_req.aux_buf, + el_req.aux_size); + } + dolby_vision_vf_add(vf, el_vf); + el_flag = 1; + if (vf->width == el_vf->width) + el_halfsize_flag = 0; + } else { + if (!el_vf) + pr_dolby_error( + "bl(%p-%lld) not found el\n", + vf, vf->pts_us64); + else + pr_dolby_error( + "bl(%p-%lld) not found el(%p-%lld)\n", + vf, vf->pts_us64, + el_vf, el_vf->pts_us64); + } + } else if (toggle_mode == 1) { + if (debug_dolby & 2) + pr_dolby_dbg( + "+++ get bl(%p-%lld) +++\n", + vf, vf->pts_us64); + dolby_vision_vf_add(vf, NULL); + } + + if ((toggle_mode == 0) + && req.dv_enhance_exist) + el_flag = 1; + + if (toggle_mode != 2) { + last_total_md_size = total_md_size; + last_total_comp_size = total_comp_size; + } else if (meta_flag_bl && meta_flag_el) { + total_md_size = last_total_md_size; + total_comp_size = last_total_comp_size; + el_flag = dovi_setting.el_flag; + meta_flag_bl = 0; + } + if ((src_format == FORMAT_DOVI) + && meta_flag_bl && meta_flag_el) { + /* dovi frame no meta or meta error */ + /* use old setting for this frame */ + return -1; + } + w = (vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width; + h = (vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height; + } + + if ((src_format == FORMAT_DOVI) + && meta_flag_bl && meta_flag_el) { + /* dovi frame no meta or meta error */ + /* use old setting for this frame */ + return -1; + } + + /* if not DOVI, release metadata_parser */ + if ((src_format != FORMAT_DOVI) + && metadata_parser + && !bypass_release) { + if (p_funcs) + p_funcs->metadata_parser_release(); + metadata_parser = NULL; + } + + check_format = src_format; + current_mode = dolby_vision_mode; + + if (dolby_vision_policy_process( + ¤t_mode, check_format)) { + if (!dolby_vision_wait_init) + dolby_vision_set_toggle_flag(1); + pr_dolby_dbg("[dolby_vision_parse_metadata] output change from %d to %d\n", + dolby_vision_mode, current_mode); + dolby_vision_mode = current_mode; + } + + if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { + new_dovi_setting.video_width = 0; + new_dovi_setting.video_height = 0; + return -1; + } + + if (!p_funcs) + return -1; + + /* TV core */ + if (is_meson_txlx_package_962X() && !force_stb_mode) { + if (!pq_config_set_flag) { + memcpy(&(((struct pq_config_s *) + pq_config_fake)->target_display_config), + &def_tgt_display_cfg, + sizeof(def_tgt_display_cfg)); + pq_config_set_flag = true; + } + calculate_panel_max_pq( + vinfo, + &(((struct pq_config_s *) + pq_config_fake)->target_display_config)); + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->video_width = w << 16; + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->video_height = h << 16; + ((struct pq_config_s *) + pq_config_fake)->target_display_config.tuningMode = + dolby_vision_tunning_mode; + if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) { + ((struct pq_config_s *)pq_config_fake) + ->target_display_config.tuningMode |= + TUNINGMODE_EL_FORCEDDISABLE; + el_halfsize_flag = 0; + } else + ((struct pq_config_s *)pq_config_fake) + ->target_display_config.tuningMode &= + (~TUNINGMODE_EL_FORCEDDISABLE); +#ifdef V1_5 + /* disable global dimming */ + if (dolby_vision_flags & FLAG_CERTIFICAION) + ((struct pq_config_s *)pq_config_fake) + ->target_display_config.tuningMode &= + (~TUNINGMODE_EXTLEVEL4_DISABLE); + else + ((struct pq_config_s *)pq_config_fake) + ->target_display_config.tuningMode |= + TUNINGMODE_EXTLEVEL4_DISABLE; + + if (src_format != ((struct tv_dovi_setting_s *) + tv_dovi_setting)->src_format) + p_funcs->tv_control_path( + FORMAT_INVALID, 0, + NULL, 0, + NULL, 0, + 0, 0, + SIG_RANGE_SMPTE, + NULL, NULL, + 0, + NULL, + NULL); +#endif + flag = p_funcs->tv_control_path( + src_format, input_mode, + comp_buf, total_comp_size, + md_buf, total_md_size, + src_bdp, + src_chroma_format, + SIG_RANGE_SMPTE, /* bit/chroma/range */ + (struct pq_config_s *)pq_config_fake, &menu_param, + (!el_flag) || + (dolby_vision_flags & FLAG_DISABLE_COMPOSER), + &hdr10_param, + tv_dovi_setting); + if (flag >= 0) { + if (input_mode == INPUT_MODE_HDMI) { + if (h > 1080) + ((struct tv_dovi_setting_s *) + tv_dovi_setting) + ->core1_reg_lut[1] = + 0x0000000100000043; + else + ((struct tv_dovi_setting_s *) + tv_dovi_setting) + ->core1_reg_lut[1] = + 0x0000000100000042; + } else { + if (src_format == FORMAT_HDR10) + ((struct tv_dovi_setting_s *) + tv_dovi_setting) + ->core1_reg_lut[1] = + 0x000000010000404c; + else if (el_halfsize_flag) + ((struct tv_dovi_setting_s *) + tv_dovi_setting) + ->core1_reg_lut[1] = + 0x000000010000004c; + else + ((struct tv_dovi_setting_s *) + tv_dovi_setting) + ->core1_reg_lut[1] = + 0x0000000100000044; + } + /* enable CRC */ + if (dolby_vision_flags & FLAG_CERTIFICAION) + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->core1_reg_lut[3] = + 0x000000ea00000001; + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->src_format = src_format; + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->el_flag = el_flag; + ((struct tv_dovi_setting_s *)tv_dovi_setting) + ->el_halfsize_flag = el_halfsize_flag; + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->video_width = w; + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->video_height = h; + ((struct tv_dovi_setting_s *)tv_dovi_setting) + ->input_mode = input_mode; + tv_dovi_setting_change_flag = true; + dovi_setting_video_flag = video_frame; + if (debug_dolby & 1) { + if (el_flag) + pr_dolby_dbg("tv setting %s-%d: flag=%02x,md=%d,comp=%d\n", + input_mode == INPUT_MODE_HDMI ? + "hdmi" : "ott", + src_format, + flag, + total_md_size, + total_comp_size); + else + pr_dolby_dbg("tv setting %s-%d: flag=%02x,md=%d\n", + input_mode == INPUT_MODE_HDMI ? + "hdmi" : "ott", + src_format, + flag, + total_md_size); + } + dump_tv_setting( + (struct tv_dovi_setting_s *)tv_dovi_setting, + frame_count, debug_dolby); + el_mode = el_flag; + return 0; /* setting updated */ + } + if (flag < 0) { + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->video_width = 0; + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->video_height = 0; + pr_dolby_error("tv_control_path() failed\n"); + } + return -1; + } + + /* STB core */ + /* check target luminance */ + if (is_graphics_output_off()) { + graphic_min = 0; + graphic_max = 0; + } else { + graphic_min = + dolby_vision_graphic_min; +#ifdef V2_4 + if (dolby_vision_flags & FLAG_CERTIFICAION) + graphic_max = 500; + else + graphic_max = + dolby_vision_graphic_max; +#else + graphic_max = dolby_vision_graphic_max; +#endif + } + if (dolby_vision_flags & FLAG_USE_SINK_MIN_MAX) { + if (vinfo->vout_device->dv_info->ieeeoui == 0x00d046) { + if (vinfo->vout_device->dv_info->ver == 0) { + /* need lookup PQ table ... */ + } else if (vinfo->vout_device->dv_info->ver == 1) { + if (vinfo->vout_device->dv_info->tmaxLUM) { + /* Target max luminance = 100+50*CV */ + graphic_max = + target_lumin_max = + (vinfo->vout_device + ->dv_info->tmaxLUM + * 50 + 100); + /* Target min luminance = (CV/127)^2 */ + graphic_min = + dolby_vision_target_min = + (vinfo->vout_device-> + dv_info->tminLUM ^ 2) + * 10000 / (127 * 127); + } + } + } else if (vinfo->hdr_info.hdr_support & 4) { + if (vinfo->hdr_info.lumi_max) { + /* Luminance value = 50 * (2 ^ (CV/32)) */ + graphic_max = + target_lumin_max = 50 * + (2 ^ (vinfo->hdr_info.lumi_max >> 5)); + /* Desired Content Min Luminance =*/ + /* Desired Content Max Luminance*/ + /* * (CV/255) * (CV/255) / 100 */ + graphic_min = + dolby_vision_target_min = + target_lumin_max * 10000 + * vinfo->hdr_info.lumi_min + * vinfo->hdr_info.lumi_min + / (255 * 255 * 100); + } + } + if (target_lumin_max) { + dolby_vision_target_max[0][0] = + dolby_vision_target_max[0][1] = + dolby_vision_target_max[1][0] = + dolby_vision_target_max[1][1] = + dolby_vision_target_max[2][0] = + dolby_vision_target_max[2][1] = + target_lumin_max; + } else { + memcpy( + dolby_vision_target_max, + dolby_vision_default_max, + sizeof(dolby_vision_target_max)); + } + } + + /* check dst format */ + if ((dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) + || (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT)) + dst_format = FORMAT_DOVI; + else if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_HDR10) + dst_format = FORMAT_HDR10; + else + dst_format = FORMAT_SDR; + +#ifdef V2_4 + if ((src_format != dovi_setting.src_format) + || (dst_format != dovi_setting.dst_format)) + p_funcs->control_path( + FORMAT_INVALID, 0, + comp_buf, 0, + md_buf, 0, + 0, 0, 0, SIG_RANGE_SMPTE, + 0, 0, 0, 0, + 0, + &hdr10_param, + &new_dovi_setting); + if (!vsvdb_config_set_flag) { + memset(&new_dovi_setting.vsvdb_tbl[0], + 0, sizeof(new_dovi_setting.vsvdb_tbl)); + new_dovi_setting.vsvdb_len = 0; + new_dovi_setting.vsvdb_changed = 1; + vsvdb_config_set_flag = true; + } + if ((dolby_vision_flags & + FLAG_DISABLE_LOAD_VSVDB) == 0) { + /* check if vsvdb is changed */ + if (vinfo && vinfo->vout_device && + vinfo->vout_device->dv_info && + (vinfo->vout_device->dv_info->ieeeoui == 0x00d046) + && (vinfo->vout_device->dv_info + ->block_flag == CORRECT)) { + if (new_dovi_setting.vsvdb_len + != vinfo->vout_device->dv_info->length) + new_dovi_setting.vsvdb_changed = 1; + else if (memcmp(&new_dovi_setting.vsvdb_tbl[0], + &vinfo->vout_device->dv_info->rawdata[0], + vinfo->vout_device->dv_info->length)) + new_dovi_setting.vsvdb_changed = 1; + memset(&new_dovi_setting.vsvdb_tbl[0], + 0, sizeof(new_dovi_setting.vsvdb_tbl)); + memcpy(&new_dovi_setting.vsvdb_tbl[0], + &vinfo->vout_device->dv_info->rawdata[0], + vinfo->vout_device->dv_info->length); + new_dovi_setting.vsvdb_len = + vinfo->vout_device->dv_info->length; + } else { + if (new_dovi_setting.vsvdb_len) + new_dovi_setting.vsvdb_changed = 1; + memset(&new_dovi_setting.vsvdb_tbl[0], + 0, sizeof(new_dovi_setting.vsvdb_tbl)); + new_dovi_setting.vsvdb_len = 0; + } + } + if (dolby_vision_graphics_priority || + (dolby_vision_flags & + FLAG_PRIORITY_GRAPHIC)) + pri_mode = GRAPHIC_PRIORITY; + else + pri_mode = VIDEO_PRIORITY; + + if (dst_format == FORMAT_DOVI) { + if ((dolby_vision_flags + & FLAG_FORCE_DOVI_LL) || + (dolby_vision_ll_policy + >= DOLBY_VISION_LL_YUV422)) + new_dovi_setting.use_ll_flag = 1; + else + new_dovi_setting.use_ll_flag = 0; + if ((dolby_vision_ll_policy == + DOLBY_VISION_LL_RGB444) + || (dolby_vision_flags + & FLAG_FORCE_RGB_OUTPUT)) + new_dovi_setting.ll_rgb_desired = 1; + else + new_dovi_setting.ll_rgb_desired = 0; + } else { + new_dovi_setting.use_ll_flag = 0; + new_dovi_setting.ll_rgb_desired = 0; + } + if ((dst_format == FORMAT_HDR10) && + (dolby_vision_flags & FLAG_DOVI2HDR10_NOMAPPING)) + new_dovi_setting.dovi2hdr10_nomapping = 1; + else + new_dovi_setting.dovi2hdr10_nomapping = 0; + + /* always use rgb setting */ +#if 1 + new_dovi_setting.g_bitdepth = 8; + new_dovi_setting.g_format = GF_SDR_RGB; +#else + if (dolby_vision_flags & FLAG_CERTIFICAION) { + new_dovi_setting.g_bitdepth = 8; + new_dovi_setting.g_format = GF_SDR_RGB; + } else { + new_dovi_setting.g_bitdepth = 10; + new_dovi_setting.g_format = GF_SDR_YUV; + } +#endif + new_dovi_setting.diagnostic_enable = 0; + new_dovi_setting.diagnostic_mux_select = 0; + new_dovi_setting.dovi_ll_enable = 0; + if (vinfo) { + new_dovi_setting.vout_width = vinfo->width; + new_dovi_setting.vout_height = vinfo->height; + } else { + new_dovi_setting.vout_width = 0; + new_dovi_setting.vout_height = 0; + } + memset(&new_dovi_setting.ext_md, 0, sizeof(struct ext_md_s)); +#endif + new_dovi_setting.video_width = w << 16; + new_dovi_setting.video_height = h << 16; + flag = p_funcs->control_path( + src_format, dst_format, + comp_buf, total_comp_size, + md_buf, total_md_size, + pri_mode, + src_bdp, 0, SIG_RANGE_SMPTE, /* bit/chroma/range */ + graphic_min, + graphic_max * 10000, + dolby_vision_target_min, + dolby_vision_target_max[src_format][dst_format] * 10000, + (!el_flag) || + (dolby_vision_flags & FLAG_DISABLE_COMPOSER), + &hdr10_param, + &new_dovi_setting); + if (flag >= 0) { +#ifdef V2_4 + stb_core_setting_update_flag = flag; + if ((dolby_vision_flags + & FLAG_FORCE_DOVI_LL) + && (dst_format == FORMAT_DOVI)) + new_dovi_setting.dovi_ll_enable = 1; + if ((dolby_vision_flags + & FLAG_FORCE_RGB_OUTPUT) + && (dst_format == FORMAT_DOVI)) { + new_dovi_setting.dovi_ll_enable = 1; + new_dovi_setting.diagnostic_enable = 1; + new_dovi_setting.diagnostic_mux_select = 1; + } + if (debug_dolby & 2) + pr_dolby_dbg( + "ll_enable=%d,diagnostic=%d,ll_policy=%d\n", + new_dovi_setting.dovi_ll_enable, + new_dovi_setting.diagnostic_enable, + dolby_vision_ll_policy); +#endif + new_dovi_setting.src_format = src_format; + new_dovi_setting.dst_format = dst_format; + new_dovi_setting.el_flag = el_flag; + new_dovi_setting.el_halfsize_flag = el_halfsize_flag; + new_dovi_setting.video_width = w; + new_dovi_setting.video_height = h; + dovi_setting_video_flag = video_frame; + if (debug_dolby & 1) { + if (el_flag) + pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%02x,md=%d,comp=%d\n", + src_format, dst_format, + dolby_vision_target_min, + dolby_vision_target_max[src_format][dst_format], + flag, + total_md_size, total_comp_size); + else + pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%02x,md=%d\n", + src_format, dst_format, + dolby_vision_target_min, + dolby_vision_target_max[src_format][dst_format], + flag, + total_md_size); + } + dump_setting(&new_dovi_setting, frame_count, debug_dolby); + el_mode = el_flag; + return 0; /* setting updated */ + } + if (flag < 0) { + new_dovi_setting.video_width = 0; + new_dovi_setting.video_height = 0; + pr_dolby_error("control_path() failed\n"); + } + return -1; /* do nothing for this frame */ +} +EXPORT_SYMBOL(dolby_vision_parse_metadata); + +/* 0: no el; >0: with el */ +/* 1: need wait el vf */ +/* 2: no match el found */ +/* 3: found match el */ +int dolby_vision_wait_metadata(struct vframe_s *vf) +{ + struct provider_aux_req_s req; + struct vframe_s *el_vf; + int ret = 0; + unsigned int mode; + + if (single_step_enable) + if (dolby_vision_flags & FLAG_SINGLE_STEP) + /* wait fake el for "step" */ + return 1; + if (single_step_enable) + if (!(dolby_vision_flags & FLAG_SINGLE_STEP)) + dolby_vision_flags |= FLAG_SINGLE_STEP; + if (dolby_vision_flags & FLAG_CERTIFICAION) { + bool ott_mode = true; + + if (is_meson_txlx_package_962X() + && !force_stb_mode) + ott_mode = + (((struct tv_dovi_setting_s *) + tv_dovi_setting)->input_mode != + INPUT_MODE_HDMI); + if ((setting_update_count > crc_count) + && (ott_mode == true)) + return 1; + } + + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + + if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) + vf_notify_provider_by_name("dvbldec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + if (req.dv_enhance_exist) { + el_vf = dvel_vf_peek(); + while (el_vf) { + if (debug_dolby & 2) + pr_dolby_dbg("=== peek bl(%p-%lld) with el(%p-%lld) ===\n", + vf, vf->pts_us64, + el_vf, el_vf->pts_us64); + if ((el_vf->pts_us64 == vf->pts_us64) + || !(dolby_vision_flags & FLAG_CHECK_ES_PTS)) { + /* found el */ + ret = 3; + break; + } else if (el_vf->pts_us64 < vf->pts_us64) { + if (debug_dolby & 2) + pr_dolby_dbg("bl(%p-%lld) => skip el pts(%p-%lld)\n", + vf, vf->pts_us64, + el_vf, el_vf->pts_us64); + el_vf = dvel_vf_get(); + dvel_vf_put(el_vf); + vf_notify_provider(DVEL_RECV_NAME, + VFRAME_EVENT_RECEIVER_PUT, NULL); + if (debug_dolby & 2) + pr_dolby_dbg("=== get & put el(%p-%lld) ===\n", + el_vf, el_vf->pts_us64); + + /* skip old el and peek new */ + el_vf = dvel_vf_peek(); + } else { + /* no el found */ + ret = 2; + break; + } + } + /* need wait el */ + if (el_vf == NULL) { + if (debug_dolby & 2) + pr_dolby_dbg( + "=== bl wait el(%p-%lld) ===\n", + vf, vf->pts_us64); + ret = 1; + } + } + if (ret == 1) + return ret; + + if (!dolby_vision_wait_init + && !dolby_vision_core1_on) { + if (is_dovi_frame(vf)) { + if (dolby_vision_policy_process( + &mode, FORMAT_DOVI)) { + if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) + && (dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_BYPASS)) { + dolby_vision_wait_init = true; + dolby_vision_wait_count = + dolby_vision_wait_delay; + dolby_vision_wait_on = true; + } + } + } else if (is_hdr10_frame(vf)) { + if (dolby_vision_policy_process( + &mode, FORMAT_HDR10)) { + if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) + && (dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_BYPASS)) { + dolby_vision_wait_init = true; + dolby_vision_wait_count = + dolby_vision_wait_delay; + dolby_vision_wait_on = true; + } + } + } else if (dolby_vision_policy_process( + &mode, FORMAT_SDR)) { + if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) + && (dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_BYPASS)) { + dolby_vision_wait_init = true; + dolby_vision_wait_count = + dolby_vision_wait_delay; + dolby_vision_wait_on = true; + } + } + /* don't use run mode when sdr -> dv and vd1 not disable */ + if (dolby_vision_wait_init && + (READ_VPP_REG(VPP_MISC) & (1<<10))) + dolby_vision_on_count = + dolby_vision_run_mode_delay + 1; + } + if (dolby_vision_wait_init + && dolby_vision_wait_count) { + dolby_vision_wait_count--; + pr_dolby_dbg("delay wait %d\n", + dolby_vision_wait_count); + ret = 1; + } else if (dolby_vision_core1_on + && (dolby_vision_on_count <= + dolby_vision_run_mode_delay)) + ret = 1; + + return ret; +} + +int dolby_vision_update_metadata(struct vframe_s *vf) +{ + int ret = -1; + + if (!dolby_vision_enable) + return -1; + if (vf && dolby_vision_vf_check(vf)) { + ret = dolby_vision_parse_metadata( + vf, 1, false); + frame_count++; + } + + return ret; +} +EXPORT_SYMBOL(dolby_vision_update_metadata); + +static void update_dolby_vision_status(enum signal_format_e src_format) +{ + if (((src_format == FORMAT_DOVI) + || (src_format == FORMAT_DOVI_LL)) + && (dolby_vision_status != DV_PROCESS)) { + pr_dolby_dbg( + "Dolby Vision mode changed to DV_PROCESS %d\n", + src_format); + dolby_vision_status = DV_PROCESS; + } else if ((src_format == FORMAT_HDR10) + && (dolby_vision_status != HDR_PROCESS)) { + pr_dolby_dbg( + "Dolby Vision mode changed to HDR_PROCESS %d\n", + src_format); + dolby_vision_status = HDR_PROCESS; + } else if ((src_format == FORMAT_SDR) + && (dolby_vision_status != SDR_PROCESS)) { + pr_dolby_dbg( + "Dolby Vision mode changed to SDR_PROCESS %d\n", + src_format); + dolby_vision_status = SDR_PROCESS; + } +} + +static unsigned int last_dolby_vision_policy; +int dolby_vision_process(struct vframe_s *vf, u32 display_size) +{ + int src_chroma_format = 0; + u32 h_size = (display_size >> 16) & 0xffff; + u32 v_size = display_size & 0xffff; + const struct vinfo_s *vinfo = get_current_vinfo(); + bool reset_flag = false; + bool force_set = false; + + if (!is_meson_gxm_cpu() && !is_meson_txlx_cpu() + && !(get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A)) + return -1; + + if (dolby_vision_flags & FLAG_CERTIFICAION) { + if (vf) { + h_size = (vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width; + v_size = (vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height; + } else { + h_size = 0; + v_size = 0; + } + dolby_vision_on_count = 1 + + dolby_vision_run_mode_delay; + } + + if ((core1_disp_hsize != h_size) + || (core1_disp_vsize != v_size)) + force_set = true; + + if ((dolby_vision_flags & FLAG_CERTIFICAION) + && (setting_update_count > crc_count) + && is_dolby_vision_on()) { + s32 delay_count = + (dolby_vision_flags >> + FLAG_FRAME_DELAY_SHIFT) + & FLAG_FRAME_DELAY_MASK; + bool ott_mode = true; + + if (is_meson_txlx_package_962X() + && !force_stb_mode) + ott_mode = + (((struct tv_dovi_setting_s *) + tv_dovi_setting)->input_mode != + INPUT_MODE_HDMI); + if ((is_meson_txlx_package_962E() + || is_meson_gxm_cpu() + || (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) + || force_stb_mode) + && (setting_update_count == 1) + && (crc_read_delay == 1)) { + /* work around to enable crc for frame 0 */ + VSYNC_WR_MPEG_REG(0x36fb, 1); + crc_read_delay++; + } else { + crc_read_delay++; + if ((crc_read_delay > delay_count) + && (ott_mode == true)) { + tv_dolby_vision_insert_crc( + (crc_count == 0) ? true : false); + crc_read_delay = 0; + } + } + } + + if (dolby_vision_on + && is_video_output_off(vf) + && !video_off_handled) { + dolby_vision_set_toggle_flag(1); + frame_count = 0; + pr_dolby_dbg("video off\n"); + if (debug_dolby) + video_off_handled = 1; + } + + if (last_dolby_vision_policy != dolby_vision_policy) { + /* handle policy change */ + dolby_vision_set_toggle_flag(1); + last_dolby_vision_policy = dolby_vision_policy; + } + +#ifdef V2_4 + if (is_meson_txlx_package_962E() + || is_meson_gxm_cpu() + || (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A) + || force_stb_mode) { + if (last_dolby_vision_ll_policy + != dolby_vision_ll_policy) { + /* handle ll mode policy change */ + dolby_vision_set_toggle_flag(1); + } + } +#endif + if (!vf) { + if (dolby_vision_flags & FLAG_TOGGLE_FRAME) + dolby_vision_parse_metadata( + NULL, 1, false); + } + if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { + if (vinfo && sink_support_dolby_vision(vinfo)) + dolby_vision_set_toggle_flag(1); + if (!is_meson_txlx_package_962X() || force_stb_mode) { + if (vinfo && vinfo->vout_device && + (!vinfo->vout_device->dv_info) + && (vsync_count < FLAG_VSYNC_CNT)) { + vsync_count++; + return 0; + } + } + if (dolby_vision_status != BYPASS_PROCESS) { + enable_dolby_vision(0); + if (vinfo && + !is_meson_txlx_package_962X() && + !force_stb_mode) + send_hdmi_pkt(FORMAT_SDR, vinfo); + if (dolby_vision_flags & FLAG_TOGGLE_FRAME) + dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; + } + return 0; + } + + if (dolby_vision_flags & FLAG_CERTIFICAION) + video_effect_bypass(1); + + if (!p_funcs) { + dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; + tv_dovi_setting_change_flag = false; + new_dovi_setting.video_width = 0; + new_dovi_setting.video_height = 0; + return 0; + } + if ((debug_dolby & 2) && force_set + && !(dolby_vision_flags & FLAG_CERTIFICAION)) + pr_dolby_dbg( + "core1 size changed--old: %d x %d, new: %d x %d\n", + core1_disp_hsize, core1_disp_vsize, + h_size, v_size); + if (dolby_vision_flags & FLAG_TOGGLE_FRAME) { + if (!(dolby_vision_flags & FLAG_CERTIFICAION)) + reset_flag = + (dolby_vision_reset & 1) + && (!dolby_vision_core1_on) + && (dolby_vision_on_count == 0); + if (is_meson_txlx_package_962X() && !force_stb_mode) { + if (tv_dovi_setting_change_flag) { + if (vf && (vf->type & VIDTYPE_VIU_422)) + src_chroma_format = 2; + else if (vf) + src_chroma_format = 1; + if (force_set && + !(dolby_vision_flags + & FLAG_CERTIFICAION)) + reset_flag = true; + tv_dolby_core1_set( + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->core1_reg_lut, + h_size, + v_size, + dovi_setting_video_flag, /* BL enable */ + dovi_setting_video_flag + && (((struct tv_dovi_setting_s *) + tv_dovi_setting)->el_flag), /* EL en */ + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->el_halfsize_flag, + src_chroma_format, + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->input_mode == + INPUT_MODE_HDMI, + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->src_format == + FORMAT_HDR10, + reset_flag + ); + if (!h_size || !v_size) + dovi_setting_video_flag = false; + if (dovi_setting_video_flag + && (dolby_vision_on_count == 0)) + pr_dolby_dbg("first frame reset %d\n", + reset_flag); + enable_dolby_vision(1); + tv_dovi_setting_change_flag = false; + core1_disp_hsize = h_size; + core1_disp_vsize = v_size; + update_dolby_vision_status( + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->src_format); + } + } else { + if ((new_dovi_setting.video_width & 0xffff) + && (new_dovi_setting.video_height & 0xffff)) { + if (force_set && + !(dolby_vision_flags + & FLAG_CERTIFICAION)) + reset_flag = true; + apply_stb_core_settings( + dovi_setting_video_flag, + dolby_vision_mask & 0x7, + reset_flag, + (h_size << 16) | v_size); + memcpy(&dovi_setting, &new_dovi_setting, + sizeof(dovi_setting)); + new_dovi_setting.video_width = + new_dovi_setting.video_height = 0; + if (!h_size || !v_size) + dovi_setting_video_flag = false; + if (dovi_setting_video_flag + && (dolby_vision_on_count == 0)) + pr_dolby_dbg("first frame reset %d\n", + reset_flag); + enable_dolby_vision(1); + core1_disp_hsize = h_size; + core1_disp_vsize = v_size; + /* send HDMI packet according to dst_format */ + if (vinfo && !force_stb_mode) + send_hdmi_pkt( + dovi_setting.dst_format, vinfo); + update_dolby_vision_status( + dovi_setting.src_format); + } + } + dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; + } else if (dolby_vision_core1_on && + !(dolby_vision_flags & FLAG_CERTIFICAION)) { + bool reset_flag = + (dolby_vision_reset & 2) + && (dolby_vision_on_count + <= (dolby_vision_reset_delay >> 8)) + && (dolby_vision_on_count + >= (dolby_vision_reset_delay & 0xff)); + if (is_meson_txlx_package_962E() + || force_stb_mode) { + if ((dolby_vision_on_count <= + dolby_vision_run_mode_delay) + || force_set) { + if (force_set) + reset_flag = true; + apply_stb_core_settings( + dovi_setting_video_flag, + /* core 1 only */ + dolby_vision_mask & 0x1, + reset_flag, + (h_size << 16) | v_size); + core1_disp_hsize = h_size; + core1_disp_vsize = v_size; + if (dolby_vision_on_count <= + dolby_vision_run_mode_delay) + pr_dolby_dbg("fake frame %d reset %d\n", + dolby_vision_on_count, + reset_flag); + } + } else if (is_meson_txlx_package_962X()) { + if ((dolby_vision_on_count <= + dolby_vision_run_mode_delay) + || force_set) { + if (force_set) + reset_flag = true; + tv_dolby_core1_set( + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->core1_reg_lut, + h_size, + v_size, + dovi_setting_video_flag, /* BL enable */ + dovi_setting_video_flag && + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->el_flag, /*ELenable*/ + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->el_halfsize_flag, + src_chroma_format, + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->input_mode == + INPUT_MODE_HDMI, + ((struct tv_dovi_setting_s *) + tv_dovi_setting)->src_format == + FORMAT_HDR10, + reset_flag); + core1_disp_hsize = h_size; + core1_disp_vsize = v_size; + if (dolby_vision_on_count <= + dolby_vision_run_mode_delay) + pr_dolby_dbg("fake frame %d reset %d\n", + dolby_vision_on_count, + reset_flag); + } + } else if (is_meson_gxm_cpu() || + (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A)) { + if ((dolby_vision_on_count <= + dolby_vision_run_mode_delay) + || force_set) { + if (force_set) + reset_flag = true; + apply_stb_core_settings( + true, /* always enable */ + /* core 1 only */ + dolby_vision_mask & 0x1, + reset_flag, + (h_size << 16) | v_size); + core1_disp_hsize = h_size; + core1_disp_vsize = v_size; + if (dolby_vision_on_count < + dolby_vision_run_mode_delay) + pr_dolby_dbg("fake frame %d reset %d\n", + dolby_vision_on_count, + reset_flag); + } + } + } + if (dolby_vision_core1_on) { + if (dolby_vision_on_count <= + dolby_vision_run_mode_delay) + dolby_vision_on_count++; + } else + dolby_vision_on_count = 0; + return 0; +} +EXPORT_SYMBOL(dolby_vision_process); + +bool is_dolby_vision_on(void) +{ + return dolby_vision_on + || dolby_vision_wait_on; +} +EXPORT_SYMBOL(is_dolby_vision_on); + +bool for_dolby_vision_certification(void) +{ + return is_dolby_vision_on() && + dolby_vision_flags & FLAG_CERTIFICAION; +} +EXPORT_SYMBOL(for_dolby_vision_certification); + +void dolby_vision_set_toggle_flag(int flag) +{ + if (flag) + dolby_vision_flags |= FLAG_TOGGLE_FRAME; + else + dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; +} +EXPORT_SYMBOL(dolby_vision_set_toggle_flag); + +void set_dolby_vision_mode(int mode) +{ + if ((is_meson_gxm_cpu() || is_meson_txlx_cpu() || + (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A)) + && dolby_vision_enable) { + if (dolby_vision_policy_process( + &mode, FORMAT_SDR)) { + dolby_vision_set_toggle_flag(1); + if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) + && (dolby_vision_mode == + DOLBY_VISION_OUTPUT_MODE_BYPASS)) + dolby_vision_wait_on = true; + pr_info("DOVI output change from %d to %d\n", + dolby_vision_mode, mode); + dolby_vision_mode = mode; + } + } +} +EXPORT_SYMBOL(set_dolby_vision_mode); + +int get_dolby_vision_mode(void) +{ + return dolby_vision_mode; +} +EXPORT_SYMBOL(get_dolby_vision_mode); + +bool is_dolby_vision_enable(void) +{ + return dolby_vision_enable; +} +EXPORT_SYMBOL(is_dolby_vision_enable); + +bool is_dolby_vision_stb_mode(void) +{ + return force_stb_mode || + is_meson_txlx_package_962E() || + is_meson_gxm_cpu() || + (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A); +} +EXPORT_SYMBOL(is_dolby_vision_stb_mode); + +int register_dv_functions(const struct dolby_vision_func_s *func) +{ + int ret = -1; + unsigned int reg_clk; + unsigned int reg_value; + struct pq_config_s *pq_config; + struct tv_dovi_setting_s *dovi_setting; + if (!p_funcs && func) { + pr_info("*** register_dv_functions. version %s ***\n", + func->version_info); + p_funcs = func; + ret = 0; + /* get efuse flag*/ + reg_clk = READ_VPP_REG(DOLBY_TV_CLKGATE_CTRL); + WRITE_VPP_REG(DOLBY_TV_CLKGATE_CTRL, 0x2800); + reg_value = READ_VPP_REG(DOLBY_TV_REG_START + 1); + if (is_meson_txlx_package_962X() + || is_meson_txlx_package_962E()) { + if ((reg_value & 0x400) == 0) + efuse_mode = 0; + else + efuse_mode = 1; + } else { + if ((reg_value & 0x100) == 0) + efuse_mode = 0; + else + efuse_mode = 1; + } + efuse_mode = 0;/*for g12a tmp*/ + WRITE_VPP_REG(DOLBY_TV_CLKGATE_CTRL, reg_clk); + pr_dolby_dbg + ("efuse_mode=%d reg_value = 0x%x\n", + efuse_mode, + reg_value); + if (is_meson_gxm_cpu() || + (get_cpu_type() == + MESON_CPU_MAJOR_ID_G12A)) + dolby_vision_run_mode_delay = 3; + pq_config = vmalloc(sizeof(pq_config)); + pq_config_fake = (struct pq_config_s *)pq_config; + dovi_setting = vmalloc(sizeof(dovi_setting)); + tv_dovi_setting = (struct tv_dovi_setting_s *)dovi_setting; + } + return ret; +} +EXPORT_SYMBOL(register_dv_functions); + +int unregister_dv_functions(void) +{ + int ret = -1; + + if (p_funcs) { + pr_info("*** unregister_dv_functions ***\n"); + if (pq_config_fake) { + vfree(pq_config_fake); + pq_config_fake = NULL; + } + if (tv_dovi_setting) { + vfree(tv_dovi_setting); + tv_dovi_setting = NULL; + } + p_funcs = NULL; + ret = 0; + } + return ret; +} +EXPORT_SYMBOL(unregister_dv_functions); + +void tv_dolby_vision_crc_clear(int flag) +{ + crc_outpuf_buff_off = 0; + crc_count = 0; + crc_bypass_count = 0; + setting_update_count = 0; + if (!crc_output_buf) + crc_output_buf = vmalloc(CRC_BUFF_SIZE); + pr_info( + "tv_dolby_vision_crc_clear, crc_output_buf %p\n", + crc_output_buf); + if (crc_output_buf) + memset(crc_output_buf, 0, CRC_BUFF_SIZE); +} + +char *tv_dolby_vision_get_crc(u32 *len) +{ + if ((!crc_output_buf) || + (!len) || + (crc_outpuf_buff_off == 0)) + return NULL; + *len = crc_outpuf_buff_off; + return crc_output_buf; +} + +void tv_dolby_vision_insert_crc(bool print) +{ + char str[64]; + int len; + bool crc_enable; + u32 crc; + + if (dolby_vision_flags & FLAG_DISABLE_CRC) { + crc_bypass_count++; + crc_count++; + return; + } + if (is_meson_txlx_package_962X() + && !force_stb_mode) { + crc_enable = (READ_VPP_REG(0x33e7) == 0xb); + crc = READ_VPP_REG(0x33ef); + } else { + crc_enable = true; /* (READ_VPP_REG(0x36fb) & 1); */ + crc = READ_VPP_REG(0x36fd); + } + if ((crc == 0) || (crc_enable == false) || (!crc_output_buf)) { + crc_bypass_count++; + crc_count++; + return; + } + if (crc_count < crc_bypass_count) + crc_bypass_count = crc_count; + memset(str, 0, sizeof(str)); + snprintf(str, 64, "crc(%d) = 0x%08x", + crc_count - crc_bypass_count, crc); + len = strlen(str); + str[len] = 0xa; + len++; + memcpy( + &crc_output_buf[crc_outpuf_buff_off], + &str[0], len); + crc_outpuf_buff_off += len; + if (print || (debug_dolby & 2)) + pr_info("%s\n", str); + crc_count++; +} + +void tv_dolby_vision_dma_table_modify(u32 tbl_id, uint64_t value) +{ + uint64_t *tbl = NULL; + + if (!dma_vaddr || (tbl_id >= 3754)) { + pr_info("No dma table %p to write or id %d overflow\n", + dma_vaddr, tbl_id); + return; + } + tbl = (uint64_t *)dma_vaddr; + pr_info("dma_vaddr:%p, modify table[%d]=0x%llx -> 0x%llx\n", + dma_vaddr, tbl_id, tbl[tbl_id], value); + tbl[tbl_id] = value; +} + +void tv_dolby_vision_efuse_info(void) +{ + if (p_funcs != NULL) { + pr_info("\n dv efuse info:\n"); + pr_info("efuse_mode:%d, version: %s\n", + efuse_mode, p_funcs->version_info); + } else { + pr_info("\n p_funcs is NULL\n"); + pr_info("efuse_mode:%d\n", efuse_mode); + } +} + +void tv_dolby_vision_el_info(void) +{ + pr_info("el_mode:%d\n", el_mode); +} + +static int amdolby_vision_open(struct inode *inode, struct file *file) +{ + struct amdolby_vision_dev_s *devp; + /* Get the per-device structure that contains this cdev */ + devp = container_of(inode->i_cdev, struct amdolby_vision_dev_s, cdev); + file->private_data = devp; + return 0; + +} + +static char *pq_config_buf; +static uint32_t pq_config_level; +static ssize_t amdolby_vision_write( + struct file *file, + const char *buf, + size_t len, + loff_t *off) +{ + int i; + + if (pq_config_buf == NULL) { + pq_config_buf = vmalloc(108*1024); + pq_config_level = 0; + if (pq_config_buf == NULL) + return -ENOSPC; + } + for (i = 0; i < len; i++) { + pq_config_buf[pq_config_level] = buf[i]; + pq_config_level++; + if (pq_config_level == sizeof(struct pq_config_s)) { + dolby_vision_update_pq_config(pq_config_buf); + pq_config_level = 0; + break; + } + } + if (len <= 0x1f) { + dolby_vision_update_vsvdb_config( + pq_config_buf, len); + pq_config_level = 0; + } + return len; +} + +static ssize_t amdolby_vision_read( + struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + char *out; + u32 data_size = 0, res, retVal = 0; + + if (!is_dolby_vision_enable()) + return retVal; + out = tv_dolby_vision_get_crc(&data_size); + if (out && data_size > 0) { + res = copy_to_user((void *)buf, + (void *)out, + data_size); + retVal = data_size - res; + pr_info( + "amdolby_vision_read crc size %d, res: %d, ret: %d\n", + data_size, res, retVal); + tv_dolby_vision_crc_clear(0); + } + return retVal; +} + +static int amdolby_vision_release(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return 0; +} + +static long amdolby_vision_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return 0; +} + + +#ifdef CONFIG_COMPAT +static long amdolby_vision_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned long ret; + + arg = (unsigned long)compat_ptr(arg); + ret = amdolby_vision_ioctl(file, cmd, arg); + return ret; +} +#endif + +static const struct file_operations amdolby_vision_fops = { + .owner = THIS_MODULE, + .open = amdolby_vision_open, + .write = amdolby_vision_write, + .read = amdolby_vision_read, + .release = amdolby_vision_release, + .unlocked_ioctl = amdolby_vision_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amdolby_vision_compat_ioctl, +#endif +}; + +static void parse_param_amdolby_vision(char *buf_orig, char **parm) +{ + char *ps, *token; + unsigned int n = 0; + char delim1[3] = " "; + char delim2[2] = "\n"; + + ps = buf_orig; + strcat(delim1, delim2); + while (1) { + token = strsep(&ps, delim1); + if (token == NULL) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } +} + +static const char *amdolby_vision_debug_usage_str = { + "Usage:\n" + "echo dolby_crc 0/1 > /sys/class/amdolby_vision/debug; dolby_crc insert or clr\n" + "echo dolby_dma index(D) value(H) > /sys/class/amdolby_vision/debug; dolby dma table modify\n" + "echo dv_efuse > /sys/class/amdolby_vision/debug; get dv efuse info\n" + "echo dv_el > /sys/class/amdolby_vision/debug; get dv enhanced layer info\n" +}; +static ssize_t amdolby_vision_debug_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", amdolby_vision_debug_usage_str); +} + +static ssize_t amdolby_vision_debug_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + char *buf_orig, *parm[8] = {NULL}; + long val = 0; + + if (!buf) + return count; + buf_orig = kstrdup(buf, GFP_KERNEL); + parse_param_amdolby_vision(buf_orig, (char **)&parm); + if (!strcmp(parm[0], "dolby_crc")) { + if (kstrtoul(parm[1], 10, &val) < 0) + return -EINVAL; + if (val == 1) + tv_dolby_vision_crc_clear(val); + else + tv_dolby_vision_insert_crc(true); + } else if (!strcmp(parm[0], "dolby_dma")) { + long tbl_id; + long value; + + if (kstrtoul(parm[1], 10, &tbl_id) < 0) + return -EINVAL; + if (kstrtoul(parm[2], 16, &value) < 0) + return -EINVAL; + tv_dolby_vision_dma_table_modify((u32)tbl_id, (uint64_t)value); + } else if (!strcmp(parm[0], "dv_efuse")) { + tv_dolby_vision_efuse_info(); + } else if (!strcmp(parm[0], "dv_el")) { + tv_dolby_vision_el_info(); + } else { + pr_info("unsupport cmd\n"); + } + + kfree(buf_orig); + return count; +} + +/* supported mode: IPT_TUNNEL/HDR10/SDR10 */ +static const int dv_mode_table[6] = { + 5, /*DOLBY_VISION_OUTPUT_MODE_BYPASS*/ + 0, /*DOLBY_VISION_OUTPUT_MODE_IPT*/ + 1, /*DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL*/ + 2, /*DOLBY_VISION_OUTPUT_MODE_HDR10*/ + 3, /*DOLBY_VISION_OUTPUT_MODE_SDR10*/ + 4, /*DOLBY_VISION_OUTPUT_MODE_SDR8*/ +}; + +static const char dv_mode_str[6][12] = { + "IPT", + "IPT_TUNNEL", + "HDR10", + "SDR10", + "SDR8", + "BYPASS" +}; + +static ssize_t amdolby_vision_dv_mode_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + pr_info("usage: echo mode > /sys/class/amdolby_vision/dv_mode\n"); + pr_info("\tDOLBY_VISION_OUTPUT_MODE_BYPASS 0\n"); + pr_info("\tDOLBY_VISION_OUTPUT_MODE_IPT 1\n"); + pr_info("\tDOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL 2\n"); + pr_info("\tDOLBY_VISION_OUTPUT_MODE_HDR10 3\n"); + pr_info("\tDOLBY_VISION_OUTPUT_MODE_SDR10 4\n"); + pr_info("\tDOLBY_VISION_OUTPUT_MODE_SDR8 5\n"); + if (is_dolby_vision_enable()) + pr_info("current dv_mode = %s\n", + dv_mode_str[get_dolby_vision_mode()]); + else + pr_info("current dv_mode = off\n"); + return 0; +} +static ssize_t amdolby_vision_dv_mode_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + size_t r; + int val; + + r = kstrtoint(buf, 0, &val); + if (r != 0) + return -EINVAL; + + if ((val >= 0) && (val < 6)) + set_dolby_vision_mode(dv_mode_table[val]); + else if (val & 0x200) + dolby_vision_dump_struct(); + else if (val & 0x70) + dolby_vision_dump_setting(val); + return count; +} + + +static struct class_attribute amdolby_vision_class_attrs[] = { + __ATTR(debug, 0644, + amdolby_vision_debug_show, amdolby_vision_debug_store), + __ATTR(dv_mode, 0644, + amdolby_vision_dv_mode_show, amdolby_vision_dv_mode_store), + __ATTR_NULL +}; + +static int amdolby_vision_probe(struct platform_device *pdev) +{ + int ret = 0; + int i = 0; + struct amdolby_vision_dev_s *devp = &amdolby_vision_dev; + + pr_info("\n amdolby_vision probe start\n"); + memset(devp, 0, (sizeof(struct amdolby_vision_dev_s))); + ret = alloc_chrdev_region(&devp->devno, 0, 1, AMDOLBY_VISION_NAME); + if (ret < 0) + goto fail_alloc_region; + devp->clsp = class_create(THIS_MODULE, + AMDOLBY_VISION_CLASS_NAME); + if (IS_ERR(devp->clsp)) { + ret = PTR_ERR(devp->clsp); + goto fail_create_class; + } + for (i = 0; amdolby_vision_class_attrs[i].attr.name; i++) { + if (class_create_file(devp->clsp, + &amdolby_vision_class_attrs[i]) < 0) + goto fail_class_create_file; + } + cdev_init(&devp->cdev, &amdolby_vision_fops); + devp->cdev.owner = THIS_MODULE; + ret = cdev_add(&devp->cdev, devp->devno, 1); + if (ret) + goto fail_add_cdev; + + devp->dev = device_create(devp->clsp, NULL, devp->devno, + NULL, AMDOLBY_VISION_NAME); + if (IS_ERR(devp->dev)) { + ret = PTR_ERR(devp->dev); + goto fail_create_device; + } + + dolby_vision_init_receiver(pdev); + pr_info("%s: ok\n", __func__); + return 0; + +fail_create_device: + pr_info("[amdolby_vision.] : amdolby_vision device create error.\n"); + cdev_del(&devp->cdev); +fail_add_cdev: + pr_info("[amdolby_vision.] : amdolby_vision add device error.\n"); +fail_class_create_file: + pr_info("[amdolby_vision.] : amdolby_vision class create file error.\n"); + for (i = 0; amdolby_vision_class_attrs[i].attr.name; i++) { + class_remove_file(devp->clsp, + &amdolby_vision_class_attrs[i]); + } + class_destroy(devp->clsp); +fail_create_class: + pr_info("[amdolby_vision.] : amdolby_vision class create error.\n"); + unregister_chrdev_region(devp->devno, 1); +fail_alloc_region: + pr_info("[amdolby_vision.] : amdolby_vision alloc error.\n"); + pr_info("[amdolby_vision.] : amdolby_vision_init.\n"); + return ret; + + +} + +static int __exit amdolby_vision_remove(struct platform_device *pdev) +{ + struct amdolby_vision_dev_s *devp = &amdolby_vision_dev; + + if (pq_config_buf) { + vfree(pq_config_buf); + pq_config_buf = NULL; + } + + device_destroy(devp->clsp, devp->devno); + cdev_del(&devp->cdev); + class_destroy(devp->clsp); + unregister_chrdev_region(devp->devno, 1); + pr_info("[ amdolby_vision.] : amdolby_vision_exit.\n"); + return 0; +} + + +static const struct of_device_id amlogic_dolby_vision_match[] = { + { + .compatible = "amlogic, aml_amdolby_vision_driver", + }, + {}, +}; + +static struct platform_driver aml_amdolby_vision_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "aml_amdolby_vision_driver", + .of_match_table = amlogic_dolby_vision_match, + }, + .probe = amdolby_vision_probe, + .remove = __exit_p(amdolby_vision_remove), +}; + +static int __init amdolby_vision_init(void) +{ + pr_info("%s:module init\n", __func__); + + if (platform_driver_register(&aml_amdolby_vision_driver)) { + pr_err("failed to register amdolby_vision module\n"); + return -ENODEV; + } + return 0; +} + +static void __exit amdolby_vision_exit(void) +{ + pr_info("%s:module exit\n", __func__); + platform_driver_unregister(&aml_amdolby_vision_driver); +} + +module_init(amdolby_vision_init); +module_exit(amdolby_vision_exit); + +MODULE_DESCRIPTION("AMLOGIC amdolby_vision driver"); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h new file mode 100644 index 000000000000..4e07d5e882bc --- /dev/null +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h @@ -0,0 +1,623 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/dolby_vision/amdolby_vision.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ +#ifndef _AMDV_H_ +#define _AMDV_H_ + +#define V1_5 +#define V2_4 + +#include + +#define DEF_G2L_LUT_SIZE_2P 8 +#define DEF_G2L_LUT_SIZE (1 << DEF_G2L_LUT_SIZE_2P) + +#ifdef V2_4 +#define EXT_MD_AVAIL_LEVEL_1 (1 << 0) +#define EXT_MD_AVAIL_LEVEL_2 (1 << 1) +#define EXT_MD_AVAIL_LEVEL_4 (1 << 2) +#define EXT_MD_AVAIL_LEVEL_5 (1 << 3) +#define EXT_MD_AVAIL_LEVEL_6 (1 << 4) +#define EXT_MD_AVAIL_LEVEL_255 (1 << 31) +#endif +#define PQ2G_LUT_SIZE (4 + 1024 * 4 + 16 * 3) +#define GM_LUT_HDR_SIZE (13 + 2*9) +#define LUT_DIM 17 +#define GM_LUT_SIZE (3 * LUT_DIM * LUT_DIM * LUT_DIM * 2) +#define BACLIGHT_LUT_SIZE 4096 +#define TUNING_LUT_ENTRIES 14 + +#define TUNINGMODE_FORCE_ABSOLUTE 0x1 +#define TUNINGMODE_EXTLEVEL1_DISABLE 0x2 +#define TUNINGMODE_EXTLEVEL2_DISABLE 0x4 +#define TUNINGMODE_EXTLEVEL4_DISABLE 0x8 +#define TUNINGMODE_EXTLEVEL5_DISABLE 0x10 +#define TUNINGMODE_EL_FORCEDDISABLE 0x20 + +/*! @brief Output CSC configuration.*/ +# pragma pack(push, 1) +struct TgtOutCscCfg { + int32_t lms2RgbMat[3][3]; /**<@brief LMS to RGB matrix */ + int32_t lms2RgbMatScale; /**<@brief LMS 2 RGB matrix scale */ + uint8_t whitePoint[3]; /**<@brief White point */ + uint8_t whitePointScale; /**<@brief White point scale */ + int32_t reserved[3]; +}; +#pragma pack(pop) + +/*! @brief Global dimming configuration.*/ +# pragma pack(push, 1) +struct TgtGDCfg { + int32_t gdEnable; + uint32_t gdWMin; + uint32_t gdWMax; + uint32_t gdWMm; + uint32_t gdWDynRngSqrt; + uint32_t gdWeightMean; + uint32_t gdWeightStd; + uint32_t gdDelayMilliSec_hdmi; + int32_t gdRgb2YuvExt; + int32_t gdM33Rgb2Yuv[3][3]; + int32_t gdM33Rgb2YuvScale2P; + int32_t gdRgb2YuvOffExt; + int32_t gdV3Rgb2YuvOff[3]; + uint32_t gdUpBound; + uint32_t gdLowBound; + uint32_t lastMaxPq; + uint16_t gdWMinPq; + uint16_t gdWMaxPq; + uint16_t gdWMmPq; + uint16_t gdTriggerPeriod; + uint32_t gdTriggerLinThresh; + uint32_t gdDelayMilliSec_ott; +#ifdef V1_5 + uint32_t reserved[6]; +#else + uint32_t reserved[9]; +#endif +}; +#pragma pack(pop) + +/*! @defgroup general Enumerations and data structures*/ +# pragma pack(push, 1) +struct TargetDisplayConfig { + uint16_t gain; + uint16_t offset; + uint16_t gamma; /**<@brief Gamma */ + uint16_t eotf; + uint16_t bitDepth; /**<@brief Bit Depth */ + uint16_t rangeSpec; + uint16_t diagSize; /**<@brief Diagonal Size */ + uint16_t maxPq; + uint16_t minPq; + uint16_t mSWeight; + uint16_t mSEdgeWeight; + int16_t minPQBias; + int16_t midPQBias; + int16_t maxPQBias; + int16_t trimSlopeBias; + int16_t trimOffsetBias; + int16_t trimPowerBias; + int16_t msWeightBias; + int16_t brightness; /**<@brief Brighness */ + int16_t contrast; /**<@brief Contrast */ + int16_t chromaWeightBias; + int16_t saturationGainBias; + uint16_t chromaWeight; + uint16_t saturationGain; + uint16_t crossTalk; + uint16_t tuningMode; + int16_t reserved0; + int16_t dbgExecParamsPrintPeriod; + int16_t dbgDmMdPrintPeriod; + int16_t dbgDmCfgPrintPeriod; + uint16_t maxPq_dupli; + uint16_t minPq_dupli; + int32_t keyWeight; + int32_t intensityVectorWeight; + int32_t chromaVectorWeight; + int16_t chip_fpga_lowcomplex; + int16_t midPQBiasLut[TUNING_LUT_ENTRIES]; + int16_t saturationGainBiasLut[TUNING_LUT_ENTRIES]; + int16_t chromaWeightBiasLut[TUNING_LUT_ENTRIES]; + int16_t slopeBiasLut[TUNING_LUT_ENTRIES]; + int16_t offsetBiasLut[TUNING_LUT_ENTRIES]; + int16_t backlightBiasLut[TUNING_LUT_ENTRIES]; + struct TgtGDCfg gdConfig; +#ifdef V1_5 + uint8_t vsvdb[7]; + uint8_t reserved1[5]; +#endif + int32_t min_lin; + int32_t max_lin; + int16_t backlight_scaler; + int32_t min_lin_dupli; + int32_t max_lin_dupli; + struct TgtOutCscCfg ocscConfig; +#ifdef V1_5 + int16_t reserved2; +#else + int16_t reserved00; +#endif + int16_t brightnessPreservation; + int32_t iintensityVectorWeight; + int32_t ichromaVectorWeight; + int16_t isaturationGainBias; + int16_t chip_12b_ocsc; + int16_t chip_512_tonecurve; + int16_t chip_nolvl5; + int16_t padding[8]; +}; +#pragma pack(pop) + +/*! @brief PQ config main data structure.*/ +struct pq_config_s { + unsigned char default_gm_lut[GM_LUT_HDR_SIZE + GM_LUT_SIZE]; + unsigned char gd_gm_lut_min[GM_LUT_HDR_SIZE + GM_LUT_SIZE]; + unsigned char gd_gm_lut_max[GM_LUT_HDR_SIZE + GM_LUT_SIZE]; + unsigned char pq2gamma[sizeof(int32_t)*PQ2G_LUT_SIZE]; + unsigned char backlight_lut[BACLIGHT_LUT_SIZE]; + struct TargetDisplayConfig target_display_config; +}; + +enum input_mode_e { + INPUT_MODE_OTT = 0, + INPUT_MODE_HDMI = 1 +}; + +struct ui_menu_params_s { + uint16_t u16BackLightUIVal; + uint16_t u16BrightnessUIVal; + uint16_t u16ContrastUIVal; +}; + +enum signal_format_e { + FORMAT_INVALID = -1, + FORMAT_DOVI = 0, + FORMAT_HDR10 = 1, + FORMAT_SDR = 2, + FORMAT_DOVI_LL = 3 +}; + +enum priority_mode_e { + VIDEO_PRIORITY = 0, + GRAPHIC_PRIORITY = 1 +}; + +enum cp_signal_range_e { + SIG_RANGE_SMPTE = 0, /* head range */ + SIG_RANGE_FULL = 1, /* full range */ + SIG_RANGE_SDI = 2 /* PQ */ +}; + +enum graphics_format_e { + GF_SDR_YUV = 0, /* BT.709 YUV BT1886 */ + GF_SDR_RGB = 1, /* BT.709 RGB BT1886 */ + GF_HDR_YUV = 2, /* BT.2020 YUV PQ */ + GF_HDR_RGB = 3 /* BT.2020 RGB PQ */ +}; + +struct run_mode_s { + uint16_t width; + uint16_t height; + uint16_t el_width; + uint16_t el_height; + uint16_t hdmi_mode; +}; + +struct composer_register_ipcore_s { + /* offset 0xc8 */ + uint32_t Composer_Mode; + uint32_t VDR_Resolution; + uint32_t Bit_Depth; + uint32_t Coefficient_Log2_Denominator; + uint32_t BL_Num_Pivots_Y; + uint32_t BL_Pivot[5]; + uint32_t BL_Order; + uint32_t BL_Coefficient_Y[8][3]; + uint32_t EL_NLQ_Offset_Y; + uint32_t EL_Coefficient_Y[3]; + uint32_t Mapping_IDC_U; + uint32_t BL_Num_Pivots_U; + uint32_t BL_Pivot_U[3]; + uint32_t BL_Order_U; + uint32_t BL_Coefficient_U[4][3]; + uint32_t MMR_Coefficient_U[22][2]; + uint32_t MMR_Order_U; + uint32_t EL_NLQ_Offset_U; + uint32_t EL_Coefficient_U[3]; + uint32_t Mapping_IDC_V; + uint32_t BL_Num_Pivots_V; + uint32_t BL_Pivot_V[3]; + uint32_t BL_Order_V; + uint32_t BL_Coefficient_V[4][3]; + uint32_t MMR_Coefficient_V[22][2]; + uint32_t MMR_Order_V; + uint32_t EL_NLQ_Offset_V; + uint32_t EL_Coefficient_V[3]; +}; + +/** @brief DM registers for IPCORE 1 */ +struct dm_register_ipcore_1_s { + uint32_t SRange; + uint32_t Srange_Inverse; + uint32_t Frame_Format_1; + uint32_t Frame_Format_2; + uint32_t Frame_Pixel_Def; + uint32_t Y2RGB_Coefficient_1; + uint32_t Y2RGB_Coefficient_2; + uint32_t Y2RGB_Coefficient_3; + uint32_t Y2RGB_Coefficient_4; + uint32_t Y2RGB_Coefficient_5; + uint32_t Y2RGB_Offset_1; + uint32_t Y2RGB_Offset_2; + uint32_t Y2RGB_Offset_3; + uint32_t EOTF; +/* uint32_t Sparam_1;*/ +/* uint32_t Sparam_2;*/ +/* uint32_t Sgamma; */ + uint32_t A2B_Coefficient_1; + uint32_t A2B_Coefficient_2; + uint32_t A2B_Coefficient_3; + uint32_t A2B_Coefficient_4; + uint32_t A2B_Coefficient_5; + uint32_t C2D_Coefficient_1; + uint32_t C2D_Coefficient_2; + uint32_t C2D_Coefficient_3; + uint32_t C2D_Coefficient_4; + uint32_t C2D_Coefficient_5; + uint32_t C2D_Offset; + uint32_t Active_area_left_top; + uint32_t Active_area_bottom_right; +}; + +/** @brief DM registers for IPCORE 2 */ +struct dm_register_ipcore_2_s { + uint32_t SRange; + uint32_t Srange_Inverse; + uint32_t Y2RGB_Coefficient_1; + uint32_t Y2RGB_Coefficient_2; + uint32_t Y2RGB_Coefficient_3; + uint32_t Y2RGB_Coefficient_4; + uint32_t Y2RGB_Coefficient_5; + uint32_t Y2RGB_Offset_1; + uint32_t Y2RGB_Offset_2; + uint32_t Y2RGB_Offset_3; + uint32_t Frame_Format; + uint32_t EOTF; + uint32_t A2B_Coefficient_1; + uint32_t A2B_Coefficient_2; + uint32_t A2B_Coefficient_3; + uint32_t A2B_Coefficient_4; + uint32_t A2B_Coefficient_5; + uint32_t C2D_Coefficient_1; + uint32_t C2D_Coefficient_2; + uint32_t C2D_Coefficient_3; + uint32_t C2D_Coefficient_4; + uint32_t C2D_Coefficient_5; + uint32_t C2D_Offset; + uint32_t VDR_Resolution; +}; + +/** @brief DM registers for IPCORE 3 */ +struct dm_register_ipcore_3_s { + uint32_t D2C_coefficient_1; + uint32_t D2C_coefficient_2; + uint32_t D2C_coefficient_3; + uint32_t D2C_coefficient_4; + uint32_t D2C_coefficient_5; + uint32_t B2A_Coefficient_1; + uint32_t B2A_Coefficient_2; + uint32_t B2A_Coefficient_3; + uint32_t B2A_Coefficient_4; + uint32_t B2A_Coefficient_5; + uint32_t Eotf_param_1; + uint32_t Eotf_param_2; + uint32_t IPT_Scale; + uint32_t IPT_Offset_1; + uint32_t IPT_Offset_2; + uint32_t IPT_Offset_3; + uint32_t Output_range_1; + uint32_t Output_range_2; + uint32_t RGB2YUV_coefficient_register1; + uint32_t RGB2YUV_coefficient_register2; + uint32_t RGB2YUV_coefficient_register3; + uint32_t RGB2YUV_coefficient_register4; + uint32_t RGB2YUV_coefficient_register5; + uint32_t RGB2YUV_offset_0; + uint32_t RGB2YUV_offset_1; + uint32_t RGB2YUV_offset_2; +}; + +/** @brief DM luts for IPCORE 1 and 2 */ +struct dm_lut_ipcore_s { + uint32_t TmLutI[64*4]; + uint32_t TmLutS[64*4]; + uint32_t SmLutI[64*4]; + uint32_t SmLutS[64*4]; + uint32_t G2L[DEF_G2L_LUT_SIZE]; +}; + +/** @brief hdmi metadata for IPCORE 3 */ +struct md_reister_ipcore_3_s { + uint32_t raw_metadata[128]; + uint32_t size; +}; + +struct hdr_10_infoframe_s { + uint8_t infoframe_type_code; + uint8_t infoframe_version_number; + uint8_t length_of_info_frame; + uint8_t data_byte_1; + uint8_t data_byte_2; + uint8_t display_primaries_x_0_LSB; + uint8_t display_primaries_x_0_MSB; + uint8_t display_primaries_y_0_LSB; + uint8_t display_primaries_y_0_MSB; + uint8_t display_primaries_x_1_LSB; + uint8_t display_primaries_x_1_MSB; + uint8_t display_primaries_y_1_LSB; + uint8_t display_primaries_y_1_MSB; + uint8_t display_primaries_x_2_LSB; + uint8_t display_primaries_x_2_MSB; + uint8_t display_primaries_y_2_LSB; + uint8_t display_primaries_y_2_MSB; + uint8_t white_point_x_LSB; + uint8_t white_point_x_MSB; + uint8_t white_point_y_LSB; + uint8_t white_point_y_MSB; + uint8_t max_display_mastering_luminance_LSB; + uint8_t max_display_mastering_luminance_MSB; + uint8_t min_display_mastering_luminance_LSB; + uint8_t min_display_mastering_luminance_MSB; + uint8_t max_content_light_level_LSB; + uint8_t max_content_light_level_MSB; + uint8_t max_frame_average_light_level_LSB; + uint8_t max_frame_average_light_level_MSB; +}; + +struct hdr10_param_s { + uint32_t min_display_mastering_luminance; + uint32_t max_display_mastering_luminance; + uint16_t Rx; + uint16_t Ry; + uint16_t Gx; + uint16_t Gy; + uint16_t Bx; + uint16_t By; + uint16_t Wx; + uint16_t Wy; + uint16_t max_content_light_level; + uint16_t max_pic_average_light_level; +}; + +#ifdef V2_4 +struct ext_level_1_s { + uint8_t min_PQ_hi; + uint8_t min_PQ_lo; + uint8_t max_PQ_hi; + uint8_t max_PQ_lo; + uint8_t avg_PQ_hi; + uint8_t avg_PQ_lo; +}; + +struct ext_level_2_s { + uint8_t target_max_PQ_hi; + uint8_t target_max_PQ_lo; + uint8_t trim_slope_hi; + uint8_t trim_slope_lo; + uint8_t trim_offset_hi; + uint8_t trim_offset_lo; + uint8_t trim_power_hi; + uint8_t trim_power_lo; + uint8_t trim_chroma_weight_hi; + uint8_t trim_chroma_weight_lo; + uint8_t trim_saturation_gain_hi; + uint8_t trim_saturation_gain_lo; + uint8_t ms_weight_hi; + uint8_t ms_weight_lo; +}; + +struct ext_level_4_s { + uint8_t anchor_PQ_hi; + uint8_t anchor_PQ_lo; + uint8_t anchor_power_hi; + uint8_t anchor_power_lo; +}; + +struct ext_level_5_s { + uint8_t active_area_left_offset_hi; + uint8_t active_area_left_offset_lo; + uint8_t active_area_right_offset_hi; + uint8_t active_area_right_offset_lo; + uint8_t active_area_top_offset_hi; + uint8_t active_area_top_offset_lo; + uint8_t active_area_bottom_offset_hi; + uint8_t active_area_bottom_offset_lo; +}; + +struct ext_level_6_s { + uint8_t max_display_mastering_luminance_hi; + uint8_t max_display_mastering_luminance_lo; + uint8_t min_display_mastering_luminance_hi; + uint8_t min_display_mastering_luminance_lo; + uint8_t max_content_light_level_hi; + uint8_t max_content_light_level_lo; + uint8_t max_frame_average_light_level_hi; + uint8_t max_frame_average_light_level_lo; +}; + +struct ext_level_255_s { + uint8_t dm_run_mode; + uint8_t dm_run_version; + uint8_t dm_debug0; + uint8_t dm_debug1; + uint8_t dm_debug2; + uint8_t dm_debug3; +}; + +struct ext_md_s { + uint32_t available_level_mask; + struct ext_level_1_s level_1; + struct ext_level_2_s level_2; + struct ext_level_4_s level_4; + struct ext_level_5_s level_5; + struct ext_level_6_s level_6; + struct ext_level_255_s level_255; +}; +#endif + +struct dovi_setting_s { + struct composer_register_ipcore_s comp_reg; + struct dm_register_ipcore_1_s dm_reg1; + struct dm_register_ipcore_2_s dm_reg2; + struct dm_register_ipcore_3_s dm_reg3; + struct dm_lut_ipcore_s dm_lut1; + struct dm_lut_ipcore_s dm_lut2; + /* for dovi output */ + struct md_reister_ipcore_3_s md_reg3; + /* for hdr10 output */ + struct hdr_10_infoframe_s hdr_info; + /* current process */ + enum signal_format_e src_format; + enum signal_format_e dst_format; + /* enhanced layer */ + bool el_flag; + bool el_halfsize_flag; + /* frame width & height */ + uint32_t video_width; + uint32_t video_height; +#ifdef V2_4 + /* use for stb 2.4 */ + enum graphics_format_e g_format; + uint32_t g_bitdepth; + uint32_t dovi2hdr10_nomapping; + uint32_t use_ll_flag; + uint32_t ll_rgb_desired; + uint32_t diagnostic_enable; + uint32_t diagnostic_mux_select; + uint32_t dovi_ll_enable; + uint32_t vout_width; + uint32_t vout_height; + u8 vsvdb_tbl[32]; + struct ext_md_s ext_md; + uint32_t vsvdb_len; + uint32_t vsvdb_changed; +#endif +}; + +struct amdolby_vision_port_t { + const char *name; + struct device *dev; + const struct file_operations *fops; + void *runtime; +}; + +extern int control_path( + enum signal_format_e in_format, + enum signal_format_e out_format, + char *in_comp, int in_comp_size, + char *in_md, int in_md_size, + enum priority_mode_e set_priority, + int set_bit_depth, int set_chroma_format, int set_yuv_range, + int set_graphic_min_lum, int set_graphic_max_lum, + int set_target_min_lum, int set_target_max_lum, + int set_no_el, + struct hdr10_param_s *hdr10_param, + struct dovi_setting_s *output); + +struct tv_dovi_setting_s { + uint64_t core1_reg_lut[3754]; + /* current process */ + enum signal_format_e src_format; + enum signal_format_e dst_format; + /* enhanced layer */ + bool el_flag; + bool el_halfsize_flag; + /* frame width & height */ + uint32_t video_width; + uint32_t video_height; + enum input_mode_e input_mode; +}; + +extern int tv_control_path( + enum signal_format_e in_format, + enum input_mode_e in_mode, + char *in_comp, int in_comp_size, + char *in_md, int in_md_size, + int set_bit_depth, int set_chroma_format, int set_yuv_range, + struct pq_config_s *pq_config, + struct ui_menu_params_s *menu_param, + int set_no_el, + struct hdr10_param_s *hdr10_param, + struct tv_dovi_setting_s *output); + +extern void *metadata_parser_init(int flag); +extern int metadata_parser_reset(int flag); +extern int metadata_parser_process( + char *src_rpu, int rpu_len, + char *dst_comp, int *comp_len, + char *dst_md, int *md_len, bool src_eos); +extern void metadata_parser_release(void); + +struct dolby_vision_func_s { + const char *version_info; + void * (*metadata_parser_init)(int flag); + int (*metadata_parser_reset)(int flag); + int (*metadata_parser_process)( + char *src_rpu, int rpu_len, + char *dst_comp, int *comp_len, + char *dst_md, int *md_len, bool src_eos); + void (*metadata_parser_release)(void); + int (*control_path)( + enum signal_format_e in_format, + enum signal_format_e out_format, + char *in_comp, int in_comp_size, + char *in_md, int in_md_size, + enum priority_mode_e set_priority, + int set_bit_depth, int set_chroma_format, int set_yuv_range, + int set_graphic_min_lum, int set_graphic_max_lum, + int set_target_min_lum, int set_target_max_lum, + int set_no_el, + struct hdr10_param_s *hdr10_param, + struct dovi_setting_s *output); + int (*tv_control_path)( + enum signal_format_e in_format, + enum input_mode_e in_mode, + char *in_comp, int in_comp_size, + char *in_md, int in_md_size, + int set_bit_depth, int set_chroma_format, int set_yuv_range, + struct pq_config_s *pq_config, + struct ui_menu_params_s *menu_param, + int set_no_el, + struct hdr10_param_s *hdr10_param, + struct tv_dovi_setting_s *output); +}; + +extern int register_dv_functions(const struct dolby_vision_func_s *func); +extern int unregister_dv_functions(void); +#ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +#define VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) +#define VSYNC_RD_MPEG_REG(adr) READ_VPP_REG(adr) +#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ + WRITE_VPP_REG_BITS(adr, val, start, len) +#else +extern int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); +extern u32 VSYNC_RD_MPEG_REG(u32 adr); +extern int VSYNC_WR_MPEG_REG(u32 adr, u32 val); +#endif + +#endif diff --git a/drivers/amlogic/media/enhancement/amvecm/Makefile b/drivers/amlogic/media/enhancement/amvecm/Makefile index d837361a85ac..2edf28b48b05 100644 --- a/drivers/amlogic/media/enhancement/amvecm/Makefile +++ b/drivers/amlogic/media/enhancement/amvecm/Makefile @@ -2,7 +2,6 @@ # AMLOGIC VE & CM. # -ccflags-y := -I$(PWD)/$(src)/dolby_vision/ obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) += am_vecm.o -am_vecm-objs := amve.o amcm.o amcsc.o amvecm.o amdolby_vision.o keystone_correction.o bitdepth.o set_hdr2_v0.o +am_vecm-objs := amve.o amcm.o amcsc.o amvecm.o keystone_correction.o bitdepth.o set_hdr2_v0.o diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm.c b/drivers/amlogic/media/enhancement/amvecm/amcm.c index 9bdaff84aa9f..5cf992b7c1ae 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcm.c @@ -28,6 +28,7 @@ #include "arch/cm_regs.h" #include "amcm.h" #include "amcm_regmap.h" +#include #define pr_amcm_dbg(fmt, args...)\ do {\ @@ -249,15 +250,13 @@ void amcm_enable(void) { int temp; - if (!is_dolby_vision_enable()) { - if (!(READ_VPP_REG(VPP_MISC) & (0x1 << 28))) - WRITE_VPP_REG_BITS(VPP_MISC, 1, 28, 1); + if (!(READ_VPP_REG(VPP_MISC) & (0x1 << 28))) + WRITE_VPP_REG_BITS(VPP_MISC, 1, 28, 1); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); + temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); + if (!(temp & 0x2)) { WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); - temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); - if (!(temp & 0x2)) { - WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); - WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, temp | 0x2); - } + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, temp | 0x2); } } diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc.c b/drivers/amlogic/media/enhancement/amvecm/amcsc.c index 92993cb71d65..45c47c6a2795 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc.c @@ -35,7 +35,7 @@ #include "amcsc.h" #include "set_hdr2_v0.h" - +#include #define pr_csc(fmt, args...)\ do {\ @@ -2585,6 +2585,97 @@ static void vpp_set_mtx_en_read(void) OSD1_MTX_EN_MASK); } +/* dvll output 12bit */ +static int dvll_RGB_to_YUV709l_coeff[MATRIX_5x3_COEF_SIZE] = { + 0, 0, 0, /* pre offset */ + COEFF_NORM(0.181873), COEFF_NORM(0.611831), COEFF_NORM(0.061765), + COEFF_NORM(-0.100251), COEFF_NORM(-0.337249), COEFF_NORM(0.437500), + COEFF_NORM(0.437500), COEFF_NORM(-0.397384), COEFF_NORM(-0.040116), + 0, 0, 0, /* 10'/11'/12' */ + 0, 0, 0, /* 20'/21'/22' */ + 64, 512, 512, /* offset */ + 0, 0, 0 /* mode, right_shift, clip_en */ +}; +static int *cur_post_mtx = bypass_coeff; +static int cur_post_on = CSC_OFF; +static int32_t *post_mtx_backup; +static int32_t post_on_backup; +static bool restore_post_table; +/* coeff: pointer to target coeff array */ +/* bits: how many bits for target coeff, could be 10 ~ 12, default 10 */ +int enable_rgb_to_yuv_matrix_for_dvll( + int32_t on, uint32_t *coeff_orig, uint32_t bits) +{ + int32_t i, j; + uint32_t coeff01, coeff23, coeff45, coeff67; + uint32_t coeff8, scale, shift, offset[3]; + int32_t *coeff = dvll_RGB_to_YUV709l_coeff; + + if ((bits < 10) || (bits > 12)) + return -1; + if (on && !coeff_orig) + return -2; + if (on) { + /* only store the start one */ + if (cur_post_mtx != + dvll_RGB_to_YUV709l_coeff) { + post_mtx_backup = cur_post_mtx; + post_on_backup = cur_post_on; + } + coeff01 = coeff_orig[0]; + coeff23 = coeff_orig[1]; + coeff45 = coeff_orig[2]; + coeff67 = coeff_orig[3]; + coeff8 = coeff_orig[4] & 0xffff; + scale = (coeff_orig[4] >> 16) & 0x0f; + offset[0] = 0; /* coeff_orig[5]; */ + offset[1] = 0; /* coeff_orig[6]; */ + offset[2] = 0; /* coeff_orig[7]; */ + if (scale >= bits) { + shift = scale - bits; + coeff[5] = (coeff01 & 0xffff) >> shift; + coeff[3] = ((coeff01 >> 16) & 0xffff) >> shift; + coeff[4] = (coeff23 & 0xffff) >> shift; + coeff[8] = ((coeff23 >> 16) & 0xffff) >> shift; + coeff[6] = (coeff45 & 0xffff) >> shift; + coeff[7] = ((coeff45 >> 16) & 0xffff) >> shift; + coeff[11] = (coeff67 & 0xffff) >> shift; + coeff[9] = ((coeff67 >> 16) & 0xffff) >> shift; + coeff[10] = (coeff8 & 0xffff) >> shift; + } else { + shift = bits - scale; + coeff[5] = (coeff01 & 0xffff) << shift; + coeff[3] = ((coeff01 >> 16) & 0xffff) << shift; + coeff[4] = (coeff23 & 0xffff) << shift; + coeff[8] = ((coeff23 >> 16) & 0xffff) << shift; + coeff[6] = (coeff45 & 0xffff) << shift; + coeff[7] = ((coeff45 >> 16) & 0xffff) << shift; + coeff[11] = (coeff67 & 0xffff) << shift; + coeff[9] = ((coeff67 >> 16) & 0xffff) << shift; + coeff[10] = (coeff8 & 0xffff) << shift; + } + coeff[18] = offset[0] >> (12 - bits); + coeff[19] = offset[1] >> (12 - bits); + coeff[20] = offset[2] >> (12 - bits); + for (i = 3; i < 12; i++) { + if (coeff[i] & (1 << bits)) + for (j = bits + 1; j <= 12; j++) + coeff[i] |= 1 << j; + } + coeff[22] = bits - 10; + set_vpp_matrix(VPP_MATRIX_POST, + coeff, CSC_ON); + vpp_set_mtx_en_write(); + restore_post_table = true; + } else if (restore_post_table) { + set_vpp_matrix(VPP_MATRIX_POST, + post_mtx_backup, post_on_backup); + vpp_set_mtx_en_write(); + restore_post_table = false; + } + return 0; +} +EXPORT_SYMBOL(enable_rgb_to_yuv_matrix_for_dvll); static void vpp_set_matrix( enum vpp_matrix_sel_e vd1_or_vd2_or_post, unsigned int on, diff --git a/drivers/amlogic/media/enhancement/amvecm/amdolby_vision.c b/drivers/amlogic/media/enhancement/amvecm/amdolby_vision.c deleted file mode 100644 index 7f28d2bf7de7..000000000000 --- a/drivers/amlogic/media/enhancement/amvecm/amdolby_vision.c +++ /dev/null @@ -1,2086 +0,0 @@ -/* - * drivers/amlogic/media/enhancement/amvecm/amdolby_vision.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "arch/vpp_regs.h" -#include "arch/vpp_hdr_regs.h" -#include "arch/vpp_dolbyvision_regs.h" -#include "dolby_vision/dolby_vision.h" - -DEFINE_SPINLOCK(dovi_lock); -static const struct dolby_vision_func_s *p_funcs; - -#define DOLBY_VISION_OUTPUT_MODE_IPT 0 -#define DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL 1 -#define DOLBY_VISION_OUTPUT_MODE_HDR10 2 -#define DOLBY_VISION_OUTPUT_MODE_SDR10 3 -#define DOLBY_VISION_OUTPUT_MODE_SDR8 4 -#define DOLBY_VISION_OUTPUT_MODE_BYPASS 5 -static unsigned int dolby_vision_mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; -module_param(dolby_vision_mode, uint, 0664); -MODULE_PARM_DESC(dolby_vision_mode, "\n dolby_vision_mode\n"); - -/* if sink support DV, always output DV */ -/* else always output SDR/HDR */ -#define DOLBY_VISION_FOLLOW_SINK 0 -/* output DV only if source is DV and sink support DV */ -/* else always output SDR/HDR */ -#define DOLBY_VISION_FOLLOW_SOURCE 1 -/* always follow dolby_vision_mode */ -#define DOLBY_VISION_FORCE_OUTPUT_MODE 2 -static unsigned int dolby_vision_policy; -module_param(dolby_vision_policy, uint, 0664); -MODULE_PARM_DESC(dolby_vision_policy, "\n dolby_vision_policy\n"); - -static bool dolby_vision_enable; -module_param(dolby_vision_enable, bool, 0664); -MODULE_PARM_DESC(dolby_vision_enable, "\n dolby_vision_enable\n"); - -#define BYPASS_PROCESS 0 -#define SDR_PROCESS 1 -#define HDR_PROCESS 2 -#define DV_PROCESS 3 -static uint dolby_vision_status; -module_param(dolby_vision_status, uint, 0664); -MODULE_PARM_DESC(dolby_vision_status, "\n dolby_vision_status\n"); - -#define FLAG_RESET_EACH_FRAME 0x01 -#define FLAG_META_FROM_BL 0x02 -#define FLAG_BYPASS_CVM 0x04 -#define FLAG_USE_SINK_MIN_MAX 0x08 -#define FLAG_CLKGATE_WHEN_LOAD_LUT 0x10 -#define FLAG_SINGLE_STEP 0x20 -#define FLAG_CERTIFICAION 0x40 -#define FLAG_CHANGE_SEQ_HEAD 0x80 -#define FLAG_DISABLE_COMPOSER 0x100 -#define FLAG_BYPASS_CSC 0x200 -#define FLAG_CHECK_ES_PTS 0x400 -#define FLAG_TOGGLE_FRAME 0x80000000 -static unsigned int dolby_vision_flags = - FLAG_META_FROM_BL | FLAG_BYPASS_CVM; -module_param(dolby_vision_flags, uint, 0664); -MODULE_PARM_DESC(dolby_vision_flags, "\n dolby_vision_flags\n"); - -static unsigned int htotal_add = 0x140; -static unsigned int vtotal_add = 0x40; -static unsigned int vsize_add; -static unsigned int vwidth = 0x8; -static unsigned int hwidth = 0x8; -static unsigned int vpotch = 0x10; -static unsigned int hpotch = 0x8; -static unsigned int g_htotal_add = 0x40; -static unsigned int g_vtotal_add = 0x80; -static unsigned int g_vsize_add; -static unsigned int g_vwidth = 0x18; -static unsigned int g_hwidth = 0x10; -static unsigned int g_vpotch = 0x8; -static unsigned int g_hpotch = 0x10; - -module_param(vtotal_add, uint, 0664); -MODULE_PARM_DESC(vtotal_add, "\n vtotal_add\n"); -module_param(vpotch, uint, 0664); -MODULE_PARM_DESC(vpotch, "\n vpotch\n"); - -static unsigned int dolby_vision_target_min = 50; /* 0.0001 */ -static unsigned int dolby_vision_target_max[3][3] = { - { 4000, 4000, 100 }, /* DOVI => DOVI/HDR/SDR */ - { 1000, 1000, 100 }, /* HDR => DOVI/HDR/SDR */ - { 600, 1000, 100 }, /* SDR => DOVI/HDR/SDR */ -}; - -static unsigned int dolby_vision_default_max[3][3] = { - { 4000, 4000, 100 }, /* DOVI => DOVI/HDR/SDR */ - { 1000, 1000, 100 }, /* HDR => DOVI/HDR/SDR */ - { 600, 1000, 100 }, /* SDR => DOVI/HDR/SDR */ -}; - -static unsigned int dolby_vision_graphic_min = 50; /* 0.0001 */ -static unsigned int dolby_vision_graphic_max = 100; /* 1 */ -module_param(dolby_vision_graphic_min, uint, 0664); -MODULE_PARM_DESC(dolby_vision_graphic_min, "\n dolby_vision_graphic_min\n"); - -static unsigned int debug_dolby; -module_param(debug_dolby, uint, 0664); -MODULE_PARM_DESC(debug_dolby, "\n debug_dolby\n"); - -static unsigned int debug_dolby_frame = 0xffff; -module_param(debug_dolby_frame, uint, 0664); -MODULE_PARM_DESC(debug_dolby_frame, "\n debug_dolby_frame\n"); - -#define pr_dolby_dbg(fmt, args...)\ - do {\ - if (debug_dolby)\ - pr_info("DOLBY: " fmt, ## args);\ - } while (0) -#define pr_dolby_error(fmt, args...)\ - pr_info("DOLBY ERROR: " fmt, ## args) -#define dump_enable \ - ((debug_dolby_frame >= 0xffff) || (debug_dolby_frame == frame_count)) -#define is_graphics_output_off() \ - (!(READ_VPP_REG(VPP_MISC) & (1<<12))) - -static bool dolby_vision_on; -static bool dolby_vision_wait_on; -static unsigned int frame_count; -static struct hdr10_param_s hdr10_param; -static struct master_display_info_s hdr10_data; -static struct dovi_setting_s dovi_setting; -static struct dovi_setting_s new_dovi_setting; - -static int dolby_core1_set( - uint32_t dm_count, - uint32_t comp_count, - uint32_t lut_count, - uint32_t *p_core1_dm_regs, - uint32_t *p_core1_comp_regs, - uint32_t *p_core1_lut, - int hsize, - int vsize, - int bl_enable, - int el_enable, - int el_41_mode, - int scramble_en, - bool dovi_src, - int lut_endian) -{ - uint32_t count; - uint32_t bypass_flag = 0; - int composer_enable = el_enable; - int i; - - if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) - composer_enable = 0; - - if ((!dolby_vision_on) - || (dolby_vision_flags & FLAG_RESET_EACH_FRAME)) { - VSYNC_WR_MPEG_REG(VIU_SW_RESET, (1 << 10)|(1 << 9)); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); - } - - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, 0); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL1, - ((hsize + 0x40) << 16) | (vsize + 0x20)); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL3, (hwidth << 16) | vwidth); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL4, (hpotch << 16) | vpotch); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL2, (hsize << 16) | vsize); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL5, 0xa); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x0); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 4, 4); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 2, 1); - - /* bypass composer to get 12bit when SDR and HDR source */ - if (!dovi_src) - bypass_flag |= 1 << 0; - if (scramble_en) { - if (dolby_vision_flags & FLAG_BYPASS_CSC) - bypass_flag |= 1 << 1; - if (dolby_vision_flags & FLAG_BYPASS_CVM) - bypass_flag |= 1 << 2; - } - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, - 0x78 | bypass_flag); /* bypass CVM and/or CSC */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, - 0x78 | bypass_flag); /* for delay */ - if ((dolby_vision_flags & FLAG_RESET_EACH_FRAME) && (dm_count == 0)) - count = 24; - else - count = dm_count; - for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 6 + i, - p_core1_dm_regs[i]); - - if ((dolby_vision_flags & FLAG_RESET_EACH_FRAME) && (comp_count == 0)) - count = 173; - else - count = comp_count; - for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 6 + 44 + i, - p_core1_comp_regs[i]); - - /* metadata program done */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 3, 1); - - if ((dolby_vision_flags & FLAG_RESET_EACH_FRAME) && (lut_count == 0)) - count = 256 * 5; - else - count = lut_count; - if (count) { - if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, - 2, 2, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x1401); - if (lut_endian) - for (i = 0; i < count; i += 4) { - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, - p_core1_lut[i+3]); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, - p_core1_lut[i+2]); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, - p_core1_lut[i+1]); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, - p_core1_lut[i]); - } - else - for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, - p_core1_lut[i]); - if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, - 0, 2, 2); - } - - /* enable core1 */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, - bl_enable << 0 | - composer_enable << 1 | - el_41_mode << 2); - return 0; -} - -static int dolby_core2_set( - uint32_t dm_count, - uint32_t lut_count, - uint32_t *p_core2_dm_regs, - uint32_t *p_core2_lut, - int hsize, - int vsize, - int dolby_enable, - int lut_endian) -{ - uint32_t count; - int i; - - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, 0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL1, - ((hsize + g_htotal_add) << 16) - | (vsize + g_vtotal_add + g_vsize_add)); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL3, - (g_hwidth << 16) | g_vwidth); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL4, - (g_hpotch << 16) | g_vpotch); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL2, - (hsize << 16) | (vsize + g_vsize_add)); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0x0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, 2); - - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); - - if ((dolby_vision_flags & FLAG_RESET_EACH_FRAME) - && (dm_count == 0)) - count = 24; - else - count = dm_count; - for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 6 + i, - p_core2_dm_regs[i]); - /* core2 metadata program done */ - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 3, 1); - - if (dolby_vision_flags & FLAG_RESET_EACH_FRAME) - count = 256 * 5; - else - count = lut_count; - if (count) { - if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE2A_CLKGATE_CTRL, - 2, 2, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x1401); - if (lut_endian) - for (i = 0; i < count; i += 4) { - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, - p_core2_lut[i+3]); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, - p_core2_lut[i+2]); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, - p_core2_lut[i+1]); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, - p_core2_lut[i]); - } - else - for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, - p_core2_lut[i]); - /* core1 lookup table program done */ - if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS( - DOLBY_CORE2A_CLKGATE_CTRL, 0, 2, 2); - } - - /* enable core2 */ - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, dolby_enable << 0); - return 0; -} - -static int dolby_core3_set( - uint32_t dm_count, - uint32_t md_count, - uint32_t *p_core3_dm_regs, - uint32_t *p_core3_md_regs, - int hsize, - int vsize, - int dolby_enable, - int scramble_en) -{ - uint32_t count; - int i; - int vsize_hold = 0x10; - - /* turn off free run clock */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_CLKGATE_CTRL, 0); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL1, - ((hsize + htotal_add) << 16) - | (vsize + vtotal_add + vsize_add + vsize_hold * 2)); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL2, - (hsize << 16) | (vsize + vsize_add)); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL3, - (0x80 << 16) | vsize_hold); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL4, - (0x04 << 16) | vsize_hold); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL5, 0x0000); - if (dolby_vision_mode != - DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, 0); - else - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, - 0x10000000); /* swap UV */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 5, 7); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 4); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 2, 1); - /* Control Register, address 0x04 2:0 RW */ - /* Output_operating mode*/ - /* 00- IPT 12 bit 444 bypass Dolby Vision output*/ - /* 01- IPT 12 bit tunnelled over RGB 8 bit 444, dolby vision output*/ - /* 02- HDR10 output, RGB 10 bit 444 PQ*/ - /* 03- Deep color SDR, RGB 10 bit 444 Gamma*/ - /* 04- SDR, RGB 8 bit 444 Gamma*/ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, dolby_vision_mode); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, dolby_vision_mode); - /* for delay */ - - if ((dolby_vision_flags & FLAG_RESET_EACH_FRAME) - && (dm_count == 0)) - count = 26; - else - count = dm_count; - for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x6 + i, - p_core3_dm_regs[i]); - /* from addr 0x18 */ - - count = md_count; - for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, - p_core3_md_regs[i]); - for (; i < 30; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, 0); - - /* from addr 0x90 */ - /* core3 metadata program done */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 3, 1); - - /* enable core3 */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL0, (dolby_enable << 0)); - return 0; -} - -static uint32_t dolby_ctrl_backup; -static uint32_t viu_misc_ctrl_backup; -static uint32_t vpu_hdmi_fmt_backup; -static uint32_t viu_eotf_ctrl_backup; -static uint32_t xvycc_lut_ctrl_backup; -static uint32_t inv_lut_ctrl_backup; -static uint32_t vpp_matrix_backup; -static uint32_t vpp_vadj_backup; -static uint32_t vpp_dummy1_backup; -static uint32_t vpp_gainoff_backup; -void enable_dolby_vision(int enable) -{ - if (enable) { - if (!dolby_vision_on) { - dolby_ctrl_backup = - VSYNC_RD_MPEG_REG(VPP_DOLBY_CTRL); - viu_misc_ctrl_backup = - VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1); - vpu_hdmi_fmt_backup = - VSYNC_RD_MPEG_REG(VPU_HDMI_FMT_CTRL); - viu_eotf_ctrl_backup = - VSYNC_RD_MPEG_REG(VIU_EOTF_CTL); - xvycc_lut_ctrl_backup = - VSYNC_RD_MPEG_REG(XVYCC_LUT_CTL); - inv_lut_ctrl_backup = - VSYNC_RD_MPEG_REG(XVYCC_INV_LUT_CTL); - vpp_matrix_backup = - VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); - vpp_vadj_backup = - VSYNC_RD_MPEG_REG(VPP_VADJ_CTRL); - vpp_dummy1_backup = - VSYNC_RD_MPEG_REG(VPP_DUMMY_DATA1); - vpp_gainoff_backup = - VSYNC_RD_MPEG_REG(VPP_GAINOFF_CTRL0); - VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, - (0x0<<21) /* cm_datx4_mode */ - |(0x0<<20) /* reg_front_cti_bit_mode */ - |(0x0<<17) /* vpp_clip_ext_mode 19:17 */ - |(0x1<<16) /* vpp_dolby2_en */ - |(0x0<<15) /* mat_xvy_dat_mode */ - |(0x1<<14) /* vpp_ve_din_mode */ - |(0x1<<12) /* mat_vd2_dat_mode 13:12 */ - |(0x3<<8) /* vpp_dpath_sel 10:8 */ - |0x1f); /* vpp_uns2s_mode 7:0 */ - VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL1, - (0 << 4) /* 23-20 ext mode */ - | (0 << 3) /* 19 osd bypass */ - | (0 << 2) /* 18 core2 bypass */ - | (0 << 1) /* 17 core1 el bypass */ - | (0 << 0), /* 16 core1 bl bypass */ - 16, 8); - VSYNC_WR_MPEG_REG(VPU_HDMI_FMT_CTRL, 0); - VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, 0); - VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, 0); - VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, 0); - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); - VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, 0); - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, 0x20000000); - VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, 0); - VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_MATRIX_CTRL, 0, 0, 1); - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 28, 1); - enable_osd_path(0, 0); - pr_dolby_dbg("Dolby Vision turn on\n"); - } - dolby_vision_on = true; - dolby_vision_wait_on = false; - } else { - if (dolby_vision_on) { - VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, - dolby_ctrl_backup); - VSYNC_WR_MPEG_REG(VIU_MISC_CTRL1, - viu_misc_ctrl_backup); - VSYNC_WR_MPEG_REG(VPU_HDMI_FMT_CTRL, - vpu_hdmi_fmt_backup); - VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, - viu_eotf_ctrl_backup); - VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, - xvycc_lut_ctrl_backup); - VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, - inv_lut_ctrl_backup); - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, - vpp_matrix_backup); - VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, - vpp_vadj_backup); - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, - vpp_dummy1_backup); - VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, - vpp_gainoff_backup); - VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_MATRIX_CTRL, 1, 0, 1); - enable_osd_path(1, -1); - pr_dolby_dbg("Dolby Vision turn off\n"); - } - dolby_vision_on = false; - dolby_vision_wait_on = false; - dolby_vision_status = BYPASS_PROCESS; - } -} -EXPORT_SYMBOL(enable_dolby_vision); - -static bool video_is_hdr10; -module_param(video_is_hdr10, bool, 0664); -MODULE_PARM_DESC(video_is_hdr10, "\n video_is_hdr10\n"); - -/* dolby vision enhanced layer receiver*/ -#define DVEL_RECV_NAME "dvel" - -static inline void dvel_vf_put(struct vframe_s *vf) -{ - struct vframe_provider_s *vfp = vf_get_provider(DVEL_RECV_NAME); - int event = 0; - - if (vfp) { - vf_put(vf, DVEL_RECV_NAME); - event |= VFRAME_EVENT_RECEIVER_PUT; - vf_notify_provider(DVEL_RECV_NAME, event, NULL); - } -} - -static inline struct vframe_s *dvel_vf_peek(void) -{ - return vf_peek(DVEL_RECV_NAME); -} - -static inline struct vframe_s *dvel_vf_get(void) -{ - int event = 0; - struct vframe_s *vf = vf_get(DVEL_RECV_NAME); - - if (vf) { - event |= VFRAME_EVENT_RECEIVER_GET; - vf_notify_provider(DVEL_RECV_NAME, event, NULL); - } - return vf; -} - -static struct vframe_s *dv_vf[16][2]; -static void *metadata_parser; -static bool metadata_parser_reset_flag; -static char meta_buf[1024]; -static char md_buf[1024]; -static char comp_buf[8196]; - -static int dvel_receiver_event_fun(int type, void *data, void *arg) -{ - char *provider_name = (char *)data; - int i; - unsigned long flags; - - if (type == VFRAME_EVENT_PROVIDER_UNREG) { - pr_info("%s, provider %s unregistered\n", - __func__, provider_name); - spin_lock_irqsave(&dovi_lock, flags); - for (i = 0; i < 16; i++) { - if (dv_vf[i][0]) { - if (dv_vf[i][1]) - dvel_vf_put(dv_vf[i][1]); - dv_vf[i][1] = NULL; - } - dv_vf[i][0] = NULL; - } - if (metadata_parser && p_funcs) { - p_funcs->metadata_parser_release(); - metadata_parser = NULL; - }; - new_dovi_setting.video_width = - new_dovi_setting.video_height = 0; - spin_unlock_irqrestore(&dovi_lock, flags); - memset(&hdr10_data, 0, sizeof(hdr10_data)); - memset(&hdr10_param, 0, sizeof(hdr10_param)); - frame_count = 0; - return -1; - } else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) { - return RECEIVER_ACTIVE; - } else if (type == VFRAME_EVENT_PROVIDER_REG) { - pr_info("%s, provider %s registered\n", - __func__, provider_name); - spin_lock_irqsave(&dovi_lock, flags); - for (i = 0; i < 16; i++) - dv_vf[i][0] = dv_vf[i][1] = NULL; - new_dovi_setting.video_width = - new_dovi_setting.video_height = 0; - spin_unlock_irqrestore(&dovi_lock, flags); - memset(&hdr10_data, 0, sizeof(hdr10_data)); - memset(&hdr10_param, 0, sizeof(hdr10_param)); - frame_count = 0; - } - return 0; -} - -static const struct vframe_receiver_op_s dvel_vf_receiver = { - .event_cb = dvel_receiver_event_fun -}; - -static struct vframe_receiver_s dvel_vf_recv; - -void dolby_vision_init_receiver(void) -{ - pr_info("%s(%s)\n", __func__, DVEL_RECV_NAME); - vf_receiver_init(&dvel_vf_recv, DVEL_RECV_NAME, - &dvel_vf_receiver, &dvel_vf_recv); - vf_reg_receiver(&dvel_vf_recv); - pr_info("%s: %s\n", __func__, dvel_vf_recv.name); -} -EXPORT_SYMBOL(dolby_vision_init_receiver); - -#define MAX_FILENAME_LENGTH 64 -static const char comp_file[] = "%s_comp.%04d.reg"; -static const char dm_reg_core1_file[] = "%s_dm_core1.%04d.reg"; -static const char dm_reg_core2_file[] = "%s_dm_core2.%04d.reg"; -static const char dm_reg_core3_file[] = "%s_dm_core3.%04d.reg"; -static const char dm_lut_core1_file[] = "%s_dm_core1.%04d.lut"; -static const char dm_lut_core2_file[] = "%s_dm_core2.%04d.lut"; - -static void dump_struct(void *structure, int struct_length, - const char file_string[], int frame_nr) -{ - char fn[MAX_FILENAME_LENGTH]; - struct file *fp; - loff_t pos = 0; - mm_segment_t old_fs = get_fs(); - - if (frame_nr == 0) - return; - set_fs(KERNEL_DS); - snprintf(fn, MAX_FILENAME_LENGTH, file_string, - "/data/tmp/tmp", frame_nr-1); - fp = filp_open(fn, O_RDWR|O_CREAT, 0666); - if (fp == NULL) - pr_info("Error open file for writing %s\n", fn); - vfs_write(fp, structure, struct_length, &pos); - vfs_fsync(fp, 0); - filp_close(fp, NULL); - set_fs(old_fs); -} - -void dolby_vision_dump_struct(void) -{ - dump_struct(&dovi_setting.dm_reg1, - sizeof(dovi_setting.dm_reg1), - dm_reg_core1_file, frame_count); - if (dovi_setting.el_flag) - dump_struct(&dovi_setting.comp_reg, - sizeof(dovi_setting.comp_reg), - comp_file, frame_count); - - if (!is_graphics_output_off()) - dump_struct(&dovi_setting.dm_reg2, - sizeof(dovi_setting.dm_reg2), - dm_reg_core2_file, frame_count); - - dump_struct(&dovi_setting.dm_reg3, - sizeof(dovi_setting.dm_reg3), - dm_reg_core3_file, frame_count); - - dump_struct(&dovi_setting.dm_lut1, - sizeof(dovi_setting.dm_lut1), - dm_lut_core1_file, frame_count); - if (!is_graphics_output_off()) - dump_struct(&dovi_setting.dm_lut2, - sizeof(dovi_setting.dm_lut2), - dm_lut_core2_file, frame_count); - pr_dolby_dbg("setting for frame %d dumped\n", frame_count); -} -EXPORT_SYMBOL(dolby_vision_dump_struct); - -static void dump_setting( - struct dovi_setting_s *setting, - int frame_cnt, int debug_flag) -{ - int i; - uint32_t *p; - - if ((debug_flag & 0x10) && dump_enable) { - pr_info("core1\n"); - p = (uint32_t *)&setting->dm_reg1; - for (i = 0; i < 26; i++) - pr_info("%x\n", p[i]); - if (setting->el_flag) { - pr_info("\ncomposer\n"); - p = (uint32_t *)&setting->comp_reg; - for (i = 0; i < 173; i++) - pr_info("%x\n", p[i]); - } - } - - if ((debug_flag & 0x20) && dump_enable) { - pr_info("\ncore1lut\n"); - p = (uint32_t *)&setting->dm_lut1.TmLutI; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - p = (uint32_t *)&setting->dm_lut1.TmLutS; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - p = (uint32_t *)&setting->dm_lut1.SmLutI; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - p = (uint32_t *)&setting->dm_lut1.SmLutS; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - p = (uint32_t *)&setting->dm_lut1.G2L; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - } - - if ((debug_flag & 0x10) && dump_enable && !is_graphics_output_off()) { - pr_info("core2\n"); - p = (uint32_t *)&setting->dm_reg2; - for (i = 0; i < 24; i++) - pr_info("%x\n", p[i]); - } - - if ((debug_flag & 0x20) && dump_enable && !is_graphics_output_off()) { - pr_info("\ncore2lut\n"); - p = (uint32_t *)&setting->dm_lut2.TmLutI; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - p = (uint32_t *)&setting->dm_lut2.TmLutS; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - p = (uint32_t *)&setting->dm_lut2.SmLutI; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - p = (uint32_t *)&setting->dm_lut2.SmLutS; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - p = (uint32_t *)&setting->dm_lut2.G2L; - for (i = 0; i < 64; i++) - pr_info("%x, %x, %x, %x\n", - p[i*4+3], p[i*4+2], p[i*4+1], p[i*4]); - pr_info("\n"); - } - - if ((debug_flag & 0x10) && dump_enable) { - pr_info("core3\n"); - p = (uint32_t *)&setting->dm_reg3; - for (i = 0; i < 26; i++) - pr_info("%x\n", p[i]); - } - - if ((debug_flag & 0x40) && dump_enable - && (dolby_vision_mode <= DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL)) { - pr_info("\ncore3_meta %d\n", setting->md_reg3.size); - p = setting->md_reg3.raw_metadata; - for (i = 0; i < setting->md_reg3.size; i++) - pr_info("%x\n", p[i]); - pr_info("\n"); - } -} - -void dolby_vision_dump_setting(int debug_flag) -{ - pr_dolby_dbg("\n====== setting for frame %d ======\n", frame_count); - dump_setting(&new_dovi_setting, frame_count, debug_flag); - pr_dolby_dbg("=== setting for frame %d dumped ===\n\n", frame_count); -} -EXPORT_SYMBOL(dolby_vision_dump_setting); - -static int sink_support_dolby_vision(const struct vinfo_s *vinfo) -{ - struct vout_device_s *vdev = NULL; - - if (!vinfo || !vinfo->vout_device) - return 0; - - vdev = vinfo->vout_device; - - if (!vdev->dv_info) - return 0; - if (vdev->dv_info->ieeeoui != 0x00d046) - return 0; - /* 2160p60 if TV support */ - if ((vinfo->width >= 3840) - && (vinfo->height >= 2160) - && (vdev->dv_info->sup_2160p60hz == 1)) - return 1; - /* 1080p~2160p30 if TV support */ - else if (((vinfo->width == 1920) - && (vinfo->height == 1080)) - || ((vinfo->width >= 3840) - && (vinfo->height >= 2160) - && (vdev->dv_info->sup_2160p60hz == 0))) - return 1; - return 0; -} - -static int dolby_vision_policy_process( - int *mode, enum signal_format_e src_format) -{ - const struct vinfo_s *vinfo; - int mode_change = 0; - - if ((!dolby_vision_enable) || (!p_funcs) - || ((get_cpu_type() != MESON_CPU_MAJOR_ID_GXM))) - return mode_change; - - vinfo = get_current_vinfo(); - if (dolby_vision_policy == DOLBY_VISION_FOLLOW_SINK) { - if (vinfo && sink_support_dolby_vision(vinfo)) { - /* TV support DOVI, All -> DOVI */ - if (dolby_vision_mode != - DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) { - pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n"); - *mode = DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL; - mode_change = 1; - } - } else { - /* TV not support DOVI */ - if (src_format == FORMAT_DOVI) { - /* DOVI to SDR */ - if (dolby_vision_mode != - DOLBY_VISION_OUTPUT_MODE_SDR8) { - pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n"); - *mode = DOLBY_VISION_OUTPUT_MODE_SDR8; - mode_change = 1; - } - } else if (dolby_vision_mode != - DOLBY_VISION_OUTPUT_MODE_BYPASS) { - /* HDR/SDR bypass */ - pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n"); - *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; - mode_change = 1; - } - } - } else if (dolby_vision_policy == DOLBY_VISION_FOLLOW_SOURCE) { - if (src_format == FORMAT_DOVI) { - /* DOVI source */ - if (vinfo && sink_support_dolby_vision(vinfo)) { - /* TV support DOVI, DOVI -> DOVI */ - if (dolby_vision_mode != - DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) { - pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n"); - *mode = - DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL; - mode_change = 1; - } - } else { - /* TV not support DOVI, DOVI -> SDR */ - if (dolby_vision_mode != - DOLBY_VISION_OUTPUT_MODE_SDR8) { - pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n"); - *mode = DOLBY_VISION_OUTPUT_MODE_SDR8; - mode_change = 1; - } - } - } else if (dolby_vision_mode != - DOLBY_VISION_OUTPUT_MODE_BYPASS) { - /* HDR/SDR bypass */ - pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS"); - *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; - mode_change = 1; - } - } else if (dolby_vision_policy == DOLBY_VISION_FORCE_OUTPUT_MODE) { - if (dolby_vision_mode != *mode) { - pr_dolby_dbg("dovi output mode change %d -> %d\n", - dolby_vision_mode, *mode); - mode_change = 1; - } - } - return mode_change; -} - -static bool is_dovi_frame(struct vframe_s *vf) -{ - struct provider_aux_req_s req; - char *p; - unsigned int size = 0; - unsigned int type = 0; - - req.vf = vf; - req.bot_flag = 0; - req.aux_buf = NULL; - req.aux_size = 0; - req.dv_enhance_exist = 0; - vf_notify_provider_by_name("dvbldec", - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); - if (req.dv_enhance_exist) - return true; - if (!req.aux_buf || !req.aux_size) - return 0; - p = req.aux_buf; - while (p < req.aux_buf + req.aux_size - 8) { - size = *p++; - size = (size << 8) | *p++; - size = (size << 8) | *p++; - size = (size << 8) | *p++; - type = *p++; - type = (type << 8) | *p++; - type = (type << 8) | *p++; - type = (type << 8) | *p++; - if (type == 0x01000000) - return true; - p += size; - } - return false; -} - -/* 0: no el; >0: with el */ -/* 1: need wait el vf */ -/* 2: no match el found */ -/* 3: found match el */ -int dolby_vision_wait_metadata(struct vframe_s *vf) -{ - struct provider_aux_req_s req; - struct vframe_s *el_vf; - int ret = 0; - unsigned int mode; - - if (debug_dolby & 0x80) { - if (dolby_vision_flags & FLAG_SINGLE_STEP) - /* wait fake el for "step" */ - return 1; - - dolby_vision_flags |= FLAG_SINGLE_STEP; - } - req.vf = vf; - req.bot_flag = 0; - req.aux_buf = NULL; - req.aux_size = 0; - req.dv_enhance_exist = 0; - vf_notify_provider_by_name("dvbldec", - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); - if (req.dv_enhance_exist) { - el_vf = dvel_vf_peek(); - while (el_vf) { - if (debug_dolby & 2) - pr_dolby_dbg("=== peek bl(%p-%lld) with el(%p-%lld) ===\n", - vf, vf->pts_us64, - el_vf, el_vf->pts_us64); - if ((el_vf->pts_us64 == vf->pts_us64) - || !(dolby_vision_flags & FLAG_CHECK_ES_PTS)) { - /* found el */ - ret = 3; - break; - } else if (el_vf->pts_us64 < vf->pts_us64) { - if (debug_dolby & 2) - pr_dolby_dbg("bl(%p-%lld) => skip el pts(%p-%lld)\n", - vf, vf->pts_us64, - el_vf, el_vf->pts_us64); - el_vf = dvel_vf_get(); - dvel_vf_put(el_vf); - vf_notify_provider(DVEL_RECV_NAME, - VFRAME_EVENT_RECEIVER_PUT, NULL); - if (debug_dolby & 2) { - pr_dolby_dbg("=== get & put el(%p-%lld) ===\n", - el_vf, el_vf->pts_us64); - } - /* skip old el and peek new */ - el_vf = dvel_vf_peek(); - } else { - /* no el found */ - ret = 2; - break; - } - } - /* need wait el */ - if (el_vf == NULL) { - pr_dolby_dbg("=== bl wait el(%p-%lld) ===\n", - vf, vf->pts_us64); - ret = 1; - } - } - if (is_dovi_frame(vf) && !dolby_vision_on) { - /* dovi source, but dovi not enabled */ - mode = dolby_vision_mode; - if (dolby_vision_policy_process( - &mode, FORMAT_DOVI)) { - dolby_vision_set_toggle_flag(1); - if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) - && (dolby_vision_mode == - DOLBY_VISION_OUTPUT_MODE_BYPASS)) - dolby_vision_wait_on = true; - dolby_vision_mode = mode; - ret = 1; - } - } - return ret; -} - -void dolby_vision_vf_put(struct vframe_s *vf) -{ - int i; - - if (vf) - for (i = 0; i < 16; i++) { - if (dv_vf[i][0] == vf) { - if (dv_vf[i][1]) { - if (debug_dolby & 2) - pr_dolby_dbg("--- put bl(%p-%lld) with el(%p-%lld) ---\n", - vf, vf->pts_us64, - dv_vf[i][1], - dv_vf[i][1]->pts_us64); - dvel_vf_put(dv_vf[i][1]); - } else if (debug_dolby & 2) { - pr_dolby_dbg("--- put bl(%p-%lld) ---\n", - vf, vf->pts_us64); - } - dv_vf[i][0] = NULL; - dv_vf[i][1] = NULL; - } - } -} -EXPORT_SYMBOL(dolby_vision_vf_put); - -struct vframe_s *dolby_vision_vf_peek_el(struct vframe_s *vf) -{ - int i; - - if (dolby_vision_flags) { - for (i = 0; i < 16; i++) { - if (dv_vf[i][0] == vf) { - if (dv_vf[i][1] - && (dolby_vision_status == BYPASS_PROCESS)) - dv_vf[i][1]->type |= VIDTYPE_VD2; - return dv_vf[i][1]; - } - } - } - return NULL; -} -EXPORT_SYMBOL(dolby_vision_vf_peek_el); - -static void dolby_vision_vf_add(struct vframe_s *vf, struct vframe_s *el_vf) -{ - int i; - - for (i = 0; i < 16; i++) { - if (dv_vf[i][0] == NULL) { - dv_vf[i][0] = vf; - dv_vf[i][1] = el_vf; - break; - } - } -} - -static int dolby_vision_vf_check(struct vframe_s *vf) -{ - int i; - - for (i = 0; i < 16; i++) { - if (dv_vf[i][0] == vf) { - if (debug_dolby & 2) { - if (dv_vf[i][1]) - pr_dolby_dbg("=== bl(%p-%lld) with el(%p-%lld) toggled ===\n", - vf, - vf->pts_us64, - dv_vf[i][1], - dv_vf[i][1]->pts_us64); - else - pr_dolby_dbg("=== bl(%p-%lld) toggled ===\n", - vf, - vf->pts_us64); - } - return 0; - } - } - return 1; -} - -static int parse_sei_and_meta( - struct vframe_s *vf, - struct provider_aux_req_s *req, - int *total_comp_size, - int *total_md_size, - enum signal_format_e *src_format) -{ - int i; - char *p; - unsigned int size = 0; - unsigned int type = 0; - int md_size = 0; - int comp_size = 0; - int parser_ready = 0; - int ret = 2; - unsigned long flags; - - if ((req->aux_buf == NULL) - || (req->aux_size == 0)) - return 1; - - p = req->aux_buf; - while (p < req->aux_buf + req->aux_size - 8) { - size = *p++; - size = (size << 8) | *p++; - size = (size << 8) | *p++; - size = (size << 8) | *p++; - type = *p++; - type = (type << 8) | *p++; - type = (type << 8) | *p++; - type = (type << 8) | *p++; - - if (type == 0x01000000) { - /* source is VS10 */ - *src_format = FORMAT_DOVI; - meta_buf[0] = meta_buf[1] = meta_buf[2] = 0; - memcpy(&meta_buf[3], p+1, size-1); - if ((debug_dolby & 4) && dump_enable) { - pr_dolby_dbg("metadata(%d):\n", size); - for (i = 0; i < size+2; i += 8) - pr_info("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", - meta_buf[i], - meta_buf[i+1], - meta_buf[i+2], - meta_buf[i+3], - meta_buf[i+4], - meta_buf[i+5], - meta_buf[i+6], - meta_buf[i+7]); - } - - /* prepare metadata parser */ - parser_ready = 0; - if (metadata_parser == NULL) { - metadata_parser = - p_funcs->metadata_parser_init( - dolby_vision_flags - & FLAG_CHANGE_SEQ_HEAD - ? 1 : 0); - p_funcs->metadata_parser_reset(1); - if (metadata_parser != NULL) { - parser_ready = 1; - pr_dolby_dbg("metadata parser init OK\n"); - } - } else { - if (p_funcs->metadata_parser_reset( - metadata_parser_reset_flag) == 0) - metadata_parser_reset_flag = 0; - parser_ready = 1; - } - if (!parser_ready) { - pr_dolby_error( - "meta(%d), pts(%lld) -> metadata parser init fail\n", - size, vf->pts_us64); - return 2; - } - - md_size = comp_size = 0; - spin_lock_irqsave(&dovi_lock, flags); - if (p_funcs->metadata_parser_process( - meta_buf, size + 2, - comp_buf + *total_comp_size, - &comp_size, - md_buf + *total_md_size, - &md_size, - true)) { - pr_dolby_error( - "meta(%d), pts(%lld) -> metadata parser process fail\n", - size, vf->pts_us64); - ret = 2; - } else { - *total_comp_size += comp_size; - *total_md_size += md_size; - ret = 0; - } - spin_unlock_irqrestore(&dovi_lock, flags); - } - p += size; - } - if (*total_md_size) { - pr_dolby_dbg( - "meta(%d), pts(%lld) -> md(%d), comp(%d)\n", - size, vf->pts_us64, - *total_md_size, *total_comp_size); - if ((debug_dolby & 8) && dump_enable) { - pr_dolby_dbg("parsed md(%d):\n", *total_md_size); - for (i = 0; i < *total_md_size + 7; i += 8) { - pr_info("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", - md_buf[i], - md_buf[i+1], - md_buf[i+2], - md_buf[i+3], - md_buf[i+4], - md_buf[i+5], - md_buf[i+6], - md_buf[i+7]); - } - } - } - return ret; -} - -#define INORM 50000 -static u32 bt2020_primaries[3][2] = { - {0.17 * INORM + 0.5, 0.797 * INORM + 0.5}, /* G */ - {0.131 * INORM + 0.5, 0.046 * INORM + 0.5}, /* B */ - {0.708 * INORM + 0.5, 0.292 * INORM + 0.5}, /* R */ -}; - -static u32 bt2020_white_point[2] = { - 0.3127 * INORM + 0.5, 0.3290 * INORM + 0.5 -}; - -void prepare_hdr10_param( - struct vframe_master_display_colour_s *p_mdc, - struct hdr10_param_s *p_hdr10_param) -{ - struct vframe_content_light_level_s *p_cll = - &p_mdc->content_light_level; - bool flag = false; - uint32_t max_lum = 1000 * 10000; - uint32_t min_lum = 50; - - if ((p_mdc->present_flag) - && !(dolby_vision_flags & FLAG_CERTIFICAION)) { - if (p_mdc->luminance[0]) - max_lum = p_mdc->luminance[0]; - if (p_mdc->luminance[1]) - min_lum = p_mdc->luminance[1]; - if ((p_hdr10_param-> - max_display_mastering_luminance - != max_lum) - || (p_hdr10_param-> - min_display_mastering_luminance - != min_lum) - || (p_hdr10_param->Rx - != p_mdc->primaries[2][0]) - || (p_hdr10_param->Ry - != p_mdc->primaries[2][1]) - || (p_hdr10_param->Gx - != p_mdc->primaries[0][0]) - || (p_hdr10_param->Gy - != p_mdc->primaries[0][1]) - || (p_hdr10_param->Bx - != p_mdc->primaries[1][0]) - || (p_hdr10_param->By - != p_mdc->primaries[1][1]) - || (p_hdr10_param->Wx - != p_mdc->white_point[0]) - || (p_hdr10_param->Wy - != p_mdc->white_point[1])) - flag = true; - if (true) { - p_hdr10_param-> - max_display_mastering_luminance - = max_lum; - p_hdr10_param-> - min_display_mastering_luminance - = min_lum; - p_hdr10_param->Rx - = p_mdc->primaries[2][0]; - p_hdr10_param->Ry - = p_mdc->primaries[2][1]; - p_hdr10_param->Gx - = p_mdc->primaries[0][0]; - p_hdr10_param->Gy - = p_mdc->primaries[0][1]; - p_hdr10_param->Bx - = p_mdc->primaries[1][0]; - p_hdr10_param->By - = p_mdc->primaries[1][1]; - p_hdr10_param->Wx - = p_mdc->white_point[0]; - p_hdr10_param->Wy - = p_mdc->white_point[1]; - } - } else { - if ((p_hdr10_param-> - min_display_mastering_luminance - != max_lum) - || (p_hdr10_param-> - max_display_mastering_luminance - != min_lum) - || (p_hdr10_param->Rx - != bt2020_primaries[2][0]) - || (p_hdr10_param->Ry - != bt2020_primaries[2][1]) - || (p_hdr10_param->Gx - != bt2020_primaries[0][0]) - || (p_hdr10_param->Gy - != bt2020_primaries[0][1]) - || (p_hdr10_param->Bx - != bt2020_primaries[1][0]) - || (p_hdr10_param->By - != bt2020_primaries[1][1]) - || (p_hdr10_param->Wx - != bt2020_white_point[0]) - || (p_hdr10_param->Wy - != bt2020_white_point[1])) - flag = true; - if (true) { - p_hdr10_param-> - min_display_mastering_luminance - = min_lum; - p_hdr10_param-> - max_display_mastering_luminance - = max_lum; - p_hdr10_param->Rx - = bt2020_primaries[2][0]; - p_hdr10_param->Ry - = bt2020_primaries[2][1]; - p_hdr10_param->Gx - = bt2020_primaries[0][0]; - p_hdr10_param->Gy - = bt2020_primaries[0][1]; - p_hdr10_param->Bx - = bt2020_primaries[1][0]; - p_hdr10_param->By - = bt2020_primaries[1][1]; - p_hdr10_param->Wx - = bt2020_white_point[0]; - p_hdr10_param->Wy - = bt2020_white_point[1]; - } - } - - if (p_cll->present_flag) { - if ((p_hdr10_param->max_content_light_level - != p_cll->max_content) - || (p_hdr10_param->max_pic_average_light_level - != p_cll->max_pic_average)) - flag = true; - if (flag) { - p_hdr10_param->max_content_light_level - = p_cll->max_content; - p_hdr10_param->max_pic_average_light_level - = p_cll->max_pic_average; - } - } else { - if ((p_hdr10_param->max_content_light_level != 0) - || (p_hdr10_param->max_pic_average_light_level != 0)) - flag = true; - if (true) { - p_hdr10_param->max_content_light_level = 0; - p_hdr10_param->max_pic_average_light_level = 0; - } - } - - if (flag) { - pr_dolby_dbg("HDR10:\n"); - pr_dolby_dbg("\tR = %04x, %04x\n", - p_hdr10_param->Rx, - p_hdr10_param->Ry); - pr_dolby_dbg("\tG = %04x, %04x\n", - p_hdr10_param->Gx, - p_hdr10_param->Gy); - pr_dolby_dbg("\tB = %04x, %04x\n", - p_hdr10_param->Bx, - p_hdr10_param->By); - pr_dolby_dbg("\tW = %04x, %04x\n", - p_hdr10_param->Wx, - p_hdr10_param->Wy); - pr_dolby_dbg("\tMax = %d\n", - p_hdr10_param-> - max_display_mastering_luminance); - pr_dolby_dbg("\tMin = %d\n", - p_hdr10_param-> - min_display_mastering_luminance); - pr_dolby_dbg("\tMCLL = %d\n", - p_hdr10_param-> - max_content_light_level); - pr_dolby_dbg("\tMPALL = %d\n\n", - p_hdr10_param-> - max_pic_average_light_level); - } -} - -static inline void fresh_tx_hdr_pkt(struct vout_device_s *vdev) -{ - if (vdev) { - if (vdev->fresh_tx_hdr_pkt) - vdev->fresh_tx_hdr_pkt(&hdr10_data); - } -} - -static inline void fresh_tx_vsif_pkt(struct vout_device_s *vdev, - int dv_en, int dv_mode) -{ - int tmp = (dv_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL ? 1 : 0); - - if (vdev) { - if (vdev->fresh_tx_vsif_pkt) - vdev->fresh_tx_vsif_pkt(dv_en, tmp); - } -} - -static bool send_hdmi_pkt( - enum signal_format_e dst_format, - const struct vinfo_s *vinfo) -{ - struct hdr_10_infoframe_s *p_hdr; - int i; - bool flag = false; - struct vout_device_s *vdev = NULL; - - if (vinfo->vout_device) - vdev = vinfo->vout_device; - - if (dst_format == FORMAT_HDR10) { - p_hdr = &dovi_setting.hdr_info; - hdr10_data.features = - (1 << 29) /* video available */ - | (5 << 26) /* unspecified */ - | (0 << 25) /* limit */ - | (1 << 24) /* color available */ - | (9 << 16) /* bt2020 */ - | (14 << 8) /* bt2020-10 */ - | (10 << 0);/* bt2020c */ - if (hdr10_data.primaries[0][0] != - ((p_hdr->display_primaries_x_0_MSB << 8) - | p_hdr->display_primaries_x_0_LSB)) - flag = true; - hdr10_data.primaries[0][0] = - (p_hdr->display_primaries_x_0_MSB << 8) - | p_hdr->display_primaries_x_0_LSB; - - if (hdr10_data.primaries[0][1] != - ((p_hdr->display_primaries_y_0_MSB << 8) - | p_hdr->display_primaries_y_0_LSB)) - flag = true; - hdr10_data.primaries[0][1] = - (p_hdr->display_primaries_y_0_MSB << 8) - | p_hdr->display_primaries_y_0_LSB; - - if (hdr10_data.primaries[1][0] != - ((p_hdr->display_primaries_x_1_MSB << 8) - | p_hdr->display_primaries_x_1_LSB)) - flag = true; - hdr10_data.primaries[1][0] = - (p_hdr->display_primaries_x_1_MSB << 8) - | p_hdr->display_primaries_x_1_LSB; - - if (hdr10_data.primaries[1][1] != - ((p_hdr->display_primaries_y_1_MSB << 8) - | p_hdr->display_primaries_y_1_LSB)) - flag = true; - hdr10_data.primaries[1][1] = - (p_hdr->display_primaries_y_1_MSB << 8) - | p_hdr->display_primaries_y_1_LSB; - - if (hdr10_data.primaries[2][0] != - ((p_hdr->display_primaries_x_2_MSB << 8) - | p_hdr->display_primaries_x_2_LSB)) - flag = true; - hdr10_data.primaries[2][0] = - (p_hdr->display_primaries_x_2_MSB << 8) - | p_hdr->display_primaries_x_2_LSB; - - if (hdr10_data.primaries[2][1] != - ((p_hdr->display_primaries_y_2_MSB << 8) - | p_hdr->display_primaries_y_2_LSB)) - flag = true; - hdr10_data.primaries[2][1] = - (p_hdr->display_primaries_y_2_MSB << 8) - | p_hdr->display_primaries_y_2_LSB; - - if (hdr10_data.white_point[0] != - ((p_hdr->white_point_x_MSB << 8) - | p_hdr->white_point_x_LSB)) - flag = true; - hdr10_data.white_point[0] = - (p_hdr->white_point_x_MSB << 8) - | p_hdr->white_point_x_LSB; - - if (hdr10_data.white_point[1] != - ((p_hdr->white_point_y_MSB << 8) - | p_hdr->white_point_y_LSB)) - flag = true; - hdr10_data.white_point[1] = - (p_hdr->white_point_y_MSB << 8) - | p_hdr->white_point_y_LSB; - - if (hdr10_data.luminance[0] != - ((p_hdr->max_display_mastering_luminance_MSB << 8) - | p_hdr->max_display_mastering_luminance_LSB)) - flag = true; - hdr10_data.luminance[0] = - (p_hdr->max_display_mastering_luminance_MSB << 8) - | p_hdr->max_display_mastering_luminance_LSB; - - if (hdr10_data.luminance[1] != - ((p_hdr->min_display_mastering_luminance_MSB << 8) - | p_hdr->min_display_mastering_luminance_LSB)) - flag = true; - hdr10_data.luminance[1] = - (p_hdr->min_display_mastering_luminance_MSB << 8) - | p_hdr->min_display_mastering_luminance_LSB; - - if (hdr10_data.max_content != - ((p_hdr->max_content_light_level_MSB << 8) - | p_hdr->max_content_light_level_LSB)) - flag = true; - hdr10_data.max_content = - (p_hdr->max_content_light_level_MSB << 8) - | p_hdr->max_content_light_level_LSB; - - if (hdr10_data.max_frame_average != - ((p_hdr->max_frame_average_light_level_MSB << 8) - | p_hdr->max_frame_average_light_level_LSB)) - flag = true; - hdr10_data.max_frame_average = - (p_hdr->max_frame_average_light_level_MSB << 8) - | p_hdr->max_frame_average_light_level_LSB; - fresh_tx_hdr_pkt(vdev); - fresh_tx_vsif_pkt(vdev, 0, 0); - - if (flag) { - pr_dolby_dbg("Info frame for hdr10 changed:\n"); - for (i = 0; i < 3; i++) - pr_dolby_dbg( - "\tprimaries[%1d] = %04x, %04x\n", - i, - hdr10_data.primaries[i][0], - hdr10_data.primaries[i][1]); - pr_dolby_dbg("\twhite_point = %04x, %04x\n", - hdr10_data.white_point[0], - hdr10_data.white_point[1]); - pr_dolby_dbg("\tMax = %d\n", - hdr10_data.luminance[0]); - pr_dolby_dbg("\tMin = %d\n", - hdr10_data.luminance[1]); - pr_dolby_dbg("\tMCLL = %d\n", - hdr10_data.max_content); - pr_dolby_dbg("\tMPALL = %d\n\n", - hdr10_data.max_frame_average); - } - } else if (dst_format == FORMAT_DOVI) { - hdr10_data.features = - (1 << 29) /* video available */ - | (5 << 26) /* unspecified */ - | (0 << 25) /* limit */ - | (1 << 24) /* color available */ - | (1 << 16) /* bt709 */ - | (1 << 8) /* bt709 */ - | (1 << 0); /* bt709 */ - for (i = 0; i < 3; i++) { - hdr10_data.primaries[i][0] = 0; - hdr10_data.primaries[i][1] = 0; - } - hdr10_data.white_point[0] = 0; - hdr10_data.white_point[1] = 0; - hdr10_data.luminance[0] = 0; - hdr10_data.luminance[1] = 0; - hdr10_data.max_content = 0; - hdr10_data.max_frame_average = 0; - fresh_tx_hdr_pkt(vdev); - fresh_tx_vsif_pkt(vdev, 1, dolby_vision_mode); - } else { - hdr10_data.features = - (1 << 29) /* video available */ - | (5 << 26) /* unspecified */ - | (0 << 25) /* limit */ - | (1 << 24) /* color available */ - | (1 << 16) /* bt709 */ - | (1 << 8) /* bt709 */ - | (1 << 0); /* bt709 */ - for (i = 0; i < 3; i++) { - hdr10_data.primaries[i][0] = 0; - hdr10_data.primaries[i][1] = 0; - } - hdr10_data.white_point[0] = 0; - hdr10_data.white_point[1] = 0; - hdr10_data.luminance[0] = 0; - hdr10_data.luminance[1] = 0; - hdr10_data.max_content = 0; - hdr10_data.max_frame_average = 0; - fresh_tx_hdr_pkt(vdev); - fresh_tx_vsif_pkt(vdev, 0, 0); - } - return flag; -} - -static uint32_t null_vf_cnt; -static bool video_off_handled; -static int is_video_output_off(struct vframe_s *vf) -{ - if ((READ_VPP_REG(VPP_MISC) & (1<<10)) == 0) { - if (vf == NULL) - null_vf_cnt++; - else - null_vf_cnt = 0; - if (null_vf_cnt > 5) { - null_vf_cnt = 0; - return 1; - } - } else - video_off_handled = 0; - return 0; -} - -#define signal_color_primaries ((vf->signal_type >> 16) & 0xff) -#define signal_transfer_characteristic ((vf->signal_type >> 8) & 0xff) -static int dolby_vision_parse_metadata(struct vframe_s *vf) -{ - const struct vinfo_s *vinfo = get_current_vinfo(); - struct vframe_s *el_vf; - struct provider_aux_req_s req; - struct provider_aux_req_s el_req; - int flag; - enum signal_format_e src_format = FORMAT_SDR; - enum signal_format_e dst_format; - int total_md_size = 0; - int total_comp_size = 0; - bool el_flag = 0; - bool el_halfsize_flag = 1; - uint32_t w = vinfo->width; - uint32_t h = vinfo->height; - int meta_flag_bl = 1; - int meta_flag_el = 1; - struct vframe_master_display_colour_s *p_mdc = - &vf->prop.master_display_colour; - unsigned int current_mode = dolby_vision_mode; - uint32_t target_lumin_max = 0; - struct vout_device_s *vdev = NULL; - unsigned int ieeeoui = 0; - - if ((!dolby_vision_enable) || (!p_funcs)) - return -1; - - if (vinfo->vout_device) { - vdev = vinfo->vout_device; - if (vdev->dv_info) - ieeeoui = vdev->dv_info->ieeeoui; - } - - if (vf) { - pr_dolby_dbg("frame %d pts %lld:\n", frame_count, vf->pts_us64); - - /* check source format */ - if (signal_transfer_characteristic == 16) - video_is_hdr10 = true; - else - video_is_hdr10 = false; - - if (video_is_hdr10 || p_mdc->present_flag) - src_format = FORMAT_HDR10; - - /* prepare parameter from SEI for hdr10 */ - if (src_format == FORMAT_HDR10) - prepare_hdr10_param(p_mdc, &hdr10_param); - - req.vf = vf; - req.bot_flag = 0; - req.aux_buf = NULL; - req.aux_size = 0; - req.dv_enhance_exist = 0; - vf_notify_provider_by_name("dvbldec", - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); - /* parse meta in base layer */ - if (dolby_vision_flags & FLAG_META_FROM_BL) - meta_flag_bl = parse_sei_and_meta( - vf, &req, - &total_comp_size, &total_md_size, - &src_format); - if (req.dv_enhance_exist) { - el_vf = dvel_vf_get(); - if (el_vf && - ((el_vf->pts_us64 == vf->pts_us64) - || !(dolby_vision_flags & FLAG_CHECK_ES_PTS))) { - if (debug_dolby & 2) - pr_dolby_dbg("+++ get bl(%p-%lld) with el(%p-%lld) +++\n", - vf, vf->pts_us64, - el_vf, el_vf->pts_us64); - el_req.vf = el_vf; - el_req.bot_flag = 0; - el_req.aux_buf = NULL; - el_req.aux_size = 0; - vf_notify_provider_by_name("dveldec", - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&el_req); - /* parse meta in enhanced layer */ - if (!(dolby_vision_flags & FLAG_META_FROM_BL)) - meta_flag_el = parse_sei_and_meta( - el_vf, &el_req, - &total_comp_size, - &total_md_size, - &src_format); - dolby_vision_vf_add(vf, el_vf); - if (dolby_vision_flags) { - el_flag = 1; - if (vf->width == el_vf->width) - el_halfsize_flag = 0; - } - } else { - if (!el_vf) - pr_dolby_error( - "bl(%p-%lld) not found el\n", - vf, vf->pts_us64); - else - pr_dolby_error( - "bl(%p-%lld) not found el(%p-%lld)\n", - vf, vf->pts_us64, - el_vf, el_vf->pts_us64); - } - } else { - if (debug_dolby & 2) - pr_dolby_dbg( - "+++ get bl(%p-%lld) +++\n", - vf, vf->pts_us64); - dolby_vision_vf_add(vf, NULL); - } - if ((src_format == FORMAT_DOVI) - && meta_flag_bl && meta_flag_el) { - /* dovi frame no meta or meta error */ - /* use old setting for this frame */ - return -1; - } - w = (vf->type & VIDTYPE_COMPRESS) ? - vf->compWidth : vf->width; - h = (vf->type & VIDTYPE_COMPRESS) ? - vf->compHeight : vf->height; - } - - /* if not DOVI, release metadata_parser */ - if ((src_format != FORMAT_DOVI) && metadata_parser) { - p_funcs->metadata_parser_release(); - metadata_parser = NULL; - } - - current_mode = dolby_vision_mode; - if (dolby_vision_policy_process( - ¤t_mode, src_format)) { - dolby_vision_set_toggle_flag(1); - if ((current_mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) - && (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS)) - dolby_vision_wait_on = true; - dolby_vision_mode = current_mode; - } - - if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { - new_dovi_setting.video_width = 0; - new_dovi_setting.video_height = 0; - return -1; - } - - /* check target luminance */ - if (is_graphics_output_off()) { - dolby_vision_graphic_min = 0; - dolby_vision_graphic_max = 0; - } else { - dolby_vision_graphic_min = 50; - dolby_vision_graphic_max = 100; - } - if (dolby_vision_flags & FLAG_USE_SINK_MIN_MAX) { - if (ieeeoui == 0x00d046) { - if (vdev->dv_info->ver == 0) { - /* need lookup PQ table ... */ - /*dolby_vision_graphic_min =*/ - /*dolby_vision_target_min =*/ - /* vdev->dv_info.ver0.target_min_pq;*/ - /*dolby_vision_graphic_max =*/ - /*target_lumin_max =*/ - /* vdev->dv_info.ver0.target_max_pq;*/ - } else if (vdev->dv_info->ver == 1) { - if (vdev->dv_info-> - vers.ver1.target_max_lum) { - /* Target max luminance = 100+50*CV */ - dolby_vision_graphic_max = - target_lumin_max = - (vdev->dv_info-> - vers.ver1.target_max_lum - * 50 + 100); - /* Target min luminance = (CV/127)^2 */ - dolby_vision_graphic_min = - dolby_vision_target_min = - (vdev->dv_info-> - vers.ver1.target_min_lum ^ 2) - * 10000 / (127 * 127); - } - } - } else if (vinfo->hdr_info.hdr_support & 4) { - if (vinfo->hdr_info.lumi_max) { - /* Luminance value = 50 * (2 ^ (CV/32)) */ - dolby_vision_graphic_max = - target_lumin_max = 50 * - (2 ^ (vinfo->hdr_info.lumi_max >> 5)); - /* Desired Content Min Luminance =*/ - /*Desired Content Max Luminance*/ - /* (CV/255) * (CV/255) / 100 */ - dolby_vision_graphic_min = - dolby_vision_target_min = - target_lumin_max * 10000 - * vinfo->hdr_info.lumi_min - * vinfo->hdr_info.lumi_min - / (255 * 255 * 100); - } - } - if (target_lumin_max) { - dolby_vision_target_max[0][0] = - dolby_vision_target_max[0][1] = - dolby_vision_target_max[1][0] = - dolby_vision_target_max[1][1] = - dolby_vision_target_max[2][0] = - dolby_vision_target_max[2][1] = - target_lumin_max; - } else { - memcpy( - dolby_vision_target_max, - dolby_vision_default_max, - sizeof(dolby_vision_target_max)); - } - } - - /* check dst format */ - if ((dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) - || (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT)) - dst_format = FORMAT_DOVI; - else if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_HDR10) - dst_format = FORMAT_HDR10; - else - dst_format = FORMAT_SDR; - - new_dovi_setting.video_width = w << 16; - new_dovi_setting.video_height = h << 16; - flag = p_funcs->control_path( - src_format, dst_format, - comp_buf, total_comp_size, - md_buf, total_md_size, - VIDEO_PRIORITY, - 12, 0, SIG_RANGE_SMPTE, /* bit/chroma/range */ - dolby_vision_graphic_min, - dolby_vision_graphic_max * 10000, - dolby_vision_target_min, - dolby_vision_target_max[src_format][dst_format] * 10000, - (!el_flag) || - (dolby_vision_flags & FLAG_DISABLE_COMPOSER), - &hdr10_param, - &new_dovi_setting); - if (flag >= 0) { - new_dovi_setting.src_format = src_format; - new_dovi_setting.dst_format = dst_format; - new_dovi_setting.el_flag = el_flag; - new_dovi_setting.el_halfsize_flag = el_halfsize_flag; - new_dovi_setting.video_width = w; - new_dovi_setting.video_height = h; - if (el_flag) - pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%02x,md_%s=%d,comp=%d\n", - src_format, dst_format, - dolby_vision_target_min, - dolby_vision_target_max[src_format][dst_format], - flag, meta_flag_bl ? "el" : "bl", - total_md_size, total_comp_size); - else - pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%02x,md_%s=%d\n", - src_format, dst_format, - dolby_vision_target_min, - dolby_vision_target_max[src_format][dst_format], - flag, meta_flag_bl ? "el" : "bl", - total_md_size); - dump_setting(&new_dovi_setting, frame_count, debug_dolby); - return 0; /* setting updated */ - } - - new_dovi_setting.video_width = 0; - new_dovi_setting.video_height = 0; - pr_dolby_error("control_path() failed\n"); - - return -1; /* do nothing for this frame */ -} - -int dolby_vision_update_metadata(struct vframe_s *vf) -{ - int ret = -1; - - if (!dolby_vision_enable) - return -1; - - if (vf && dolby_vision_vf_check(vf)) { - ret = dolby_vision_parse_metadata(vf); - frame_count++; - } - - return ret; -} -EXPORT_SYMBOL(dolby_vision_update_metadata); - -static unsigned int last_dolby_vision_policy; -int dolby_vision_process(struct vframe_s *vf) -{ - const struct vinfo_s *vinfo = get_current_vinfo(); - - if (get_cpu_type() != MESON_CPU_MAJOR_ID_GXM) - return -1; - - if ((!dolby_vision_enable) || (!p_funcs)) - return -1; - - if (is_dolby_vision_on() - && is_video_output_off(vf) - && !video_off_handled) { - dolby_vision_set_toggle_flag(1); - pr_dolby_dbg("video off\n"); - if (debug_dolby) - video_off_handled = 1; - } - - if (last_dolby_vision_policy != dolby_vision_policy) { - /* handle policy change */ - dolby_vision_set_toggle_flag(1); - last_dolby_vision_policy = dolby_vision_policy; - } else if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { - if (dolby_vision_status != BYPASS_PROCESS) { - enable_dolby_vision(0); - send_hdmi_pkt(FORMAT_SDR, vinfo); - if (dolby_vision_flags & FLAG_TOGGLE_FRAME) - dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; - } - return 0; - } - - if (!vf) { - if ((dolby_vision_flags & FLAG_TOGGLE_FRAME)) - dolby_vision_parse_metadata(NULL); - } - if (dolby_vision_flags & FLAG_RESET_EACH_FRAME) - dolby_vision_set_toggle_flag(1); - - if (dolby_vision_flags & FLAG_TOGGLE_FRAME) { - if ((new_dovi_setting.video_width & 0xffff) - && (new_dovi_setting.video_height & 0xffff)) { - memcpy(&dovi_setting, &new_dovi_setting, - sizeof(dovi_setting)); - new_dovi_setting.video_width = - new_dovi_setting.video_height = 0; - } - dolby_core1_set( - 24, 173, 256 * 5, - (uint32_t *)&dovi_setting.dm_reg1, - (uint32_t *)&dovi_setting.comp_reg, - (uint32_t *)&dovi_setting.dm_lut1, - dovi_setting.video_width, - dovi_setting.video_height, - 1, /* BL enable */ - dovi_setting.el_flag, /* EL enable */ - dovi_setting.el_halfsize_flag, /* if BL and EL is 4:1 */ - dolby_vision_mode == - DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL, - dovi_setting.src_format == FORMAT_DOVI, - 1); - dolby_core2_set( - 24, 256 * 5, - (uint32_t *)&dovi_setting.dm_reg2, - (uint32_t *)&dovi_setting.dm_lut2, - 1920, 1080, 1, 1); - dolby_core3_set( - 26, dovi_setting.md_reg3.size, - (uint32_t *)&dovi_setting.dm_reg3, - dovi_setting.md_reg3.raw_metadata, - vinfo->width, vinfo->height, 1, - dolby_vision_mode == - DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL); - enable_dolby_vision(1); - /* update dolby_vision_status */ - if ((dovi_setting.src_format == FORMAT_DOVI) - && (dolby_vision_status != DV_PROCESS)) { - pr_dolby_dbg( - "Dolby Vision mode changed to DV_PROCESS %d\n", - dovi_setting.src_format); - dolby_vision_status = DV_PROCESS; - } else if ((dovi_setting.src_format == FORMAT_HDR10) - && (dolby_vision_status != HDR_PROCESS)) { - pr_dolby_dbg( - "Dolby Vision mode changed to HDR_PROCESS %d\n", - dovi_setting.src_format); - dolby_vision_status = HDR_PROCESS; - } else if ((dovi_setting.src_format == FORMAT_SDR) - && (dolby_vision_status != SDR_PROCESS)) { - pr_dolby_dbg( - "Dolby Vision mode changed to SDR_PROCESS %d\n", - dovi_setting.src_format); - dolby_vision_status = SDR_PROCESS; - } - /* send HDMI packet according to dst_format */ - send_hdmi_pkt(dovi_setting.dst_format, vinfo); - dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; - } - return 0; -} -EXPORT_SYMBOL(dolby_vision_process); - -bool is_dolby_vision_on(void) -{ - return dolby_vision_on - || dolby_vision_wait_on; -} -EXPORT_SYMBOL(is_dolby_vision_on); - -bool for_dolby_vision_certification(void) -{ - return is_dolby_vision_on() && - dolby_vision_flags & FLAG_CERTIFICAION; -} -EXPORT_SYMBOL(for_dolby_vision_certification); - -void dolby_vision_set_toggle_flag(int flag) -{ - if (flag) - dolby_vision_flags |= FLAG_TOGGLE_FRAME; - else - dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; -} -EXPORT_SYMBOL(dolby_vision_set_toggle_flag); - -void set_dolby_vision_mode(int mode) -{ - if ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXM) - && dolby_vision_enable) { - video_is_hdr10 = false; - if (dolby_vision_policy_process( - &mode, FORMAT_SDR)) { - dolby_vision_set_toggle_flag(1); - if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) - && (dolby_vision_mode == - DOLBY_VISION_OUTPUT_MODE_BYPASS)) - dolby_vision_wait_on = true; - pr_info("DOVI output change from %d to %d\n", - dolby_vision_mode, mode); - dolby_vision_mode = mode; - } - } -} -EXPORT_SYMBOL(set_dolby_vision_mode); - -int get_dolby_vision_mode(void) -{ - return dolby_vision_mode; -} -EXPORT_SYMBOL(get_dolby_vision_mode); - -bool is_dolby_vision_enable(void) -{ - return dolby_vision_enable; -} -EXPORT_SYMBOL(is_dolby_vision_enable); - -int register_dv_functions(const struct dolby_vision_func_s *func) -{ - int ret = -1; - - if (!p_funcs && func) { - pr_info("*** register_dv_functions\n ***"); - p_funcs = func; - ret = 0; - } - return ret; -} -EXPORT_SYMBOL(register_dv_functions); - -int unregister_dv_functions(void) -{ - int ret = -1; - - if (p_funcs) { - pr_info("*** unregister_dv_functions\n ***"); - p_funcs = NULL; - ret = 0; - } - return ret; -} -EXPORT_SYMBOL(unregister_dv_functions); diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 5c650fa7bafd..6886d81e5619 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -55,6 +55,7 @@ #include "amcsc.h" #include "keystone_correction.h" #include "bitdepth.h" +#include #define pr_amvecm_dbg(fmt, args...)\ do {\ @@ -3178,8 +3179,8 @@ static void amvecm_pq_enable(int enable) { if (enable) { vecm_latch_flag |= FLAG_VE_DNLP_EN; - - amcm_enable(); + if (!is_dolby_vision_enable()) + amcm_enable(); WRITE_VPP_REG_BITS(SRSHARP0_PK_NR_ENABLE, 1, 1, 1); WRITE_VPP_REG_BITS(SRSHARP1_PK_NR_ENABLE, 1, 1, 1); @@ -3452,14 +3453,9 @@ static const char *amvecm_debug_usage_str = { "echo vpp_mtx vd1_12 rgb2yuv > /sys/class/amvecm/debug; 12bit vd1 mtx\n" "echo vpp_mtx vd1_12 yuv2rgb > /sys/class/amvecm/debug; 12bit vd1 mtx\n" "echo bitdepth 10/12/other-num > /sys/class/amvecm/debug; config data path\n" - "echo dolby_config 0/1/2.. > /sys/class/amvecm/debug; dolby dma table config\n" - "echo dolby_crc 0/1 > /sys/class/amvecm/debug; dolby_crc insert or clr\n" "echo datapath_config param1(D) param2(D) > /sys/class/amvecm/debug; config data path\n" "echo datapath_status > /sys/class/amvecm/debug; data path status\n" - "echo dolby_dma index(D) value(H) > /sys/class/amvecm/debug; dolby dma table modify\n" "echo clip_config 0/1/2/.. 0/1/... 0/1 > /sys/class/amvecm/debug; config clip\n" - "echo dv_efuse > /sys/class/amvecm/debug; get dv efuse info\n" - "echo dv_el > /sys/class/amvecm/debug; get dv enhanced layer info\n" }; static ssize_t amvecm_debug_show(struct class *cla, struct class_attribute *attr, char *buf) @@ -3749,63 +3745,6 @@ static ssize_t amvecm_debug_store(struct class *cla, return count; } -/* supported mode: IPT_TUNNEL/HDR10/SDR10 */ -static const int dv_mode_table[6] = { - 5, /*DOLBY_VISION_OUTPUT_MODE_BYPASS*/ - 0, /*DOLBY_VISION_OUTPUT_MODE_IPT*/ - 1, /*DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL*/ - 2, /*DOLBY_VISION_OUTPUT_MODE_HDR10*/ - 3, /*DOLBY_VISION_OUTPUT_MODE_SDR10*/ - 4, /*DOLBY_VISION_OUTPUT_MODE_SDR8*/ -}; - -static const char dv_mode_str[6][12] = { - "IPT", - "IPT_TUNNEL", - "HDR10", - "SDR10", - "SDR8", - "BYPASS" -}; - -static ssize_t amvecm_dv_mode_show(struct class *cla, - struct class_attribute *attr, char *buf) -{ - pr_info("usage: echo mode > /sys/class/amvecm/dv_mode\n"); - pr_info("\tDOLBY_VISION_OUTPUT_MODE_BYPASS 0\n"); - pr_info("\tDOLBY_VISION_OUTPUT_MODE_IPT 1\n"); - pr_info("\tDOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL 2\n"); - pr_info("\tDOLBY_VISION_OUTPUT_MODE_HDR10 3\n"); - pr_info("\tDOLBY_VISION_OUTPUT_MODE_SDR10 4\n"); - pr_info("\tDOLBY_VISION_OUTPUT_MODE_SDR8 5\n"); - if (is_dolby_vision_enable()) - pr_info("current dv_mode = %s\n", - dv_mode_str[get_dolby_vision_mode()]); - else - pr_info("current dv_mode = off\n"); - return 0; -} - -static ssize_t amvecm_dv_mode_store(struct class *cla, - struct class_attribute *attr, - const char *buf, size_t count) -{ - size_t r; - int val; - - r = sscanf(buf, "%x\n", &val); - if ((r != 1)) - return -EINVAL; - - if ((val >= 0) && (val < 6)) - set_dolby_vision_mode(dv_mode_table[val]); - else if (val & 0x200) - dolby_vision_dump_struct(); - else if (val & 0x70) - dolby_vision_dump_setting(val); - return count; -} - static const char *amvecm_reg_usage_str = { "Usage:\n" "echo rv addr(H) > /sys/class/amvecm/reg;\n" @@ -4086,8 +4025,6 @@ static struct class_attribute amvecm_class_attrs[] = { set_hdr_289lut_show, set_hdr_289lut_store), __ATTR(vpp_demo, 0644, amvecm_vpp_demo_show, amvecm_vpp_demo_store), - __ATTR(dv_mode, 0644, - amvecm_dv_mode_show, amvecm_dv_mode_store), __ATTR(reg, 0644, amvecm_reg_show, amvecm_reg_store), __ATTR(pq_user_set, 0644, @@ -4160,8 +4097,10 @@ static void aml_vecm_dt_parse(struct platform_device *pdev) amvecm_gamma_init(gamma_en); if (!is_dolby_vision_enable()) WRITE_VPP_REG_BITS(VPP_MISC, 1, 28, 1); - if (cm_en) - amcm_enable(); + if (cm_en) { + if (!is_dolby_vision_enable()) + amcm_enable(); + } else amcm_disable(); /* WRITE_VPP_REG_BITS(VPP_MISC, cm_en, 28, 1); */ @@ -4274,8 +4213,6 @@ static int aml_vecm_probe(struct platform_device *pdev) else vlock_en = 0; aml_vecm_dt_parse(pdev); - if (is_meson_gxm_cpu()) - dolby_vision_init_receiver(); probe_ok = 1; pr_info("%s: ok\n", __func__); return 0; diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h index 8d3b1ea88745..9edbc21b8b70 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h @@ -60,15 +60,34 @@ #define DOLBY_CORE3_SWAP_CTRL4 0x36f5 #define DOLBY_CORE3_SWAP_CTRL5 0x36f6 #define DOLBY_CORE3_SWAP_CTRL6 0x36f7 +#define DOLBY_CORE3_DIAG_CTRL 0x36f8 + #define DOLBY_CORE3_CRC_CTRL 0x36fb #define DOLBY_CORE3_INPUT_CSC_CRC 0x36fc #define DOLBY_CORE3_OUTPUT_CSC_CRC 0x36fd +#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d +#define DOLBY_PATH_CTRL 0x1a0c #define VIU_MISC_CTRL1 0x1a07 #define VPP_DOLBY_CTRL 0x1d93 #define VIU_SW_RESET 0x1a01 #define VPU_HDMI_FMT_CTRL 0x2743 - +#define DOLBY_TV_REG_START 0x3300 +#define DOLBY_TV_CLKGATE_CTRL 0x33f1 +#define DOLBY_TV_SWAP_CTRL0 0x33f2 +#define DOLBY_TV_SWAP_CTRL1 0x33f3 +#define DOLBY_TV_SWAP_CTRL2 0x33f4 +#define DOLBY_TV_SWAP_CTRL3 0x33f5 +#define DOLBY_TV_SWAP_CTRL4 0x33f6 +#define DOLBY_TV_SWAP_CTRL5 0x33f7 +#define DOLBY_TV_SWAP_CTRL6 0x33f8 +#define DOLBY_TV_SWAP_CTRL7 0x33f9 +#define DOLBY_TV_AXI2DMA_CTRL0 0x33fa +#define DOLBY_TV_AXI2DMA_CTRL1 0x33fb +#define DOLBY_TV_AXI2DMA_CTRL2 0x33fc +#define DOLBY_TV_AXI2DMA_CTRL3 0x33fd +#define DOLBY_TV_STATUS0 0x33fe +#define DOLBY_TV_STATUS1 0x33ff #if 0 /* core 1 display manager 24 registers */ struct dm_register_ipcore_1_s { diff --git a/drivers/amlogic/media/enhancement/amvecm/dolby_vision/dolby_vision.h b/drivers/amlogic/media/enhancement/amvecm/dolby_vision/dolby_vision.h deleted file mode 100644 index d550b8806423..000000000000 --- a/drivers/amlogic/media/enhancement/amvecm/dolby_vision/dolby_vision.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - * drivers/amlogic/media/enhancement/amvecm/dolby_vision/dolby_vision.h - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - */ - -#ifndef _DV_H_ -#define _DV_H_ - -#include - -#define DEF_G2L_LUT_SIZE_2P 8 -#define DEF_G2L_LUT_SIZE (1 << DEF_G2L_LUT_SIZE_2P) - -enum signal_format_e { - FORMAT_DOVI = 0, - FORMAT_HDR10 = 1, - FORMAT_SDR = 2 -}; - -enum priority_mode_e { - VIDEO_PRIORITY = 0, - GRAPHIC_PRIORITY = 1 -}; - -enum cp_signal_range_e { - SIG_RANGE_SMPTE = 0, /* head range */ - SIG_RANGE_FULL = 1, /* full range */ - SIG_RANGE_SDI = 2 /* PQ */ -}; - -struct composer_register_ipcore_s { - uint32_t Composer_Mode; - uint32_t VDR_Resolution; - uint32_t Bit_Depth; - uint32_t Coefficient_Log2_Denominator; - uint32_t BL_Num_Pivots_Y; - uint32_t BL_Pivot[5]; - uint32_t BL_Order; - uint32_t BL_Coefficient_Y[8][3]; - uint32_t EL_NLQ_Offset_Y; - uint32_t EL_Coefficient_Y[3]; - uint32_t Mapping_IDC_U; - uint32_t BL_Num_Pivots_U; - uint32_t BL_Pivot_U[3]; - uint32_t BL_Order_U; - uint32_t BL_Coefficient_U[4][3]; - uint32_t MMR_Coefficient_U[22][2]; - uint32_t MMR_Order_U; - uint32_t EL_NLQ_Offset_U; - uint32_t EL_Coefficient_U[3]; - uint32_t Mapping_IDC_V; - uint32_t BL_Num_Pivots_V; - uint32_t BL_Pivot_V[3]; - uint32_t BL_Order_V; - uint32_t BL_Coefficient_V[4][3]; - uint32_t MMR_Coefficient_V[22][2]; - uint32_t MMR_Order_V; - uint32_t EL_NLQ_Offset_V; - uint32_t EL_Coefficient_V[3]; -}; - -/** @brief DM registers for IPCORE 1 */ -struct dm_register_ipcore_1_s { - uint32_t SRange; - uint32_t Srange_Inverse; - uint32_t Frame_Format_1; - uint32_t Frame_Format_2; - uint32_t Frame_Pixel_Def; - uint32_t Y2RGB_Coefficient_1; - uint32_t Y2RGB_Coefficient_2; - uint32_t Y2RGB_Coefficient_3; - uint32_t Y2RGB_Coefficient_4; - uint32_t Y2RGB_Coefficient_5; - uint32_t Y2RGB_Offset_1; - uint32_t Y2RGB_Offset_2; - uint32_t Y2RGB_Offset_3; - uint32_t EOTF; - uint32_t A2B_Coefficient_1; - uint32_t A2B_Coefficient_2; - uint32_t A2B_Coefficient_3; - uint32_t A2B_Coefficient_4; - uint32_t A2B_Coefficient_5; - uint32_t C2D_Coefficient_1; - uint32_t C2D_Coefficient_2; - uint32_t C2D_Coefficient_3; - uint32_t C2D_Coefficient_4; - uint32_t C2D_Coefficient_5; - uint32_t C2D_Offset; - uint32_t Active_area_left_top; - uint32_t Active_area_bottom_right; -}; - -/** @brief DM registers for IPCORE 2 */ -struct dm_register_ipcore_2_s { - uint32_t SRange; - uint32_t Srange_Inverse; - uint32_t Y2RGB_Coefficient_1; - uint32_t Y2RGB_Coefficient_2; - uint32_t Y2RGB_Coefficient_3; - uint32_t Y2RGB_Coefficient_4; - uint32_t Y2RGB_Coefficient_5; - uint32_t Y2RGB_Offset_1; - uint32_t Y2RGB_Offset_2; - uint32_t Y2RGB_Offset_3; - uint32_t Frame_Format; - uint32_t EOTF; - uint32_t A2B_Coefficient_1; - uint32_t A2B_Coefficient_2; - uint32_t A2B_Coefficient_3; - uint32_t A2B_Coefficient_4; - uint32_t A2B_Coefficient_5; - uint32_t C2D_Coefficient_1; - uint32_t C2D_Coefficient_2; - uint32_t C2D_Coefficient_3; - uint32_t C2D_Coefficient_4; - uint32_t C2D_Coefficient_5; - uint32_t C2D_Offset; - uint32_t VDR_Resolution; -}; - -/** @brief DM registers for IPCORE 3 */ -struct dm_register_ipcore_3_s { - uint32_t D2C_coefficient_1; - uint32_t D2C_coefficient_2; - uint32_t D2C_coefficient_3; - uint32_t D2C_coefficient_4; - uint32_t D2C_coefficient_5; - uint32_t B2A_Coefficient_1; - uint32_t B2A_Coefficient_2; - uint32_t B2A_Coefficient_3; - uint32_t B2A_Coefficient_4; - uint32_t B2A_Coefficient_5; - uint32_t Eotf_param_1; - uint32_t Eotf_param_2; - uint32_t IPT_Scale; - uint32_t IPT_Offset_1; - uint32_t IPT_Offset_2; - uint32_t IPT_Offset_3; - uint32_t Output_range_1; - uint32_t Output_range_2; - uint32_t RGB2YUV_coefficient_register1; - uint32_t RGB2YUV_coefficient_register2; - uint32_t RGB2YUV_coefficient_register3; - uint32_t RGB2YUV_coefficient_register4; - uint32_t RGB2YUV_coefficient_register5; - uint32_t RGB2YUV_offset_0; - uint32_t RGB2YUV_offset_1; - uint32_t RGB2YUV_offset_2; -}; - -/** @brief DM luts for IPCORE 1 and 2 */ -struct dm_lut_ipcore_s { - uint32_t TmLutI[64*4]; - uint32_t TmLutS[64*4]; - uint32_t SmLutI[64*4]; - uint32_t SmLutS[64*4]; - uint32_t G2L[DEF_G2L_LUT_SIZE]; -}; - -/** @brief hdmi metadata for IPCORE 3 */ -struct md_reister_ipcore_3_s { - uint32_t raw_metadata[128]; - uint32_t size; -}; - -struct hdr_10_infoframe_s { - uint8_t infoframe_type_code; - uint8_t infoframe_version_number; - uint8_t length_of_info_frame; - uint8_t data_byte_1; - uint8_t data_byte_2; - uint8_t display_primaries_x_0_LSB; - uint8_t display_primaries_x_0_MSB; - uint8_t display_primaries_y_0_LSB; - uint8_t display_primaries_y_0_MSB; - uint8_t display_primaries_x_1_LSB; - uint8_t display_primaries_x_1_MSB; - uint8_t display_primaries_y_1_LSB; - uint8_t display_primaries_y_1_MSB; - uint8_t display_primaries_x_2_LSB; - uint8_t display_primaries_x_2_MSB; - uint8_t display_primaries_y_2_LSB; - uint8_t display_primaries_y_2_MSB; - uint8_t white_point_x_LSB; - uint8_t white_point_x_MSB; - uint8_t white_point_y_LSB; - uint8_t white_point_y_MSB; - uint8_t max_display_mastering_luminance_LSB; - uint8_t max_display_mastering_luminance_MSB; - uint8_t min_display_mastering_luminance_LSB; - uint8_t min_display_mastering_luminance_MSB; - uint8_t max_content_light_level_LSB; - uint8_t max_content_light_level_MSB; - uint8_t max_frame_average_light_level_LSB; - uint8_t max_frame_average_light_level_MSB; -}; - -struct hdr10_param_s { - uint32_t min_display_mastering_luminance; - uint32_t max_display_mastering_luminance; - uint16_t Rx; - uint16_t Ry; - uint16_t Gx; - uint16_t Gy; - uint16_t Bx; - uint16_t By; - uint16_t Wx; - uint16_t Wy; - uint16_t max_content_light_level; - uint16_t max_pic_average_light_level; -}; - -struct dovi_setting_s { - struct composer_register_ipcore_s comp_reg; - struct dm_register_ipcore_1_s dm_reg1; - struct dm_register_ipcore_2_s dm_reg2; - struct dm_register_ipcore_3_s dm_reg3; - struct dm_lut_ipcore_s dm_lut1; - struct dm_lut_ipcore_s dm_lut2; - /* for dovi output */ - struct md_reister_ipcore_3_s md_reg3; - /* for hdr10 output */ - struct hdr_10_infoframe_s hdr_info; - /* current process */ - enum signal_format_e src_format; - enum signal_format_e dst_format; - /* enhanced layer */ - bool el_flag; - bool el_halfsize_flag; - /* frame width & height */ - uint32_t video_width; - uint32_t video_height; -}; - -extern int control_path( - enum signal_format_e in_format, - enum signal_format_e out_format, - char *in_comp, int in_comp_size, - char *in_md, int in_md_size, - enum priority_mode_e set_priority, - int set_bit_depth, int set_chroma_format, int set_yuv_range, - int set_graphic_min_lum, int set_graphic_max_lum, - int set_target_min_lum, int set_target_max_lum, - int set_no_el, - struct hdr10_param_s *hdr10_param, - struct dovi_setting_s *output); -extern void *metadata_parser_init(int flag); -extern int metadata_parser_reset(int flag); -extern int metadata_parser_process( - char *src_rpu, int rpu_len, - char *dst_comp, int *comp_len, - char *dst_md, int *md_len, bool src_eos); -extern void metadata_parser_release(void); - -struct dolby_vision_func_s { - void * (*metadata_parser_init)(int); - int (*metadata_parser_reset)(int flag); - int (*metadata_parser_process)( - char *src_rpu, int rpu_len, - char *dst_comp, int *comp_len, - char *dst_md, int *md_len, bool src_eos); - void (*metadata_parser_release)(void); - int (*control_path)( - enum signal_format_e in_format, - enum signal_format_e out_format, - char *in_comp, int in_comp_size, - char *in_md, int in_md_size, - enum priority_mode_e set_priority, - int set_bit_depth, int set_chroma_format, int set_yuv_range, - int set_graphic_min_lum, int set_graphic_max_lum, - int set_target_min_lum, int set_target_max_lum, - int set_no_el, - struct hdr10_param_s *hdr10_param, - struct dovi_setting_s *output); -}; - -extern int register_dv_functions(const struct dolby_vision_func_s *func); -extern int unregister_dv_functions(void); -#ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA -#define VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) -#define VSYNC_RD_MPEG_REG(adr) READ_VPP_REG(adr) -#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ - WRITE_VPP_REG_BITS(adr, val, start, len) -#else -extern int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); -extern u32 VSYNC_RD_MPEG_REG(u32 adr); -extern int VSYNC_WR_MPEG_REG(u32 adr, u32 val); -#endif - -#endif diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index f7049e17c62b..4def52daf1f8 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -3048,7 +3048,7 @@ static struct osd_device_data_s osd_g12a = { .has_deband = 1, .has_lut = 1, .has_rdma = 1, - .has_dolby_vision = 0, + .has_dolby_vision = 1, .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 9fc6c16e8c8d..8af26bb47da8 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -5203,6 +5203,7 @@ static void osd_basic_update_disp_geometry(u32 index) { struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index]; u32 data32; + u32 buffer_w, buffer_h; data32 = (osd_hw.dispdata[index].x_start & 0xfff) | (osd_hw.dispdata[index].x_end & 0xfff) << 16; @@ -5347,6 +5348,27 @@ static void osd_basic_update_disp_geometry(u32 index) | (osd_hw.pandata[index].y_end & 0x1fff) << 16; VSYNCOSD_WR_MPEG_REG(osd_reg->osd_blk0_cfg_w2, data32); } + + data32 = (osd_hw.free_src_data[OSD1].x_start & 0x1fff) | + (osd_hw.free_src_data[OSD1].x_end & 0x1fff) << 16; + VSYNCOSD_WR_MPEG_REG( + hw_osd_reg_array[OSD1].osd_blk0_cfg_w1, data32); + buffer_w = ((data32 >> 16) & 0x1fff) - (data32 & 0x1fff) + 1; + data32 = ((osd_hw.free_src_data[OSD1].y_start + + osd_hw.pandata[OSD1].y_start) & 0x1fff) + | ((osd_hw.free_src_data[OSD1].y_end + + osd_hw.pandata[OSD1].y_start) & 0x1fff) << 16; + VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK0_CFG_W2, data32); + buffer_h = ((data32 >> 16) & 0x1fff) - (data32 & 0x1fff) + 1; + if (osd_hw.osd_meson_dev.has_dolby_vision) { + VSYNCOSD_WR_MPEG_REG( + DOLBY_CORE2A_SWAP_CTRL1, + ((buffer_w + 0x40) << 16) + | (buffer_h + 0x80 + 0)); + VSYNCOSD_WR_MPEG_REG( + DOLBY_CORE2A_SWAP_CTRL2, + (buffer_w << 16) | (buffer_h + 0)); + } data32 = VSYNCOSD_RD_MPEG_REG(osd_reg->osd_ctrl_stat); data32 &= ~0x1ff008;//0x1ff00e; data32 |= osd_hw.gbl_alpha[index] << 12; diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 1307d3151dd3..5f700c2d7a89 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -85,6 +85,7 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_DEFAULT_LEVEL_DESC, LOG_MASK_DESC); #include #include "../common/vfm/vfm.h" +#include static u32 osd_vpp_misc; static u32 osd_vpp_misc_mask; @@ -672,7 +673,6 @@ static u32 ori_end_x_lines; static u32 ori_start_y_lines; static u32 ori_end_y_lines; -#if DEBUG_TMP static u32 zoom2_start_x_lines; static u32 zoom2_end_x_lines; static u32 zoom2_start_y_lines; @@ -682,7 +682,6 @@ static u32 ori2_start_x_lines; static u32 ori2_end_x_lines; static u32 ori2_start_y_lines; static u32 ori2_end_y_lines; -#endif /* wide settings */ static u32 wide_setting; @@ -852,7 +851,7 @@ static int android_clone_rate = 30; static int noneseamless_play_clone_rate = 5; #endif -#define CONFIG_AM_VOUT //DEBUG_TMP +#define CONFIG_AM_VOUT void safe_disble_videolayer(void) { @@ -970,10 +969,8 @@ static inline void video_vf_put(struct vframe_s *vf) if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) { vf_put(vf, RECEIVER_NAME); -#if DEBUG_TMP if (is_dolby_vision_enable()) dolby_vision_vf_put(vf); -#endif video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; } } @@ -1174,7 +1171,6 @@ static void vpp_settings_h(struct vpp_frame_par_s *framePtr) framePtr->VPP_line_in_length_); } -#if DEBUG_TMP static void vd2_settings_h(struct vframe_s *vf) { u32 VPP_hd_start_lines_; @@ -1192,7 +1188,6 @@ static void vd2_settings_h(struct vframe_s *vf) VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); } } -#endif static void vpp_settings_v(struct vpp_frame_par_s *framePtr) { @@ -1362,7 +1357,6 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) vpp_filter->vpp_vsc_start_phase_step); } -#if DEBUG_TMP static void vd2_settings_v(struct vframe_s *vf) { u32 VPP_vd_start_lines_; @@ -1381,7 +1375,6 @@ static void vd2_settings_v(struct vframe_s *vf) VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); } } -#endif #ifdef TV_3D_FUNCTION_OPEN @@ -1668,7 +1661,6 @@ static void zoom_display_horz(int hscale) 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); } -#if DEBUG_TMP static void vd2_zoom_display_horz(int hscale) { u32 ls, le, rs, re; @@ -1751,7 +1743,6 @@ static void vd2_zoom_display_horz(int hscale) (((le / 2 - ls / 2 + 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); } -#endif static void zoom_display_vert(void) { @@ -1904,7 +1895,6 @@ static void zoom_display_vert(void) } } -#if DEBUG_TMP static void vd2_zoom_display_vert(void) { @@ -1970,7 +1960,6 @@ static void vd2_zoom_display_vert(void) } } } -#endif #ifdef TV_3D_FUNCTION_OPEN /* judge the out mode is 240:LBRBLRBR or 120:LRLRLR */ @@ -2037,10 +2026,9 @@ bool has_enhanced_layer(struct vframe_s *vf) return 0; if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS) return 0; -#if DEBUG_TMP if (!is_dolby_vision_on()) return 0; -#endif + req.vf = vf; req.bot_flag = 0; req.aux_buf = NULL; @@ -2062,10 +2050,8 @@ static void vsync_toggle_frame(struct vframe_s *vf) return; frame_count++; toggle_count++; -#if DEBUG_TMP if (is_dolby_vision_enable()) vf_with_el = has_enhanced_layer(vf); -#endif ori_start_x_lines = 0; ori_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? vf->compWidth : vf->width) - 1; @@ -2608,8 +2594,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) #ifdef TV_REVERSE if (reverse) { if (is_meson_txlx_package_962X() - /*&& !is_dolby_vision_stb_mode()*/ - /*&& is_dolby_vision_on()*/)/*DEBUG_TMP*/ + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) VSYNC_WR_MPEG_REG( AFBC_VD_CFMT_CTRL, HFORMATTER_REPEAT | @@ -2632,8 +2618,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) #endif { if (is_meson_txlx_package_962X() - /*&& !is_dolby_vision_stb_mode()*/ - /*&& is_dolby_vision_on()*/)/*DEBUG_TMP*/ + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) VSYNC_WR_MPEG_REG( AFBC_VD_CFMT_CTRL, HFORMATTER_REPEAT | @@ -2724,10 +2710,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VDIF_DEMUX_MODE_RGB_444; } } -#if DEBUG_TMP if (is_dolby_vision_enable()) vf_with_el = has_enhanced_layer(vf); -#endif if (frame_par->hscale_skip_count) r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; @@ -2800,8 +2784,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) else vformatter = 0; if (is_meson_txlx_package_962X() - /*&& !is_dolby_vision_stb_mode()*/ - /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { VSYNC_WR_MPEG_REG( VIU_VD1_FMT_CTRL + cur_dev->viu_off, HFORMATTER_REPEAT | @@ -2837,7 +2821,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { VSYNC_WR_MPEG_REG( VIU_VD1_FMT_CTRL + cur_dev->viu_off, - (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + (is_dolby_vision_on() ? HFORMATTER_REPEAT : 0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | vini_phase | vphase | @@ -2854,7 +2838,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { VSYNC_WR_MPEG_REG( VIU_VD1_FMT_CTRL + cur_dev->viu_off, - (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + (is_dolby_vision_on() ? HFORMATTER_REPEAT : 0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | @@ -2902,8 +2886,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); } else { if (is_meson_txlx_package_962X() - /*&& !is_dolby_vision_stb_mode()*/ - /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { VSYNC_WR_MPEG_REG( VIU_VD1_FMT_CTRL + cur_dev->viu_off, HFORMATTER_REPEAT | @@ -2917,7 +2901,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { VSYNC_WR_MPEG_REG( VIU_VD1_FMT_CTRL + cur_dev->viu_off, - (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + (is_dolby_vision_on() ? HFORMATTER_REPEAT : 0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | @@ -3145,8 +3129,8 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) #ifdef TV_REVERSE if (reverse) { if (is_meson_txlx_package_962X() - /*&& !is_dolby_vision_stb_mode()*/ - /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { VSYNC_WR_MPEG_REG( VD2_AFBC_VD_CFMT_CTRL, HFORMATTER_REPEAT | @@ -3171,8 +3155,8 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { #endif if (is_meson_txlx_package_962X() - /*&& !is_dolby_vision_stb_mode()*/ - /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { VSYNC_WR_MPEG_REG( VD2_AFBC_VD_CFMT_CTRL, HFORMATTER_REPEAT | @@ -3284,8 +3268,8 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) ((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT; if (is_meson_txlx_package_962X() - /*&& !is_dolby_vision_stb_mode()*/ - /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_REPEAT | @@ -3311,7 +3295,7 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, - (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + (is_dolby_vision_on() ? HFORMATTER_REPEAT : 0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | @@ -3321,7 +3305,7 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, - (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + (is_dolby_vision_on() ? HFORMATTER_REPEAT : 0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | vini_phase | vphase | @@ -3354,8 +3338,8 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VFORMATTER_EN); } else { if (is_meson_txlx_package_962X() - /*&& !is_dolby_vision_stb_mode()*/ - /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_REPEAT | @@ -3370,7 +3354,7 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, - (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + (is_dolby_vision_on() ? HFORMATTER_REPEAT : 0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | @@ -3379,7 +3363,7 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); pr_info("\tvd2 set fmt(dovi:%d)\n", - /*is_dolby_vision_on()*/0);/*DEBUG_TMP*/ + /*is_dolby_vision_on()*/0); } } /* LOOP/SKIP pattern */ @@ -3900,11 +3884,11 @@ static enum vmode_e new_vmode = VMODE_MAX; static inline bool video_vf_disp_mode_check(struct vframe_s *vf) { struct provider_disp_mode_req_s req; - //int ret = -1; + int ret = -1; req.vf = vf; req.disp_mode = 0; req.req_mode = 1; -#if DEBUG_TMP + if (is_dolby_vision_enable()) { ret = vf_notify_provider_by_name("dv_vdin", VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); @@ -3912,7 +3896,6 @@ static inline bool video_vf_disp_mode_check(struct vframe_s *vf) vf_notify_provider_by_name("vdin0", VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); } else -#endif vf_notify_provider_by_name("vdin0", VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); if (req.disp_mode == VFRAME_DISP_MODE_OK) @@ -3924,11 +3907,11 @@ static inline bool video_vf_disp_mode_check(struct vframe_s *vf) static enum vframe_disp_mode_e video_vf_disp_mode_get(struct vframe_s *vf) { struct provider_disp_mode_req_s req; - //int ret = -1; + int ret = -1; req.vf = vf; req.disp_mode = 0; req.req_mode = 0; -#if DEBUG_TMP + if (is_dolby_vision_enable()) { ret = vf_notify_provider_by_name("dv_vdin", VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); @@ -3936,7 +3919,6 @@ static enum vframe_disp_mode_e video_vf_disp_mode_get(struct vframe_s *vf) vf_notify_provider_by_name("vdin0", VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); } else -#endif vf_notify_provider_by_name("vdin0", VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); return req.disp_mode; @@ -3977,7 +3959,6 @@ static inline bool video_vf_dirty_put(struct vframe_s *vf) } -#if DEBUG_TMP struct vframe_s *dolby_vision_toggle_frame(struct vframe_s *vf) { struct vframe_s *toggle_vf = NULL; @@ -4050,9 +4031,7 @@ struct vframe_s *dolby_vision_toggle_frame(struct vframe_s *vf) } return toggle_vf; } -#endif -#if DEBUG_TMP static int dolby_vision_need_wait(void) { struct vframe_s *vf; @@ -4062,7 +4041,6 @@ static int dolby_vision_need_wait(void) return 1; return 0; } -#endif /* patch for 4k2k bandwidth issue, skiw mali and vpu mif */ static void dmc_adjust_for_mali_vpu(unsigned int width, unsigned int height) @@ -4075,8 +4053,9 @@ static void dmc_adjust_for_mali_vpu(unsigned int width, unsigned int height) } /*avoid 3840x2160 crop*/ if ((width >= 2000) && (height >= 1400) && - (dmc_config_state != 1) && (toggle_same_count < 30)) { - if (0) {/* if (is_dolby_vision_enable()) { */ + (dmc_config_state != 1) && + (toggle_same_count < 30)) { + if (is_dolby_vision_enable()) { /* vpu dmc */ WRITE_DMCREG( DMC_AM0_CHAN_CTRL, @@ -4200,7 +4179,6 @@ void correct_vd1_mif_size_for_DV(struct vpp_frame_par_s *par) } } -#if DEBUG_TMP void correct_vd2_mif_size_for_DV( struct vpp_frame_par_s *par, struct vframe_s *bl_vf) @@ -4244,7 +4222,6 @@ void correct_vd2_mif_size_for_DV( /* TODO: if el len is 0, need disable bl */ } } -#endif #ifdef FIQ_VSYNC void vsync_fisr_in(void) @@ -4268,9 +4245,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) #ifdef CONFIG_AM_VIDEO_LOG int toggle_cnt; #endif -#if DEBUG_TMP struct vframe_s *toggle_vf = NULL; -#endif struct vframe_s *toggle_frame = NULL; int video1_off_req = 0; struct vframe_s *cur_dispbuf_back = cur_dispbuf; @@ -4398,11 +4373,9 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) enable_rdma_log_count--; } #endif -#if DEBUG_TMP /* check video frame before VECM process */ if (is_dolby_vision_enable() && vf) dolby_vision_check_hdr10(vf); -#endif #ifdef CONFIG_TVIN_VDIN /* patch for m8 4k2k wifidisplay bandwidth bottleneck */ @@ -4631,11 +4604,9 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) 0) == 1) break; #endif -#if DEBUG_TMP if (is_dolby_vision_enable() && dolby_vision_need_wait()) break; -#endif /* *two special case: *case1:4k display case,input buffer not enough & @@ -4675,8 +4646,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) } vsync_toggle_frame(vf); toggle_frame = vf; - if (0/*is_dolby_vision_enable()*/) { /*DEBUG_TMP*/ - //toggle_vf = dolby_vision_toggle_frame(vf); + if (is_dolby_vision_enable()) { + toggle_vf = dolby_vision_toggle_frame(vf); video_pause_global = 0; } else { cur_dispbuf2 = NULL; @@ -4705,11 +4676,9 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) vf = video_vf_peek(); if (!vf) next_peek_underflow++; -#if DEBUG_TMP if (for_dolby_vision_certification() && toggle_vf) break; -#endif if (debug_flag & DEBUG_FLAG_TOGGLE_FRAME_PER_VSYNC) break; video_get_vf_cnt++; @@ -4738,11 +4707,9 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) "sys.time = 0x%x, video time = 0x%x\n", timestamp_pcrscr_get(), timestamp_vpts_get()); -#if DEBUG_TMP if (is_dolby_vision_enable() && dolby_vision_need_wait()) break; -#endif #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) refresh_on_vs(vf); if (amvecm_on_vs( @@ -4762,12 +4729,10 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) break; vsync_toggle_frame(vf); toggle_frame = vf; -#if DEBUG_TMP if (is_dolby_vision_enable()) toggle_vf = dolby_vision_toggle_frame(vf); else -#endif cur_dispbuf2 = NULL; frame_repeat_count = 0; @@ -4796,8 +4761,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) cur_dispbuf); } else vsync_toggle_frame(cur_dispbuf); - /*DEBUG_TMP*/ - if (0/*is_dolby_vision_enable()*/) { + if (is_dolby_vision_enable()) { pause_vf = cur_dispbuf; video_pause_global = 1; } else { @@ -4805,14 +4769,13 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) video_pause_global = 2; } } -#if DEBUG_TMP if (pause_vf && (video_pause_global == 1) && is_dolby_vision_enable()) { toggle_vf = pause_vf; - dolby_vision_parse_metadata(cur_dispbuf, true); + dolby_vision_parse_metadata( + cur_dispbuf, 0, false); dolby_vision_set_toggle_flag(1); } -#endif break; } @@ -4853,10 +4816,27 @@ SET_FILTER: frame_par_di_set = 1; } -#if DEBUG_TMP if (is_dolby_vision_enable()) { u32 frame_size = 0, h_size, v_size; - + /* force toggle when keeping frame after playing */ + if ((cur_dispbuf == &vf_local) + && !toggle_vf + && is_dolby_vision_on()) { + toggle_vf = cur_dispbuf; + dolby_vision_parse_metadata( + cur_dispbuf, 2, false); + dolby_vision_set_toggle_flag(1); + } + /* force toggle in pause mode */ + if (cur_dispbuf + && (cur_dispbuf != &vf_local) + && !toggle_vf + && is_dolby_vision_on()) { + toggle_vf = cur_dispbuf; + dolby_vision_parse_metadata( + cur_dispbuf, 0, false); + dolby_vision_set_toggle_flag(1); + } if (cur_frame_par) { if (cur_frame_par->VPP_hd_start_lines_ >= cur_frame_par->VPP_hd_end_lines_) @@ -4883,7 +4863,6 @@ SET_FILTER: dolby_vision_process(toggle_vf, frame_size); dolby_vision_update_setting(); } -#endif if ((platform_type == 1) || (platform_type == 0)) { if (mode_3d_changed) { mode_3d_changed = 0; @@ -5139,7 +5118,6 @@ SET_FILTER: zoom_start_y_lines = zoom_start_y; zoom_end_y_lines = zoom_end_y; zoom_display_vert(); -#if DEBUG_TMP if (is_dolby_vision_enable() && cur_dispbuf2) { zoom2_start_x_lines = ori2_start_x_lines; zoom2_end_x_lines = ori2_end_x_lines; @@ -5150,7 +5128,6 @@ SET_FILTER: vd2_zoom_display_horz(0); vd2_zoom_display_vert(); } -#endif } /*vpp input size setting*/ VSYNC_WR_MPEG_REG(VPP_IN_H_V_SIZE, @@ -5176,7 +5153,7 @@ SET_FILTER: /* vpp filters */ /* SET_MPEG_REG_MASK(VPP_SC_MISC + cur_dev->vpp_off, */ /* VPP_SC_TOP_EN | VPP_SC_VERT_EN | VPP_SC_HORZ_EN); */ - if (/*for_dolby_vision_certification()*/0) {/*DEBUG_TMP*/ + if (for_dolby_vision_certification()) { /* turn off PPS for Dolby Vision certification */ VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, 0, VPP_SC_TOP_EN_BIT, VPP_SC_TOP_EN_WID); @@ -5340,12 +5317,10 @@ SET_FILTER: vpp_settings_h(cur_frame_par); vpp_settings_v(cur_frame_par); -#if DEBUG_TMP if (is_dolby_vision_enable() && cur_dispbuf2) { vd2_settings_h(cur_dispbuf2); vd2_settings_v(cur_dispbuf2); } -#endif frame_par_ready_to_set = 0; frame_par_force_to_set = 0; first_set = 1; @@ -5819,7 +5794,7 @@ static void video_vf_unreg_provider(void) cur_dispbuf = &vf_local; cur_dispbuf->video_angle = 0; } - if (0/*is_dolby_vision_enable()*/) {/*DEBUG_TMP*/ + if (is_dolby_vision_enable()) { if (cur_dispbuf2 == &vf_local2) cur_dispbuf2 = NULL; else if (cur_dispbuf2 != NULL) { @@ -7505,7 +7480,7 @@ static ssize_t video_test_screen_store(struct class *cla, data &= (~VPP_VD1_POSTBLEND); #endif -#if 0 //DEBUG_TMP +#if DEBUG_TMP if (test_screen & 0x04000000) data |= VPP_VD2_PREBLEND; else @@ -7557,7 +7532,7 @@ static ssize_t video_rgb_screen_store(struct class *cla, if (r < 0) return -EINVAL; -#if 0 //DEBUG_TMP +#if DEBUG_TMP /* vdin0 pre post blend enable or disabled */ data = READ_VCBUS_REG(VPP_MISC); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c index ac8ef9c00e12..47efcb5ad0ab 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c @@ -767,81 +767,147 @@ static void Edid_ParsingVendSpec(struct rx_cap *pRXCap, { struct dv_info *dv = &pRXCap->dv_info; unsigned char *dat = buf; - unsigned char len; unsigned char pos = 0; - len = dat[pos] & 0x1f; + memset(dv, 0, sizeof(struct dv_info)); + dv->block_flag = CORRECT; + dv->length = dat[pos] & 0x1f; + memcpy(dv->rawdata, dat, dv->length + 1); pos++; if (dat[pos] != 1) { - pr_info(EDID "parsing fail %s[%d]\n", __func__, + pr_info("hdmitx: edid: parsing fail %s[%d]\n", __func__, __LINE__); - } else { - pos++; + return; + } + pos++; dv->ieeeoui = dat[pos++]; dv->ieeeoui += dat[pos++] << 8; dv->ieeeoui += dat[pos++] << 16; + if (dv->ieeeoui != DV_IEEE_OUI) { + dv->block_flag = ERROR_LENGTH; + return; + } dv->ver = (dat[pos] >> 5) & 0x7; - /* Refer to DV 2.6 Page 11 */ + /* Refer to DV 2.9 Page 27 */ if (dv->ver == 0) { - dv->sup_yuv422_12bit = dat[pos] & 0x1; - dv->sup_2160p60hz = (dat[pos] >> 1) & 0x1; - dv->sup_global_dimming = (dat[pos] >> 2) & 0x1; - pos++; - dv->vers.ver0.chrom_red_primary_x = - (dat[pos+1] << 8) | (dat[pos] >> 4); - dv->vers.ver0.chrom_red_primary_y = - (dat[pos+2] << 8) | (dat[pos] & 0xf); - pos += 3; - dv->vers.ver0.chrom_green_primary_x = - (dat[pos+1] << 8) | (dat[pos] >> 4); - dv->vers.ver0.chrom_green_primary_y = - (dat[pos+2] << 8) | (dat[pos] & 0xf); - pos += 3; - dv->vers.ver0.chrom_blue_primary_x = - (dat[pos+1] << 8) | (dat[pos] >> 4); - dv->vers.ver0.chrom_blue_primary_y = - (dat[pos+2] << 8) | (dat[pos] & 0xf); - pos += 3; - dv->vers.ver0.chrom_white_primary_x = - (dat[pos+1] << 8) | (dat[pos] >> 4); - dv->vers.ver0.chrom_white_primary_y = - (dat[pos+2] << 8) | (dat[pos] & 0xf); - pos += 3; - dv->vers.ver0.target_min_pq = - (dat[pos+1] << 8) | (dat[pos] >> 4); - dv->vers.ver0.target_max_pq = - (dat[pos+2] << 8) | (dat[pos] & 0xf); - pos += 3; - dv->vers.ver0.dm_major_ver = dat[pos] >> 4; - dv->vers.ver0.dm_minor_ver = dat[pos] & 0xf; - pos++; - } - /* Refer to DV 2.6 Page 14 */ - if (dv->ver == 1) { - dv->vers.ver1.dm_version = (dat[pos] >> 2) & 0x7; - dv->sup_yuv422_12bit = dat[pos] & 0x1; - dv->sup_2160p60hz = (dat[pos] >> 1) & 0x1; - pos++; - dv->sup_global_dimming = dat[pos] & 0x1; - dv->vers.ver1.target_max_lum = dat[pos] >> 1; - pos++; - dv->colorimetry = dat[pos] & 0x1; - dv->vers.ver1.target_min_lum = dat[pos] >> 1; - pos += 2; /* byte8 is reserved as 0 */ - dv->vers.ver1.chrom_red_primary_x = dat[pos++]; - dv->vers.ver1.chrom_red_primary_y = dat[pos++]; - dv->vers.ver1.chrom_green_primary_x = dat[pos++]; - dv->vers.ver1.chrom_green_primary_y = dat[pos++]; - dv->vers.ver1.chrom_blue_primary_x = dat[pos++]; - dv->vers.ver1.chrom_blue_primary_y = dat[pos++]; - } + if (dv->length == 0x19) { + dv->sup_yuv422_12bit = dat[pos] & 0x1; + dv->sup_2160p60hz = (dat[pos] >> 1) & 0x1; + dv->sup_global_dimming = (dat[pos] >> 2) & 0x1; + pos++; + dv->Rx = + (dat[pos+1] << 4) | (dat[pos] >> 4); + dv->Ry = + (dat[pos+2] << 4) | (dat[pos] & 0xf); + pos += 3; + dv->Gx = + (dat[pos+1] << 4) | (dat[pos] >> 4); + dv->Gy = + (dat[pos+2] << 4) | (dat[pos] & 0xf); + pos += 3; + dv->Bx = + (dat[pos+1] << 4) | (dat[pos] >> 4); + dv->By = + (dat[pos+2] << 4) | (dat[pos] & 0xf); + pos += 3; + dv->Wx = + (dat[pos+1] << 4) | (dat[pos] >> 4); + dv->Wy = + (dat[pos+2] << 4) | (dat[pos] & 0xf); + pos += 3; + dv->tminPQ = + (dat[pos+1] << 4) | (dat[pos] >> 4); + dv->tmaxPQ = + (dat[pos+2] << 4) | (dat[pos] & 0xf); + pos += 3; + dv->dm_major_ver = dat[pos] >> 4; + dv->dm_minor_ver = dat[pos] & 0xf; + pos++; + } else + dv->block_flag = ERROR_LENGTH; } - if (pos > len) + if (dv->ver == 1) { + if (dv->length == 0x0B) {/* Refer to DV 2.9 Page 33 */ + dv->dm_version = (dat[pos] >> 2) & 0x7; + dv->sup_yuv422_12bit = dat[pos] & 0x1; + dv->sup_2160p60hz = (dat[pos] >> 1) & 0x1; + pos++; + dv->sup_global_dimming = dat[pos] & 0x1; + dv->tmaxLUM = dat[pos] >> 1; + pos++; + dv->colorimetry = dat[pos] & 0x1; + dv->tminLUM = dat[pos] >> 1; + pos++; + dv->low_latency = dat[pos] & 0x3; + dv->Bx = 0x20 | ((dat[pos] >> 5) & 0x7); + dv->By = 0x08 | ((dat[pos] >> 2) & 0x7); + pos++; + dv->Gx = 0x00 | (dat[pos] >> 1); + dv->Ry = 0x40 | ((dat[pos] & 0x1) | + ((dat[pos + 1] & 0x1) << 1) | + ((dat[pos + 2] & 0x3) << 2)); + pos++; + dv->Gy = 0x80 | (dat[pos] >> 1); + pos++; + dv->Rx = 0xA0 | (dat[pos] >> 3); + pos++; + } else if (dv->length == 0x0E) { + dv->dm_version = (dat[pos] >> 2) & 0x7; + dv->sup_yuv422_12bit = dat[pos] & 0x1; + dv->sup_2160p60hz = (dat[pos] >> 1) & 0x1; + pos++; + dv->sup_global_dimming = dat[pos] & 0x1; + dv->tmaxLUM = dat[pos] >> 1; + pos++; + dv->colorimetry = dat[pos] & 0x1; + dv->tminLUM = dat[pos] >> 1; + pos += 2; /* byte8 is reserved as 0 */ + dv->Rx = dat[pos++]; + dv->Ry = dat[pos++]; + dv->Gx = dat[pos++]; + dv->Gy = dat[pos++]; + dv->Bx = dat[pos++]; + dv->By = dat[pos++]; + } else + dv->block_flag = ERROR_LENGTH; + } + if (dv->ver == 2) { + if (dv->length == 0x0B) { + dv->sup_2160p60hz = 0x1;/*default*/ + dv->dm_version = (dat[pos] >> 2) & 0x7; + dv->sup_yuv422_12bit = dat[pos] & 0x1; + dv->sup_backlight_control = (dat[pos] >> 1) & 0x1; + pos++; + dv->sup_global_dimming = (dat[pos] >> 2) & 0x1; + dv->backlt_min_luma = dat[pos] & 0x3; + dv->tminPQ = dat[pos] >> 3; + pos++; + dv->Interface = dat[pos] & 0x3; + dv->tmaxPQ = dat[pos] >> 3; + pos++; + dv->sup_10b_12b_444 = ((dat[pos] & 0x1) << 1) | + (dat[pos + 1] & 0x1); + dv->Gx = 0x00 | (dat[pos] >> 1); + pos++; + dv->Gy = 0x80 | (dat[pos] >> 1); + pos++; + dv->Rx = 0xA0 | (dat[pos] >> 3); + dv->Bx = 0x20 | (dat[pos] & 0x7); + pos++; + dv->Ry = 0x40 | (dat[pos] >> 3); + dv->By = 0x08 | (dat[pos] & 0x7); + pos++; + } else + dv->block_flag = ERROR_LENGTH; + } + + if (pos > dv->length) pr_info("hdmitx: edid: maybe invalid dv%d data\n", dv->ver); + return; } /* ----------------------------------------------------------- */ @@ -2174,6 +2240,8 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, return 0; if (pRXCap->dc_y444 && pRXCap->dc_30bit) rx_y444_max_dc = COLORDEPTH_30B; + if (pRXCap->dc_y444 && pRXCap->dc_36bit) + rx_y444_max_dc = COLORDEPTH_36B; if (para->cd <= rx_y444_max_dc) valid = 1; else @@ -2186,6 +2254,8 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, return 0; if (pRXCap->dc_y444 && pRXCap->dc_30bit) rx_y422_max_dc = COLORDEPTH_30B; + if (pRXCap->dc_y444 && pRXCap->dc_36bit) + rx_y422_max_dc = COLORDEPTH_36B; if (para->cd <= rx_y422_max_dc) valid = 1; else @@ -2196,6 +2266,8 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, /* Always assume RX supports RGB444 */ if (pRXCap->dc_30bit) rx_rgb_max_dc = COLORDEPTH_30B; + if (pRXCap->dc_36bit) + rx_rgb_max_dc = COLORDEPTH_36B; if (para->cd <= rx_rgb_max_dc) valid = 1; else @@ -2205,6 +2277,8 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, if (para->cs == COLORSPACE_YUV420) { if (pRXCap->dc_30bit_420) rx_y420_max_dc = COLORDEPTH_30B; + if (pRXCap->dc_36bit_420) + rx_y420_max_dc = COLORDEPTH_36B; if (para->cd <= rx_y420_max_dc) valid = 1; else diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 850faab86e13..ab5186ca8813 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -70,7 +70,8 @@ static struct class *hdmitx_class; static int set_disp_mode_auto(void); static void hdmitx_get_edid(struct hdmitx_dev *hdev); static void hdmitx_set_drm_pkt(struct master_display_info_s *data); -static void hdmitx_set_vsif_pkt(enum eotf_type type, uint8_t tunnel_mode); +static void hdmitx_set_vsif_pkt(enum eotf_type type, enum mode_type + tunnel_mode, struct dv_vsif_para *data); static int check_fbc_special(unsigned char *edid_dat); static struct vinfo_s *hdmitx_get_current_vinfo(void); @@ -1091,84 +1092,204 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data) CLR_AVI_BT2020); } -static void hdmitx_set_vsif_pkt(enum eotf_type type, uint8_t tunnel_mode) +static void hdmitx_set_vsif_pkt(enum eotf_type type, + enum mode_type tunnel_mode, struct dv_vsif_para *data) { struct hdmitx_dev *hdev = &hdmitx_device; + struct dv_vsif_para para = {0}; unsigned char VEN_HB[3] = {0x81, 0x01}; - unsigned char VEN_DB[24] = {0x00}; + unsigned char VEN_DB1[24] = {0x00}; + unsigned char VEN_DB2[27] = {0x00}; unsigned char len = 0; unsigned int vic = hdev->cur_VIC; unsigned int hdmi_vic_4k_flag = 0; + static enum eotf_type ltype = EOTF_T_NULL; + static uint8_t ltmode = -1; - if (hdev->chip_type < MESON_CPU_ID_GXL) { - pr_info("hdmitx: not support DolbyVision\n"); + if ((hdev->ready == 0) || (hdev->RXCap.dv_info.ieeeoui + != DV_IEEE_OUI)) { + ltype = EOTF_T_NULL; + ltmode = -1; return; } - if ((vic == HDMI_3840x2160p30_16x9) || - (vic == HDMI_3840x2160p25_16x9) || - (vic == HDMI_3840x2160p24_16x9) || - (vic == HDMI_4096x2160p24_256x135)) - hdmi_vic_4k_flag = 1; - - switch (type) { - case EOTF_T_DOLBYVISION: - len = 0x18; - break; - case EOTF_T_HDR10: - len = 0x05; - break; - case EOTF_T_SDR: - len = 0x05; - break; - case EOTF_T_NULL: - default: - len = 0x05; - break; + if ((hdev->chip_type) < MESON_CPU_ID_GXL) { + pr_info("hdmitx: not support DolbyVision\n"); + return; } +/*ver0 and ver1_15 use hdmi 1.4b VSIF*/ + if ((hdev->RXCap.dv_info.ver == 0) || ((hdev->RXCap.dv_info.ver == 1) + && (hdev->RXCap.dv_info.length == 0xE))) { + if ((vic == HDMI_3840x2160p30_16x9) || + (vic == HDMI_3840x2160p25_16x9) || + (vic == HDMI_3840x2160p24_16x9) || + (vic == HDMI_4096x2160p24_256x135)) + hdmi_vic_4k_flag = 1; - VEN_HB[2] = len; - VEN_DB[0] = 0x03; - VEN_DB[1] = 0x0c; - VEN_DB[2] = 0x00; - VEN_DB[3] = 0x00; - - if (hdmi_vic_4k_flag) { - VEN_DB[3] = 0x20; - if (vic == HDMI_3840x2160p30_16x9) - VEN_DB[4] = 0x1; - else if (vic == HDMI_3840x2160p25_16x9) - VEN_DB[4] = 0x2; - else if (vic == HDMI_3840x2160p24_16x9) - VEN_DB[4] = 0x3; - else if (vic == HDMI_4096x2160p24_256x135) - VEN_DB[4] = 0x4; - else - VEN_DB[4] = 0x0; - } - - if (type == EOTF_T_DOLBYVISION) { - hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB, VEN_HB); - if (tunnel_mode == 1) { - hdev->HWOp.CntlConfig(hdev, CONF_AVI_RGBYCC_INDIC, - COLORSPACE_RGB444); - hdev->HWOp.CntlConfig(hdev, CONF_AVI_Q01, - RGB_RANGE_FUL); - } else { - hdev->HWOp.CntlConfig(hdev, CONF_AVI_RGBYCC_INDIC, - COLORSPACE_YUV422); - hdev->HWOp.CntlConfig(hdev, CONF_AVI_YQ01, - YCC_RANGE_FUL); + switch (type) { + case EOTF_T_DOLBYVISION: + len = 0x18; + hdev->dv_src_feature = 1; + break; + case EOTF_T_HDR10: + case EOTF_T_SDR: + case EOTF_T_NULL: + default: + len = 0x05; + hdev->dv_src_feature = 0; + break; + } + + VEN_HB[2] = len; + VEN_DB1[0] = 0x03; + VEN_DB1[1] = 0x0c; + VEN_DB1[2] = 0x00; + VEN_DB1[3] = 0x00; + + if (hdmi_vic_4k_flag) { + VEN_DB1[3] = 0x20; + if (vic == HDMI_3840x2160p30_16x9) + VEN_DB1[4] = 0x1; + else if (vic == HDMI_3840x2160p25_16x9) + VEN_DB1[4] = 0x2; + else if (vic == HDMI_3840x2160p24_16x9) + VEN_DB1[4] = 0x3; + else if (vic == HDMI_4096x2160p24_256x135) + VEN_DB1[4] = 0x4; + else + VEN_DB1[4] = 0x0; + } + if (type == EOTF_T_DOLBYVISION) { + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB1, VEN_HB); + if (tunnel_mode == RGB_8BIT) { + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, + COLORSPACE_RGB444); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_Q01, + RGB_RANGE_FUL); + } else { + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, + COLORSPACE_YUV422); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_YQ01, + YCC_RANGE_FUL); + } + } else { + if (hdmi_vic_4k_flag) + hdev->HWOp.SetPacket( + HDMI_PACKET_VEND, VEN_DB1, VEN_HB); + else + hdev->HWOp.SetPacket( + HDMI_PACKET_VEND, NULL, NULL); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, hdev->para->cs); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_Q01, RGB_RANGE_LIM); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_YQ01, YCC_RANGE_LIM); + } + + } + /*ver1_12 and ver2 use Dolby VSIF*/ + if ((hdev->RXCap.dv_info.ver == 2) || ((hdev->RXCap.dv_info.ver == 1) + && (hdev->RXCap.dv_info.length == 0xB))) { + + if (data == NULL) + data = ¶ + /*4k vsif package */ + if ((vic == HDMI_3840x2160p30_16x9) || + (vic == HDMI_3840x2160p25_16x9) || + (vic == HDMI_3840x2160p24_16x9) || + (vic == HDMI_4096x2160p24_256x135)) + hdmi_vic_4k_flag = 1; + + switch (type) { + case EOTF_T_DOLBYVISION: + case EOTF_T_LL_MODE: + len = 0x1b; + hdev->dv_src_feature = 1; + break; + case EOTF_T_HDR10: + case EOTF_T_SDR: + case EOTF_T_NULL: + default: + len = 0x5; + hdev->dv_src_feature = 0; + break; + } + VEN_HB[2] = len; + VEN_DB2[0] = 0x46; + VEN_DB2[1] = 0xd0; + VEN_DB2[2] = 0x00; + VEN_DB2[3] = (data->vers.ver2.low_latency) | + (data->vers.ver2.dobly_vision_signal << 1); + VEN_DB2[4] = (data->vers.ver2.eff_tmax_PQ_hi) + | (data->vers.ver2.auxiliary_MD_present << 6) + | (data->vers.ver2.backlt_ctrl_MD_present << 7); + VEN_DB2[5] = data->vers.ver2.eff_tmax_PQ_low; + VEN_DB2[6] = data->vers.ver2.auxiliary_runmode; + VEN_DB2[7] = data->vers.ver2.auxiliary_runversion; + VEN_DB2[8] = data->vers.ver2.auxiliary_debug0; + + /*Dolby Vision standard case*/ + if (type == EOTF_T_DOLBYVISION) { + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB2, VEN_HB); + if (tunnel_mode == RGB_8BIT) {/*RGB444*/ + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, + COLORSPACE_RGB444); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_Q01, + RGB_RANGE_FUL); + } else {/*YUV422*/ + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, + COLORSPACE_YUV422); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_YQ01, + YCC_RANGE_FUL); + } + } + /*Dolby Vision low-latency case*/ + else if (type == EOTF_T_LL_MODE) { + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB2, VEN_HB); + if (tunnel_mode == RGB_10_12BIT) {/*10/12bit RGB444*/ + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, + COLORSPACE_RGB444); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_Q01, + RGB_RANGE_LIM); + } else if (tunnel_mode == YUV444_10_12BIT) { + /*10/12bit YUV444*/ + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, + COLORSPACE_YUV444); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_YQ01, + YCC_RANGE_LIM); + } else {/*YUV422*/ + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, + COLORSPACE_YUV422); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_YQ01, + YCC_RANGE_LIM); + } + } + /*SDR case*/ + else { + if (hdmi_vic_4k_flag) { + VEN_DB1[0] = 0x03; + VEN_DB1[1] = 0x0c; + VEN_DB1[2] = 0x00; + hdev->HWOp.SetPacket( + HDMI_PACKET_VEND, VEN_DB2, VEN_HB); + } else + hdev->HWOp.SetPacket( + HDMI_PACKET_VEND, NULL, NULL); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, hdev->para->cs); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_Q01, RGB_RANGE_LIM); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_YQ01, YCC_RANGE_LIM); } - } else { - if (hdmi_vic_4k_flag) - hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB, VEN_HB); - else - hdev->HWOp.SetPacket(HDMI_PACKET_VEND, NULL, NULL); - hdev->HWOp.CntlConfig(hdev, CONF_AVI_RGBYCC_INDIC, - hdev->para->cs); - hdev->HWOp.CntlConfig(hdev, CONF_AVI_Q01, RGB_RANGE_LIM); - hdev->HWOp.CntlConfig(hdev, CONF_AVI_YQ01, YCC_RANGE_LIM); } } @@ -1290,7 +1411,7 @@ static ssize_t store_config(struct device *dev, hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, DRM_DB, DRM_HB); } else if (strncmp(buf, "vsif", 4) == 0) - hdmitx_set_vsif_pkt(buf[4] - '0', buf[5] == '1'); + hdmitx_set_vsif_pkt(buf[4] - '0', buf[5] == '1', NULL); return 16; } @@ -1581,9 +1702,9 @@ static ssize_t show_dc_cap(struct device *dev, #if 0 if (pRXCap->dc_48bit_420) pos += snprintf(buf + pos, PAGE_SIZE, "420,16bit\n"); +#endif if (pRXCap->dc_36bit_420) pos += snprintf(buf + pos, PAGE_SIZE, "420,12bit\n"); -#endif if (pRXCap->dc_30bit_420) { pos += snprintf(buf + pos, PAGE_SIZE, "420,10bit\n"); pos += snprintf(buf + pos, PAGE_SIZE, "420,8bit\n"); @@ -1611,12 +1732,8 @@ static ssize_t show_dc_cap(struct device *dev, } next444: if (pRXCap->dc_y444) { -#if 0 if (pRXCap->dc_36bit) pos += snprintf(buf + pos, PAGE_SIZE, "444,12bit\n"); - if (pRXCap->dc_36bit) - pos += snprintf(buf + pos, PAGE_SIZE, "422,12bit\n"); -#endif if (pRXCap->dc_30bit) { pos += snprintf(buf + pos, PAGE_SIZE, "444,10bit\n"); pos += snprintf(buf + pos, PAGE_SIZE, "444,8bit\n"); @@ -1625,6 +1742,8 @@ next444: if (pRXCap->dc_48bit) pos += snprintf(buf + pos, PAGE_SIZE, "444,16bit\n"); #endif + if (pRXCap->dc_36bit) + pos += snprintf(buf + pos, PAGE_SIZE, "422,12bit\n"); if (pRXCap->dc_30bit) { pos += snprintf(buf + pos, PAGE_SIZE, "422,10bit\n"); pos += snprintf(buf + pos, PAGE_SIZE, "422,8bit\n"); @@ -1640,9 +1759,9 @@ nextrgb: #if 0 if (pRXCap->dc_48bit) pos += snprintf(buf + pos, PAGE_SIZE, "rgb,16bit\n"); +#endif if (pRXCap->dc_36bit) pos += snprintf(buf + pos, PAGE_SIZE, "rgb,12bit\n"); -#endif if (pRXCap->dc_30bit) pos += snprintf(buf + pos, PAGE_SIZE, "rgb,10bit\n"); pos += snprintf(buf + pos, PAGE_SIZE, "rgb,8bit\n"); @@ -1740,29 +1859,103 @@ static ssize_t show_dv_cap(struct device *dev, struct device_attribute *attr, char *buf) { int pos = 0; + int i; const struct dv_info *dv = &(hdmitx_device.RXCap.dv_info); - if (dv->ieeeoui != 0x00d046) + if (dv->ieeeoui != DV_IEEE_OUI) { + pos += snprintf(buf + pos, PAGE_SIZE, + "The Rx don't support DolbyVision\n"); return pos; + } + if (dv->block_flag != CORRECT) { + pos += snprintf(buf + pos, PAGE_SIZE, + "DolbyVision block is error\n"); + return pos; + } pos += snprintf(buf + pos, PAGE_SIZE, - "DolbyVision%d RX support list:\n", dv->ver); - if (dv->sup_yuv422_12bit) - pos += snprintf(buf + pos, PAGE_SIZE, " yuv422_12bit\n"); - pos += snprintf(buf + pos, PAGE_SIZE, - " 2160p%shz: 1\n", dv->sup_2160p60hz ? "60" : "30"); - if (dv->sup_global_dimming) - pos += snprintf(buf + pos, PAGE_SIZE, " global dimming\n"); - if (dv->colorimetry) - pos += snprintf(buf + pos, PAGE_SIZE, " colorimetry\n"); - pos += snprintf(buf + pos, PAGE_SIZE, - " IEEEOUI: 0x%06x\n", dv->ieeeoui); - if (dv->ver == 0) - pos += snprintf(buf + pos, PAGE_SIZE, " DM Ver: %x:%x\n", - dv->vers.ver0.dm_major_ver, dv->vers.ver0.dm_minor_ver); - if (dv->ver == 1) - pos += snprintf(buf + pos, PAGE_SIZE, " DM Ver: %x\n", - dv->vers.ver1.dm_version); + "DolbyVision RX support list:\n"); + if (dv->ver == 0) { + pos += snprintf(buf + pos, PAGE_SIZE, + "VSVDB Version: V%d\n", dv->ver); + pos += snprintf(buf + pos, PAGE_SIZE, + "2160p%shz: 1\n", + dv->sup_2160p60hz ? "60" : "30"); + pos += snprintf(buf + pos, PAGE_SIZE, + "Support mode:\n"); + pos += snprintf(buf + pos, PAGE_SIZE, + " DV_RGB_444_8BIT\n"); + if (dv->sup_yuv422_12bit) + pos += snprintf(buf + pos, PAGE_SIZE, + " DV_YCbCr_422_12BIT\n"); + } + if (dv->ver == 1) { + pos += snprintf(buf + pos, PAGE_SIZE, + "VSVDB Version: V%d(%d-byte)\n", + dv->ver, dv->length + 1); + if (dv->length == 0xB) { + pos += snprintf(buf + pos, PAGE_SIZE, + "2160p%shz: 1\n", + dv->sup_2160p60hz ? "60" : "30"); + pos += snprintf(buf + pos, PAGE_SIZE, + "Support mode:\n"); + pos += snprintf(buf + pos, PAGE_SIZE, + " DV_RGB_444_8BIT\n"); + if (dv->sup_yuv422_12bit) + pos += snprintf(buf + pos, PAGE_SIZE, + " DV_YCbCr_422_12BIT\n"); + if (dv->low_latency == 0x01) + pos += snprintf(buf + pos, PAGE_SIZE, + " LL_YCbCr_422_12BIT\n"); + } + + if (dv->length == 0xE) { + pos += snprintf(buf + pos, PAGE_SIZE, + "2160p%shz: 1\n", + dv->sup_2160p60hz ? "60" : "30"); + pos += snprintf(buf + pos, PAGE_SIZE, + "Support mode:\n"); + pos += snprintf(buf + pos, PAGE_SIZE, + " DV_RGB_444_8BIT\n"); + if (dv->sup_yuv422_12bit) + pos += snprintf(buf + pos, PAGE_SIZE, + " DV_YCbCr_422_12BIT\n"); + } + } + if (dv->ver == 2) { + pos += snprintf(buf + pos, PAGE_SIZE, + "VSVDB Version: V%d\n", dv->ver); + pos += snprintf(buf + pos, PAGE_SIZE, + "2160p60hz: 1\n"); + pos += snprintf(buf + pos, PAGE_SIZE, + "Support mode:\n"); + if ((dv->Interface != 0x00) && (dv->Interface != 0x01)) { + pos += snprintf(buf + pos, PAGE_SIZE, + " DV_RGB_444_8BIT\n"); + if (dv->sup_yuv422_12bit) + pos += snprintf(buf + pos, PAGE_SIZE, + " DV_YCbCr_422_12BIT\n"); + } + pos += snprintf(buf + pos, PAGE_SIZE, + " LL_YCbCr_422_12BIT\n"); + if ((dv->Interface == 0x01) || (dv->Interface == 0x03)) { + if (dv->sup_10b_12b_444 == 0x1) { + pos += snprintf(buf + pos, PAGE_SIZE, + " LL_RGB_444_10BIT\n"); + } + if (dv->sup_10b_12b_444 == 0x2) { + pos += snprintf(buf + pos, PAGE_SIZE, + " LL_RGB_444_12BIT\n"); + } + } + } + pos += snprintf(buf + pos, PAGE_SIZE, + "IEEEOUI: 0x%06x\n", dv->ieeeoui); + pos += snprintf(buf + pos, PAGE_SIZE, "VSVDB: "); + for (i = 0; i < (dv->length + 1); i++) + pos += snprintf(buf+pos, PAGE_SIZE, "%02x", + dv->rawdata[i]); + pos += snprintf(buf + pos, PAGE_SIZE, "\n"); return pos; } @@ -2793,6 +2986,8 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) mutex_unlock(&setclk_mutex); return; } + /*after plugout, DV mode can't be supported*/ + hdmitx_set_vsif_pkt(0, 0, NULL); hdev->ready = 0; if (hdev->repeater_tx) rx_repeat_hpd_state(0); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c index d7d98da41891..087c4b6b961e 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c @@ -35,7 +35,7 @@ #include "hw/common.h" static void hdmitx_set_spd_info(struct hdmitx_dev *hdmitx_device); -static void hdmi_set_vend_spec_infofram(struct hdmitx_dev *hdmitx_device, +static void hdmi_set_vend_spec_infofram(struct hdmitx_dev *hdev, enum hdmi_vic VideoCode); static struct hdmitx_vidpara hdmi_tx_video_params[] = { @@ -659,30 +659,40 @@ static void hdmi_set_vend_spec_infofram(struct hdmitx_dev *hdev, int i; unsigned char VEN_DB[6]; unsigned char VEN_HB[3]; - VEN_HB[0] = 0x81; VEN_HB[1] = 0x01; VEN_HB[2] = 0x5; + if (VideoCode == 0) { /* For non-4kx2k mode setting */ + hdev->HWOp.SetPacket(HDMI_PACKET_VEND, NULL, VEN_HB); + return; + } + + if ((hdev->RXCap.dv_info.block_flag == CORRECT) || + (hdev->dv_src_feature == 1)) { /* For dolby */ + return; + } + for (i = 0; i < 0x6; i++) VEN_DB[i] = 0; VEN_DB[0] = 0x03; VEN_DB[1] = 0x0c; VEN_DB[2] = 0x00; - VEN_DB[3] = 0x20; /* 4k x 2k Spec P156 */ - if (VideoCode == 0) { /* For non-4kx2k mode setting */ - hdev->HWOp.SetPacket(HDMI_PACKET_VEND, NULL, VEN_HB); - return; - } - if (VideoCode == HDMI_4k2k_30) + VEN_DB[3] = 0x00; /* 4k x 2k Spec P156 */ + + if (VideoCode == HDMI_4k2k_30) { + VEN_DB[3] = 0x20; VEN_DB[4] = 0x1; - else if (VideoCode == HDMI_4k2k_25) + } else if (VideoCode == HDMI_4k2k_25) { + VEN_DB[3] = 0x20; VEN_DB[4] = 0x2; - else if (VideoCode == HDMI_4k2k_24) + } else if (VideoCode == HDMI_4k2k_24) { + VEN_DB[3] = 0x20; VEN_DB[4] = 0x3; - else if (VideoCode == HDMI_4k2k_smpte_24) + } else if (VideoCode == HDMI_4k2k_smpte_24) { + VEN_DB[3] = 0x20; VEN_DB[4] = 0x4; - else + } else ; hdev->HWOp.SetPacket(HDMI_PACKET_VEND, VEN_DB, VEN_HB); } diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index 73e3e6d71448..d3719ed3f27e 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -2020,8 +2020,13 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) case HDMI_PACKET_VEND: if ((!DB) || (!HB)) { hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 0, 3, 1); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, 0x0); return; } + /*DV function must set bit 0~1 to 0 in P_VPU_HDMI_FMT_CTRL */ + if ((HB[2] == 0x18) || (HB[2] == 0x1b)) + hd_set_reg_bits(P_VPU_HDMI_FMT_CTRL, 0, 0, 2); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID0, DB[0]); hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID1, DB[1]); hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID2, DB[2]); @@ -2039,6 +2044,13 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) else hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, 6); } + if (HB[2] == 0x1b) {/*set dolby vsif data information*/ + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD1, DB[4]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD2, DB[5]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD3, DB[6]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD4, DB[7]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD5, DB[8]); + } /* Enable VSI packet */ hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 1, 3, 1); hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO1, 0); diff --git a/include/linux/amlogic/media/amdolbyvision/dolby_vision.h b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h new file mode 100644 index 000000000000..1d4c11d3b7b3 --- /dev/null +++ b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h @@ -0,0 +1,48 @@ +#ifndef _DV_H_ +#define _DV_H_ + +#define V1_5 +#define V2_4 + +#include + +extern void enable_dolby_vision(int enable); +extern bool is_dolby_vision_enable(void); +extern bool is_dolby_vision_on(void); +extern bool for_dolby_vision_certification(void); +extern void set_dolby_vision_mode(int mode); +extern int get_dolby_vision_mode(void); +extern void dolby_vision_set_toggle_flag(int flag); +extern int dolby_vision_wait_metadata(struct vframe_s *vf); +extern int dolby_vision_pop_metadata(void); +extern int dolby_vision_update_metadata(struct vframe_s *vf); +extern int dolby_vision_process(struct vframe_s *vf, u32 display_size); +extern void dolby_vision_init_receiver(void *pdev); +extern void dolby_vision_vf_put(struct vframe_s *vf); +extern struct vframe_s *dolby_vision_vf_peek_el(struct vframe_s *vf); +extern void dolby_vision_dump_setting(int debug_flag); +extern void dolby_vision_dump_struct(void); +extern void enable_osd_path(int on, int shadow_mode); +extern void tv_dolby_vision_config(int config); +extern void dolby_vision_update_pq_config( + char *pq_config_buf); +extern int dolby_vision_update_setting(void); +extern bool is_dolby_vision_stb_mode(void); +extern void tv_dolby_vision_crc_clear(int flag); +extern char *tv_dolby_vision_get_crc(u32 *len); +extern void tv_dolby_vision_insert_crc(bool print); +extern int dolby_vision_check_hdr10(struct vframe_s *vf); +extern void tv_dolby_vision_dma_table_modify( + u32 tbl_id, uint64_t value); +extern void tv_dolby_vision_efuse_info(void); +extern int dolby_vision_parse_metadata( + struct vframe_s *vf, u8 toggle_mode, bool bypass_release); +extern void dolby_vision_update_vsvdb_config( + char *vsvdb_buf, u32 tbl_size); +extern void tv_dolby_vision_el_info(void); + +extern int enable_rgb_to_yuv_matrix_for_dvll( + int32_t on, uint32_t *coeff_orig, uint32_t bits); + + +#endif diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index c4e97628c707..44c80c8327f8 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -249,24 +249,6 @@ extern void amvecm_sharpness_enable(int sel); extern int metadata_read_u32(uint32_t *value); extern int metadata_wait(struct vframe_s *vf); extern int metadata_sync(uint32_t frame_id, uint64_t pts); - -extern void enable_dolby_vision(int enable); -extern bool is_dolby_vision_enable(void); -extern bool is_dolby_vision_on(void); -extern bool for_dolby_vision_certification(void); -extern void set_dolby_vision_mode(int mode); -extern int get_dolby_vision_mode(void); -extern void dolby_vision_set_toggle_flag(int flag); -extern int dolby_vision_wait_metadata(struct vframe_s *vf); -extern int dolby_vision_pop_metadata(void); -extern int dolby_vision_update_metadata(struct vframe_s *vf); -extern int dolby_vision_process(struct vframe_s *vf); -extern void dolby_vision_init_receiver(void); -extern void dolby_vision_vf_put(struct vframe_s *vf); -extern struct vframe_s *dolby_vision_vf_peek_el(struct vframe_s *vf); -extern void dolby_vision_dump_setting(int debug_flag); -extern void dolby_vision_dump_struct(void); -extern void enable_osd_path(int on, int shadow_mode); extern void amvecm_wakeup_queue(void); #endif /* AMVECM_H */ diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index cb7a98a49c68..47df648fecbe 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -355,6 +355,7 @@ struct hdmitx_dev { unsigned char hdmi_audio_off_flag; enum hdmi_hdr_transfer hdr_transfer_feature; enum hdmi_hdr_color hdr_color_feature; + unsigned int dv_src_feature; unsigned int sdr_hdr_feature; unsigned int flag_3dfp:1; unsigned int flag_3dtb:1; diff --git a/include/linux/amlogic/media/vout/vinfo.h b/include/linux/amlogic/media/vout/vinfo.h index c4ce9924fa4c..46a0a8f1a5af 100644 --- a/include/linux/amlogic/media/vout/vinfo.h +++ b/include/linux/amlogic/media/vout/vinfo.h @@ -66,50 +66,87 @@ enum eotf_type { EOTF_T_DOLBYVISION, EOTF_T_HDR10, EOTF_T_SDR, + EOTF_T_LL_MODE, EOTF_T_MAX, }; -/* Dolby Version support information */ -struct dv_info { - uint32_t ieeeoui; - uint8_t ver; /* 0 or 1 */ - uint8_t sup_yuv422_12bit:1; /* if as 0, then support RGB tunnel mode */ - uint8_t sup_2160p60hz:1; /* if as 0, then support 2160p30hz */ - uint8_t sup_global_dimming:1; - uint8_t colorimetry:1; +enum mode_type { + YUV422_BIT12 = 0, + RGB_8BIT, + RGB_10_12BIT, + YUV444_10_12BIT, +}; + +#define DV_IEEE_OUI 0x00D046 + +/* Dolby Version VSIF parameter*/ +struct dv_vsif_para { + uint8_t ver; /* 0 or 1 or 2*/ + uint8_t length;/*ver1: 15 or 12*/ union { struct { - uint16_t chrom_red_primary_x; - uint16_t chrom_red_primary_y; - uint16_t chrom_green_primary_x; - uint16_t chrom_green_primary_y; - uint16_t chrom_blue_primary_x; - uint16_t chrom_blue_primary_y; - uint16_t chrom_white_primary_x; - uint16_t chrom_white_primary_y; - uint16_t target_min_pq; - uint16_t target_max_pq; - uint8_t dm_major_ver; - uint8_t dm_minor_ver; - } ver0; - struct { - uint8_t dm_version; - uint8_t target_max_lum; - uint8_t target_min_lum; - uint8_t chrom_red_primary_x; - uint8_t chrom_red_primary_y; - uint8_t chrom_green_primary_x; - uint8_t chrom_green_primary_y; - uint8_t chrom_blue_primary_x; - uint8_t chrom_blue_primary_y; - } ver1; + uint8_t low_latency:1; + uint8_t dobly_vision_signal:1; + uint8_t backlt_ctrl_MD_present:1; + uint8_t auxiliary_MD_present:1; + uint8_t eff_tmax_PQ_hi; + uint8_t eff_tmax_PQ_low; + uint8_t auxiliary_runmode; + uint8_t auxiliary_runversion; + uint8_t auxiliary_debug0; + } ver2; } vers; }; +/* Dolby Version support information from EDID*/ +/* Refer to DV Spec version2.9 page26 to page39*/ +enum block_type { + ERROR_NULL = 0, + ERROR_LENGTH, + ERROR_OUI, + CORRECT, +}; + +struct dv_info { + unsigned char rawdata[27]; + enum block_type block_flag; + uint32_t ieeeoui; + uint8_t ver; /* 0 or 1 or 2*/ + uint8_t length;/*ver1: 15 or 12*/ + + uint8_t sup_yuv422_12bit:1; + /* if as 0, then support RGB tunnel mode */ + uint8_t sup_2160p60hz:1; + /* if as 0, then support 2160p30hz */ + uint8_t sup_global_dimming:1; + uint16_t Rx; + uint16_t Ry; + uint16_t Gx; + uint16_t Gy; + uint16_t Bx; + uint16_t By; + uint16_t Wx; + uint16_t Wy; + uint16_t tminPQ; + uint16_t tmaxPQ; + uint8_t dm_major_ver; + uint8_t dm_minor_ver; + uint8_t dm_version; + uint8_t tmaxLUM; + uint8_t colorimetry:1;/* ver1*/ + uint8_t tminLUM; + uint8_t low_latency:1;/* ver1_12 and 2*/ + uint8_t sup_backlight_control:1;/*only ver2*/ + uint8_t backlt_min_luma;/*only ver2*/ + uint8_t Interface;/*only ver2*/ + uint8_t sup_10b_12b_444;/*only ver2*/ +}; + struct vout_device_s { const struct dv_info *dv_info; void (*fresh_tx_hdr_pkt)(struct master_display_info_s *data); - void (*fresh_tx_vsif_pkt)(enum eotf_type type, uint8_t tunnel_mode); + void (*fresh_tx_vsif_pkt)(enum eotf_type type, + enum mode_type tunnel_mode, struct dv_vsif_para *data); }; struct vinfo_base_s {