/* * linux/drivers/video/fbdev/exynos/panel/dimming.h * * Header file for Samsung AID Dimming Driver. * * Copyright (c) 2016 Samsung Electronics * Gwanghui Lee * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #ifndef _DIMMING_H_ #define _DIMMING_H_ //#define DEBUG_DIMMING #define DEBUG_EXCUTION_TIME #define DEBUG_DIMMING_RESULT //#define DEBUG_DIMMING_RESULT_ASCENDING #define MAX_PRINT_BUF_SIZE (512) #define MAX_OFFSET_LIST 4 #ifndef __KERNEL__ #include #include #include #include #define EINVAL (22) #define DIM_ERR "[err] " #define DIM_WARN "[warn] " /* #define DIM_INFO "[info] " */ #define DIM_INFO "" #define DIM_DEBUG "[dbg] " #define pr_err(fmt, ...) printf(DIM_ERR fmt, ##__VA_ARGS__) #define pr_warn(fmt, ...) printf(DIM_WARN fmt, ##__VA_ARGS__) #define pr_info(fmt, ...) printf(DIM_INFO fmt, ##__VA_ARGS__) #ifdef DEBUG_DIMMING #define pr_debug(fmt, ...) printf(DIM_DEBUG fmt, ##__VA_ARGS__) #else #define pr_debug(fmt, ...) do {} while(0) #endif #define unlikely #define __func__ __FUNCTION__ typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; typedef char s8; typedef short s16; typedef int s32; typedef long long s64; typedef int bool; enum { false = 0, true = 1, }; static u64 do_div64(u64 *num, u32 den) { u64 rem = *num % den; *num /= den; return rem; } #define do_div(num, den) (do_div64(&(num), den)) #define GFP_KERNEL (0) #define typeof typeid #define kfree free #define kmalloc(size, flags) malloc((size)) #define kzalloc(size, flags) kmalloc((size), (flags)) #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #else #include #include #include #include #endif /* _LINUX_ */ #define DIMMING_CALC_PRECISE #define BIT_SHIFT (24) #define DIMMING_BITSHIFT (BIT_SHIFT) #define GRAY_SCALE_MAX (256) #define ERROR_DETECT_BOUND (1) #if (BIT_SHIFT != 22) && (BIT_SHIFT != 24) && (BIT_SHIFT != 26) #ifndef __KERNEL__ #define GENERATE_GAMMA_CURVE #include #else #error "Unable to generate gamma curve in KERNEL" #endif /* __KERNEL */ #endif /* BIT_SHIFT CONDITION */ enum tag { TAG_DIM_GLOBAL_INFO_START, TAG_DIM_GLOBAL_INFO_END, TAG_TP_LUT_INFO_START, TAG_TP_LUT_INFO_END, TAG_TP_LUT_START, TAG_TP_LUT_END, TAG_DIM_LUT_INFO_START, TAG_DIM_LUT_INFO_END, TAG_DIM_LUT_START, TAG_DIM_LUT_END, TAG_MTP_OFFSET_START, TAG_MTP_OFFSET_END, TAG_TP_VOLT_START, TAG_TP_VOLT_END, TAG_GRAY_SCALE_VOLT_START, TAG_GRAY_SCALE_VOLT_END, TAG_GAMMA_CENTER_START, TAG_GAMMA_CENTER_END, TAG_MTP_OFFSET_TEST_RANGE_START, TAG_MTP_OFFSET_TEST_RANGE_END, MAX_INPUT_TAG, }; enum { GLOBAL_DIM_INFO_NR_TP, GLOBAL_DIM_INFO_NR_LUMINANCE, GLOBAL_DIM_INFO_VREGOUT, GLOBAL_DIM_INFO_VREF, GLOBAL_DIM_INFO_GAMMA, GLOBAL_DIM_INFO_VT_VOLTAGE, }; enum { TP_LUT_NONE, TP_LUT_LEVEL, TP_LUT_NAME, TP_LUT_VOLT_SRC, TP_LUT_GAMMA_CENTER, TP_LUT_GAMMA_CALC, MAX_TP_LUT_FIELD, }; enum { DIM_LUT_NONE, DIM_LUT_LUMINANCE, DIM_LUT_AOR, DIM_LUT_BASE_LUMINANCE, DIM_LUT_GAMMA, DIM_LUT_GRAY_SCALE_OFFSET, DIM_LUT_COLOR_SHIFT_OFFSET, MAX_DIM_LUT_FIELD, }; enum { R_OFFSET, G_OFFSET, B_OFFSET, RGB_MAX_OFFSET, }; enum color { RED, GREEN, BLUE, MAX_COLOR, }; enum rgbw_color { RGBW_RED, RGBW_GREEN, RGBW_BLUE, RGBW_WHITE, MAX_RGBW_COLOR, }; enum gamma_degree { GAMMA_NONE = 0, GAMMA_MIN, GAMMA_1_60 = GAMMA_MIN, GAMMA_1_65, GAMMA_1_70, GAMMA_1_75, GAMMA_1_80, GAMMA_1_85, GAMMA_1_90, GAMMA_1_95, GAMMA_2_00, GAMMA_2_05, GAMMA_2_10, GAMMA_2_12, GAMMA_2_13, GAMMA_2_15, GAMMA_2_20, GAMMA_2_25, GAMMA_MAX, }; enum { VREG_OUT, V0_OUT, VT_OUT, MAX_VOLT_SRC, }; extern const char *tag_name[]; extern const char *global_dim_info_name[]; extern const char *dim_lut_field_name[]; extern const char *color_name[]; extern const char *volt_src_name[]; struct gamma_curve { int gamma; int *gamma_curve_table; }; typedef s32(*s32_TP_COLORs)[MAX_COLOR]; typedef s64(*s64_TP_COLORs)[MAX_COLOR]; typedef u32(*u32_TP_COLORs)[MAX_COLOR]; typedef u64(*u64_TP_COLORs)[MAX_COLOR]; typedef s32(*s32_TPs); typedef s64(*s64_TPs); typedef u32(*u32_TPs); typedef u64(*u64_TPs); struct _range { int from, to, step; }; #ifdef DEBUG_EXCUTION_TIME #ifdef __KERNEL__ typedef long long mytime_t; #define gettime(t) ((t) = jiffies) #define difftime(t1, t2) ((jiffies_to_msecs((t2) - (t1))) * 1000) #else #ifdef _WIN32 typedef long long mytime_t; #define gettime(t) ((t) = clock()) #define difftime(t1, t2) (((t2) - (t1)) * 1000000 / CLOCKS_PER_SEC) #else typedef struct timespec mytime_t; #define gettime(t) (clock_gettime(CLOCK_MONOTONIC, &(t))) #define BILLION 1000000000L #define difftime(t1, t2) ((BILLION * ((t2).tv_sec - (t1).tv_sec) + (t2).tv_nsec - (t1).tv_nsec) / 1000) #endif #endif /* __KERNEL__ */ #endif /* DEBUG_EXCUTION_TIME */ #define in_range(i, r) \ ((r).from <= (r).to) ? \ ((r).from <= (i) && (i) < (r).to) : \ ((r).from >= (i) && (i) > (r).to) #define for_each_range(i, r) \ for ((i) = (r).from; \ (i) != (r).to && in_range(i, r); \ (i) += (r).step) #define for_each_tp(__pos__) \ for ((__pos__) = 0; \ (__pos__) < (NR_TP); \ (__pos__)++) #define for_each_color(__pos__) \ for ((__pos__) = 0; \ (__pos__) < (MAX_COLOR);\ (__pos__)++) #define for_each_tp_color(v, c) \ for_each_tp(v) \ for_each_color(c) #define for_each_tp_order(__pos__, idx, order) \ for ((idx) = 0, (__pos__) = (order)[(idx)]; \ (idx) < (NR_TP); \ (__pos__) = (order)[++(idx)]) /* DIM_LUT_V0 : INSERT BASE_LUMINANCE DIRECTLY */ #define DIM_LUT_V0_INIT(l, bl, gma, rtbl, ctbl) \ { \ .luminance = (l), \ .base_luminance = (bl), \ .base_gray = (0), \ .g_curve_degree = (gma), \ .gray_scale_offset = (rtbl), \ .rgb_color_offset = (s32 (*)[MAX_COLOR])(ctbl), \ } /* DIM_LUT_V1 : INSERT BASE_GRAY and Calculate BASE_LUMINANCE */ #define DIM_LUT_V1_INIT(l, bg, gma, rtbl, ctbl) \ { \ .luminance = (l), \ .base_luminance = (0), \ .base_gray = (bg), \ .g_curve_degree = (gma), \ .gray_scale_offset = (rtbl), \ .rgb_color_offset = (s32 (*)[MAX_COLOR])(ctbl), \ } #define DIM_LUT_INIT(l, bl, gma, rtbl, ctbl) \ DIM_LUT_V0_INIT(l, bl, gma, rtbl, ctbl) /* GM2LUT_V0 : INSERT COLOR OFFSET */ #define GM2_LUT_V0_INIT(ctbl) \ { \ .rgb_color_offset = (s32 (*)[MAX_COLOR])(ctbl), \ } #define GM2_LUT_V0_INIT_SRC(ctbl, gamma_index) \ { \ .rgb_color_offset = (s32 (*)[MAX_COLOR])(ctbl), \ .source_gamma = (gamma_index), \ } #define GM2_LUT_V0_SRC(gamma_index) \ { \ .source_gamma = (gamma_index), \ } #define GM2_LUT_V1_INIT_SRC(ctbl, gamma_index) \ { \ .rgb_color_offset = (s32 (*)[MAX_COLOR])(ctbl), \ .source_gamma = (gamma_index), \ } #define GM2_LUT_V1(...) \ { \ .nr_offset_list = M_NARGS(__VA_ARGS__), \ .offset_list = { \ [0] = M_GET_ELEM_1(__VA_ARGS__), \ [1] = M_GET_ELEM_2(__VA_ARGS__), \ [2] = M_GET_ELEM_3(__VA_ARGS__), \ } \ } struct dimming_lut_info { int nrow; int ncol; int fields[20]; struct _range gray_scale_offset_range; struct _range rgb_color_offset_range; }; struct dimming_tp_output { u64 L; u32 M_GRAY; s64 vout[MAX_COLOR]; s32 center[MAX_COLOR]; s32 center_debug[MAX_COLOR]; }; struct dimming_lut { /* input data from user setting */ u32 luminance; u32 aor; u32 base_luminance; u32 base_gray; enum gamma_degree g_curve_degree; s32 *gray_scale_offset; s32(*rgb_color_offset)[MAX_COLOR]; /* output(reversed distortion) data will be stored */ struct dimming_tp_output *tpout; struct dimming_tp_output *tpout_debug; }; struct gray_scale { u64 gamma_value; s64 vout[MAX_COLOR]; }; struct tp_lut_info { int nrow; int ncol; int fields[20]; }; struct tp { int level; /* gray_level of each tp */ int volt_src; /* voltage source of each tp*/ char name[10]; /* name of each tp */ s32 center[MAX_COLOR]; /* center gamma's fixed value of tp */ s32 offset[MAX_COLOR]; /* mtp offset value of tp */ s64 vout[MAX_COLOR]; /* voltage output of tp */ u32 denominator; /* denominator of tp */ u32 numerator; /* numerator of tp */ u32 bits; /* available bit of tp */ struct _range range; /* tp input range for Test Case Generation */ }; struct dimming_info { s64 vregout; /* vregout * (1 << bitshift) */ s64 vref; /* vref * (1 << bitshift) */ u32 vt_voltage[16]; /* vt voltage table */ u32 v0_voltage[16]; /* v0 voltage table */ struct tp_lut_info tp_lut_info; int nr_tp; /* number of turning point */ struct tp *tp; /* information of panel's tuning point */ int nr_luminance; /* number of luminance */ struct gray_scale gray_scale_lut[GRAY_SCALE_MAX]; struct dimming_lut_info dim_lut_info; struct dimming_lut *dim_lut; int target_luminance; enum gamma_degree target_g_curve_degree; s32 hbm_luminance; s32 (*hbm_gamma_tbl)[MAX_COLOR]; }; struct dimming_init_info { const char *name; int nr_tp; /* number of turning point */ struct tp *tp; /* information of panel's tuning point */ int nr_luminance; /* number of luminance */ s64 vregout; /* vregout * (1 << bitshift) */ s64 vref; /* vref * (1 << bitshift) */ int bitshift; /* bitshift for precise calculation */ u32 vt_voltage[16]; /* vt voltage table */ u32 v0_voltage[16]; /* v0 voltage table */ int target_luminance; /* target luminance */ int target_gamma; /* target gamma value */ struct dimming_lut *dim_lut; s32 hbm_luminance; }; /* gamma mode 2 */ struct dimming_color_offset { s32(*rgb_color_offset)[MAX_COLOR]; void *source_gamma; }; struct gm2_dimming_lut { s32(*rgb_color_offset)[MAX_COLOR]; void *source_gamma; }; struct gm2_dimming_lut_v1 { struct dimming_color_offset offset_list[MAX_OFFSET_LIST]; int nr_offset_list; int affected_addr; }; struct gm2_dimming_init_info { const char *name; int nr_tp; /* number of turning point */ struct tp *tp; /* information of panel's tuning point */ struct gm2_dimming_lut *dim_lut; int nr_dim_lut; struct gm2_dimming_lut_v1 *dim_lut_v1; int nr_dim_lut_v1; // struct gm2_dimming_lut *def_gamma; // int nr_def_gamma; int *brt_range; int sz_brt_range; }; #ifdef CONFIG_PANEL_AID_DIMMING int init_dimming_info(struct dimming_info *, struct dimming_init_info *); int init_dimming_mtp(struct dimming_info *, s32 (*)[MAX_COLOR]); int init_dimming_hbm_info(struct dimming_info *, s32 (*)[MAX_COLOR], u32); s64 interpolation_round(s64 from, s64 to, int cur_step, int total_step); s64 disp_interpolation64(s64 from, s64 to, int cur_step, int total_step); s64 disp_round(s64 num, u32 digits); s64 disp_div64(s64 num, s64 den); s64 disp_pow(s64 num, u32 digits); #ifdef DIMMING_CALC_PRECISE s64 disp_div64_round(s64 num, s64 den, u32 digits); #endif static inline s64 disp_pow_round(s64 num, u32 digits) { if (digits < 1) return 0; return disp_div64(num + 5 * disp_pow(10, digits - 1), disp_pow(10, digits)) * disp_pow(10, digits); } int process_dimming(struct dimming_info *); int gamma_table_add_offset(s32 (*src)[MAX_COLOR], s32 (*ofs)[MAX_COLOR], s32 (*out)[MAX_COLOR], struct tp *tp, int nr_tp); int gamma_table_interpolation(s32 (*from)[MAX_COLOR], s32 (*to)[MAX_COLOR], s32 (*out)[MAX_COLOR], int nr_tp, int cur_step, int total_step); int gamma_table_interpolation_round(s32 (*from)[MAX_COLOR], s32 (*to)[MAX_COLOR], s32 (*out)[MAX_COLOR], int nr_tp, int cur_step, int total_step); void get_dimming_gamma(struct dimming_info *dim_info, u32 luminance, u8 *output, void (*copy)(u8 *output, u32 value, u32 index, u32 color)); /* for debug */ void print_dimming_info(struct dimming_info *dim_info, int tag); #else static inline int init_dimming_info(struct dimming_info *dim_info, struct dimming_init_info *src) { return 0; } static inline int init_dimming_mtp(struct dimming_info *dim_info, s32 (*mtp)[MAX_COLOR]) { return 0; } static inline int init_dimming_hbm_info(struct dimming_info *dim_info, s32 (*hbm_gamma_tbl)[MAX_COLOR], u32 hbm_luminance) { return 0; } static inline s64 interpolation_round(s64 from, s64 to, int cur_step, int total_step) { return 0; } static inline s64 disp_interpolation64(s64 from, s64 to, int cur_step, int total_step) { return 0; } static inline s64 disp_round(s64 num, u32 digits) { return 0; } static inline s64 disp_div64(s64 num, s64 den) { return 0; } #ifdef DIMMING_CALC_PRECISE static inline s64 disp_div64_round(s64 num, s64 den, u32 digits) { return 0; } #endif static inline int process_dimming(struct dimming_info *dim_info) { return 0; } static inline int gamma_table_interpolation(s32 (*from)[MAX_COLOR], s32 (*to)[MAX_COLOR], s32 (*out)[MAX_COLOR], int nr_tp, int cur_step, int total_step) { return 0; } int gamma_table_interpolation_round(s32 (*from)[MAX_COLOR], s32 (*to)[MAX_COLOR], s32 (*out)[MAX_COLOR], int nr_tp, int cur_step, int total_step) { return 0; } void get_dimming_gamma(struct dimming_info *dim_info, u32 luminance, u8 *output, void (*copy)(u8 *output, u32 value, u32 index, u32 color)) {} /* for debug */ static inline void print_dimming_info(struct dimming_info *dim_info, int tag) {} #endif /* CONFIG_PANEL_AID_DIMMING */ #endif /* _DIMMING_H_ */