android_kernel_xiaomi_sm8350/techpack/display/msm/sde/sde_hw_ad4.c
Michael Bestas 23b65c3a24
Add 'techpack/display/' from tag 'LA.UM.9.14.r1-18300-LAHAINA.0'
git-subtree-dir: techpack/display
git-subtree-mainline: 2d46776923
git-subtree-split: 64f31403b4
Change-Id: I7f4c42a3ba6b11a8db861cdd171a52d8f58f2e06
2022-05-19 00:04:54 +03:00

1772 lines
54 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
*/
#include <drm/msm_drm_pp.h>
#include "sde_hw_catalog.h"
#include "sde_hw_util.h"
#include "sde_hw_mdss.h"
#include "sde_hw_lm.h"
#include "sde_ad4.h"
#define AD_STATE_READY(x) \
(((x) & ad4_init) && \
((x) & ad4_cfg) && \
((x) & ad4_mode) && \
(((x) & ad4_input) | ((x) & ad4_strength)))
#define MERGE_WIDTH_RIGHT 6
#define MERGE_WIDTH_LEFT 5
#define AD_IPC_FRAME_COUNT 2
enum ad4_ops_bitmask {
ad4_init = BIT(AD_INIT),
ad4_cfg = BIT(AD_CFG),
ad4_mode = BIT(AD_MODE),
ad4_input = BIT(AD_INPUT),
ad4_strength = BIT(AD_STRENGTH),
ad4_ops_max = BIT(31),
};
enum ad4_state {
ad4_state_idle,
ad4_state_startup,
ad4_state_run,
/* idle power collapse suspend state */
ad4_state_ipcs,
/* idle power collapse resume state */
ad4_state_ipcr,
/* manual mode state */
ad4_state_manual,
ad4_state_max,
};
struct ad4_roi_info {
u32 h_start;
u32 h_end;
u32 v_start;
u32 v_end;
u32 f_in;
u32 f_out;
};
typedef int (*ad4_prop_setup)(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *ad);
static int ad4_params_check(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_no_op_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
static int ad4_setup_debug_manual(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_mode_setup(struct sde_hw_dspp *dspp, enum ad4_modes mode);
static int ad4_mode_setup_common(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_init_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
static int ad4_init_setup_idle(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_init_setup_run(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_init_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
static int ad4_cfg_setup_idle(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_cfg_setup_run(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_cfg_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_input_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_roi_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg);
static int ad4_roi_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_roi_coordinate_offset(struct sde_hw_cp_cfg *hw_cfg,
struct ad4_roi_info *output);
static int ad4_input_setup_idle(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_input_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_suspend_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_assertive_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_assertive_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_backlight_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_backlight_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_strength_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_strength_setup_idle(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_ipc_suspend_setup_run(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_ipc_suspend_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_ipc_resume_setup_ipcs(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_ipc_reset_setup_startup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static int ad4_cfg_ipc_reset(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg);
static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = {
[ad4_state_idle][AD_MODE] = ad4_mode_setup_common,
[ad4_state_idle][AD_INIT] = ad4_init_setup_idle,
[ad4_state_idle][AD_CFG] = ad4_cfg_setup_idle,
[ad4_state_idle][AD_INPUT] = ad4_input_setup_idle,
[ad4_state_idle][AD_SUSPEND] = ad4_suspend_setup,
[ad4_state_idle][AD_ASSERTIVE] = ad4_assertive_setup,
[ad4_state_idle][AD_BACKLIGHT] = ad4_backlight_setup,
[ad4_state_idle][AD_STRENGTH] = ad4_strength_setup_idle,
[ad4_state_idle][AD_ROI] = ad4_roi_setup,
[ad4_state_idle][AD_IPC_SUSPEND] = ad4_no_op_setup,
[ad4_state_idle][AD_IPC_RESUME] = ad4_no_op_setup,
[ad4_state_idle][AD_IPC_RESET] = ad4_no_op_setup,
[ad4_state_startup][AD_MODE] = ad4_mode_setup_common,
[ad4_state_startup][AD_INIT] = ad4_init_setup,
[ad4_state_startup][AD_CFG] = ad4_cfg_setup,
[ad4_state_startup][AD_INPUT] = ad4_input_setup,
[ad4_state_startup][AD_SUSPEND] = ad4_suspend_setup,
[ad4_state_startup][AD_ASSERTIVE] = ad4_assertive_setup,
[ad4_state_startup][AD_BACKLIGHT] = ad4_backlight_setup,
[ad4_state_startup][AD_IPC_SUSPEND] = ad4_no_op_setup,
[ad4_state_startup][AD_STRENGTH] = ad4_no_op_setup,
[ad4_state_startup][AD_ROI] = ad4_roi_setup,
[ad4_state_startup][AD_IPC_RESUME] = ad4_no_op_setup,
[ad4_state_startup][AD_IPC_RESET] = ad4_ipc_reset_setup_startup,
[ad4_state_run][AD_MODE] = ad4_mode_setup_common,
[ad4_state_run][AD_INIT] = ad4_init_setup_run,
[ad4_state_run][AD_CFG] = ad4_cfg_setup_run,
[ad4_state_run][AD_INPUT] = ad4_input_setup,
[ad4_state_run][AD_SUSPEND] = ad4_suspend_setup,
[ad4_state_run][AD_ASSERTIVE] = ad4_assertive_setup,
[ad4_state_run][AD_BACKLIGHT] = ad4_backlight_setup,
[ad4_state_run][AD_STRENGTH] = ad4_no_op_setup,
[ad4_state_run][AD_ROI] = ad4_roi_setup,
[ad4_state_run][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_run,
[ad4_state_run][AD_IPC_RESUME] = ad4_no_op_setup,
[ad4_state_run][AD_IPC_RESET] = ad4_setup_debug,
[ad4_state_ipcs][AD_MODE] = ad4_no_op_setup,
[ad4_state_ipcs][AD_INIT] = ad4_no_op_setup,
[ad4_state_ipcs][AD_CFG] = ad4_no_op_setup,
[ad4_state_ipcs][AD_INPUT] = ad4_no_op_setup,
[ad4_state_ipcs][AD_SUSPEND] = ad4_no_op_setup,
[ad4_state_ipcs][AD_ASSERTIVE] = ad4_no_op_setup,
[ad4_state_ipcs][AD_BACKLIGHT] = ad4_no_op_setup,
[ad4_state_ipcs][AD_STRENGTH] = ad4_no_op_setup,
[ad4_state_ipcs][AD_ROI] = ad4_no_op_setup,
[ad4_state_ipcs][AD_IPC_SUSPEND] = ad4_no_op_setup,
[ad4_state_ipcs][AD_IPC_RESUME] = ad4_ipc_resume_setup_ipcs,
[ad4_state_ipcs][AD_IPC_RESET] = ad4_no_op_setup,
[ad4_state_ipcr][AD_MODE] = ad4_mode_setup_common,
[ad4_state_ipcr][AD_INIT] = ad4_init_setup_ipcr,
[ad4_state_ipcr][AD_CFG] = ad4_cfg_setup_ipcr,
[ad4_state_ipcr][AD_INPUT] = ad4_input_setup_ipcr,
[ad4_state_ipcr][AD_SUSPEND] = ad4_suspend_setup,
[ad4_state_ipcr][AD_ASSERTIVE] = ad4_assertive_setup_ipcr,
[ad4_state_ipcr][AD_BACKLIGHT] = ad4_backlight_setup_ipcr,
[ad4_state_ipcr][AD_STRENGTH] = ad4_no_op_setup,
[ad4_state_ipcr][AD_ROI] = ad4_roi_setup_ipcr,
[ad4_state_ipcr][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_ipcr,
[ad4_state_ipcr][AD_IPC_RESUME] = ad4_no_op_setup,
[ad4_state_ipcr][AD_IPC_RESET] = ad4_ipc_reset_setup_ipcr,
[ad4_state_manual][AD_MODE] = ad4_mode_setup_common,
[ad4_state_manual][AD_INIT] = ad4_init_setup,
[ad4_state_manual][AD_CFG] = ad4_cfg_setup,
[ad4_state_manual][AD_INPUT] = ad4_no_op_setup,
[ad4_state_manual][AD_SUSPEND] = ad4_no_op_setup,
[ad4_state_manual][AD_ASSERTIVE] = ad4_no_op_setup,
[ad4_state_manual][AD_BACKLIGHT] = ad4_no_op_setup,
[ad4_state_manual][AD_STRENGTH] = ad4_strength_setup,
[ad4_state_manual][AD_ROI] = ad4_roi_setup,
[ad4_state_manual][AD_IPC_SUSPEND] = ad4_no_op_setup,
[ad4_state_manual][AD_IPC_RESUME] = ad4_no_op_setup,
[ad4_state_manual][AD_IPC_RESET] = ad4_setup_debug_manual,
};
struct ad4_info {
enum ad4_state state;
u32 completed_ops_mask;
bool ad4_support;
enum ad4_modes mode;
bool is_master;
u32 last_assertive;
u32 cached_assertive;
u32 last_str_inroi;
u32 last_str_outroi;
u64 last_als;
u64 cached_als;
u64 last_bl;
u64 cached_bl;
u32 frame_count;
u32 frmt_mode;
u32 irdx_control_0;
u32 tf_ctrl;
u32 vc_control_0;
struct ad4_roi_info last_roi_cfg;
struct ad4_roi_info cached_roi_cfg;
};
static struct ad4_info info[DSPP_MAX] = {
[DSPP_0] = {ad4_state_idle, 0, true, AD4_OFF, false, 0x80, 0x80},
[DSPP_1] = {ad4_state_idle, 0, true, AD4_OFF, false, 0x80, 0x80},
[DSPP_2] = {ad4_state_max, 0, false, AD4_OFF, false, 0x80, 0x80},
[DSPP_3] = {ad4_state_max, 0, false, AD4_OFF, false, 0x80, 0x80},
};
void sde_setup_dspp_ad4(struct sde_hw_dspp *dspp, void *ad_cfg)
{
int ret = 0;
struct sde_ad_hw_cfg *cfg = ad_cfg;
ret = ad4_params_check(dspp, ad_cfg);
if (ret)
return;
ret = prop_set_func[info[dspp->idx].state][cfg->prop](dspp, ad_cfg);
if (ret)
DRM_ERROR("op failed %d ret %d\n", cfg->prop, ret);
}
int sde_validate_dspp_ad4(struct sde_hw_dspp *dspp, u32 *prop)
{
if (!dspp || !prop) {
DRM_ERROR("invalid params dspp %pK prop %pK\n", dspp, prop);
return -EINVAL;
}
if (*prop >= AD_PROPMAX) {
DRM_ERROR("invalid prop set %d\n", *prop);
return -EINVAL;
}
if (dspp->idx >= DSPP_MAX || !info[dspp->idx].ad4_support) {
DRM_ERROR("ad4 not supported for dspp idx %d\n", dspp->idx);
return -EINVAL;
}
return 0;
}
static int ad4_params_check(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
struct sde_hw_mixer *hw_lm;
if (!dspp || !cfg || !cfg->hw_cfg) {
DRM_ERROR("invalid dspp %pK cfg %pK hw_cfg %pK\n",
dspp, cfg, ((cfg) ? (cfg->hw_cfg) : NULL));
return -EINVAL;
}
if (!cfg->hw_cfg->mixer_info) {
DRM_ERROR("invalid mixed info\n");
return -EINVAL;
}
if (dspp->idx >= DSPP_MAX || !info[dspp->idx].ad4_support) {
DRM_ERROR("ad4 not supported for dspp idx %d\n", dspp->idx);
return -EINVAL;
}
if (cfg->prop >= AD_PROPMAX) {
DRM_ERROR("invalid prop set %d\n", cfg->prop);
return -EINVAL;
}
if (info[dspp->idx].state >= ad4_state_max) {
DRM_ERROR("in max state for dspp idx %d\n", dspp->idx);
return -EINVAL;
}
if (!prop_set_func[info[dspp->idx].state][cfg->prop]) {
DRM_ERROR("prop set not implemented for state %d prop %d\n",
info[dspp->idx].state, cfg->prop);
return -EINVAL;
}
if (!cfg->hw_cfg->num_of_mixers ||
cfg->hw_cfg->num_of_mixers > CRTC_DUAL_MIXERS_ONLY) {
DRM_ERROR("invalid mixer cnt %d\n",
cfg->hw_cfg->num_of_mixers);
return -EINVAL;
}
hw_lm = cfg->hw_cfg->mixer_info;
if (!hw_lm) {
DRM_ERROR("invalid mixer info\n");
return -EINVAL;
}
if (cfg->hw_cfg->num_of_mixers == 1 &&
hw_lm->cfg.out_height != cfg->hw_cfg->displayv &&
hw_lm->cfg.out_width != cfg->hw_cfg->displayh) {
DRM_ERROR("single_lm lmh %d lmw %d displayh %d displayw %d\n",
hw_lm->cfg.out_height, hw_lm->cfg.out_width,
cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
return -EINVAL;
} else if (hw_lm->cfg.out_height != cfg->hw_cfg->displayv &&
hw_lm->cfg.out_width != (cfg->hw_cfg->displayh >> 1)) {
DRM_ERROR("dual_lm lmh %d lmw %d displayh %d displayw %d\n",
hw_lm->cfg.out_height, hw_lm->cfg.out_width,
cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
return -EINVAL;
}
return 0;
}
static int ad4_no_op_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)
{
return 0;
}
static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)
{
u32 in_str = 0, out_str = 0;
struct sde_hw_mixer *hw_lm;
hw_lm = cfg->hw_cfg->mixer_info;
if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer)
/* this AD core is the salve core */
return 0;
in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c);
out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x50);
pr_debug("%s(): AD in strength %d, out strength %d\n", __func__,
in_str, out_str);
return 0;
}
static int ad4_setup_debug_manual(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u32 in_str = 0, out_str = 0;
struct sde_hw_mixer *hw_lm;
hw_lm = cfg->hw_cfg->mixer_info;
if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer)
/* this AD core is the salve core */
return 0;
in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x15c);
out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x160);
pr_debug("%s(): AD in strength = %d, out strength = %d in manual mode\n",
__func__, in_str, out_str);
return 0;
}
static int ad4_mode_setup(struct sde_hw_dspp *dspp, enum ad4_modes mode)
{
u32 blk_offset;
if (mode == AD4_OFF) {
blk_offset = 0x04;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
0x101);
info[dspp->idx].state = ad4_state_idle;
pr_debug("%s(): AD state move to idle\n", __func__);
info[dspp->idx].completed_ops_mask = 0;
/* reset last values to register default */
info[dspp->idx].last_assertive = 0x80;
info[dspp->idx].cached_assertive = U8_MAX;
info[dspp->idx].last_bl = 0xFFFF;
info[dspp->idx].cached_bl = U64_MAX;
info[dspp->idx].last_als = 0x0;
info[dspp->idx].cached_als = U64_MAX;
info[dspp->idx].last_roi_cfg.h_start = 0x0;
info[dspp->idx].last_roi_cfg.h_end = 0xffff;
info[dspp->idx].last_roi_cfg.v_start = 0x0;
info[dspp->idx].last_roi_cfg.v_end = 0xffff;
info[dspp->idx].last_roi_cfg.f_in = 0x400;
info[dspp->idx].last_roi_cfg.f_out = 0x400;
info[dspp->idx].cached_roi_cfg.h_start = U32_MAX;
info[dspp->idx].cached_roi_cfg.h_end = U32_MAX;
info[dspp->idx].cached_roi_cfg.v_start = U32_MAX;
info[dspp->idx].cached_roi_cfg.v_end = U32_MAX;
info[dspp->idx].cached_roi_cfg.f_in = U32_MAX;
info[dspp->idx].cached_roi_cfg.f_out = U32_MAX;
} else {
if (mode == AD4_MANUAL) {
/*vc_control_0 */
blk_offset = 0x138;
SDE_REG_WRITE(&dspp->hw,
dspp->cap->sblk->ad.base + blk_offset, 0);
/* irdx_control_0 */
blk_offset = 0x13c;
SDE_REG_WRITE(&dspp->hw,
dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].irdx_control_0);
}
if (info[dspp->idx].state == ad4_state_idle) {
if (mode == AD4_MANUAL) {
info[dspp->idx].state = ad4_state_manual;
pr_debug("%s(): AD state move to manual\n",
__func__);
} else {
info[dspp->idx].frame_count = 0;
info[dspp->idx].state = ad4_state_startup;
pr_debug("%s(): AD state move to startup\n",
__func__);
}
}
blk_offset = 0x04;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
0x100);
}
return 0;
}
static int ad4_init_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)
{
u32 frame_start, frame_end, proc_start, proc_end;
struct sde_hw_mixer *hw_lm;
u32 blk_offset, tile_ctl, val, i;
u32 off1, off2, off3, off4, off5, off6;
struct drm_msm_ad4_init *init;
if (!cfg->hw_cfg->payload) {
info[dspp->idx].completed_ops_mask &= ~ad4_init;
return 0;
}
if (cfg->hw_cfg->len != sizeof(struct drm_msm_ad4_init)) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(struct drm_msm_ad4_init), cfg->hw_cfg->len,
cfg->hw_cfg->payload);
return -EINVAL;
}
hw_lm = cfg->hw_cfg->mixer_info;
if (cfg->hw_cfg->num_of_mixers == 1) {
frame_start = 0;
frame_end = 0xffff;
proc_start = 0;
proc_end = 0xffff;
tile_ctl = 0;
info[dspp->idx].is_master = true;
} else {
tile_ctl = 0x5;
if (hw_lm->cfg.right_mixer) {
frame_start = (cfg->hw_cfg->displayh >> 1) -
MERGE_WIDTH_RIGHT;
frame_end = cfg->hw_cfg->displayh - 1;
proc_start = (cfg->hw_cfg->displayh >> 1);
proc_end = frame_end;
tile_ctl |= 0x10;
info[dspp->idx].is_master = false;
} else {
frame_start = 0;
frame_end = (cfg->hw_cfg->displayh >> 1) +
MERGE_WIDTH_LEFT;
proc_start = 0;
proc_end = (cfg->hw_cfg->displayh >> 1) - 1;
tile_ctl |= 0x10;
info[dspp->idx].is_master = true;
}
}
init = cfg->hw_cfg->payload;
info[dspp->idx].frmt_mode = (init->init_param_009 & (BIT(14) - 1));
blk_offset = 0xc;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
init->init_param_010);
init->init_param_012 = cfg->hw_cfg->displayv & (BIT(17) - 1);
init->init_param_011 = cfg->hw_cfg->displayh & (BIT(17) - 1);
blk_offset = 0x10;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
((init->init_param_011 << 16) | init->init_param_012));
blk_offset = 0x14;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
tile_ctl);
blk_offset = 0x44;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
((((init->init_param_013) & (BIT(17) - 1)) << 16) |
(init->init_param_014 & (BIT(17) - 1))));
blk_offset = 0x5c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_015 & (BIT(16) - 1)));
blk_offset = 0x60;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_016 & (BIT(8) - 1)));
blk_offset = 0x64;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_017 & (BIT(12) - 1)));
blk_offset = 0x68;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_018 & (BIT(12) - 1)));
blk_offset = 0x6c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_019 & (BIT(12) - 1)));
blk_offset = 0x70;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_020 & (BIT(16) - 1)));
blk_offset = 0x74;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_021 & (BIT(8) - 1)));
blk_offset = 0x78;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_022 & (BIT(8) - 1)));
blk_offset = 0x7c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_023 & (BIT(16) - 1)));
blk_offset = 0x80;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(((init->init_param_024 & (BIT(16) - 1)) << 16) |
((init->init_param_025 & (BIT(16) - 1)))));
blk_offset = 0x84;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(((init->init_param_026 & (BIT(16) - 1)) << 16) |
((init->init_param_027 & (BIT(16) - 1)))));
blk_offset = 0x90;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_028 & (BIT(16) - 1)));
blk_offset = 0x94;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_029 & (BIT(16) - 1)));
blk_offset = 0x98;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(((init->init_param_035 & (BIT(16) - 1)) << 16) |
((init->init_param_030 & (BIT(16) - 1)))));
blk_offset = 0x9c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(((init->init_param_032 & (BIT(16) - 1)) << 16) |
((init->init_param_031 & (BIT(16) - 1)))));
blk_offset = 0xa0;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(((init->init_param_034 & (BIT(16) - 1)) << 16) |
((init->init_param_033 & (BIT(16) - 1)))));
blk_offset = 0xb4;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_036 & (BIT(8) - 1)));
blk_offset = 0xcc;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_037 & (BIT(8) - 1)));
blk_offset = 0xc0;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_038 & (BIT(8) - 1)));
blk_offset = 0xd8;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_039 & (BIT(8) - 1)));
blk_offset = 0xe8;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_040 & (BIT(16) - 1)));
blk_offset = 0xf4;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_041 & (BIT(8) - 1)));
blk_offset = 0x100;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_042 & (BIT(16) - 1)));
blk_offset = 0x10c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_043 & (BIT(8) - 1)));
blk_offset = 0x120;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_044 & (BIT(16) - 1)));
blk_offset = 0x124;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_045 & (BIT(16) - 1)));
blk_offset = 0x128;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_046 & (BIT(1) - 1)));
blk_offset = 0x12c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_047 & (BIT(8) - 1)));
info[dspp->idx].irdx_control_0 = (init->init_param_048 & (BIT(5) - 1));
blk_offset = 0x140;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_049 & (BIT(8) - 1)));
blk_offset = 0x144;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_050 & (BIT(8) - 1)));
blk_offset = 0x148;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(((init->init_param_051 & (BIT(8) - 1)) << 8) |
((init->init_param_052 & (BIT(8) - 1)))));
blk_offset = 0x14c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_053 & (BIT(10) - 1)));
blk_offset = 0x150;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_054 & (BIT(10) - 1)));
blk_offset = 0x154;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_055 & (BIT(8) - 1)));
blk_offset = 0x158;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_056 & (BIT(8) - 1)));
blk_offset = 0x164;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_057 & (BIT(8) - 1)));
blk_offset = 0x168;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_058 & (BIT(4) - 1)));
blk_offset = 0x17c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(frame_start & (BIT(16) - 1)));
blk_offset = 0x180;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(frame_end & (BIT(16) - 1)));
blk_offset = 0x184;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(proc_start & (BIT(16) - 1)));
blk_offset = 0x188;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(proc_end & (BIT(16) - 1)));
blk_offset = 0x18c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_059 & (BIT(4) - 1)));
blk_offset = 0x190;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(((init->init_param_061 & (BIT(8) - 1)) << 8) |
((init->init_param_060 & (BIT(8) - 1)))));
blk_offset = 0x194;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_062 & (BIT(10) - 1)));
blk_offset = 0x1a0;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_063 & (BIT(10) - 1)));
blk_offset = 0x1a4;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_064 & (BIT(10) - 1)));
blk_offset = 0x1a8;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_065 & (BIT(10) - 1)));
blk_offset = 0x1ac;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_066 & (BIT(8) - 1)));
blk_offset = 0x1b0;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_067 & (BIT(8) - 1)));
blk_offset = 0x1b4;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_068 & (BIT(6) - 1)));
blk_offset = 0x460;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_069 & (BIT(16) - 1)));
blk_offset = 0x464;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_070 & (BIT(10) - 1)));
blk_offset = 0x468;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_071 & (BIT(10) - 1)));
blk_offset = 0x46c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_072 & (BIT(10) - 1)));
blk_offset = 0x470;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_073 & (BIT(8) - 1)));
blk_offset = 0x474;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_074 & (BIT(10) - 1)));
blk_offset = 0x478;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(init->init_param_075 & (BIT(10) - 1)));
off1 = 0x1c0;
off2 = 0x210;
off3 = 0x260;
off4 = 0x2b0;
off5 = 0x380;
off6 = 0x3d0;
for (i = 0; i < AD4_LUT_GRP0_SIZE - 1; i = i + 2) {
val = (init->init_param_001[i] & (BIT(16) - 1));
val |= ((init->init_param_001[i + 1] & (BIT(16) - 1))
<< 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off1, val);
off1 += 4;
val = (init->init_param_002[i] & (BIT(16) - 1));
val |= ((init->init_param_002[i + 1] & (BIT(16) - 1))
<< 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off2, val);
off2 += 4;
val = (init->init_param_003[i] & (BIT(16) - 1));
val |= ((init->init_param_003[i + 1] & (BIT(16) - 1))
<< 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off3, val);
off3 += 4;
val = (init->init_param_004[i] & (BIT(16) - 1));
val |= ((init->init_param_004[i + 1] & (BIT(16) - 1))
<< 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off4, val);
off4 += 4;
val = (init->init_param_007[i] & (BIT(16) - 1));
val |= ((init->init_param_007[i + 1] &
(BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off5, val);
off5 += 4;
val = (init->init_param_008[i] & (BIT(12) - 1));
val |= ((init->init_param_008[i + 1] &
(BIT(12) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off6, val);
off6 += 4;
}
/* write last index data */
i = AD4_LUT_GRP0_SIZE - 1;
val = ((init->init_param_001[i] & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off1, val);
val = ((init->init_param_002[i] & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off2, val);
val = ((init->init_param_003[i] & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off3, val);
val = ((init->init_param_004[i] & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off4, val);
val = ((init->init_param_007[i] & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off5, val);
val = ((init->init_param_008[i] & (BIT(12) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off6, val);
off1 = 0x300;
off2 = 0x340;
for (i = 0; i < AD4_LUT_GRP1_SIZE; i = i + 2) {
val = (init->init_param_005[i] & (BIT(16) - 1));
val |= ((init->init_param_005[i + 1] &
(BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off1, val);
off1 += 4;
val = (init->init_param_006[i] & (BIT(16) - 1));
val |= ((init->init_param_006[i + 1] & (BIT(16) - 1))
<< 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + off2, val);
off2 += 4;
}
return 0;
}
static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg)
{
u32 blk_offset, val;
struct drm_msm_ad4_cfg *ad_cfg;
if (!cfg->hw_cfg->payload) {
info[dspp->idx].completed_ops_mask &= ~ad4_cfg;
return 0;
}
if (cfg->hw_cfg->len != sizeof(struct drm_msm_ad4_cfg)) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(struct drm_msm_ad4_cfg), cfg->hw_cfg->len,
cfg->hw_cfg->payload);
return -EINVAL;
}
ad_cfg = cfg->hw_cfg->payload;
blk_offset = 0x20;
val = (ad_cfg->cfg_param_005 & (BIT(8) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0x24;
val = (ad_cfg->cfg_param_006 & (BIT(7) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
info[dspp->idx].tf_ctrl = (ad_cfg->cfg_param_008 & (BIT(8) - 1));
blk_offset = 0x38;
val = (ad_cfg->cfg_param_009 & (BIT(10) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0x3c;
val = (ad_cfg->cfg_param_010 & (BIT(12) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0x88;
val = (ad_cfg->cfg_param_013 & (BIT(8) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_014 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0xa4;
val = (ad_cfg->cfg_param_015 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_016 & (BIT(10) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_017 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_018 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0xc4;
val = (ad_cfg->cfg_param_019 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_020 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0xb8;
val = (ad_cfg->cfg_param_021 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_022 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0xd0;
val = (ad_cfg->cfg_param_023 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_024 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0xdc;
val = (ad_cfg->cfg_param_025 & (BIT(16) - 1));
val |= ((ad_cfg->cfg_param_026 & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_027 & (BIT(16) - 1));
val |= ((ad_cfg->cfg_param_028 & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_029 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0xec;
val = (ad_cfg->cfg_param_030 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_031 & (BIT(12) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0xf8;
val = (ad_cfg->cfg_param_032 & (BIT(10) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_033 & (BIT(8) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0x104;
val = (ad_cfg->cfg_param_034 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_035 & (BIT(12) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0x110;
val = (ad_cfg->cfg_param_036 & (BIT(12) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_037 & (BIT(12) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_038 & (BIT(8) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_039 & (BIT(8) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0x134;
val = (ad_cfg->cfg_param_040 & (BIT(12) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
info[dspp->idx].vc_control_0 = (ad_cfg->cfg_param_041 & (BIT(7) - 1));
blk_offset = 0x16c;
val = (ad_cfg->cfg_param_044 & (BIT(8) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_045 & (BIT(8) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (ad_cfg->cfg_param_046 & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
return 0;
}
static int ad4_input_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u64 *val, als;
u32 blk_offset;
if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
return -EINVAL;
}
blk_offset = 0x28;
if (cfg->hw_cfg->payload) {
val = cfg->hw_cfg->payload;
} else {
als = 0;
val = &als;
}
info[dspp->idx].last_als = (*val & (BIT(16) - 1));
info[dspp->idx].completed_ops_mask |= ad4_input;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].last_als);
return 0;
}
static int ad4_roi_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret = 0;
u32 blk_offset = 0, val = 0;
struct ad4_roi_info roi_cfg = {};
ret = ad4_roi_coordinate_offset(cfg->hw_cfg, &roi_cfg);
if (ret) {
DRM_ERROR("params invalid\n");
return -EINVAL;
}
info[dspp->idx].last_roi_cfg = roi_cfg;
/*roi h start and end*/
blk_offset = 0x18;
val = (info[dspp->idx].last_roi_cfg.h_end & (BIT(16) - 1));
val |= ((info[dspp->idx].last_roi_cfg.h_start & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
/*roi v start and end*/
blk_offset += 4;
val = (info[dspp->idx].last_roi_cfg.v_end & (BIT(16) - 1));
val |= ((info[dspp->idx].last_roi_cfg.v_start & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
/*roi factor in and out*/
blk_offset = 0x40;
val = ((info[dspp->idx].last_roi_cfg.f_in & (BIT(16) - 1)) << 16);
val |= (info[dspp->idx].last_roi_cfg.f_out & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
return ret;
}
static int ad4_roi_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret = 0;
struct ad4_roi_info roi_cfg = {};
ret = ad4_roi_coordinate_offset(cfg->hw_cfg, &roi_cfg);
if (ret) {
DRM_ERROR("params invalid\n");
return -EINVAL;
}
info[dspp->idx].cached_roi_cfg = roi_cfg;
return 0;
}
static int ad4_roi_coordinate_offset(struct sde_hw_cp_cfg *hw_cfg,
struct ad4_roi_info *output)
{
struct sde_hw_mixer *hw_lm = hw_cfg->mixer_info;
struct drm_msm_ad4_roi_cfg *roi = NULL;
if (!hw_cfg->payload) {
output->h_start = 0x0;
output->h_end = hw_cfg->displayh;
output->v_start = 0x0;
output->v_end = hw_cfg->displayv;
output->f_in = 0x400;
output->f_out = 0x400;
return 0;
}
if (hw_cfg->len != sizeof(struct drm_msm_ad4_roi_cfg)) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(struct drm_msm_ad4_roi_cfg), hw_cfg->len,
hw_cfg->payload);
return -EINVAL;
}
roi = (struct drm_msm_ad4_roi_cfg *)hw_cfg->payload;
if (roi->h_x >= hw_cfg->displayh || roi->v_x >= hw_cfg->displayv) {
DRM_ERROR("invalid roi=[%u,%u,%u,%u], display=[%u,%u]\n",
roi->h_x, roi->h_y, roi->v_x, roi->v_y,
hw_cfg->displayh, hw_cfg->displayv);
return -EINVAL;
}
if (roi->h_x >= roi->h_y || roi->v_x >= roi->v_y) {
DRM_ERROR("invalid roi=[%u,%u,%u,%u], display=[%u,%u]\n",
roi->h_x, roi->h_y, roi->v_x, roi->v_y,
hw_cfg->displayh, hw_cfg->displayv);
return -EINVAL;
}
if (roi->h_y > hw_cfg->displayh)
roi->h_y = hw_cfg->displayh;
if (roi->v_y > hw_cfg->displayv)
roi->v_y = hw_cfg->displayv;
/* single dspp cfg */
output->h_start = roi->h_x;
output->h_end = roi->h_y;
output->v_start = roi->v_x;
output->v_end = roi->v_y;
output->f_in = roi->factor_in;
output->f_out = roi->factor_out;
/* check whether dual dspp */
if (hw_cfg->num_of_mixers != 2)
return 0;
if (roi->h_y <= hw_lm->cfg.out_width) {
if (hw_lm->cfg.right_mixer) {
/* the region on the left of screen, clear right info */
output->h_start = 0;
output->h_end = 0;
output->v_start = 0;
output->v_end = 0;
}
} else if (roi->h_x < hw_lm->cfg.out_width) {
/* the region occupy both sides of screen: left and right */
if (hw_lm->cfg.right_mixer) {
output->h_start = 0;
output->h_end -= (hw_lm->cfg.out_width -
MERGE_WIDTH_RIGHT);
} else {
output->h_end = hw_lm->cfg.out_width;
}
} else {
/* the region on the right of the screen*/
if (hw_lm->cfg.right_mixer) {
output->h_start -= (hw_lm->cfg.out_width -
MERGE_WIDTH_RIGHT);
output->h_end -= (hw_lm->cfg.out_width -
MERGE_WIDTH_RIGHT);
} else {
output->h_start = 0;
output->h_end = 0;
output->v_start = 0;
output->v_end = 0;
}
}
return 0;
}
static int ad4_suspend_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
info[dspp->idx].state = ad4_state_idle;
pr_debug("%s(): AD state move to idle\n", __func__);
info[dspp->idx].completed_ops_mask = 0;
return 0;
}
static int ad4_mode_setup_common(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
if (cfg->hw_cfg->len != sizeof(u64) || !cfg->hw_cfg->payload) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
return -EINVAL;
}
info[dspp->idx].mode = *((enum ad4_modes *)
(cfg->hw_cfg->payload));
info[dspp->idx].completed_ops_mask |= ad4_mode;
if (AD_STATE_READY(info[dspp->idx].completed_ops_mask) ||
info[dspp->idx].mode == AD4_OFF)
ad4_mode_setup(dspp, info[dspp->idx].mode);
return 0;
}
static int ad4_init_setup_idle(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret;
u32 blk_offset;
if (!cfg->hw_cfg->payload) {
info[dspp->idx].completed_ops_mask &= ~ad4_init;
return 0;
}
ret = ad4_init_setup(dspp, cfg);
if (ret)
return ret;
/* enable memory initialization*/
/* frmt mode */
blk_offset = 0x8;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(info[dspp->idx].frmt_mode & 0x1fff));
/* memory init */
blk_offset = 0x450;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0x1);
/* enforce 0 initial strength when powering up AD config */
/* irdx_control_0 */
blk_offset = 0x13c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0x6);
info[dspp->idx].completed_ops_mask |= ad4_init;
if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
ad4_mode_setup(dspp, info[dspp->idx].mode);
return 0;
}
static int ad4_init_setup_run(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret;
u32 blk_offset;
if (!cfg->hw_cfg->payload) {
info[dspp->idx].completed_ops_mask &= ~ad4_init;
return 0;
}
ret = ad4_init_setup(dspp, cfg);
if (ret)
return ret;
/* disable memory initialization*/
/* frmt mode */
blk_offset = 0x8;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(info[dspp->idx].frmt_mode | 0x2000));
/* no need to explicitly set memory initialization sequence,
* since AD hw were not powered off.
*/
/* irdx_control_0 */
blk_offset = 0x13c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].irdx_control_0);
return 0;
}
static int ad4_init_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret;
u32 blk_offset;
if (!cfg->hw_cfg->payload) {
info[dspp->idx].completed_ops_mask &= ~ad4_init;
return 0;
}
ret = ad4_init_setup(dspp, cfg);
if (ret)
return ret;
/* no need to explicitly set memory initialization sequence,
* since register reset values are the correct configuration
*/
/* frmt mode */
blk_offset = 0x8;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(info[dspp->idx].frmt_mode | 0x2000));
/* irdx_control_0 */
blk_offset = 0x13c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].irdx_control_0);
info[dspp->idx].completed_ops_mask |= ad4_init;
if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
ad4_mode_setup(dspp, info[dspp->idx].mode);
return 0;
}
static int ad4_cfg_setup_idle(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret;
u32 blk_offset;
if (!cfg->hw_cfg->payload) {
info[dspp->idx].completed_ops_mask &= ~ad4_cfg;
return 0;
}
ret = ad4_cfg_setup(dspp, cfg);
if (ret)
return ret;
/* enforce 0 initial strength when powering up AD config */
/* assertiveness */
blk_offset = 0x30;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0x0);
/* tf control */
blk_offset = 0x34;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0x55);
/* vc_control_0 */
blk_offset = 0x138;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].vc_control_0);
info[dspp->idx].completed_ops_mask |= ad4_cfg;
if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
ad4_mode_setup(dspp, info[dspp->idx].mode);
return 0;
}
static int ad4_cfg_setup_run(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret;
u32 blk_offset;
if (!cfg->hw_cfg->payload) {
info[dspp->idx].completed_ops_mask &= ~ad4_cfg;
return 0;
}
ret = ad4_cfg_setup(dspp, cfg);
if (ret)
return ret;
/* assertiveness */
blk_offset = 0x30;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].last_assertive);
/* tf control */
blk_offset = 0x34;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].tf_ctrl);
/* vc_control_0 */
blk_offset = 0x138;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].vc_control_0);
return 0;
}
static int ad4_cfg_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret;
u32 blk_offset;
if (!cfg->hw_cfg->payload) {
info[dspp->idx].completed_ops_mask &= ~ad4_cfg;
return 0;
}
ret = ad4_cfg_setup(dspp, cfg);
if (ret)
return ret;
/* assertiveness */
blk_offset = 0x30;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].last_assertive);
info[dspp->idx].completed_ops_mask |= ad4_cfg;
if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
ad4_mode_setup(dspp, info[dspp->idx].mode);
return 0;
}
static int ad4_input_setup_idle(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret;
ret = ad4_input_setup(dspp, cfg);
if (ret)
return ret;
info[dspp->idx].completed_ops_mask |= ad4_input;
if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
ad4_mode_setup(dspp, info[dspp->idx].mode);
return 0;
}
static int ad4_input_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u64 *val, als;
u32 blk_offset;
if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
return -EINVAL;
}
blk_offset = 0x28;
if (cfg->hw_cfg->payload) {
val = cfg->hw_cfg->payload;
} else {
als = 0;
val = &als;
}
info[dspp->idx].cached_als = *val & (BIT(16) - 1);
info[dspp->idx].completed_ops_mask |= ad4_input;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].last_als);
if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
ad4_mode_setup(dspp, info[dspp->idx].mode);
return 0;
}
static int ad4_assertive_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u64 *val, assertive;
u32 blk_offset;
if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
return -EINVAL;
}
blk_offset = 0x30;
if (cfg->hw_cfg->payload) {
val = cfg->hw_cfg->payload;
} else {
assertive = 0;
val = &assertive;
}
info[dspp->idx].last_assertive = *val & (BIT(8) - 1);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
(info[dspp->idx].last_assertive));
return 0;
}
static int ad4_assertive_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u64 *val, assertive;
u32 blk_offset;
if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
return -EINVAL;
}
blk_offset = 0x30;
if (cfg->hw_cfg->payload) {
val = cfg->hw_cfg->payload;
} else {
assertive = 0;
val = &assertive;
}
info[dspp->idx].cached_assertive = *val & (BIT(8) - 1);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].last_assertive);
return 0;
}
static int ad4_backlight_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u64 *val, bl;
u32 blk_offset;
if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
return -EINVAL;
}
blk_offset = 0x2c;
if (cfg->hw_cfg->payload) {
val = cfg->hw_cfg->payload;
} else {
bl = 0;
val = &bl;
}
info[dspp->idx].last_bl = *val & (BIT(16) - 1);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].last_bl);
return 0;
}
static int ad4_backlight_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u64 *val, bl;
u32 blk_offset;
if (cfg->hw_cfg->len != sizeof(u64) && cfg->hw_cfg->payload) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(u64), cfg->hw_cfg->len, cfg->hw_cfg->payload);
return -EINVAL;
}
blk_offset = 0x2c;
if (cfg->hw_cfg->payload) {
val = cfg->hw_cfg->payload;
} else {
bl = 0;
val = &bl;
}
info[dspp->idx].cached_bl = *val & (BIT(16) - 1);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].last_bl);
return 0;
}
void sde_read_intr_resp_ad4(struct sde_hw_dspp *dspp, u32 event,
u32 *resp_in, u32 *resp_out)
{
if (!dspp || !resp_in || !resp_out) {
DRM_ERROR("invalid params dspp %pK resp_in %pK resp_out %pK\n",
dspp, resp_in, resp_out);
return;
}
switch (event) {
case AD4_IN_OUT_BACKLIGHT:
*resp_in = SDE_REG_READ(&dspp->hw,
dspp->cap->sblk->ad.base + 0x2c);
*resp_out = SDE_REG_READ(&dspp->hw,
dspp->cap->sblk->ad.base + 0x48);
pr_debug("%s(): AD4 input BL %u, output BL %u\n", __func__,
(*resp_in), (*resp_out));
break;
default:
break;
}
}
static int ad4_ipc_suspend_setup_run(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u32 in_str = 0, out_str = 0, i = 0;
struct sde_hw_mixer *hw_lm;
hw_lm = cfg->hw_cfg->mixer_info;
if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer) {
/* this AD core is the salve core */
for (i = DSPP_0; i < DSPP_MAX; i++) {
if (info[i].is_master) {
in_str = info[i].last_str_inroi;
out_str = info[i].last_str_outroi;
break;
}
}
} else {
in_str = SDE_REG_READ(&dspp->hw,
dspp->cap->sblk->ad.base + 0x4c);
out_str = SDE_REG_READ(&dspp->hw,
dspp->cap->sblk->ad.base + 0x50);
pr_debug("%s(): AD in strength %d, out %d\n", __func__,
in_str, out_str);
}
info[dspp->idx].last_str_inroi = in_str;
info[dspp->idx].last_str_outroi = out_str;
info[dspp->idx].state = ad4_state_ipcs;
pr_debug("%s(): AD state move to ipcs\n", __func__);
return 0;
}
static int ad4_ipc_resume_setup_ipcs(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u32 blk_offset, val;
info[dspp->idx].frame_count = 0;
info[dspp->idx].state = ad4_state_ipcr;
pr_debug("%s(): AD state move to ipcr\n", __func__);
/* no need to rewrite frmt_mode bit 13 and mem_init,
* since the default register values are exactly what
* we wanted.
*/
/* ipc resume with manual strength */
/* tf control */
blk_offset = 0x34;
val = (0x55 & (BIT(8) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
/* set roi config */
blk_offset = 0x18;
val = (info[dspp->idx].last_roi_cfg.h_end & (BIT(16) - 1));
val |= ((info[dspp->idx].last_roi_cfg.h_start & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (info[dspp->idx].last_roi_cfg.v_end & (BIT(16) - 1));
val |= ((info[dspp->idx].last_roi_cfg.v_start & (BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0x40;
val = ((info[dspp->idx].last_roi_cfg.f_in & (BIT(16) - 1)) << 16);
val |= (info[dspp->idx].last_roi_cfg.f_out & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
/* set manual strength */
blk_offset = 0x15c;
val = (info[dspp->idx].last_str_inroi & (BIT(10) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0x160;
val = (info[dspp->idx].last_str_outroi & (BIT(10) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
/* enable manual mode */
blk_offset = 0x138;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0);
return 0;
}
static int ad4_ipc_suspend_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
info[dspp->idx].state = ad4_state_ipcs;
pr_debug("%s(): AD state move to ipcs\n", __func__);
return 0;
}
static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret;
u32 in_str = 0, out_str = 0, i = 0;
struct sde_hw_mixer *hw_lm;
/* Read AD calculator strength output during the 2 frames of manual
* strength mode, and assign the strength output to last_str
* when frame count reaches AD_IPC_FRAME_COUNT to avoid flickers
* caused by strength was not converged before entering IPC mode
*/
hw_lm = cfg->hw_cfg->mixer_info;
if ((cfg->hw_cfg->num_of_mixers == 2) && hw_lm->cfg.right_mixer) {
/* this AD core is the salve core */
for (i = DSPP_0; i < DSPP_MAX; i++) {
if (info[i].is_master) {
in_str = info[i].last_str_inroi;
out_str = info[i].last_str_outroi;
break;
}
}
} else {
in_str = SDE_REG_READ(&dspp->hw,
dspp->cap->sblk->ad.base + 0x4c);
out_str = SDE_REG_READ(&dspp->hw,
dspp->cap->sblk->ad.base + 0x50);
pr_debug("%s(): AD in strength %d, out %d\n", __func__,
in_str, out_str);
}
if (info[dspp->idx].frame_count == AD_IPC_FRAME_COUNT) {
info[dspp->idx].state = ad4_state_run;
pr_debug("%s(): AD state move to run\n", __func__);
info[dspp->idx].last_str_inroi = in_str;
info[dspp->idx].last_str_outroi = out_str;
ret = ad4_cfg_ipc_reset(dspp, cfg);
if (ret)
return ret;
} else {
info[dspp->idx].frame_count++;
}
return 0;
}
static int ad4_cfg_ipc_reset(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u32 blk_offset, val = 0;
/* revert manual strength */
/* tf control */
blk_offset = 0x34;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].tf_ctrl);
/* vc_control_0 */
blk_offset = 0x138;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].vc_control_0);
/* reset cached ALS, backlight and assertiveness */
if (info[dspp->idx].cached_als != U64_MAX) {
SDE_REG_WRITE(&dspp->hw,
dspp->cap->sblk->ad.base + 0x28,
info[dspp->idx].cached_als);
info[dspp->idx].last_als = info[dspp->idx].cached_als;
info[dspp->idx].cached_als = U64_MAX;
}
if (info[dspp->idx].cached_bl != U64_MAX) {
SDE_REG_WRITE(&dspp->hw,
dspp->cap->sblk->ad.base + 0x2c,
info[dspp->idx].cached_bl);
info[dspp->idx].last_bl = info[dspp->idx].cached_bl;
info[dspp->idx].cached_bl = U64_MAX;
}
if (info[dspp->idx].cached_assertive != U8_MAX) {
SDE_REG_WRITE(&dspp->hw,
dspp->cap->sblk->ad.base + 0x30,
info[dspp->idx].cached_assertive);
info[dspp->idx].last_assertive =
info[dspp->idx].cached_assertive;
info[dspp->idx].cached_assertive = U8_MAX;
}
/*reset cached roi config*/
if (info[dspp->idx].cached_roi_cfg.h_start != U32_MAX) {
blk_offset = 0x18;
val = (info[dspp->idx].cached_roi_cfg.h_end & (BIT(16) - 1));
val |= ((info[dspp->idx].cached_roi_cfg.h_start &
(BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw,
dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (info[dspp->idx].cached_roi_cfg.v_end & (BIT(16) - 1));
val |= ((info[dspp->idx].cached_roi_cfg.v_start &
(BIT(16) - 1)) << 16);
SDE_REG_WRITE(&dspp->hw,
dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset = 0x40;
val = ((info[dspp->idx].cached_roi_cfg.f_in &
(BIT(16) - 1)) << 16);
val |= (info[dspp->idx].cached_roi_cfg.f_out & (BIT(16) - 1));
SDE_REG_WRITE(&dspp->hw,
dspp->cap->sblk->ad.base + blk_offset, val);
info[dspp->idx].last_roi_cfg = info[dspp->idx].cached_roi_cfg;
info[dspp->idx].cached_roi_cfg.h_start = U32_MAX;
info[dspp->idx].cached_roi_cfg.h_end = U32_MAX;
info[dspp->idx].cached_roi_cfg.v_start = U32_MAX;
info[dspp->idx].cached_roi_cfg.v_end = U32_MAX;
info[dspp->idx].cached_roi_cfg.f_in = U32_MAX;
info[dspp->idx].cached_roi_cfg.f_out = U32_MAX;
}
return 0;
}
static int ad4_ipc_reset_setup_startup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u32 blk_offset;
if (info[dspp->idx].frame_count == AD_IPC_FRAME_COUNT) {
info[dspp->idx].state = ad4_state_run;
pr_debug("%s(): AD state move to run\n", __func__);
/* revert enforce 0 initial strength */
/* irdx_control_0 */
blk_offset = 0x13c;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].irdx_control_0);
/* assertiveness */
blk_offset = 0x30;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].last_assertive);
/* tf control */
blk_offset = 0x34;
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset,
info[dspp->idx].tf_ctrl);
} else {
info[dspp->idx].frame_count++;
}
return 0;
}
static int ad4_strength_setup(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
u64 in_str = 0, out_str = 0, val;
u32 blk_offset = 0x15c;
struct drm_msm_ad4_manual_str_cfg *str_cfg = NULL;
if (cfg->hw_cfg->payload && (cfg->hw_cfg->len !=
sizeof(struct drm_msm_ad4_manual_str_cfg))) {
DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n",
sizeof(struct drm_msm_ad4_manual_str_cfg),
cfg->hw_cfg->len, cfg->hw_cfg->payload);
return -EINVAL;
}
if (cfg->hw_cfg->payload) {
str_cfg = (struct drm_msm_ad4_manual_str_cfg *)
cfg->hw_cfg->payload;
in_str = str_cfg->in_str;
out_str = str_cfg->out_str;
}
/* set manual strength */
info[dspp->idx].completed_ops_mask |= ad4_strength;
val = (in_str & (BIT(10) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
blk_offset += 4;
val = (out_str & (BIT(10) - 1));
SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val);
return 0;
}
static int ad4_strength_setup_idle(struct sde_hw_dspp *dspp,
struct sde_ad_hw_cfg *cfg)
{
int ret;
ret = ad4_strength_setup(dspp, cfg);
if (ret)
return ret;
if (AD_STATE_READY(info[dspp->idx].completed_ops_mask))
ad4_mode_setup(dspp, info[dspp->idx].mode);
return 0;
}