Browse Source

disp: msm: sde: frame data feature

Add support to send a data packet of info, written to
predefined buffers, providing information about each submitted frame.
Add required UAPI definitions for frame data buffers and event
notification.
Add support to read ubwc statistics from hw, based on defined rois.

Change-Id: I51f279de98ae4e2a02b0df6943d334764011d5db
Signed-off-by: Nilaan Gunabalachandran <[email protected]>
Nilaan Gunabalachandran 4 years ago
parent
commit
c5835a215e

+ 87 - 0
include/uapi/display/drm/sde_drm.h

@@ -526,6 +526,92 @@ struct sde_drm_roi_v1 {
 #define SDE_RECOVERY_CAPTURE		1
 #define SDE_RECOVERY_CAPTURE		1
 #define SDE_RECOVERY_HARD_RESET		2
 #define SDE_RECOVERY_HARD_RESET		2
 
 
+/**
+ * Define UBWC statistics config
+ */
+#define UBWC_STATS_MAX_ROI		0x3
+
+/**
+ * struct sde_drm_ubwc_stats_roi - region of interest for ubwc stats
+ * y_coord0: first y offset from top of display
+ * y_coord1: second y offset from top of display
+ */
+struct sde_drm_ubwc_stats_roi {
+	__u16 y_coord0;
+	__u16 y_coord1;
+};
+
+/**
+ * struct sde_drm_ubwc_stats_data: ubwc statistics
+ * roi: region of interest
+ * worst_bw: worst bandwidth, per roi
+ * worst_bw_y_coord: y offset (row) location of worst bandwidth, per roi
+ * total_bw: total bandwidth, per roi
+ * error: error status
+ * meta_error: meta error data
+ */
+struct sde_drm_ubwc_stats_data {
+	struct sde_drm_ubwc_stats_roi roi;
+	__u16 worst_bw[UBWC_STATS_MAX_ROI];
+	__u16 worst_bw_y_coord[UBWC_STATS_MAX_ROI];
+	__u32 total_bw[UBWC_STATS_MAX_ROI];
+	__u32 error;
+	__u32 meta_error;
+};
+
+/**
+ * Define frame data config
+ */
+#define SDE_FRAME_DATA_BUFFER_MAX	0x3
+#define SDE_FRAME_DATA_GUARD_BYTES	0xFF
+#define SDE_FRAME_DATA_MAX_PLANES	0x10
+
+/**
+ * struct sde_drm_frame_data_buffers_ctrl - control frame data buffers
+ * num_buffers: number of allocated buffers
+ * fds: fd list for allocated buffers
+ */
+struct sde_drm_frame_data_buffers_ctrl {
+	__u32 num_buffers;
+	__u32 fds[SDE_FRAME_DATA_BUFFER_MAX];
+};
+
+/**
+ * struct sde_drm_frame_data_buf - frame data buffer info sent to userspace
+ * fd: buffer fd
+ * offset: offset from buffer address
+ * status: status flag
+ */
+struct sde_drm_frame_data_buf {
+	__u32 fd;
+	__u32 offset;
+	__u32 status;
+};
+
+/**
+ * struct sde_drm_plane_frame_data - definition of plane frame data struct
+ * plane_id: drm plane id
+ * ubwc_stats: ubwc statistics
+ */
+struct sde_drm_plane_frame_data {
+	__u32 plane_id;
+
+	struct sde_drm_ubwc_stats_data ubwc_stats;
+};
+
+/**
+ * struct sde_drm_frame_data_packet - definition of frame data struct
+ * frame_count: interface frame count
+ * commit_count: sw commit count
+ * plane_frame_data: data available per plane
+ */
+struct sde_drm_frame_data_packet {
+	__u32 frame_count;
+	__u64 commit_count;
+
+	struct sde_drm_plane_frame_data plane_frame_data[SDE_FRAME_DATA_MAX_PLANES];
+};
+
 /*
 /*
  * Colorimetry Data Block values
  * Colorimetry Data Block values
  * These bit nums are defined as per the CTA spec
  * These bit nums are defined as per the CTA spec
@@ -723,6 +809,7 @@ struct drm_msm_noise_layer_cfg {
 #define DRM_EVENT_LTM_WB_PB 0X80000009
 #define DRM_EVENT_LTM_WB_PB 0X80000009
 #define DRM_EVENT_LTM_OFF 0X8000000A
 #define DRM_EVENT_LTM_OFF 0X8000000A
 #define DRM_EVENT_MMRM_CB 0X8000000B
 #define DRM_EVENT_MMRM_CB 0X8000000B
+#define DRM_EVENT_FRAME_DATA 0x8000000C
 
 
 #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

+ 2 - 0
msm/msm_drv.h

@@ -136,6 +136,7 @@ enum msm_mdp_plane_property {
 	PLANE_PROP_INVERSE_PMA,
 	PLANE_PROP_INVERSE_PMA,
 	PLANE_PROP_FP16_IGC,
 	PLANE_PROP_FP16_IGC,
 	PLANE_PROP_FP16_UNMULT,
 	PLANE_PROP_FP16_UNMULT,
+	PLANE_PROP_UBWC_STATS_ROI,
 
 
 	/* enum/bitmask properties */
 	/* enum/bitmask properties */
 	PLANE_PROP_BLEND_OP,
 	PLANE_PROP_BLEND_OP,
@@ -181,6 +182,7 @@ enum msm_mdp_crtc_property {
 	CRTC_PROP_CACHE_STATE,
 	CRTC_PROP_CACHE_STATE,
 	CRTC_PROP_VM_REQ_STATE,
 	CRTC_PROP_VM_REQ_STATE,
 	CRTC_PROP_NOISE_LAYER_V1,
 	CRTC_PROP_NOISE_LAYER_V1,
+	CRTC_PROP_FRAME_DATA_BUF,
 
 
 	/* total # of properties */
 	/* total # of properties */
 	CRTC_PROP_COUNT
 	CRTC_PROP_COUNT

+ 164 - 34
msm/sde/sde_crtc.c

@@ -454,6 +454,23 @@ static const struct attribute_group *sde_crtc_attr_groups[] = {
 	NULL,
 	NULL,
 };
 };
 
 
+static void sde_crtc_event_notify(struct drm_crtc *crtc, uint32_t type, uint32_t len, uint64_t val)
+{
+	struct drm_event event;
+
+	if (!crtc) {
+		SDE_ERROR("invalid crtc\n");
+		return;
+	}
+
+	event.type = type;
+	event.length = len;
+	msm_mode_object_event_notify(&crtc->base, crtc->dev, &event, (u8 *)&val);
+
+	SDE_EVT32(DRMID(crtc), type, len, val >> 32, val & 0xFFFFFFFF);
+	SDE_DEBUG("crtc:%d event(%d) value(%llu) notified\n", DRMID(crtc), type, val);
+}
+
 static void sde_crtc_destroy(struct drm_crtc *crtc)
 static void sde_crtc_destroy(struct drm_crtc *crtc)
 {
 {
 	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
 	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
@@ -2313,6 +2330,144 @@ static void _sde_crtc_dest_scaler_setup(struct drm_crtc *crtc)
 	}
 	}
 }
 }
 
 
+static void _sde_crtc_put_frame_data_buffer(struct sde_frame_data_buffer *buf)
+{
+	if (!buf)
+		return;
+
+	msm_gem_put_buffer(buf->gem);
+	kfree(buf);
+	buf = NULL;
+}
+
+static int _sde_crtc_get_frame_data_buffer(struct drm_crtc *crtc, uint32_t fd)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_frame_data_buffer *buf;
+	uint32_t cur_buf;
+
+	sde_crtc = to_sde_crtc(crtc);
+	cur_buf = sde_crtc->frame_data.cnt;
+
+	buf = kzalloc(sizeof(struct sde_frame_data_buffer), GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	sde_crtc->frame_data.buf[cur_buf] = buf;
+	buf->fb = drm_framebuffer_lookup(crtc->dev, NULL, fd);
+	if (!buf->fb) {
+		SDE_ERROR("unable to get fb");
+		return -EINVAL;
+	}
+
+	buf->gem = msm_framebuffer_bo(buf->fb, 0);
+	if (!buf->gem) {
+		SDE_ERROR("unable to get drm gem");
+		return -EINVAL;
+	}
+
+	return msm_gem_get_buffer(buf->gem, crtc->dev, buf->fb,
+			sizeof(struct sde_drm_frame_data_packet));
+}
+
+static void _sde_crtc_set_frame_data_buffers(struct drm_crtc *crtc,
+			struct sde_crtc_state *cstate, void __user *usr)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_drm_frame_data_buffers_ctrl ctrl;
+	int i, ret;
+
+	if (!crtc || !cstate || !usr)
+		return;
+
+	sde_crtc = to_sde_crtc(crtc);
+
+	ret = copy_from_user(&ctrl, usr, sizeof(ctrl));
+	if (ret) {
+		SDE_ERROR("failed to copy frame data ctrl, ret %d\n", ret);
+		return;
+	}
+
+	if (!ctrl.num_buffers) {
+		SDE_DEBUG("clearing frame data buffers");
+		goto exit;
+	} else if (ctrl.num_buffers > SDE_FRAME_DATA_BUFFER_MAX) {
+		SDE_ERROR("invalid number of buffers %d", ctrl.num_buffers);
+		return;
+	}
+
+	for (i = 0; i < ctrl.num_buffers; i++) {
+		if (_sde_crtc_get_frame_data_buffer(crtc, ctrl.fds[i])) {
+			SDE_ERROR("unable to set buffer for fd %d", ctrl.fds[i]);
+			goto exit;
+		}
+		sde_crtc->frame_data.cnt++;
+	}
+
+	return;
+exit:
+	while (sde_crtc->frame_data.cnt--)
+		_sde_crtc_put_frame_data_buffer(
+				sde_crtc->frame_data.buf[sde_crtc->frame_data.cnt]);
+}
+
+static void _sde_crtc_frame_data_notify(struct drm_crtc *crtc,
+		struct sde_drm_frame_data_packet *frame_data_packet)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_drm_frame_data_buf buf;
+	struct msm_gem_object *msm_gem;
+	u32 cur_buf;
+
+	sde_crtc = to_sde_crtc(crtc);
+	cur_buf = sde_crtc->frame_data.idx;
+	msm_gem = to_msm_bo(sde_crtc->frame_data.buf[cur_buf]->gem);
+
+	buf.fd = sde_crtc->frame_data.buf[cur_buf]->fd;
+	buf.offset = msm_gem->offset;
+
+	sde_crtc_event_notify(crtc, DRM_EVENT_FRAME_DATA, sizeof(struct sde_drm_frame_data_buf),
+			(uint64_t)(&buf));
+
+	sde_crtc->frame_data.idx = ++sde_crtc->frame_data.idx % sde_crtc->frame_data.cnt;
+}
+
+void sde_crtc_get_frame_data(struct drm_crtc *crtc)
+{
+	struct sde_crtc *sde_crtc;
+	struct drm_plane *plane;
+	struct sde_drm_frame_data_packet frame_data_packet = {0, 0};
+	struct sde_drm_frame_data_packet *data;
+	struct sde_frame_data *frame_data;
+	int i = 0;
+
+	if (!crtc || !crtc->state)
+		return;
+
+	sde_crtc = to_sde_crtc(crtc);
+	frame_data = &sde_crtc->frame_data;
+
+	if (frame_data->cnt) {
+		struct msm_gem_object *msm_gem;
+
+		msm_gem = to_msm_bo(frame_data->buf[frame_data->cnt]->gem);
+		data = (struct sde_drm_frame_data_packet *)
+				(((u8 *)msm_gem->vaddr) + msm_gem->offset);
+	} else {
+		data = &frame_data_packet;
+	}
+
+	data->commit_count = sde_crtc->play_count;
+	data->frame_count = sde_crtc->fps_info.frame_count;
+
+	/* Collect plane specific data */
+	drm_for_each_plane_mask(plane, crtc->dev, sde_crtc->plane_mask_old)
+		sde_plane_get_frame_data(plane, &data->plane_frame_data[i]);
+
+	if (frame_data->cnt)
+		_sde_crtc_frame_data_notify(crtc, data);
+}
+
 static void sde_crtc_frame_event_cb(void *data, u32 event, ktime_t ts)
 static void sde_crtc_frame_event_cb(void *data, u32 event, ktime_t ts)
 {
 {
 	struct drm_crtc *crtc = (struct drm_crtc *)data;
 	struct drm_crtc *crtc = (struct drm_crtc *)data;
@@ -2320,8 +2475,6 @@ static void sde_crtc_frame_event_cb(void *data, u32 event, ktime_t ts)
 	struct msm_drm_private *priv;
 	struct msm_drm_private *priv;
 	struct sde_crtc_frame_event *fevent;
 	struct sde_crtc_frame_event *fevent;
 	struct sde_kms_frame_event_cb_data *cb_data;
 	struct sde_kms_frame_event_cb_data *cb_data;
-	struct drm_plane *plane;
-	u32 ubwc_error, meta_error;
 	unsigned long flags;
 	unsigned long flags;
 	u32 crtc_id;
 	u32 crtc_id;
 
 
@@ -2360,21 +2513,8 @@ static void sde_crtc_frame_event_cb(void *data, u32 event, ktime_t ts)
 	/* log and clear plane ubwc errors if any */
 	/* log and clear plane ubwc errors if any */
 	if (event & (SDE_ENCODER_FRAME_EVENT_ERROR
 	if (event & (SDE_ENCODER_FRAME_EVENT_ERROR
 				| SDE_ENCODER_FRAME_EVENT_PANEL_DEAD
 				| SDE_ENCODER_FRAME_EVENT_PANEL_DEAD
-				| SDE_ENCODER_FRAME_EVENT_DONE)) {
-		drm_for_each_plane_mask(plane, crtc->dev,
-						sde_crtc->plane_mask_old) {
-			ubwc_error = sde_plane_get_ubwc_error(plane);
-			meta_error = sde_plane_get_meta_error(plane);
-			if (ubwc_error | meta_error) {
-				SDE_EVT32(DRMID(crtc), DRMID(plane), ubwc_error,
-						meta_error, SDE_EVTLOG_ERROR);
-				SDE_DEBUG("crtc%d plane %d ubwc_error %d meta_error %d\n",
-						DRMID(crtc), DRMID(plane), ubwc_error, meta_error);
-				sde_plane_clear_ubwc_error(plane);
-				sde_plane_clear_meta_error(plane);
-			}
-		}
-	}
+				| SDE_ENCODER_FRAME_EVENT_DONE))
+		sde_crtc_get_frame_data(crtc);
 
 
 	if ((event & SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE) &&
 	if ((event & SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE) &&
 		(sde_crtc && sde_crtc->retire_frame_event_sf)) {
 		(sde_crtc && sde_crtc->retire_frame_event_sf)) {
@@ -2654,23 +2794,6 @@ static void sde_crtc_frame_event_work(struct kthread_work *work)
 	SDE_ATRACE_END("crtc_frame_event");
 	SDE_ATRACE_END("crtc_frame_event");
 }
 }
 
 
-static void sde_crtc_event_notify(struct drm_crtc *crtc, uint32_t type, uint32_t len, uint32_t val)
-{
-	struct drm_event event;
-
-	if (!crtc) {
-		SDE_ERROR("invalid crtc\n");
-		return;
-	}
-
-	event.type = type;
-	event.length = len;
-	msm_mode_object_event_notify(&crtc->base, crtc->dev, &event, (u8 *)&val);
-
-	SDE_EVT32(DRMID(crtc), type, len, val);
-	SDE_DEBUG("crtc:%d event(%d) value(%d) notified\n", DRMID(crtc), type, val);
-}
-
 void sde_crtc_complete_commit(struct drm_crtc *crtc,
 void sde_crtc_complete_commit(struct drm_crtc *crtc,
 		struct drm_crtc_state *old_state)
 		struct drm_crtc_state *old_state)
 {
 {
@@ -5707,6 +5830,10 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
 
 
 	sde_crtc_install_noise_layer_properties(sde_crtc, catalog, info);
 	sde_crtc_install_noise_layer_properties(sde_crtc, catalog, info);
 
 
+	if (catalog->has_ubwc_stats)
+		msm_property_install_range(&sde_crtc->property_info, "frame_data",
+				0x0, 0, ~0, 0, CRTC_PROP_FRAME_DATA_BUF);
+
 	kfree(info);
 	kfree(info);
 }
 }
 
 
@@ -5862,6 +5989,9 @@ static int sde_crtc_atomic_set_property(struct drm_crtc *crtc,
 		_sde_crtc_set_noise_layer(sde_crtc, cstate,
 		_sde_crtc_set_noise_layer(sde_crtc, cstate,
 					(void __user *)(uintptr_t)val);
 					(void __user *)(uintptr_t)val);
 		break;
 		break;
+	case CRTC_PROP_FRAME_DATA_BUF:
+		_sde_crtc_set_frame_data_buffers(crtc, cstate, (void __user *)(uintptr_t)val);
+		break;
 	default:
 	default:
 		/* nothing to do */
 		/* nothing to do */
 		break;
 		break;

+ 27 - 0
msm/sde/sde_crtc.h

@@ -224,6 +224,30 @@ struct sde_crtc_misr_info {
  */
  */
 #define SDE_CRTC_MAX_EVENT_COUNT	16
 #define SDE_CRTC_MAX_EVENT_COUNT	16
 
 
+/**
+ * struct sde_frame_data_buffer - defines frame data buffer structure
+ * @fd: framebuffer id associated with this buffer
+ * @fb: drm framebuffer for the buffer
+ * @gem: drm gem handle for he buffer
+ */
+struct sde_frame_data_buffer {
+	u32 fd;
+	struct drm_framebuffer *fb;
+	struct drm_gem_object *gem;
+};
+
+/**
+ * struct sde_frame_data - defines sde frame data structure
+ * @idx : currently used frame data buffe
+ * @cnt : rnumber of available frame data buffers
+ * @buf : list of frame data buffers
+ */
+struct sde_frame_data {
+	u32 idx;
+	u32 cnt;
+	struct sde_frame_data_buffer *buf[SDE_FRAME_DATA_BUFFER_MAX];
+};
+
 /**
 /**
  * struct sde_crtc - virtualized CRTC data structure
  * struct sde_crtc - virtualized CRTC data structure
  * @base          : Base drm crtc structure
  * @base          : Base drm crtc structure
@@ -303,6 +327,7 @@ struct sde_crtc_misr_info {
  * @skip_blend_plane_w: skip blend plane width
  * @skip_blend_plane_w: skip blend plane width
  * @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
  */
  */
 struct sde_crtc {
 struct sde_crtc {
 	struct drm_crtc base;
 	struct drm_crtc base;
@@ -402,6 +427,8 @@ struct sde_crtc {
 	u32 skip_blend_plane_w;
 	u32 skip_blend_plane_w;
 	u32 skip_blend_plane_h;
 	u32 skip_blend_plane_h;
 	u32 line_time_in_ns;
 	u32 line_time_in_ns;
+
+	struct sde_frame_data frame_data;
 };
 };
 
 
 enum sde_crtc_dirty_flags {
 enum sde_crtc_dirty_flags {

+ 4 - 0
msm/sde/sde_hw_catalog.c

@@ -1938,6 +1938,9 @@ static void sde_sspp_set_features(struct sde_mdss_cfg *sde_cfg,
 				SSPP_MAX_PER_PIPE_BW_HIGH, i);
 				SSPP_MAX_PER_PIPE_BW_HIGH, i);
 		else
 		else
 			sblk->max_per_pipe_bw_high = sblk->max_per_pipe_bw;
 			sblk->max_per_pipe_bw_high = sblk->max_per_pipe_bw;
+
+		if (sde_cfg->has_ubwc_stats)
+			set_bit(SDE_SSPP_UBWC_STATS, &sspp->features);
 	}
 	}
 }
 }
 
 
@@ -5071,6 +5074,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
 		set_bit(SDE_MDP_PERIPH_TOP_0_REMOVED, &sde_cfg->mdp[0].features);
 		set_bit(SDE_MDP_PERIPH_TOP_0_REMOVED, &sde_cfg->mdp[0].features);
 		sde_cfg->has_precise_vsync_ts = true;
 		sde_cfg->has_precise_vsync_ts = true;
 		sde_cfg->has_trusted_vm_support = true;
 		sde_cfg->has_trusted_vm_support = true;
+		sde_cfg->has_ubwc_stats = true;
 	} else if (IS_YUPIK_TARGET(hw_rev)) {
 	} else if (IS_YUPIK_TARGET(hw_rev)) {
 		sde_cfg->has_cwb_support = true;
 		sde_cfg->has_cwb_support = true;
 		sde_cfg->has_qsync = true;
 		sde_cfg->has_qsync = true;

+ 5 - 0
msm/sde/sde_hw_catalog.h

@@ -275,6 +275,7 @@ enum {
  * @SDE_SSPP_FP16_GC         FP16 GC color processing block support
  * @SDE_SSPP_FP16_GC         FP16 GC color processing block support
  * @SDE_SSPP_FP16_CSC        FP16 CSC color processing block support
  * @SDE_SSPP_FP16_CSC        FP16 CSC color processing block support
  * @SDE_SSPP_FP16_UNMULT     FP16 alpha unmult color processing block support
  * @SDE_SSPP_FP16_UNMULT     FP16 alpha unmult color processing block support
+ * @SDE_SSPP_UBWC_STATS:     Support for ubwc stats
  * @SDE_SSPP_MAX             maximum value
  * @SDE_SSPP_MAX             maximum value
  */
  */
 enum {
 enum {
@@ -311,6 +312,7 @@ enum {
 	SDE_SSPP_FP16_GC,
 	SDE_SSPP_FP16_GC,
 	SDE_SSPP_FP16_CSC,
 	SDE_SSPP_FP16_CSC,
 	SDE_SSPP_FP16_UNMULT,
 	SDE_SSPP_FP16_UNMULT,
+	SDE_SSPP_UBWC_STATS,
 	SDE_SSPP_MAX
 	SDE_SSPP_MAX
 };
 };
 
 
@@ -1543,6 +1545,7 @@ struct sde_perf_cfg {
  * @has_vig_p010  indicates if vig pipe supports p010 format
  * @has_vig_p010  indicates if vig pipe supports p010 format
  * @has_fp16      indicates if FP16 format is supported on SSPP pipes
  * @has_fp16      indicates if FP16 format is supported on SSPP pipes
  * @has_precise_vsync_ts  indicates if HW has vsyc timestamp logging capability
  * @has_precise_vsync_ts  indicates if HW has vsyc timestamp logging capability
+ * @has_ubwc_stats: indicates if ubwc stats feature is supported
  * @mdss_hw_block_size  Max offset of MDSS_HW block (0 offset), used for debug
  * @mdss_hw_block_size  Max offset of MDSS_HW block (0 offset), used for debug
  * @inline_rot_formats formats supported by the inline rotator feature
  * @inline_rot_formats formats supported by the inline rotator feature
  * @irq_offset_list     list of sde_intr_irq_offsets to initialize irq table
  * @irq_offset_list     list of sde_intr_irq_offsets to initialize irq table
@@ -1627,6 +1630,8 @@ struct sde_mdss_cfg {
 	bool has_vig_p010;
 	bool has_vig_p010;
 	bool has_fp16;
 	bool has_fp16;
 	bool has_precise_vsync_ts;
 	bool has_precise_vsync_ts;
+	bool has_ubwc_stats;
+
 	u32 mdss_hw_block_size;
 	u32 mdss_hw_block_size;
 	u32 mdss_count;
 	u32 mdss_count;
 	struct sde_mdss_base_cfg mdss[MAX_BLOCKS];
 	struct sde_mdss_base_cfg mdss[MAX_BLOCKS];

+ 92 - 7
msm/sde/sde_hw_sspp.c

@@ -77,6 +77,10 @@
 #define SSPP_SRC_ADDR_SW_STATUS            0x70
 #define SSPP_SRC_ADDR_SW_STATUS            0x70
 #define SSPP_CREQ_LUT_0                    0x74
 #define SSPP_CREQ_LUT_0                    0x74
 #define SSPP_CREQ_LUT_1                    0x78
 #define SSPP_CREQ_LUT_1                    0x78
+#define SSPP_UBWC_STATS_ROI                0x7C
+#define SSPP_UBWC_STATS_DATA               0x80
+#define SSPP_UBWC_STATS_ROI_REC1           0xB4
+#define SSPP_UBWC_STATS_DATA_REC1          0xB8
 #define SSPP_SW_PIX_EXT_C0_LR              0x100
 #define SSPP_SW_PIX_EXT_C0_LR              0x100
 #define SSPP_SW_PIX_EXT_C0_TB              0x104
 #define SSPP_SW_PIX_EXT_C0_TB              0x104
 #define SSPP_SW_PIX_EXT_C0_REQ_PIXELS      0x108
 #define SSPP_SW_PIX_EXT_C0_REQ_PIXELS      0x108
@@ -96,8 +100,9 @@
 #define SSPP_TRAFFIC_SHAPER_REC1           0x158
 #define SSPP_TRAFFIC_SHAPER_REC1           0x158
 #define SSPP_EXCL_REC_SIZE                 0x1B4
 #define SSPP_EXCL_REC_SIZE                 0x1B4
 #define SSPP_EXCL_REC_XY                   0x1B8
 #define SSPP_EXCL_REC_XY                   0x1B8
-#define SSPP_META_ERROR_STATUS_REC1        0x1C4
+#define SSPP_UBWC_STATIC_CTRL_REC1         0x1C0
 #define SSPP_UBWC_ERROR_STATUS_REC1        0x1C8
 #define SSPP_UBWC_ERROR_STATUS_REC1        0x1C8
+#define SSPP_META_ERROR_STATUS_REC1        0x1C4
 #define SSPP_VIG_OP_MODE                   0x0
 #define SSPP_VIG_OP_MODE                   0x0
 #define SSPP_VIG_CSC_10_OP_MODE            0x0
 #define SSPP_VIG_CSC_10_OP_MODE            0x0
 #define SSPP_TRAFFIC_SHAPER_BPC_MAX        0xFF
 #define SSPP_TRAFFIC_SHAPER_BPC_MAX        0xFF
@@ -436,7 +441,8 @@ static void sde_hw_sspp_setup_format(struct sde_hw_pipe *ctx,
 	SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS + idx, BIT(31));
 	SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS + idx, BIT(31));
 }
 }
 
 
-static void sde_hw_sspp_clear_ubwc_error(struct sde_hw_pipe *ctx, uint32_t multirect_index)
+static void sde_hw_sspp_clear_ubwc_error(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index multirect_index)
 {
 {
 	struct sde_hw_blk_reg_map *c;
 	struct sde_hw_blk_reg_map *c;
 
 
@@ -445,7 +451,8 @@ static void sde_hw_sspp_clear_ubwc_error(struct sde_hw_pipe *ctx, uint32_t multi
 	SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31));
 	SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31));
 }
 }
 
 
-static u32 sde_hw_sspp_get_ubwc_error(struct sde_hw_pipe *ctx, uint32_t multirect_index)
+static u32 sde_hw_sspp_get_ubwc_error(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index multirect_index)
 {
 {
 	struct sde_hw_blk_reg_map *c;
 	struct sde_hw_blk_reg_map *c;
 	u32 reg_code;
 	u32 reg_code;
@@ -457,7 +464,8 @@ static u32 sde_hw_sspp_get_ubwc_error(struct sde_hw_pipe *ctx, uint32_t multirec
 	return reg_code;
 	return reg_code;
 }
 }
 
 
-static void sde_hw_sspp_clear_ubwc_error_v1(struct sde_hw_pipe *ctx, uint32_t multirect_index)
+static void sde_hw_sspp_clear_ubwc_error_v1(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index multirect_index)
 {
 {
 	struct sde_hw_blk_reg_map *c;
 	struct sde_hw_blk_reg_map *c;
 
 
@@ -469,7 +477,8 @@ static void sde_hw_sspp_clear_ubwc_error_v1(struct sde_hw_pipe *ctx, uint32_t mu
 		SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31));
 		SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31));
 }
 }
 
 
-static u32 sde_hw_sspp_get_ubwc_error_v1(struct sde_hw_pipe *ctx, uint32_t multirect_index)
+static u32 sde_hw_sspp_get_ubwc_error_v1(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index multirect_index)
 {
 {
 	struct sde_hw_blk_reg_map *c;
 	struct sde_hw_blk_reg_map *c;
 	u32 reg_code;
 	u32 reg_code;
@@ -484,7 +493,8 @@ static u32 sde_hw_sspp_get_ubwc_error_v1(struct sde_hw_pipe *ctx, uint32_t multi
 	return reg_code;
 	return reg_code;
 }
 }
 
 
-static void sde_hw_sspp_clear_meta_error(struct sde_hw_pipe *ctx, uint32_t multirect_index)
+static void sde_hw_sspp_clear_meta_error(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index multirect_index)
 {
 {
 	struct sde_hw_blk_reg_map *c;
 	struct sde_hw_blk_reg_map *c;
 
 
@@ -496,7 +506,8 @@ static void sde_hw_sspp_clear_meta_error(struct sde_hw_pipe *ctx, uint32_t multi
 		SDE_REG_WRITE(c, SSPP_META_ERROR_STATUS, BIT(31));
 		SDE_REG_WRITE(c, SSPP_META_ERROR_STATUS, BIT(31));
 }
 }
 
 
-static u32 sde_hw_sspp_get_meta_error(struct sde_hw_pipe *ctx, uint32_t multirect_index)
+static u32 sde_hw_sspp_get_meta_error(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index multirect_index)
 {
 {
 	struct sde_hw_blk_reg_map *c;
 	struct sde_hw_blk_reg_map *c;
 	u32 reg_code;
 	u32 reg_code;
@@ -511,6 +522,75 @@ static u32 sde_hw_sspp_get_meta_error(struct sde_hw_pipe *ctx, uint32_t multirec
 	return reg_code;
 	return reg_code;
 }
 }
 
 
+static void sde_hw_sspp_ubwc_stats_set_roi(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index multirect_index,
+		struct sde_drm_ubwc_stats_roi *roi)
+{
+	struct sde_hw_blk_reg_map *c;
+	u32 idx, ctrl_off, roi_off;
+	u32 ctrl_val = 0, roi_val = 0;
+
+	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
+		return;
+
+	if (multirect_index == SDE_SSPP_RECT_SOLO || multirect_index == SDE_SSPP_RECT_0) {
+		ctrl_off = SSPP_UBWC_STATIC_CTRL + idx;
+		roi_off = SSPP_UBWC_STATS_ROI + idx;
+	} else {
+		ctrl_off = SSPP_UBWC_STATIC_CTRL_REC1 + idx;
+		roi_off = SSPP_UBWC_STATS_ROI_REC1 + idx;
+	}
+
+	c = &ctx->hw;
+
+	ctrl_val = SDE_REG_READ(c, ctrl_off);
+
+	if (roi) {
+		ctrl_val |= BIT(24);
+		if (roi->y_coord0) {
+			ctrl_val |= BIT(25);
+			roi_val |= roi->y_coord0;
+
+			if (roi->y_coord1) {
+				ctrl_val |= BIT(26);
+				roi_val |= (roi->y_coord1) << 0x10;
+			}
+		}
+	} else {
+		ctrl_val &= ~(BIT(24) | BIT(25) | BIT(26));
+	}
+
+	SDE_REG_WRITE(c, ctrl_off, ctrl_val);
+	SDE_REG_WRITE(c, roi_off, roi_val);
+}
+
+static void sde_hw_sspp_ubwc_stats_get_data(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index multirect_index,
+		struct sde_drm_ubwc_stats_data *data)
+{
+	struct sde_hw_blk_reg_map *c;
+	u32 idx, value = 0;
+	int i;
+
+	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
+		return;
+
+	if (multirect_index == SDE_SSPP_RECT_SOLO || multirect_index == SDE_SSPP_RECT_0)
+		idx += SSPP_UBWC_STATS_DATA;
+	else
+		idx += SSPP_UBWC_STATS_DATA_REC1;
+
+	c = &ctx->hw;
+
+	for (i = 0; i < UBWC_STATS_MAX_ROI; i++) {
+		value = SDE_REG_READ(c, idx);
+		data->worst_bw[i] = value & 0xFFFF;
+		data->worst_bw_y_coord[i] = (value >> 0x10) & 0xFFFF;
+		data->total_bw[i] = SDE_REG_READ(c, idx + 4);
+		idx += 8;
+	}
+}
+
 static void sde_hw_sspp_setup_secure(struct sde_hw_pipe *ctx,
 static void sde_hw_sspp_setup_secure(struct sde_hw_pipe *ctx,
 		enum sde_sspp_multirect_index rect_mode,
 		enum sde_sspp_multirect_index rect_mode,
 		bool enable)
 		bool enable)
@@ -1373,6 +1453,11 @@ static void _setup_layer_ops(struct sde_hw_pipe *c,
 		c->ops.setup_inverse_pma = sde_hw_sspp_setup_dgm_inverse_pma;
 		c->ops.setup_inverse_pma = sde_hw_sspp_setup_dgm_inverse_pma;
 	else if (test_bit(SDE_SSPP_INVERSE_PMA, &features))
 	else if (test_bit(SDE_SSPP_INVERSE_PMA, &features))
 		c->ops.setup_inverse_pma = sde_hw_sspp_setup_inverse_pma;
 		c->ops.setup_inverse_pma = sde_hw_sspp_setup_inverse_pma;
+
+	if (test_bit(SDE_SSPP_UBWC_STATS, &features)) {
+		c->ops.set_ubwc_stats_roi = sde_hw_sspp_ubwc_stats_set_roi;
+		c->ops.get_ubwc_stats_data = sde_hw_sspp_ubwc_stats_get_data;
+	}
 }
 }
 
 
 static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,
 static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,

+ 28 - 4
msm/sde/sde_hw_sspp.h

@@ -596,28 +596,52 @@ struct sde_hw_sspp_ops {
 	 * @ctx: Pointer to pipe context
 	 * @ctx: Pointer to pipe context
 	 * @multirect_index: rec in use
 	 * @multirect_index: rec in use
 	 */
 	 */
-	void (*clear_meta_error)(struct sde_hw_pipe *ctx, uint32_t multirect_index);
+	void (*clear_meta_error)(struct sde_hw_pipe *ctx,
+			enum sde_sspp_multirect_index multirect_index);
 
 
 	/**
 	/**
 	 * get_meta_error - get the meta error-code
 	 * get_meta_error - get the meta error-code
 	 * @ctx: Pointer to pipe context
 	 * @ctx: Pointer to pipe context
 	 * @multirect_index: rec in use
 	 * @multirect_index: rec in use
 	 */
 	 */
-	u32 (*get_meta_error)(struct sde_hw_pipe *ctx, uint32_t multirect_index);
+	u32 (*get_meta_error)(struct sde_hw_pipe *ctx,
+			enum sde_sspp_multirect_index multirect_index);
 
 
 	/**
 	/**
 	 * clear_ubwc_error - clear the ubwc error-code registers
 	 * clear_ubwc_error - clear the ubwc error-code registers
 	 * @ctx: Pointer to pipe context
 	 * @ctx: Pointer to pipe context
 	 * @multirect_index: rec in use
 	 * @multirect_index: rec in use
 	 */
 	 */
-	void (*clear_ubwc_error)(struct sde_hw_pipe *ctx, uint32_t multirect_index);
+	void (*clear_ubwc_error)(struct sde_hw_pipe *ctx,
+			enum sde_sspp_multirect_index multirect_index);
 
 
 	/**
 	/**
 	 * get_ubwc_error - get the ubwc error-code
 	 * get_ubwc_error - get the ubwc error-code
 	 * @ctx: Pointer to pipe context
 	 * @ctx: Pointer to pipe context
 	 * @multirect_index: rec in use
 	 * @multirect_index: rec in use
 	 */
 	 */
-	u32 (*get_ubwc_error)(struct sde_hw_pipe *ctx, uint32_t multirect_index);
+	u32 (*get_ubwc_error)(struct sde_hw_pipe *ctx,
+			enum sde_sspp_multirect_index multirect_index);
+
+	/**
+	 * get_ubwc_stats_data - get ubwc stats data
+	 * @ctx: Pointer to pipe context
+	 * @multirect_index: rec in use
+	 * @data: Pointer to ubwc data to populate
+	 */
+	void (*get_ubwc_stats_data)(struct sde_hw_pipe *ctx,
+			enum sde_sspp_multirect_index multirect_index,
+			struct sde_drm_ubwc_stats_data *data);
+
+	/**
+	 * set_ubwc_stats_roi - set ubwc stats roi
+	 * @ctx: Pointer to pipe context
+	 * @multirect_index: rec in use
+	 * @roi: roi to be programmed
+	 */
+	void (*set_ubwc_stats_roi)(struct sde_hw_pipe *ctx,
+			enum sde_sspp_multirect_index multirect_index,
+			struct sde_drm_ubwc_stats_roi *roi);
 
 
 	/**
 	/**
 	 * setup_fp16_csc - set FP16 CSC cp block
 	 * setup_fp16_csc - set FP16 CSC cp block

+ 65 - 50
msm/sde/sde_plane.c

@@ -2854,6 +2854,7 @@ static void _sde_plane_map_prop_to_dirty_bits(void)
 	plane_prop_array[PLANE_PROP_SRC_CONFIG] =
 	plane_prop_array[PLANE_PROP_SRC_CONFIG] =
 	plane_prop_array[PLANE_PROP_ZPOS] =
 	plane_prop_array[PLANE_PROP_ZPOS] =
 	plane_prop_array[PLANE_PROP_EXCL_RECT_V1] =
 	plane_prop_array[PLANE_PROP_EXCL_RECT_V1] =
+	plane_prop_array[PLANE_PROP_UBWC_STATS_ROI] =
 		SDE_PLANE_DIRTY_RECTS;
 		SDE_PLANE_DIRTY_RECTS;
 
 
 	plane_prop_array[PLANE_PROP_CSC_V1] =
 	plane_prop_array[PLANE_PROP_CSC_V1] =
@@ -3141,6 +3142,15 @@ static void _sde_plane_update_format_and_rects(struct sde_plane *psde,
 	if (psde->pipe_hw->ops.setup_dgm_csc)
 	if (psde->pipe_hw->ops.setup_dgm_csc)
 		psde->pipe_hw->ops.setup_dgm_csc(psde->pipe_hw,
 		psde->pipe_hw->ops.setup_dgm_csc(psde->pipe_hw,
 			pstate->multirect_index, psde->csc_usr_ptr);
 			pstate->multirect_index, psde->csc_usr_ptr);
+
+	if (psde->pipe_hw->ops.set_ubwc_stats_roi) {
+		if (SDE_FORMAT_IS_UBWC(fmt) && !SDE_FORMAT_IS_YUV(fmt))
+			psde->pipe_hw->ops.set_ubwc_stats_roi(psde->pipe_hw,
+					pstate->multirect_index, &pstate->ubwc_stats_roi);
+		else
+			psde->pipe_hw->ops.set_ubwc_stats_roi(psde->pipe_hw,
+					pstate->multirect_index, NULL);
+	}
 }
 }
 
 
 static void _sde_plane_update_sharpening(struct sde_plane *psde)
 static void _sde_plane_update_sharpening(struct sde_plane *psde)
@@ -3862,6 +3872,9 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
 			ARRAY_SIZE(e_fb_translation_mode), 0,
 			ARRAY_SIZE(e_fb_translation_mode), 0,
 			PLANE_PROP_FB_TRANSLATION_MODE);
 			PLANE_PROP_FB_TRANSLATION_MODE);
 
 
+	if (psde->pipe_hw->ops.set_ubwc_stats_roi)
+		msm_property_install_range(&psde->property_info, "ubwc_stats_roi",
+				0, 0, 0xFFFFFFFF, 0, PLANE_PROP_UBWC_STATS_ROI);
 	kfree(info);
 	kfree(info);
 }
 }
 
 
@@ -4077,6 +4090,30 @@ static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
 			pstate->excl_rect.w, pstate->excl_rect.h);
 			pstate->excl_rect.w, pstate->excl_rect.h);
 }
 }
 
 
+static void _sde_plane_set_ubwc_stats_roi(struct sde_plane *psde,
+		struct sde_plane_state *pstate, uint64_t roi)
+{
+	uint16_t y0, y1;
+
+	if (!psde || !pstate) {
+		SDE_ERROR("invalid argument(s)\n");
+		return;
+	}
+
+	y0 = roi & 0xFFFF;
+	y1 = (roi >> 0x10) & 0xFFFF;
+
+	if (y0 > psde->pipe_cfg.src_rect.h || y1 > psde->pipe_cfg.src_rect.h) {
+		SDE_ERROR_PLANE(psde, "invalid ubwc roi y0 0x%x, y1 0x%x, src height 0x%x",
+				y0, y1, psde->pipe_cfg.src_rect.h);
+		y0 = 0;
+		y1 = 0;
+	}
+
+	pstate->ubwc_stats_roi.y_coord0 = y0;
+	pstate->ubwc_stats_roi.y_coord1 = y1;
+}
+
 static int sde_plane_atomic_set_property(struct drm_plane *plane,
 static int sde_plane_atomic_set_property(struct drm_plane *plane,
 		struct drm_plane_state *state, struct drm_property *property,
 		struct drm_plane_state *state, struct drm_property *property,
 		uint64_t val)
 		uint64_t val)
@@ -4118,6 +4155,9 @@ static int sde_plane_atomic_set_property(struct drm_plane *plane,
 				_sde_plane_set_excl_rect_v1(psde, pstate,
 				_sde_plane_set_excl_rect_v1(psde, pstate,
 						(void *)(uintptr_t)val);
 						(void *)(uintptr_t)val);
 				break;
 				break;
+			case PLANE_PROP_UBWC_STATS_ROI:
+				_sde_plane_set_ubwc_stats_roi(psde, pstate, val);
+				break;
 			default:
 			default:
 				/* nothing to do */
 				/* nothing to do */
 				break;
 				break;
@@ -4385,76 +4425,51 @@ static void sde_plane_reset(struct drm_plane *plane)
 	plane->state = &pstate->base;
 	plane->state = &pstate->base;
 }
 }
 
 
-u32 sde_plane_get_ubwc_error(struct drm_plane *plane)
+void sde_plane_get_frame_data(struct drm_plane *plane,
+		struct sde_drm_plane_frame_data *data)
 {
 {
-	u32 ubwc_error = 0;
 	struct sde_plane *psde;
 	struct sde_plane *psde;
 	struct sde_plane_state *pstate;
 	struct sde_plane_state *pstate;
+	struct sde_drm_ubwc_stats_data *ubwc_stats;
 
 
 	if (!plane) {
 	if (!plane) {
 		SDE_ERROR("invalid plane\n");
 		SDE_ERROR("invalid plane\n");
-		return 0;
+		return;
 	}
 	}
+
 	psde = to_sde_plane(plane);
 	psde = to_sde_plane(plane);
 	pstate = to_sde_plane_state(plane->state);
 	pstate = to_sde_plane_state(plane->state);
+	ubwc_stats = &data->ubwc_stats;
 
 
-	if (!psde->is_virtual && psde->pipe_hw->ops.get_ubwc_error)
-		ubwc_error = psde->pipe_hw->ops.get_ubwc_error(psde->pipe_hw,
-				pstate->multirect_index);
-
-	return ubwc_error;
-}
-
-void sde_plane_clear_ubwc_error(struct drm_plane *plane)
-{
-	struct sde_plane *psde;
-	struct sde_plane_state *pstate;
+	data->plane_id = DRMID(plane);
 
 
-	if (!plane) {
-		SDE_ERROR("invalid plane\n");
-		return;
+	if (psde->pipe_hw->ops.get_ubwc_stats_data) {
+		memcpy(&ubwc_stats->roi, &pstate->ubwc_stats_roi,
+				sizeof(struct sde_drm_ubwc_stats_roi));
+		psde->pipe_hw->ops.get_ubwc_stats_data(psde->pipe_hw,
+				pstate->multirect_index, ubwc_stats);
 	}
 	}
-	psde = to_sde_plane(plane);
-	pstate = to_sde_plane_state(plane->state);
-
-	if (psde->pipe_hw->ops.clear_ubwc_error)
-		psde->pipe_hw->ops.clear_ubwc_error(psde->pipe_hw, pstate->multirect_index);
-}
 
 
-u32 sde_plane_get_meta_error(struct drm_plane *plane)
-{
-	u32 meta_error = 0;
-	struct sde_plane *psde;
-	struct sde_plane_state *pstate;
+	if (psde->pipe_hw->ops.get_ubwc_error)
+		ubwc_stats->error = psde->pipe_hw->ops.get_ubwc_error(psde->pipe_hw,
+				pstate->multirect_index);
 
 
-	if (!plane) {
-		SDE_ERROR("invalid plane\n");
-		return 0;
-	}
-	psde = to_sde_plane(plane);
-	pstate = to_sde_plane_state(plane->state);
+	if (psde->pipe_hw->ops.clear_ubwc_error && ubwc_stats->error)
+		psde->pipe_hw->ops.clear_ubwc_error(psde->pipe_hw, pstate->multirect_index);
 
 
 	if (psde->pipe_hw->ops.get_meta_error)
 	if (psde->pipe_hw->ops.get_meta_error)
-		meta_error = psde->pipe_hw->ops.get_meta_error(psde->pipe_hw,
+		ubwc_stats->meta_error = psde->pipe_hw->ops.get_meta_error(psde->pipe_hw,
 				pstate->multirect_index);
 				pstate->multirect_index);
 
 
-	return meta_error;
-}
-
-void sde_plane_clear_meta_error(struct drm_plane *plane)
-{
-	struct sde_plane *psde;
-	struct sde_plane_state *pstate;
+	if (psde->pipe_hw->ops.clear_meta_error && ubwc_stats->meta_error)
+		psde->pipe_hw->ops.clear_meta_error(psde->pipe_hw, pstate->multirect_index);
 
 
-	if (!plane) {
-		SDE_ERROR("invalid plane\n");
-		return;
+	if (ubwc_stats->error || ubwc_stats->meta_error) {
+		SDE_EVT32(DRMID(plane),  ubwc_stats->error, ubwc_stats->meta_error,
+				SDE_EVTLOG_ERROR);
+		SDE_DEBUG_PLANE(psde, "plane%d ubwc_error %d meta_error %d\n",
+				ubwc_stats->error, ubwc_stats->meta_error);
 	}
 	}
-	psde = to_sde_plane(plane);
-	pstate = to_sde_plane_state(plane->state);
-
-	if (psde->pipe_hw->ops.clear_meta_error)
-		psde->pipe_hw->ops.clear_meta_error(psde->pipe_hw, pstate->multirect_index);
 }
 }
 
 
 #ifdef CONFIG_DEBUG_FS
 #ifdef CONFIG_DEBUG_FS

+ 7 - 21
msm/sde/sde_plane.h

@@ -111,6 +111,7 @@ enum sde_plane_sclcheck_state {
  * @static_cache_state:	plane cache state for static image
  * @static_cache_state:	plane cache state for static image
  * @cdp_cfg:	CDP configuration
  * @cdp_cfg:	CDP configuration
  * @cont_splash_populated: State was populated as part of cont. splash
  * @cont_splash_populated: State was populated as part of cont. splash
+ * @ubwc_stats_roi: cached roi for ubwc stats
  */
  */
 struct sde_plane_state {
 struct sde_plane_state {
 	struct drm_plane_state base;
 	struct drm_plane_state base;
@@ -144,6 +145,8 @@ struct sde_plane_state {
 	struct sde_hw_pipe_cdp_cfg cdp_cfg;
 	struct sde_hw_pipe_cdp_cfg cdp_cfg;
 
 
 	bool cont_splash_populated;
 	bool cont_splash_populated;
+
+	struct sde_drm_ubwc_stats_roi ubwc_stats_roi;
 };
 };
 
 
 /**
 /**
@@ -314,30 +317,13 @@ bool sde_plane_is_sec_ui_allowed(struct drm_plane *plane);
  */
  */
 void sde_plane_secure_ctrl_xin_client(struct drm_plane *plane,
 void sde_plane_secure_ctrl_xin_client(struct drm_plane *plane,
 		struct drm_crtc *crtc);
 		struct drm_crtc *crtc);
-
-/*
- * sde_plane_get_ubwc_error - gets the ubwc error code
- * @plane: Pointer to DRM plane object
- */
-u32 sde_plane_get_ubwc_error(struct drm_plane *plane);
-
-/*
- * sde_plane_clear_ubwc_error - clears the ubwc error code
- * @plane: Pointer to DRM plane object
- */
-void sde_plane_clear_ubwc_error(struct drm_plane *plane);
-
-/*
- * sde_plane_get_meta_error - gets the meta error code
- * @plane: Pointer to DRM plane object
- */
-u32 sde_plane_get_meta_error(struct drm_plane *plane);
-
 /*
 /*
- * sde_plane_clear_meta_error - clears the meta error code
+ * sde_plane_get_frame_data - gets the plane frame data
  * @plane: Pointer to DRM plane object
  * @plane: Pointer to DRM plane object
+ * @frame_data: Pointer to plane frame data structure
  */
  */
-void sde_plane_clear_meta_error(struct drm_plane *plane);
+void sde_plane_get_frame_data(struct drm_plane *plane,
+		struct sde_drm_plane_frame_data *frame_data);
 
 
 /*
 /*
  * sde_plane_setup_src_split_order - enable/disable pipe's src_split_order
  * sde_plane_setup_src_split_order - enable/disable pipe's src_split_order