disp: msm: sde: configure the dnsc_blur hw block

Add changes to configure the downscale blur hardware block based on
the conifgs set by user-mode. Program the ctl's writeback flush and
active bits when dnsc_blur is enabled. Bind the pingpong block that
feeds pixels to dnsc_blur hw block. Disable the active bits and unbind
the pp block binding during wb disable.

Change-Id: I1961ab437e344b13d0c186c1675a5bf79b84ea74
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
This commit is contained in:
Veera Sundaram Sankaran
2021-09-15 16:20:50 -07:00
parent 93ec98a33e
commit cc23729c87
5 changed files with 214 additions and 34 deletions

View File

@@ -18,6 +18,7 @@
#define SDE_CONNECTOR_NAME_SIZE 16 #define SDE_CONNECTOR_NAME_SIZE 16
#define SDE_CONNECTOR_DHDR_MEMPOOL_MAX_SIZE SZ_32 #define SDE_CONNECTOR_DHDR_MEMPOOL_MAX_SIZE SZ_32
#define MAX_CMD_RECEIVE_SIZE 256 #define MAX_CMD_RECEIVE_SIZE 256
#define DNSC_BLUR_MAX_COUNT 1
struct sde_connector; struct sde_connector;
struct sde_connector_state; struct sde_connector_state;
@@ -678,6 +679,9 @@ struct sde_connector {
* @old_topology_name: topology of previous atomic state. remove this in later * @old_topology_name: topology of previous atomic state. remove this in later
* kernel versions which provide drm_atomic_state old_state pointers * kernel versions which provide drm_atomic_state old_state pointers
* @cont_splash_populated: State was populated as part of cont. splash * @cont_splash_populated: State was populated as part of cont. splash
* @dnsc_blur_count: Number of downscale blur blocks used
* @dnsc_blur_cfg: Configs for the downscale blur block
* @dnsc_blur_lut: LUT idx used for the Gaussian filter LUTs in downscale blur block
*/ */
struct sde_connector_state { struct sde_connector_state {
struct drm_connector_state base; struct drm_connector_state base;
@@ -694,6 +698,10 @@ struct sde_connector_state {
enum sde_rm_topology_name old_topology_name; enum sde_rm_topology_name old_topology_name;
bool cont_splash_populated; bool cont_splash_populated;
u32 dnsc_blur_count;
struct sde_drm_dnsc_blur_cfg dnsc_blur_cfg[DNSC_BLUR_MAX_COUNT];
u32 dnsc_blur_lut;
}; };
/** /**

View File

@@ -3222,6 +3222,15 @@ void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
phys_enc->hw_cdm->idx, true); phys_enc->hw_cdm->idx, true);
} }
if (phys_enc->hw_dnsc_blur && phys_enc->hw_dnsc_blur->ops.bind_pingpong_blk &&
phys_enc->hw_pp) {
phys_enc->hw_dnsc_blur->ops.bind_pingpong_blk(phys_enc->hw_dnsc_blur,
false, phys_enc->hw_pp->idx);
if (ctl->ops.update_dnsc_blur_bitmask)
ctl->ops.update_dnsc_blur_bitmask(ctl, phys_enc->hw_dnsc_blur->idx, true);
}
if (phys_enc == sde_enc->cur_master && phys_enc->hw_pp && if (phys_enc == sde_enc->cur_master && phys_enc->hw_pp &&
ctl->ops.reset_post_disable) ctl->ops.reset_post_disable)
ctl->ops.reset_post_disable(ctl, &phys_enc->intf_cfg_v1, ctl->ops.reset_post_disable(ctl, &phys_enc->intf_cfg_v1,

View File

@@ -16,6 +16,7 @@
#include "sde_hw_top.h" #include "sde_hw_top.h"
#include "sde_hw_wb.h" #include "sde_hw_wb.h"
#include "sde_hw_cdm.h" #include "sde_hw_cdm.h"
#include "sde_hw_dnsc_blur.h"
#include "sde_encoder.h" #include "sde_encoder.h"
#include "sde_connector.h" #include "sde_connector.h"
@@ -260,6 +261,7 @@ struct sde_encoder_irq {
* @hw_qdss: Hardware interface to the qdss registers * @hw_qdss: Hardware interface to the qdss registers
* @cdm_cfg: Chroma-down hardware configuration * @cdm_cfg: Chroma-down hardware configuration
* @hw_pp: Hardware interface to the ping pong registers * @hw_pp: Hardware interface to the ping pong registers
* @hw_dnsc_blur: Hardware interface to the downscale blur registers
* @sde_kms: Pointer to the sde_kms top level * @sde_kms: Pointer to the sde_kms top level
* @cached_mode: DRM mode cached at mode_set time, acted on in enable * @cached_mode: DRM mode cached at mode_set time, acted on in enable
* @enabled: Whether the encoder has enabled and running a mode * @enabled: Whether the encoder has enabled and running a mode
@@ -316,6 +318,7 @@ struct sde_encoder_phys {
struct sde_hw_qdss *hw_qdss; struct sde_hw_qdss *hw_qdss;
struct sde_hw_cdm_cfg cdm_cfg; struct sde_hw_cdm_cfg cdm_cfg;
struct sde_hw_pingpong *hw_pp; struct sde_hw_pingpong *hw_pp;
struct sde_hw_dnsc_blur *hw_dnsc_blur;
struct sde_kms *sde_kms; struct sde_kms *sde_kms;
struct drm_display_mode cached_mode; struct drm_display_mode cached_mode;
enum sde_enc_split_role split_role; enum sde_enc_split_role split_role;

View File

@@ -15,6 +15,7 @@
#include "sde_wb.h" #include "sde_wb.h"
#include "sde_vbif.h" #include "sde_vbif.h"
#include "sde_crtc.h" #include "sde_crtc.h"
#include "sde_hw_dnsc_blur.h"
#define to_sde_encoder_phys_wb(x) \ #define to_sde_encoder_phys_wb(x) \
container_of(x, struct sde_encoder_phys_wb, base) container_of(x, struct sde_encoder_phys_wb, base)
@@ -509,6 +510,7 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc,
struct sde_hw_ctl *hw_ctl = phys_enc->hw_ctl; struct sde_hw_ctl *hw_ctl = phys_enc->hw_ctl;
struct sde_crtc *crtc = to_sde_crtc(wb_enc->crtc); struct sde_crtc *crtc = to_sde_crtc(wb_enc->crtc);
struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp; struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp;
struct sde_hw_dnsc_blur *hw_dnsc_blur = phys_enc->hw_dnsc_blur;
bool need_merge = (crtc->num_mixers > 1); bool need_merge = (crtc->num_mixers > 1);
int i = 0; int i = 0;
@@ -538,6 +540,9 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc,
intf_cfg.merge_3d[intf_cfg.merge_3d_count++] = intf_cfg.merge_3d[intf_cfg.merge_3d_count++] =
hw_pp->merge_3d->idx; hw_pp->merge_3d->idx;
if (hw_dnsc_blur)
intf_cfg.dnsc_blur[intf_cfg.dnsc_blur_count++] = hw_dnsc_blur->idx;
if (hw_pp->ops.setup_3d_mode) if (hw_pp->ops.setup_3d_mode)
hw_pp->ops.setup_3d_mode(hw_pp, (enable && need_merge) ? hw_pp->ops.setup_3d_mode(hw_pp, (enable && need_merge) ?
BLEND_3D_H_ROW_INT : 0); BLEND_3D_H_ROW_INT : 0);
@@ -573,16 +578,13 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc,
} }
} }
/** static void _sde_encoder_phys_wb_setup_ctl(struct sde_encoder_phys *phys_enc,
* sde_encoder_phys_wb_setup_cdp - setup chroma down prefetch block
* @phys_enc: Pointer to physical encoder
*/
static void sde_encoder_phys_wb_setup_cdp(struct sde_encoder_phys *phys_enc,
const struct sde_format *format) const struct sde_format *format)
{ {
struct sde_encoder_phys_wb *wb_enc; struct sde_encoder_phys_wb *wb_enc;
struct sde_hw_wb *hw_wb; struct sde_hw_wb *hw_wb;
struct sde_hw_cdm *hw_cdm; struct sde_hw_cdm *hw_cdm;
struct sde_hw_dnsc_blur *hw_dnsc_blur;
struct sde_hw_ctl *ctl; struct sde_hw_ctl *ctl;
const int num_wb = 1; const int num_wb = 1;
@@ -599,6 +601,7 @@ static void sde_encoder_phys_wb_setup_cdp(struct sde_encoder_phys *phys_enc,
wb_enc = to_sde_encoder_phys_wb(phys_enc); wb_enc = to_sde_encoder_phys_wb(phys_enc);
hw_wb = wb_enc->hw_wb; hw_wb = wb_enc->hw_wb;
hw_cdm = phys_enc->hw_cdm; hw_cdm = phys_enc->hw_cdm;
hw_dnsc_blur = phys_enc->hw_dnsc_blur;
ctl = phys_enc->hw_ctl; ctl = phys_enc->hw_ctl;
if (test_bit(SDE_CTL_ACTIVE_CFG, &ctl->caps->features) && if (test_bit(SDE_CTL_ACTIVE_CFG, &ctl->caps->features) &&
@@ -619,6 +622,11 @@ static void sde_encoder_phys_wb_setup_cdp(struct sde_encoder_phys *phys_enc,
intf_cfg_v1->cdm[0] = hw_cdm->idx; intf_cfg_v1->cdm[0] = hw_cdm->idx;
} }
if (hw_dnsc_blur) {
intf_cfg_v1->dnsc_blur_count = num_wb;
intf_cfg_v1->dnsc_blur[0] = hw_dnsc_blur->idx;
}
if (mode_3d && hw_pp && hw_pp->merge_3d && if (mode_3d && hw_pp && hw_pp->merge_3d &&
intf_cfg_v1->merge_3d_count < MAX_MERGE_3D_PER_CTL_V1) intf_cfg_v1->merge_3d_count < MAX_MERGE_3D_PER_CTL_V1)
intf_cfg_v1->merge_3d[intf_cfg_v1->merge_3d_count++] = intf_cfg_v1->merge_3d[intf_cfg_v1->merge_3d_count++] =
@@ -1015,6 +1023,7 @@ static void _sde_encoder_phys_wb_update_cwb_flush(
struct sde_hw_ctl *hw_ctl; struct sde_hw_ctl *hw_ctl;
struct sde_hw_cdm *hw_cdm; struct sde_hw_cdm *hw_cdm;
struct sde_hw_pingpong *hw_pp; struct sde_hw_pingpong *hw_pp;
struct sde_hw_dnsc_blur *hw_dnsc_blur;
struct sde_crtc *crtc; struct sde_crtc *crtc;
struct sde_crtc_state *crtc_state; struct sde_crtc_state *crtc_state;
int i = 0; int i = 0;
@@ -1043,6 +1052,7 @@ static void _sde_encoder_phys_wb_update_cwb_flush(
hw_pp = phys_enc->hw_pp; hw_pp = phys_enc->hw_pp;
hw_wb = wb_enc->hw_wb; hw_wb = wb_enc->hw_wb;
hw_cdm = phys_enc->hw_cdm; hw_cdm = phys_enc->hw_cdm;
hw_dnsc_blur = phys_enc->hw_dnsc_blur;
/* In CWB mode, program actual source master sde_hw_ctl from crtc */ /* In CWB mode, program actual source master sde_hw_ctl from crtc */
hw_ctl = crtc->mixers[0].hw_ctl; hw_ctl = crtc->mixers[0].hw_ctl;
@@ -1080,6 +1090,9 @@ static void _sde_encoder_phys_wb_update_cwb_flush(
hw_ctl->ops.update_bitmask(hw_ctl, SDE_HW_FLUSH_CDM, hw_ctl->ops.update_bitmask(hw_ctl, SDE_HW_FLUSH_CDM,
hw_cdm->idx, 1); hw_cdm->idx, 1);
if (hw_ctl->ops.update_dnsc_blur_bitmask && hw_dnsc_blur)
hw_ctl->ops.update_dnsc_blur_bitmask(hw_ctl, hw_dnsc_blur->idx, 1);
if (test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features) || if (test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features) ||
test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features)) { test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features)) {
if (test_bit(SDE_WB_CWB_DITHER_CTRL, &hw_wb->caps->features)) { if (test_bit(SDE_WB_CWB_DITHER_CTRL, &hw_wb->caps->features)) {
@@ -1147,6 +1160,7 @@ static void _sde_encoder_phys_wb_update_flush(struct sde_encoder_phys *phys_enc)
struct sde_hw_ctl *hw_ctl; struct sde_hw_ctl *hw_ctl;
struct sde_hw_cdm *hw_cdm; struct sde_hw_cdm *hw_cdm;
struct sde_hw_pingpong *hw_pp; struct sde_hw_pingpong *hw_pp;
struct sde_hw_dnsc_blur *hw_dnsc_blur;
struct sde_ctl_flush_cfg pending_flush = {0,}; struct sde_ctl_flush_cfg pending_flush = {0,};
if (!phys_enc) if (!phys_enc)
@@ -1157,6 +1171,7 @@ static void _sde_encoder_phys_wb_update_flush(struct sde_encoder_phys *phys_enc)
hw_cdm = phys_enc->hw_cdm; hw_cdm = phys_enc->hw_cdm;
hw_pp = phys_enc->hw_pp; hw_pp = phys_enc->hw_pp;
hw_ctl = phys_enc->hw_ctl; hw_ctl = phys_enc->hw_ctl;
hw_dnsc_blur = phys_enc->hw_dnsc_blur;
SDE_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0); SDE_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0);
@@ -1182,6 +1197,9 @@ static void _sde_encoder_phys_wb_update_flush(struct sde_encoder_phys *phys_enc)
hw_ctl->ops.update_bitmask(hw_ctl, SDE_HW_FLUSH_MERGE_3D, hw_ctl->ops.update_bitmask(hw_ctl, SDE_HW_FLUSH_MERGE_3D,
hw_pp->merge_3d->idx, 1); hw_pp->merge_3d->idx, 1);
if (hw_ctl->ops.update_dnsc_blur_bitmask && hw_dnsc_blur)
hw_ctl->ops.update_dnsc_blur_bitmask(hw_ctl, hw_dnsc_blur->idx, 1);
if (hw_ctl->ops.get_pending_flush) if (hw_ctl->ops.get_pending_flush)
hw_ctl->ops.get_pending_flush(hw_ctl, hw_ctl->ops.get_pending_flush(hw_ctl,
&pending_flush); &pending_flush);
@@ -1191,6 +1209,43 @@ static void _sde_encoder_phys_wb_update_flush(struct sde_encoder_phys *phys_enc)
hw_wb->idx - WB_0); hw_wb->idx - WB_0);
} }
static void _sde_encoder_phys_wb_setup_dnsc_blur(struct sde_encoder_phys *phys_enc)
{
struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
struct sde_wb_device *wb_dev = wb_enc->wb_dev;
struct sde_kms *sde_kms = phys_enc->sde_kms;
struct sde_hw_dnsc_blur *hw_dnsc_blur = phys_enc->hw_dnsc_blur;
struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp;
struct sde_connector *sde_conn;
struct sde_connector_state *sde_conn_state;
struct sde_drm_dnsc_blur_cfg *cfg;
int i;
bool enable;
if (!sde_kms->catalog->dnsc_blur_count || !hw_dnsc_blur || !hw_pp
|| !hw_dnsc_blur->ops.setup_dnsc_blur)
return;
sde_conn = to_sde_connector(wb_dev->connector);
sde_conn_state = to_sde_connector_state(wb_dev->connector->state);
/* swap between 0 & 1 lut idx on each config change for gaussian lut */
sde_conn_state->dnsc_blur_lut = 1 - sde_conn_state->dnsc_blur_lut;
for (i = 0; i < sde_conn_state->dnsc_blur_count; i++) {
cfg = &sde_conn_state->dnsc_blur_cfg[i];
enable = (cfg->flags & DNSC_BLUR_EN);
hw_dnsc_blur->ops.setup_dnsc_blur(hw_dnsc_blur, cfg, sde_conn_state->dnsc_blur_lut);
if (hw_dnsc_blur->ops.setup_dither)
hw_dnsc_blur->ops.setup_dither(hw_dnsc_blur, cfg);
if (hw_dnsc_blur->ops.bind_pingpong_blk)
hw_dnsc_blur->ops.bind_pingpong_blk(hw_dnsc_blur, enable, hw_pp->idx);
}
}
static void _sde_encoder_phys_wb_setup_prog_line(struct sde_encoder_phys *phys_enc) static void _sde_encoder_phys_wb_setup_prog_line(struct sde_encoder_phys *phys_enc)
{ {
struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
@@ -1280,13 +1335,15 @@ static void sde_encoder_phys_wb_setup(
sde_encoder_phys_wb_setup_fb(phys_enc, fb, wb_roi); sde_encoder_phys_wb_setup_fb(phys_enc, fb, wb_roi);
sde_encoder_phys_wb_setup_cdp(phys_enc, wb_enc->wb_fmt); _sde_encoder_phys_wb_setup_ctl(phys_enc, wb_enc->wb_fmt);
_sde_encoder_phys_wb_setup_cache(wb_enc, fb); _sde_encoder_phys_wb_setup_cache(wb_enc, fb);
_sde_encoder_phys_wb_setup_cwb(phys_enc, true); _sde_encoder_phys_wb_setup_cwb(phys_enc, true);
_sde_encoder_phys_wb_setup_prog_line(phys_enc); _sde_encoder_phys_wb_setup_prog_line(phys_enc);
_sde_encoder_phys_wb_setup_dnsc_blur(phys_enc);
} }
static void sde_encoder_phys_wb_ctl_start_irq(void *arg, int irq_idx) static void sde_encoder_phys_wb_ctl_start_irq(void *arg, int irq_idx)
@@ -1495,6 +1552,7 @@ static void sde_encoder_phys_wb_mode_set(
phys_enc->hw_ctl = NULL; phys_enc->hw_ctl = NULL;
phys_enc->hw_cdm = NULL; phys_enc->hw_cdm = NULL;
phys_enc->hw_dnsc_blur = NULL;
/* Retrieve previously allocated HW Resources. CTL shouldn't fail */ /* Retrieve previously allocated HW Resources. CTL shouldn't fail */
sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL); sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL);
@@ -1526,6 +1584,20 @@ static void sde_encoder_phys_wb_mode_set(
phys_enc->hw_cdm = NULL; phys_enc->hw_cdm = NULL;
} }
/* Downscale Blur is optional */
sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_DNSC_BLUR);
for (i = 0; i <= instance; i++) {
sde_rm_get_hw(rm, &iter);
if (i == instance)
phys_enc->hw_dnsc_blur = to_sde_hw_dnsc_blur(iter.hw);
}
if (IS_ERR(phys_enc->hw_dnsc_blur)) {
SDE_ERROR("Downscale Blur required but not allocated: %ld\n",
PTR_ERR(phys_enc->hw_dnsc_blur));
phys_enc->hw_dnsc_blur = NULL;
}
phys_enc->kickoff_timeout_ms = phys_enc->kickoff_timeout_ms =
sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent); sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);

View File

@@ -304,44 +304,132 @@ error:
return ret; return ret;
} }
int sde_wb_connector_set_property(struct drm_connector *connector, static void _sde_wb_connector_clear_dnsc_blur(struct drm_connector_state *state)
struct drm_connector_state *state,
int property_index,
uint64_t value,
void *display)
{ {
struct sde_wb_device *wb_dev = display; struct sde_connector_state *cstate = to_sde_connector_state(state);
struct drm_framebuffer *out_fb; int i;
int rc = 0;
SDE_DEBUG("\n"); for (i = 0; i < cstate->dnsc_blur_count; i++)
memset(&cstate->dnsc_blur_cfg[i], 0, sizeof(struct sde_drm_dnsc_blur_cfg));
cstate->dnsc_blur_count = 0;
}
if (state && (property_index == CONNECTOR_PROP_OUT_FB)) { static int _sde_wb_connector_set_dnsc_blur(struct sde_wb_device *wb_dev,
const struct sde_format *sde_format; struct drm_connector_state *state, void __user *usr_ptr)
{
struct sde_connector_state *cstate = to_sde_connector_state(state);
struct sde_kms *sde_kms = sde_connector_get_kms(wb_dev->connector);
struct sde_drm_dnsc_blur_cfg *dnsc_blur_cfg = &cstate->dnsc_blur_cfg[0];
u32 copy_count;
int ret = 0, i;
out_fb = sde_connector_get_out_fb(state); if (!sde_kms || !sde_kms->catalog)
if (!out_fb) return -EINVAL;
goto done;
sde_format = sde_get_sde_format_ext(out_fb->format->format, if (!usr_ptr)
out_fb->modifier); goto disable;
if (!sde_format) {
SDE_ERROR("failed to get sde format\n"); /* copy only the first block */
rc = -EINVAL; if (copy_from_user(dnsc_blur_cfg, usr_ptr, sizeof(struct sde_drm_dnsc_blur_cfg))) {
goto done; SDE_ERROR("failed to copy dnsc_blur block 0 data\n");
ret = -EINVAL;
goto disable;
}
if (dnsc_blur_cfg->num_blocks > sde_kms->catalog->dnsc_blur_count) {
SDE_ERROR("invalid number of dnsc_blur blocks:%d\n", dnsc_blur_cfg->num_blocks);
ret = -EINVAL;
goto disable;
}
/* no further data required */
if (dnsc_blur_cfg->num_blocks <= 1)
goto end;
dnsc_blur_cfg++;
usr_ptr += sizeof(struct sde_drm_dnsc_blur_cfg);
copy_count = dnsc_blur_cfg->num_blocks - 1;
/* copy rest of the blocks */
if ((dnsc_blur_cfg->flags & DNSC_BLUR_INDEPENDENT_BLK_CFG)) {
if (copy_from_user(dnsc_blur_cfg, usr_ptr,
copy_count * sizeof(struct sde_drm_dnsc_blur_cfg))) {
SDE_ERROR("failed to copy dnsc_blur data\n");
ret = -EINVAL;
goto disable;
} }
if (!sde_wb_is_format_valid(wb_dev, out_fb->format->format, /* duplicate rest of the blocks */
out_fb->modifier)) { } else if (dnsc_blur_cfg->flags & DNSC_BLUR_MIRROR_BLK_CFG) {
SDE_ERROR("unsupported writeback format 0x%x/0x%llx\n", for (i = 0; i < copy_count; i++) {
out_fb->format->format, memcpy(dnsc_blur_cfg, &cstate->dnsc_blur_cfg[0],
out_fb->modifier); sizeof(struct sde_drm_dnsc_blur_cfg));
rc = -EINVAL; dnsc_blur_cfg++;
goto done;
} }
} }
done: end:
cstate->dnsc_blur_count = dnsc_blur_cfg->num_blocks;
return 0;
disable:
_sde_wb_connector_clear_dnsc_blur(state);
return ret;
}
static int _sde_wb_connector_set_out_fb(struct sde_wb_device *wb_dev,
struct drm_connector_state *state)
{
struct drm_framebuffer *out_fb;
const struct sde_format *sde_format;
int rc = 0;
out_fb = sde_connector_get_out_fb(state);
if (!out_fb)
goto end;
sde_format = sde_get_sde_format_ext(out_fb->format->format, out_fb->modifier);
if (!sde_format) {
SDE_ERROR("failed to get sde format\n");
rc = -EINVAL;
goto end;
}
if (!sde_wb_is_format_valid(wb_dev, out_fb->format->format, out_fb->modifier)) {
SDE_ERROR("unsupported writeback format 0x%x/0x%llx\n",
out_fb->format->format, out_fb->modifier);
rc = -EINVAL;
goto end;
}
end:
return rc;
}
int sde_wb_connector_set_property(struct drm_connector *connector,
struct drm_connector_state *state, int idx, uint64_t value, void *display)
{
struct sde_wb_device *wb_dev = display;
int rc = 0;
if (!connector || !state || !wb_dev) {
SDE_ERROR("invalid argument(s)\n");
return -EINVAL;
}
switch (idx) {
case CONNECTOR_PROP_OUT_FB:
rc = _sde_wb_connector_set_out_fb(wb_dev, state);
break;
case CONNECTOR_PROP_DNSC_BLUR:
rc = _sde_wb_connector_set_dnsc_blur(wb_dev, state,
(void __user *)(uintptr_t)value);
break;
default:
/* nothing to do */
break;
}
return rc; return rc;
} }