kernel_samsung_a53x/drivers/gpu/drm/samsung/panel/dimming.h
2024-06-15 16:02:09 -03:00

515 lines
13 KiB
C
Executable file

/*
* linux/drivers/video/fbdev/exynos/panel/dimming.h
*
* Header file for Samsung AID Dimming Driver.
*
* Copyright (c) 2016 Samsung Electronics
* Gwanghui Lee <gwanghui.lee@samsung.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#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 <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#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 <math.h>
#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_ */