Merge "disp: msm: sde: add custom event to notify OPR, MISR value change"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
7f6a4cdee7
@@ -8,6 +8,12 @@
|
|||||||
#define _MSM_DRM_PP_H_
|
#define _MSM_DRM_PP_H_
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <drm/drm.h>
|
||||||
|
|
||||||
|
#define ENABLE_EVENT_SPR_OPR_VALUE
|
||||||
|
#define ENABLE_EVENT_INTF_MISR_SIGNATURE
|
||||||
|
#define MAX_DSI_DISPLAY 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct drm_msm_pcc_coeff - PCC coefficient structure for each color
|
* struct drm_msm_pcc_coeff - PCC coefficient structure for each color
|
||||||
* component.
|
* component.
|
||||||
@@ -752,4 +758,21 @@ struct drm_msm_dimming_bl_lut {
|
|||||||
__u32 mapped_bl[DIMMING_BL_LUT_LEN];
|
__u32 mapped_bl[DIMMING_BL_LUT_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct drm_msm_opr_value {
|
||||||
|
__u32 num_valid_opr;
|
||||||
|
__u32 opr_value[MAX_DSI_DISPLAY];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SDE_MAX_ROI 4
|
||||||
|
struct drm_msm_roi {
|
||||||
|
__u32 num_rects;
|
||||||
|
struct drm_clip_rect roi[SDE_MAX_ROI];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_msm_misr_sign {
|
||||||
|
__u64 num_valid_misr;
|
||||||
|
struct drm_msm_roi roi_list;
|
||||||
|
__u64 misr_sign_value[MAX_DSI_DISPLAY];
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _MSM_DRM_PP_H_ */
|
#endif /* _MSM_DRM_PP_H_ */
|
||||||
|
@@ -917,6 +917,8 @@ struct sde_drm_dnsc_blur_cfg {
|
|||||||
#define DRM_EVENT_FRAME_DATA 0x8000000C
|
#define DRM_EVENT_FRAME_DATA 0x8000000C
|
||||||
#define DRM_EVENT_DIMMING_BL 0X8000000D
|
#define DRM_EVENT_DIMMING_BL 0X8000000D
|
||||||
#define DRM_EVENT_VM_RELEASE 0X8000000E
|
#define DRM_EVENT_VM_RELEASE 0X8000000E
|
||||||
|
#define DRM_EVENT_OPR_VALUE 0X8000000F
|
||||||
|
#define DRM_EVENT_MISR_SIGN 0X80000010
|
||||||
|
|
||||||
#ifndef DRM_MODE_FLAG_VID_MODE_PANEL
|
#ifndef DRM_MODE_FLAG_VID_MODE_PANEL
|
||||||
#define DRM_MODE_FLAG_VID_MODE_PANEL 0x01
|
#define DRM_MODE_FLAG_VID_MODE_PANEL 0x01
|
||||||
|
@@ -837,6 +837,20 @@ static int _set_spr_pu_feature(struct sde_hw_dspp *hw_dspp,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sde_dspp_spr_read_opr_value(struct sde_hw_dspp *hw_dspp, u32 *opr_value)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!opr_value || !hw_dspp || !hw_dspp->ops.read_spr_opr_value)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
rc = hw_dspp->ops.read_spr_opr_value(hw_dspp, opr_value);
|
||||||
|
if (rc)
|
||||||
|
SDE_ERROR("invalid opr read %d", rc);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int _set_demura_pu_feature(struct sde_hw_dspp *hw_dspp,
|
static int _set_demura_pu_feature(struct sde_hw_dspp *hw_dspp,
|
||||||
struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *sde_crtc)
|
struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *sde_crtc)
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -366,4 +367,11 @@ void sde_cp_disable_features(struct drm_crtc *crtc);
|
|||||||
void sde_cp_set_skip_blend_plane_info(struct drm_crtc *crtc,
|
void sde_cp_set_skip_blend_plane_info(struct drm_crtc *crtc,
|
||||||
struct sde_cp_crtc_skip_blend_plane *skip_blend);
|
struct sde_cp_crtc_skip_blend_plane *skip_blend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_dspp_spr_read_opr_value(): read opr value
|
||||||
|
* @hw_dspp: Pointer to DSPP hardware description.
|
||||||
|
* @opr_value: Pointer to opr value.
|
||||||
|
*/
|
||||||
|
int sde_dspp_spr_read_opr_value(struct sde_hw_dspp *hw_dspp, u32 *opr_value);
|
||||||
|
|
||||||
#endif /*_SDE_COLOR_PROCESSING_H */
|
#endif /*_SDE_COLOR_PROCESSING_H */
|
||||||
|
@@ -1794,6 +1794,11 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
|
|||||||
case CONNECTOR_PROP_DYN_TRANSFER_TIME:
|
case CONNECTOR_PROP_DYN_TRANSFER_TIME:
|
||||||
_sde_connector_set_prop_dyn_transfer_time(c_conn, val);
|
_sde_connector_set_prop_dyn_transfer_time(c_conn, val);
|
||||||
break;
|
break;
|
||||||
|
case CONNECTOR_PROP_LP:
|
||||||
|
/* suspend case: clear stale MISR */
|
||||||
|
if (val == SDE_MODE_DPMS_OFF)
|
||||||
|
memset(&c_conn->previous_misr_sign, 0, sizeof(struct sde_misr_sign));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3415,6 +3420,15 @@ int sde_connector_register_custom_event(struct sde_kms *kms,
|
|||||||
c_conn->dimming_bl_notify_enabled = val;
|
c_conn->dimming_bl_notify_enabled = val;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
case DRM_EVENT_MISR_SIGN:
|
||||||
|
if (!conn_drm) {
|
||||||
|
SDE_ERROR("invalid connector\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
c_conn = to_sde_connector(conn_drm);
|
||||||
|
c_conn->misr_event_notify_enabled = val;
|
||||||
|
ret = sde_encoder_register_misr_event(c_conn->encoder, val);
|
||||||
|
break;
|
||||||
case DRM_EVENT_PANEL_DEAD:
|
case DRM_EVENT_PANEL_DEAD:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
@@ -3444,6 +3458,7 @@ int sde_connector_event_notify(struct drm_connector *connector, uint32_t type,
|
|||||||
case DRM_EVENT_DIMMING_BL:
|
case DRM_EVENT_DIMMING_BL:
|
||||||
case DRM_EVENT_PANEL_DEAD:
|
case DRM_EVENT_PANEL_DEAD:
|
||||||
case DRM_EVENT_SDE_HW_RECOVERY:
|
case DRM_EVENT_SDE_HW_RECOVERY:
|
||||||
|
case DRM_EVENT_MISR_SIGN:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -482,6 +482,18 @@ struct sde_connector_dyn_hdr_metadata {
|
|||||||
bool dynamic_hdr_update;
|
bool dynamic_hdr_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct sde_misr_sign - defines sde misr signature structure
|
||||||
|
* @num_valid_misr : count of valid misr signature
|
||||||
|
* @roi_list : list of roi
|
||||||
|
* @misr_sign_value : list of misr signature
|
||||||
|
*/
|
||||||
|
struct sde_misr_sign {
|
||||||
|
atomic64_t num_valid_misr;
|
||||||
|
struct msm_roi_list roi_list;
|
||||||
|
u64 misr_sign_value[MAX_DSI_DISPLAYS];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sde_connector - local sde connector structure
|
* struct sde_connector - local sde connector structure
|
||||||
* @base: Base drm connector structure
|
* @base: Base drm connector structure
|
||||||
@@ -541,6 +553,8 @@ struct sde_connector_dyn_hdr_metadata {
|
|||||||
* @cmd_rx_buf: the return buffer of response of command transfer
|
* @cmd_rx_buf: the return buffer of response of command transfer
|
||||||
* @rx_len: the length of dcs command received buffer
|
* @rx_len: the length of dcs command received buffer
|
||||||
* @cached_edid: cached edid data for the connector
|
* @cached_edid: cached edid data for the connector
|
||||||
|
* @misr_event_notify_enabled: Flag to indicate if misr event notify is enabled or not
|
||||||
|
* @previous_misr_sign: store previous misr signature
|
||||||
*/
|
*/
|
||||||
struct sde_connector {
|
struct sde_connector {
|
||||||
struct drm_connector base;
|
struct drm_connector base;
|
||||||
@@ -616,6 +630,8 @@ struct sde_connector {
|
|||||||
int rx_len;
|
int rx_len;
|
||||||
|
|
||||||
struct edid *cached_edid;
|
struct edid *cached_edid;
|
||||||
|
bool misr_event_notify_enabled;
|
||||||
|
struct sde_misr_sign previous_misr_sign;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -78,7 +78,8 @@ static int _sde_crtc_set_noise_layer(struct sde_crtc *sde_crtc,
|
|||||||
void __user *usr_ptr);
|
void __user *usr_ptr);
|
||||||
static int sde_crtc_vm_release_handler(struct drm_crtc *crtc_drm,
|
static int sde_crtc_vm_release_handler(struct drm_crtc *crtc_drm,
|
||||||
bool en, struct sde_irq_callback *irq);
|
bool en, struct sde_irq_callback *irq);
|
||||||
|
static int sde_crtc_opr_event_handler(struct drm_crtc *crtc_drm,
|
||||||
|
bool en, struct sde_irq_callback *irq);
|
||||||
|
|
||||||
static struct sde_crtc_custom_events custom_events[] = {
|
static struct sde_crtc_custom_events custom_events[] = {
|
||||||
{DRM_EVENT_AD_BACKLIGHT, sde_cp_ad_interrupt},
|
{DRM_EVENT_AD_BACKLIGHT, sde_cp_ad_interrupt},
|
||||||
@@ -92,6 +93,7 @@ static struct sde_crtc_custom_events custom_events[] = {
|
|||||||
{DRM_EVENT_MMRM_CB, sde_crtc_mmrm_interrupt_handler},
|
{DRM_EVENT_MMRM_CB, sde_crtc_mmrm_interrupt_handler},
|
||||||
{DRM_EVENT_VM_RELEASE, sde_crtc_vm_release_handler},
|
{DRM_EVENT_VM_RELEASE, sde_crtc_vm_release_handler},
|
||||||
{DRM_EVENT_FRAME_DATA, sde_crtc_frame_data_interrupt_handler},
|
{DRM_EVENT_FRAME_DATA, sde_crtc_frame_data_interrupt_handler},
|
||||||
|
{DRM_EVENT_OPR_VALUE, sde_crtc_opr_event_handler},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* default input fence timeout, in ms */
|
/* default input fence timeout, in ms */
|
||||||
@@ -2989,6 +2991,56 @@ static void _sde_crtc_retire_event(struct drm_connector *connector,
|
|||||||
SDE_ATRACE_END("signal_retire_fence");
|
SDE_ATRACE_END("signal_retire_fence");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sde_crtc_opr_event_notify(struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
struct sde_crtc *sde_crtc;
|
||||||
|
uint32_t current_opr_value[MAX_DSI_DISPLAYS] = {0};
|
||||||
|
int i, rc;
|
||||||
|
bool updated = false;
|
||||||
|
struct drm_event event;
|
||||||
|
|
||||||
|
sde_crtc = to_sde_crtc(crtc);
|
||||||
|
|
||||||
|
atomic_set(&sde_crtc->previous_opr_value.num_valid_opr, 0);
|
||||||
|
for (i = 0; i < sde_crtc->num_mixers; i++) {
|
||||||
|
rc = sde_dspp_spr_read_opr_value(sde_crtc->mixers[i].hw_dspp,
|
||||||
|
¤t_opr_value[i]);
|
||||||
|
if (rc) {
|
||||||
|
SDE_ERROR("failed to collect OPR %d", i, rc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_inc(&sde_crtc->previous_opr_value.num_valid_opr);
|
||||||
|
if (current_opr_value[i] == sde_crtc->previous_opr_value.opr_value[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sde_crtc->previous_opr_value.opr_value[i] = current_opr_value[i];
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updated) {
|
||||||
|
event.type = DRM_EVENT_OPR_VALUE;
|
||||||
|
event.length = sizeof(sde_crtc->previous_opr_value);
|
||||||
|
msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
|
||||||
|
(u8 *)&sde_crtc->previous_opr_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _sde_crtc_frame_done_notify(struct drm_crtc *crtc,
|
||||||
|
struct sde_crtc_frame_event *fevent)
|
||||||
|
{
|
||||||
|
struct sde_crtc *sde_crtc;
|
||||||
|
struct sde_connector *sde_conn;
|
||||||
|
|
||||||
|
sde_crtc = to_sde_crtc(crtc);
|
||||||
|
if (sde_crtc->opr_event_notify_enabled)
|
||||||
|
sde_crtc_opr_event_notify(crtc);
|
||||||
|
|
||||||
|
sde_conn = to_sde_connector(fevent->connector);
|
||||||
|
if (sde_conn && sde_conn->misr_event_notify_enabled)
|
||||||
|
sde_encoder_misr_sign_event_notify(fevent->connector->encoder);
|
||||||
|
}
|
||||||
|
|
||||||
static void sde_crtc_frame_event_work(struct kthread_work *work)
|
static void sde_crtc_frame_event_work(struct kthread_work *work)
|
||||||
{
|
{
|
||||||
struct msm_drm_private *priv;
|
struct msm_drm_private *priv;
|
||||||
@@ -3059,6 +3111,7 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)
|
|||||||
sde_fence_signal(sde_crtc->output_fence, fevent->ts,
|
sde_fence_signal(sde_crtc->output_fence, fevent->ts,
|
||||||
(fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR)
|
(fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR)
|
||||||
? SDE_FENCE_SIGNAL_ERROR : SDE_FENCE_SIGNAL);
|
? SDE_FENCE_SIGNAL_ERROR : SDE_FENCE_SIGNAL);
|
||||||
|
_sde_crtc_frame_done_notify(crtc, fevent);
|
||||||
SDE_ATRACE_END("signal_release_fence");
|
SDE_ATRACE_END("signal_release_fence");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4913,6 +4966,10 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
|
|||||||
power_on = 0;
|
power_on = 0;
|
||||||
sde_crtc_event_notify(crtc, DRM_EVENT_CRTC_POWER, &power_on, sizeof(u32));
|
sde_crtc_event_notify(crtc, DRM_EVENT_CRTC_POWER, &power_on, sizeof(u32));
|
||||||
|
|
||||||
|
/* suspend case: clear stale OPR value */
|
||||||
|
if (sde_crtc->opr_event_notify_enabled)
|
||||||
|
memset(&sde_crtc->previous_opr_value, 0, sizeof(struct sde_opr_value));
|
||||||
|
|
||||||
mutex_unlock(&sde_crtc->crtc_lock);
|
mutex_unlock(&sde_crtc->crtc_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7859,6 +7916,19 @@ static int sde_crtc_mmrm_interrupt_handler(struct drm_crtc *crtc_drm,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sde_crtc_opr_event_handler(struct drm_crtc *crtc_drm,
|
||||||
|
bool en, struct sde_irq_callback *irq)
|
||||||
|
{
|
||||||
|
struct sde_crtc *sde_crtc;
|
||||||
|
|
||||||
|
sde_crtc = to_sde_crtc(crtc_drm);
|
||||||
|
if (!sde_crtc)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
sde_crtc->opr_event_notify_enabled = en;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int sde_crtc_vm_release_handler(struct drm_crtc *crtc_drm,
|
static int sde_crtc_vm_release_handler(struct drm_crtc *crtc_drm,
|
||||||
bool en, struct sde_irq_callback *irq)
|
bool en, struct sde_irq_callback *irq)
|
||||||
{
|
{
|
||||||
|
@@ -232,6 +232,16 @@ struct sde_frame_data {
|
|||||||
struct sde_frame_data_buffer *buf[SDE_FRAME_DATA_BUFFER_MAX];
|
struct sde_frame_data_buffer *buf[SDE_FRAME_DATA_BUFFER_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct sde_opr_value - defines sde opr value structure
|
||||||
|
* @num_valid_opr : count of valid opr values
|
||||||
|
* @opr_value : list of opr value
|
||||||
|
*/
|
||||||
|
struct sde_opr_value {
|
||||||
|
atomic_t num_valid_opr;
|
||||||
|
u32 opr_value[MAX_DSI_DISPLAYS];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sde_crtc - virtualized CRTC data structure
|
* struct sde_crtc - virtualized CRTC data structure
|
||||||
* @base : Base drm crtc structure
|
* @base : Base drm crtc structure
|
||||||
@@ -317,6 +327,8 @@ struct sde_frame_data {
|
|||||||
* @skip_blend_plane_h: skip blend plane height
|
* @skip_blend_plane_h: skip blend plane height
|
||||||
* @line_time_in_ns : current mode line time in nano sec is needed for QOS update
|
* @line_time_in_ns : current mode line time in nano sec is needed for QOS update
|
||||||
* @frame_data : Framedata data structure
|
* @frame_data : Framedata data structure
|
||||||
|
* @previous_opr_value : store previous opr values
|
||||||
|
* @opr_event_notify_enabled : Flag to indicate if opr event notify is enabled or not
|
||||||
*/
|
*/
|
||||||
struct sde_crtc {
|
struct sde_crtc {
|
||||||
struct drm_crtc base;
|
struct drm_crtc base;
|
||||||
@@ -423,6 +435,9 @@ struct sde_crtc {
|
|||||||
u32 line_time_in_ns;
|
u32 line_time_in_ns;
|
||||||
|
|
||||||
struct sde_frame_data frame_data;
|
struct sde_frame_data frame_data;
|
||||||
|
|
||||||
|
struct sde_opr_value previous_opr_value;
|
||||||
|
bool opr_event_notify_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sde_crtc_dirty_flags {
|
enum sde_crtc_dirty_flags {
|
||||||
|
@@ -77,6 +77,9 @@
|
|||||||
/* Maximum number of VSYNC wait attempts for RSC state transition */
|
/* Maximum number of VSYNC wait attempts for RSC state transition */
|
||||||
#define MAX_RSC_WAIT 5
|
#define MAX_RSC_WAIT 5
|
||||||
|
|
||||||
|
#define IS_ROI_UPDATED(a, b) (a.x1 != b.x1 || a.x2 != b.x2 || \
|
||||||
|
a.y1 != b.y1 || a.y2 != b.y2)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum sde_enc_rc_events - events for resource control state machine
|
* enum sde_enc_rc_events - events for resource control state machine
|
||||||
* @SDE_ENC_RC_EVENT_KICKOFF:
|
* @SDE_ENC_RC_EVENT_KICKOFF:
|
||||||
@@ -2193,6 +2196,7 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc,
|
|||||||
struct drm_crtc *crtc = drm_enc->crtc;
|
struct drm_crtc *crtc = drm_enc->crtc;
|
||||||
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
|
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
|
||||||
struct sde_connector *sde_conn;
|
struct sde_connector *sde_conn;
|
||||||
|
int crtc_id = 0;
|
||||||
|
|
||||||
priv = drm_enc->dev->dev_private;
|
priv = drm_enc->dev->dev_private;
|
||||||
sde_kms = to_sde_kms(priv->kms);
|
sde_kms = to_sde_kms(priv->kms);
|
||||||
@@ -2218,10 +2222,14 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crtc_id = drm_crtc_index(crtc);
|
||||||
if (is_vid_mode) {
|
if (is_vid_mode) {
|
||||||
sde_encoder_irq_control(drm_enc, false);
|
sde_encoder_irq_control(drm_enc, false);
|
||||||
_sde_encoder_pm_qos_remove_request(drm_enc);
|
_sde_encoder_pm_qos_remove_request(drm_enc);
|
||||||
} else {
|
} else {
|
||||||
|
if (priv->event_thread[crtc_id].thread)
|
||||||
|
kthread_flush_worker(&priv->event_thread[crtc_id].worker);
|
||||||
|
|
||||||
/* disable all the clks and resources */
|
/* disable all the clks and resources */
|
||||||
_sde_encoder_update_rsc_client(drm_enc, false);
|
_sde_encoder_update_rsc_client(drm_enc, false);
|
||||||
_sde_encoder_resource_control_helper(drm_enc, false);
|
_sde_encoder_resource_control_helper(drm_enc, false);
|
||||||
@@ -2985,6 +2993,13 @@ void sde_encoder_virt_restore(struct drm_encoder *drm_enc)
|
|||||||
|
|
||||||
_sde_encoder_virt_enable_helper(drm_enc);
|
_sde_encoder_virt_enable_helper(drm_enc);
|
||||||
sde_encoder_control_te(drm_enc, true);
|
sde_encoder_control_te(drm_enc, true);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* During IPC misr ctl register is reset.
|
||||||
|
* Need to reconfigure misr after every IPC.
|
||||||
|
*/
|
||||||
|
if (atomic_read(&sde_enc->misr_enable))
|
||||||
|
sde_enc->misr_reconfigure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sde_encoder_populate_encoder_phys(struct drm_encoder *drm_enc,
|
static void sde_encoder_populate_encoder_phys(struct drm_encoder *drm_enc,
|
||||||
@@ -3032,7 +3047,7 @@ static void sde_encoder_populate_encoder_phys(struct drm_encoder *drm_enc,
|
|||||||
phys->ops.enable(phys);
|
phys->ops.enable(phys);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sde_enc->misr_enable && phys->ops.setup_misr &&
|
if (atomic_read(&sde_enc->misr_enable) && phys->ops.setup_misr &&
|
||||||
(sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE)))
|
(sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE)))
|
||||||
phys->ops.setup_misr(phys, true,
|
phys->ops.setup_misr(phys, true,
|
||||||
sde_enc->misr_frame_count);
|
sde_enc->misr_frame_count);
|
||||||
@@ -3977,7 +3992,7 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sde_enc->misr_enable)
|
if (atomic_read(&sde_enc->misr_enable))
|
||||||
sde_encoder_misr_configure(&sde_enc->base, true,
|
sde_encoder_misr_configure(&sde_enc->base, true,
|
||||||
sde_enc->misr_frame_count);
|
sde_enc->misr_frame_count);
|
||||||
|
|
||||||
@@ -4888,7 +4903,7 @@ static ssize_t _sde_encoder_misr_setup(struct file *file,
|
|||||||
if (sscanf(buf, "%u %u", &enable, &frame_count) != 2)
|
if (sscanf(buf, "%u %u", &enable, &frame_count) != 2)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sde_enc->misr_enable = enable;
|
atomic_set(&sde_enc->misr_enable, enable);
|
||||||
sde_enc->misr_reconfigure = true;
|
sde_enc->misr_reconfigure = true;
|
||||||
sde_enc->misr_frame_count = frame_count;
|
sde_enc->misr_frame_count = frame_count;
|
||||||
return count;
|
return count;
|
||||||
@@ -4935,7 +4950,7 @@ static ssize_t _sde_encoder_misr_read(struct file *file,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sde_enc->misr_enable) {
|
if (!atomic_read(&sde_enc->misr_enable)) {
|
||||||
len += scnprintf(buf + len, MISR_BUFF_SIZE - len,
|
len += scnprintf(buf + len, MISR_BUFF_SIZE - len,
|
||||||
"disabled\n");
|
"disabled\n");
|
||||||
goto buff_check;
|
goto buff_check;
|
||||||
@@ -5914,3 +5929,80 @@ void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc)
|
|||||||
phys_enc->ops.add_to_minidump(phys_enc);
|
phys_enc->ops.add_to_minidump(phys_enc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sde_encoder_misr_sign_event_notify(struct drm_encoder *drm_enc)
|
||||||
|
{
|
||||||
|
struct drm_event event;
|
||||||
|
struct drm_connector *connector;
|
||||||
|
struct sde_connector *c_conn = NULL;
|
||||||
|
struct sde_connector_state *c_state = NULL;
|
||||||
|
struct sde_encoder_virt *sde_enc = NULL;
|
||||||
|
struct sde_encoder_phys *phys = NULL;
|
||||||
|
u32 current_misr_value[MAX_DSI_DISPLAYS] = {0};
|
||||||
|
int rc = 0, i = 0;
|
||||||
|
bool misr_updated = false, roi_updated = false;
|
||||||
|
struct msm_roi_list *prev_roi, *c_state_roi;
|
||||||
|
|
||||||
|
if (!drm_enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sde_enc = to_sde_encoder_virt(drm_enc);
|
||||||
|
if (!atomic_read(&sde_enc->misr_enable)) {
|
||||||
|
SDE_DEBUG("MISR is disabled\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connector = sde_enc->cur_master->connector;
|
||||||
|
if (!connector)
|
||||||
|
return;
|
||||||
|
|
||||||
|
c_conn = to_sde_connector(connector);
|
||||||
|
c_state = to_sde_connector_state(connector->state);
|
||||||
|
|
||||||
|
atomic64_set(&c_conn->previous_misr_sign.num_valid_misr, 0);
|
||||||
|
for (i = 0; i < sde_enc->num_phys_encs; i++) {
|
||||||
|
phys = sde_enc->phys_encs[i];
|
||||||
|
|
||||||
|
if (!phys || !phys->ops.collect_misr) {
|
||||||
|
SDE_DEBUG("invalid misr ops\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = phys->ops.collect_misr(phys, true, ¤t_misr_value[i]);
|
||||||
|
if (rc) {
|
||||||
|
SDE_ERROR("failed to collect misr %d\n", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic64_inc(&c_conn->previous_misr_sign.num_valid_misr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sde_enc->num_phys_encs; i++) {
|
||||||
|
if (current_misr_value[i] != c_conn->previous_misr_sign.misr_sign_value[i]) {
|
||||||
|
c_conn->previous_misr_sign.misr_sign_value[i] = current_misr_value[i];
|
||||||
|
misr_updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_roi = &c_conn->previous_misr_sign.roi_list;
|
||||||
|
c_state_roi = &c_state->rois;
|
||||||
|
|
||||||
|
if (prev_roi->num_rects != c_state_roi->num_rects) {
|
||||||
|
roi_updated = true;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < prev_roi->num_rects; i++) {
|
||||||
|
if (IS_ROI_UPDATED(prev_roi->roi[i], c_state_roi->roi[i]))
|
||||||
|
roi_updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roi_updated)
|
||||||
|
memcpy(&c_conn->previous_misr_sign.roi_list, &c_state->rois, sizeof(c_state->rois));
|
||||||
|
|
||||||
|
if (misr_updated || roi_updated) {
|
||||||
|
event.type = DRM_EVENT_MISR_SIGN;
|
||||||
|
event.length = sizeof(c_conn->previous_misr_sign);
|
||||||
|
msm_mode_object_event_notify(&connector->base, connector->dev, &event,
|
||||||
|
(u8 *)&c_conn->previous_misr_sign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -222,7 +222,7 @@ struct sde_encoder_virt {
|
|||||||
struct sde_rsc_client *rsc_client;
|
struct sde_rsc_client *rsc_client;
|
||||||
bool rsc_state_init;
|
bool rsc_state_init;
|
||||||
struct msm_display_info disp_info;
|
struct msm_display_info disp_info;
|
||||||
bool misr_enable;
|
atomic_t misr_enable;
|
||||||
bool misr_reconfigure;
|
bool misr_reconfigure;
|
||||||
u32 misr_frame_count;
|
u32 misr_frame_count;
|
||||||
|
|
||||||
@@ -692,4 +692,38 @@ static inline bool sde_encoder_is_widebus_enabled(struct drm_encoder *drm_enc)
|
|||||||
bool sde_encoder_is_line_insertion_supported(struct drm_encoder *drm_enc);
|
bool sde_encoder_is_line_insertion_supported(struct drm_encoder *drm_enc);
|
||||||
|
|
||||||
void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc);
|
void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_encoder_misr_sign_event_notify - collect MISR, check with previous value
|
||||||
|
* if change then notify to client with custom event
|
||||||
|
* @drm_enc: pointer to drm encoder
|
||||||
|
*/
|
||||||
|
void sde_encoder_misr_sign_event_notify(struct drm_encoder *drm_enc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_encoder_register_misr_event - register or deregister MISR event
|
||||||
|
* @drm_enc: pointer to drm encoder
|
||||||
|
* @val: indicates register or deregister
|
||||||
|
*/
|
||||||
|
static inline int sde_encoder_register_misr_event(struct drm_encoder *drm_enc, bool val)
|
||||||
|
{
|
||||||
|
struct sde_encoder_virt *sde_enc = NULL;
|
||||||
|
|
||||||
|
if (!drm_enc)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
sde_enc = to_sde_encoder_virt(drm_enc);
|
||||||
|
atomic_set(&sde_enc->misr_enable, val);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To setup MISR ctl reg, set misr_reconfigure as true.
|
||||||
|
* MISR is calculated for the specific number of frames.
|
||||||
|
*/
|
||||||
|
if (atomic_read(&sde_enc->misr_enable)) {
|
||||||
|
sde_enc->misr_reconfigure = true;
|
||||||
|
sde_enc->misr_frame_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* __SDE_ENCODER_H__ */
|
#endif /* __SDE_ENCODER_H__ */
|
||||||
|
@@ -745,3 +745,17 @@ void sde_demura_pu_cfg(struct sde_hw_dspp *dspp, void *cfg)
|
|||||||
((roi_list) ? roi_list->roi[0].y2 : -1),
|
((roi_list) ? roi_list->roi[0].y2 : -1),
|
||||||
((hw_cfg) ? hw_cfg->panel_height : -1));
|
((hw_cfg) ? hw_cfg->panel_height : -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sde_spr_read_opr_value(struct sde_hw_dspp *ctx, uint32_t *opr_value)
|
||||||
|
{
|
||||||
|
uint32_t reg_off;
|
||||||
|
|
||||||
|
if (!ctx || !opr_value)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
reg_off = ctx->cap->sblk->spr.base + 0x78;
|
||||||
|
|
||||||
|
*opr_value = SDE_REG_READ(&ctx->hw, reg_off);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -153,4 +153,12 @@ void sde_setup_fp16_unmultv1(struct sde_hw_pipe *ctx,
|
|||||||
* @cfg: partial update configuraton for the frame.
|
* @cfg: partial update configuraton for the frame.
|
||||||
*/
|
*/
|
||||||
void sde_demura_pu_cfg(struct sde_hw_dspp *ctx, void *cfg);
|
void sde_demura_pu_cfg(struct sde_hw_dspp *ctx, void *cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_spr_read_opr_value - api to read spr opr value
|
||||||
|
* @ctx: pointer to dspp object.
|
||||||
|
* @opr_value: Pointer to opr value.
|
||||||
|
*/
|
||||||
|
int sde_spr_read_opr_value(struct sde_hw_dspp *ctx, uint32_t *opr_value);
|
||||||
|
|
||||||
#endif /* _SDE_HW_COLOR_PROC_V4_H_ */
|
#endif /* _SDE_HW_COLOR_PROC_V4_H_ */
|
||||||
|
@@ -343,6 +343,7 @@ static void dspp_spr(struct sde_hw_dspp *c)
|
|||||||
|
|
||||||
c->ops.setup_spr_init_config = reg_dmav1_setup_spr_init_cfgv1;
|
c->ops.setup_spr_init_config = reg_dmav1_setup_spr_init_cfgv1;
|
||||||
c->ops.setup_spr_pu_config = reg_dmav1_setup_spr_pu_cfgv1;
|
c->ops.setup_spr_pu_config = reg_dmav1_setup_spr_pu_cfgv1;
|
||||||
|
c->ops.read_spr_opr_value = sde_spr_read_opr_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -268,6 +269,14 @@ struct sde_hw_dspp_ops {
|
|||||||
* @cfg: Pointer to configuration
|
* @cfg: Pointer to configuration
|
||||||
*/
|
*/
|
||||||
void (*setup_spr_pu_config)(struct sde_hw_dspp *ctx, void *cfg);
|
void (*setup_spr_pu_config)(struct sde_hw_dspp *ctx, void *cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read_spr_opr_value - function to read spr opr value
|
||||||
|
* @ctx: Pointer to dspp context
|
||||||
|
* @opr_value: Pointer to opr value
|
||||||
|
*/
|
||||||
|
int (*read_spr_opr_value)(struct sde_hw_dspp *ctx, u32 *opr_value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* setup_demura_cfg - function to program demura cfg
|
* setup_demura_cfg - function to program demura cfg
|
||||||
* @ctx: Pointer to dspp context
|
* @ctx: Pointer to dspp context
|
||||||
|
Reference in New Issue
Block a user