From 0a39876093d53e7c2fa216f62a4051fdbd8ae70b Mon Sep 17 00:00:00 2001 From: ChiHun Won Date: Mon, 29 Apr 2019 15:07:17 +0900 Subject: [PATCH] [NEUS7920-164] fbdev: dpu20: udpated dqe for supporting aps Change-Id: Id8c91fc1fe51337aa96fe507751050756de77b40 Signed-off-by: ChiHun Won --- .../fbdev/exynos/dpu20/cal_9610/dqe_reg.c | 33 + .../fbdev/exynos/dpu20/cal_9610/regs-dqe.h | 69 +- drivers/video/fbdev/exynos/dpu20/dqe.h | 59 +- drivers/video/fbdev/exynos/dpu20/dqe_drv.c | 677 +++++++++++++++--- 4 files changed, 709 insertions(+), 129 deletions(-) diff --git a/drivers/video/fbdev/exynos/dpu20/cal_9610/dqe_reg.c b/drivers/video/fbdev/exynos/dpu20/cal_9610/dqe_reg.c index e73c40163939..55110f1080e0 100644 --- a/drivers/video/fbdev/exynos/dpu20/cal_9610/dqe_reg.c +++ b/drivers/video/fbdev/exynos/dpu20/cal_9610/dqe_reg.c @@ -102,6 +102,39 @@ u32 dqe_reg_get_hsc_full_pxl_num(void) return dqe_read_mask(DQEHSC_FULL_PXL_NUM, DQEHSC_FULL_PXL_NUM_MASK); } +void dqe_reg_set_aps_on(u32 on) +{ + dqe_write_mask(DQECON, on ? ~0 : 0, DQE_APS_ON_MASK); +} + +u32 dqe_reg_get_aps_on(void) +{ + return dqe_read_mask(DQECON, DQE_APS_ON_MASK); +} + +void dqe_reg_set_aps_full_pxl_num(struct decon_lcd *lcd_info) +{ + u32 val, mask; + + val = (u32)(lcd_info->xres * lcd_info->yres); + mask = DQEAPS_FULL_PXL_NUM_MASK; + dqe_write_mask(DQEAPS_FULL_PXL_NUM, val, mask); +} + +u32 dqe_reg_get_aps_full_pxl_num(void) +{ + return dqe_read_mask(DQEAPS_FULL_PXL_NUM, DQEAPS_FULL_PXL_NUM_MASK); +} + +void dqe_reg_set_aps_img_size(struct decon_lcd *lcd_info) +{ + u32 val, mask; + + val = DQEAPS_FULL_IMG_VSIZE_F(lcd_info->yres) | DQEAPS_FULL_IMG_HSIZE_F(lcd_info->xres); + mask = DQEAPS_FULL_IMG_VSIZE_MASK | DQEAPS_FULL_IMG_HSIZE_MASK; + dqe_write_mask(DQEAPS_FULL_IMG_SIZESET, val, mask); +} + void dqe_reg_set_img_size(u32 id, struct decon_lcd *lcd_info) { u32 width, val, mask; diff --git a/drivers/video/fbdev/exynos/dpu20/cal_9610/regs-dqe.h b/drivers/video/fbdev/exynos/dpu20/cal_9610/regs-dqe.h index 93fdf62f8b1c..bdacc10429f9 100644 --- a/drivers/video/fbdev/exynos/dpu20/cal_9610/regs-dqe.h +++ b/drivers/video/fbdev/exynos/dpu20/cal_9610/regs-dqe.h @@ -8,7 +8,8 @@ #define DQE_APS_SW_RESET_GET(_v) (((_v) >> 18) & 0x1) #define DQE_HSC_SW_RESET_MASK (1 << 16) #define DQE_HSC_SW_RESET_GET(_v) (((_v) >> 16) & 0x1) - +#define DQE_APS_ON_MASK (1 << 4) +#define DQE_APS_ON_GET(_v) (((_v) >> 4) & 0x1) #define DQE_HSC_ON_MASK (1 << 3) #define DQE_HSC_ON_GET(_v) (((_v) >> 3) & 0x1) #define DQE_GAMMA_ON_MASK (1 << 2) @@ -173,6 +174,64 @@ #define DQEGAMMALUT_B_63_62 0x01b8 #define DQEGAMMALUT_B_64 0x01bc +/*APS_SET*/ +#define DQEAPSLUT_MAX (15) +#define DQEAPSLUT_BASE 0x01C0 + +#define DQEAPSLUT_ST(_v) (((_v) & 0xff) << 16) +#define DQEAPSLUT_NS(_v) (((_v) & 0xff) << 8) +#define DQEAPSLUT_LT(_v) (((_v) & 0xff) << 0) +#define DQEAPSLUT_PL_W2(_v) (((_v) & 0xf) << 16) +#define DQEAPSLUT_PL_W1(_v) (((_v) & 0xf) << 0) +#define DQEAPSLUT_CTMODE(_v) (((_v) & 0x3) << 0) +#define DQEAPSLUT_PP_EN(_v) (((_v) & 0x1) << 0) +#define DQEAPSLUT_TDR_MAX(_v) (((_v) & 0x3ff) << 16) +#define DQEAPSLUT_TDR_MIN(_v) (((_v) & 0x3ff) << 0) +#define DQEAPSLUT_AMBIENT_LIGHT(_v) (((_v) & 0xff) << 0) +#define DQEAPSLUT_BACK_LIGHT(_v) (((_v) & 0xff) << 0) +#define DQEAPSLUT_DSTEP(_v) (((_v) & 0x3f) << 0) +#define DQEAPSLUT_SCALE_MODE(_v) (((_v) & 0x3) << 0) +#define DQEAPSLUT_THRESHOLD_3(_v) (((_v) & 0x3) << 4) +#define DQEAPSLUT_THRESHOLD_2(_v) (((_v) & 0x3) << 2) +#define DQEAPSLUT_THRESHOLD_1(_v) (((_v) & 0x3) << 0) +#define DQEAPSLUT_GAIN_LIMIT(_v) (((_v) & 0x3ff) << 0) +#define DQEAPSLUT_ROI_SAME(_v) (((_v) & 0x1) << 2) +#define DQEAPSLUT_UPDATE_METHOD(_v) (((_v) & 0x1) << 1) +#define DQEAPSLUT_PARTIAL_FRAME(_v) (((_v) & 0x1) << 0) +#define DQEAPSLUT_ROI_Y1(_v) (((_v) & 0x1fff) << 16) +#define DQEAPSLUT_ROI_X1(_v) (((_v) & 0x1fff) << 0) +#define DQEAPSLUT_IBSI_01(_v) (((_v) & 0xffff) << 16) +#define DQEAPSLUT_IBSI_00(_v) (((_v) & 0xffff) << 0) +#define DQEAPSLUT_IBSI_11(_v) (((_v) & 0xffff) << 16) +#define DQEAPSLUT_IBSI_10(_v) (((_v) & 0xffff) << 0) + +#define DQEAPS_GAIN 0x01C0 +#define DQEAPS_WEIGHT 0x01C4 +#define DQEAPS_CTMODE 0x01C8 +#define DQEAPS_PPEN 0x01CC +#define DQEAPS_TDRMINMAX 0x01D0 +#define DQEAPS_AMBIENT_LIGHT 0x01D4 +#define DQEAPS_BACK_LIGHT 0x01D8 +#define DQEAPS_DSTEP 0x01DC +#define DQEAPS_SCALE_MODE 0x01E0 +#define DQEAPS_THRESHOLD 0x01E4 +#define DQEAPS_GAIN_LIMIT 0x01E8 +#define DQEAPS_DIMMING_DONE_INTR 0x01EC + +#define DQEAPS_PARTIAL_CON 0x0234 + +#define DQEAPS_FULL_IMG_SIZESET 0x0238 +#define DQEAPS_FULL_IMG_VSIZE_F(_v) ((_v) << 16) +#define DQEAPS_FULL_IMG_VSIZE_MASK (0x1fff << 16) +#define DQEAPS_FULL_IMG_VSIZE_GET(_v) (((_v) >> 16) & 0x1fff) +#define DQEAPS_FULL_IMG_HSIZE_F(_v) ((_v) << 0) +#define DQEAPS_FULL_IMG_HSIZE_MASK (0x1fff << 0) +#define DQEAPS_FULL_IMG_HSIZE_GET(_v) (((_v) >> 0) & 0x1fff) + +#define DQEAPS_PARTIAL_ROI_UP_LEFT_POS 0x023C +#define DQEAPS_PARTIAL_IBSI_01_00 0x0308 +#define DQEAPS_PARTIAL_IBSI_11_10 0x030C + /*HSC_SET */ #define DQEHSCLUT_MAX (11) #define DQEHSCLUT_BASE 0x0208 @@ -211,11 +270,11 @@ #define DQEHSCLUT_POLY_CURVE8(_v) (((_v) & 0x3ff) << 10) #define DQEHSCLUT_POLY_CURVE7(_v) (((_v) & 0x3ff) << 0) -#define DQEHSCLUT_SKIN_S2(_v) (((_v) & 0x1ff) << 16) +#define DQEHSCLUT_SKIN_S2(_v) (((_v) & 0x3ff) << 16) #define DQEHSCLUT_SKIN_S1(_v) (((_v) & 0x3ff) << 0) #define DQEHSCLUT_SKIN_H2(_v) (((_v) & 0x1ff) << 16) -#define DQEHSCLUT_SKIN_H1(_v) (((_v) & 0x3ff) << 0) +#define DQEHSCLUT_SKIN_H1(_v) (((_v) & 0x1ff) << 0) #define DQEHSCLUT_YCOMP_RATIO(_v) (((_v) & 0xf) << 12) #define DQEHSCLUT_TSC_GAIN(_v) (((_v) & 0x3ff) << 0) @@ -258,6 +317,10 @@ #define DQEHSC_FULL_PXL_NUM_MASK (0x03ffffff << 0) #define DQEHSC_FULL_PXL_NUM_GET(_v) (((_v) >> 0) & 0x03ffffff) +#define DQEAPS_FULL_PXL_NUM 0x0320 +#define DQEAPS_FULL_PXL_NUM_MASK (0x03ffffff << 0) +#define DQEAPS_FULL_PXL_NUM_GET(_v) (((_v) >> 0) & 0x03ffffff) + #define SHADOW_DQE_OFFSET 0x9000 #endif diff --git a/drivers/video/fbdev/exynos/dpu20/dqe.h b/drivers/video/fbdev/exynos/dpu20/dqe.h index ca5123c01d0d..f54aa31e8479 100644 --- a/drivers/video/fbdev/exynos/dpu20/dqe.h +++ b/drivers/video/fbdev/exynos/dpu20/dqe.h @@ -73,6 +73,13 @@ static inline void dqe_write_mask(u32 reg_id, u32 val, u32 mask) writel(val, decon->res.regs + DQE_BASE + reg_id); } +static inline bool IS_DQE_OFF_STATE(struct decon_device *decon) +{ + return decon == NULL || + decon->state == DECON_STATE_OFF || + decon->state == DECON_STATE_INIT; +} + struct dqe_reg_dump { u32 addr; u32 val; @@ -82,10 +89,13 @@ struct dqe_ctx { struct dqe_reg_dump cgc[DQECGC1LUT_MAX + DQECGC2LUT_MAX]; struct dqe_reg_dump gamma[DQEGAMMALUT_MAX]; struct dqe_reg_dump hsc[DQEHSCLUT_MAX]; + struct dqe_reg_dump aps[DQEAPSLUT_MAX]; u32 cgc_on; u32 gamma_on; u32 hsc_on; u32 hsc_control; + u32 aps_on; + u32 aps_lux; bool need_udpate; u32 color_mode; u32 night_light_on; @@ -102,13 +112,9 @@ struct dqe_device { extern int dqe_log_level; /* CAL APIs list */ -void dqe_reg_module_on_off(bool en_she, bool en_cgc, bool en_gamma, - bool en_hsc, bool en_aps); -void dqe_reg_module_reset(bool en_hsc, bool en_aps, bool en_rst); void dqe_reg_start(u32 id, struct decon_lcd *lcd_info); void dqe_reg_stop(u32 id); -void dqe_reg_set_she_on(u32 on); void dqe_reg_set_cgc_on(u32 on); u32 dqe_reg_get_cgc_on(void); void dqe_reg_set_gamma_on(u32 on); @@ -124,36 +130,13 @@ u32 dqe_reg_get_hsc_control(void); void dqe_reg_set_hsc_full_pxl_num(struct decon_lcd *lcd_info); u32 dqe_reg_get_hsc_full_pxl_num(void); void dqe_reg_set_aps_on(u32 on); -void dqe_reg_reset(u32 en); -void dqe_reg_set_gammagray_on(u32 on); -void dqe_reg_lpd_mode_exit(u32 en); - -void dqe_reg_module_on_off(bool en_she, bool en_cgc, bool en_gamma, - bool en_hsc, bool en_aps); -void dqe_reg_module_reset(bool en_hsc, bool en_aps, bool en_rst); - -void dqe_reg_set_img_size0(u32 width, u32 height); -void dqe_reg_set_img_size1(u32 width, u32 height); -void dqe_reg_set_img_size2(u32 width, u32 height); - -/* DQE_HSC register set */ -void dqe_reg_set_hsc_ppsc_on(u32 en); -void dqe_reg_set_hsc_ycomp_on(u32 en); -void dqe_reg_set_hsc_tsc_on(u32 en); -void dqe_reg_set_hsc_dither_on(u32 en); -void dqe_reg_set_hsc_pphc_on(u32 en); -void dqe_reg_set_hsc_skin_on(u32 en); -void dqe_reg_set_hsc_ppscgain_rgb(u32 r, u32 g, u32 b); -void dqe_reg_set_hsc_ppsc_gain_cmy(u32 c, u32 m, u32 y); -void dqe_reg_set_hsc_alphascale_shift(u32 alpha_shift1, u32 alpha_shift2, - u32 alpha_scale); -void dqe_reg_set_hsc_poly_curve0(u32 curve1, u32 curve2, u32 curve3, u32 curve4); -void dqe_reg_set_hsc_poly_curve1(u32 curve5, u32 curve6, u32 curve7, u32 curve8); -void dqe_reg_set_hsc_skin(u32 skin_h1, u32 skin_h2, u32 skin_s1, u32 skin_s2); -void dqe_reg_set_hsc_pphcgain_rgb(u32 r, u32 g, u32 b); -void dqe_reg_set_hsc_pphcgain_cmy(u32 c, u32 m, u32 y); -void dqe_reg_set_hsc_tsc_ycomp(u32 ratio, u32 gain); +u32 dqe_reg_get_aps_on(void); +void dqe_reg_set_aps_full_pxl_num(struct decon_lcd *lcd_info); +u32 dqe_reg_get_aps_full_pxl_num(void); +void dqe_reg_set_aps_img_size(struct decon_lcd *lcd_info); +int dqe_save_context(void); +int dqe_restore_context(void); void decon_dqe_sw_reset(struct decon_device *decon); void decon_dqe_enable(struct decon_device *decon); void decon_dqe_disable(struct decon_device *decon); @@ -162,4 +145,14 @@ int decon_dqe_create_interface(struct decon_device *decon); int decon_dqe_set_color_mode(struct decon_color_mode_with_render_intent_info *color_mode); int decon_dqe_set_color_transform(struct decon_color_transform_info *transform); +/* APS GAMMA */ +#define APS_GAMMA_BIT_LENGTH (8) +#define APS_GAMMA_BIT (8) +#define APS_GAMMA_PHASE_SHIFT (APS_GAMMA_BIT - 6) +#define APS_GAMMA_INPUT_MASK (0x3f << APS_GAMMA_PHASE_SHIFT) +#define APS_GAMMA_PHASE_MASK ((1 << APS_GAMMA_PHASE_SHIFT)-1) +#define APS_GAMMA_PIXEL_MAX ((1 << APS_GAMMA_BIT)-1) +#define APS_GAMMA_INTP_LIMIT (0x7 << APS_GAMMA_BIT) +#define APS_GAMMA_DEFAULT_VALUE_ALIGN (APS_GAMMA_BIT-8) + #endif diff --git a/drivers/video/fbdev/exynos/dpu20/dqe_drv.c b/drivers/video/fbdev/exynos/dpu20/dqe_drv.c index c430aa9c9404..168168f1ed43 100644 --- a/drivers/video/fbdev/exynos/dpu20/dqe_drv.c +++ b/drivers/video/fbdev/exynos/dpu20/dqe_drv.c @@ -29,6 +29,7 @@ struct class *dqe_class; u32 gamma_lut[3][65]; u32 cgc_lut[50]; u32 hsc_lut[35]; +u32 aps_lut[26]; #define TUNE_MODE_SIZE 4 u32 tune_mode[TUNE_MODE_SIZE][280]; @@ -50,14 +51,57 @@ const s32 bypass_hsc_tune[35] = { 0,0,0,0,0,0,0,1,15,1,0,1,0,0,0,0,0,0,0,5,-10,0,10,30,170,230,240,155,70,32,1,10,64,51,204 }; +int aps_gmarr_LUT64[3][65] = { + /*set slope = 1*/ + { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, + 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, + 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, + 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, + 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, + 240, 244, 248, 252, 256, + }, + /*set slope = 2.2*/ + { + 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, + 4, 5, 6, 7, 9, 10, 12, 13, 15, 17, + 19, 22, 24, 26, 29, 32, 35, 38, 41, 44, + 48, 51, 55, 59, 63, 67, 72, 76, 81, 86, + 91, 96, 101, 106, 112, 117, 123, 129, 135, 142, + 148, 155, 162, 169, 176, 183, 190, 198, 206, 214, + 222, 230, 238, 247, 256, + }, + /*set slope = 1/2.2*/ + { + 0, 38, 52, 63, 72, 80, 87, 93, 99, 104, + 110, 114, 119, 124, 128, 132, 136, 140, 143, 147, + 150, 154, 157, 160, 163, 166, 169, 172, 175, 178, + 181, 184, 186, 189, 192, 194, 197, 199, 201, 204, + 206, 209, 211, 213, 215, 218, 220, 222, 224, 226, + 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, + 248, 250, 252, 254, 256, + }, +}; + +int aps_gm_LUT64[65] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, + 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, + 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, + 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, + 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, + 240, 244, 248, 252, 256, +}; + static void dqe_dump(void) { int acquired = console_trylock(); struct decon_device *decon = get_decon_drvdata(0); - if (IS_DECON_OFF_STATE(decon)) { - decon_info("%s: DECON%d is disabled, state(%d)\n", - __func__, decon->id, decon->state); + if (IS_DQE_OFF_STATE(decon)) { + decon_info("%s: DECON is disabled, state(%d)\n", + __func__, (decon) ? (decon->state) : -1); return; } @@ -102,6 +146,19 @@ static void dqe_load_context(void) dqe->ctx.hsc[DQEHSCLUT_MAX - 1].addr = DQEHSC_SKIN_H; dqe->ctx.hsc[DQEHSCLUT_MAX - 1].val = dqe_read(dqe->ctx.hsc[DQEHSCLUT_MAX - 1].addr); + for (i = 0; i < DQEAPSLUT_MAX - 4; i++) { + dqe->ctx.aps[i].addr = DQEAPSLUT_BASE + (i * 4); + dqe->ctx.aps[i].val = dqe_read(dqe->ctx.aps[i].addr); + } + dqe->ctx.aps[DQEAPSLUT_MAX - 4].addr = DQEAPS_PARTIAL_CON; + dqe->ctx.aps[DQEAPSLUT_MAX - 4].val = dqe_read(dqe->ctx.aps[DQEAPSLUT_MAX - 4].addr); + dqe->ctx.aps[DQEAPSLUT_MAX - 3].addr = DQEAPS_PARTIAL_ROI_UP_LEFT_POS; + dqe->ctx.aps[DQEAPSLUT_MAX - 3].val = dqe_read(dqe->ctx.aps[DQEAPSLUT_MAX - 3].addr); + dqe->ctx.aps[DQEAPSLUT_MAX - 2].addr = DQEAPS_PARTIAL_IBSI_01_00; + dqe->ctx.aps[DQEAPSLUT_MAX - 2].val = dqe_read(dqe->ctx.aps[DQEAPSLUT_MAX - 2].addr); + dqe->ctx.aps[DQEAPSLUT_MAX - 1].addr = DQEAPS_PARTIAL_IBSI_11_10; + dqe->ctx.aps[DQEAPSLUT_MAX - 1].val = dqe_read(dqe->ctx.aps[DQEAPSLUT_MAX - 1].addr); + for (i = 0; i < DQECGC1LUT_MAX; i++) { dqe_dbg("0x%04x %d %d %d", dqe->ctx.cgc[i].addr, @@ -132,6 +189,11 @@ static void dqe_load_context(void) dqe_dbg("0x%04x %08x ", dqe->ctx.hsc[i].addr, dqe->ctx.hsc[i].val); } + + for (i = 0; i < DQEAPSLUT_MAX; i++) { + dqe_dbg("0x%04x %08x ", + dqe->ctx.aps[i].addr, dqe->ctx.aps[i].val); + } } static void dqe_init_context(void) @@ -181,10 +243,27 @@ static void dqe_init_context(void) dqe->ctx.hsc[9].val = 0x00008046; /* DQEHSC_POLY_CURVE2 */ dqe->ctx.hsc[10].val = 0x0040000a; /* DQEHSC_SKIN_H */ + dqe->ctx.aps[0].val = 0x00808080; /* DQEAPS_GAIN */ + dqe->ctx.aps[1].val = 0x000e000a; /* DQEAPS_WEIGHT */ + dqe->ctx.aps[2].val = 0x00000001; /* DQEAPS_CTMODE */ + dqe->ctx.aps[3].val = 0x00000001; /* DQEAPS_PPEN */ + dqe->ctx.aps[4].val = 0x00ff0040; /* DQEAPS_TDRMINMAX */ + dqe->ctx.aps[5].val = 0x0000008c; /* DQEAPS_AMBIENT_LIGHT */ + dqe->ctx.aps[6].val = 0x000000ff; /* DQEAPS_BACK_LIGHT */ + dqe->ctx.aps[7].val = 0x00000001; /* DQEAPS_DSTEP */ + dqe->ctx.aps[8].val = 0x00000001; /* DQEAPS_SCALE_MODE*/ + dqe->ctx.aps[9].val = 0x00000015; /* DQEAPS_THRESHOLD */ + dqe->ctx.aps[10].val = 0x0000007f; /* DQEAPS_GAIN_LIMIT */ + dqe->ctx.aps[11].val = 0x00000000; /* DQEAPS_PARTIAL_CON */ + dqe->ctx.aps[12].val = 0x00000000; /* DQEAPS_PARTIAL_ROI_UP_LEFT_POS */ + dqe->ctx.aps[13].val = 0x00000000; /* DQEAPS_PARTIAL_IBSI_01_00 */ + dqe->ctx.aps[14].val = 0x00000000; /* DQEAPS_PARTIAL_IBSI_11_10 */ + dqe->ctx.cgc_on = 0; dqe->ctx.gamma_on = 0; dqe->ctx.hsc_on = 0; dqe->ctx.hsc_control = 0; + dqe->ctx.aps_on = 0; dqe->ctx.need_udpate = true; @@ -207,7 +286,7 @@ static void dqe_init_context(void) tune_mode[i][k] = tune_mode[i-1][k]; } -static int dqe_save_context(void) +int dqe_save_context(void) { int i; struct dqe_device *dqe = dqe_drvdata; @@ -236,10 +315,12 @@ static int dqe_save_context(void) dqe->ctx.hsc_on = dqe_reg_get_hsc_on(); dqe->ctx.hsc_control = dqe_reg_get_hsc_control(); + dqe->ctx.aps_on = dqe_reg_get_aps_on(); + return 0; } -static int dqe_restore_context(void) +int dqe_restore_context(void) { int i; struct dqe_device *dqe = dqe_drvdata; @@ -276,6 +357,23 @@ static int dqe_restore_context(void) dqe_reg_set_hsc_control(dqe->ctx.hsc_control); } + for (i = 0; i < DQEAPSLUT_MAX; i++) + dqe_write(dqe->ctx.aps[i].addr, + dqe->ctx.aps[i].val); + + if (dqe->ctx.aps_on) { + if (decon) { + dqe_reg_set_aps_full_pxl_num(decon->lcd_info); + dqe_dbg("dqe DQEAPS_FULL_PXL_NUM: %d\n", + dqe_reg_get_aps_full_pxl_num()); + + dqe_dbg("dqe DQEAPS_FULL_IMG_SIZESET: %x\n", + dqe_read(DQEAPS_FULL_IMG_SIZESET)); + } + dqe_reg_set_aps_on(1); + } else + dqe_reg_set_aps_on(0); + dqe->ctx.need_udpate = false; return 0; @@ -366,28 +464,87 @@ static void dqe_hsc_lut_set(void) DQEHSCLUT_SKIN_S2(hsc_lut[32]) | DQEHSCLUT_SKIN_S1(hsc_lut[31])); } +static void dqe_aps_lut_set(void) +{ + struct dqe_device *dqe = dqe_drvdata; + + /* DQEAPS_GAIN */ + dqe->ctx.aps[0].val = ( + DQEAPSLUT_ST(aps_lut[0]) | DQEAPSLUT_NS(aps_lut[1]) | + DQEAPSLUT_LT(aps_lut[2])); + /* DQEAPS_WEIGHT */ + dqe->ctx.aps[1].val = ( + DQEAPSLUT_PL_W2(aps_lut[3]) | DQEAPSLUT_PL_W1(aps_lut[4])); + /* DQEAPS_CTMODE */ + dqe->ctx.aps[2].val = ( + DQEAPSLUT_CTMODE(aps_lut[5])); + /* DQEAPS_PPEN */ + dqe->ctx.aps[3].val = ( + DQEAPSLUT_PP_EN(aps_lut[6])); + /* DQEAPS_TDRMINMAX */ + dqe->ctx.aps[4].val = ( + DQEAPSLUT_TDR_MAX(aps_lut[7]) | DQEAPSLUT_TDR_MIN(aps_lut[8])); + /* DQEAPS_AMBIENT_LIGHT */ + dqe->ctx.aps[5].val = ( + DQEAPSLUT_AMBIENT_LIGHT(aps_lut[9])); + /* DQEAPS_BACK_LIGHT */ + dqe->ctx.aps[6].val = ( + DQEAPSLUT_BACK_LIGHT(aps_lut[10])); + /* DQEAPS_DSTEP */ + dqe->ctx.aps[7].val = ( + DQEAPSLUT_DSTEP(aps_lut[11])); + /* DQEAPS_SCALE_MODE */ + dqe->ctx.aps[8].val = ( + DQEAPSLUT_SCALE_MODE(aps_lut[12])); + /* DQEAPS_THRESHOLD */ + dqe->ctx.aps[9].val = ( + DQEAPSLUT_THRESHOLD_3(aps_lut[13]) | DQEAPSLUT_THRESHOLD_2(aps_lut[14]) | + DQEAPSLUT_THRESHOLD_1(aps_lut[15])); + /* DQEAPS_GAIN_LIMIT */ + dqe->ctx.aps[10].val = ( + DQEAPSLUT_GAIN_LIMIT(aps_lut[16])); + /* DQEAPS_PARTIAL_CON */ + dqe->ctx.aps[11].val = ( + DQEAPSLUT_ROI_SAME(aps_lut[17]) | DQEAPSLUT_UPDATE_METHOD(aps_lut[18]) | + DQEAPSLUT_PARTIAL_FRAME(aps_lut[19])); + /* DQEAPS_PARTIAL_ROI_UP_LEFT_POS */ + dqe->ctx.aps[12].val = ( + DQEAPSLUT_ROI_Y1(aps_lut[20]) | DQEAPSLUT_ROI_X1(aps_lut[21])); + /* DQEAPS_PARTIAL_IBSI_01_00 */ + dqe->ctx.aps[13].val = ( + DQEAPSLUT_IBSI_01(aps_lut[22]) | DQEAPSLUT_IBSI_00(aps_lut[23])); + /* DQEAPS_PARTIAL_IBSI_11_10 */ + dqe->ctx.aps[14].val = ( + DQEAPSLUT_IBSI_11(aps_lut[24]) | DQEAPSLUT_IBSI_10(aps_lut[25])); +} + static ssize_t decon_dqe_gamma_show(struct device *dev, struct device_attribute *attr, char *buf) { - int i; ssize_t count = 0; struct dqe_device *dqe = dev_get_drvdata(dev); + int i, j, str_len = 0; + char gamma_result[1000] = {0, }; dqe_info("%s\n", __func__); mutex_lock(&dqe->lock); - for (i = 0; i < DQEGAMMALUT_MAX; i++) { - dqe_info("%d %d ", - DQEGAMMALUT_X_GET(dqe->ctx.gamma[i].val), - DQEGAMMALUT_Y_GET(dqe->ctx.gamma[i].val)); - dqe_dbg("0x%04x %08x ", - dqe->ctx.gamma[i].addr, dqe->ctx.gamma[i].val); + gamma_result[0] = '\0'; + for (i = 0; i < 3; i++) { + for (j = 0; j < 65; j++) { + char num[5] = {0,}; + + sprintf(num, "%d,", gamma_lut[i][j]); + strcat(gamma_result, num); + } } + str_len = strlen(gamma_result); + gamma_result[str_len - 1] = '\0'; mutex_unlock(&dqe->lock); - count = snprintf(buf, PAGE_SIZE, "gamma_on = %d\n", dqe->ctx.gamma_on); + count = sprintf(buf, "%s\n", gamma_result); return count; } @@ -412,15 +569,8 @@ static ssize_t decon_dqe_gamma_store(struct device *dev, struct device_attribute goto err; } - if (decon) { - if ((decon->state == DECON_STATE_OFF) || - (decon->state == DECON_STATE_INIT)) { - dqe_err("decon is not enabled!(%d)\n", decon->state); - ret = -1; - goto err; - } - } else { - dqe_err("decon is NULL!\n"); + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); ret = -1; goto err; } @@ -495,26 +645,28 @@ static DEVICE_ATTR(gamma, 0660, static ssize_t decon_dqe_cgc_show(struct device *dev, struct device_attribute *attr, char *buf) { - int i; ssize_t count = 0; struct dqe_device *dqe = dev_get_drvdata(dev); + int i, str_len = 0; + char cgc_result[300] = {0, }; dqe_info("%s\n", __func__); mutex_lock(&dqe->lock); - for (i = 0; i < DQECGC1LUT_MAX; i++) { - dqe_info("%d %d %d ", - DQECGCLUT_R_GET(dqe->ctx.cgc[i].val), - DQECGCLUT_G_GET(dqe->ctx.cgc[i].val), - DQECGCLUT_B_GET(dqe->ctx.cgc[i].val)); - dqe_dbg("0x%04x %08x", - dqe->ctx.cgc[i].addr, dqe->ctx.cgc[i].val); + cgc_result[0] = '\0'; + for (i = 0; i < 50; i++) { + char num[5] = {0,}; + + sprintf(num, "%d,", cgc_lut[i]); + strcat(cgc_result, num); } + str_len = strlen(cgc_result); + cgc_result[str_len - 1] = '\0'; mutex_unlock(&dqe->lock); - count = snprintf(buf, PAGE_SIZE, "cgc_on = %d\n", dqe->ctx.cgc_on); + count = sprintf(buf, "%s\n", cgc_result); return count; } @@ -539,15 +691,8 @@ static ssize_t decon_dqe_cgc_store(struct device *dev, struct device_attribute * goto err; } - if (decon) { - if ((decon->state == DECON_STATE_OFF) || - (decon->state == DECON_STATE_INIT)) { - dqe_err("decon is not enabled!(%d)\n", decon->state); - ret = -1; - goto err; - } - } else { - dqe_err("decon is NULL!\n"); + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); ret = -1; goto err; } @@ -622,30 +767,26 @@ static ssize_t decon_dqe_hsc_show(struct device *dev, { ssize_t count = 0; struct dqe_device *dqe = dev_get_drvdata(dev); + int i, str_len = 0; + char hsc_result[250] = {0, }; dqe_info("%s\n", __func__); mutex_lock(&dqe->lock); - dqe_info("%d %d %d %d %d %d", - DQEHSCLUT_R_GET(dqe->ctx.hsc[0].val), - DQEHSCLUT_G_GET(dqe->ctx.hsc[0].val), - DQEHSCLUT_B_GET(dqe->ctx.hsc[0].val), - DQEHSCLUT_C_GET(dqe->ctx.hsc[1].val), - DQEHSCLUT_M_GET(dqe->ctx.hsc[1].val), - DQEHSCLUT_Y_GET(dqe->ctx.hsc[1].val)); - - dqe_info("%d %d %d %d %d %d", - DQEHSCLUT_R_GET(dqe->ctx.hsc[6].val), - DQEHSCLUT_G_GET(dqe->ctx.hsc[6].val), - DQEHSCLUT_B_GET(dqe->ctx.hsc[6].val), - DQEHSCLUT_C_GET(dqe->ctx.hsc[7].val), - DQEHSCLUT_M_GET(dqe->ctx.hsc[7].val), - DQEHSCLUT_Y_GET(dqe->ctx.hsc[7].val)); + hsc_result[0] = '\0'; + for (i = 0; i < 35; i++) { + char num[6] = {0,}; + + sprintf(num, "%d,", hsc_lut[i]); + strcat(hsc_result, num); + } + str_len = strlen(hsc_result); + hsc_result[str_len - 1] = '\0'; mutex_unlock(&dqe->lock); - count = snprintf(buf, PAGE_SIZE, "hsc_on = %d\n", dqe->ctx.hsc_on); + count = sprintf(buf, "%s\n", hsc_result); return count; } @@ -671,15 +812,8 @@ static ssize_t decon_dqe_hsc_store(struct device *dev, struct device_attribute * goto err; } - if (decon) { - if ((decon->state == DECON_STATE_OFF) || - (decon->state == DECON_STATE_INIT)) { - dqe_err("decon is not enabled!(%d)\n", decon->state); - ret = -1; - goto err; - } - } else { - dqe_err("decon is NULL!\n"); + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); ret = -1; goto err; } @@ -760,6 +894,379 @@ static DEVICE_ATTR(hsc, 0660, decon_dqe_hsc_show, decon_dqe_hsc_store); +static ssize_t decon_dqe_aps_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t count = 0; + struct dqe_device *dqe = dev_get_drvdata(dev); + int i, str_len = 0; + char aps_result[150] = {0, }; + + dqe_info("%s\n", __func__); + + mutex_lock(&dqe->lock); + + aps_result[0] = '\0'; + for (i = 0; i < 26; i++) { + char num[5] = {0,}; + + sprintf(num, "%d,", aps_lut[i]); + strcat(aps_result, num); + } + str_len = strlen(aps_result); + aps_result[str_len - 1] = '\0'; + + mutex_unlock(&dqe->lock); + + count = sprintf(buf, "%s\n", aps_result); + + return count; +} + +static ssize_t decon_dqe_aps_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + int i, j, k; + int ret = 0; + char *head = NULL; + char *ptr = NULL; + struct dqe_device *dqe = dev_get_drvdata(dev); + struct decon_device *decon = get_decon_drvdata(0); + + dqe_info("%s +\n", __func__); + + mutex_lock(&dqe->lock); + + if (count <= 0) { + dqe_err("aps write count error\n"); + ret = -1; + goto err; + } + + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); + ret = -1; + goto err; + } + + head = (char *)buffer; + if (*head != 0) { + dqe_dbg("%s\n", head); + for (i = 0; i < 1; i++) { + k = 25; + for (j = 0; j < k; j++) { + ptr = strchr(head, ','); + if (ptr == NULL) { + dqe_err("not found comma.(%d, %d)\n", i, j); + ret = -EINVAL; + goto err; + } + *ptr = 0; + ret = kstrtou32(head, 0, &aps_lut[j]); + if (ret) { + dqe_err("strtos32(%d, %d) error.\n", i, j); + ret = -EINVAL; + goto err; + } + head = ptr + 1; + } + } + k = 0; + while (*(head + k) >= '0' && *(head + k) <= '9') + k++; + *(head + k) = 0; + ret = kstrtos32(head, 0, &aps_lut[j]); + if (ret) { + dqe_err("strtos32(%d, %d) error.\n", i-1, j); + ret = -EINVAL; + goto err; + } + } else { + dqe_err("buffer is null.\n"); + goto err; + } + + for (j = 0; j < 26; j++) + dqe_dbg("%d ", aps_lut[j]); + + dqe_aps_lut_set(); + + dqe->ctx.need_udpate = false; + + mutex_unlock(&dqe->lock); + + dqe_info("%s -\n", __func__); + + return count; +err: + mutex_unlock(&dqe->lock); + + dqe_info("%s : err(%d)\n", __func__, ret); + + return ret; +} + +static DEVICE_ATTR(aps, 0660, + decon_dqe_aps_show, + decon_dqe_aps_store); + +static ssize_t decon_dqe_aps_onoff_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t count = 0; + struct dqe_device *dqe = dev_get_drvdata(dev); + + dqe_info("%s\n", __func__); + + count = snprintf(buf, PAGE_SIZE, "aps_onoff = %d\n", dqe->ctx.aps_on); + + return count; +} + +static ssize_t decon_dqe_aps_onoff_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + int i, ret = 0; + unsigned int value = 0; + struct dqe_device *dqe = dev_get_drvdata(dev); + struct decon_device *decon = get_decon_drvdata(0); + + dqe_info("%s +\n", __func__); + + mutex_lock(&dqe->lock); + + if (count <= 0) { + dqe_err("aps_onoff write count error\n"); + ret = -1; + goto err; + } + + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); + ret = -1; + goto err; + } + + ret = kstrtouint(buffer, 0, &value); + if (ret < 0) + goto err; + + dqe_info("%s: %d\n", __func__, value); + + if (!value) + dqe->ctx.aps_on = 0; + else + dqe->ctx.aps_on = DQE_APS_ON_MASK; + + dqe->ctx.need_udpate = true; + + dqe_restore_context(); + + switch (value) { + case 1: + dqe_write(DQEAPS_FULL_PXL_NUM, 0); + dqe_write(DQEAPS_FULL_IMG_SIZESET, 0); + dqe_reg_set_aps_full_pxl_num(decon->lcd_info); + break; + case 2: + dqe_write(DQEAPS_FULL_PXL_NUM, 0); + dqe_write(DQEAPS_FULL_IMG_SIZESET, 0); + dqe_reg_set_aps_img_size(decon->lcd_info); + break; + case 3: + dqe_write(DQEAPS_FULL_PXL_NUM, 0); + dqe_write(DQEAPS_FULL_IMG_SIZESET, 0); + dqe_reg_set_aps_full_pxl_num(decon->lcd_info); + dqe_reg_set_aps_img_size(decon->lcd_info); + break; + case 4: + dqe_write(DQEAPS_FULL_PXL_NUM, 0); + dqe_write(DQEAPS_FULL_IMG_SIZESET, 0); + break; + case 11: + for (i = 0; i < 65; i++) + aps_gm_LUT64[i] = aps_gmarr_LUT64[0][i]; + break; + case 12: + for (i = 0; i < 65; i++) + aps_gm_LUT64[i] = aps_gmarr_LUT64[1][i]; + break; + case 13: + for (i = 0; i < 65; i++) + aps_gm_LUT64[i] = aps_gmarr_LUT64[2][i]; + break; + default: + break; + } + + dqe_info("dqe DQEAPS_FULL_PXL_NUM: %x\n", + dqe_read(DQEAPS_FULL_PXL_NUM)); + dqe_info("dqe DQEAPS_FULL_IMG_SIZESET: %x\n", + dqe_read(DQEAPS_FULL_IMG_SIZESET)); + + decon_reg_update_req_dqe(decon->id); + + mutex_unlock(&dqe->lock); + + dqe_info("%s -\n", __func__); + + return count; +err: + mutex_unlock(&dqe->lock); + + dqe_info("%s : err(%d)\n", __func__, ret); + + return ret; +} + +static DEVICE_ATTR(aps_onoff, 0660, + decon_dqe_aps_onoff_show, + decon_dqe_aps_onoff_store); + +int dqe_aps_gamma_LUT64(int gm_input) +{ + int gm_index = 0; + int gm_index_sub = 0; + int gm_index_subS = 0; + + int gm_val_R = 0; + int gm_val_L = 0; + + int gm_val_diff = 0; + int gm_val_mul = 0; + int gm_val_pre = 0; + int gm_val_p = 0; + + //int gm_val = 0; + int gm_DOUT_pre = 0; + + gm_index = (gm_input & APS_GAMMA_INPUT_MASK) >> APS_GAMMA_PHASE_SHIFT; //0~63 + gm_index_sub = (gm_input & APS_GAMMA_PHASE_MASK); //0~15 + gm_index_subS = (gm_input & APS_GAMMA_PHASE_MASK); //0~15 + + gm_val_R = aps_gm_LUT64[gm_index + 1]; + gm_val_L = aps_gm_LUT64[gm_index]; + + gm_val_diff = gm_val_R - gm_val_L; // LUT index Rvalue - Lvalue + gm_val_mul = gm_val_diff * gm_index_subS; + + gm_val_pre = (0x0 | gm_val_L << APS_GAMMA_PHASE_SHIFT) + gm_val_mul; + gm_val_p = ((gm_val_pre >> APS_GAMMA_PHASE_SHIFT) & APS_GAMMA_PIXEL_MAX) + + ((gm_val_pre >> (APS_GAMMA_PHASE_SHIFT - 1)) & 0x01); + gm_DOUT_pre = (gm_val_p > APS_GAMMA_PIXEL_MAX) ? APS_GAMMA_PIXEL_MAX : gm_val_p; + + return gm_DOUT_pre; +} + +int dqe_aps_convert_luma_to_al(int inLuma) +{ + int tmpAL; + int maxLuma = 5000; + int maxAL = 255; + int outAL; + + if (inLuma > 5000) + inLuma = 5000; + + // normailize + tmpAL = (inLuma * maxAL) / maxLuma; + + outAL = dqe_aps_gamma_LUT64(tmpAL); + + dqe_dbg("%s: %4d -> %3d\n", __func__, inLuma, outAL); + + return outAL; +} + +static ssize_t decon_dqe_aps_lux_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t count = 0; + struct dqe_device *dqe = dev_get_drvdata(dev); + struct decon_device *decon = get_decon_drvdata(0); + int ret = 0; + + mutex_lock(&dqe->lock); + + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); + ret = -1; + } + + if (ret > -1) + ret = dqe->ctx.aps_lux; + + mutex_unlock(&dqe->lock); + + count = snprintf(buf, PAGE_SIZE, "%d\n", ret); + + return count; +} + +static ssize_t decon_dqe_aps_lux_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + int ret = 0; + unsigned int value = 0; + u32 outAL = 0; + struct dqe_device *dqe = dev_get_drvdata(dev); + struct decon_device *decon = get_decon_drvdata(0); + + dqe_dbg("%s +\n", __func__); + + mutex_lock(&dqe->lock); + + if (count <= 0) { + dqe_err("aps_lux write count error\n"); + ret = -1; + goto err; + } + + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); + ret = -1; + goto err; + } + + ret = kstrtouint(buffer, 0, &value); + if (ret < 0) + goto err; + + dqe->ctx.aps_lux = value; + outAL = (u32)dqe_aps_convert_luma_to_al(value); + + dqe_info("%s: %4d -> %3d\n", __func__, value, outAL); + + /* DQEAPS_AMBIENT_LIGHT */ + dqe->ctx.aps[5].val = (DQEAPSLUT_AMBIENT_LIGHT(outAL)); + + dqe_write(dqe->ctx.aps[5].addr, dqe->ctx.aps[5].val); + + dqe->ctx.aps_on = DQE_APS_ON_MASK; + + dqe_reg_set_aps_full_pxl_num(decon->lcd_info); + + dqe_reg_set_aps_on(1); + + decon_reg_update_req_dqe(decon->id); + + mutex_unlock(&dqe->lock); + + dqe_dbg("%s -\n", __func__); + + return count; +err: + mutex_unlock(&dqe->lock); + + dqe_info("%s : err(%d)\n", __func__, ret); + + return ret; +} + +static DEVICE_ATTR(aps_lux, 0660, + decon_dqe_aps_lux_show, + decon_dqe_aps_lux_store); + static ssize_t decon_dqe_xml_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -991,15 +1498,8 @@ static ssize_t decon_dqe_aosp_colors_store(struct device *dev, struct device_att goto err; } - if (decon) { - if ((decon->state == DECON_STATE_OFF) || - (decon->state == DECON_STATE_INIT)) { - dqe_err("decon is not enabled!(%d)\n", decon->state); - ret = -1; - goto err; - } - } else { - dqe_err("decon is NULL!\n"); + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); ret = -1; goto err; } @@ -1119,6 +1619,9 @@ static struct attribute *dqe_attrs[] = { &dev_attr_gamma.attr, &dev_attr_cgc.attr, &dev_attr_hsc.attr, + &dev_attr_aps.attr, + &dev_attr_aps_onoff.attr, + &dev_attr_aps_lux.attr, &dev_attr_xml.attr, &dev_attr_tune_mode1.attr, &dev_attr_tune_mode2.attr, @@ -1137,15 +1640,8 @@ int decon_dqe_set_color_mode(struct decon_color_mode_with_render_intent_info *mo mutex_lock(&dqe->lock); - if (decon) { - if ((decon->state == DECON_STATE_OFF) || - (decon->state == DECON_STATE_INIT)) { - dqe_err("decon is not enabled!(%d)\n", decon->state); - ret = -1; - goto err; - } - } else { - dqe_err("decon is NULL!\n"); + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); ret = -1; goto err; } @@ -1250,14 +1746,8 @@ int decon_dqe_set_color_transform(struct decon_color_transform_info *transform) dqe->ctx.boosted_on = 0; - if (decon) { - if ((decon->state == DECON_STATE_OFF) || - (decon->state == DECON_STATE_INIT)) { - dqe_err("decon is not enabled!(%d)\n", decon->state); - goto err; - } - } else { - dqe_err("decon is NULL!\n"); + if (IS_DQE_OFF_STATE(decon)) { + dqe_err("decon is not enabled!(%d)\n", (decon) ? (decon->state) : -1); goto err; } @@ -1378,10 +1868,11 @@ void decon_dqe_enable(struct decon_device *decon) dqe_reg_start(decon->id, decon->lcd_info); val = dqe_read(DQECON); - dqe_info("dqe gamma:%d cgc:%d hsc:%d\n", + dqe_info("dqe gamma:%d cgc:%d hsc:%d aps:%d\n", DQE_GAMMA_ON_GET(val), DQE_CGC_ON_GET(val), - DQE_HSC_ON_GET(val)); + DQE_HSC_ON_GET(val), + DQE_APS_ON_GET(val)); } void decon_dqe_disable(struct decon_device *decon) -- 2.20.1