disp: msm: sde: add support for hardware based rounded corner

Add support for hardware based rounded corner part of
color processing framework.

Change-Id: Ie05c5ecba6bd0323d1c8fd6949e12cec1f56b477
Signed-off-by: Anjaneya Prasad Musunuri <aprasad@codeaurora.org>
This commit is contained in:
Anjaneya Prasad Musunuri committed 2021-06-18 14:58:40 +05:30
1 parent 345c21e7d4
commit 4d21a3502a
17 files changed
+2156 -62

No files matched your search

+1
View File
@@ -70,6 +70,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \
sde/sde_hw_qdss.o \
sde_dbg.o \
sde_dbg_evtlog.o \
sde/sde_hw_rc.o \
msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \
sde/sde_encoder_phys_wb.o \
+2 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -138,6 +138,7 @@ enum msm_mdp_crtc_property {
CRTC_PROP_DEST_SCALER_LUT_ED,
CRTC_PROP_DEST_SCALER_LUT_CIR,
CRTC_PROP_DEST_SCALER_LUT_SEP,
CRTC_PROP_DSPP_INFO,
/* # of blob properties */
CRTC_PROP_BLOBCOUNT,
+652 -32
View File
@@ -1,11 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/dma-buf.h>
#include <linux/string.h>
#include <drm/msm_drm_pp.h>
#include "sde_color_processing.h"
#include "sde_kms.h"
@@ -29,6 +30,7 @@ struct sde_cp_node {
struct list_head active_list;
struct list_head dirty_list;
bool is_dspp_feature;
bool lm_flush_override;
u32 prop_blob_sz;
struct sde_irq_callback *irq;
};
@@ -55,6 +57,8 @@ static void dspp_ad_install_property(struct drm_crtc *crtc);
static void dspp_ltm_install_property(struct drm_crtc *crtc);
static void dspp_rc_install_property(struct drm_crtc *crtc);
static void dspp_vlut_install_property(struct drm_crtc *crtc);
static void dspp_gamut_install_property(struct drm_crtc *crtc);
@@ -111,6 +115,7 @@ do { \
func[SDE_DSPP_IGC] = dspp_igc_install_property; \
func[SDE_DSPP_HIST] = dspp_hist_install_property; \
func[SDE_DSPP_DITHER] = dspp_dither_install_property; \
func[SDE_DSPP_RC] = dspp_rc_install_property; \
} while (0)
typedef void (*lm_prop_install_func_t)(struct drm_crtc *crtc);
@@ -122,7 +127,7 @@ static void lm_gc_install_property(struct drm_crtc *crtc);
#define setup_lm_prop_install_funcs(func) \
(func[SDE_MIXER_GC] = lm_gc_install_property)
enum {
enum sde_cp_crtc_features {
/* Append new DSPP features before SDE_CP_CRTC_DSPP_MAX */
/* DSPP Features start */
SDE_CP_CRTC_DSPP_IGC,
@@ -158,6 +163,7 @@ enum {
SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF2,
SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3,
SDE_CP_CRTC_DSPP_LTM_VLUT,
SDE_CP_CRTC_DSPP_RC_MASK,
SDE_CP_CRTC_DSPP_MAX,
/* DSPP features end */
@@ -169,12 +175,52 @@ enum {
SDE_CP_CRTC_MAX_FEATURES,
};
enum sde_cp_crtc_pu_features {
SDE_CP_CRTC_DSPP_RC_PU,
SDE_CP_CRTC_MAX_PU_FEATURES,
};
typedef void (*dspp_cap_update_func_t)(struct sde_crtc *crtc,
struct sde_kms_info *info);
enum sde_dspp_caps_features {
SDE_CP_RC_CAPS,
SDE_CP_CAPS_MAX,
};
static void rc_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info);
static dspp_cap_update_func_t dspp_cap_update_func[SDE_CP_CAPS_MAX];
#define setup_dspp_caps_funcs(func) \
(func[SDE_CP_RC_CAPS] = rc_caps_update)
static void _sde_cp_crtc_enable_hist_irq(struct sde_crtc *sde_crtc);
typedef int (*set_feature_wrapper)(struct sde_hw_dspp *hw_dspp,
typedef int (*feature_wrapper)(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *hw_crtc);
static struct sde_kms *get_kms(struct drm_crtc *crtc)
{
struct msm_drm_private *priv = crtc->dev->dev_private;
return to_sde_kms(priv->kms);
}
static void update_pu_feature_enable(struct sde_crtc *sde_crtc,
u32 feature, bool enable)
{
if (!sde_crtc || feature > SDE_CP_CRTC_MAX_PU_FEATURES) {
DRM_ERROR("invalid args feature %d\n", feature);
return;
}
if (enable)
sde_crtc->cp_pu_feature_mask |= BIT(feature);
else
sde_crtc->cp_pu_feature_mask &= ~BIT(feature);
}
static int set_dspp_vlut_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *hw_crtc)
@@ -655,9 +701,127 @@ static int set_ltm_hist_crtl_feature(struct sde_hw_dspp *hw_dspp,
return ret;
}
set_feature_wrapper crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
static int check_rc_mask_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
#define setup_crtc_feature_wrappers(wrappers) \
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments");
return -EINVAL;
}
if (!hw_dspp->ops.validate_rc_mask) {
DRM_ERROR("invalid rc ops");
return -EINVAL;
}
ret = hw_dspp->ops.validate_rc_mask(hw_dspp, hw_cfg);
if (ret)
DRM_ERROR("failed to validate rc mask %d", ret);
return ret;
}
static int set_rc_mask_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments\n");
return -EINVAL;
}
if (!hw_dspp->ops.setup_rc_mask || !hw_dspp->ops.setup_rc_data) {
DRM_ERROR("invalid rc ops\n");
return -EINVAL;
}
DRM_DEBUG_DRIVER("dspp %d setup mask for rc instance %u\n",
hw_dspp->idx, hw_dspp->cap->sblk->rc.idx);
ret = hw_dspp->ops.setup_rc_mask(hw_dspp, hw_cfg);
if (ret) {
DRM_ERROR("failed to setup rc mask, ret %d\n", ret);
goto exit;
}
/* rc data should be programmed once if dspp are in multi-pipe mode */
if (hw_dspp->cap->sblk->rc.idx % hw_cfg->num_of_mixers == 0) {
ret = hw_dspp->ops.setup_rc_data(hw_dspp, hw_cfg);
if (ret) {
DRM_ERROR("failed to setup rc data, ret %d\n", ret);
goto exit;
}
}
update_pu_feature_enable(sde_crtc, SDE_CP_CRTC_DSPP_RC_PU,
hw_cfg->payload != NULL);
exit:
return ret;
}
static int set_rc_pu_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments\n");
return -EINVAL;
}
if (!hw_dspp->ops.setup_rc_pu_roi) {
DRM_ERROR("invalid rc ops\n");
return -EINVAL;
}
DRM_DEBUG_DRIVER("dspp %d setup pu roi for rc instance %u\n",
hw_dspp->idx, hw_dspp->cap->sblk->rc.idx);
ret = hw_dspp->ops.setup_rc_pu_roi(hw_dspp, hw_cfg);
if (ret < 0)
DRM_ERROR("failed to setup rc pu roi, ret %d\n", ret);
return ret;
}
static int check_rc_pu_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments\n");
return -EINVAL;
}
if (!hw_dspp->ops.validate_rc_pu_roi) {
SDE_ERROR("invalid rc ops");
return -EINVAL;
}
ret = hw_dspp->ops.validate_rc_pu_roi(hw_dspp, hw_cfg);
if (ret)
SDE_ERROR("failed to validate rc pu roi, ret %d", ret);
return ret;
}
feature_wrapper check_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
#define setup_check_crtc_feature_wrappers(wrappers) \
do { \
memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = check_rc_mask_feature; \
} while (0)
feature_wrapper set_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
#define setup_set_crtc_feature_wrappers(wrappers) \
do { \
memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_VLUT] = set_dspp_vlut_feature; \
@@ -697,6 +861,21 @@ do { \
wrappers[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF2] = set_ltm_queue_buf_feature; \
wrappers[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3] = set_ltm_queue_buf_feature; \
wrappers[SDE_CP_CRTC_DSPP_LTM_HIST_CTL] = set_ltm_hist_crtl_feature; \
wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = set_rc_mask_feature; \
} while (0)
feature_wrapper set_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
#define setup_set_crtc_pu_feature_wrappers(wrappers) \
do { \
memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_RC_PU] = set_rc_pu_feature; \
} while (0)
feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
#define setup_check_crtc_pu_feature_wrappers(wrappers) \
do { \
memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_RC_PU] = check_rc_pu_feature; \
} while (0)
#define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \
@@ -886,12 +1065,6 @@ static int sde_cp_enable_crtc_property(struct drm_crtc *crtc,
return ret;
}
static struct sde_kms *get_kms(struct drm_crtc *crtc)
{
struct msm_drm_private *priv = crtc->dev->dev_private;
return to_sde_kms(priv->kms);
}
static void sde_cp_crtc_prop_attach(struct sde_cp_prop_attach *prop_attach)
{
@@ -938,6 +1111,9 @@ void sde_cp_crtc_init(struct drm_crtc *crtc)
if (IS_ERR(sde_crtc->hist_blob))
sde_crtc->hist_blob = NULL;
msm_property_install_blob(&sde_crtc->property_info,
"dspp_caps", DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_DSPP_INFO);
mutex_init(&sde_crtc->crtc_cp_lock);
INIT_LIST_HEAD(&sde_crtc->active_list);
INIT_LIST_HEAD(&sde_crtc->dirty_list);
@@ -948,6 +1124,7 @@ void sde_cp_crtc_init(struct drm_crtc *crtc)
spin_lock_init(&sde_crtc->ltm_lock);
INIT_LIST_HEAD(&sde_crtc->ltm_buf_free);
INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy);
sde_cp_crtc_disable(crtc);
}
static void sde_cp_crtc_install_immutable_property(struct drm_crtc *crtc,
@@ -1182,6 +1359,70 @@ static void _sde_cp_crtc_enable_hist_irq(struct sde_crtc *sde_crtc)
spin_unlock_irqrestore(&node->state_lock, flags);
}
static int sde_cp_crtc_checkfeature(struct sde_cp_node *prop_node,
struct sde_crtc *sde_crtc, struct sde_crtc_state *sde_crtc_state)
{
struct sde_hw_cp_cfg hw_cfg;
struct sde_hw_mixer *hw_lm;
struct sde_hw_dspp *hw_dspp;
u32 num_mixers;
int i = 0, ret = 0;
bool feature_enabled = false;
feature_wrapper check_feature = NULL;
if (!prop_node || !sde_crtc || !sde_crtc_state) {
DRM_ERROR("invalid arguments");
return -EINVAL;
}
num_mixers = sde_crtc->num_mixers;
if (prop_node->feature >= SDE_CP_CRTC_MAX_FEATURES) {
DRM_ERROR("invalid feature %d\n", prop_node->feature);
return -EINVAL;
}
check_feature = check_crtc_feature_wrappers[prop_node->feature];
if (check_feature == NULL)
return 0;
memset(&hw_cfg, 0, sizeof(hw_cfg));
sde_cp_get_hw_payload(prop_node, &hw_cfg, &feature_enabled);
hw_cfg.num_of_mixers = sde_crtc->num_mixers;
hw_cfg.last_feature = 0;
for (i = 0; i < num_mixers; i++) {
hw_dspp = sde_crtc->mixers[i].hw_dspp;
if (!hw_dspp || i >= DSPP_MAX)
continue;
hw_cfg.dspp[i] = hw_dspp;
}
for (i = 0; i < num_mixers && !ret; i++) {
hw_lm = sde_crtc->mixers[i].hw_lm;
hw_dspp = sde_crtc->mixers[i].hw_dspp;
if (!hw_lm) {
ret = -EINVAL;
continue;
}
hw_cfg.ctl = sde_crtc->mixers[i].hw_ctl;
hw_cfg.mixer_info = hw_lm;
/* use incoming state information */
hw_cfg.displayh = num_mixers *
sde_crtc_state->lm_roi[i].w;
hw_cfg.displayv = sde_crtc_state->lm_roi[i].h;
DRM_DEBUG_DRIVER("check cp feature %d on mixer %d\n",
prop_node->feature, hw_lm->idx - LM_0);
ret = check_feature(hw_dspp, &hw_cfg, sde_crtc);
if (ret)
break;
}
return ret;
}
static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
struct sde_crtc *sde_crtc)
{
@@ -1206,11 +1447,11 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
}
if ((prop_node->feature >= SDE_CP_CRTC_MAX_FEATURES) ||
crtc_feature_wrappers[prop_node->feature] == NULL) {
set_crtc_feature_wrappers[prop_node->feature] == NULL) {
ret = -EINVAL;
} else {
set_feature_wrapper set_feature =
crtc_feature_wrappers[prop_node->feature];
feature_wrapper set_feature =
set_crtc_feature_wrappers[prop_node->feature];
catalog = get_kms(&sde_crtc->base)->catalog;
hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled;
@@ -1252,6 +1493,250 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
list_del_init(&prop_node->dirty_list);
}
static int sde_cp_crtc_check_pu_features(struct drm_crtc *crtc)
{
int ret = 0, i = 0, j = 0;
struct sde_crtc *sde_crtc;
struct sde_crtc_state *sde_crtc_state;
struct sde_hw_cp_cfg hw_cfg;
struct sde_hw_dspp *hw_dspp;
if (!crtc) {
DRM_ERROR("invalid crtc %pK\n", crtc);
return -EINVAL;
}
sde_crtc = to_sde_crtc(crtc);
if (!sde_crtc) {
DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc);
return -EINVAL;
}
sde_crtc_state = to_sde_crtc_state(crtc->state);
if (!sde_crtc_state) {
DRM_ERROR("invalid sde_crtc_state %pK\n", sde_crtc_state);
return -EINVAL;
}
for (i = 0; i < sde_crtc->num_mixers; i++) {
if (!sde_crtc->mixers[i].hw_lm) {
DRM_ERROR("invalid lm in mixer %d\n", i);
return -EINVAL;
}
if (!sde_crtc->mixers[i].hw_ctl) {
DRM_ERROR("invalid ctl in mixer %d\n", i);
return -EINVAL;
}
}
/* early return when not a partial update frame */
if (sde_crtc_state->user_roi_list.num_rects == 0) {
DRM_DEBUG_DRIVER("no partial update required\n");
return 0;
}
memset(&hw_cfg, 0, sizeof(hw_cfg));
hw_cfg.num_of_mixers = sde_crtc->num_mixers;
hw_cfg.payload = &sde_crtc_state->user_roi_list;
hw_cfg.len = sizeof(sde_crtc_state->user_roi_list);
for (i = 0; i < hw_cfg.num_of_mixers; i++)
hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp;
for (i = 0; i < SDE_CP_CRTC_MAX_PU_FEATURES; i++) {
feature_wrapper check_pu_feature =
check_crtc_pu_feature_wrappers[i];
if (!check_pu_feature ||
!(sde_crtc->cp_pu_feature_mask & BIT(i)))
continue;
for (j = 0; j < hw_cfg.num_of_mixers; j++) {
hw_dspp = sde_crtc->mixers[j].hw_dspp;
/* use incoming state information */
hw_cfg.mixer_info = sde_crtc->mixers[j].hw_lm;
hw_cfg.ctl = sde_crtc->mixers[j].hw_ctl;
hw_cfg.displayh = hw_cfg.num_of_mixers *
sde_crtc_state->lm_roi[j].w;
hw_cfg.displayv = sde_crtc_state->lm_roi[j].h;
ret = check_pu_feature(hw_dspp, &hw_cfg, sde_crtc);
if (ret) {
DRM_ERROR("failed pu feature %d in mixer %d\n",
i, j);
return -EAGAIN;
}
}
}
return ret;
}
int sde_cp_crtc_check_properties(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
struct sde_crtc *sde_crtc = NULL;
struct sde_crtc_state *sde_crtc_state = NULL;
struct sde_cp_node *prop_node = NULL, *n = NULL;
int ret = 0;
if (!crtc || !crtc->dev || !state) {
DRM_ERROR("invalid crtc %pK dev %pK state %pK\n", crtc,
(crtc ? crtc->dev : NULL), state);
return -EINVAL;
}
sde_crtc = to_sde_crtc(crtc);
if (!sde_crtc) {
DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc);
return -EINVAL;
}
sde_crtc_state = to_sde_crtc_state(state);
if (!sde_crtc_state) {
DRM_ERROR("invalid sde_crtc_state %pK\n", sde_crtc_state);
return -EINVAL;
}
mutex_lock(&sde_crtc->crtc_cp_lock);
ret = sde_cp_crtc_check_pu_features(crtc);
if (ret) {
DRM_ERROR("failed check pu features, ret %d\n", ret);
goto exit;
}
if (list_empty(&sde_crtc->dirty_list)) {
DRM_DEBUG_DRIVER("Dirty list is empty\n");
goto exit;
}
list_for_each_entry_safe(prop_node, n, &sde_crtc->dirty_list,
dirty_list) {
ret = sde_cp_crtc_checkfeature(prop_node, sde_crtc,
sde_crtc_state);
if (ret) {
DRM_ERROR("failed check on prop_node %u\n",
prop_node->property_id);
/* remove invalid feature from dirty list */
list_del_init(&prop_node->dirty_list);
goto exit;
}
}
exit:
mutex_unlock(&sde_crtc->crtc_cp_lock);
return ret;
}
static int sde_cp_crtc_set_pu_features(struct drm_crtc *crtc, bool *need_flush)
{
int ret = 0, i = 0, j = 0;
struct sde_crtc *sde_crtc;
struct sde_crtc_state *sde_crtc_state;
struct sde_hw_cp_cfg hw_cfg;
struct sde_hw_dspp *hw_dspp;
struct sde_hw_mixer *hw_lm;
struct sde_mdss_cfg *catalog;
struct sde_rect user_rect, cached_rect;
if (!need_flush) {
DRM_ERROR("invalid need_flush %pK\n", need_flush);
return -EINVAL;
}
if (!crtc) {
DRM_ERROR("invalid crtc %pK\n", crtc);
return -EINVAL;
}
sde_crtc = to_sde_crtc(crtc);
if (!sde_crtc) {
DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc);
return -EINVAL;
}
sde_crtc_state = to_sde_crtc_state(crtc->state);
if (!sde_crtc_state) {
DRM_ERROR("invalid sde_crtc_state %pK\n", sde_crtc_state);
return -EINVAL;
}
for (i = 0; i < sde_crtc->num_mixers; i++) {
if (!sde_crtc->mixers[i].hw_lm) {
DRM_ERROR("invalid lm in mixer %d\n", i);
return -EINVAL;
}
if (!sde_crtc->mixers[i].hw_ctl) {
DRM_ERROR("invalid ctl in mixer %d\n", i);
return -EINVAL;
}
}
/* early return if not a partial update frame or no change in rois */
if (sde_crtc_state->user_roi_list.num_rects == 0) {
DRM_DEBUG_DRIVER("no partial update required\n");
memset(&sde_crtc_state->cached_user_roi_list, 0,
sizeof(struct msm_roi_list));
return 0;
}
sde_kms_rect_merge_rectangles(&sde_crtc_state->user_roi_list,
&user_rect);
sde_kms_rect_merge_rectangles(&sde_crtc_state->cached_user_roi_list,
&cached_rect);
if (sde_kms_rect_is_equal(&user_rect, &cached_rect)) {
DRM_DEBUG_DRIVER("no change in list of ROIs\n");
return 0;
}
catalog = get_kms(&sde_crtc->base)->catalog;
memset(&hw_cfg, 0, sizeof(hw_cfg));
hw_cfg.num_of_mixers = sde_crtc->num_mixers;
hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled;
hw_cfg.payload = &sde_crtc_state->user_roi_list;
hw_cfg.len = sizeof(sde_crtc_state->user_roi_list);
for (i = 0; i < hw_cfg.num_of_mixers; i++)
hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp;
for (i = 0; i < SDE_CP_CRTC_MAX_PU_FEATURES; i++) {
feature_wrapper set_pu_feature =
set_crtc_pu_feature_wrappers[i];
if (!set_pu_feature ||
!(sde_crtc->cp_pu_feature_mask & BIT(i)))
continue;
for (j = 0; j < hw_cfg.num_of_mixers; j++) {
hw_lm = sde_crtc->mixers[j].hw_lm;
hw_dspp = sde_crtc->mixers[j].hw_dspp;
hw_cfg.mixer_info = hw_lm;
hw_cfg.ctl = sde_crtc->mixers[j].hw_ctl;
hw_cfg.displayh = hw_cfg.num_of_mixers *
hw_lm->cfg.out_width;
hw_cfg.displayv = hw_lm->cfg.out_height;
ret = set_pu_feature(hw_dspp, &hw_cfg, sde_crtc);
/* feature does not need flush when ret > 0 */
if (ret < 0) {
DRM_ERROR("failed pu feature %d in mixer %d\n",
i, j);
return ret;
} else if (ret == 0) {
*need_flush = true;
}
}
}
memcpy(&sde_crtc_state->cached_user_roi_list,
&sde_crtc_state->user_roi_list,
sizeof(struct msm_roi_list));
return 0;
}
void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
{
struct sde_crtc *sde_crtc = NULL;
@@ -1259,6 +1744,8 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
struct sde_cp_node *prop_node = NULL, *n = NULL;
struct sde_hw_ctl *ctl;
u32 num_mixers = 0, i = 0;
int rc = 0;
bool need_flush = false;
if (!crtc || !crtc->dev) {
DRM_ERROR("invalid crtc %pK dev %pK\n", crtc,
@@ -1274,42 +1761,49 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
num_mixers = sde_crtc->num_mixers;
if (!num_mixers) {
DRM_DEBUG_DRIVER("no mixers for this crtc\n");
DRM_ERROR("no mixers for this crtc\n");
return;
}
mutex_lock(&sde_crtc->crtc_cp_lock);
/* Check if dirty lists are empty and ad features are disabled for
* early return. If ad properties are active then we need to issue
* dspp flush.
**/
if (list_empty(&sde_crtc->dirty_list) &&
list_empty(&sde_crtc->ad_dirty)) {
if (list_empty(&sde_crtc->ad_active)) {
DRM_DEBUG_DRIVER("Dirty list is empty\n");
goto exit;
}
set_dspp_flush = true;
list_empty(&sde_crtc->ad_dirty) &&
list_empty(&sde_crtc->ad_active) &&
list_empty(&sde_crtc->active_list)) {
DRM_DEBUG_DRIVER("all lists are empty\n");
goto exit;
}
if (!list_empty(&sde_crtc->ad_active))
sde_cp_ad_set_prop(sde_crtc, AD_IPC_RESET);
rc = sde_cp_crtc_set_pu_features(crtc, &need_flush);
if (rc) {
DRM_ERROR("failed set pu features, skip cp updates\n");
goto exit;
} else if (need_flush) {
set_dspp_flush = true;
set_lm_flush = true;
}
list_for_each_entry_safe(prop_node, n, &sde_crtc->dirty_list,
dirty_list) {
dirty_list) {
sde_cp_crtc_setfeature(prop_node, sde_crtc);
/* Set the flush flag to true */
if (prop_node->is_dspp_feature)
if (prop_node->is_dspp_feature &&
!prop_node->lm_flush_override)
set_dspp_flush = true;
else
set_lm_flush = true;
}
list_for_each_entry_safe(prop_node, n, &sde_crtc->ad_dirty,
dirty_list) {
if (!list_empty(&sde_crtc->ad_active)) {
sde_cp_ad_set_prop(sde_crtc, AD_IPC_RESET);
set_dspp_flush = true;
}
list_for_each_entry_safe(prop_node, n, &sde_crtc->ad_dirty,
dirty_list) {
sde_cp_crtc_setfeature(prop_node, sde_crtc);
set_dspp_flush = true;
}
for (i = 0; i < num_mixers; i++) {
@@ -1381,7 +1875,13 @@ void sde_cp_crtc_install_properties(struct drm_crtc *crtc)
SDE_CP_CRTC_MAX_FEATURES), GFP_KERNEL);
setup_dspp_prop_install_funcs(dspp_prop_install_func);
setup_lm_prop_install_funcs(lm_prop_install_func);
setup_crtc_feature_wrappers(crtc_feature_wrappers);
setup_set_crtc_feature_wrappers(set_crtc_feature_wrappers);
setup_check_crtc_feature_wrappers(check_crtc_feature_wrappers);
setup_set_crtc_pu_feature_wrappers(
set_crtc_pu_feature_wrappers);
setup_check_crtc_pu_feature_wrappers(
check_crtc_pu_feature_wrappers);
setup_dspp_caps_funcs(dspp_cap_update_func);
}
if (!priv->cp_property)
goto exit;
@@ -1944,6 +2444,57 @@ static void dspp_ltm_install_property(struct drm_crtc *crtc)
}
}
static void dspp_rc_install_property(struct drm_crtc *crtc)
{
char feature_name[256];
struct sde_kms *kms = NULL;
struct sde_mdss_cfg *catalog = NULL;
struct sde_cp_node *prop_node = NULL;
struct sde_crtc *sde_crtc = NULL;
u32 version;
if (!crtc) {
DRM_ERROR("invalid arguments");
return;
}
sde_crtc = to_sde_crtc(crtc);
if (!sde_crtc) {
DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc);
return;
}
kms = get_kms(crtc);
catalog = kms->catalog;
version = catalog->dspp[0].sblk->rc.version >> 16;
switch (version) {
case 1:
snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d",
"SDE_DSPP_RC_MASK_V", version);
sde_cp_crtc_install_blob_property(crtc, feature_name,
SDE_CP_CRTC_DSPP_RC_MASK,
sizeof(struct drm_msm_rc_mask_cfg));
/* Override flush mechanism to use layer mixer flush bits */
if (!catalog->rc_lm_flush_override)
break;
DRM_DEBUG("rc using lm flush override\n");
list_for_each_entry(prop_node, &sde_crtc->feature_list,
feature_list) {
if (prop_node->feature == SDE_CP_CRTC_DSPP_RC_MASK) {
prop_node->lm_flush_override = true;
break;
}
}
break;
default:
DRM_ERROR("version %d not supported\n", version);
break;
}
}
static void lm_gc_install_property(struct drm_crtc *crtc)
{
char feature_name[256];
@@ -3373,3 +3924,72 @@ void sde_cp_mode_switch_prop_dirty(struct drm_crtc *crtc_drm)
}
mutex_unlock(&crtc->crtc_cp_lock);
}
static void rc_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info)
{
struct sde_mdss_cfg *catalog = get_kms(&crtc->base)->catalog;
u32 i, num_mixers = crtc->num_mixers;
char blk_name[256];
if (!catalog->rc_count || num_mixers > catalog->rc_count)
return;
for (i = 0; i < num_mixers; i++) {
struct sde_hw_dspp *dspp = crtc->mixers[i].hw_dspp;
if (!dspp || (dspp->idx - DSPP_0) >= catalog->rc_count)
continue;
snprintf(blk_name, sizeof(blk_name), "rc%u",
(dspp->idx - DSPP_0));
sde_kms_info_add_keyint(info, blk_name, 1);
}
}
void sde_cp_crtc_enable(struct drm_crtc *drm_crtc)
{
struct sde_crtc *crtc;
struct sde_kms_info *info = NULL;
u32 i, num_mixers;
if (!drm_crtc) {
DRM_ERROR("invalid crtc handle");
return;
}
crtc = to_sde_crtc(drm_crtc);
num_mixers = crtc->num_mixers;
if (!num_mixers)
return;
mutex_lock(&crtc->crtc_cp_lock);
info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
if (info) {
for (i = 0; i < ARRAY_SIZE(dspp_cap_update_func); i++)
dspp_cap_update_func[i](crtc, info);
msm_property_set_blob(&crtc->property_info,
&crtc->dspp_blob_info,
info->data, SDE_KMS_INFO_DATALEN(info),
CRTC_PROP_DSPP_INFO);
}
kfree(info);
mutex_unlock(&crtc->crtc_cp_lock);
}
void sde_cp_crtc_disable(struct drm_crtc *drm_crtc)
{
struct sde_kms_info *info = NULL;
struct sde_crtc *crtc;
if (!drm_crtc) {
DRM_ERROR("invalid crtc handle");
return;
}
crtc = to_sde_crtc(drm_crtc);
mutex_lock(&crtc->crtc_cp_lock);
info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
if (info)
msm_property_set_blob(&crtc->property_info,
&crtc->dspp_blob_info,
info->data, SDE_KMS_INFO_DATALEN(info),
CRTC_PROP_DSPP_INFO);
mutex_unlock(&crtc->crtc_cp_lock);
kfree(info);
}
+24 -1
View File
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_COLOR_PROCESSING_H
@@ -93,6 +93,15 @@ void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc);
*/
int sde_cp_crtc_set_property(struct drm_crtc *crtc,
struct drm_property *property, uint64_t val);
/**
* sde_cp_crtc_check_properties: Verify color processing properties for a crtc.
* Should be called during atomic check call.
* @crtc: Pointer to crtc.
* @state: Pointer to crtc state.
* @returns: 0 on success, non-zero otherwise
*/
int sde_cp_crtc_check_properties(struct drm_crtc *crtc,
struct drm_crtc_state *state);
/**
* sde_cp_crtc_apply_properties: Enable/disable properties
@@ -196,4 +205,18 @@ int sde_cp_ltm_off_event_handler(struct drm_crtc *crtc_drm, bool en,
* @crtc_drm: Pointer to crtc.
*/
void sde_cp_mode_switch_prop_dirty(struct drm_crtc *crtc_drm);
/**
* sde_cp_crtc_enable(): enable color processing info in the crtc.
* Should be called during crtc enable.
* @crtc: Pointer to drm_crtc.
*/
void sde_cp_crtc_enable(struct drm_crtc *crtc);
/**
* sde_cp_crtc_disable(): disable color processing info in the crtc.
* Should be called during crtc disable.
* @crtc: Pointer to drm_crtc.
*/
void sde_cp_crtc_disable(struct drm_crtc *crtc);
#endif /*_SDE_COLOR_PROCESSING_H */
+33 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -781,6 +781,9 @@ static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc,
}
sde_kms_rect_merge_rectangles(&sde_conn_state->rois, &conn_roi);
SDE_DEBUG("conn_roi x:%u, y:%u, w:%u, h:%u\n",
conn_roi.x, conn_roi.y,
conn_roi.w, conn_roi.h);
SDE_EVT32_VERBOSE(DRMID(crtc), DRMID(conn),
conn_roi.x, conn_roi.y,
conn_roi.w, conn_roi.h);
@@ -4079,6 +4082,7 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
/* disable clk & bw control until clk & bw properties are set */
cstate->bw_control = false;
cstate->bw_split_vote = false;
sde_cp_crtc_disable(crtc);
mutex_unlock(&sde_crtc->crtc_lock);
}
@@ -4150,7 +4154,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc,
}
sde_crtc->enabled = true;
sde_cp_crtc_enable(crtc);
/* update color processing on resume */
event.type = DRM_EVENT_CRTC_POWER;
event.length = sizeof(u32);
@@ -4903,6 +4907,12 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
goto end;
}
rc = sde_cp_crtc_check_properties(crtc, state);
if (rc) {
SDE_ERROR("crtc%d failed cp properties check %d\n",
crtc->base.id, rc);
goto end;
}
end:
kfree(pstates);
kfree(multirect_plane);
@@ -4989,6 +4999,26 @@ static void sde_kms_add_ubwc_info(struct sde_kms_info *info,
sde_kms_info_add_keystr(info, "DDR version", "DDR5");
}
/**
* _sde_crtc_install_cp_properties - install color properties for crtc
* @info: Pointer to kms info structure
* @catalog: Pointer to catalog structure
*/
static void _sde_crtc_install_cp_properties(struct sde_kms_info *info,
struct sde_mdss_cfg *catalog)
{
if (!info || !catalog) {
SDE_ERROR("invalid info or catalog\n");
return;
}
sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr);
sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus);
if (catalog->dspp_count && catalog->rc_count)
sde_kms_info_add_keyint(info, "rc_mem_size",
catalog->dspp[0].sblk->rc.mem_total_size);
}
/**
* sde_crtc_install_properties - install all drm properties for crtc
* @crtc: Pointer to drm crtc structure
@@ -5189,8 +5219,7 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
}
sde_kms_info_add_keyint(info, "has_src_split", catalog->has_src_split);
sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr);
sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus);
_sde_crtc_install_cp_properties(info, catalog);
if (catalog->perf.max_bw_low)
sde_kms_info_add_keyint(info, "max_bandwidth_low",
catalog->perf.max_bw_low * 1000LL);
+9 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -276,6 +276,7 @@ struct sde_crtc_misr_info {
* @cur_perf : current performance committed to clock/bandwidth driver
* @plane_mask_old: keeps track of the planes used in the previous commit
* @frame_trigger_mode: frame trigger mode
* @cp_pu_feature_mask: mask indicating cp feature enable for partial update
* @ltm_buffer_cnt : number of ltm buffers
* @ltm_buffers : struct stores ltm buffer related data
* @ltm_buf_free : list of LTM buffers that are available
@@ -285,6 +286,7 @@ struct sde_crtc_misr_info {
* @ltm_lock : Spinlock to protect ltm buffer_cnt, hist_en and ltm lists
* @needs_hw_reset : Initiate a hw ctl reset
* @comp_ratio : Compression ratio
* @dspp_blob_info : blob containing dspp hw capability information
*/
struct sde_crtc {
struct drm_crtc base;
@@ -358,6 +360,8 @@ struct sde_crtc {
struct drm_property_blob *hist_blob;
enum frame_trigger_mode_type frame_trigger_mode;
u32 cp_pu_feature_mask;
u32 ltm_buffer_cnt;
struct sde_ltm_buffer *ltm_buffers[LTM_BUFFER_SIZE];
struct list_head ltm_buf_free;
@@ -369,6 +373,8 @@ struct sde_crtc {
bool needs_hw_reset;
int comp_ratio;
struct drm_property_blob *dspp_blob_info;
};
#define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
@@ -389,6 +395,7 @@ struct sde_crtc {
* @lm_roi : Current LM ROI, possibly sub-rectangle of mode.
* Origin top left of CRTC.
* @user_roi_list : List of user's requested ROIs as from set property
* @cached_user_roi_list : Copy of user_roi_list from previous PU frame
* @property_state: Local storage for msm_prop properties
* @property_values: Current crtc property values
* @input_fence_timeout_ns : Cached input fence timeout, in ns
@@ -416,7 +423,7 @@ struct sde_crtc_state {
struct sde_rect crtc_roi;
struct sde_rect lm_bounds[CRTC_DUAL_MIXERS];
struct sde_rect lm_roi[CRTC_DUAL_MIXERS];
struct msm_roi_list user_roi_list;
struct msm_roi_list user_roi_list, cached_user_roi_list;
struct msm_property_state property_state;
struct msm_property_value property_values[CRTC_PROP_COUNT];
+54 -3
View File
@@ -383,6 +383,14 @@ enum {
LTM_PROP_MAX,
};
enum {
RC_OFF,
RC_LEN,
RC_VERSION,
RC_MEM_TOTAL_SIZE,
RC_PROP_MAX,
};
enum {
MIXER_OFF,
MIXER_LEN,
@@ -692,6 +700,13 @@ static struct sde_prop_type ltm_prop[] = {
{LTM_VERSION, "qcom,sde-dspp-ltm-version", false, PROP_TYPE_U32},
};
static struct sde_prop_type rc_prop[] = {
{RC_OFF, "qcom,sde-dspp-rc-off", false, PROP_TYPE_U32_ARRAY},
{RC_LEN, "qcom,sde-dspp-rc-size", false, PROP_TYPE_U32},
{RC_VERSION, "qcom,sde-dspp-rc-version", false, PROP_TYPE_U32},
{RC_MEM_TOTAL_SIZE, "qcom,sde-dspp-rc-mem-size", false, PROP_TYPE_U32},
};
static struct sde_prop_type ds_top_prop[] = {
{DS_TOP_OFF, "qcom,sde-dest-scaler-top-off", false, PROP_TYPE_U32},
{DS_TOP_LEN, "qcom,sde-dest-scaler-top-size", false, PROP_TYPE_U32},
@@ -2357,14 +2372,15 @@ static int sde_dspp_parse_dt(struct device_node *np,
{
int rc, prop_count[DSPP_PROP_MAX], i;
int ad_prop_count[AD_PROP_MAX];
int ltm_prop_count[LTM_PROP_MAX];
int ltm_prop_count[LTM_PROP_MAX], rc_prop_count[RC_PROP_MAX];
bool prop_exists[DSPP_PROP_MAX], ad_prop_exists[AD_PROP_MAX];
bool ltm_prop_exists[LTM_PROP_MAX];
bool ltm_prop_exists[LTM_PROP_MAX], rc_prop_exists[RC_PROP_MAX];
bool blocks_prop_exists[DSPP_BLOCKS_PROP_MAX];
struct sde_prop_value *ad_prop_value = NULL, *ltm_prop_value = NULL;
struct sde_prop_value *rc_prop_value = NULL;
int blocks_prop_count[DSPP_BLOCKS_PROP_MAX];
struct sde_prop_value *prop_value = NULL, *blocks_prop_value = NULL;
u32 off_count, ad_off_count, ltm_off_count;
u32 off_count, ad_off_count, ltm_off_count, rc_off_count;
struct sde_dspp_cfg *dspp;
struct sde_dspp_sub_blks *sblk;
struct device_node *snp = NULL;
@@ -2426,6 +2442,22 @@ static int sde_dspp_parse_dt(struct device_node *np,
if (rc)
goto end;
/* Parse RC dtsi entries */
rc_prop_value = kcalloc(RC_PROP_MAX,
sizeof(struct sde_prop_value), GFP_KERNEL);
if (!rc_prop_value) {
rc = -ENOMEM;
goto end;
}
rc = _validate_dt_entry(np, rc_prop, ARRAY_SIZE(rc_prop),
rc_prop_count, &rc_off_count);
if (rc)
goto end;
rc = _read_dt_entry(np, rc_prop, ARRAY_SIZE(rc_prop), rc_prop_count,
rc_prop_exists, rc_prop_value);
if (rc)
goto end;
/* get DSPP feature dt properties if they exist */
snp = of_get_child_by_name(np, dspp_prop[DSPP_BLOCKS].prop_name);
if (snp) {
@@ -2489,6 +2521,22 @@ static int sde_dspp_parse_dt(struct device_node *np,
set_bit(SDE_DSPP_LTM, &dspp->features);
}
sblk->rc.id = SDE_DSPP_RC;
sde_cfg->rc_count = rc_off_count;
if (rc_prop_value && (i < rc_off_count) &&
rc_prop_exists[RC_OFF]) {
sblk->rc.base = PROP_VALUE_ACCESS(rc_prop_value,
RC_OFF, i);
sblk->rc.len = PROP_VALUE_ACCESS(rc_prop_value,
RC_LEN, 0);
sblk->rc.version = PROP_VALUE_ACCESS(rc_prop_value,
RC_VERSION, 0);
sblk->rc.mem_total_size = PROP_VALUE_ACCESS(
rc_prop_value, RC_MEM_TOTAL_SIZE,
0);
sblk->rc.idx = i;
set_bit(SDE_DSPP_RC, &dspp->features);
}
}
end:
@@ -2496,6 +2544,8 @@ end:
kfree(ad_prop_value);
kfree(ltm_prop_value);
kfree(blocks_prop_value);
kfree(rc_prop_value);
return rc;
}
@@ -4399,6 +4449,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
sde_cfg->allow_gdsc_toggle = true;
clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
sde_cfg->rc_lm_flush_override = true;
} else {
SDE_ERROR("unsupported chipset id:%X\n", hw_rev);
sde_cfg->perf.min_prefill_lines = 0xffff;
+22
View File
@@ -315,6 +315,7 @@ enum {
* @SDE_DSPP_VLUT PA VLUT block
* @SDE_DSPP_AD AD block
* @SDE_DSPP_LTM LTM block
* @SDE_DSPP_RC RC block
* @SDE_DSPP_MAX maximum value
*/
enum {
@@ -330,6 +331,7 @@ enum {
SDE_DSPP_VLUT,
SDE_DSPP_AD,
SDE_DSPP_LTM,
SDE_DSPP_RC,
SDE_DSPP_MAX
};
@@ -664,6 +666,20 @@ struct sde_lm_sub_blks {
struct sde_pp_blk gc;
};
/**
* struct sde_dspp_rc: Pixel processing rounded corner sub-blk information
* @info: HW register and features supported by this sub-blk.
* @version: HW Algorithm version.
* @idx: HW block instance id.
* @mem_total_size: data memory size.
*/
struct sde_dspp_rc {
SDE_HW_SUBBLK_INFO;
u32 version;
u32 idx;
u32 mem_total_size;
};
struct sde_dspp_sub_blks {
struct sde_pp_blk igc;
struct sde_pp_blk pcc;
@@ -677,6 +693,7 @@ struct sde_dspp_sub_blks {
struct sde_pp_blk ad;
struct sde_pp_blk ltm;
struct sde_pp_blk vlut;
struct sde_dspp_rc rc;
};
struct sde_pingpong_sub_blks {
@@ -1271,6 +1288,7 @@ struct sde_limit_cfg {
* @has_base_layer Supports staging layer as base layer
* @allow_gdsc_toggle Flag to check if gdsc toggle is needed after crtc is
* disabled when external vote is present
* @rc_lm_flush_override Support Rounded Corner using layer mixer flush
* @sc_cfg: system cache configuration
* @uidle_cfg Settings for uidle feature
* @sui_misr_supported indicate if secure-ui-misr is supported
@@ -1287,6 +1305,7 @@ struct sde_limit_cfg {
* @has_vig_p010 indicates if vig pipe supports p010 format
* @inline_rot_formats formats supported by the inline rotator feature
* @mdss_irqs bitmap with the irqs supported by the target
* @rc_count number of rounded corner hardware instances
*/
struct sde_mdss_cfg {
u32 hwversion;
@@ -1329,6 +1348,7 @@ struct sde_mdss_cfg {
bool update_tcsr_disp_glitch;
bool has_base_layer;
bool allow_gdsc_toggle;
bool rc_lm_flush_override;
struct sde_sc_cfg sc_cfg;
@@ -1394,6 +1414,7 @@ struct sde_mdss_cfg {
u32 ad_count;
u32 ltm_count;
u32 rc_count;
u32 merge_3d_count;
struct sde_merge_3d_cfg merge_3d[MAX_BLOCKS];
@@ -1441,6 +1462,7 @@ struct sde_mdss_hw_cfg_handler {
#define BLK_WB(s) ((s)->wb)
#define BLK_AD(s) ((s)->ad)
#define BLK_LTM(s) ((s)->ltm)
#define BLK_RC(s) ((s)->rc)
/**
* sde_hw_set_preference: populate the individual hw lm preferences,
+43 -1
View File
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved.
*/
#include <drm/msm_drm_pp.h>
#include "sde_hw_mdss.h"
#include "sde_hwio.h"
@@ -10,6 +11,7 @@
#include "sde_hw_color_processing.h"
#include "sde_dbg.h"
#include "sde_ad4.h"
#include "sde_hw_rc.h"
#include "sde_kms.h"
static struct sde_dspp_cfg *_dspp_offset(enum sde_dspp dspp,
@@ -229,6 +231,37 @@ static void dspp_ltm(struct sde_hw_dspp *c)
}
}
static void dspp_rc(struct sde_hw_dspp *c)
{
int ret = 0;
if (!c) {
SDE_ERROR("invalid arguments\n");
return;
}
if (c->cap->sblk->rc.version == SDE_COLOR_PROCESS_VER(0x1, 0x0)) {
ret = sde_hw_rc_init(c);
if (ret) {
SDE_ERROR("rc init failed, ret %d\n", ret);
return;
}
ret = reg_dmav1_init_dspp_op_v4(SDE_DSPP_RC, c->idx);
if (!ret)
c->ops.setup_rc_data =
sde_hw_rc_setup_data_dma;
else
c->ops.setup_rc_data =
sde_hw_rc_setup_data_ahb;
c->ops.validate_rc_mask = sde_hw_rc_check_mask;
c->ops.setup_rc_mask = sde_hw_rc_setup_mask;
c->ops.validate_rc_pu_roi = sde_hw_rc_check_pu_roi;
c->ops.setup_rc_pu_roi = sde_hw_rc_setup_pu_roi;
}
}
static void (*dspp_blocks[SDE_DSPP_MAX])(struct sde_hw_dspp *c);
static void _init_dspp_ops(void)
@@ -245,6 +278,7 @@ static void _init_dspp_ops(void)
dspp_blocks[SDE_DSPP_VLUT] = dspp_vlut;
dspp_blocks[SDE_DSPP_AD] = dspp_ad;
dspp_blocks[SDE_DSPP_LTM] = dspp_ltm;
dspp_blocks[SDE_DSPP_RC] = dspp_rc;
}
static void _setup_dspp_ops(struct sde_hw_dspp *c, unsigned long features)
@@ -274,6 +308,7 @@ struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx,
struct sde_hw_dspp *c;
struct sde_dspp_cfg *cfg;
int rc;
char buf[256];
if (!addr || !m)
return ERR_PTR(-EINVAL);
@@ -317,6 +352,13 @@ struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx,
c->hw.xin_id);
}
if ((cfg->sblk->rc.id == SDE_DSPP_RC) && cfg->sblk->rc.base) {
snprintf(buf, ARRAY_SIZE(buf), "%s_%d", "rc", c->idx - DSPP_0);
sde_dbg_reg_register_dump_range(SDE_DBG_NAME, buf,
c->hw.blk_off + cfg->sblk->rc.base,
c->hw.blk_off + cfg->sblk->rc.base +
cfg->sblk->rc.len, c->hw.xin_id);
}
return c;
blk_init_error:
+41 -1
View File
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_DSPP_H
@@ -209,6 +209,46 @@ struct sde_hw_dspp_ops {
* @status: Pointer to u32 where ltm status value is dumped.
*/
void (*ltm_read_intr_status)(struct sde_hw_dspp *ctx, u32 *status);
/**
* validate_rc_mask - Validate RC mask configuration
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*validate_rc_mask)(struct sde_hw_dspp *ctx, void *cfg);
/**
* setup_rc_mask - Setup RC mask configuration
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*setup_rc_mask)(struct sde_hw_dspp *ctx, void *cfg);
/**
* validate_rc_pu_roi - Validate RC regions in during partial update.
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*validate_rc_pu_roi)(struct sde_hw_dspp *ctx, void *cfg);
/**
* setup_rc_pu_roi - Setup RC regions in during partial update.
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*setup_rc_pu_roi)(struct sde_hw_dspp *ctx, void *cfg);
/**
* setup_rc_data - Program RC mask data
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*setup_rc_data)(struct sde_hw_dspp *ctx, void *cfg);
};
/**
+8 -1
View File
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_MDSS_H
@@ -171,6 +171,7 @@ enum sde_stage {
SDE_STAGE_10,
SDE_STAGE_MAX
};
enum sde_dspp {
DSPP_0 = 1,
DSPP_1,
@@ -185,6 +186,12 @@ enum sde_ltm {
LTM_MAX
};
enum sde_rc {
RC_0 = DSPP_0,
RC_1,
RC_MAX
};
enum sde_ds {
DS_TOP,
DS_0,
+1051
View File
File diff suppressed because it is too large. Load diff
+71
View File
@@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_RC_H
#define _SDE_HW_RC_H
#include "sde_hw_mdss.h"
/**
* sde_hw_rc_init - Initialize RC internal state object and ops
* @hw_dspp: DSPP instance.
* Return: 0 on success, non-zero otherwise.
*/
int sde_hw_rc_init(struct sde_hw_dspp *hw_dspp);
/**
* sde_hw_rc_check_mask - Validate RC mask configuration
* @hw_dspp: DSPP instance.
* @cfg: Pointer to configuration blob.
* Return: 0 on success, non-zero otherwise.
*/
int sde_hw_rc_check_mask(struct sde_hw_dspp *hw_dspp, void *cfg);
/**
* sde_hw_rc_setup_mask - Setup RC mask configuration
* @hw_dspp: DSPP instance.
* @cfg: Pointer to configuration blob.
* Return: 0 on success, non-zero otherwise.
*/
int sde_hw_rc_setup_mask(struct sde_hw_dspp *hw_dspp, void *cfg);
/**
* sde_hw_rc_check_pu_roi - Validate RC partial update region of interest
* @hw_dspp: DSPP instance.
* @cfg: Pointer to configuration blob.
* Return: 0 on success.
* > 0 on early return.
* < 0 on error.
*/
int sde_hw_rc_check_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg);
/**
* sde_hw_rc_setup_pu_roi - Setup RC partial update region of interest
* @hw_dspp: DSPP instance.
* @cfg: Pointer to configuration blob.
* Return: 0 on success.
* > 0 on early return.
* < 0 on error.
*/
int sde_hw_rc_setup_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg);
/**
* sde_hw_rc_setup_data_ahb - Program mask data with AHB
* @hw_dspp: DSPP instance.
* @cfg: Pointer to configuration blob.
* Return: 0 on success, non-zero otherwise.
*/
int sde_hw_rc_setup_data_ahb(struct sde_hw_dspp *hw_dspp, void *cfg);
/**
* sde_hw_rc_setup_data_dma - Program mask data with DMA
* @hw_dspp: DSPP instance.
* @cfg: Pointer to configuration blob.
* Return: 0 on success, non-zero otherwise.
*/
int sde_hw_rc_setup_data_dma(struct sde_hw_dspp *hw_dspp, void *cfg);
#endif
+40 -13
View File
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/iopoll.h>
#include "sde_hw_mdss.h"
#include "sde_hw_ctl.h"
@@ -14,6 +15,7 @@
#define ALIGNED_OFFSET (U32_MAX & ~(GUARD_BYTES))
#define ADDR_ALIGN BIT(8)
#define MAX_RELATIVE_OFF (BIT(20) - 1)
#define ABSOLUTE_RANGE BIT(27)
#define DECODE_SEL_OP (BIT(HW_BLK_SELECT))
#define REG_WRITE_OP ((BIT(REG_SINGLE_WRITE)) | (BIT(REG_BLK_WRITE_SINGLE)) | \
@@ -39,6 +41,7 @@
#define GRP_DMA_HW_BLK_SELECT (DMA0 | DMA1 | DMA2 | DMA3)
#define GRP_DSPP_HW_BLK_SELECT (DSPP0 | DSPP1 | DSPP2 | DSPP3)
#define GRP_LTM_HW_BLK_SELECT (LTM0 | LTM1)
#define GRP_MDSS_HW_BLK_SELECT (MDSS)
#define BUFFER_SPACE_LEFT(cfg) ((cfg)->dma_buf->buffer_size - \
(cfg)->dma_buf->index)
@@ -162,7 +165,7 @@ static void get_decode_sel(unsigned long blk, u32 *decode_sel)
int i = 0;
*decode_sel = 0;
for_each_set_bit(i, &blk, 31) {
for_each_set_bit(i, &blk, REG_DMA_BLK_MAX) {
switch (BIT(i)) {
case VIG0:
*decode_sel |= BIT(0);
@@ -212,6 +215,9 @@ static void get_decode_sel(unsigned long blk, u32 *decode_sel)
case LTM1:
*decode_sel |= BIT(23);
break;
case MDSS:
*decode_sel |= BIT(31);
break;
default:
DRM_ERROR("block not supported %zx\n", (size_t)BIT(i));
break;
@@ -240,6 +246,9 @@ int write_multi_reg_index(struct sde_reg_dma_setup_ops_cfg *cfg)
cfg->dma_buf->index);
loc[0] = HW_INDEX_REG_WRITE_OPCODE;
loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF);
if (cfg->blk == MDSS)
loc[0] |= ABSOLUTE_RANGE;
loc[1] = SIZE_DWORD(cfg->data_size);
cfg->dma_buf->index += ops_mem_size[cfg->ops];
@@ -253,6 +262,9 @@ int write_multi_reg_inc(struct sde_reg_dma_setup_ops_cfg *cfg)
loc = (u32 *)((u8 *)cfg->dma_buf->vaddr +
cfg->dma_buf->index);
loc[0] = AUTO_INC_REG_WRITE_OPCODE;
if (cfg->blk == MDSS)
loc[0] |= ABSOLUTE_RANGE;
loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF);
loc[1] = SIZE_DWORD(cfg->data_size);
cfg->dma_buf->index += ops_mem_size[cfg->ops];
@@ -268,6 +280,9 @@ static int write_multi_lut_reg(struct sde_reg_dma_setup_ops_cfg *cfg)
cfg->dma_buf->index);
loc[0] = BLK_REG_WRITE_OPCODE;
loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF);
if (cfg->blk == MDSS)
loc[0] |= ABSOLUTE_RANGE;
loc[1] = (cfg->inc) ? 0 : BIT(31);
loc[1] |= (cfg->wrap_size & WRAP_MAX_SIZE) << 16;
loc[1] |= ((SIZE_DWORD(cfg->data_size)) & MAX_DWORDS_SZ);
@@ -285,6 +300,9 @@ static int write_single_reg(struct sde_reg_dma_setup_ops_cfg *cfg)
cfg->dma_buf->index);
loc[0] = SINGLE_REG_WRITE_OPCODE;
loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF);
if (cfg->blk == MDSS)
loc[0] |= ABSOLUTE_RANGE;
loc[1] = *cfg->data;
cfg->dma_buf->index += ops_mem_size[cfg->ops];
cfg->dma_buf->ops_completed |= REG_WRITE_OP;
@@ -301,6 +319,9 @@ static int write_single_modify(struct sde_reg_dma_setup_ops_cfg *cfg)
cfg->dma_buf->index);
loc[0] = SINGLE_REG_MODIFY_OPCODE;
loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF);
if (cfg->blk == MDSS)
loc[0] |= ABSOLUTE_RANGE;
loc[1] = cfg->mask;
loc[2] = *cfg->data;
cfg->dma_buf->index += ops_mem_size[cfg->ops];
@@ -381,6 +402,7 @@ static int validate_write_reg(struct sde_reg_dma_setup_ops_cfg *cfg)
static int validate_write_decode_sel(struct sde_reg_dma_setup_ops_cfg *cfg)
{
u32 remain_len;
bool vig_blk, dma_blk, dspp_blk, mdss_blk;
remain_len = BUFFER_SPACE_LEFT(cfg);
if (remain_len < ops_mem_size[HW_BLK_SELECT]) {
@@ -393,15 +415,16 @@ static int validate_write_decode_sel(struct sde_reg_dma_setup_ops_cfg *cfg)
DRM_ERROR("blk set as 0\n");
return -EINVAL;
}
/* VIG, DMA and DSPP can't be combined */
if (((cfg->blk & GRP_VIG_HW_BLK_SELECT) &&
(cfg->blk & GRP_DSPP_HW_BLK_SELECT)) ||
((cfg->blk & GRP_DMA_HW_BLK_SELECT) &&
(cfg->blk & GRP_DSPP_HW_BLK_SELECT)) ||
((cfg->blk & GRP_VIG_HW_BLK_SELECT) &&
(cfg->blk & GRP_DMA_HW_BLK_SELECT))) {
DRM_ERROR("invalid blk combination %x\n",
cfg->blk);
vig_blk = (cfg->blk & GRP_VIG_HW_BLK_SELECT) ? true : false;
dma_blk = (cfg->blk & GRP_DMA_HW_BLK_SELECT) ? true : false;
dspp_blk = (cfg->blk & GRP_DSPP_HW_BLK_SELECT) ? true : false;
mdss_blk = (cfg->blk & MDSS) ? true : false;
if ((vig_blk && dspp_blk) || (dma_blk && dspp_blk) ||
(vig_blk && dma_blk) ||
(mdss_blk && (vig_blk | dma_blk | dspp_blk))) {
DRM_ERROR("invalid blk combination %x\n", cfg->blk);
return -EINVAL;
}
@@ -672,6 +695,8 @@ int init_v12(struct sde_hw_reg_dma *cfg)
v1_supported[LTM_INIT] = GRP_LTM_HW_BLK_SELECT;
v1_supported[LTM_ROI] = GRP_LTM_HW_BLK_SELECT;
v1_supported[LTM_VLUT] = GRP_LTM_HW_BLK_SELECT;
v1_supported[RC_DATA] = (GRP_DSPP_HW_BLK_SELECT |
GRP_MDSS_HW_BLK_SELECT);
return 0;
}
@@ -685,7 +710,8 @@ static int check_support_v1(enum sde_reg_dma_features feature,
if (!is_supported)
return -EINVAL;
if (feature >= REG_DMA_FEATURES_MAX || blk >= MDSS) {
if (feature >= REG_DMA_FEATURES_MAX
|| blk >= BIT_ULL(REG_DMA_BLK_MAX)) {
*is_supported = false;
return ret;
}
@@ -805,7 +831,8 @@ static struct sde_reg_dma_buffer *alloc_reg_dma_buf_v1(u32 size)
int rc = 0;
if (!size || SIZE_DWORD(size) > MAX_DWORDS_SZ) {
DRM_ERROR("invalid buffer size %d\n", size);
DRM_ERROR("invalid buffer size %d, max %d\n",
SIZE_DWORD(size), MAX_DWORDS_SZ);
return ERR_PTR(-EINVAL);
}
+90 -1
View File
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <drm/msm_drm_pp.h>
#include "sde_reg_dma.h"
#include "sde_hw_reg_dma_v1_color_proc.h"
@@ -65,6 +66,9 @@
#define MEMCOLOR_MEM_SIZE ((sizeof(struct drm_msm_memcol)) + \
REG_DMA_HEADERS_BUFFER_SZ)
#define RC_MEM_SIZE ((RC_DATA_SIZE_MAX * 2 * sizeof(u32)) + \
REG_DMA_HEADERS_BUFFER_SZ)
#define QSEED3_MEM_SIZE (sizeof(struct sde_hw_scaler3_cfg) + \
(450 * sizeof(u32)) + \
REG_DMA_HEADERS_BUFFER_SZ)
@@ -131,6 +135,7 @@ static u32 feature_map[SDE_DSPP_MAX] = {
[SDE_DSPP_DITHER] = REG_DMA_FEATURES_MAX,
[SDE_DSPP_HIST] = REG_DMA_FEATURES_MAX,
[SDE_DSPP_AD] = REG_DMA_FEATURES_MAX,
[SDE_DSPP_RC] = RC_DATA,
};
static u32 sspp_feature_map[SDE_SSPP_MAX] = {
@@ -157,6 +162,7 @@ static u32 feature_reg_dma_sz[SDE_DSPP_MAX] = {
[SDE_DSPP_HSIC] = HSIC_MEM_SIZE,
[SDE_DSPP_SIXZONE] = SIXZONE_MEM_SIZE,
[SDE_DSPP_MEMCOLOR] = MEMCOLOR_MEM_SIZE,
[SDE_DSPP_RC] = RC_MEM_SIZE,
};
static u32 sspp_feature_reg_dma_sz[SDE_SSPP_MAX] = {
@@ -1103,6 +1109,89 @@ void reg_dmav1_setup_dspp_igcv31(struct sde_hw_dspp *ctx, void *cfg)
DRM_ERROR("failed to kick off ret %d\n", rc);
}
int reg_dmav1_setup_rc_datav1(struct sde_hw_dspp *ctx, void *cfg)
{
struct drm_msm_rc_mask_cfg *rc_mask_cfg;
struct sde_hw_reg_dma_ops *dma_ops;
struct sde_reg_dma_kickoff_cfg kick_off;
struct sde_hw_cp_cfg *hw_cfg = cfg;
struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
int rc = 0;
u32 i = 0;
u32 *data = NULL;
u32 buf_sz = 0, abs_offset = 0;
u32 cfg_param_07;
u64 cfg_param_09;
rc = reg_dma_dspp_check(ctx, cfg, RC_DATA);
if (rc) {
DRM_ERROR("invalid dma dspp check rc = %d\n");
return -EINVAL;
}
if (hw_cfg->len != sizeof(struct drm_msm_rc_mask_cfg)) {
DRM_ERROR("invalid size of payload len %d exp %zd\n",
hw_cfg->len, sizeof(struct drm_msm_rc_mask_cfg));
return -EINVAL;
}
rc_mask_cfg = hw_cfg->payload;
buf_sz = rc_mask_cfg->cfg_param_08 * 2 * sizeof(u32);
abs_offset = ctx->hw.blk_off + ctx->cap->sblk->rc.base + 0x28;
dma_ops = sde_reg_dma_get_ops();
dma_ops->reset_reg_dma_buf(dspp_buf[RC_DATA][ctx->idx]);
REG_DMA_INIT_OPS(dma_write_cfg, MDSS, RC_DATA,
dspp_buf[RC_DATA][ctx->idx]);
REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0, 0);
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
DRM_ERROR("write decode select failed ret %d\n", rc);
return -ENOMEM;
}
DRM_DEBUG_DRIVER("allocating %u bytes of memory for dma\n", buf_sz);
data = kzalloc(buf_sz, GFP_KERNEL);
if (!data) {
DRM_ERROR("memory allocation failed ret %d\n", rc);
return -ENOMEM;
}
cfg_param_07 = rc_mask_cfg->cfg_param_07;
for (i = 0; i < rc_mask_cfg->cfg_param_08; i++) {
cfg_param_09 = rc_mask_cfg->cfg_param_09[i];
DRM_DEBUG_DRIVER("cfg_param_09[%d] = 0x%016lX at %u\n", i,
cfg_param_09,
i + cfg_param_07);
data[i * 2] = (i == 0) ? (BIT(30) | (cfg_param_07 << 18)) : 0;
data[i * 2] |= (cfg_param_09 & 0x3FFFF);
data[i * 2 + 1] = ((cfg_param_09 >> 18) & 0x3FFFF);
}
REG_DMA_SETUP_OPS(dma_write_cfg, abs_offset, data, buf_sz,
REG_BLK_WRITE_INC, 0, 0, 0);
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
DRM_ERROR("rc dma write failed ret %d\n", rc);
goto exit;
}
/* defer trigger to kickoff phase */
REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl,
dspp_buf[RC_DATA][ctx->idx], REG_DMA_WRITE,
DMA_CTL_QUEUE0, WRITE_TRIGGER);
rc = dma_ops->kick_off(&kick_off);
if (rc) {
DRM_ERROR("failed to kick off ret %d\n", rc);
goto exit;
}
exit:
kfree(data);
return rc;
}
static void _dspp_pccv4_off(struct sde_hw_dspp *ctx, void *cfg)
{
struct sde_reg_dma_kickoff_cfg kick_off;
+10 -1
View File
@@ -1,7 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_REG_DMA_V1_COLOR_PROC_H
#define _SDE_HW_REG_DMA_V1_COLOR_PROC_H
@@ -242,6 +243,14 @@ void reg_dmav1_setup_ltm_roiv1(struct sde_hw_dspp *ctx, void *cfg);
*/
void reg_dmav1_setup_ltm_vlutv1(struct sde_hw_dspp *ctx, void *cfg);
/**
* reg_dmav1_setup_rc_datav1() - RC DATA v1 implementation using reg dma v1.
* @ctx: dspp ctx info
* @cfg: pointer to struct sde_hw_cp_cfg
* @returns: 0 if success, non-zero otherwise
*/
int reg_dmav1_setup_rc_datav1(struct sde_hw_dspp *ctx, void *cfg);
/**
* reg_dmav1_deinit_ltm_ops() - deinitialize the ltm feature op for sde v4
* which were initialized.
+5 -1
View File
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_REG_DMA_H
@@ -57,6 +57,7 @@ enum sde_reg_dma_read_sel {
* @LTM_INIT: LTM INIT
* @LTM_ROI: LTM ROI
* @LTM_VLUT: LTM VLUT
* @RC_DATA: Rounded corner data
* @REG_DMA_FEATURES_MAX: invalid selection
*/
enum sde_reg_dma_features {
@@ -75,6 +76,7 @@ enum sde_reg_dma_features {
LTM_INIT,
LTM_ROI,
LTM_VLUT,
RC_DATA,
REG_DMA_FEATURES_MAX,
};
@@ -131,6 +133,8 @@ enum sde_reg_dma_setup_ops {
REG_DMA_SETUP_OPS_MAX,
};
#define REG_DMA_BLK_MAX 32
/**
* enum sde_reg_dma_blk - defines blocks for which reg dma op should be
* performed