author | Cheng Wang <cheng.wang@amlogic.com> | 2019-08-02 08:20:17 (GMT) |
---|---|---|
committer | Tao Zeng <tao.zeng@amlogic.com> | 2019-08-07 01:14:09 (GMT) |
commit | 4a86c572a057375dbf777d6cc581cd79ca19e0e1 (patch) | |
tree | 8e8d2fdb4ee46696048b2620ecd5d39eee58bee7 | |
parent | 0560609ab8e7386cde52a9653a34a3ba5b5a3567 (diff) | |
download | common-4a86c572a057375dbf777d6cc581cd79ca19e0e1.zip common-4a86c572a057375dbf777d6cc581cd79ca19e0e1.tar.gz common-4a86c572a057375dbf777d6cc581cd79ca19e0e1.tar.bz2 |
amvecm: add HDR10+ function for android Q [1/1]
PD#SWPL-11684
Problem:
add HDR10+ function for android Q
Solution:
add HDR10+ function for android Q
Verify:
on u212
Change-Id: If225822de1280018a00304201778b9a6ab179534
Signed-off-by: Cheng Wang <cheng.wang@amlogic.com>
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | arch/arm64/configs/meson64_defconfig | 2 | ||||
-rw-r--r-- | drivers/amlogic/media/enhancement/amvecm/Makefile | 1 | ||||
-rw-r--r-- | drivers/amlogic/media/enhancement/amvecm/amcsc.c | 16 | ||||
-rw-r--r-- | drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c | 4 | ||||
-rw-r--r-- | drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.h | 53 | ||||
-rw-r--r-- | drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c | 820 | ||||
-rw-r--r-- | drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h | 134 | ||||
-rw-r--r-- | drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h | 5 | ||||
-rw-r--r-- | include/linux/amlogic/media/vfm/vframe.h | 49 |
10 files changed, 1037 insertions, 53 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index f392806..dcb779a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14976,3 +14976,9 @@ F: arch/arm/boot/dts/amlogic/partition_mbox_normal_dynamic.dtsi F: arch/arm64/boot/dts/amlogic/firmware_avb_Q.dtsi F: arch/arm64/boot/dts/amlogic/firmware_normal_Q.dtsi F: arch/arm64/boot/dts/amlogic/partition_mbox_normal_dynamic.dtsi + +AMLOGIC ADD HDR10+ FUNCTION FOR ANDROID Q +M: Cheng Wang <cheng.wang@amlogic.com> +F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c +F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h + diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 2b1f9a7..d77d99b 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -514,9 +514,9 @@ CONFIG_AMLOGIC_SND_SOC_MESON=y CONFIG_AMLOGIC_SND_SOC_AUGE=y CONFIG_AMLOGIC_SND_SPLIT_MODE=y CONFIG_AMLOGIC_SND_SOC_COMMON=y -CONFIG_HID_SONY=y CONFIG_HIDRAW=y CONFIG_UHID=y +CONFIG_HID_SONY=y CONFIG_USB_HIDDEV=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y diff --git a/drivers/amlogic/media/enhancement/amvecm/Makefile b/drivers/amlogic/media/enhancement/amvecm/Makefile index 894e057..4e258fb 100644 --- a/drivers/amlogic/media/enhancement/amvecm/Makefile +++ b/drivers/amlogic/media/enhancement/amvecm/Makefile @@ -16,3 +16,4 @@ am_vecm-objs += vlock.o am_vecm-objs += hdr/am_hdr10_plus.o am_vecm-objs += local_contrast.o am_vecm-objs += amvecm_drm.o +am_vecm-objs += hdr/am_hdr10_plus_ootf.o diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc.c b/drivers/amlogic/media/enhancement/amvecm/amcsc.c index e4ef11b..52bcaea 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc.c @@ -40,6 +40,7 @@ #include "set_hdr2_v0.h" #include <linux/amlogic/media/amdolbyvision/dolby_vision.h> #include "hdr/am_hdr10_plus.h" +#include "hdr/am_hdr10_plus_ootf.h" #define pr_csc(fmt, args...)\ do {\ @@ -1885,6 +1886,7 @@ const char matrix_name[7][16] = { static void print_vpp_matrix(int m_select, int *s, int on) { unsigned int size; + if (s == NULL) return; if (m_select == VPP_MATRIX_OSD) @@ -2468,6 +2470,7 @@ void enable_osd_path(int on, int shadow_mode) static int *osd1_mtx_backup; static uint32_t osd1_eotf_ctl_backup; static uint32_t osd1_oetf_ctl_backup; + if (!on) { osd1_mtx_backup = cur_osd_mtx; osd1_eotf_ctl_backup = hdr_osd_reg.viu_osd1_eotf_ctl; @@ -3121,6 +3124,7 @@ static void vpp_set_matrix( struct matrix_s *m) { int reg_value; + if (force_csc_type != 0xff) csc_mode = force_csc_type; @@ -3657,6 +3661,7 @@ int signal_type_changed(struct vframe_s *vf, struct vinfo_s *vinfo) enum vpp_matrix_csc_e get_csc_type(void) { enum vpp_matrix_csc_e csc_type = VPP_MATRIX_NULL; + if ((signal_color_primaries == 1) && (signal_transfer_characteristic < 14)) { if (signal_range == 0) @@ -3921,6 +3926,7 @@ static void apply_scale_factor(int64_t (*in)[3], int32_t *rs) static void N2C(int64_t (*in)[3], int32_t ibl, int32_t obl) { int i, j; + for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) { in[i][j] = @@ -3937,6 +3943,7 @@ static void cal_mtx_seting( { int i, j; int32_t right_shift; + if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB) { apply_scale_factor(in, &right_shift); m->right_shift = right_shift; @@ -4176,6 +4183,7 @@ static void amvecm_cp_hdr_info(struct master_display_info_s *hdr_data, struct vframe_master_display_colour_s *p) { int i, j; + if (customer_hdmi_display_en) { hdr_data->features = (1 << 29) /* video available */ @@ -4390,8 +4398,9 @@ static int hdr_process( int i, j; if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { - hdr_func(VD1_HDR, HDR_SDR); + hdr_func(OSD1_HDR, HDR_BYPASS); + hdr_func(VD1_HDR, HDR_SDR); return need_adjust_contrast_saturation; } @@ -5988,6 +5997,8 @@ static void hdr10_plus_metadata_update(struct vframe_s *vf, hdr10_plus_parser_metadata(vf); + hdr10_plus_ootf_gen(); + if (tx_hdr10_plus_support) hdr10_plus_hdmitx_vsif_parser(hdmitx_hdr10plus_param); } @@ -6294,7 +6305,8 @@ static void video_process( if ((signal_change_flag & SIG_HDR10_PLUS_MODE) || (cur_csc_type != VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC)) - hdr10_plus_process(vf); + hdr_process(csc_type, vinfo, p); + /*hdr10_plus_process(vf);*/ pr_csc("hdr10_plus_process.\n"); } else { if ((csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB) && diff --git a/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c index e4447c4..4273c96 100644 --- a/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c +++ b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c @@ -28,6 +28,7 @@ #include <linux/amlogic/media/vfm/vframe_receiver.h> #include "am_hdr10_plus.h" +#include "am_hdr10_plus_ootf.h" uint debug_hdr; #define pr_hdr(fmt, args...)\ @@ -80,7 +81,7 @@ struct hdr_plus_bits_s sei_md_bits = { .len_color_saturation_weight = 6 }; -struct vframe_hdr_plus_sei_s hdr_plus_sei; +struct vframe_hdr_plus_sei_s1 hdr_plus_sei; #define NAL_UNIT_SEI 39 #define NAL_UNIT_SEI_SUFFIX 40 @@ -642,6 +643,7 @@ void hdr10_plus_process(struct vframe_s *vf) { if (!vf) return; + hdr10_plus_ootf_gen(); } void hdr10_plus_debug(void) diff --git a/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.h b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.h index 79c7356..8a93b97 100644 --- a/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.h +++ b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.h @@ -17,6 +17,57 @@ #ifndef AM_HDR_H #define AM_HDR_H + +struct vframe_hdr_plus_sei_s1 { + u16 present_flag; + u16 itu_t_t35_country_code; + u16 itu_t_t35_terminal_provider_code; + u16 itu_t_t35_terminal_provider_oriented_code; + u16 application_identifier; + u16 application_version; + /*num_windows max is 3*/ + u16 num_windows; + /*windows xy*/ + u16 window_upper_left_corner_x[3]; + u16 window_upper_left_corner_y[3]; + u16 window_lower_right_corner_x[3]; + u16 window_lower_right_corner_y[3]; + u16 center_of_ellipse_x[3]; + u16 center_of_ellipse_y[3]; + u16 rotation_angle[3]; + u16 semimajor_axis_internal_ellipse[3]; + u16 semimajor_axis_external_ellipse[3]; + u16 semiminor_axis_external_ellipse[3]; + u16 overlap_process_option[3]; + /*target luminance*/ + u32 tgt_sys_disp_max_lumi; + u16 tgt_sys_disp_act_pk_lumi_flag; + u16 num_rows_tgt_sys_disp_act_pk_lumi; + u16 num_cols_tgt_sys_disp_act_pk_lumi; + u16 tgt_sys_disp_act_pk_lumi[25][25]; + + /*num_windows max is 3, e.g maxscl[num_windows][i];*/ + u32 maxscl[3][3]; + u32 average_maxrgb[3]; + u16 num_distribution_maxrgb_percentiles[3]; + u16 distribution_maxrgb_percentages[3][15]; + u32 distribution_maxrgb_percentiles[3][15]; + u16 fraction_bright_pixels[3]; + + u16 mast_disp_act_pk_lumi_flag; + u16 num_rows_mast_disp_act_pk_lumi; + u16 num_cols_mast_disp_act_pk_lumi; + u16 mast_disp_act_pk_lumi[25][25]; + /*num_windows max is 3, e.g knee_point_x[num_windows]*/ + u16 tone_mapping_flag[3]; + u16 knee_point_x[3]; + u16 knee_point_y[3]; + u16 num_bezier_curve_anchors[3]; + u16 bezier_curve_anchors[3][15]; + u16 color_saturation_mapping_flag[3]; + u16 color_saturation_weight[3]; +}; + struct hdr_plus_bits_s { u16 len_itu_t_t35_country_code; u16 len_itu_t_t35_terminal_provider_code; @@ -74,5 +125,7 @@ extern void hdr10_plus_hdmitx_vsif_parser( extern void hdr10_plus_parser_metadata(struct vframe_s *vf); extern void hdr10_plus_process(struct vframe_s *vf); extern void hdr10_plus_debug(void); +extern struct vframe_hdr_plus_sei_s1 hdr_plus_sei; + #endif /* AM_HDR_H */ diff --git a/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c new file mode 100644 index 0000000..52f4da8 --- a/dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c @@ -0,0 +1,820 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/* Standard Linux headers */ +#include <linux/types.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/debugfs.h> +#include <linux/uaccess.h> +#include <linux/amlogic/media/vout/vout_notify.h> +#include <linux/amlogic/media/vfm/vframe_provider.h> +#include <linux/amlogic/media/vfm/vframe_receiver.h> +#include <linux/amlogic/media/amvecm/amvecm.h> +#include "../arch/vpp_hdr_regs.h" +#include "am_hdr10_plus.h" +#include "am_hdr10_plus_ootf.h" +#include "../set_hdr2_v0.h" + +unsigned int hdr10_plus_printk; +module_param(hdr10_plus_printk, uint, 0664); +MODULE_PARM_DESC(hdr10_plus_printk, "hdr10_plus_printk"); + +#define pr_hdr(fmt, args...)\ + do {\ + if (hdr10_plus_printk)\ + pr_info(fmt, ## args);\ + } while (0) + +/*EBZCurveParameters to gen OOTF bezier curves*/ +void EBZCurveParametersInit(struct EBZCurveParameters *EBZCurveParameters) +{ + int i; + + EBZCurveParameters->Sx = 0; + EBZCurveParameters->Sy = 0; + EBZCurveParameters->order = N; + for (i = 0; i < N; i++) + EBZCurveParameters->Anchor[i] = PORCESSING_DATA_MAX; +} + +/*percentile actually obtained from metadata */ +void PercentileInit(struct Percentiles *percentile, + struct hdr10_plus_sei_s *hdr10_plus_sei) +{ + int i; + + percentile->num_percentile = hdr10_plus_sei->num_distributions[0]; + for (i = 0; i < percentile->num_percentile; i++) { + percentile->percentilePercent[i] = + hdr10_plus_sei->distribution_index[0][i]; + percentile->percentileValue[i] = + hdr10_plus_sei->distribution_values[0][i] / 10; + } +} + +/*metadata should obtained from 3C or 2094 metadata*/ +void MetaDataInit(struct Scene2094Metadata *Metadata, + struct hdr10_plus_sei_s *hdr10_plus_sei) +{ + int i; + + Metadata->maxSceneSourceLuminance = + max(max(hdr10_plus_sei->maxscl[0][0], + hdr10_plus_sei->maxscl[0][1]), + hdr10_plus_sei->maxscl[0][2]); + Metadata->minLuminance = MIN_LUMINANCE; + Metadata->referenceLuminance = + hdr10_plus_sei->targeted_system_display_maximum_luminance; + PercentileInit(&(Metadata->percentiles), hdr10_plus_sei); + + Metadata->EBZCurveParameters.Sx = hdr10_plus_sei->knee_point_x[0]; + Metadata->EBZCurveParameters.Sy = hdr10_plus_sei->knee_point_y[0]; + Metadata->EBZCurveParameters.order = + hdr10_plus_sei->num_bezier_curve_anchors[0]; + for (i = 0; i < N - 1; i++) + Metadata->EBZCurveParameters.Anchor[i] = + hdr10_plus_sei->bezier_curve_anchors[0][i]; +} + +/* get EBZcurve params from metadata.*/ +void getMetaData(struct Scene2094Metadata *metadata, + struct EBZCurveParameters *referenceBezierParams) +{ + int i; + + referenceBezierParams->order = metadata->EBZCurveParameters.order + 1; + referenceBezierParams->Sy = metadata->EBZCurveParameters.Sy; + referenceBezierParams->Sx = metadata->EBZCurveParameters.Sx; + for (i = 0; i < referenceBezierParams->order; i++) + referenceBezierParams->Anchor[i] = + metadata->EBZCurveParameters.Anchor[i]; +} + +/*TV side default setting: bezier curve params to gen basic OOTF curve*/ +void BasisOOTF_Params_init(struct BasisOOTF_Params *BasisOOTF_Params) +{ + int P2ToP9_MAX1_init[ORDER - 2] = { + 0.5582 * PORCESSING_DATA_MAX, 0.6745 * PORCESSING_DATA_MAX, + 0.7703 * PORCESSING_DATA_MAX, 0.8231 * PORCESSING_DATA_MAX, + 0.8729 * PORCESSING_DATA_MAX, 0.9130 * PORCESSING_DATA_MAX, + 0.9599 * PORCESSING_DATA_MAX, 0.9844 * PORCESSING_DATA_MAX + }; + int P2ToP9_MAX2_init[ORDER - 2] = { + 0.4839 * PORCESSING_DATA_MAX, 0.6325 * PORCESSING_DATA_MAX, + 0.7253 * PORCESSING_DATA_MAX, 0.7722 * PORCESSING_DATA_MAX, + 0.8201 * PORCESSING_DATA_MAX, 0.8837 * PORCESSING_DATA_MAX, + 0.9208 * PORCESSING_DATA_MAX, 0.9580 * PORCESSING_DATA_MAX + }; + int i; + + /*u12*/ + BasisOOTF_Params->SY1_V1 = 0 << (PROCESSING_MAX - 12); + BasisOOTF_Params->SY1_V2 = 1229 << (PROCESSING_MAX - 12); + BasisOOTF_Params->SY1_T1 = 901 << (PROCESSING_MAX - 12); + BasisOOTF_Params->SY1_T2 = 4095 << (PROCESSING_MAX - 12); + BasisOOTF_Params->SY2_V1 = 0 << (PROCESSING_MAX - 12); + BasisOOTF_Params->SY2_V2 = 819 << (PROCESSING_MAX - 12); + BasisOOTF_Params->SY2_T1 = 1024 << (PROCESSING_MAX - 12); + BasisOOTF_Params->SY2_T2 = 3890 << (PROCESSING_MAX - 12); + + /* KP mixing gain (final KP from bounds KP # 1 and KP # 2*/ + /*as a function of scene percentile) */ + BasisOOTF_Params->KP_G_V1 = 4095 << (PROCESSING_MAX - 12); + BasisOOTF_Params->KP_G_V2 = 205 << (PROCESSING_MAX - 12); + BasisOOTF_Params->KP_G_T1 = 205 << (PROCESSING_MAX - 12); + BasisOOTF_Params->KP_G_T2 = 2048 << (PROCESSING_MAX - 12); + + /*Thresholds of minimum bound of P1 coefficient*/ + BasisOOTF_Params->P1_LIMIT_V1 = 3767 << (PROCESSING_MAX - 12); + BasisOOTF_Params->P1_LIMIT_V2 = 4013 << (PROCESSING_MAX - 12); + BasisOOTF_Params->P1_LIMIT_T1 = 41 << (PROCESSING_MAX - 12); + BasisOOTF_Params->P1_LIMIT_T2 = 410 << (PROCESSING_MAX - 12); + + /*Thresholds to compute relative shape of curve (P2~P9 coefficient)*/ + /*by pre-defined bounds - as a function of scene percentile*/ + BasisOOTF_Params->P2To9_T1 = 205 << (PROCESSING_MAX - 12); + BasisOOTF_Params->P2To9_T2 = 2252 << (PROCESSING_MAX - 12); + + for (i = 0; i < (ORDER - 2); i++) { + BasisOOTF_Params->P2ToP9_MAX1[i] = P2ToP9_MAX1_init[i]; + BasisOOTF_Params->P2ToP9_MAX2[i] = P2ToP9_MAX2_init[i]; + } + + /*Ps mixing gain (obtain all Ps coefficients) -*/ + /*as a function of TM dynamic compression ratio*/ + BasisOOTF_Params->PS_G_T1 = 512 << (PROCESSING_MAX - 12); + BasisOOTF_Params->PS_G_T2 = 3890 << (PROCESSING_MAX - 12); + + /*Post-processing : Reduce P1/P2 (to enhance mid tone)*/ + /*for high TM dynamic range compression cases*/ + BasisOOTF_Params->LOW_SY_T1 = 20 << (PROCESSING_MAX - 12); + BasisOOTF_Params->LOW_SY_T2 = 164 << (PROCESSING_MAX - 12); + BasisOOTF_Params->LOW_K_T1 = 491 << (PROCESSING_MAX - 12); + BasisOOTF_Params->LOW_K_T2 = 1638 << (PROCESSING_MAX - 12); + BasisOOTF_Params->RED_P1_V1 = 2662 << (PROCESSING_MAX - 12); + BasisOOTF_Params->RED_P1_T1 = 410 << (PROCESSING_MAX - 12); + BasisOOTF_Params->RED_P1_T2 = 3071 << (PROCESSING_MAX - 12); + BasisOOTF_Params->RED_P2_V1 = 3276 << (PROCESSING_MAX - 12); + BasisOOTF_Params->RED_P2_T1 = 410 << (PROCESSING_MAX - 12); + BasisOOTF_Params->RED_P2_T2 = 3071 << (PROCESSING_MAX - 12); +} + +/*obtain percentile info on psl50 and psl99,*/ +/*to calculate content average level and distribution later*/ +void getPercentile_50_99(struct Percentiles *scenePercentiles, + int *psll50, int *psll99) +{ + int i; + int npsll = PERCENTILE_ORDER; + int delta; + + /*Find exact percentiles if provided , else interpolate*/ + int psll50_1 = -1, per50_1 = -1; + int psll50_2 = -1, per50_2 = -1; + int psll99_1 = -1, per99_1 = -1; + int psll99_2 = -1, per99_2 = -1; + + /* Search for exact percent index or bounds*/ + int curPercent = 0, prevPercent = 0; + int curPsll = 0, prevPsll = 0; + + /*Set output to -1 (invalid)*/ + *psll50 = -1; + *psll99 = -1; + + for (i = 0; i < npsll; i++) { + if (i == 1 || i == 2) + continue; + curPercent = scenePercentiles->percentilePercent[i]; + curPsll = scenePercentiles->percentileValue[i]; + if (curPercent == 50) + *psll50 = curPsll; + else if (*psll50 == -1 && curPercent > 50 && prevPercent < 50) { + per50_1 = prevPercent; + per50_2 = curPercent; + psll50_1 = prevPsll; + psll50_2 = curPsll; + } + + if (curPercent == 99) { + *psll99 = curPsll; + } else if (*psll99 == -1 && curPercent > 99 && + prevPercent < 99) { + per99_1 = prevPercent; + per99_2 = curPercent; + psll99_1 = prevPsll; + psll99_2 = curPsll; + } + prevPercent = curPercent; + prevPsll = curPsll; + } + + if (*psll50 == -1) { + delta = max((per50_2 - per50_1), 1); + *psll50 = psll50_1 + (psll50_2 - psll50_1) * + (50 - per50_1) / delta; + } + + if (*psll99 == -1) { + delta = max((per99_2 - per99_1), 1); + *psll99 = psll99_1 + (psll99_2 - psll99_1) * + (99 - per99_1) / delta; + } +} + +/* function to calculate linear interpolation*/ +int rampWeight(int v1, int v2, int t1, int t2, int t) +{ + int retVal = v1; + + if (t1 == t2) + retVal = (t < t1) ? (v1) : (v2); + else { + if (t <= t1) + retVal = v1; + else if (t >= t2) + retVal = v2; + else + retVal = v1 + (v2 - v1) * (t - t1) / (t2 - t1); + } + + return retVal; +} + +/*p1 calculation based on default setting and*/ +/*content statistic information(percentile)*/ +int calcP1(int sx, int sy, int tgtL, int calcMaxL, + struct BasisOOTF_Params *basisOOTF_Params, + int *p1_red_gain) + +{ + int ax, ay, k, p1_limit, k2, p1_t, p1; + int low_sy_g, high_k_g, high_tm_g, red_p1; + + ax = min(sx, PORCESSING_DATA_MAX); + ay = min(sy, PORCESSING_DATA_MAX); + + k = tgtL * PORCESSING_DATA_MAX / max(tgtL, calcMaxL); + p1_limit = rampWeight(basisOOTF_Params->P1_LIMIT_V2, + basisOOTF_Params->P1_LIMIT_V1, + basisOOTF_Params->P1_LIMIT_T1, + basisOOTF_Params->P1_LIMIT_T2, sy); + k2 = (PORCESSING_DATA_MAX + 1 - ax) * PORCESSING_DATA_MAX / + (ORDER * (PORCESSING_DATA_MAX + 1 - ay)); + p1_t = k2 * PORCESSING_DATA_MAX / k; + p1 = max(min(p1_t, p1_limit), 0); + low_sy_g = rampWeight(PORCESSING_DATA_MAX + 1, 0, + basisOOTF_Params->LOW_SY_T1, basisOOTF_Params->LOW_SY_T2, sy); + high_k_g = rampWeight(PORCESSING_DATA_MAX + 1, 0, + basisOOTF_Params->LOW_K_T1, basisOOTF_Params->LOW_K_T2, k); + high_tm_g = low_sy_g * high_k_g >> PROCESSING_MAX; + red_p1 = rampWeight(PORCESSING_DATA_MAX + 1, + basisOOTF_Params->RED_P1_V1, basisOOTF_Params->RED_P1_T1, + basisOOTF_Params->RED_P1_T2, high_tm_g); + p1 = min(max((p1 * red_p1) >> PROCESSING_MAX, P1MIN), p1_limit); + + if (p1_red_gain != NULL) + *p1_red_gain = high_tm_g; + + return p1; +} + +/*gen BasisOOTF parameters (sx,sy,p1~pn-1),based on content percentiles*/ + /*and default bezier params*/ +int basisOOTF(struct Scene2094Metadata *metadata, + struct BasisOOTF_Params *basisOOTF_Params, int productPeak, + int sourceMaxL, struct EBZCurveParameters *sceneBezierParams) +{ + int order = ORDER; + int psll50, psll99, centerLuminance, k, sy1, sy2, sy, sx, rem; + int high_tm_g, p1, rem_p29, rem_ps, rem_red_p2, ps2to9[ORDER - 1]; + int coeffi, plin[ORDER - 1], pcoeff[ORDER - 1]; + int targetLuminance = productPeak; + int sourceLuminance = max(targetLuminance, sourceMaxL); + int i; + + getPercentile_50_99(&(metadata->percentiles), &psll50, &psll99); + + centerLuminance = psll50 * PORCESSING_DATA_MAX / max(psll99, 1); + k = targetLuminance * PORCESSING_DATA_MAX / sourceLuminance; + + sy1 = rampWeight(basisOOTF_Params->SY1_V1, basisOOTF_Params->SY1_V2, + basisOOTF_Params->SY1_T1, basisOOTF_Params->SY1_T2, k); + sy2 = rampWeight(basisOOTF_Params->SY2_V1, basisOOTF_Params->SY2_V2, + basisOOTF_Params->SY2_T1, basisOOTF_Params->SY2_T2, k); + rem = rampWeight(basisOOTF_Params->KP_G_V1, basisOOTF_Params->KP_G_V2, + basisOOTF_Params->KP_G_T1, basisOOTF_Params->KP_G_T2, + centerLuminance); + sy = (rem * sy1 + (PORCESSING_DATA_MAX + 1 - rem) * sy2) >> + PROCESSING_MAX; + sx = sy * k; + + /*P coefficient*/ + high_tm_g = 0; + + p1 = calcP1(sx, sy, targetLuminance, sourceMaxL, + basisOOTF_Params, &high_tm_g); + + for (i = 0; i < (NPCOEFF - 1); i++) { + rem_p29 = rampWeight(basisOOTF_Params->P2ToP9_MAX2[i], + basisOOTF_Params->P2ToP9_MAX1[i], basisOOTF_Params->P2To9_T1, + basisOOTF_Params->P2To9_T2, centerLuminance); + ps2to9[i] = (rem_p29 * basisOOTF_Params->P2ToP9_MAX1[i] + + (PORCESSING_DATA_MAX + 1 - rem_p29) * + basisOOTF_Params->P2ToP9_MAX2[i]) >> PROCESSING_MAX; + } + + rem_ps = rampWeight(PORCESSING_DATA_MAX + 1, 0, + basisOOTF_Params->PS_G_T1, basisOOTF_Params->PS_G_T2, k); + + pcoeff[0] = p1; + for (i = 1; i < NPCOEFF; i++) { + coeffi = i + 1; + plin[i] = (coeffi * PORCESSING_DATA_MAX / order); + pcoeff[i] = max(min((rem_ps * ps2to9[i - 1] + + (PORCESSING_DATA_MAX + 1 - rem_ps) * plin[i]) >> PROCESSING_MAX, + coeffi * p1), plin[i]); + } + + /*p[1] recalc precision:0.01,bad*/ + rem_red_p2 = rampWeight(PORCESSING_DATA_MAX + 1, + basisOOTF_Params->RED_P2_V1, basisOOTF_Params->RED_P2_T1, + basisOOTF_Params->RED_P2_T2, high_tm_g); + pcoeff[1] = max(min((pcoeff[1] * rem_red_p2) >> PROCESSING_MAX, 2 * p1), + 2 * PORCESSING_DATA_MAX / ORDER); + + /*finally pcoeff[ORDER-1],sy,sx*/ + sceneBezierParams->Sx = sx; + sceneBezierParams->Sy = sy; + /*only calc ORDER(10) < actual order(15)*/ + for (i = 0; i < NPCOEFF; i++) + sceneBezierParams->Anchor[i] = pcoeff[i]; + + return 0; +} + +/* receive bezier parameter(Kx,ky,P)and return guided parameter base on*/ +/*product panel luminance out: product curve params(Kx,ky,P) */ +int GuidedOOTF(struct Scene2094Metadata *metadata, + struct BasisOOTF_Params *basisOOTF_Params, + struct EBZCurveParameters *referenceBezierParams, + int ProductLuminance, + struct EBZCurveParameters *productBezierParams) +{ + int KP_BYPASS = 1229; + int refenceLuminance = metadata->referenceLuminance; + int productLuminance = ProductLuminance; + int minLuminance = metadata->minLuminance; + int maxLuminance = metadata->maxSceneSourceLuminance; + int order = referenceBezierParams->order; + int numP = order - 1; + + int blendCoeff, norm; + int anchorLinear[14]; + int i; + int ps1; + + struct EBZCurveParameters minBezierParams; + + EBZCurveParametersInit(&minBezierParams); + + for (i = 0; i < numP; i++) + anchorLinear[i] = (i + 1) * PORCESSING_DATA_MAX / order; + +/*---------case 0: productPeak < minL ----------------- */ + if (productLuminance < minLuminance) { + productBezierParams->Sx = 0; + productBezierParams->Sy = 0; + for (i = 0; i < numP; i++) + productBezierParams->Anchor[i] = anchorLinear[i]; + productBezierParams->order = order; + return -1; + } +/*---------case 1: productPeak = ref ----------------- */ + if (productLuminance == refenceLuminance) { + productBezierParams->Sx = referenceBezierParams->Sx; + productBezierParams->Sy = referenceBezierParams->Sy; + productBezierParams->order = referenceBezierParams->order; + + for (i = 0; i < numP; i++) { + productBezierParams->Anchor[i] = + referenceBezierParams->Anchor[i]; + } + } +/*---------case 2: productPeak > maxL ----------------- */ + else if (productLuminance > maxLuminance) { + productBezierParams->Sx = KP_BYPASS; + productBezierParams->Sy = KP_BYPASS; + productBezierParams->order = order; + for (i = 0; i < numP; i++) + productBezierParams->Anchor[i] = anchorLinear[i]; + } +/*---------case 3: minL < productPeak < maxL ----------------- */ + else { + productBezierParams->order = referenceBezierParams->order; +/*---------case 3.1: minL < productPeak < ref ----------------- */ + if (productLuminance < refenceLuminance) { + norm = refenceLuminance - minLuminance; + blendCoeff = refenceLuminance - productLuminance; + + basisOOTF(metadata, basisOOTF_Params, minLuminance, + maxLuminance, &minBezierParams); + + productBezierParams->Sy = + (blendCoeff * minBezierParams.Sy + + (norm - blendCoeff) * referenceBezierParams->Sy + + (norm >> 1)) / norm; + productBezierParams->Sx = + productBezierParams->Sy * productLuminance / + maxLuminance; + for (i = 0; i < numP ; i++) { + productBezierParams->Anchor[i] = + (blendCoeff * referenceBezierParams->Anchor[i] + + (norm - blendCoeff) * + minBezierParams.Anchor[i] + + (norm >> 1)) / norm; + } +/*---------case 3.2: ref < productPeak < maxL ----------------- */ + } else { + norm = maxLuminance - refenceLuminance; + blendCoeff = productLuminance - refenceLuminance; + + productBezierParams->Sy = (blendCoeff * KP_BYPASS + + (norm - blendCoeff) * referenceBezierParams->Sy + + (norm >> 1)) / norm; + productBezierParams->Sx = productBezierParams->Sy * + productLuminance / maxLuminance; + + for (i = 0; i < numP ; i++) { + productBezierParams->Anchor[i] = + (blendCoeff * anchorLinear[i] + + (norm - blendCoeff) * + referenceBezierParams->Anchor[i] + + (norm >> 1)) / norm; + } + } + + ps1 = calcP1(productBezierParams->Sx, productBezierParams->Sy, + productLuminance, maxLuminance, basisOOTF_Params, NULL); + + productBezierParams->Anchor[0] = ps1; + + for (i = 1; i < numP; i++) { + productBezierParams->Anchor[i] = + min(productBezierParams->Anchor[i], + (i + 1) * productBezierParams->Anchor[0]); + } + } + + return 0; +} + +/*bezier optimise method to gen bezier function*/ +int Decasteliau(uint64_t *BezierCurve, uint64_t *AnchorY, + uint64_t u, int order, uint64_t range_ebz_x) +{ + uint64_t PointY[16]; + int i, j; + + for (i = 0; i < order + 1; i++) + PointY[i] = AnchorY[i]; + + for (i = 1; i <= order; i++) + for (j = 0; j <= order - i; j++) { + PointY[j] = (PointY[j] * (range_ebz_x - u) + + PointY[j + 1] * u + range_ebz_x / 2); + PointY[j] = div64_u64(PointY[j], range_ebz_x); + } + + BezierCurve[1] = PointY[0]; + return 0; +} + +#define org_anchory + +uint64_t oo_lut_x[OOLUT_NUM] = { + 0, 16, 32, 64, 128, 256, 512, 1024, 2048, 2560, 3072, 3584, 4096, + 5120, 6144, 7168, 8192, 10240, 12288, 14336, 16384, 20480, 24576, + 28672, 32768, 40960, 49152, 57344, 65536, 81920, 98304, 114688, + 131072, 163840, 196608, 229376, 262144, 327680, 393216, 458752, + 524288, 655360, 786432, 917504, 1048576, 1179648, 1310720, 1441792, + 1572864, 1703936, 1835008, 1966080, 2097152, 2359296, 2621440, 2883584, + 3145728, 3407872, 3670016, 3932160, 4194304, 4718592, 5242880, 5767168, + 6291456, 6815744, 7340032, 7864320, 8388608, 9437184, 10485760, + 11534336, 12582912, 13631488, 14680064, 15728640, 16777216, 18874368, + 20971520, 23068672, 25165824, 27262976, 29360128, 31457280, 33554432, + 37748736, 41943040, 46137344, 50331648, 54525952, 58720256, 62914560, + 67108864, 75497472, 83886080, 92274688, 100663296, 109051904, 117440512, + 125829120, 134217728, 150994944, 167772160, 184549376, 201326592, + 218103808, 234881024, 251658240, 268435456, 301989888, 335544320, + 369098752, 402653184, 436207616, 469762048, 503316480, 536870912, + 603979776, 671088640, 738197504, 805306368, 872415232, 939524096, + 1006632960, 1073741824, 1207959552, 1342177280, 1476395008, 1610612736, + 1744830464, 1879048192, 2013265920ULL, 2147483648ULL, 2281701376ULL, + 2415919104ULL, 2550136832ULL, 2684354560ULL, 2818572288ULL, + 2952790016ULL, 3087007744ULL, 3221225472ULL, 3355443200ULL, + 3489660928ULL, 3623878656ULL, 3758096384ULL, + 3892314112ULL, 4026531840ULL, 4160749568ULL, 4294967296ULL +}; + +/*gen OOTF curve and gain from (sx,sy) and P1~pn-1*/ +int genEBZCurve(uint64_t *CurveX, uint64_t *CurveY, + unsigned int *gain, unsigned int *gain_ter, + uint64_t nKx, uint64_t nKy, + uint64_t *AnchorY, int order) +{ + uint64_t myAnchorY[16]; + uint64_t temp; + uint64_t linearX[POINTS]; + uint64_t Kx, Ky; + + uint64_t range_ebz_x; + uint64_t range_ebz_y; + + uint64_t step_alpha; + uint64_t step_ter[POINTS]; + uint64_t BezierCurve[2]; + int i; + int numP = N-1; + + + /*u12->U16*/ + Kx = nKx << (U32 - PROCESSING_MAX); + Ky = nKy << (U32 - PROCESSING_MAX); + + range_ebz_x = _U32_MAX - Kx; + range_ebz_y = _U32_MAX - Ky; + +#ifdef org_anchory + for (i = 0; i < numP; i++)/* u12-> ebz_y, u32*/ + /*anchorY default range:PROCESSING_MAX */ + myAnchorY[i + 1] = AnchorY[i] << (U32-PROCESSING_MAX); + myAnchorY[0] = 0; + myAnchorY[N] = _U32_MAX; /* u12 */ +#else + for (i = 0; i < numP; i++)/* u12-> ebz_y, u32*/ + /*anchorY default range:PROCESSING_MAX */ + myAnchorY[i + 1] = (AnchorY[i] * range_ebz_y) >> PROCESSING_MAX; + myAnchorY[0] = 0; + myAnchorY[N] = range_ebz_y; /*u12 -> U32*/ +#endif /* org_anchory */ + + for (i = 0; i < POINTS; i++) { + #if 0 + linearX[i] = (uint64_t)(i*_U32_MAX/POINTS); /* x index sample */ + #else + linearX[i] = oo_lut_x[i];/* x index sample,u32 */ + #endif + CurveY[i] = 0; + step_ter[i] = 1023; + } + + for (i = 0; i < POINTS; i++) { + if (linearX[i] < Kx) { + CurveX[i] = linearX[i];/*u32*/ + CurveY[i] = linearX[i] * Ky; + CurveY[i] = div64_u64(CurveY[i], Kx + 1); + temp = CurveY[i] << GAIN_BIT;/*u12*/ + gain[i] = div64_u64(temp, CurveX[i] + 1); + step_ter[i] = 1024; + /*just as a mark for debugging*/ + /*printk("%d(int64):x->y,%lld->%lld,gain=%d\n",*/ + /*i, CurveX[i],CurveY[i],gain[i]);*/ + } else{ + /* step_alpha = (linearX[i]-Kx)/range_ebz_x,*/ + /*norm in Decasteliau() function*/ + step_alpha = (linearX[i] - Kx); + step_ter[i] = step_alpha; + /* calc each point from 1st to N-th layer*/ + Decasteliau(&BezierCurve[0], myAnchorY, step_alpha, + order, range_ebz_x); + /* u32 u32 u32*/ + #ifdef org_anchory /*range_ebz_y = _U32_MAX*/ + CurveY[i] = Ky + ((range_ebz_y * BezierCurve[1] + + range_ebz_y / 2) >> U32); + #else + CurveY[i] = Ky + ((range_ebz_y * BezierCurve[1] + + range_ebz_y / 2)); + CurveY[i] = div64_u64(CurveY[i], range_ebz_y); + #endif /* org_anchory*/ + + /*CurveX[i] = Kx +*/ + /*((range_ebz_x * BezierCurve[0] + range_ebz_x / 2) / */ + /*range_ebz_x);*/ + CurveX[i] = Kx + step_alpha; + temp = CurveY[i] << GAIN_BIT; + gain[i] = div64_u64(temp, CurveX[i] + 1); + + } + temp = CurveY[i] << GAIN_BIT;/*u12*/ + gain[i] = div64_u64(temp, CurveX[i] + 1); + temp = CurveY[i] << GAIN_BIT; + gain_ter[i] = div64_u64(temp, linearX[i] + 1); + } + return 0; +} + +void vframe_hdr_plus_sei_s_init(struct hdr10_plus_sei_s *hdr10_plus_sei) +{ + + int i, temp; + + int percentilePercent_init[PERCENTILE_ORDER] = { + 1, 5, 10, 25, 50, 75, 90, 95, 99}; + int percentileValue_init[PERCENTILE_ORDER] = { + 0, 1, 2, 79, 2537, 9900, 9901, 9902, 9904}; + + hdr10_plus_sei->num_distributions[0] = PERCENTILE_ORDER - 1; + + for (i = 0; i < 3; i++) + hdr10_plus_sei->maxscl[0][i] = hdr_plus_sei.maxscl[0][i] / 10; + + hdr10_plus_sei->targeted_system_display_maximum_luminance = + hdr_plus_sei.tgt_sys_disp_max_lumi; + + for (i = 0; i < (hdr10_plus_sei->num_distributions[0]); i++) { + hdr10_plus_sei->distribution_index[0][i] = + percentilePercent_init[i]; + hdr10_plus_sei->distribution_values[0][i] = + percentileValue_init[i]; + + } + + hdr10_plus_sei->knee_point_x[0] = hdr_plus_sei.knee_point_x[0]; + hdr10_plus_sei->knee_point_y[0] = hdr_plus_sei.knee_point_y[0]; + + hdr10_plus_sei->num_bezier_curve_anchors[0] = + hdr_plus_sei.num_bezier_curve_anchors[0]; + + for (i = 0; i < (hdr10_plus_sei->num_bezier_curve_anchors[0]); i++) { + hdr10_plus_sei->bezier_curve_anchors[0][i] = + hdr_plus_sei.bezier_curve_anchors[0][i] << + (PROCESSING_MAX - 10); + } + + /*debug--*/ + if (hdr10_plus_printk) { + + for (i = 0; i < 3; i++) + pr_hdr("hdr10_plus_sei->maxscl[0][%d]=%d\n", + i, hdr10_plus_sei->maxscl[0][i]); + + pr_hdr("targeted_system_display_maximum_luminance=%d\n", + hdr10_plus_sei->targeted_system_display_maximum_luminance); + + for (i = 0; i < (hdr10_plus_sei->num_distributions[0]); i++) { + pr_hdr("distribution_values[0][%d]=%d\n", + i, hdr10_plus_sei->distribution_values[0][i]); + pr_hdr("hdr10_plus_sei->distribution_index[0][%d]=%d\n", + i, hdr10_plus_sei->distribution_index[0][i]); + } + + pr_hdr("hdr10_plus_sei->knee_point_x = %d\n" + "hdr10_plus_sei->knee_point_y = %d\n", + hdr10_plus_sei->knee_point_x[0], + hdr10_plus_sei->knee_point_y[0]); + + pr_hdr("hdr10_plus_sei->num_bezier_curve_anchors[0] = %d\n", + hdr10_plus_sei->num_bezier_curve_anchors[0]); + + for (i = 0; i < (hdr10_plus_sei->num_bezier_curve_anchors[0]); + i++) { + pr_hdr("bezier_curve_anchors[0][%d] = ", i); + pr_hdr("%d\n", hdr_plus_sei.bezier_curve_anchors[0][i]); + } + for (i = 0; i < 3; i++) { + pr_hdr("average_maxrgb[%d] = ", i); + pr_hdr("%d\n", hdr_plus_sei.average_maxrgb[i]); + } + + temp = hdr_plus_sei.num_distribution_maxrgb_percentiles[0]; + + for (i = 0; i < temp; i++) { + pr_hdr("distribution_maxrgb_percentages[0][%d] = ", i); + pr_hdr("%d\n", + hdr_plus_sei.distribution_maxrgb_percentages[0][i]); + pr_hdr("distribution_maxrgb_percentiles[0][%d] = ", i); + pr_hdr("%d\n", + hdr_plus_sei.distribution_maxrgb_percentiles[0][i]); + } + } + +} + +unsigned int gain[POINTS]; +unsigned int gain_ter[POINTS]; +uint64_t curveX[POINTS], curveY[POINTS]; + +int hdr10_plus_ootf_gen(void) +{ + int referenceCurve_flag = 1; + + int order, i; + uint64_t Kx, Ky; + uint64_t AnchorY[15]; + + /* bezier params obtained from metadata */ + struct hdr10_plus_sei_s hdr10_plus_sei; + struct Scene2094Metadata metadata; + struct EBZCurveParameters referenceBezierParams; + struct EBZCurveParameters productBezierParams; + struct BasisOOTF_Params basisOOTF_Params; + + /* mapping */ + enum hdr_module_sel { + VD1_HDR = 0x1, + VD2_HDR = 0x2, + OSD1_HDR = 0x4, + VDIN0_HDR = 0x8, + VDIN1_HDR = 0x10, + DI_HDR = 0x20, + HDR_MAX + }; + + int productPeak = 700; + +/* for (i = 0; i < POINTS; i++) { + * curveX[i] = 0; + * curveY[i] = 0; + * gain[i] = 0; + * gain_ter[i] = 0; + * } + */ + + memset(curveX, 0, sizeof(uint64_t) * POINTS); + memset(curveY, 0, sizeof(uint64_t) * POINTS); + memset(gain, 0, sizeof(unsigned int) * POINTS); + memset(gain_ter, 0, sizeof(unsigned int) * POINTS); + + BasisOOTF_Params_init(&basisOOTF_Params); + + /* the final tv OOTF curve params init*/ + EBZCurveParametersInit(&productBezierParams); + /* the bezier parameters from metadata init*/ + EBZCurveParametersInit(&referenceBezierParams); + + /* repace with real vframe data*/ + vframe_hdr_plus_sei_s_init(&hdr10_plus_sei); + + /*step 1. get metadata from vframe*/ + MetaDataInit(&metadata, &hdr10_plus_sei); + /*step 2. get bezier params from metadata*/ + getMetaData(&metadata, &referenceBezierParams); + /*step 3. gen final guided OOTF*/ + if (referenceCurve_flag == 0) + /* Basis OOTF : Direct calculation of product TM curve from*/ + /*ST-2094 percentile metadata */ + basisOOTF(&metadata, &basisOOTF_Params, productPeak, + /* here length(minBezierParams->Anchor) =order*/ + metadata.maxSceneSourceLuminance, &productBezierParams); + else + GuidedOOTF(&metadata, &basisOOTF_Params, &referenceBezierParams, + productPeak, &productBezierParams); + + /*step 4. get guided bezier params*/ + Kx = (uint64_t)productBezierParams.Sx; + Ky = (uint64_t)productBezierParams.Sy; + order = productBezierParams.order; + for (i = 0; i < productBezierParams.order - 1; i++) + AnchorY[i] = (uint64_t)productBezierParams.Anchor[i]; + + /*step 5. gen bezier curve*/ + genEBZCurve(&curveX[0], &curveY[0], &gain[0], &gain_ter[0], + Kx, Ky, &AnchorY[0], order); + /* debug */ + if (hdr10_plus_printk) { + for (i = 0; i < POINTS; i++) { + pr_hdr("fixed version:: %3d:(%lld, %lld)->%4d\n", + i, curveX[i], curveY[i], gain[i]); + } + hdr10_plus_printk = 0; + } + + /*hdr10+ temporary does not support other anchors 20190603*/ + if (hdr_plus_sei.num_bezier_curve_anchors[0] == 9) { + for (i = 0; i < POINTS; i++) + hdr_lut_param.ogain_lut[i] = gain[i]; + VSYNC_WR_MPEG_REG(VD1_HDR2_ADPS_ALPHA0, 0x28002800); + /* VSYNC_WR_MPEG_REG(VD1_HDR2_ADPS_ALPHA1,0x0a7a2800);*/ + VSYNC_WR_MPEG_REG_BITS(VD1_HDR2_ADPS_ALPHA1, 0x2800, 0, 16); + set_ootf_lut(VD1_HDR, &hdr_lut_param); + } + return 0; +} diff --git a/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h new file mode 100644 index 0000000..2e807d1 --- a/dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h @@ -0,0 +1,134 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef AM_HDR10_PLUS_OOTF_H +#define AM_HDR10_PLUS_OOTF_H + +#define N 10 +#define PERCENTILE_ORDER 10 +#define NUM_P (N - 1) +#define POINTS 149 +#define OOLUT_NUM 149 +#define PROCESSING_MAX 12 +#define PORCESSING_DATA_MAX ((1 << PROCESSING_MAX) - 1) +#define PROCESSING_MAX_HALF ((1 << (PROCESSING_MAX - 1)) - 1) +#define GAIN_BIT 7 +#define U16 16 +#define U16_MAXI ((1 << U16) - 1) +#define MIN_LUMINANCE 200 + +#define U32 32 +#define _U32_MAX 0xffffffff + +struct EBZCurveParameters { + int order; + int Sx, Sy; + int Anchor[N + 1]; +}; + +struct Percentiles { + int num_percentile; + int percentilePercent[PERCENTILE_ORDER]; + int percentileValue[PERCENTILE_ORDER]; +}; + +struct Scene2094Metadata { + int maxSceneSourceLuminance; + int referenceLuminance; + int minLuminance; + struct Percentiles percentiles; + struct EBZCurveParameters EBZCurveParameters; +}; + +struct hdr10_plus_sei_s { + int targeted_system_display_maximum_luminance; + int maxscl[3][3]; + int average_maxrgb[3]; + int num_distributions[3]; + int distribution_index[3][9]; + int distribution_values[3][9]; + + int tone_mapping_flag[3]; + int knee_point_x[3]; + int knee_point_y[3]; + int num_bezier_curve_anchors[3]; + int bezier_curve_anchors[3][14]; + int color_saturation_mapping_flag[3]; +}; + +#define ORDER 10 +#define NPCOEFF (ORDER - 1) +#define P1MIN (PORCESSING_DATA_MAX / ORDER) +struct BasisOOTF_Params { + /*Knee-Point (KP) parameters*/ + /*KP ramp base thresholds (two bounds KP 1 and KP 2 are computed)*/ + int SY1_V1; + int SY1_V2; + int SY1_T1; + int SY1_T2; + + int SY2_V1; + int SY2_V2; + int SY2_T1; + int SY2_T2; + + /*KP mixing gain (final KP from bounds KP#1*/ + /*and KP#2 as a function of scene percentile)*/ + int KP_G_V1; + int KP_G_V2; + int KP_G_T1; + int KP_G_T2; + + /* P coefficient parameters*/ + /* Thresholds of minimum bound of P1 coefficient*/ + int P1_LIMIT_V1; + int P1_LIMIT_V2; + int P1_LIMIT_T1; + int P1_LIMIT_T2; + + /* Thresholds to compute relative shape of curve (P2~P9 coefficient)*/ + /* by pre-defined bounds - as a function of scene percentile*/ + int P2To9_T1; + int P2To9_T2; + + /* Defined relative shape bounds (P2~P9 coefficient) for*/ + /*a given maximum TM dynamic compression (eg : 20x )*/ + int P2ToP9_MAX1[ORDER - 2]; + int P2ToP9_MAX2[ORDER - 2]; + + /* Ps mixing gain (obtain all Ps coefficients) -*/ + /*as a function of TM dynamic compression ratio*/ + int PS_G_T1; + int PS_G_T2; + + /* Post-processing : Reduce P1/P2 (to enhance mid tone)*/ + /*for high TM dynamic range compression cases*/ + int LOW_SY_T1; + int LOW_SY_T2; + int LOW_K_T1; + int LOW_K_T2; + int RED_P1_V1; + int RED_P1_T1; + int RED_P1_T2; + int RED_P2_V1; + int RED_P2_T1; + int RED_P2_T2; +}; + +extern int hdr10_plus_ootf_gen(void); + +#endif /* AM_HDR10_PLUS_OOTF_H */ diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h index f9cd50c..8c5c39c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h @@ -175,4 +175,9 @@ extern int _VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); extern u32 _VSYNC_RD_MPEG_REG(u32 adr); extern int _VSYNC_WR_MPEG_REG(u32 adr, u32 val); +extern void set_ootf_lut( + enum hdr_module_sel module_sel, + struct hdr_proc_lut_param_s *hdr_lut_param); +extern struct hdr_proc_lut_param_s hdr_lut_param; + #endif diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 8214dcf..82394b2 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -163,55 +163,6 @@ struct vframe_master_display_colour_s { content_light_level; }; /* master_display_colour_info_volume from SEI */ -struct vframe_hdr_plus_sei_s { - u16 present_flag; - u16 itu_t_t35_country_code; - u16 itu_t_t35_terminal_provider_code; - u16 itu_t_t35_terminal_provider_oriented_code; - u16 application_identifier; - u16 application_version; - /*num_windows max is 3*/ - u16 num_windows; - /*windows xy*/ - u16 window_upper_left_corner_x[3]; - u16 window_upper_left_corner_y[3]; - u16 window_lower_right_corner_x[3]; - u16 window_lower_right_corner_y[3]; - u16 center_of_ellipse_x[3]; - u16 center_of_ellipse_y[3]; - u16 rotation_angle[3]; - u16 semimajor_axis_internal_ellipse[3]; - u16 semimajor_axis_external_ellipse[3]; - u16 semiminor_axis_external_ellipse[3]; - u16 overlap_process_option[3]; - /*target luminance*/ - u32 tgt_sys_disp_max_lumi; - u16 tgt_sys_disp_act_pk_lumi_flag; - u16 num_rows_tgt_sys_disp_act_pk_lumi; - u16 num_cols_tgt_sys_disp_act_pk_lumi; - u16 tgt_sys_disp_act_pk_lumi[25][25]; - - /*num_windows max is 3, e.g maxscl[num_windows][i];*/ - u32 maxscl[3][3]; - u32 average_maxrgb[3]; - u16 num_distribution_maxrgb_percentiles[3]; - u16 distribution_maxrgb_percentages[3][15]; - u32 distribution_maxrgb_percentiles[3][15]; - u16 fraction_bright_pixels[3]; - - u16 mast_disp_act_pk_lumi_flag; - u16 num_rows_mast_disp_act_pk_lumi; - u16 num_cols_mast_disp_act_pk_lumi; - u16 mast_disp_act_pk_lumi[25][25]; - /*num_windows max is 3, e.g knee_point_x[num_windows]*/ - u16 tone_mapping_flag[3]; - u16 knee_point_x[3]; - u16 knee_point_y[3]; - u16 num_bezier_curve_anchors[3]; - u16 bezier_curve_anchors[3][15]; - u16 color_saturation_mapping_flag[3]; - u16 color_saturation_weight[3]; -}; /* vframe properties */ struct vframe_prop_s { struct vframe_hist_s hist; |