Files
android_kernel_samsung_sm86…/msm/sde/sde_hw_ad4.c
Narendra Muppalla 3709853456 Display drivers kernel project initial snapshot
This change brings msm display driver including sde,
dp, dsi, rotator, dsi pll and dp pll from base 4.19 kernel
project. It is first source code snapshot from base kernel project.

Change-Id: Iec864c064ce5ea04e170f24414c728684002f284
Signed-off-by: Narendra Muppalla <NarendraM@codeaurora.org>
2019-04-14 22:20:59 -07:00

1772 regels
54 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2019, 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) {
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;
}