blob: 9a1eaa3dc83867a4262671d414ffded0dc127fe6 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <linux/types.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/amvecm/amvecm.h>
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
#include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
#endif
#include <linux/amlogic/media/amvecm/hdr2_ext.h>
#include "deinterlace.h"
#include "di_data_l.h"
#include <linux/amlogic/media/di/di.h>
#include "register.h"
#include "di_prc.h"
enum EREG_HDR_IDX {
EMATRIXI_COEF00_01,
EMATRIXI_COEF02_10,
EMATRIXI_COEF11_12,
EMATRIXI_COEF20_21,
EMATRIXI_COEF22,
EMATRIXI_COEF30_31,
EMATRIXI_COEF32_40,
EMATRIXI_COEF41_42,
EMATRIXI_OFFSET0_1,
EMATRIXI_OFFSET2,
EMATRIXI_PRE_OFFSET0_1,
EMATRIXI_PRE_OFFSET2,
EMATRIXI_CLIP,
EMATRIXI_EN_CTRL,
EMATRIXO_COEF00_01,
EMATRIXO_COEF02_10,
EMATRIXO_COEF11_12,
EMATRIXO_COEF20_21,
EMATRIXO_COEF22,
EMATRIXO_COEF30_31,
EMATRIXO_COEF32_40,
EMATRIXO_COEF41_42,
EMATRIXO_OFFSET0_1,
EMATRIXO_OFFSET2,
EMATRIXO_PRE_OFFSET0_1,
EMATRIXO_PRE_OFFSET2,
EMATRIXO_CLIP,
EMATRIXO_EN_CTRL,
ECGAIN_OFFT,
ECGAIN_COEF0,
ECGAIN_COEF1,
EADPS_CTRL,
EADPS_ALPHA0,
EADPS_ALPHA1,
EADPS_BETA0,
EADPS_BETA1,
EADPS_BETA2,
EADPS_COEF0,
EADPS_COEF1,
EGMUT_CTRL,
EGMUT_COEF0,
EGMUT_COEF1,
EGMUT_COEF2,
EGMUT_COEF3,
EGMUT_COEF4,
EHDR_CTRL,
};
static const unsigned int reg_hdr_idx_tab[] = {
[EMATRIXI_COEF00_01] = DI_HDR2_MATRIXI_COEF00_01,
[EMATRIXI_COEF02_10] = DI_HDR2_MATRIXI_COEF02_10,
[EMATRIXI_COEF11_12] = DI_HDR2_MATRIXI_COEF11_12,
[EMATRIXI_COEF20_21] = DI_HDR2_MATRIXI_COEF20_21,
[EMATRIXI_COEF22] = DI_HDR2_MATRIXI_COEF22,
[EMATRIXI_COEF30_31] = DI_HDR2_MATRIXI_COEF30_31,
[EMATRIXI_COEF32_40] = DI_HDR2_MATRIXI_COEF32_40,
[EMATRIXI_COEF41_42] = DI_HDR2_MATRIXI_COEF41_42,
[EMATRIXI_OFFSET0_1] = DI_HDR2_MATRIXI_OFFSET0_1,
[EMATRIXI_OFFSET2] = DI_HDR2_MATRIXI_OFFSET2,
[EMATRIXI_PRE_OFFSET0_1] = DI_HDR2_MATRIXI_PRE_OFFSET0_1,
[EMATRIXI_PRE_OFFSET2] = DI_HDR2_MATRIXI_PRE_OFFSET2,
[EMATRIXI_CLIP] = DI_HDR2_MATRIXI_CLIP,
[EMATRIXI_EN_CTRL] = DI_HDR2_MATRIXI_EN_CTRL,
[EMATRIXO_COEF00_01] = DI_HDR2_MATRIXO_COEF00_01,
[EMATRIXO_COEF02_10] = DI_HDR2_MATRIXO_COEF02_10,
[EMATRIXO_COEF11_12] = DI_HDR2_MATRIXO_COEF11_12,
[EMATRIXO_COEF20_21] = DI_HDR2_MATRIXO_COEF20_21,
[EMATRIXO_COEF22] = DI_HDR2_MATRIXO_COEF22,
[EMATRIXO_COEF30_31] = DI_HDR2_MATRIXO_COEF30_31,
[EMATRIXO_COEF32_40] = DI_HDR2_MATRIXO_COEF32_40,
[EMATRIXO_COEF41_42] = DI_HDR2_MATRIXO_COEF41_42,
[EMATRIXO_OFFSET0_1] = DI_HDR2_MATRIXO_OFFSET0_1,
[EMATRIXO_OFFSET2] = DI_HDR2_MATRIXO_OFFSET2,
[EMATRIXO_PRE_OFFSET0_1] = DI_HDR2_MATRIXO_PRE_OFFSET0_1,
[EMATRIXO_PRE_OFFSET2] = DI_HDR2_MATRIXO_PRE_OFFSET2,
[EMATRIXO_CLIP] = DI_HDR2_MATRIXO_CLIP,
[EMATRIXO_EN_CTRL] = DI_HDR2_MATRIXO_EN_CTRL,
[ECGAIN_OFFT] = DI_HDR2_CGAIN_OFFT,
[ECGAIN_COEF0] = DI_HDR2_CGAIN_COEF0,
[ECGAIN_COEF1] = DI_HDR2_CGAIN_COEF1,
[EADPS_CTRL] = DI_HDR2_ADPS_CTRL,
[EADPS_ALPHA0] = DI_HDR2_ADPS_ALPHA0,
[EADPS_ALPHA1] = DI_HDR2_ADPS_ALPHA1,
[EADPS_BETA0] = DI_HDR2_ADPS_BETA0,
[EADPS_BETA1] = DI_HDR2_ADPS_BETA1,
[EADPS_BETA2] = DI_HDR2_ADPS_BETA2,
[EADPS_COEF0] = DI_HDR2_ADPS_COEF0,
[EADPS_COEF1] = DI_HDR2_ADPS_COEF1,
[EGMUT_CTRL] = DI_HDR2_GMUT_CTRL,
[EGMUT_COEF0] = DI_HDR2_GMUT_COEF0,
[EGMUT_COEF1] = DI_HDR2_GMUT_COEF1,
[EGMUT_COEF2] = DI_HDR2_GMUT_COEF2,
[EGMUT_COEF3] = DI_HDR2_GMUT_COEF3,
[EGMUT_COEF4] = DI_HDR2_GMUT_COEF4,
[EHDR_CTRL] = DI_HDR2_CTRL,
};
struct di_hdr_sub_s {
/* */
unsigned char en; /* 1: en; 2: to disable; 0: disable */
bool para_done;
bool n_update;
bool pre_post; //
bool have_set; //for disable
unsigned int w;
unsigned int h;
unsigned int last_sgn_type; //
enum hdr_process_sel last_prc_sel;
/* */
enum hdr_module_sel module_sel; //set by di
enum hdr_process_sel hdr_process_select; //
struct hdr_proc_setting_param_s hdr_para;
};
struct di_hdr_s {
/* set by di*/
unsigned int code;
unsigned int size;
const struct reg_acc *op;
const struct di_hdr_ops_s *ops; /**/
struct di_hdr_sub_s c;
};
static unsigned int hdr_get_data_size(void)
{
return sizeof(struct di_hdr_s);
}
static bool hdr_data_check(void *pdata)
{
struct di_hdr_s *pd;
pd = (struct di_hdr_s *)pdata;
if (!pdata || pd->code != DIM_C_HDR_DATA_CODE) {
PR_ERR("dim:%s:code\n", __func__);
return false;
}
if (pd->size < hdr_get_data_size()) {
PR_ERR("dim:%s:size:%d->%d\n",
__func__,
pd->size, hdr_get_data_size());
return false;
}
//dbg_hdr("%s:\n", __func__);
return true;
}
/************************************************
* di_mp_uit_get(edi_mp_hdr_en): en
* di_mp_uit_get(edi_mp_hdr_mode):
* ref to enum hdr_process_sel
* di_mp_uit_get(edi_mp_hdr_ctrl):
* bit 0: for update setting every frame
* bit 8: for print level
***********************************************/
static bool is_ctr_update_oneframe(void)
{
return (di_mp_uit_get(edi_mp_hdr_ctrl) & DI_BIT0) ? true : false;
}
static unsigned char ctr_get_dbg_level(void)
{
unsigned int dbg_level;
dbg_level = (di_mp_uit_get(edi_mp_hdr_ctrl) & 0xff00) >> 8;
//dbg_hdr("%s:%d\n", __func__, dbg_level);
return (unsigned char)dbg_level;
}
static bool hdr_init(void)
{
struct di_hdr_s *pd;
if (!hdr_data_check(get_datal()->hw_hdr))
return false;
pd = (struct di_hdr_s *)get_datal()->hw_hdr;
pd->c.module_sel = DI_HDR;
pd->c.para_done = false;
pd->c.en = di_mp_uit_get(edi_mp_hdr_en);
return true;
}
static bool hdr_get_setting(struct vframe_s *vfm)
{
struct di_hdr_s *pd;
if (!hdr_data_check(get_datal()->hw_hdr))
return false;
pd = (struct di_hdr_s *)get_datal()->hw_hdr;
if (!pd->c.en)
return false;
pd->c.module_sel = DI_HDR;
/* pre or post */
if (vfm) {
if (IS_I_SRC(vfm->type))
pd->c.pre_post = 0; /* post */
else
pd->c.pre_post = 1; /* pre */
} else {
pd->c.pre_post = 3;
}
get_hdr_setting(pd->c.module_sel,
pd->c.hdr_process_select,
&pd->c.hdr_para,
HDR_FULL_SETTING);
/* finish */
pd->c.para_done = true;
pd->c.n_update = true;
dbg_hdr("%s:\n", __func__);
return true;
}
#define HDR_IVALID 3
static unsigned char hdr_get_pre_post(void)
{
struct di_hdr_s *pd;
if (!hdr_data_check(get_datal()->hw_hdr))
return HDR_IVALID;
pd = (struct di_hdr_s *)get_datal()->hw_hdr;
if (!pd->c.en)
return HDR_IVALID;
return (unsigned char)pd->c.pre_post;
}
/* from set_hdr_matrix */
static void dim_hdr_set_matrix(struct di_hdr_s *pd,
enum hdr_matrix_sel mtx_sel)
{
enum hdr_module_sel module_sel;
struct hdr_proc_mtx_param_s *pmtx;//hdr_mtx_param;
struct hdr_proc_adpscl_param_s *padpscl;
const struct reg_acc *op;
const unsigned int *regt;
int c_gain_lim_coef[3]; //ary copy and << 2?
int gmut_coef[3][3]; //copy and reset
int gmut_shift;
int i = 0;
regt = &reg_hdr_idx_tab[0];
module_sel = pd->c.module_sel;
pmtx = &pd->c.hdr_para.hdr_mtx_param;//&pd->hdr_mtx_param;
padpscl = &pd->c.hdr_para.hdr_adpscl_param;
op = pd->op;
if (ctr_get_dbg_level() > 1) {
dbg_hdr("%s:mtx_sel=%d,module_sel=0x%x,mtx_only[0x%x]\n",
__func__,
mtx_sel,
module_sel,
pmtx->mtx_only);
dbg_hdr("\tpscl:%d\n", padpscl->adpscl_alpha[0]);
dbg_hdr("op:0x%px\n", op);
}
if (!pmtx)
return;
op->bwr(regt[EHDR_CTRL], pmtx->mtx_on, 13, 1);
/*****************************
* need change clock gate as freerun when mtx on directly,
* not rdma op
*****************************/
/* Now only operate osd1/vd1/vd2 hdr core */
op->bwr(regt[EHDR_CTRL], pmtx->mtx_on, 13, 1);
/* recover the clock gate as auto gate by rdma op when mtx off */
/* Now only operate osd1/vd1/vd2 hdr core */
if (mtx_sel == HDR_IN_MTX) {
if (pmtx->mtx_only == MTX_ONLY &&
!pmtx->mtx_on)
op->wr(regt[EMATRIXI_EN_CTRL], 1);
else
op->wr(regt[EMATRIXI_EN_CTRL], pmtx->mtx_on);
op->bwr(regt[EHDR_CTRL], pmtx->mtx_on, 4, 1);
op->bwr(regt[EHDR_CTRL], pmtx->mtx_only,
16, 1);
op->bwr(regt[EHDR_CTRL], 1, 14, 1);
op->wr(regt[EMATRIXI_COEF00_01],
(pmtx->mtx_in[0 * 3 + 0] << 16) |
(pmtx->mtx_in[0 * 3 + 1] & 0x1FFF));
op->wr(regt[EMATRIXI_COEF02_10],
(pmtx->mtx_in[0 * 3 + 2] << 16) |
(pmtx->mtx_in[1 * 3 + 0] & 0x1FFF));
op->wr(regt[EMATRIXI_COEF11_12],
(pmtx->mtx_in[1 * 3 + 1] << 16) |
(pmtx->mtx_in[1 * 3 + 2] & 0x1FFF));
op->wr(regt[EMATRIXI_COEF20_21],
(pmtx->mtx_in[2 * 3 + 0] << 16) |
(pmtx->mtx_in[2 * 3 + 1] & 0x1FFF));
op->wr(regt[EMATRIXI_COEF22],
pmtx->mtx_in[2 * 3 + 2]);
op->wr(regt[EMATRIXI_OFFSET0_1],
(pmtx->mtxi_pos_offset[0] << 16) |
(pmtx->mtxi_pos_offset[1] & 0xFFF));
op->wr(regt[EMATRIXI_OFFSET2],
pmtx->mtxi_pos_offset[2]);
op->wr(regt[EMATRIXI_PRE_OFFSET0_1],
(pmtx->mtxi_pre_offset[0] << 16) |
(pmtx->mtxi_pre_offset[1] & 0xFFF));
op->wr(regt[EMATRIXI_PRE_OFFSET2],
pmtx->mtxi_pre_offset[2]);
} else if (mtx_sel == HDR_GAMUT_MTX) {
for (i = 0; i < 9; i++)
gmut_coef[i / 3][i % 3] =
pmtx->mtx_gamut[i];
if ((pmtx->p_sel & HDR_SDR) ||
(pmtx->p_sel & HDR10P_SDR) ||
(pmtx->p_sel & HLG_SDR)) {
if (pmtx->gmt_bit_mode) {
gmut_shift = 8;
/*gamut shift bit for used for enable oo 33bit*/
/*after tm2 revb fix 32bit bug*/
gmut_shift |= 1 << 4;
} else {
/* use integer mode for gamut coeff */
gmut_shift = 0;
}
} else {
/* 2048 as 1.0 for gamut coeff */
gmut_shift = 11;
}
for (i = 0; i < 3; i++)
c_gain_lim_coef[i] = pmtx->mtx_cgain[i] << 2;
/*gamut mode: 1->gamut before ootf*/
/*2->gamut after ootf*/
/*other->disable gamut*/
op->bwr(regt[EHDR_CTRL],
pmtx->mtx_gamut_mode, 6, 2);
op->wr(regt[EGMUT_CTRL], gmut_shift);
op->wr(regt[EGMUT_COEF0],
(gmut_coef[0][1] & 0xffff) << 16 |
(gmut_coef[0][0] & 0xffff));
op->wr(regt[EGMUT_COEF1],
(gmut_coef[1][0] & 0xffff) << 16 |
(gmut_coef[0][2] & 0xffff));
op->wr(regt[EGMUT_COEF2],
(gmut_coef[1][2] & 0xffff) << 16 |
(gmut_coef[1][1] & 0xffff));
op->wr(regt[EGMUT_COEF3],
(gmut_coef[2][1] & 0xffff) << 16 |
(gmut_coef[2][0] & 0xffff));
op->wr(regt[EGMUT_COEF4],
gmut_coef[2][2] & 0xffff);
op->wr(regt[ECGAIN_COEF0],
c_gain_lim_coef[1] << 16 |
c_gain_lim_coef[0]);
op->bwr(regt[ECGAIN_COEF1],
c_gain_lim_coef[2], 0, 12);
op->wr(regt[EADPS_CTRL],
padpscl->adpscl_bypass[2] << 6 |
padpscl->adpscl_bypass[1] << 5 |
padpscl->adpscl_bypass[0] << 4 |
padpscl->adpscl_mode);
op->wr(regt[EADPS_ALPHA0],
padpscl->adpscl_alpha[1] << 16 |
padpscl->adpscl_alpha[0]);
op->wr(regt[EADPS_ALPHA1],
padpscl->adpscl_shift[0] << 24 |
padpscl->adpscl_shift[1] << 20 |
padpscl->adpscl_shift[2] << 16 |
padpscl->adpscl_alpha[2]);
op->wr(regt[EADPS_BETA0],
padpscl->adpscl_beta_s[0] << 20 |
padpscl->adpscl_beta[0]);
op->wr(regt[EADPS_BETA1],
padpscl->adpscl_beta_s[1] << 20 |
padpscl->adpscl_beta[1]);
op->wr(regt[EADPS_BETA2],
padpscl->adpscl_beta_s[2] << 20 |
padpscl->adpscl_beta[2]);
op->wr(regt[EADPS_COEF0],
padpscl->adpscl_ys_coef[1] << 16 |
padpscl->adpscl_ys_coef[0]);
op->wr(regt[EADPS_COEF1],
padpscl->adpscl_ys_coef[2]);
} else if (mtx_sel == HDR_OUT_MTX) {
op->wr(regt[ECGAIN_OFFT],
(pmtx->mtx_cgain_offset[2] << 16) |
pmtx->mtx_cgain_offset[1]);
op->wr(regt[EMATRIXO_EN_CTRL],
pmtx->mtx_on);
op->bwr(regt[EHDR_CTRL], 0, 17, 1);
op->bwr(regt[EHDR_CTRL], 1, 15, 1);
op->wr(regt[EMATRIXO_COEF00_01],
(pmtx->mtx_out[0 * 3 + 0] << 16) |
(pmtx->mtx_out[0 * 3 + 1] & 0x1FFF));
op->wr(regt[EMATRIXO_COEF02_10],
(pmtx->mtx_out[0 * 3 + 2] << 16) |
(pmtx->mtx_out[1 * 3 + 0] & 0x1FFF));
op->wr(regt[EMATRIXO_COEF11_12],
(pmtx->mtx_out[1 * 3 + 1] << 16) |
(pmtx->mtx_out[1 * 3 + 2] & 0x1FFF));
op->wr(regt[EMATRIXO_COEF20_21],
(pmtx->mtx_out[2 * 3 + 0] << 16) |
(pmtx->mtx_out[2 * 3 + 1] & 0x1FFF));
op->wr(regt[EMATRIXO_COEF22],
pmtx->mtx_out[2 * 3 + 2]);
op->wr(regt[EMATRIXO_OFFSET0_1],
(pmtx->mtxo_pos_offset[0] << 16) |
(pmtx->mtxo_pos_offset[1] & 0xFFF));
op->wr(regt[EMATRIXO_OFFSET2],
pmtx->mtxo_pos_offset[2]);
op->wr(regt[EMATRIXO_PRE_OFFSET0_1],
(pmtx->mtxo_pre_offset[0] << 16) |
(pmtx->mtxo_pre_offset[1] & 0xFFF));
op->wr(regt[EMATRIXO_PRE_OFFSET2],
pmtx->mtxo_pre_offset[2]);
}
/* below is dbg */
if (ctr_get_dbg_level() <= 1)
return;
if (mtx_sel == HDR_IN_MTX) {
PR_INF("hdr:in_mtx %d;%d; = 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,%x\n",
pmtx->mtx_on,
pmtx->mtx_only,
(pmtx->mtxi_pre_offset[0] << 16) |
(pmtx->mtxi_pre_offset[1] & 0xFFF),
(pmtx->mtx_in[0 * 3 + 0] << 16) |
(pmtx->mtx_in[0 * 3 + 1] & 0x1FFF),
(pmtx->mtx_in[0 * 3 + 2] << 16) |
(pmtx->mtx_in[1 * 3 + 0] & 0x1FFF),
(pmtx->mtx_in[1 * 3 + 1] << 16) |
(pmtx->mtx_in[1 * 3 + 2] & 0x1FFF),
(pmtx->mtx_in[2 * 3 + 0] << 16) |
(pmtx->mtx_in[2 * 3 + 1] & 0x1FFF),
pmtx->mtx_in[2 * 3 + 2],
(pmtx->mtxi_pos_offset[0] << 16) |
(pmtx->mtxi_pos_offset[1] & 0xFFF));
} else if (mtx_sel == HDR_GAMUT_MTX) {
PR_INF("hdr: gamut_mtx %d mode %d shift %d = %x %x %x %x %x\n",
pmtx->mtx_on,
pmtx->mtx_gamut_mode,
gmut_shift,
(gmut_coef[0][1] & 0xffff) << 16 |
(gmut_coef[0][0] & 0xffff),
(gmut_coef[1][0] & 0xffff) << 16 |
(gmut_coef[0][2] & 0xffff),
(gmut_coef[1][2] & 0xffff) << 16 |
(gmut_coef[1][1] & 0xffff),
(gmut_coef[2][1] & 0xffff) << 16 |
(gmut_coef[2][0] & 0xffff),
gmut_coef[2][2] & 0xffff);
PR_INF("hdr: adpscl bypass %d\n",
padpscl->adpscl_bypass[0]);
PR_INF("hdr: adpscl bypass %d, x_shift %d, y_shift %d\n",
padpscl->adpscl_bypass[0],
padpscl->adpscl_shift[0],
padpscl->adpscl_shift[1]);
} else if (mtx_sel == HDR_OUT_MTX) {
PR_INF("hdr: out_mtx %d %d = %x,%x %x %x %x %x,%x\n",
pmtx->mtx_on,
pmtx->mtx_only,
(pmtx->mtxo_pre_offset[0] << 16) |
(pmtx->mtxo_pre_offset[1] & 0xFFF),
(pmtx->mtx_out[0 * 3 + 0] << 16) |
(pmtx->mtx_out[0 * 3 + 1] & 0x1FFF),
(pmtx->mtx_out[0 * 3 + 2] << 16) |
(pmtx->mtx_out[1 * 3 + 0] & 0x1FFF),
(pmtx->mtx_out[1 * 3 + 1] << 16) |
(pmtx->mtx_out[1 * 3 + 2] & 0x1FFF),
(pmtx->mtx_out[2 * 3 + 0] << 16) |
(pmtx->mtx_out[2 * 3 + 1] & 0x1FFF),
pmtx->mtx_out[2 * 3 + 2],
(pmtx->mtxo_pos_offset[0] << 16) |
(pmtx->mtxo_pos_offset[1] & 0xFFF));
}
}
/************************************************
* from set_eotf_lut
* plut -> hdr_lut_param
************************************************/
static void dim_hdr_set_eotf_lut(struct di_hdr_s *pd,
enum hdr_module_sel module_sel,
struct hdr_proc_lut_param_s *plut)
{
unsigned int eotf_lut_addr_port = 0;
unsigned int eotf_lut_data_port = 0;
unsigned int hdr_ctrl = 0;
unsigned int i = 0;
const struct reg_acc *op = pd->op;
if (module_sel == DI_HDR || module_sel == DI_M2M_HDR) {
eotf_lut_addr_port = DI_EOTF_LUT_ADDR_PORT;
eotf_lut_data_port = DI_EOTF_LUT_DATA_PORT;
hdr_ctrl = DI_HDR2_CTRL;
} else {
PR_ERR("dim:%s:not di hdr\n", __func__);
return;
}
op->bwr(hdr_ctrl, plut->lut_on, 3, 1);
if (!plut->lut_on)
return;
op->wr(eotf_lut_addr_port, 0x0);
for (i = 0; i < HDR2_EOTF_LUT_SIZE; i++)
op->wr(eotf_lut_data_port, (unsigned int)plut->eotf_lut[i]);
}
/************************************************
* from set_ootf_lut
* plut -> hdr_lut_param
************************************************/
static void dim_hdr_set_ootf_lut(struct di_hdr_s *pd,
enum hdr_module_sel module_sel,
struct hdr_proc_lut_param_s *plut)
{
unsigned int ootf_lut_addr_port = 0;
unsigned int ootf_lut_data_port = 0;
unsigned int hdr_ctrl = 0;
unsigned int i = 0;
const struct reg_acc *op = pd->op;
if (module_sel == DI_HDR ||
module_sel == DI_M2M_HDR) {
ootf_lut_addr_port = DI_OGAIN_LUT_ADDR_PORT;
ootf_lut_data_port = DI_OGAIN_LUT_DATA_PORT;
hdr_ctrl = DI_HDR2_CTRL;
} else {
PR_ERR("dim:%s:not di hdr\n", __func__);
return;
}
op->bwr(hdr_ctrl, plut->lut_on, 1, 1);
if (!plut->lut_on)
return;
op->wr(ootf_lut_addr_port, 0x0);
for (i = 0; i < HDR2_OOTF_LUT_SIZE / 2; i++)
op->wr(ootf_lut_data_port,
((unsigned int)plut->ogain_lut[i * 2 + 1] << 16) +
(unsigned int)plut->ogain_lut[i * 2]);
op->wr(ootf_lut_data_port, (unsigned int)plut->ogain_lut[148]);
}
/************************************************
* from set_oetf_lut
* plut-> hdr_lut_param
***********************************************/
static void dim_hdr_set_oetf_lut(struct di_hdr_s *pd,
enum hdr_module_sel module_sel,
struct hdr_proc_lut_param_s *plut)
{
unsigned int oetf_lut_addr_port = 0;
unsigned int oetf_lut_data_port = 0;
unsigned int hdr_ctrl = 0;
unsigned int i = 0;
unsigned int tmp1, tmp2;
const struct reg_acc *op = pd->op;
if (module_sel == DI_HDR ||
module_sel == DI_M2M_HDR) {
oetf_lut_addr_port = DI_OETF_LUT_ADDR_PORT;
oetf_lut_data_port = DI_OETF_LUT_DATA_PORT;
hdr_ctrl = DI_HDR2_CTRL;
} else {
PR_ERR("dim:%s:not di hdr\n", __func__);
return;
}
op->bwr(hdr_ctrl, plut->lut_on, 2, 1);
if (!plut->lut_on)
return;
op->wr(oetf_lut_addr_port, 0x0);
for (i = 0; i < HDR2_OETF_LUT_SIZE / 2; i++) {
tmp1 = (unsigned int)plut->oetf_lut[i * 2 + 1];
tmp2 = (unsigned int)plut->oetf_lut[i * 2];
if (plut->bitdepth == 10) {
tmp1 = tmp1 >> 2;
tmp2 = tmp2 >> 2;
}
op->wr(oetf_lut_data_port, (tmp1 << 16) + tmp2);
}
tmp1 = (unsigned int)plut->oetf_lut[148];
if (plut->bitdepth == 10)
op->wr(oetf_lut_data_port, tmp1 >> 2);
else
op->wr(oetf_lut_data_port, tmp1);
}
/************************************************
* from set_c_gain
* plut->hdr_lut_param
************************************************/
static void dim_hdr_set_c_gain(struct di_hdr_s *pd,
enum hdr_module_sel module_sel,
struct hdr_proc_lut_param_s *plut)
{
unsigned int cgain_lut_addr_port = 0;
unsigned int cgain_lut_data_port = 0;
unsigned int hdr_ctrl = 0;
unsigned int cgain_coef1 = 0;
unsigned int i = 0;
const struct reg_acc *op = pd->op;
if (module_sel == DI_HDR ||
module_sel == DI_M2M_HDR) {
cgain_lut_addr_port = DI_CGAIN_LUT_ADDR_PORT;
cgain_lut_data_port = DI_CGAIN_LUT_DATA_PORT;
hdr_ctrl = DI_HDR2_CTRL;
cgain_coef1 = DI_HDR2_CGAIN_COEF1;
} else {
PR_ERR("dim:%s:not di hdr\n", __func__);
return;
}
/*cgain mode: 0->y domin*/
/*cgain mode: 1->rgb domin, use r/g/b max*/
op->bwr(hdr_ctrl, 0, 12, 1);
op->bwr(hdr_ctrl, plut->cgain_en, 0, 1);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_SM1)) {
if (plut->bitdepth == 10)
op->bwr(cgain_coef1, 0x400, 16, 13);
else if (plut->bitdepth == 12)
op->bwr(cgain_coef1, 0x1000, 16, 13);
}
if (!plut->cgain_en)
return;
op->wr(cgain_lut_addr_port, 0x0);
for (i = 0; i < HDR2_CGAIN_LUT_SIZE / 2; i++)
op->wr(cgain_lut_data_port,
((unsigned int)plut->cgain_lut[i * 2 + 1] << 16) +
(unsigned int)plut->cgain_lut[i * 2]);
op->wr(cgain_lut_data_port, (unsigned int)plut->cgain_lut[64]);
}
/************************************************
* hdr_hist_config
* plut -> hdr_lut_param
************************************************/
static void dim_hdr_hist_config(struct di_hdr_s *pd,
enum hdr_module_sel module_sel,
struct hdr_proc_lut_param_s *plut)
{
unsigned int hist_ctrl;
unsigned int hist_hs_he;
unsigned int hist_vs_ve;
const struct reg_acc *op = pd->op;
if (module_sel == DI_HDR ||
module_sel == DI_M2M_HDR) {
hist_ctrl = DI_HDR2_HIST_CTRL;
hist_hs_he = DI_HDR2_HIST_H_START_END;
hist_vs_ve = DI_HDR2_HIST_V_START_END;
} else {
PR_ERR("dim:%s:not di hdr\n", __func__);
return;
}
if (get_cpu_type() < MESON_CPU_MAJOR_ID_TM2)
return;
if (plut->hist_en) {
op->wr(hist_ctrl, 0);
op->wr(hist_hs_he, 0xeff);
op->wr(hist_vs_ve, 0x86f);
} else {
op->wr(hist_ctrl, 0x5510);
op->wr(hist_hs_he, 0x10000);
op->wr(hist_vs_ve, 0x0);
}
}
static void dim_hdr_set(unsigned char pre_post)
{
enum hdr_module_sel module_sel;
struct di_hdr_s *pd;
if (!hdr_data_check(get_datal()->hw_hdr))
return;
pd = (struct di_hdr_s *)get_datal()->hw_hdr;
if (!pd->c.en ||
!pd->c.para_done ||
!pd->c.n_update) {
if (ctr_get_dbg_level() > 0) {
dbg_hdr("no need update\n");
dbg_hdr("%s:en[%d],para_done[%d], update[%d]\n",
__func__,
pd->c.en,
pd->c.para_done,
pd->c.n_update);
}
return;
}
pd->c.have_set = true;
module_sel = pd->c.module_sel;
/* same register with pps */
if (pre_post < 2)
pd->op->bwr(DI_SC_TOP_CTRL, (pre_post ? 3 : 0), 29, 2);
pd->op->bwr(DI_HDR_IN_HSIZE, pd->c.w, 0, 13);
pd->op->bwr(DI_HDR_IN_VSIZE, pd->c.h, 0, 13);
/*************************/
dim_hdr_set_matrix(pd, HDR_IN_MTX);//, &pd->hdr_mtx_param, NULL
dim_hdr_set_eotf_lut(pd, module_sel, &pd->c.hdr_para.hdr_lut_param);
dim_hdr_set_matrix(pd, HDR_GAMUT_MTX);//, &pd->hdr_mtx_param, NULL
dim_hdr_set_ootf_lut(pd, module_sel, &pd->c.hdr_para.hdr_lut_param);
dim_hdr_set_oetf_lut(pd, module_sel, &pd->c.hdr_para.hdr_lut_param);
dim_hdr_set_matrix(pd, HDR_OUT_MTX); //, &pd->hdr_mtx_param, NULL
dim_hdr_set_c_gain(pd, module_sel, &pd->c.hdr_para.hdr_lut_param);
dim_hdr_hist_config(pd, module_sel, &pd->c.hdr_para.hdr_lut_param);
pd->c.n_update = false;
dbg_hdr("%s:pre_post[%d]\n", __func__, pre_post);
#ifdef HIS_CODE //ary: discuss with mingliang, this is not need for di
if (clip_func == 0xff) {
if (get_cpu_type() == MESON_CPU_MAJOR_ID_T3)
dim_hdr_clip_func_after_ootf(xxx);
}
#endif
}
static bool hdr_disable(void)
{
struct di_hdr_s *pd;
if (!hdr_data_check(get_datal()->hw_hdr))
return false;
pd = (struct di_hdr_s *)get_datal()->hw_hdr;
if (pd->c.en &&
pd->c.have_set &&
pd->c.hdr_process_select != HDR_BYPASS) {
pd->c.hdr_process_select = HDR_BYPASS;
hdr_get_setting(NULL);
dim_hdr_set(3);
PR_INF("%s:\n", __func__);
}
memset(&pd->c, 0, sizeof(pd->c));
return true;
}
static bool hdr_get_change(struct vframe_s *vfm, unsigned int force_change)
{
struct di_hdr_s *hdr;
unsigned int x, y;
if (!hdr_data_check(get_datal()->hw_hdr))
return false;
hdr = (struct di_hdr_s *)get_datal()->hw_hdr;
if (!di_mp_uit_get(edi_mp_hdr_en) &&
(!hdr->c.en || hdr->c.en == 2)) {
hdr->c.en = 0;
return false;
}
if (!di_mp_uit_get(edi_mp_hdr_en) && hdr->c.en == 1)
goto HDR_UP_INF;
if (force_change)
goto HDR_UP_INF;
if (!vfm)
return false;
if (hdr->c.last_sgn_type != vfm->signal_type)
goto HDR_UP_INF;
if (di_mp_uit_get(edi_mp_hdr_mode) &&
hdr->c.last_prc_sel != di_mp_uit_get(edi_mp_hdr_mode))
goto HDR_UP_INF;
if (is_ctr_update_oneframe() && hdr->c.en)
hdr->c.n_update = true;
return false;
HDR_UP_INF:
if (!di_mp_uit_get(edi_mp_hdr_en) &&
hdr->c.en == 1 &&
hdr->c.hdr_process_select != HDR_BYPASS) {
/*en -> disable*/
hdr->c.en = 2;
hdr->c.hdr_process_select = HDR_BYPASS;
} else {
if (di_mp_uit_get(edi_mp_hdr_en))
hdr->c.en = 1;
if (di_mp_uit_get(edi_mp_hdr_mode))
hdr->c.hdr_process_select =
di_mp_uit_get(edi_mp_hdr_mode);
/* else: to do need get hdr sel from hdr module*/
}
if (vfm) {
PR_INF("%s:0x%x->0x%x\n",
"signal_type",
hdr->c.last_sgn_type, vfm->signal_type);
hdr->c.last_sgn_type = vfm->signal_type;
}
PR_INF("%s:0x%x->0x%x\n",
"hdr_process_select",
hdr->c.last_prc_sel, hdr->c.hdr_process_select);
hdr->c.last_prc_sel = hdr->c.hdr_process_select;
dim_vf_x_y(vfm, &x, &y);
hdr->c.w = x;
hdr->c.h = y;
hdr->c.n_update = true;
return true;
}
const struct di_hdr_ops_s di_hdr_op_data = {
.get_data_size = hdr_get_data_size,
.init = hdr_init, /* reg */
.unreg_setting = hdr_disable, /* unreg */
.get_change = hdr_get_change,
.get_setting = hdr_get_setting,
.set = dim_hdr_set,
.get_pre_post = hdr_get_pre_post,
};
void dim_hdr_prob(void)
{
struct di_hdr_s *hdr;
unsigned int sizev;
if (!IS_IC_SUPPORT(HDR) || !cfgg(HDR_EN))
return;
hdr = (struct di_hdr_s *)get_datal()->hw_hdr;
if (!hdr) {
vfree(hdr);
hdr = NULL;
PR_INF("%s:hdr is not null, clear\n", __func__);
}
sizev = hdr_get_data_size();
hdr = vmalloc(sizeof(*hdr));
if (!hdr) {
PR_WARN("%s:vmalloc\n", __func__);
return;
}
memset(hdr, 0, sizeof(*hdr));
hdr->code = DIM_C_HDR_DATA_CODE;
hdr->size = sizev;
hdr->op = &di_pre_regset;
hdr->ops = &di_hdr_op_data;
get_datal()->hw_hdr = hdr;
/*check*/
hdr = (struct di_hdr_s *)get_datal()->hw_hdr;
PR_INF("%s:0x%x\n", __func__, hdr->code);
}
void dim_hdr_remove(void)
{
if (!get_datal()->hw_hdr)
return;
vfree(get_datal()->hw_hdr);
get_datal()->hw_hdr = NULL;
PR_INF("%s:end\n", __func__);
}
const struct di_hdr_ops_s *dim_hdr_ops(void)
{
struct di_hdr_s *hdr;
if (!get_datal()->hw_hdr)
return NULL;
hdr = (struct di_hdr_s *)get_datal()->hw_hdr;
return hdr->ops;
}
int dim_dbg_hdr_reg1(struct seq_file *s, void *v, unsigned int indx)
{
int i;
unsigned int rbase = 0;
unsigned int nub1, off2, nub2, off3, nub3;
nub1 = 0x1d;
off2 = 0x24;
nub2 = 2;
off3 = 0x28;
nub3 = 0x18;
if (indx == VD1_HDR) {
seq_puts(s, "VD1_HDR\n");
rbase = 0x3800;//VD1_HDR2_CTRL;
} else if (indx == DI_HDR || indx == DI_M2M_HDR) {
seq_puts(s, "DI_HDR\n");
rbase = DI_HDR2_CTRL;
}
if (!rbase) {
seq_puts(s, "base is 0, do nothing\n");
return 0;
}
for (i = 0; i < nub1; i++) {
seq_printf(s, "%d:[0x%x]=0x%x\n",
i,
rbase + i,
DIM_RDMA_RD(rbase + i));
}
for (i = 0; i < nub2; i++) {
seq_printf(s, "%d:[0x%x]=0x%x\n",
i,
rbase + off2 + i,
DIM_RDMA_RD(rbase + off2 + i));
}
for (i = 0; i < nub3; i++) {
seq_printf(s, "%d:[0x%x]=0x%x\n",
i,
rbase + off3 + i,
DIM_RDMA_RD(rbase + off3 + i));
}
return 0;
}
int dim_dbg_hdr_para_show(struct seq_file *s, void *v)
{
int i;
struct di_hdr_s *pd;
char *splt = "---------------------------";
pd = (struct di_hdr_s *)get_datal()->hw_hdr;
if (!pd) {
seq_puts(s, "no hdr, donothing\n");
return 0;
}
seq_printf(s, "%s\n", splt);
seq_printf(s, "code[0x%x],size[%d], op:0x%px,ops:0x%px,dbg_level[%d]\n",
pd->code,
pd->size,
pd->op,
pd->ops,
ctr_get_dbg_level());
seq_printf(s, "%s\n", splt);
seq_printf(s, "en[%d], para_done[%d], n_update:%d, have_set:%d\n",
pd->c.en,
pd->c.para_done,
pd->c.n_update,
pd->c.have_set);
seq_printf(s, "l_sgn_type[0x%x], l_prc_sel[0x%x], pre_post:%d\n",
pd->c.last_sgn_type,
pd->c.last_prc_sel,
pd->c.pre_post);
seq_printf(s, "module_sel[0x%x], hdr_process_select[0x%x]\n",
pd->c.module_sel,
pd->c.hdr_process_select);
seq_printf(s, "%s:%s\n", "hdr_mtx_param", splt);
seq_printf(s, "mtx_on[0x%x], mtx_only[0x%x], p_sel[0x%x]\n",
pd->c.hdr_para.hdr_mtx_param.mtx_on,
pd->c.hdr_para.hdr_mtx_param.mtx_only,
pd->c.hdr_para.hdr_mtx_param.p_sel);
seq_printf(s, "%s:%s\n", "hdr_lut_param", splt);
seq_printf(s, "lut_on[%d], bitdepth[%d], cgain_en[%d], hist_en[%d]\n",
pd->c.hdr_para.hdr_lut_param.lut_on,
pd->c.hdr_para.hdr_lut_param.bitdepth,
pd->c.hdr_para.hdr_lut_param.cgain_en,
pd->c.hdr_para.hdr_lut_param.hist_en);
seq_printf(s, "%s:%s\n", "hdr_lut_param", splt);
seq_printf(s, "clip_en[%d], clip_max[0x%x]\n",
pd->c.hdr_para.hdr_clip_param.clip_en,
pd->c.hdr_para.hdr_clip_param.clip_max);
seq_printf(s, "%s:%s\n", "mtx_in", splt);
for (i = 0; i < MTX_NUM_PARAM; i++)
seq_printf(s, "%d:%d\n",
i, pd->c.hdr_para.hdr_mtx_param.mtx_in[i]);
return 0;
}