blob: aa2caccef0bf349b997179ce304abfa9f252d585 [file] [log] [blame]
Dhaval Patel14d46ce2017-01-17 16:28:12 -08001/*
Clarence Ip4f339092018-01-05 13:29:04 -05002 * Copyright (C) 2014-2018 The Linux Foundation. All rights reserved.
Dhaval Patel14d46ce2017-01-17 16:28:12 -08003 * Copyright (C) 2013 Red Hat
4 * Author: Rob Clark <robdclark@gmail.com>
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005 *
Dhaval Patel14d46ce2017-01-17 16:28:12 -08006 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07009 *
Dhaval Patel14d46ce2017-01-17 16:28:12 -080010 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070017 */
Alan Kwong1a00e4d2016-07-18 09:42:30 -040018
19#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
20
Clarence Ip4ce59322016-06-26 22:27:51 -040021#include <linux/debugfs.h>
Alan Kwong4dd64c82017-02-04 18:41:51 -080022#include <linux/dma-buf.h>
Clarence Ip5e2a9222016-06-26 22:38:24 -040023#include <uapi/drm/sde_drm.h>
Benet Clarkd009b1d2016-06-27 14:45:59 -070024#include <uapi/drm/msm_drm_pp.h>
Clarence Ipaa0faf42016-05-30 12:07:48 -040025
26#include "msm_prop.h"
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080027#include "msm_drv.h"
Clarence Ipaa0faf42016-05-30 12:07:48 -040028
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070029#include "sde_kms.h"
Clarence Ipae4e60c2016-06-26 22:44:04 -040030#include "sde_fence.h"
Clarence Ipc475b082016-06-26 09:27:23 -040031#include "sde_formats.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040032#include "sde_hw_sspp.h"
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080033#include "sde_hw_catalog_format.h"
Alan Kwong1a00e4d2016-07-18 09:42:30 -040034#include "sde_trace.h"
Dhaval Patel48c76022016-09-01 17:51:23 -070035#include "sde_crtc.h"
Lloyd Atkinson8772e202016-09-26 17:52:16 -040036#include "sde_vbif.h"
Alan Kwong83285fb2016-10-21 20:51:17 -040037#include "sde_plane.h"
Benet Clarkd009b1d2016-06-27 14:45:59 -070038#include "sde_color_processing.h"
Alan Kwong4dd64c82017-02-04 18:41:51 -080039#include "sde_hw_rot.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040040
Clarence Ip13a8cf42016-09-29 17:27:47 -040041#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
42 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
43
44#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
45 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
46
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040047#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
48#define PHASE_STEP_SHIFT 21
49#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
50#define PHASE_RESIDUAL 15
51
Clarence Ipe78efb72016-06-24 18:35:21 -040052#define SHARP_STRENGTH_DEFAULT 32
53#define SHARP_EDGE_THR_DEFAULT 112
54#define SHARP_SMOOTH_THR_DEFAULT 8
55#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040056
Clarence Ip5e2a9222016-06-26 22:38:24 -040057#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070058
Clarence Ipcae1bb62016-07-07 12:07:13 -040059#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
60
Steve Cohen13924772017-08-10 19:10:55 -040061#define TIME_MULTIPLEX_RECT(r0, r1, buffer_lines) \
62 ((r0).y >= ((r1).y + (r1).h + buffer_lines))
63
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080064/* multirect rect index */
65enum {
66 R0,
67 R1,
68 R_MAX
69};
70
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -070071#define SDE_QSEED3_DEFAULT_PRELOAD_H 0x4
72#define SDE_QSEED3_DEFAULT_PRELOAD_V 0x3
73
Alan Kwong4dd64c82017-02-04 18:41:51 -080074#define DEFAULT_REFRESH_RATE 60
75
Alan Kwong1a00e4d2016-07-18 09:42:30 -040076/**
77 * enum sde_plane_qos - Different qos configurations for each pipe
78 *
79 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
80 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
81 * this configuration is mutually exclusive from VBLANK_CTRL.
82 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
83 */
84enum sde_plane_qos {
85 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
86 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
87 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
88};
89
Clarence Ip5fc00c52016-09-23 15:03:34 -040090/*
91 * struct sde_plane - local sde plane structure
Jordan Croused8e96522017-02-13 10:14:16 -070092 * @aspace: address space pointer
Clarence Ip5fc00c52016-09-23 15:03:34 -040093 * @csc_cfg: Decoded user configuration for csc
94 * @csc_usr_ptr: Points to csc_cfg if valid user config available
95 * @csc_ptr: Points to sde_csc_cfg structure to use for current
Alan Kwongdce56da2017-04-27 15:50:34 -070096 * @mplane_list: List of multirect planes of the same pipe
Alan Kwong4dd64c82017-02-04 18:41:51 -080097 * @catalog: Points to sde catalog structure
98 * @sbuf_mode: force stream buffer mode if set
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -070099 * @sbuf_writeback: force stream buffer writeback if set
100 * @revalidate: force revalidation of all the plane properties
Clarence Ip2606dd62017-10-14 21:11:14 -0400101 * @xin_halt_forced_clk: whether or not clocks were forced on for xin halt
Alan Kwong4dd64c82017-02-04 18:41:51 -0800102 * @blob_rot_caps: Pointer to rotator capability blob
Clarence Ip5fc00c52016-09-23 15:03:34 -0400103 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700104struct sde_plane {
105 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400106
Clarence Ip730e7192016-06-26 22:45:09 -0400107 struct mutex lock;
108
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400109 enum sde_sspp pipe;
110 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700111 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400112 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400113
114 struct sde_hw_pipe *pipe_hw;
115 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -0400116 struct sde_hw_sharp_cfg sharp_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400117 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400118 uint32_t color_fill;
119 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400120 bool is_rt_pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800121 bool is_virtual;
Alan Kwongdce56da2017-04-27 15:50:34 -0700122 struct list_head mplane_list;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800123 struct sde_mdss_cfg *catalog;
124 u32 sbuf_mode;
125 u32 sbuf_writeback;
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700126 bool revalidate;
Clarence Ip2606dd62017-10-14 21:11:14 -0400127 bool xin_halt_forced_clk;
Clarence Ip4ce59322016-06-26 22:27:51 -0400128
Clarence Ip373f8592016-05-26 00:58:42 -0400129 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400130 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400131 struct sde_csc_cfg *csc_ptr;
132
Clarence Ip4c1d9772016-06-26 09:35:38 -0400133 const struct sde_sspp_sub_blks *pipe_sblk;
134
Clarence Ip5e2a9222016-06-26 22:38:24 -0400135 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400136
Clarence Ipaa0faf42016-05-30 12:07:48 -0400137 struct msm_property_info property_info;
138 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700139 struct drm_property_blob *blob_info;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800140 struct drm_property_blob *blob_rot_caps;
Clarence Ip730e7192016-06-26 22:45:09 -0400141
Clarence Ip4ce59322016-06-26 22:27:51 -0400142 /* debugfs related stuff */
143 struct dentry *debugfs_root;
144 struct sde_debugfs_regset32 debugfs_src;
145 struct sde_debugfs_regset32 debugfs_scaler;
146 struct sde_debugfs_regset32 debugfs_csc;
Clarence Ip716ab662017-03-20 06:51:24 -0700147 bool debugfs_default_scale;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700148};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700149
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700150#define to_sde_plane(x) container_of(x, struct sde_plane, base)
151
Alan Kwong4dd64c82017-02-04 18:41:51 -0800152static struct sde_kms *_sde_plane_get_kms(struct drm_plane *plane)
153{
154 struct msm_drm_private *priv;
155
156 if (!plane || !plane->dev)
157 return NULL;
158 priv = plane->dev->dev_private;
159 if (!priv)
160 return NULL;
161 return to_sde_kms(priv->kms);
162}
163
Alan Kwong4aacd532017-02-04 18:51:33 -0800164/**
165 * _sde_plane_get_crtc_state - obtain crtc state attached to given plane state
166 * @pstate: Pointer to drm plane state
167 * return: Pointer to crtc state if success; pointer error, otherwise
168 */
169static struct drm_crtc_state *_sde_plane_get_crtc_state(
170 struct drm_plane_state *pstate)
171{
172 struct drm_crtc_state *cstate;
173
174 if (!pstate || !pstate->crtc)
175 return NULL;
176
177 if (pstate->state)
178 cstate = drm_atomic_get_crtc_state(pstate->state, pstate->crtc);
179 else
180 cstate = pstate->crtc->state;
181
182 return cstate;
183}
184
Alan Kwonga15ae762017-12-16 18:03:16 -0500185static bool sde_plane_enabled(const struct drm_plane_state *state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400186{
Clarence Ipdbde9832016-06-26 09:48:36 -0400187 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400188}
189
Alan Kwong4dd64c82017-02-04 18:41:51 -0800190static bool sde_plane_sspp_enabled(struct drm_plane_state *state)
191{
192 return state && to_sde_plane_state(state)->rot.out_fb && state->crtc;
193}
194
195/**
196 * sde_plane_crtc_enabled - determine if crtc of given plane state is enabled
197 * @state: Pointer to drm plane state
198 * return: true if plane and the associated crtc are both enabled
199 */
200static bool sde_plane_crtc_enabled(struct drm_plane_state *state)
201{
202 return sde_plane_enabled(state) && state->crtc->state &&
203 state->crtc->state->active &&
204 state->crtc->state->enable;
205}
206
Veera Sundaram Sankaran7b121cb2018-03-02 08:43:04 -0800207bool sde_plane_is_sec_ui_allowed(struct drm_plane *plane)
208{
209 struct sde_plane *psde;
210
211 if (!plane)
212 return false;
213
214 psde = to_sde_plane(plane);
215
216 return (psde->features & BIT(SDE_SSPP_SEC_UI_ALLOWED));
217}
218
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400219/**
220 * _sde_plane_calc_fill_level - calculate fill level of the given source format
221 * @plane: Pointer to drm plane
222 * @fmt: Pointer to source buffer format
223 * @src_wdith: width of source buffer
224 * Return: fill level corresponding to the source buffer/format or 0 if error
225 */
226static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
227 const struct sde_format *fmt, u32 src_width)
228{
Alan Kwongdce56da2017-04-27 15:50:34 -0700229 struct sde_plane *psde, *tmp;
230 struct sde_plane_state *pstate;
231 struct sde_plane_rot_state *rstate;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400232 u32 fixed_buff_size;
233 u32 total_fl;
Alan Kwongdce56da2017-04-27 15:50:34 -0700234 u32 hflip_bytes;
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700235 u32 unused_space;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400236
Alan Kwongdce56da2017-04-27 15:50:34 -0700237 if (!plane || !fmt || !plane->state || !src_width || !fmt->bpp) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400238 SDE_ERROR("invalid arguments\n");
239 return 0;
240 }
241
242 psde = to_sde_plane(plane);
Alan Kwongdce56da2017-04-27 15:50:34 -0700243 pstate = to_sde_plane_state(plane->state);
244 rstate = &pstate->rot;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400245 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
246
Alan Kwongdce56da2017-04-27 15:50:34 -0700247 list_for_each_entry(tmp, &psde->mplane_list, mplane_list) {
248 if (!sde_plane_enabled(tmp->base.state))
249 continue;
250 SDE_DEBUG("plane%d/%d src_width:%d/%d\n",
251 psde->base.base.id, tmp->base.base.id,
252 src_width, tmp->pipe_cfg.src_rect.w);
253 src_width = max_t(u32, src_width, tmp->pipe_cfg.src_rect.w);
254 }
255
256 if ((rstate->out_rotation & DRM_REFLECT_X) &&
257 SDE_FORMAT_IS_LINEAR(fmt))
258 hflip_bytes = (src_width + 32) * fmt->bpp;
259 else
260 hflip_bytes = 0;
261
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400262 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700263
264 unused_space = 23 * 128;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400265 if (fmt->chroma_sample == SDE_CHROMA_420) {
266 /* NV12 */
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700267 total_fl = (fixed_buff_size / 2 - hflip_bytes -
268 unused_space) / ((src_width + 32) * fmt->bpp);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400269 } else {
270 /* non NV12 */
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700271 total_fl = (fixed_buff_size / 2 - hflip_bytes -
272 unused_space) * 2 / ((src_width + 32) *
273 fmt->bpp);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400274 }
275 } else {
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700276
277 unused_space = 6 * 128;
Alan Kwongdce56da2017-04-27 15:50:34 -0700278 if (pstate->multirect_mode == SDE_SSPP_MULTIRECT_PARALLEL) {
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700279 total_fl = (fixed_buff_size / 2 - hflip_bytes -
280 unused_space) * 2 / ((src_width + 32) *
281 fmt->bpp);
Alan Kwongdce56da2017-04-27 15:50:34 -0700282 } else {
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700283 total_fl = (fixed_buff_size - hflip_bytes -
284 unused_space) * 2 / ((src_width + 32) *
285 fmt->bpp);
Alan Kwongdce56da2017-04-27 15:50:34 -0700286 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400287 }
288
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700289 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u hf:%d us:%d fl:%u\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400290 plane->base.id, psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700291 (char *)&fmt->base.pixel_format,
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700292 src_width, hflip_bytes, unused_space, total_fl);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400293
294 return total_fl;
295}
296
297/**
Alan Kwongdce56da2017-04-27 15:50:34 -0700298 * _sde_plane_get_qos_lut - get LUT mapping based on fill level
299 * @tbl: Pointer to LUT table
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400300 * @total_fl: fill level
301 * Return: LUT setting corresponding to the fill level
302 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700303static u64 _sde_plane_get_qos_lut(const struct sde_qos_lut_tbl *tbl,
304 u32 total_fl)
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400305{
Alan Kwongdce56da2017-04-27 15:50:34 -0700306 int i;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400307
Alan Kwongdce56da2017-04-27 15:50:34 -0700308 if (!tbl || !tbl->nentry || !tbl->entries)
309 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400310
Alan Kwongdce56da2017-04-27 15:50:34 -0700311 for (i = 0; i < tbl->nentry; i++)
312 if (total_fl <= tbl->entries[i].fl)
313 return tbl->entries[i].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400314
Alan Kwongdce56da2017-04-27 15:50:34 -0700315 /* if last fl is zero, use as default */
316 if (!tbl->entries[i-1].fl)
317 return tbl->entries[i-1].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400318
Alan Kwongdce56da2017-04-27 15:50:34 -0700319 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400320}
321
322/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400323 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
324 * @plane: Pointer to drm plane
325 * @fb: Pointer to framebuffer associated with the given plane
326 */
327static void _sde_plane_set_qos_lut(struct drm_plane *plane,
328 struct drm_framebuffer *fb)
329{
330 struct sde_plane *psde;
331 const struct sde_format *fmt = NULL;
Alan Kwongdce56da2017-04-27 15:50:34 -0700332 u64 qos_lut;
333 u32 total_fl = 0, lut_usage;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400334
335 if (!plane || !fb) {
336 SDE_ERROR("invalid arguments plane %d fb %d\n",
337 plane != 0, fb != 0);
338 return;
339 }
340
341 psde = to_sde_plane(plane);
342
Alan Kwongdce56da2017-04-27 15:50:34 -0700343 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400344 SDE_ERROR("invalid arguments\n");
345 return;
346 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
347 return;
348 }
349
350 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700351 lut_usage = SDE_QOS_LUT_USAGE_NRT;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400352 } else {
353 fmt = sde_get_sde_format_ext(
354 fb->pixel_format,
355 fb->modifier,
356 drm_format_num_planes(fb->pixel_format));
357 total_fl = _sde_plane_calc_fill_level(plane, fmt,
358 psde->pipe_cfg.src_rect.w);
359
Narendra Muppallaec11a0a2017-06-15 15:35:17 -0700360 if (fmt && SDE_FORMAT_IS_LINEAR(fmt))
Alan Kwongdce56da2017-04-27 15:50:34 -0700361 lut_usage = SDE_QOS_LUT_USAGE_LINEAR;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400362 else
Alan Kwongdce56da2017-04-27 15:50:34 -0700363 lut_usage = SDE_QOS_LUT_USAGE_MACROTILE;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400364 }
365
Alan Kwongdce56da2017-04-27 15:50:34 -0700366 qos_lut = _sde_plane_get_qos_lut(
367 &psde->catalog->perf.qos_lut_tbl[lut_usage], total_fl);
368
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400369 psde->pipe_qos_cfg.creq_lut = qos_lut;
370
371 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
372 (fmt) ? fmt->base.pixel_format : 0,
Alan Kwongdce56da2017-04-27 15:50:34 -0700373 psde->is_rt_pipe, total_fl, qos_lut, lut_usage);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400374
Alan Kwongdce56da2017-04-27 15:50:34 -0700375 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400376 plane->base.id,
377 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700378 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400379 psde->is_rt_pipe, total_fl, qos_lut);
380
381 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
382}
383
384/**
385 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
386 * @plane: Pointer to drm plane
387 * @fb: Pointer to framebuffer associated with the given plane
388 */
389static void _sde_plane_set_danger_lut(struct drm_plane *plane,
390 struct drm_framebuffer *fb)
391{
392 struct sde_plane *psde;
393 const struct sde_format *fmt = NULL;
394 u32 danger_lut, safe_lut;
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700395 u32 total_fl = 0, lut_usage;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400396
397 if (!plane || !fb) {
398 SDE_ERROR("invalid arguments\n");
399 return;
400 }
401
402 psde = to_sde_plane(plane);
403
Alan Kwongdce56da2017-04-27 15:50:34 -0700404 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400405 SDE_ERROR("invalid arguments\n");
406 return;
407 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
408 return;
409 }
410
411 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700412 danger_lut = psde->catalog->perf.danger_lut_tbl
413 [SDE_QOS_LUT_USAGE_NRT];
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700414 lut_usage = SDE_QOS_LUT_USAGE_NRT;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400415 } else {
416 fmt = sde_get_sde_format_ext(
417 fb->pixel_format,
418 fb->modifier,
419 drm_format_num_planes(fb->pixel_format));
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700420 total_fl = _sde_plane_calc_fill_level(plane, fmt,
421 psde->pipe_cfg.src_rect.w);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400422
Narendra Muppallaec11a0a2017-06-15 15:35:17 -0700423 if (fmt && SDE_FORMAT_IS_LINEAR(fmt)) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700424 danger_lut = psde->catalog->perf.danger_lut_tbl
425 [SDE_QOS_LUT_USAGE_LINEAR];
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700426 lut_usage = SDE_QOS_LUT_USAGE_LINEAR;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400427 } else {
Alan Kwongdce56da2017-04-27 15:50:34 -0700428 danger_lut = psde->catalog->perf.danger_lut_tbl
429 [SDE_QOS_LUT_USAGE_MACROTILE];
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700430 lut_usage = SDE_QOS_LUT_USAGE_MACROTILE;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400431 }
432 }
433
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700434 safe_lut = (u32) _sde_plane_get_qos_lut(
435 &psde->catalog->perf.sfe_lut_tbl[lut_usage], total_fl);
436
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400437 psde->pipe_qos_cfg.danger_lut = danger_lut;
438 psde->pipe_qos_cfg.safe_lut = safe_lut;
439
440 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
441 (fmt) ? fmt->base.pixel_format : 0,
442 (fmt) ? fmt->fetch_mode : 0,
443 psde->pipe_qos_cfg.danger_lut,
444 psde->pipe_qos_cfg.safe_lut);
445
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700446 SDE_DEBUG("plane%u: pnum:%d fmt:%4.4s mode:%d fl:%d luts[0x%x,0x%x]\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400447 plane->base.id,
448 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700449 fmt ? (char *)&fmt->base.pixel_format : NULL,
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700450 fmt ? fmt->fetch_mode : -1, total_fl,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400451 psde->pipe_qos_cfg.danger_lut,
452 psde->pipe_qos_cfg.safe_lut);
453
454 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
455 &psde->pipe_qos_cfg);
456}
457
458/**
459 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
460 * @plane: Pointer to drm plane
461 * @enable: true to enable QoS control
462 * @flags: QoS control mode (enum sde_plane_qos)
463 */
464static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
465 bool enable, u32 flags)
466{
467 struct sde_plane *psde;
468
469 if (!plane) {
470 SDE_ERROR("invalid arguments\n");
471 return;
472 }
473
474 psde = to_sde_plane(plane);
475
476 if (!psde->pipe_hw || !psde->pipe_sblk) {
477 SDE_ERROR("invalid arguments\n");
478 return;
479 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
480 return;
481 }
482
483 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
484 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
485 psde->pipe_qos_cfg.danger_vblank =
486 psde->pipe_sblk->danger_vblank;
487 psde->pipe_qos_cfg.vblank_en = enable;
488 }
489
490 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
491 /* this feature overrules previous VBLANK_CTRL */
492 psde->pipe_qos_cfg.vblank_en = false;
493 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
494 }
495
496 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
497 psde->pipe_qos_cfg.danger_safe_en = enable;
498
499 if (!psde->is_rt_pipe) {
500 psde->pipe_qos_cfg.vblank_en = false;
501 psde->pipe_qos_cfg.danger_safe_en = false;
502 }
503
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400504 SDE_DEBUG("plane%u: pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400505 plane->base.id,
506 psde->pipe - SSPP_VIG0,
507 psde->pipe_qos_cfg.danger_safe_en,
508 psde->pipe_qos_cfg.vblank_en,
509 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400510 psde->pipe_qos_cfg.danger_vblank,
511 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400512
513 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
514 &psde->pipe_qos_cfg);
515}
516
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700517void sde_plane_set_revalidate(struct drm_plane *plane, bool enable)
518{
519 struct sde_plane *psde;
520
521 if (!plane)
522 return;
523
524 psde = to_sde_plane(plane);
525 psde->revalidate = enable;
526}
527
Alan Kwongf0fd8512016-10-24 21:39:26 -0400528int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
529{
530 struct sde_plane *psde;
531 struct msm_drm_private *priv;
532 struct sde_kms *sde_kms;
Alan Kwong1124f1f2017-11-10 18:14:39 -0500533 int rc;
Alan Kwongf0fd8512016-10-24 21:39:26 -0400534
535 if (!plane || !plane->dev) {
536 SDE_ERROR("invalid arguments\n");
537 return -EINVAL;
538 }
539
540 priv = plane->dev->dev_private;
541 if (!priv || !priv->kms) {
542 SDE_ERROR("invalid KMS reference\n");
543 return -EINVAL;
544 }
545
546 sde_kms = to_sde_kms(priv->kms);
547 psde = to_sde_plane(plane);
548
549 if (!psde->is_rt_pipe)
550 goto end;
551
Alan Kwong1124f1f2017-11-10 18:14:39 -0500552 rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
553 true);
554 if (rc) {
555 SDE_ERROR("failed to enable power resource %d\n", rc);
556 SDE_EVT32(rc, SDE_EVTLOG_ERROR);
557 return rc;
558 }
Alan Kwongf0fd8512016-10-24 21:39:26 -0400559
560 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
561
562 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
563
564end:
565 return 0;
566}
567
Alan Kwong5d324e42016-07-28 22:56:18 -0400568/**
569 * _sde_plane_set_ot_limit - set OT limit for the given plane
570 * @plane: Pointer to drm plane
571 * @crtc: Pointer to drm crtc
572 */
573static void _sde_plane_set_ot_limit(struct drm_plane *plane,
574 struct drm_crtc *crtc)
575{
576 struct sde_plane *psde;
577 struct sde_vbif_set_ot_params ot_params;
578 struct msm_drm_private *priv;
579 struct sde_kms *sde_kms;
580
581 if (!plane || !plane->dev || !crtc) {
582 SDE_ERROR("invalid arguments plane %d crtc %d\n",
583 plane != 0, crtc != 0);
584 return;
585 }
586
587 priv = plane->dev->dev_private;
588 if (!priv || !priv->kms) {
589 SDE_ERROR("invalid KMS reference\n");
590 return;
591 }
592
593 sde_kms = to_sde_kms(priv->kms);
594 psde = to_sde_plane(plane);
595 if (!psde->pipe_hw) {
596 SDE_ERROR("invalid pipe reference\n");
597 return;
598 }
599
600 memset(&ot_params, 0, sizeof(ot_params));
601 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
602 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
603 ot_params.width = psde->pipe_cfg.src_rect.w;
604 ot_params.height = psde->pipe_cfg.src_rect.h;
605 ot_params.is_wfd = !psde->is_rt_pipe;
606 ot_params.frame_rate = crtc->mode.vrefresh;
607 ot_params.vbif_idx = VBIF_RT;
608 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
609 ot_params.rd = true;
610
611 sde_vbif_set_ot_limit(sde_kms, &ot_params);
612}
613
Alan Kwonga62eeb82017-04-19 08:57:55 -0700614/**
615 * _sde_plane_set_vbif_qos - set vbif QoS for the given plane
616 * @plane: Pointer to drm plane
617 */
618static void _sde_plane_set_qos_remap(struct drm_plane *plane)
619{
620 struct sde_plane *psde;
621 struct sde_vbif_set_qos_params qos_params;
622 struct msm_drm_private *priv;
623 struct sde_kms *sde_kms;
624
625 if (!plane || !plane->dev) {
626 SDE_ERROR("invalid arguments\n");
627 return;
628 }
629
630 priv = plane->dev->dev_private;
631 if (!priv || !priv->kms) {
632 SDE_ERROR("invalid KMS reference\n");
633 return;
634 }
635
636 sde_kms = to_sde_kms(priv->kms);
637 psde = to_sde_plane(plane);
638 if (!psde->pipe_hw) {
639 SDE_ERROR("invalid pipe reference\n");
640 return;
641 }
642
643 memset(&qos_params, 0, sizeof(qos_params));
644 qos_params.vbif_idx = VBIF_RT;
645 qos_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
646 qos_params.xin_id = psde->pipe_hw->cap->xin_id;
647 qos_params.num = psde->pipe_hw->idx - SSPP_VIG0;
648 qos_params.is_rt = psde->is_rt_pipe;
649
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700650 SDE_DEBUG("plane%d pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n",
Alan Kwonga62eeb82017-04-19 08:57:55 -0700651 plane->base.id, qos_params.num,
652 qos_params.vbif_idx,
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700653 qos_params.xin_id, qos_params.is_rt,
654 qos_params.clk_ctrl);
Alan Kwonga62eeb82017-04-19 08:57:55 -0700655
656 sde_vbif_set_qos_remap(sde_kms, &qos_params);
657}
658
Alan Kwong2349d742017-04-20 08:27:30 -0700659/**
660 * _sde_plane_set_ts_prefill - set prefill with traffic shaper
661 * @plane: Pointer to drm plane
662 * @pstate: Pointer to sde plane state
663 */
664static void _sde_plane_set_ts_prefill(struct drm_plane *plane,
665 struct sde_plane_state *pstate)
666{
667 struct sde_plane *psde;
668 struct sde_hw_pipe_ts_cfg cfg;
669 struct msm_drm_private *priv;
670 struct sde_kms *sde_kms;
671
672 if (!plane || !plane->dev) {
673 SDE_ERROR("invalid arguments");
674 return;
675 }
676
677 priv = plane->dev->dev_private;
678 if (!priv || !priv->kms) {
679 SDE_ERROR("invalid KMS reference\n");
680 return;
681 }
682
683 sde_kms = to_sde_kms(priv->kms);
684 psde = to_sde_plane(plane);
685 if (!psde->pipe_hw) {
686 SDE_ERROR("invalid pipe reference\n");
687 return;
688 }
689
690 if (!psde->pipe_hw || !psde->pipe_hw->ops.setup_ts_prefill)
691 return;
692
693 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_VBLANK_AMORTIZE);
694
695 memset(&cfg, 0, sizeof(cfg));
696 cfg.size = sde_plane_get_property(pstate,
697 PLANE_PROP_PREFILL_SIZE);
698 cfg.time = sde_plane_get_property(pstate,
699 PLANE_PROP_PREFILL_TIME);
700
701 SDE_DEBUG("plane%d size:%llu time:%llu\n",
702 plane->base.id, cfg.size, cfg.time);
Dhaval Patela5f75952017-07-25 11:17:41 -0700703 SDE_EVT32_VERBOSE(DRMID(plane), cfg.size, cfg.time);
Alan Kwong2349d742017-04-20 08:27:30 -0700704 psde->pipe_hw->ops.setup_ts_prefill(psde->pipe_hw, &cfg,
705 pstate->multirect_index);
706}
707
Clarence Ipcae1bb62016-07-07 12:07:13 -0400708/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400709static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400710 struct sde_plane_state *pstate, uint64_t fd)
711{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400712 if (!psde || !pstate) {
713 SDE_ERROR("invalid arg(s), plane %d state %d\n",
714 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400715 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400716 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400717
718 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400719 if (pstate->input_fence)
720 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400721
722 /* get fence pointer for later */
Lloyd Atkinsone08229c2017-10-02 17:53:30 -0400723 if (fd == 0)
724 pstate->input_fence = NULL;
725 else
726 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400727
Clarence Ip13a8cf42016-09-29 17:27:47 -0400728 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400729}
730
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700731/**
732 * _sde_plane_inline_rot_set_ot_limit - set OT limit for the given inline
733 * rotation xin client
734 * @plane: pointer to drm plane
735 * @crtc: pointer to drm crtc
736 * @cfg: pointer to rotator vbif config
737 * @rect_w: rotator frame width
738 * @rect_h: rotator frame height
739 */
740static void _sde_plane_inline_rot_set_ot_limit(struct drm_plane *plane,
741 struct drm_crtc *crtc, const struct sde_rot_vbif_cfg *cfg,
742 u32 rect_w, u32 rect_h)
743{
744 struct sde_vbif_set_ot_params ot_params;
745 struct msm_drm_private *priv;
746 struct sde_kms *sde_kms;
747
748 if (!plane || !plane->dev) {
749 SDE_ERROR("invalid arguments\n");
750 return;
751 }
752
753 priv = plane->dev->dev_private;
754 if (!priv || !priv->kms) {
755 SDE_ERROR("invalid KMS reference\n");
756 return;
757 }
758
759 sde_kms = to_sde_kms(priv->kms);
760
761 memset(&ot_params, 0, sizeof(ot_params));
762 ot_params.xin_id = cfg->xin_id;
763 ot_params.num = cfg->num;
764 ot_params.width = rect_w;
765 ot_params.height = rect_h;
766 ot_params.is_wfd = false;
767 ot_params.frame_rate = crtc->mode.vrefresh;
768 ot_params.vbif_idx = VBIF_RT;
769 ot_params.clk_ctrl = cfg->clk_ctrl;
770 ot_params.rd = cfg->is_read;
771
772 sde_vbif_set_ot_limit(sde_kms, &ot_params);
773}
774
775/**
776 * _sde_plane_inline_rot_set_qos_remap - set vbif QoS for the given inline
777 * rotation xin client
778 * @plane: Pointer to drm plane
779 * @cfg: Pointer to rotator vbif cfg
780 */
781static void _sde_plane_inline_rot_set_qos_remap(struct drm_plane *plane,
782 const struct sde_rot_vbif_cfg *cfg)
783{
784 struct sde_vbif_set_qos_params qos_params;
785 struct msm_drm_private *priv;
786 struct sde_kms *sde_kms;
787
788 if (!plane || !plane->dev) {
789 SDE_ERROR("invalid arguments\n");
790 return;
791 }
792
793 priv = plane->dev->dev_private;
794 if (!priv || !priv->kms) {
795 SDE_ERROR("invalid KMS reference\n");
796 return;
797 }
798
799 sde_kms = to_sde_kms(priv->kms);
800
801 memset(&qos_params, 0, sizeof(qos_params));
802 qos_params.vbif_idx = VBIF_RT;
803 qos_params.xin_id = cfg->xin_id;
804 qos_params.clk_ctrl = cfg->clk_ctrl;
805 qos_params.num = cfg->num;
806 qos_params.is_rt = true;
807
808 SDE_DEBUG("vbif:%d xin:%d num:%d rt:%d clk_ctrl:%d\n",
809 qos_params.vbif_idx, qos_params.xin_id,
810 qos_params.num, qos_params.is_rt, qos_params.clk_ctrl);
811
812 sde_vbif_set_qos_remap(sde_kms, &qos_params);
813}
814
Clarence Ipcae1bb62016-07-07 12:07:13 -0400815int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400816{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400817 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400818 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400819 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400820 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400821 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800822 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400823
824 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700825 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400826 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400827 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400828 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400829 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400830 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400831 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400832
Clarence Ipcae1bb62016-07-07 12:07:13 -0400833 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800834 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400835 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800836 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400837
Dhaval Patel39323d42017-03-01 23:48:24 -0800838 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400839 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400840 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
841 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400842 psde->is_error = true;
Dhaval Patel2a3c37a2017-10-25 12:30:36 -0700843 sde_kms_timeline_status(plane->dev);
Dhaval Patel39323d42017-03-01 23:48:24 -0800844 ret = -ETIMEDOUT;
845 break;
846 case -ERESTARTSYS:
847 SDE_ERROR_PLANE(psde,
848 "%ums wait interrupted on %08X\n",
849 wait_ms, prefix);
850 psde->is_error = true;
851 ret = -ERESTARTSYS;
852 break;
853 case -EINVAL:
854 SDE_ERROR_PLANE(psde,
855 "invalid fence param for %08X\n",
856 prefix);
857 psde->is_error = true;
858 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400859 break;
860 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800861 SDE_DEBUG_PLANE(psde, "signaled\n");
862 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400863 break;
864 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700865
866 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400867 } else {
868 ret = 0;
869 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400870 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400871 return ret;
872}
873
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700874/**
875 * _sde_plane_get_aspace: gets the address space based on the
876 * fb_translation mode property
877 */
878static int _sde_plane_get_aspace(
879 struct sde_plane *psde,
880 struct sde_plane_state *pstate,
881 struct msm_gem_address_space **aspace)
882{
883 struct sde_kms *kms;
884 int mode;
885
886 if (!psde || !pstate || !aspace) {
887 SDE_ERROR("invalid parameters\n");
888 return -EINVAL;
889 }
890
891 kms = _sde_plane_get_kms(&psde->base);
892 if (!kms) {
893 SDE_ERROR("invalid kms\n");
894 return -EINVAL;
895 }
896
897 mode = sde_plane_get_property(pstate,
898 PLANE_PROP_FB_TRANSLATION_MODE);
899
900 switch (mode) {
901 case SDE_DRM_FB_NON_SEC:
902 *aspace = kms->aspace[MSM_SMMU_DOMAIN_UNSECURE];
903 if (!aspace)
904 return -EINVAL;
905 break;
906 case SDE_DRM_FB_SEC:
907 *aspace = kms->aspace[MSM_SMMU_DOMAIN_SECURE];
908 if (!aspace)
909 return -EINVAL;
910 break;
911 case SDE_DRM_FB_SEC_DIR_TRANS:
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700912 *aspace = NULL;
913 break;
914 default:
915 SDE_ERROR("invalid fb_translation mode:%d\n", mode);
916 return -EFAULT;
917 }
918
919 return 0;
920}
921
Clarence Ip282dad62016-09-27 17:07:35 -0400922static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400923 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400924 struct sde_hw_pipe_cfg *pipe_cfg,
925 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400926{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400927 struct sde_plane *psde;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700928 struct msm_gem_address_space *aspace = NULL;
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700929 int ret, mode;
930 bool secure = false;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400931
Clarence Ip13a8cf42016-09-29 17:27:47 -0400932 if (!plane || !pstate || !pipe_cfg || !fb) {
933 SDE_ERROR(
934 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
935 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400936 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400937 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400938
939 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400940 if (!psde->pipe_hw) {
941 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400942 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400943 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400944
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700945 ret = _sde_plane_get_aspace(psde, pstate, &aspace);
946 if (ret) {
947 SDE_ERROR_PLANE(psde, "Failed to get aspace %d\n", ret);
948 return;
949 }
950
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -0700951 /*
952 * framebuffer prepare is deferred for prepare_fb calls that
953 * happen during the transition from secure to non-secure.
954 * Handle the prepare at this point for such cases. This can be
955 * expected for one or two frames during the transition.
956 */
957 if (aspace && pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700958 SDE_EVT32(DRMID(plane), psde->pipe, aspace->domain_attached);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -0700959 ret = msm_framebuffer_prepare(fb, pstate->aspace);
960 if (ret) {
961 SDE_ERROR_PLANE(psde,
962 "failed to prepare framebuffer %d\n", ret);
963 return;
964 }
965 pstate->defer_prepare_fb = false;
966 }
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700967 mode = sde_plane_get_property(pstate, PLANE_PROP_FB_TRANSLATION_MODE);
968 if ((mode == SDE_DRM_FB_SEC) || (mode == SDE_DRM_FB_SEC_DIR_TRANS))
969 secure = true;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -0700970
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700971 ret = sde_format_populate_layout(aspace, fb, &pipe_cfg->layout);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400972 if (ret == -EAGAIN)
973 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
974 else if (ret)
975 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
Alan Kwongc16e0922017-05-11 14:50:46 -0700976 else if (psde->pipe_hw->ops.setup_sourceaddress) {
Dhaval Patela5f75952017-07-25 11:17:41 -0700977 SDE_EVT32_VERBOSE(psde->pipe_hw->idx,
Alan Kwongc16e0922017-05-11 14:50:46 -0700978 pipe_cfg->layout.width,
979 pipe_cfg->layout.height,
980 pipe_cfg->layout.plane_addr[0],
981 pipe_cfg->layout.plane_size[0],
982 pipe_cfg->layout.plane_addr[1],
983 pipe_cfg->layout.plane_size[1],
984 pipe_cfg->layout.plane_addr[2],
985 pipe_cfg->layout.plane_size[2],
986 pipe_cfg->layout.plane_addr[3],
987 pipe_cfg->layout.plane_size[3],
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700988 pstate->multirect_index,
989 secure);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800990 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
991 pstate->multirect_index);
Alan Kwongc16e0922017-05-11 14:50:46 -0700992 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400993}
994
abeykun48f407a2016-08-25 12:06:44 -0400995static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
996 struct sde_plane_state *pstate)
997{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500998 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400999 int ret = 0;
1000
Clarence Ip172033f2017-06-13 10:52:56 -04001001 if (!psde || !pstate) {
Clarence Ip3bf8d872017-02-16 15:25:38 -05001002 SDE_ERROR("invalid args\n");
1003 return -EINVAL;
Clarence Ip3bf8d872017-02-16 15:25:38 -05001004 }
1005
Clarence Ip172033f2017-06-13 10:52:56 -04001006 cfg = &pstate->scaler3_cfg;
Clarence Ip3bf8d872017-02-16 15:25:38 -05001007
abeykun48f407a2016-08-25 12:06:44 -04001008 cfg->dir_lut = msm_property_get_blob(
1009 &psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001010 &pstate->property_state, &cfg->dir_len,
abeykun48f407a2016-08-25 12:06:44 -04001011 PLANE_PROP_SCALER_LUT_ED);
1012 cfg->cir_lut = msm_property_get_blob(
1013 &psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001014 &pstate->property_state, &cfg->cir_len,
abeykun48f407a2016-08-25 12:06:44 -04001015 PLANE_PROP_SCALER_LUT_CIR);
1016 cfg->sep_lut = msm_property_get_blob(
1017 &psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001018 &pstate->property_state, &cfg->sep_len,
abeykun48f407a2016-08-25 12:06:44 -04001019 PLANE_PROP_SCALER_LUT_SEP);
1020 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
1021 ret = -ENODATA;
1022 return ret;
1023}
1024
Clarence Ipcb410d42016-06-26 22:52:33 -04001025static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -04001026 struct sde_plane_state *pstate,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001027 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
1028 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001029 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001030 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
1031{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001032 uint32_t decimated, i;
1033
Clarence Ip172033f2017-06-13 10:52:56 -04001034 if (!psde || !pstate || !scale_cfg || !fmt || !chroma_subsmpl_h ||
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001035 !chroma_subsmpl_v) {
Clarence Ip172033f2017-06-13 10:52:56 -04001036 SDE_ERROR(
1037 "psde %d pstate %d scale_cfg %d fmt %d smp_h %d smp_v %d\n",
1038 !!psde, !!pstate, !!scale_cfg, !!fmt, chroma_subsmpl_h,
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001039 chroma_subsmpl_v);
1040 return;
1041 }
1042
1043 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip172033f2017-06-13 10:52:56 -04001044 memset(&pstate->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001045
1046 decimated = DECIMATED_DIMENSION(src_w,
1047 psde->pipe_cfg.horz_decimation);
1048 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
1049 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
1050 decimated = DECIMATED_DIMENSION(src_h,
1051 psde->pipe_cfg.vert_decimation);
1052 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
1053 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
1054
1055
1056 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
1057 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
1058 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
1059 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
1060
1061 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
1062 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
1063 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
1064 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
1065
1066 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
1067 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
1068 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
1069 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
1070
1071 for (i = 0; i < SDE_MAX_PLANES; i++) {
1072 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
1073 psde->pipe_cfg.horz_decimation);
1074 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
1075 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001076 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
1077 scale_cfg->src_width[i] /= chroma_subsmpl_h;
1078 scale_cfg->src_height[i] /= chroma_subsmpl_v;
1079 }
1080 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
1081 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
Clarence Ip172033f2017-06-13 10:52:56 -04001082 pstate->pixel_ext.num_ext_pxls_top[i] =
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001083 scale_cfg->src_height[i];
Clarence Ip172033f2017-06-13 10:52:56 -04001084 pstate->pixel_ext.num_ext_pxls_left[i] =
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001085 scale_cfg->src_width[i];
1086 }
1087 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
1088 && (src_w == dst_w))
1089 return;
1090
1091 scale_cfg->dst_width = dst_w;
1092 scale_cfg->dst_height = dst_h;
1093 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
1094 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
1095 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
1096 scale_cfg->lut_flag = 0;
1097 scale_cfg->blend_cfg = 1;
1098 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001099}
1100
Clarence Ipcb410d42016-06-26 22:52:33 -04001101/**
Clarence Ip13a8cf42016-09-29 17:27:47 -04001102 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -04001103 * @psde: Pointer to SDE plane object
1104 * @src: Source size
1105 * @dst: Destination size
1106 * @phase_steps: Pointer to output array for phase steps
1107 * @filter: Pointer to output array for filter type
1108 * @fmt: Pointer to format definition
1109 * @chroma_subsampling: Subsampling amount for chroma channel
1110 *
1111 * Returns: 0 on success
1112 */
1113static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001114 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001115 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001116 uint32_t chroma_subsampling)
1117{
Clarence Ipcb410d42016-06-26 22:52:33 -04001118 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001119 SDE_ERROR(
1120 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
1121 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001122 return -EINVAL;
1123 }
1124
Clarence Ip4c1d9772016-06-26 09:35:38 -04001125 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -04001126 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001127 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -04001128 phase_steps[SDE_SSPP_COMP_1_2] =
1129 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
1130 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
1131 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001132
1133 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -04001134 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -04001135 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001136 (src <= dst) ? SDE_SCALE_FILTER_BIL :
1137 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001138
Clarence Ipdbde9832016-06-26 09:48:36 -04001139 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001140 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -04001141 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
1142 } else {
1143 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
1144 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001145 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -04001146 }
1147 } else {
1148 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001149 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
1150 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
1151 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001152 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001153 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001154}
1155
Clarence Ipcb410d42016-06-26 22:52:33 -04001156/**
1157 * _sde_plane_setup_pixel_ext - determine default pixel extension values
1158 * @psde: Pointer to SDE plane object
1159 * @src: Source size
1160 * @dst: Destination size
1161 * @decimated_src: Source size after decimation, if any
1162 * @phase_steps: Pointer to output array for phase steps
1163 * @out_src: Output array for pixel extension values
1164 * @out_edge1: Output array for pixel extension first edge
1165 * @out_edge2: Output array for pixel extension second edge
1166 * @filter: Pointer to array for filter type
1167 * @fmt: Pointer to format definition
1168 * @chroma_subsampling: Subsampling amount for chroma channel
1169 * @post_compare: Whether to chroma subsampled source size for comparisions
1170 */
1171static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001172 uint32_t src, uint32_t dst, uint32_t decimated_src,
1173 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -04001174 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001175 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -04001176 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001177{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001178 int64_t edge1, edge2, caf;
1179 uint32_t src_work;
1180 int i, tmp;
1181
Clarence Ipcb410d42016-06-26 22:52:33 -04001182 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -04001183 out_edge2 && filter && fmt) {
1184 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001185 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001186 caf = PHASE_STEP_UNIT_SCALE;
1187 else
1188 caf = 0;
1189
1190 for (i = 0; i < SDE_MAX_PLANES; i++) {
1191 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -04001192 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001193 src_work /= chroma_subsampling;
1194 if (post_compare)
1195 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -04001196 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001197 /* unity */
1198 edge1 = 0;
1199 edge2 = 0;
1200 } else if (dst >= src) {
1201 /* upscale */
1202 edge1 = (1 << PHASE_RESIDUAL);
1203 edge1 -= caf;
1204 edge2 = (1 << PHASE_RESIDUAL);
1205 edge2 += (dst - 1) * *(phase_steps + i);
1206 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1207 edge2 += caf;
1208 edge2 = -(edge2);
1209 } else {
1210 /* downscale */
1211 edge1 = 0;
1212 edge2 = (dst - 1) * *(phase_steps + i);
1213 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1214 edge2 += *(phase_steps + i);
1215 edge2 = -(edge2);
1216 }
1217
1218 /* only enable CAF for luma plane */
1219 caf = 0;
1220
1221 /* populate output arrays */
1222 *(out_src + i) = src_work;
1223
1224 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001225 if (edge1 >= 0) {
1226 tmp = (uint32_t)edge1;
1227 tmp >>= PHASE_STEP_SHIFT;
1228 *(out_edge1 + i) = -tmp;
1229 } else {
1230 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -04001231 *(out_edge1 + i) =
1232 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1233 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001234 }
1235 if (edge2 >= 0) {
1236 tmp = (uint32_t)edge2;
1237 tmp >>= PHASE_STEP_SHIFT;
1238 *(out_edge2 + i) = -tmp;
1239 } else {
1240 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -04001241 *(out_edge2 + i) =
1242 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1243 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001244 }
1245 }
1246 }
1247}
1248
Clarence Ip5fc00c52016-09-23 15:03:34 -04001249static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -04001250{
1251 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
1252 {
Clarence Ip373f8592016-05-26 00:58:42 -04001253 /* S15.16 format */
1254 0x00012A00, 0x00000000, 0x00019880,
1255 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1256 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -04001257 },
Clarence Ip373f8592016-05-26 00:58:42 -04001258 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -04001259 { 0xfff0, 0xff80, 0xff80,},
1260 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001261 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -04001262 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001263 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -04001264 };
abeykun1c312f62016-08-26 09:47:12 -04001265 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
1266 {
1267 /* S15.16 format */
1268 0x00012A00, 0x00000000, 0x00019880,
1269 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1270 0x00012A00, 0x00020480, 0x00000000,
1271 },
1272 /* signed bias */
1273 { 0xffc0, 0xfe00, 0xfe00,},
1274 { 0x0, 0x0, 0x0,},
1275 /* unsigned clamp */
1276 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
1277 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
1278 };
Clarence Ipe78efb72016-06-24 18:35:21 -04001279
Clarence Ip5fc00c52016-09-23 15:03:34 -04001280 if (!psde) {
1281 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001282 return;
1283 }
Clarence Ip5e2a9222016-06-26 22:38:24 -04001284
Clarence Ipcae1bb62016-07-07 12:07:13 -04001285 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001286 if (psde->csc_usr_ptr)
1287 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -04001288 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
1289 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001290 else
Clarence Ip373f8592016-05-26 00:58:42 -04001291 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001292
Clarence Ip13a8cf42016-09-29 17:27:47 -04001293 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -04001294 psde->csc_ptr->csc_mv[0],
1295 psde->csc_ptr->csc_mv[1],
1296 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -04001297}
1298
Benet Clarkeb1b4462016-06-27 14:43:06 -07001299static void sde_color_process_plane_setup(struct drm_plane *plane)
1300{
1301 struct sde_plane *psde;
1302 struct sde_plane_state *pstate;
1303 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001304 struct drm_msm_memcol *memcol = NULL;
1305 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001306
1307 psde = to_sde_plane(plane);
1308 pstate = to_sde_plane_state(plane->state);
1309
1310 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1311 if (psde->pipe_hw->ops.setup_pa_hue)
1312 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1313 saturation = (uint32_t) sde_plane_get_property(pstate,
1314 PLANE_PROP_SATURATION_ADJUST);
1315 if (psde->pipe_hw->ops.setup_pa_sat)
1316 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1317 value = (uint32_t) sde_plane_get_property(pstate,
1318 PLANE_PROP_VALUE_ADJUST);
1319 if (psde->pipe_hw->ops.setup_pa_val)
1320 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1321 contrast = (uint32_t) sde_plane_get_property(pstate,
1322 PLANE_PROP_CONTRAST_ADJUST);
1323 if (psde->pipe_hw->ops.setup_pa_cont)
1324 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001325
Benet Clarkd009b1d2016-06-27 14:45:59 -07001326 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1327 /* Skin memory color setup */
1328 memcol = msm_property_get_blob(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001329 &pstate->property_state,
Benet Clarkd009b1d2016-06-27 14:45:59 -07001330 &memcol_sz,
1331 PLANE_PROP_SKIN_COLOR);
1332 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1333 MEMCOLOR_SKIN, memcol);
1334
1335 /* Sky memory color setup */
1336 memcol = msm_property_get_blob(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001337 &pstate->property_state,
Benet Clarkd009b1d2016-06-27 14:45:59 -07001338 &memcol_sz,
1339 PLANE_PROP_SKY_COLOR);
1340 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1341 MEMCOLOR_SKY, memcol);
1342
1343 /* Foliage memory color setup */
1344 memcol = msm_property_get_blob(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001345 &pstate->property_state,
Benet Clarkd009b1d2016-06-27 14:45:59 -07001346 &memcol_sz,
1347 PLANE_PROP_FOLIAGE_COLOR);
1348 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1349 MEMCOLOR_FOLIAGE, memcol);
1350 }
1351}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001352
Clarence Ipcb410d42016-06-26 22:52:33 -04001353static void _sde_plane_setup_scaler(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -04001354 struct sde_plane_state *pstate,
1355 const struct sde_format *fmt, bool color_fill)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001356{
Clarence Ipb43d4592016-09-08 14:21:35 -04001357 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001358 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001359
Clarence Ip172033f2017-06-13 10:52:56 -04001360 if (!psde || !fmt || !pstate) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001361 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1362 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001363 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001364 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001365
Clarence Ip172033f2017-06-13 10:52:56 -04001366 pe = &pstate->pixel_ext;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001367
Clarence Ipdedbba92016-09-27 17:43:10 -04001368 psde->pipe_cfg.horz_decimation =
1369 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1370 psde->pipe_cfg.vert_decimation =
1371 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001372
1373 /* don't chroma subsample if decimating */
1374 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001375 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001376 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001377 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001378
Clarence Ip5e2a9222016-06-26 22:38:24 -04001379 /* update scaler */
1380 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ip172033f2017-06-13 10:52:56 -04001381 int rc;
abeykun48f407a2016-08-25 12:06:44 -04001382
Clarence Ip172033f2017-06-13 10:52:56 -04001383 if (!color_fill && !psde->debugfs_default_scale)
1384 rc = _sde_plane_setup_scaler3_lut(psde, pstate);
1385 else
1386 rc = -EINVAL;
1387 if (rc || pstate->scaler_check_state !=
1388 SDE_PLANE_SCLCHECK_SCALER_V2) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001389 /* calculate default config for QSEED3 */
Clarence Ip172033f2017-06-13 10:52:56 -04001390 _sde_plane_setup_scaler3(psde, pstate,
Clarence Ipcb410d42016-06-26 22:52:33 -04001391 psde->pipe_cfg.src_rect.w,
1392 psde->pipe_cfg.src_rect.h,
1393 psde->pipe_cfg.dst_rect.w,
1394 psde->pipe_cfg.dst_rect.h,
Clarence Ip172033f2017-06-13 10:52:56 -04001395 &pstate->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001396 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001397 }
Clarence Ip172033f2017-06-13 10:52:56 -04001398 } else if (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 ||
1399 color_fill || psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001400 uint32_t deci_dim, i;
1401
Clarence Ipb43d4592016-09-08 14:21:35 -04001402 /* calculate default configuration for QSEED2 */
1403 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001404
Clarence Ip13a8cf42016-09-29 17:27:47 -04001405 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001406 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1407 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001408 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001409 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001410 psde->pipe_cfg.dst_rect.w,
1411 pe->phase_step_x,
1412 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001413
Clarence Ipdbde9832016-06-26 09:48:36 -04001414 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001415 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001416 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001417 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001418 pe->phase_step_x,
1419 pe->roi_w,
1420 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001421 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001422 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001423
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001424 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001425 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001426 _sde_plane_setup_scaler2(psde,
1427 deci_dim,
1428 psde->pipe_cfg.dst_rect.h,
1429 pe->phase_step_y,
1430 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001431 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001432 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001433 pe->phase_step_y,
1434 pe->roi_h,
1435 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001436 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001437 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001438
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001439 for (i = 0; i < SDE_MAX_PLANES; i++) {
1440 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001441 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001442 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001443 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001444
1445 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001446 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001447 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001448 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001449
1450 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001451 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001452 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001453 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001454
1455 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001456 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001457 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001458 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001459 }
1460 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001461}
1462
Clarence Ipcae1bb62016-07-07 12:07:13 -04001463/**
1464 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001465 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001466 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1467 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1468 * Returns: 0 on success
1469 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001470static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001471 uint32_t color, uint32_t alpha)
1472{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001473 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001474 const struct drm_plane *plane;
Clarence Ip172033f2017-06-13 10:52:56 -04001475 struct sde_plane_state *pstate;
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07001476 bool blend_enable = true;
Clarence Ipcb410d42016-06-26 22:52:33 -04001477
Clarence Ip172033f2017-06-13 10:52:56 -04001478 if (!psde || !psde->base.state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001479 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001480 return -EINVAL;
1481 }
1482
Clarence Ipcb410d42016-06-26 22:52:33 -04001483 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001484 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001485 return -EINVAL;
1486 }
1487
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001488 plane = &psde->base;
1489 pstate = to_sde_plane_state(plane->state);
1490
Clarence Ip13a8cf42016-09-29 17:27:47 -04001491 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001492
Clarence Ipcb410d42016-06-26 22:52:33 -04001493 /*
1494 * select fill format to match user property expectation,
1495 * h/w only supports RGB variants
1496 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001497 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001498
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07001499 blend_enable = (SDE_DRM_BLEND_OP_OPAQUE !=
1500 sde_plane_get_property(pstate, PLANE_PROP_BLEND_OP));
1501
Clarence Ipcb410d42016-06-26 22:52:33 -04001502 /* update sspp */
1503 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1504 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001505 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1506 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001507
1508 /* override scaler/decimation if solid fill */
1509 psde->pipe_cfg.src_rect.x = 0;
1510 psde->pipe_cfg.src_rect.y = 0;
1511 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1512 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Clarence Ip172033f2017-06-13 10:52:56 -04001513 _sde_plane_setup_scaler(psde, pstate, fmt, true);
Clarence Ipcb410d42016-06-26 22:52:33 -04001514
Clarence Ipcb410d42016-06-26 22:52:33 -04001515 if (psde->pipe_hw->ops.setup_format)
1516 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07001517 fmt, blend_enable, SDE_SSPP_SOLID_FILL,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001518 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001519
1520 if (psde->pipe_hw->ops.setup_rects)
1521 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001522 &psde->pipe_cfg,
1523 pstate->multirect_index);
1524
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001525 if (psde->pipe_hw->ops.setup_pe)
1526 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04001527 &pstate->pixel_ext);
Dhaval Patel2bbe8702017-08-30 21:22:52 -07001528
1529 if (psde->pipe_hw->ops.setup_scaler &&
1530 pstate->multirect_index != SDE_SSPP_RECT_1)
1531 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
1532 &psde->pipe_cfg, &pstate->pixel_ext,
1533 &pstate->scaler3_cfg);
Clarence Ipcb410d42016-06-26 22:52:33 -04001534 }
1535
1536 return 0;
1537}
1538
Alan Kwong4dd64c82017-02-04 18:41:51 -08001539/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001540 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1541 */
1542static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1543{
1544 drm_framebuffer_reference(fb);
1545 return fb;
1546}
1547static void _sde_plane_fb_put(void *fb)
1548{
1549 drm_framebuffer_unreference(fb);
1550}
1551static struct sde_crtc_res_ops fb_res_ops = {
1552 .put = _sde_plane_fb_put,
1553 .get = _sde_plane_fb_get,
1554};
1555
1556/**
1557 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1558 */
1559static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1560{
1561 sde_kms_fbo_reference(fbo);
1562 return fbo;
1563}
1564static void _sde_plane_fbo_put(void *fbo)
1565{
1566 sde_kms_fbo_unreference(fbo);
1567}
1568static struct sde_crtc_res_ops fbo_res_ops = {
1569 .put = _sde_plane_fbo_put,
1570 .get = _sde_plane_fbo_get,
1571};
1572
Clarence Ip8dece622017-12-22 18:25:25 -05001573u32 sde_plane_rot_get_prefill(struct drm_plane *plane)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001574{
1575 struct drm_plane_state *state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001576 struct sde_plane_state *pstate;
1577 struct sde_plane_rot_state *rstate;
1578 struct sde_kms *sde_kms;
Clarence Ip8dece622017-12-22 18:25:25 -05001579 u32 blocksize = 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001580
Clarence Ip7eb90452017-05-23 11:41:19 -04001581 if (!plane || !plane->state || !plane->state->fb) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001582 SDE_ERROR("invalid parameters\n");
1583 return 0;
1584 }
1585
Alan Kwong4dd64c82017-02-04 18:41:51 -08001586 state = plane->state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001587 pstate = to_sde_plane_state(state);
1588 rstate = &pstate->rot;
1589
Clarence Ip8dece622017-12-22 18:25:25 -05001590 if (!rstate->out_fb_format)
1591 return 0;
1592
1593 sde_kms = _sde_plane_get_kms(plane);
Clarence Ip7eb90452017-05-23 11:41:19 -04001594 if (!sde_kms || !sde_kms->catalog) {
1595 SDE_ERROR("invalid kms\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08001596 return 0;
1597 }
1598
Clarence Ip8dece622017-12-22 18:25:25 -05001599 /* return zero if out_fb_format isn't valid */
1600 if (sde_format_get_block_size(rstate->out_fb_format,
1601 &blocksize, &blocksize))
1602 return 0;
Clarence Ip7eb90452017-05-23 11:41:19 -04001603
Clarence Ip8dece622017-12-22 18:25:25 -05001604 return blocksize + sde_kms->catalog->sbuf_headroom;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001605}
1606
1607/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08001608 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1609 * enumerating over all planes attached to the same rotator
1610 * @plane: Pointer to drm plane
1611 * @state: Pointer to drm state to be updated
Alan Kwong05109752017-08-12 20:26:45 -04001612 * return: 0 if success; error code otherwise
Alan Kwong4dd64c82017-02-04 18:41:51 -08001613 */
Alan Kwong05109752017-08-12 20:26:45 -04001614static int sde_plane_rot_calc_cfg(struct drm_plane *plane,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001615 struct drm_plane_state *state)
1616{
1617 struct sde_plane_state *pstate;
1618 struct sde_plane_rot_state *rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001619 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001620 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001621 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001622 u32 dst_x, dst_y, dst_w, dst_h;
1623 int found = 0;
1624 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001625 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001626
1627 if (!plane || !state || !state->state) {
1628 SDE_ERROR("invalid parameters\n");
Alan Kwong05109752017-08-12 20:26:45 -04001629 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001630 }
1631
Alan Kwongcdb2f282017-03-18 13:42:06 -07001632 cstate = _sde_plane_get_crtc_state(state);
1633 if (IS_ERR_OR_NULL(cstate)) {
1634 ret = PTR_ERR(cstate);
1635 SDE_ERROR("invalid crtc state %d\n", ret);
Alan Kwong05109752017-08-12 20:26:45 -04001636 return ret;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001637 }
1638
Alan Kwong4dd64c82017-02-04 18:41:51 -08001639 pstate = to_sde_plane_state(state);
1640 rstate = &pstate->rot;
1641
Alan Kwong4dd64c82017-02-04 18:41:51 -08001642 in_rot = &rstate->in_rot_rect;
1643 in_rot->x1 = state->src_x;
1644 in_rot->y1 = state->src_y;
1645 in_rot->x2 = state->src_x + state->src_w;
1646 in_rot->y2 = state->src_y + state->src_h;
1647
1648 out_rot = &rstate->out_rot_rect;
1649 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1650 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1651 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1652 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1653
1654 if (!dst_w && !dst_h) {
1655 rstate->out_rot_rect = rstate->in_rot_rect;
1656 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1657 state->fb->height << 16, rstate->in_rotation);
1658 } else {
1659 out_rot->x1 = dst_x;
1660 out_rot->y1 = dst_y;
1661 out_rot->x2 = dst_x + dst_w;
1662 out_rot->y2 = dst_y + dst_h;
1663 }
1664
1665 rstate->out_src_rect = rstate->out_rot_rect;
1666
Alan Kwong4dd64c82017-02-04 18:41:51 -08001667 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001668 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001669 struct drm_plane_state *attached_state;
1670 struct sde_plane_state *attached_pstate;
1671 struct sde_plane_rot_state *attached_rstate;
1672 struct drm_rect attached_out_rect;
1673
Alan Kwong4dd64c82017-02-04 18:41:51 -08001674 attached_state = drm_atomic_get_existing_plane_state(
1675 state->state, attached_plane);
1676
1677 if (!attached_state)
1678 continue;
1679
1680 attached_pstate = to_sde_plane_state(attached_state);
1681 attached_rstate = &attached_pstate->rot;
1682
Clarence Ipd27d9632017-06-14 09:57:26 -04001683 if (attached_state->fb != state->fb)
1684 continue;
1685
1686 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) !=
1687 sde_plane_get_property(attached_pstate,
1688 PLANE_PROP_ROTATION))
Alan Kwongcdb2f282017-03-18 13:42:06 -07001689 continue;
1690
1691 found++;
1692
1693 /* skip itself */
1694 if (attached_plane == plane)
1695 continue;
1696
Alan Kwong4dd64c82017-02-04 18:41:51 -08001697 /* find bounding rotator source roi */
1698 if (attached_state->src_x < in_rot->x1)
1699 in_rot->x1 = attached_state->src_x;
1700
1701 if (attached_state->src_y < in_rot->y1)
1702 in_rot->y1 = attached_state->src_y;
1703
1704 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1705 in_rot->x2 = attached_state->src_x +
1706 attached_state->src_w;
1707
1708 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1709 in_rot->y2 = attached_state->src_y +
1710 attached_state->src_h;
1711
1712 /* find bounding rotator destination roi */
1713 dst_x = sde_plane_get_property(attached_pstate,
1714 PLANE_PROP_ROT_DST_X);
1715 dst_y = sde_plane_get_property(attached_pstate,
1716 PLANE_PROP_ROT_DST_Y);
1717 dst_w = sde_plane_get_property(attached_pstate,
1718 PLANE_PROP_ROT_DST_W);
1719 dst_h = sde_plane_get_property(attached_pstate,
1720 PLANE_PROP_ROT_DST_H);
1721 if (!dst_w && !dst_h) {
1722 attached_out_rect.x1 = attached_state->src_x;
1723 attached_out_rect.y1 = attached_state->src_y;
1724 attached_out_rect.x2 = attached_out_rect.x1 +
1725 attached_state->src_w;
1726 attached_out_rect.y2 = attached_out_rect.y1 +
1727 attached_state->src_h;
1728 drm_rect_rotate(&attached_out_rect,
1729 state->fb->width << 16,
1730 state->fb->height << 16,
1731 rstate->in_rotation);
1732 } else {
1733 attached_out_rect.x1 = dst_x;
1734 attached_out_rect.y1 = dst_y;
1735 attached_out_rect.x2 = dst_x + dst_w;
1736 attached_out_rect.y2 = dst_y + dst_h;
1737 }
1738
Alan Kwong05109752017-08-12 20:26:45 -04001739 /* check source split left/right mismatch */
1740 if (attached_out_rect.y1 != rstate->out_src_rect.y1 ||
1741 attached_out_rect.y2 != rstate->out_src_rect.y2) {
1742 SDE_ERROR(
1743 "plane%d.%u src:%dx%d+%d+%d rot:0x%llx fb:%d plane%d.%u src:%dx%d+%d+%d rot:0x%llx fb:%d mismatch\n",
1744 plane->base.id,
1745 rstate->sequence_id,
1746 state->src_w >> 16,
1747 state->src_h >> 16,
1748 state->src_x >> 16,
1749 state->src_y >> 16,
1750 sde_plane_get_property(pstate,
1751 PLANE_PROP_ROTATION),
1752 state->fb ?
1753 state->fb->base.id :
1754 -1,
1755 attached_plane->base.id,
1756 attached_rstate->sequence_id,
1757 attached_state->src_w >> 16,
1758 attached_state->src_h >> 16,
1759 attached_state->src_x >> 16,
1760 attached_state->src_y >> 16,
1761 sde_plane_get_property(attached_pstate,
1762 PLANE_PROP_ROTATION),
1763 attached_state->fb ?
1764 attached_state->fb->base.id :
1765 -1);
1766 SDE_ERROR(
1767 "plane%d.%u sspp:%dx%d+%d+%d plane%d.%u sspp:%dx%d+%d+%d\n",
1768 plane->base.id,
1769 rstate->sequence_id,
1770 (rstate->out_src_rect.x2 -
1771 rstate->out_src_rect.x1) >> 16,
1772 (rstate->out_src_rect.y2 -
1773 rstate->out_src_rect.y1) >> 16,
1774 rstate->out_src_rect.x1 >> 16,
1775 rstate->out_src_rect.y1 >> 16,
1776 attached_plane->base.id,
1777 attached_rstate->sequence_id,
1778 (attached_out_rect.x2 -
1779 attached_out_rect.x1) >> 16,
1780 (attached_out_rect.y2 -
1781 attached_out_rect.y1) >> 16,
1782 attached_out_rect.x1 >> 16,
1783 attached_out_rect.y1 >> 16);
1784 SDE_EVT32(DRMID(plane),
1785 rstate->sequence_id,
1786 rstate->out_src_rect.x1 >> 16,
1787 rstate->out_src_rect.y1 >> 16,
1788 (rstate->out_src_rect.x2 -
1789 rstate->out_src_rect.x1) >> 16,
1790 (rstate->out_src_rect.y2 -
1791 rstate->out_src_rect.y1) >> 16,
1792 attached_plane->base.id,
1793 attached_rstate->sequence_id,
1794 attached_out_rect.x1 >> 16,
1795 attached_out_rect.y1 >> 16,
1796 (attached_out_rect.x2 -
1797 attached_out_rect.x1) >> 16,
1798 (attached_out_rect.y2 -
1799 attached_out_rect.y1) >> 16,
1800 SDE_EVTLOG_ERROR);
1801 return -EINVAL;
1802 }
1803
Alan Kwong4dd64c82017-02-04 18:41:51 -08001804 /* find relative sspp position */
1805 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1806 xpos++;
1807
1808 if (attached_out_rect.x1 < out_rot->x1)
1809 out_rot->x1 = attached_out_rect.x1;
1810
1811 if (attached_out_rect.y1 < out_rot->y1)
1812 out_rot->y1 = attached_out_rect.y1;
1813
1814 if (attached_out_rect.x2 > out_rot->x2)
1815 out_rot->x2 = attached_out_rect.x2;
1816
1817 if (attached_out_rect.y2 > out_rot->y2)
1818 out_rot->y2 = attached_out_rect.y2;
1819
1820 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1821 attached_plane->base.id,
1822 attached_rstate->sequence_id,
1823 attached_rstate->out_src_rect.x1 >> 16,
1824 attached_state->src_w >> 16,
1825 attached_state->src_h >> 16,
1826 attached_state->src_x >> 16,
1827 attached_state->src_y >> 16,
1828 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1829 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1830 attached_rstate->out_src_rect.x1 >> 16,
1831 attached_rstate->out_src_rect.y1 >> 16);
1832 }
1833
1834 rstate->out_xpos = xpos;
1835 rstate->nplane = found;
1836
1837 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1838 plane->base.id, rstate->sequence_id,
1839 rstate->out_xpos, rstate->nplane,
1840 drm_rect_width(in_rot) >> 16,
1841 drm_rect_height(in_rot) >> 16,
1842 in_rot->x1 >> 16, in_rot->y1 >> 16,
1843 drm_rect_width(&rstate->out_rot_rect) >> 16,
1844 drm_rect_height(&rstate->out_rot_rect) >> 16,
1845 rstate->out_rot_rect.x1 >> 16,
1846 rstate->out_rot_rect.y1 >> 16);
Clarence Ipeb39cce2017-07-19 14:12:43 -04001847 SDE_EVT32(DRMID(plane), rstate->sequence_id,
Clarence Ipf27c6f22017-07-10 18:19:44 -04001848 rstate->out_xpos, rstate->nplane,
1849 in_rot->x1 >> 16, in_rot->y1 >> 16,
1850 drm_rect_width(in_rot) >> 16,
1851 drm_rect_height(in_rot) >> 16,
1852 rstate->out_rot_rect.x1 >> 16,
1853 rstate->out_rot_rect.y1 >> 16,
1854 drm_rect_width(&rstate->out_rot_rect) >> 16,
1855 drm_rect_height(&rstate->out_rot_rect) >> 16);
Alan Kwong05109752017-08-12 20:26:45 -04001856
1857 return 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001858}
1859
1860/**
1861 * sde_plane_rot_submit_command - commit given state for the rotator stage
1862 * @plane: Pointer to drm plane
1863 * @state: Pointer to the state to be committed
1864 * @hw_cmd: rotator command type
1865 * return: 0 if success; error code otherwise
1866 */
1867static int sde_plane_rot_submit_command(struct drm_plane *plane,
1868 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1869{
1870 struct sde_plane *psde = to_sde_plane(plane);
1871 struct sde_plane_state *pstate = to_sde_plane_state(state);
1872 struct sde_plane_rot_state *rstate = &pstate->rot;
1873 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001874 struct drm_crtc_state *cstate;
1875 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001876 int ret, i;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001877 int fb_mode;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001878
1879 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1880 SDE_ERROR("invalid parameters\n");
1881 return -EINVAL;
1882 }
1883
Alan Kwong4aacd532017-02-04 18:51:33 -08001884 cstate = _sde_plane_get_crtc_state(state);
1885 if (IS_ERR_OR_NULL(cstate)) {
1886 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1887 return -EINVAL;
1888 }
1889 sde_cstate = to_sde_crtc_state(cstate);
1890
Alan Kwong4dd64c82017-02-04 18:41:51 -08001891 rot_cmd = &rstate->rot_cmd;
1892
1893 rot_cmd->master = (rstate->out_xpos == 0);
1894 rot_cmd->sequence_id = rstate->sequence_id;
1895 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1896 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1897 DEFAULT_REFRESH_RATE;
1898 rot_cmd->rot90 = rstate->rot90;
1899 rot_cmd->hflip = rstate->hflip;
1900 rot_cmd->vflip = rstate->vflip;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001901 fb_mode = sde_plane_get_property(pstate,
1902 PLANE_PROP_FB_TRANSLATION_MODE);
1903 if ((fb_mode == SDE_DRM_FB_SEC) ||
1904 (fb_mode == SDE_DRM_FB_SEC_DIR_TRANS))
1905 rot_cmd->secure = true;
1906 else
1907 rot_cmd->secure = false;
1908
Alan Kwong4aacd532017-02-04 18:51:33 -08001909 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1910 CRTC_PROP_ROT_PREFILL_BW);
Clarence Ip4f339092018-01-05 13:29:04 -05001911 rot_cmd->clkrate = sde_crtc_get_sbuf_clk(cstate);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001912 rot_cmd->dst_writeback = psde->sbuf_writeback;
1913
1914 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1915 rot_cmd->video_mode = true;
1916 else
1917 rot_cmd->video_mode = false;
1918
1919 rot_cmd->src_pixel_format = state->fb->pixel_format;
1920 rot_cmd->src_modifier = state->fb->modifier[0];
1921 rot_cmd->src_stride = state->fb->pitches[0];
1922
1923 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1924 if (!rot_cmd->src_format) {
1925 SDE_ERROR("failed to get src format\n");
1926 return -EINVAL;
1927 }
1928
1929 rot_cmd->src_width = state->fb->width;
1930 rot_cmd->src_height = state->fb->height;
1931 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1932 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1933 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1934 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
Alan Kwong809f3cbd2017-08-11 18:39:36 -04001935 rot_cmd->dst_rect_x = 0;
1936 rot_cmd->dst_rect_y = 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001937 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1938 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
Clarence Ip8dece622017-12-22 18:25:25 -05001939 rot_cmd->crtc_h = state->crtc_h;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001940
1941 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1942 struct sde_hw_fmt_layout layout;
1943
1944 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Clarence Ip299fa602017-07-11 18:01:37 -04001945 sde_format_populate_layout(pstate->aspace, state->fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001946 &layout);
1947 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1948 rot_cmd->src_iova[i] = layout.plane_addr[i];
1949 rot_cmd->src_len[i] = layout.plane_size[i];
1950 }
1951 rot_cmd->src_planes = layout.num_planes;
1952
1953 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Clarence Ip299fa602017-07-11 18:01:37 -04001954 sde_format_populate_layout(pstate->aspace, rstate->out_fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001955 &layout);
1956 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1957 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1958 rot_cmd->dst_len[i] = layout.plane_size[i];
1959 }
1960 rot_cmd->dst_planes = layout.num_planes;
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001961
1962 /* VBIF remapper settings */
Alan Kwong032c2e182017-06-29 16:31:38 -04001963 for (i = 0; i < rstate->rot_hw->caps->xin_count; i++) {
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001964 const struct sde_rot_vbif_cfg *cfg =
1965 &rstate->rot_hw->caps->vbif_cfg[i];
1966
1967 _sde_plane_inline_rot_set_qos_remap(plane, cfg);
1968
1969 if (cfg->is_read) {
1970 _sde_plane_inline_rot_set_ot_limit(plane,
1971 state->crtc, cfg, rot_cmd->src_rect_w,
1972 rot_cmd->src_rect_h);
1973 } else {
1974 _sde_plane_inline_rot_set_ot_limit(plane,
1975 state->crtc, cfg, rot_cmd->dst_rect_w,
1976 rot_cmd->dst_rect_h);
1977 }
1978 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001979 }
1980
1981 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
Alan Kwong05109752017-08-12 20:26:45 -04001982 if (ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001983 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001984
1985 rstate->out_rotation = rstate->in_rotation;
1986 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1987 DRM_MODE_FB_MODIFIERS : 0;
1988 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1989 rstate->out_fb_format = rot_cmd->dst_format;
1990 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1991
1992 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1993 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1994
1995 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1996 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1997 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1998 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1999 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
2000 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
2001
2002 if (rot_cmd->rot90)
2003 rstate->out_rotation &= ~DRM_ROTATE_90;
2004
2005 if (rot_cmd->hflip)
2006 rstate->out_rotation &= ~DRM_REFLECT_X;
2007
2008 if (rot_cmd->vflip)
2009 rstate->out_rotation &= ~DRM_REFLECT_Y;
2010
2011 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002012 "plane%d.%d rot:%d/%c%c%c%c/%dx%d/%4.4s/%llx/%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08002013 plane->base.id, rstate->sequence_id, hw_cmd,
2014 rot_cmd->rot90 ? 'r' : '_',
2015 rot_cmd->hflip ? 'h' : '_',
2016 rot_cmd->vflip ? 'v' : '_',
2017 rot_cmd->video_mode ? 'V' : 'C',
2018 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002019 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002020 state->fb->modifier[0],
2021 drm_rect_width(&rstate->in_rot_rect) >> 16,
2022 drm_rect_height(&rstate->in_rot_rect) >> 16,
2023 rstate->in_rot_rect.x1 >> 16,
2024 rstate->in_rot_rect.y1 >> 16);
2025
Dhaval Patel6c666622017-03-21 23:02:59 -07002026 SDE_DEBUG("plane%d.%d sspp:%d/%x/%dx%d/%4.4s/%llx/%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08002027 plane->base.id, rstate->sequence_id, hw_cmd,
2028 rstate->out_rotation,
2029 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002030 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002031 rstate->out_fb_modifier[0],
2032 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2033 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
2034
2035 return ret;
2036}
2037
2038/**
Clarence Ipd27d9632017-06-14 09:57:26 -04002039 * _sde_plane_rot_get_fb - attempt to get previously allocated fb/fbo
2040 * If an fb/fbo was already created, either from a previous frame or
2041 * from another plane in the current commit cycle, attempt to reuse
2042 * it for this commit cycle as well.
2043 * @plane: Pointer to drm plane
2044 * @cstate: Pointer to crtc state
2045 * @rstate: Pointer to rotator plane state
2046 */
2047static void _sde_plane_rot_get_fb(struct drm_plane *plane,
2048 struct drm_crtc_state *cstate,
2049 struct sde_plane_rot_state *rstate)
2050{
2051 struct sde_kms_fbo *fbo;
2052 struct drm_framebuffer *fb;
2053
Clarence Ipf27c6f22017-07-10 18:19:44 -04002054 if (!plane || !cstate || !rstate || !rstate->rot_hw)
Clarence Ipd27d9632017-06-14 09:57:26 -04002055 return;
2056
2057 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2058 (u64) &rstate->rot_hw->base);
2059 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2060 (u64) &rstate->rot_hw->base);
2061 if (fb && fbo) {
2062 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
2063 rstate->sequence_id);
2064 } else if (fbo) {
2065 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2066 (u64) &rstate->rot_hw->base);
2067 fbo = NULL;
2068 } else if (fb) {
2069 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2070 (u64) &rstate->rot_hw->base);
2071 fb = NULL;
2072 }
2073
2074 rstate->out_fbo = fbo;
2075 rstate->out_fb = fb;
2076}
2077
2078/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002079 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
2080 * for rotator (pre-sspp) stage
2081 * @plane: Pointer to drm plane
2082 * @new_state: Pointer to new drm plane state
2083 * return: 0 if success; error code otherwise
2084 */
2085static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
2086 struct drm_plane_state *new_state)
2087{
2088 struct drm_framebuffer *fb = new_state->fb;
2089 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
2090 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002091 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002092 int ret;
2093
2094 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
2095 plane->base.id,
2096 new_rstate->sequence_id, fb ? fb->base.id : 0,
2097 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
2098 sde_plane_crtc_enabled(new_state));
2099
2100 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
2101 return 0;
2102
Alan Kwongcdb2f282017-03-18 13:42:06 -07002103 cstate = _sde_plane_get_crtc_state(new_state);
2104 if (IS_ERR(cstate)) {
2105 ret = PTR_ERR(cstate);
2106 SDE_ERROR("invalid crtc state %d\n", ret);
2107 return ret;
2108 }
2109
Alan Kwong4dd64c82017-02-04 18:41:51 -08002110 /* need to re-calc based on all newly validated plane states */
Alan Kwong05109752017-08-12 20:26:45 -04002111 ret = sde_plane_rot_calc_cfg(plane, new_state);
2112 if (ret)
2113 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002114
2115 /* check if stream buffer is already attached to rotator */
Clarence Ipd27d9632017-06-14 09:57:26 -04002116 if (sde_plane_enabled(new_state) && !new_rstate->out_fb)
2117 _sde_plane_rot_get_fb(plane, cstate, new_rstate);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002118
Alan Kwong4dd64c82017-02-04 18:41:51 -08002119 /* create new stream buffer if it is not available */
2120 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
2121 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
2122 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
2123
2124 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
2125 new_rstate->sequence_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002126
2127 /* check if out_fb is already attached to rotator */
2128 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
2129 new_rstate->out_fb_pixel_format,
2130 new_rstate->out_fb_modifier,
2131 new_rstate->out_fb_flags);
2132 if (!new_rstate->out_fbo) {
2133 SDE_ERROR("failed to allocate inline buffer object\n");
2134 ret = -EINVAL;
2135 goto error_create_fbo;
2136 }
2137
Alan Kwongcdb2f282017-03-18 13:42:06 -07002138 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2139 (u64) &new_rstate->rot_hw->base,
2140 new_rstate->out_fbo, &fbo_res_ops);
2141 if (ret) {
2142 SDE_ERROR("failed to add crtc resource\n");
2143 goto error_create_fbo_res;
2144 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002145
2146 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
2147 new_rstate->out_fbo);
2148 if (!new_rstate->out_fb) {
2149 SDE_ERROR("failed to create inline framebuffer\n");
2150 ret = -EINVAL;
2151 goto error_create_fb;
2152 }
Clarence Ipf27c6f22017-07-10 18:19:44 -04002153 SDE_EVT32_VERBOSE(DRMID(plane), new_rstate->sequence_id,
2154 new_rstate->out_fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002155
Alan Kwongcdb2f282017-03-18 13:42:06 -07002156 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2157 (u64) &new_rstate->rot_hw->base,
2158 new_rstate->out_fb, &fb_res_ops);
2159 if (ret) {
2160 SDE_ERROR("failed to add crtc resource %d\n", ret);
2161 goto error_create_fb_res;
2162 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002163 }
2164
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002165 if (new_pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002166 SDE_EVT32(DRMID(plane));
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002167 SDE_DEBUG(
2168 "plane%d, domain not attached, prepare fb handled later\n",
2169 plane->base.id);
2170 return 0;
2171 }
2172
Alan Kwong4dd64c82017-02-04 18:41:51 -08002173 /* prepare rotator input buffer */
Clarence Ip299fa602017-07-11 18:01:37 -04002174 ret = msm_framebuffer_prepare(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002175 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002176 SDE_ERROR("failed to prepare input framebuffer, %d\n", ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002177 goto error_prepare_input_buffer;
2178 }
2179
2180 /* prepare rotator output buffer */
2181 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
2182 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
2183 new_rstate->sequence_id);
2184
2185 ret = msm_framebuffer_prepare(new_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002186 new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002187 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002188 SDE_ERROR("failed to prepare inline framebuffer, %d\n",
2189 ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002190 goto error_prepare_output_buffer;
2191 }
2192 }
2193
2194 return 0;
2195
2196error_prepare_output_buffer:
Clarence Ip299fa602017-07-11 18:01:37 -04002197 msm_framebuffer_cleanup(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002198error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002199 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2200 (u64) &new_rstate->rot_hw->base);
2201error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002202 new_rstate->out_fb = NULL;
2203error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002204 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2205 (u64) &new_rstate->rot_hw->base);
2206error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002207 new_rstate->out_fbo = NULL;
2208error_create_fbo:
2209 return ret;
2210}
2211
2212/**
2213 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
2214 * rotator (pre-sspp) stage
2215 * @plane: Pointer to drm plane
2216 * @old_state: Pointer to previous drm plane state
2217 * return: none
2218 */
2219static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
2220 struct drm_plane_state *old_state)
2221{
2222 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
2223 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2224 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002225 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002226 int ret;
2227
2228 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2229 old_rstate->sequence_id, old_state->fb->base.id,
2230 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
2231 sde_plane_crtc_enabled(old_state));
2232
2233 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
2234 return;
2235
Alan Kwongcdb2f282017-03-18 13:42:06 -07002236 cstate = _sde_plane_get_crtc_state(old_state);
2237 if (IS_ERR(cstate)) {
2238 ret = PTR_ERR(cstate);
2239 SDE_ERROR("invalid crtc state %d\n", ret);
2240 return;
2241 }
2242
Alan Kwong4dd64c82017-02-04 18:41:51 -08002243 if (sde_plane_crtc_enabled(old_state)) {
2244 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
2245 SDE_HW_ROT_CMD_CLEANUP);
2246 if (ret)
2247 SDE_ERROR("failed to cleanup rotator buffers\n");
2248 }
2249
2250 if (sde_plane_enabled(old_state)) {
2251 if (old_rstate->out_fb) {
2252 msm_framebuffer_cleanup(old_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002253 old_pstate->aspace);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002254 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2255 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002256 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002257 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2258 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002259 old_rstate->out_fbo = NULL;
2260 }
2261
Clarence Ip299fa602017-07-11 18:01:37 -04002262 msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002263 }
2264}
2265
2266/**
2267 * sde_plane_rot_atomic_check - verify rotator update of the given state
2268 * @plane: Pointer to drm plane
2269 * @state: Pointer to drm plane state to be validated
2270 * return: 0 if success; error code otherwise
2271 */
2272static int sde_plane_rot_atomic_check(struct drm_plane *plane,
2273 struct drm_plane_state *state)
2274{
2275 struct sde_plane *psde;
2276 struct sde_plane_state *pstate, *old_pstate;
2277 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002278 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002279 struct sde_hw_blk *hw_blk;
2280 int i, ret = 0;
2281
2282 if (!plane || !state) {
2283 SDE_ERROR("invalid plane/state\n");
2284 return -EINVAL;
2285 }
2286
2287 psde = to_sde_plane(plane);
2288 pstate = to_sde_plane_state(state);
2289 old_pstate = to_sde_plane_state(plane->state);
2290 rstate = &pstate->rot;
2291 old_rstate = &old_pstate->rot;
2292
Alan Kwongcdb2f282017-03-18 13:42:06 -07002293 /* cstate will be null if crtc is disconnected from plane */
2294 cstate = _sde_plane_get_crtc_state(state);
2295 if (IS_ERR(cstate)) {
2296 ret = PTR_ERR(cstate);
2297 SDE_ERROR("invalid crtc state %d\n", ret);
2298 return ret;
2299 }
2300
Alan Kwong4dd64c82017-02-04 18:41:51 -08002301 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2302 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
2303 !!rstate->out_sbuf, !!rstate->rot_hw,
2304 sde_plane_crtc_enabled(state));
2305
2306 rstate->in_rotation = drm_rotation_simplify(
2307 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07002308 DRM_ROTATE_0 | DRM_ROTATE_90 |
2309 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002310 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
2311 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
2312 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
2313 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
2314
Alan Kwongcdb2f282017-03-18 13:42:06 -07002315 if (sde_plane_enabled(state) && rstate->out_sbuf) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002316 SDE_DEBUG("plane%d.%d acquire rotator, fb %d\n",
2317 plane->base.id, rstate->sequence_id,
2318 state->fb ? state->fb->base.id : -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002319
Alan Kwongcdb2f282017-03-18 13:42:06 -07002320 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
2321 (u64) state->fb);
2322 if (!hw_blk) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002323 SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
2324 plane->base.id, rstate->sequence_id,
2325 state->fb ? state->fb->base.id : -1);
Alan Kwong310e9b02017-08-03 02:04:07 -04002326 SDE_EVT32(DRMID(plane), rstate->sequence_id,
2327 SDE_EVTLOG_ERROR);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002328 return -EINVAL;
2329 }
2330
Alan Kwongcdb2f282017-03-18 13:42:06 -07002331 rstate->rot_hw = to_sde_hw_rot(hw_blk);
2332
Alan Kwong4dd64c82017-02-04 18:41:51 -08002333 if (!rstate->rot_hw->ops.commit) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002334 SDE_ERROR("plane%d.%d invalid rotator ops\n",
2335 plane->base.id, rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002336 sde_crtc_res_put(cstate,
2337 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002338 rstate->rot_hw = NULL;
2339 return -EINVAL;
2340 }
2341
2342 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002343 } else {
2344 rstate->in_fb = NULL;
2345 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002346 }
2347
2348 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002349 uint32_t fb_id;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002350
Clarence Ipf27c6f22017-07-10 18:19:44 -04002351 fb_id = state->fb ? state->fb->base.id : -1;
2352 SDE_DEBUG("plane%d.%d use rotator, fb %d\n",
2353 plane->base.id, rstate->sequence_id, fb_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002354
Alan Kwong05109752017-08-12 20:26:45 -04002355 ret = sde_plane_rot_calc_cfg(plane, state);
2356 if (ret)
2357 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002358
2359 ret = sde_plane_rot_submit_command(plane, state,
2360 SDE_HW_ROT_CMD_VALIDATE);
Clarence Ipf27c6f22017-07-10 18:19:44 -04002361 if (ret)
2362 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002363
Clarence Ip317a9572017-08-08 18:16:26 -04002364 if (rstate->nplane != old_rstate->nplane ||
2365 rstate->out_xpos != old_rstate->out_xpos)
2366 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2367 SDE_PLANE_DIRTY_RECTS;
2368
Clarence Ipf27c6f22017-07-10 18:19:44 -04002369 /* check if stream buffer is already attached to rotator */
2370 _sde_plane_rot_get_fb(plane, cstate, rstate);
2371
2372 /* release buffer if output format configuration changes */
2373 if (rstate->out_fb &&
2374 ((rstate->out_fb_height != rstate->out_fb->height) ||
2375 (rstate->out_fb_width != rstate->out_fb->width) ||
2376 (rstate->out_fb_pixel_format !=
2377 rstate->out_fb->pixel_format) ||
2378 (rstate->out_fb_modifier[0] !=
2379 rstate->out_fb->modifier[0]) ||
2380 (rstate->out_fb_flags != rstate->out_fb->flags))) {
2381
2382 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
2383 rstate->sequence_id);
2384 SDE_EVT32_VERBOSE(DRMID(plane),
2385 rstate->sequence_id, fb_id);
2386
2387 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2388 (u64) &rstate->rot_hw->base);
2389 rstate->out_fb = NULL;
2390 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2391 (u64) &rstate->rot_hw->base);
2392 rstate->out_fbo = NULL;
2393 }
Clarence Ip13d91472018-01-23 17:17:30 -05002394
2395 /*
2396 * For video mode, reject any downscale factor greater than or
2397 * equal to 1.1x
2398 *
2399 * Check the downscale factor first to avoid querying the
2400 * interface mode unnecessarily.
2401 */
2402 if ((rstate->out_src_h >> 16) * 10 >= state->crtc_h * 11 &&
2403 sde_crtc_get_intf_mode(state->crtc) ==
2404 INTF_MODE_VIDEO) {
2405 SDE_DEBUG_PLANE(psde,
2406 "inline %d with invalid scale, %dx%d, %dx%d\n",
2407 rstate->sequence_id,
2408 rstate->out_src_w, rstate->out_src_h,
2409 state->crtc_w, state->crtc_h);
2410 SDE_EVT32(DRMID(plane), rstate->sequence_id,
2411 rstate->out_src_w >> 16,
2412 rstate->out_src_h >> 16,
2413 state->crtc_w, state->crtc_h,
2414 SDE_EVTLOG_ERROR);
2415 return -EINVAL;
2416 }
Clarence Ip4475d582017-04-18 11:36:00 -04002417 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002418
2419 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
2420 rstate->sequence_id);
2421
2422 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04002423 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
2424 rstate->out_fb_modifier[i] = state->fb ?
2425 state->fb->modifier[i] : 0x0;
2426
2427 if (state->fb) {
2428 rstate->out_fb_pixel_format = state->fb->pixel_format;
2429 rstate->out_fb_flags = state->fb->flags;
2430 rstate->out_fb_width = state->fb->width;
2431 rstate->out_fb_height = state->fb->height;
2432 } else {
2433 rstate->out_fb_pixel_format = 0x0;
2434 rstate->out_fb_flags = 0x0;
2435 rstate->out_fb_width = 0;
2436 rstate->out_fb_height = 0;
2437 }
2438
Alan Kwong4dd64c82017-02-04 18:41:51 -08002439 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002440 rstate->out_src_x = state->src_x;
2441 rstate->out_src_y = state->src_y;
2442 rstate->out_src_w = state->src_w;
2443 rstate->out_src_h = state->src_h;
2444
2445 rstate->out_fb_format = NULL;
2446 rstate->out_sbuf = false;
2447 rstate->out_fb = state->fb;
2448 }
2449
2450 return ret;
2451}
2452
2453/**
2454 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2455 * @plane: Pointer to drm plane
2456 * @old_state: Pointer to previous state
2457 * return: none
2458 */
2459static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2460 struct drm_plane_state *old_state)
2461{
2462 struct drm_plane_state *state;
2463 struct sde_plane_state *pstate;
2464 struct sde_plane_rot_state *rstate;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002465 int ret = 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002466
2467 if (!plane || !plane->state) {
2468 SDE_ERROR("invalid plane/state\n");
2469 return;
2470 }
2471
2472 state = plane->state;
2473 pstate = to_sde_plane_state(state);
2474 rstate = &pstate->rot;
2475
2476 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2477 rstate->sequence_id,
2478 !!rstate->out_sbuf, !!rstate->rot_hw,
2479 sde_plane_crtc_enabled(plane->state));
2480
2481 if (!sde_plane_crtc_enabled(state))
2482 return;
2483
2484 if (!rstate->out_sbuf || !rstate->rot_hw)
2485 return;
2486
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002487 /*
2488 * framebuffer prepare is deferred for prepare_fb calls that
2489 * happen during the transition from secure to non-secure.
2490 * Handle the prepare at this point for rotator in such cases.
2491 * This can be expected for one or two frames during the transition.
2492 */
2493 if (pstate->aspace && pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002494 SDE_EVT32(DRMID(plane), pstate->aspace->domain_attached);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002495 /* prepare rotator input buffer */
2496 ret = msm_framebuffer_prepare(state->fb, pstate->aspace);
2497 if (ret) {
2498 SDE_ERROR("p%d failed to prepare input fb %d\n",
2499 plane->base.id, ret);
2500 return;
2501 }
2502
2503 /* prepare rotator output buffer */
2504 if (sde_plane_enabled(state) && rstate->out_fb) {
2505 ret = msm_framebuffer_prepare(rstate->out_fb,
2506 pstate->aspace);
2507 if (ret) {
2508 SDE_ERROR(
2509 "p%d failed to prepare inline fb %d\n",
2510 plane->base.id, ret);
2511 goto error_prepare_output_buffer;
2512 }
2513 }
2514 }
2515
Alan Kwong4dd64c82017-02-04 18:41:51 -08002516 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002517
2518 return;
2519
2520error_prepare_output_buffer:
2521 msm_framebuffer_cleanup(state->fb, pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002522}
2523
Clarence Ip2606dd62017-10-14 21:11:14 -04002524static bool _sde_plane_halt_requests(struct drm_plane *plane,
2525 uint32_t xin_id, bool halt_forced_clk, bool enable)
2526{
2527 struct sde_plane *psde;
2528 struct msm_drm_private *priv;
2529 struct sde_vbif_set_xin_halt_params halt_params;
2530
2531 if (!plane || !plane->dev) {
2532 SDE_ERROR("invalid arguments\n");
2533 return false;
2534 }
2535
2536 psde = to_sde_plane(plane);
2537 if (!psde->pipe_hw || !psde->pipe_hw->cap) {
2538 SDE_ERROR("invalid pipe reference\n");
2539 return false;
2540 }
2541
2542 priv = plane->dev->dev_private;
2543 if (!priv || !priv->kms) {
2544 SDE_ERROR("invalid KMS reference\n");
2545 return false;
2546 }
2547
2548 memset(&halt_params, 0, sizeof(halt_params));
2549 halt_params.vbif_idx = VBIF_RT;
2550 halt_params.xin_id = xin_id;
2551 halt_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
2552 halt_params.forced_on = halt_forced_clk;
2553 halt_params.enable = enable;
2554
2555 return sde_vbif_set_xin_halt(to_sde_kms(priv->kms), &halt_params);
2556}
2557
2558void sde_plane_halt_requests(struct drm_plane *plane, bool enable)
2559{
2560 struct sde_plane *psde;
2561
2562 if (!plane) {
2563 SDE_ERROR("invalid plane\n");
2564 return;
2565 }
2566
2567 psde = to_sde_plane(plane);
2568 if (!psde->pipe_hw || !psde->pipe_hw->cap) {
2569 SDE_ERROR("invalid pipe reference\n");
2570 return;
2571 }
2572
2573 SDE_EVT32(DRMID(plane), psde->xin_halt_forced_clk, enable);
2574
2575 psde->xin_halt_forced_clk =
2576 _sde_plane_halt_requests(plane, psde->pipe_hw->cap->xin_id,
2577 psde->xin_halt_forced_clk, enable);
2578}
2579
2580int sde_plane_reset_rot(struct drm_plane *plane, struct drm_plane_state *state)
2581{
2582 struct sde_plane *psde;
2583 struct sde_plane_state *pstate;
2584 struct sde_plane_rot_state *rstate;
2585 bool halt_ret[MAX_BLOCKS] = {false};
2586 signed int i, count;
2587
2588 if (!plane || !state) {
2589 SDE_ERROR("invalid plane\n");
2590 return -EINVAL;
2591 }
2592
2593 psde = to_sde_plane(plane);
2594 pstate = to_sde_plane_state(state);
2595 rstate = &pstate->rot;
2596
2597 /* do nothing if not master rotator plane */
2598 if (!rstate->out_sbuf || !rstate->rot_hw ||
2599 !rstate->rot_hw->caps || (rstate->out_xpos != 0))
2600 return 0;
2601
2602 count = (signed int)rstate->rot_hw->caps->xin_count;
2603 if (count > ARRAY_SIZE(halt_ret))
2604 count = ARRAY_SIZE(halt_ret);
2605
2606 SDE_DEBUG_PLANE(psde, "issuing reset for rotator\n");
2607 SDE_EVT32(DRMID(plane), count);
2608
2609 for (i = 0; i < count; i++) {
2610 const struct sde_rot_vbif_cfg *cfg =
2611 &rstate->rot_hw->caps->vbif_cfg[i];
2612
2613 halt_ret[i] = _sde_plane_halt_requests(plane, cfg->xin_id,
2614 false, true);
2615 }
2616
2617 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_RESET);
2618
2619 for (i = count - 1; i >= 0; --i) {
2620 const struct sde_rot_vbif_cfg *cfg =
2621 &rstate->rot_hw->caps->vbif_cfg[i];
2622
2623 _sde_plane_halt_requests(plane, cfg->xin_id,
2624 halt_ret[i], false);
2625 }
2626 return 0;
2627}
2628
Clarence Ip8ee49952017-09-20 11:10:50 -04002629int sde_plane_kickoff_rot(struct drm_plane *plane)
Clarence Ipddbf7752017-05-21 18:07:30 -04002630{
Clarence Ipeb39cce2017-07-19 14:12:43 -04002631 struct sde_plane_state *pstate;
2632
2633 if (!plane || !plane->state) {
2634 SDE_ERROR("invalid plane\n");
Clarence Ip8ee49952017-09-20 11:10:50 -04002635 return -EINVAL;
Clarence Ipeb39cce2017-07-19 14:12:43 -04002636 }
2637
2638 pstate = to_sde_plane_state(plane->state);
2639
2640 if (!pstate->rot.rot_hw || !pstate->rot.rot_hw->ops.commit)
Clarence Ip8ee49952017-09-20 11:10:50 -04002641 return 0;
Clarence Ipddbf7752017-05-21 18:07:30 -04002642
Clarence Ip8ee49952017-09-20 11:10:50 -04002643 return pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
Clarence Ipddbf7752017-05-21 18:07:30 -04002644 &pstate->rot.rot_cmd,
2645 SDE_HW_ROT_CMD_START);
2646}
2647
2648/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002649 * sde_plane_rot_destroy_state - destroy state for rotator stage
2650 * @plane: Pointer to drm plane
2651 * @state: Pointer to state to be destroyed
2652 * return: none
2653 */
2654static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2655 struct drm_plane_state *state)
2656{
2657 struct sde_plane_state *pstate = to_sde_plane_state(state);
2658 struct sde_plane_rot_state *rstate = &pstate->rot;
2659
2660 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2661 rstate->sequence_id,
2662 !!rstate->out_sbuf, !!rstate->rot_hw,
2663 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002664}
2665
2666/**
2667 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2668 * @plane: Pointer to drm plane
2669 * @new_state: Pointer to duplicated state
2670 * return: 0 if success; error code otherwise
2671 */
2672static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2673 struct drm_plane_state *new_state)
2674{
2675 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2676 struct sde_plane_rot_state *rstate = &pstate->rot;
2677
2678 rstate->sequence_id++;
2679
2680 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2681 rstate->sequence_id,
2682 !!rstate->out_sbuf, !!rstate->rot_hw);
2683
Clarence Ipf27c6f22017-07-10 18:19:44 -04002684 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002685 rstate->out_fb = NULL;
2686 rstate->out_fbo = NULL;
2687
2688 return 0;
2689}
2690
2691/**
2692 * sde_plane_rot_install_caps - install plane rotator capabilities
2693 * @plane: Pointer to drm plane
2694 * return: none
2695 */
2696static void sde_plane_rot_install_caps(struct drm_plane *plane)
2697{
2698 struct sde_plane *psde = to_sde_plane(plane);
2699 const struct sde_format_extended *format_list;
2700 struct sde_kms_info *info;
2701 struct sde_hw_rot *rot_hw;
2702 const char *downscale_caps;
2703
2704 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2705 !psde->catalog->rot_count)
2706 return;
2707
2708 if (psde->blob_rot_caps)
2709 return;
2710
2711 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2712 if (!info)
2713 return;
2714
2715 rot_hw = sde_hw_rot_get(NULL);
2716 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2717 !rot_hw->ops.get_downscale_caps) {
2718 SDE_ERROR("invalid rotator hw\n");
2719 goto error_rot;
2720 }
2721
2722 sde_kms_info_reset(info);
2723
2724 format_list = rot_hw->ops.get_format_caps(rot_hw);
2725 if (format_list) {
2726 sde_kms_info_start(info, "pixel_formats");
2727 while (format_list->fourcc_format) {
2728 sde_kms_info_append_format(info,
2729 format_list->fourcc_format,
2730 format_list->modifier);
2731 ++format_list;
2732 }
2733 sde_kms_info_stop(info);
2734 }
2735
2736 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2737 if (downscale_caps) {
2738 sde_kms_info_start(info, "downscale_ratios");
2739 sde_kms_info_append(info, downscale_caps);
2740 sde_kms_info_stop(info);
2741 }
2742
2743 if (rot_hw->ops.get_cache_size)
2744 sde_kms_info_add_keyint(info, "cache_size",
2745 rot_hw->ops.get_cache_size(rot_hw));
2746
Alan Kwong1a915802017-03-31 12:55:46 -07002747 if (rot_hw->ops.get_maxlinewidth)
2748 sde_kms_info_add_keyint(info, "max_linewidth",
2749 rot_hw->ops.get_maxlinewidth(rot_hw));
2750
Alan Kwong4dd64c82017-02-04 18:41:51 -08002751 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
Narendra Muppalla22d17252017-05-31 15:13:39 -07002752 info->data, SDE_KMS_INFO_DATALEN(info),
2753 PLANE_PROP_ROT_CAPS_V1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002754
2755 sde_hw_rot_put(rot_hw);
2756error_rot:
2757 kfree(info);
2758}
2759
2760/**
2761 * sde_plane_rot_install_properties - install plane rotator properties
2762 * @plane: Pointer to drm plane
2763 * @catalog: Pointer to mdss configuration
2764 * return: none
2765 */
2766static void sde_plane_rot_install_properties(struct drm_plane *plane,
2767 struct sde_mdss_cfg *catalog)
2768{
2769 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002770 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2771 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002772
2773 if (!plane || !psde) {
2774 SDE_ERROR("invalid plane\n");
2775 return;
2776 } else if (!catalog) {
2777 SDE_ERROR("invalid catalog\n");
2778 return;
2779 }
2780
2781 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2782 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2783 DRM_ROTATE_180 | DRM_ROTATE_270;
2784
2785 msm_property_install_rotation(&psde->property_info,
2786 supported_rotations, PLANE_PROP_ROTATION);
2787
2788 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2789 return;
2790
2791 msm_property_install_range(&psde->property_info, "rot_dst_x",
2792 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2793 msm_property_install_range(&psde->property_info, "rot_dst_y",
2794 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2795 msm_property_install_range(&psde->property_info, "rot_dst_w",
2796 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2797 msm_property_install_range(&psde->property_info, "rot_dst_h",
2798 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2799 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2800 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2801}
2802
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002803void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002804{
Clarence Ipcb410d42016-06-26 22:52:33 -04002805 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002806
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002807 if (!drm_state)
2808 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002809
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002810 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002811
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002812 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2813 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002814}
2815
Steve Cohen13924772017-08-10 19:10:55 -04002816/**
2817 * multi_rect validate API allows to validate only R0 and R1 RECT
2818 * passing for each plane. Client of this API must not pass multiple
2819 * plane which are not sharing same XIN client. Such calls will fail
2820 * even though kernel client is passing valid multirect configuration.
2821 */
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002822int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2823{
2824 struct sde_plane_state *pstate[R_MAX];
2825 const struct drm_plane_state *drm_state[R_MAX];
2826 struct sde_rect src[R_MAX], dst[R_MAX];
2827 struct sde_plane *sde_plane[R_MAX];
2828 const struct sde_format *fmt[R_MAX];
Steve Cohen13924772017-08-10 19:10:55 -04002829 int xin_id[R_MAX];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002830 bool q16_data = true;
Steve Cohen13924772017-08-10 19:10:55 -04002831 int i, j, buffer_lines, width_threshold[R_MAX];
Steve Cohenf5d01512017-07-07 18:49:21 -04002832 unsigned int max_tile_height = 1;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002833 bool parallel_fetch_qualified = true;
Steve Cohen13924772017-08-10 19:10:55 -04002834 enum sde_sspp_multirect_mode mode = SDE_SSPP_MULTIRECT_NONE;
2835 const struct msm_format *msm_fmt;
Jeykumar Sankaran7126ad62017-11-30 11:36:37 -08002836 bool const_alpha_enable = true;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002837
2838 for (i = 0; i < R_MAX; i++) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002839 drm_state[i] = i ? plane->r1 : plane->r0;
Steve Cohen13924772017-08-10 19:10:55 -04002840 if (!drm_state[i]) {
2841 SDE_ERROR("drm plane state is NULL\n");
2842 return -EINVAL;
Steve Cohenf5d01512017-07-07 18:49:21 -04002843 }
Steve Cohenf5d01512017-07-07 18:49:21 -04002844
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002845 pstate[i] = to_sde_plane_state(drm_state[i]);
2846 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
Steve Cohen13924772017-08-10 19:10:55 -04002847 xin_id[i] = sde_plane[i]->pipe_hw->cap->xin_id;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002848
Steve Cohen13924772017-08-10 19:10:55 -04002849 for (j = 0; j < i; j++) {
2850 if (xin_id[i] != xin_id[j]) {
2851 SDE_ERROR_PLANE(sde_plane[i],
2852 "invalid multirect validate call base:%d xin_id:%d curr:%d xin:%d\n",
2853 j, xin_id[j], i, xin_id[i]);
2854 return -EINVAL;
2855 }
2856 }
2857
2858 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2859 if (!msm_fmt) {
2860 SDE_ERROR_PLANE(sde_plane[i], "null fb\n");
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002861 return -EINVAL;
2862 }
Steve Cohen13924772017-08-10 19:10:55 -04002863 fmt[i] = to_sde_format(msm_fmt);
2864
2865 if (SDE_FORMAT_IS_UBWC(fmt[i]) &&
2866 (fmt[i]->tile_height > max_tile_height))
2867 max_tile_height = fmt[i]->tile_height;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002868
2869 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2870 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2871 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2872 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2873 drm_state[i]->crtc_h, !q16_data);
2874
2875 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2876 SDE_ERROR_PLANE(sde_plane[i],
2877 "scaling is not supported in multirect mode\n");
2878 return -EINVAL;
2879 }
2880
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002881 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2882 SDE_ERROR_PLANE(sde_plane[i],
2883 "Unsupported format for multirect mode\n");
2884 return -EINVAL;
2885 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002886
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002887 /**
2888 * SSPP PD_MEM is split half - one for each RECT.
2889 * Tiled formats need 5 lines of buffering while fetching
2890 * whereas linear formats need only 2 lines.
2891 * So we cannot support more than half of the supported SSPP
2892 * width for tiled formats.
2893 */
Steve Cohen13924772017-08-10 19:10:55 -04002894 width_threshold[i] = sde_plane[i]->pipe_sblk->maxlinewidth;
2895 if (SDE_FORMAT_IS_UBWC(fmt[i]))
2896 width_threshold[i] /= 2;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002897
Steve Cohen13924772017-08-10 19:10:55 -04002898 if (parallel_fetch_qualified && src[i].w > width_threshold[i])
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002899 parallel_fetch_qualified = false;
2900
Steve Cohen13924772017-08-10 19:10:55 -04002901 if (sde_plane[i]->is_virtual)
2902 mode = sde_plane_get_property(pstate[i],
2903 PLANE_PROP_MULTIRECT_MODE);
Jeykumar Sankaran7126ad62017-11-30 11:36:37 -08002904
2905 if (pstate[i]->const_alpha_en != const_alpha_enable)
2906 const_alpha_enable = false;
2907
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002908 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002909
Steve Cohenf5d01512017-07-07 18:49:21 -04002910 buffer_lines = 2 * max_tile_height;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002911
Steve Cohen13924772017-08-10 19:10:55 -04002912 /**
2913 * fallback to driver mode selection logic if client is using
2914 * multirect plane without setting property.
2915 *
2916 * validate multirect mode configuration based on rectangle
2917 */
2918 switch (mode) {
2919 case SDE_SSPP_MULTIRECT_NONE:
2920 if (parallel_fetch_qualified)
2921 mode = SDE_SSPP_MULTIRECT_PARALLEL;
2922 else if (TIME_MULTIPLEX_RECT(dst[R1], dst[R0], buffer_lines) ||
2923 TIME_MULTIPLEX_RECT(dst[R0], dst[R1], buffer_lines))
2924 mode = SDE_SSPP_MULTIRECT_TIME_MX;
2925 else
2926 SDE_ERROR(
2927 "planes(%d - %d) multirect mode selection fail\n",
2928 drm_state[R0]->plane->base.id,
2929 drm_state[R1]->plane->base.id);
2930 break;
2931
2932 case SDE_SSPP_MULTIRECT_PARALLEL:
2933 if (!parallel_fetch_qualified) {
2934 SDE_ERROR("R0 plane:%d width_threshold:%d src_w:%d\n",
2935 drm_state[R0]->plane->base.id,
2936 width_threshold[R0], src[R0].w);
2937 SDE_ERROR("R1 plane:%d width_threshold:%d src_w:%d\n",
2938 drm_state[R1]->plane->base.id,
2939 width_threshold[R1], src[R1].w);
2940 SDE_ERROR("parallel fetch not qualified\n");
2941 mode = SDE_SSPP_MULTIRECT_NONE;
2942 }
2943 break;
2944
2945 case SDE_SSPP_MULTIRECT_TIME_MX:
2946 if (!TIME_MULTIPLEX_RECT(dst[R1], dst[R0], buffer_lines) &&
2947 !TIME_MULTIPLEX_RECT(dst[R0], dst[R1], buffer_lines)) {
2948 SDE_ERROR(
2949 "buffer_lines:%d R0 plane:%d dst_y:%d dst_h:%d\n",
2950 buffer_lines, drm_state[R0]->plane->base.id,
2951 dst[R0].y, dst[R0].h);
2952 SDE_ERROR(
2953 "buffer_lines:%d R1 plane:%d dst_y:%d dst_h:%d\n",
2954 buffer_lines, drm_state[R1]->plane->base.id,
2955 dst[R1].y, dst[R1].h);
2956 SDE_ERROR("time multiplexed fetch not qualified\n");
2957 mode = SDE_SSPP_MULTIRECT_NONE;
2958 }
2959 break;
2960
2961 default:
2962 SDE_ERROR("bad mode:%d selection\n", mode);
2963 mode = SDE_SSPP_MULTIRECT_NONE;
2964 break;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002965 }
2966
Jeykumar Sankaran7126ad62017-11-30 11:36:37 -08002967 for (i = 0; i < R_MAX; i++) {
Steve Cohen13924772017-08-10 19:10:55 -04002968 pstate[i]->multirect_mode = mode;
Jeykumar Sankaran7126ad62017-11-30 11:36:37 -08002969 pstate[i]->const_alpha_en = const_alpha_enable;
2970 }
Steve Cohen13924772017-08-10 19:10:55 -04002971
2972 if (mode == SDE_SSPP_MULTIRECT_NONE)
2973 return -EINVAL;
2974
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002975 if (sde_plane[R0]->is_virtual) {
2976 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2977 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2978 } else {
2979 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2980 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2981 };
2982
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002983 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2984 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2985 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2986 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Steve Cohen13924772017-08-10 19:10:55 -04002987
Clarence Ip5e2a9222016-06-26 22:38:24 -04002988 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002989}
2990
Clarence Ipa8a93eb2017-11-24 10:38:24 -05002991int sde_plane_confirm_hw_rsvps(struct drm_plane *plane,
Alan Kwonga15ae762017-12-16 18:03:16 -05002992 const struct drm_plane_state *state,
2993 struct drm_crtc_state *cstate)
Clarence Ipa8a93eb2017-11-24 10:38:24 -05002994{
Clarence Ipa8a93eb2017-11-24 10:38:24 -05002995 struct sde_plane_state *pstate;
2996 struct sde_plane_rot_state *rstate;
2997 struct sde_hw_blk *hw_blk;
2998
Alan Kwonga15ae762017-12-16 18:03:16 -05002999 if (!plane || !state || !cstate) {
3000 SDE_ERROR("invalid parameters\n");
Clarence Ipa8a93eb2017-11-24 10:38:24 -05003001 return -EINVAL;
3002 }
3003
3004 pstate = to_sde_plane_state(state);
3005 rstate = &pstate->rot;
3006
Alan Kwonga15ae762017-12-16 18:03:16 -05003007 if (sde_plane_enabled(state) && rstate->out_sbuf) {
Clarence Ipa8a93eb2017-11-24 10:38:24 -05003008 SDE_DEBUG("plane%d.%d acquire rotator, fb %d\n",
3009 plane->base.id, rstate->sequence_id,
3010 state->fb ? state->fb->base.id : -1);
3011
3012 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
3013 (u64) state->fb);
3014 if (!hw_blk) {
3015 SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
3016 plane->base.id, rstate->sequence_id,
3017 state->fb ? state->fb->base.id : -1);
3018 SDE_EVT32(DRMID(plane), rstate->sequence_id,
3019 state->fb ? state->fb->base.id : -1,
3020 SDE_EVTLOG_ERROR);
3021 return -EINVAL;
3022 }
Alan Kwonga15ae762017-12-16 18:03:16 -05003023
3024 _sde_plane_rot_get_fb(plane, cstate, rstate);
3025
3026 SDE_EVT32(DRMID(plane), rstate->sequence_id,
3027 state->fb ? state->fb->base.id : -1,
3028 rstate->out_fb ? rstate->out_fb->base.id : -1,
3029 hw_blk->id);
Clarence Ipa8a93eb2017-11-24 10:38:24 -05003030 }
Alan Kwonga15ae762017-12-16 18:03:16 -05003031
Clarence Ipa8a93eb2017-11-24 10:38:24 -05003032 return 0;
3033}
3034
Alan Kwong4dd64c82017-02-04 18:41:51 -08003035/**
3036 * sde_plane_get_ctl_flush - get control flush for the given plane
3037 * @plane: Pointer to drm plane structure
3038 * @ctl: Pointer to hardware control driver
Clarence Ip7e5f0002017-05-29 18:46:56 -04003039 * @flush_sspp: Pointer to sspp flush control word
3040 * @flush_rot: Pointer to rotator flush control word
Alan Kwong4dd64c82017-02-04 18:41:51 -08003041 */
3042void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
Clarence Ip7e5f0002017-05-29 18:46:56 -04003043 u32 *flush_sspp, u32 *flush_rot)
Alan Kwong4dd64c82017-02-04 18:41:51 -08003044{
3045 struct sde_plane_state *pstate;
3046 struct sde_plane_rot_state *rstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003047
Clarence Ip7e5f0002017-05-29 18:46:56 -04003048 if (!plane || !flush_sspp) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08003049 SDE_ERROR("invalid parameters\n");
3050 return;
3051 }
3052
3053 pstate = to_sde_plane_state(plane->state);
3054 rstate = &pstate->rot;
3055
Clarence Ip7e5f0002017-05-29 18:46:56 -04003056 *flush_sspp = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
Alan Kwong4dd64c82017-02-04 18:41:51 -08003057
Clarence Ip7e5f0002017-05-29 18:46:56 -04003058 if (!flush_rot)
3059 return;
3060
3061 *flush_rot = 0x0;
Clarence Ipb776b532017-09-12 18:30:06 -04003062 if (rstate && rstate->out_sbuf && rstate->rot_hw &&
Alan Kwong4dd64c82017-02-04 18:41:51 -08003063 ctl->ops.get_bitmask_rot)
Clarence Ip7e5f0002017-05-29 18:46:56 -04003064 ctl->ops.get_bitmask_rot(ctl, flush_rot, rstate->rot_hw->idx);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003065}
3066
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003067static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07003068 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003069{
3070 struct drm_framebuffer *fb = new_state->fb;
3071 struct sde_plane *psde = to_sde_plane(plane);
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003072 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003073 struct sde_plane_rot_state *new_rstate;
Alan Kwong4a5bd782017-06-09 15:20:52 -04003074 struct sde_hw_fmt_layout layout;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003075 struct msm_gem_address_space *aspace;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003076 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003077
3078 if (!new_state->fb)
3079 return 0;
3080
Clarence Ip13a8cf42016-09-29 17:27:47 -04003081 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003082
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003083 ret = _sde_plane_get_aspace(psde, pstate, &aspace);
3084 if (ret) {
3085 SDE_ERROR_PLANE(psde, "Failed to get aspace\n");
3086 return ret;
3087 }
3088
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07003089 /* cache aspace */
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003090 pstate->aspace = aspace;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07003091
3092 /*
3093 * when transitioning from secure to non-secure,
3094 * plane->prepare_fb happens before the commit. In such case,
3095 * defer the prepare_fb and handled it late, during the commit
3096 * after attaching the domains as part of the transition
3097 */
3098 pstate->defer_prepare_fb = (aspace && !aspace->domain_attached) ?
3099 true : false;
3100
Alan Kwong4dd64c82017-02-04 18:41:51 -08003101 ret = sde_plane_rot_prepare_fb(plane, new_state);
3102 if (ret) {
3103 SDE_ERROR("failed to prepare rot framebuffer\n");
3104 return ret;
3105 }
3106
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07003107 if (pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07003108 SDE_EVT32(DRMID(plane), psde->pipe);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07003109 SDE_DEBUG_PLANE(psde,
3110 "domain not attached, prepare_fb handled later\n");
3111 return 0;
3112 }
3113
Alan Kwong4dd64c82017-02-04 18:41:51 -08003114 new_rstate = &to_sde_plane_state(new_state)->rot;
3115
Abhijit Kulkarni1b3340c2017-06-22 12:39:37 -07003116 if (pstate->aspace) {
3117 ret = msm_framebuffer_prepare(new_rstate->out_fb,
3118 pstate->aspace);
3119 if (ret) {
3120 SDE_ERROR("failed to prepare framebuffer\n");
3121 return ret;
3122 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08003123 }
3124
Alan Kwong4a5bd782017-06-09 15:20:52 -04003125 /* validate framebuffer layout before commit */
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003126 ret = sde_format_populate_layout(pstate->aspace,
Alan Kwong4a5bd782017-06-09 15:20:52 -04003127 new_rstate->out_fb, &layout);
3128 if (ret) {
3129 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
3130 return ret;
3131 }
3132
Alan Kwong4dd64c82017-02-04 18:41:51 -08003133 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003134}
3135
Harsh Sahuea808372017-09-12 22:41:01 -07003136/**
3137 * _sde_plane_fetch_halt - halts vbif transactions for a plane
3138 * @plane: Pointer to plane
3139 * Returns: 0 on success
3140 */
3141static int _sde_plane_fetch_halt(struct drm_plane *plane)
3142{
3143 struct sde_plane *psde;
3144 int xin_id;
3145 enum sde_clk_ctrl_type clk_ctrl;
3146 struct msm_drm_private *priv;
3147 struct sde_kms *sde_kms;
3148
3149 psde = to_sde_plane(plane);
3150 if (!plane || !plane->dev || !psde->pipe_hw) {
3151 SDE_ERROR("invalid arguments\n");
3152 return -EINVAL;
3153 }
3154
3155 priv = plane->dev->dev_private;
3156 if (!priv || !priv->kms) {
3157 SDE_ERROR("invalid KMS reference\n");
3158 return -EINVAL;
3159 }
3160
3161 sde_kms = to_sde_kms(priv->kms);
3162 clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
3163 xin_id = psde->pipe_hw->cap->xin_id;
3164 SDE_DEBUG_PLANE(psde, "pipe:%d xin_id:%d clk_ctrl:%d\n",
3165 psde->pipe - SSPP_VIG0, xin_id, clk_ctrl);
3166 SDE_EVT32_VERBOSE(psde, psde->pipe - SSPP_VIG0, xin_id, clk_ctrl);
3167
3168 return sde_vbif_halt_plane_xin(sde_kms, xin_id, clk_ctrl);
3169}
3170
Harsh Sahu72d3f192017-12-04 23:49:12 -08003171
3172static inline int _sde_plane_power_enable(struct drm_plane *plane, bool enable)
3173{
3174 struct msm_drm_private *priv;
3175 struct sde_kms *sde_kms;
3176
3177 if (!plane->dev || !plane->dev->dev_private) {
3178 SDE_ERROR("invalid drm device\n");
3179 return -EINVAL;
3180 }
3181
3182 priv = plane->dev->dev_private;
3183 if (!priv->kms) {
3184 SDE_ERROR("invalid kms\n");
3185 return -EINVAL;
3186 }
3187
3188 sde_kms = to_sde_kms(priv->kms);
3189
3190 return sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
3191 enable);
3192}
3193
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003194static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07003195 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003196{
Alan Kwong4dd64c82017-02-04 18:41:51 -08003197 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ip299fa602017-07-11 18:01:37 -04003198 struct sde_plane_state *old_pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003199 struct sde_plane_rot_state *old_rstate;
Harsh Sahuea808372017-09-12 22:41:01 -07003200 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003201
Harsh Sahuea808372017-09-12 22:41:01 -07003202 if (!old_state || !old_state->fb || !plane || !plane->state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003203 return;
3204
Clarence Ip299fa602017-07-11 18:01:37 -04003205 old_pstate = to_sde_plane_state(old_state);
3206
Alan Kwong4dd64c82017-02-04 18:41:51 -08003207 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
3208
Harsh Sahuea808372017-09-12 22:41:01 -07003209 /*
3210 * plane->state gets populated for next frame after swap_state. If
3211 * plane->state->crtc pointer is not populated then it is not used in
3212 * the next frame, hence making it an unused plane.
3213 */
3214 if ((plane->state->crtc == NULL) && !psde->is_virtual) {
3215 SDE_DEBUG_PLANE(psde, "unused pipe:%u\n",
3216 psde->pipe - SSPP_VIG0);
3217
3218 /* halt this plane now */
Harsh Sahu72d3f192017-12-04 23:49:12 -08003219 ret = _sde_plane_power_enable(plane, true);
3220 if (ret) {
3221 SDE_ERROR("power resource enable failed with %d", ret);
3222 SDE_EVT32(ret);
3223 return;
3224 }
3225
Harsh Sahuea808372017-09-12 22:41:01 -07003226 ret = _sde_plane_fetch_halt(plane);
3227 if (ret) {
3228 SDE_ERROR_PLANE(psde,
3229 "unused pipe %u halt failed\n",
3230 psde->pipe - SSPP_VIG0);
3231 SDE_EVT32(DRMID(plane), psde->pipe - SSPP_VIG0,
3232 ret, SDE_EVTLOG_ERROR);
3233 }
Harsh Sahu72d3f192017-12-04 23:49:12 -08003234 _sde_plane_power_enable(plane, false);
Harsh Sahuea808372017-09-12 22:41:01 -07003235 }
3236
Clarence Ip299fa602017-07-11 18:01:37 -04003237 old_rstate = &old_pstate->rot;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003238
Clarence Ip299fa602017-07-11 18:01:37 -04003239 msm_framebuffer_cleanup(old_rstate->out_fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003240
3241 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003242}
3243
Alan Kwong4dd64c82017-02-04 18:41:51 -08003244static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003245 struct drm_plane_state *state,
3246 struct drm_plane_state *old_state)
3247{
3248 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003249 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003250 struct sde_plane_rot_state *rstate = &pstate->rot;
3251 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
3252 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003253
Dhaval Patel47302cf2016-08-18 15:04:28 -07003254 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04003255 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07003256 return;
3257
Clarence Ip282dad62016-09-27 17:07:35 -04003258 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
3259 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003260 SDE_DEBUG_PLANE(psde,
3261 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003262 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003263 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003264 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003265 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003266 } else if (pstate->multirect_index != old_pstate->multirect_index ||
3267 pstate->multirect_mode != old_pstate->multirect_mode) {
3268 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
3269 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003270 } else if (rstate->out_src_w != old_rstate->out_src_w ||
3271 rstate->out_src_h != old_rstate->out_src_h ||
3272 rstate->out_src_x != old_rstate->out_src_x ||
3273 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003274 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003275 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003276 } else if (state->crtc_w != old_state->crtc_w ||
3277 state->crtc_h != old_state->crtc_h ||
3278 state->crtc_x != old_state->crtc_x ||
3279 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003280 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003281 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003282 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
3283 pstate->excl_rect.h != old_pstate->excl_rect.h ||
3284 pstate->excl_rect.x != old_pstate->excl_rect.x ||
3285 pstate->excl_rect.y != old_pstate->excl_rect.y) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003286 SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003287 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04003288 }
3289
Alan Kwong4dd64c82017-02-04 18:41:51 -08003290 fb = rstate->out_fb;
3291 old_fb = old_rstate->out_fb;
3292
3293 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003294 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Jayant Shekhar990ff502018-01-23 12:16:27 +05303295 } else if ((fb->pixel_format != old_fb->pixel_format) ||
3296 pstate->const_alpha_en != old_pstate->const_alpha_en) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003297 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003298 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003299 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08003300 uint64_t *new_mods = fb->modifier;
3301 uint64_t *old_mods = old_fb->modifier;
3302 uint32_t *new_pitches = fb->pitches;
3303 uint32_t *old_pitches = old_fb->pitches;
3304 uint32_t *new_offset = fb->offsets;
3305 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003306 int i;
3307
Alan Kwong4dd64c82017-02-04 18:41:51 -08003308 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003309 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003310 SDE_DEBUG_PLANE(psde,
3311 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07003312 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04003313 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04003314 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
3315 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003316 break;
3317 }
3318 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08003319 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04003320 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003321 SDE_DEBUG_PLANE(psde,
3322 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07003323 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04003324 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04003325 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04003326 break;
3327 }
3328 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08003329 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003330 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003331 SDE_DEBUG_PLANE(psde,
3332 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07003333 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04003334 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04003335 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
3336 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003337 break;
3338 }
3339 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04003340 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003341}
3342
Clarence Ip059c8c32017-06-06 17:15:54 -04003343static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -04003344 struct sde_plane_state *pstate,
Clarence Ip059c8c32017-06-06 17:15:54 -04003345 const struct sde_format *fmt,
3346 uint32_t img_w, uint32_t img_h,
3347 uint32_t src_w, uint32_t src_h,
3348 uint32_t deci_w, uint32_t deci_h)
3349{
3350 int i;
3351
Clarence Ip172033f2017-06-13 10:52:56 -04003352 if (!psde || !pstate || !fmt) {
Clarence Ip059c8c32017-06-06 17:15:54 -04003353 SDE_ERROR_PLANE(psde, "invalid arguments\n");
3354 return -EINVAL;
3355 }
3356
Dhaval Patel9c6acc12017-10-17 10:54:32 -07003357 if (psde->debugfs_default_scale ||
3358 (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2 &&
3359 pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK))
Clarence Ip059c8c32017-06-06 17:15:54 -04003360 return 0;
3361
Clarence Ip172033f2017-06-13 10:52:56 -04003362 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
Clarence Ip059c8c32017-06-06 17:15:54 -04003363
3364 for (i = 0; i < SDE_MAX_PLANES; i++) {
3365 uint32_t hor_req_pixels, hor_fetch_pixels;
3366 uint32_t vert_req_pixels, vert_fetch_pixels;
3367 uint32_t src_w_tmp, src_h_tmp;
3368
3369 /* re-use color plane 1's config for plane 2 */
3370 if (i == 2)
3371 continue;
3372
3373 src_w_tmp = src_w;
3374 src_h_tmp = src_h;
3375
3376 /*
3377 * For chroma plane, width is half for the following sub sampled
3378 * formats. Except in case of decimation, where hardware avoids
3379 * 1 line of decimation instead of downsampling.
3380 */
3381 if (i == 1) {
3382 if (!deci_w &&
3383 (fmt->chroma_sample == SDE_CHROMA_420 ||
3384 fmt->chroma_sample == SDE_CHROMA_H2V1))
3385 src_w_tmp >>= 1;
3386 if (!deci_h &&
3387 (fmt->chroma_sample == SDE_CHROMA_420 ||
3388 fmt->chroma_sample == SDE_CHROMA_H1V2))
3389 src_h_tmp >>= 1;
3390 }
3391
Clarence Ip172033f2017-06-13 10:52:56 -04003392 hor_req_pixels = pstate->pixel_ext.roi_w[i];
3393 vert_req_pixels = pstate->pixel_ext.roi_h[i];
Clarence Ip059c8c32017-06-06 17:15:54 -04003394
3395 hor_fetch_pixels = DECIMATED_DIMENSION(src_w_tmp +
Clarence Ip172033f2017-06-13 10:52:56 -04003396 (int8_t)(pstate->pixel_ext.left_ftch[i] & 0xFF) +
3397 (int8_t)(pstate->pixel_ext.right_ftch[i] & 0xFF),
3398 deci_w);
Clarence Ip059c8c32017-06-06 17:15:54 -04003399 vert_fetch_pixels = DECIMATED_DIMENSION(src_h_tmp +
Clarence Ip172033f2017-06-13 10:52:56 -04003400 (int8_t)(pstate->pixel_ext.top_ftch[i] & 0xFF) +
3401 (int8_t)(pstate->pixel_ext.btm_ftch[i] & 0xFF),
3402 deci_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04003403
3404 if ((hor_req_pixels != hor_fetch_pixels) ||
3405 (hor_fetch_pixels > img_w) ||
3406 (vert_req_pixels != vert_fetch_pixels) ||
3407 (vert_fetch_pixels > img_h)) {
3408 SDE_ERROR_PLANE(psde,
3409 "req %d/%d, fetch %d/%d, src %dx%d\n",
3410 hor_req_pixels, vert_req_pixels,
3411 hor_fetch_pixels, vert_fetch_pixels,
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003412 img_w, img_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04003413 return -EINVAL;
3414 }
3415
3416 /*
3417 * Alpha plane can only be scaled using bilinear or pixel
3418 * repeat/drop, src_width and src_height are only specified
3419 * for Y and UV plane
3420 */
3421 if (i != 3 &&
Clarence Ip172033f2017-06-13 10:52:56 -04003422 (hor_req_pixels != pstate->scaler3_cfg.src_width[i] ||
3423 vert_req_pixels != pstate->scaler3_cfg.src_height[i])) {
Clarence Ip059c8c32017-06-06 17:15:54 -04003424 SDE_ERROR_PLANE(psde,
3425 "roi[%d] %d/%d, scaler src %dx%d, src %dx%d\n",
Clarence Ip172033f2017-06-13 10:52:56 -04003426 i, pstate->pixel_ext.roi_w[i],
3427 pstate->pixel_ext.roi_h[i],
3428 pstate->scaler3_cfg.src_width[i],
3429 pstate->scaler3_cfg.src_height[i],
Clarence Ip059c8c32017-06-06 17:15:54 -04003430 src_w, src_h);
3431 return -EINVAL;
3432 }
3433 }
3434
Clarence Ip172033f2017-06-13 10:52:56 -04003435 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
Clarence Ip059c8c32017-06-06 17:15:54 -04003436 return 0;
3437}
3438
Alan Kwong4dd64c82017-02-04 18:41:51 -08003439static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003440 struct drm_plane_state *state)
3441{
Clarence Ipdedbba92016-09-27 17:43:10 -04003442 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04003443 struct sde_plane *psde;
3444 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003445 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04003446 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003447 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04003448 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003449 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
3450 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04003451
3452 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003453 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3454 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04003455 ret = -EINVAL;
3456 goto exit;
3457 }
3458
3459 psde = to_sde_plane(plane);
3460 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003461 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04003462
3463 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003464 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003465 ret = -EINVAL;
3466 goto exit;
3467 }
3468
Clarence Ipdedbba92016-09-27 17:43:10 -04003469 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
3470 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04003471
3472 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08003473 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3474 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07003475 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
3476 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04003477
Dhaval Patel47302cf2016-08-18 15:04:28 -07003478 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
3479 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04003480
Dhaval Patel47302cf2016-08-18 15:04:28 -07003481 max_upscale = psde->pipe_sblk->maxupscale;
3482 max_downscale = psde->pipe_sblk->maxdwnscale;
3483 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04003484
Clarence Ip13a8cf42016-09-29 17:27:47 -04003485 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003486 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003487
Dhaval Patel47302cf2016-08-18 15:04:28 -07003488 if (!sde_plane_enabled(state))
3489 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04003490
Alan Kwong4dd64c82017-02-04 18:41:51 -08003491 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07003492 "plane%d.%u sspp:%x/%dx%d/%4.4s/%llx/%dx%d+%d+%d crtc:%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08003493 plane->base.id, rstate->sequence_id,
3494 rstate->out_rotation,
3495 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07003496 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08003497 rstate->out_fb_modifier[0],
3498 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3499 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3500 state->crtc_w, state->crtc_h,
3501 state->crtc_x, state->crtc_y);
3502
Dhaval Patel47302cf2016-08-18 15:04:28 -07003503 fmt = to_sde_format(msm_framebuffer_format(state->fb));
3504
3505 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
3506
3507 if (SDE_FORMAT_IS_YUV(fmt) &&
3508 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04003509 !(psde->features & (BIT(SDE_SSPP_CSC)
3510 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003511 SDE_ERROR_PLANE(psde,
3512 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07003513 ret = -EINVAL;
3514
3515 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08003516 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
3517 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07003518 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08003519 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
3520 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003521 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003522 src.x, src.y, src.w, src.h);
3523 ret = -E2BIG;
3524
3525 /* valid yuv image */
3526 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
3527 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003528 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003529 src.x, src.y, src.w, src.h);
3530 ret = -EINVAL;
3531
3532 /* min dst support */
3533 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003534 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003535 dst.x, dst.y, dst.w, dst.h);
3536 ret = -EINVAL;
3537
3538 /* decimation validation */
3539 } else if (deci_w || deci_h) {
3540 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
3541 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003542 SDE_ERROR_PLANE(psde,
3543 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003544 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003545 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003546 SDE_ERROR_PLANE(psde,
3547 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003548 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003549 }
3550
Dhaval Patel47302cf2016-08-18 15:04:28 -07003551 } else if (!(psde->features & SDE_SSPP_SCALER) &&
3552 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003553 SDE_ERROR_PLANE(psde,
3554 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003555 src.w, src.h, dst.w, dst.h);
3556 ret = -EINVAL;
3557
3558 /* check decimated source width */
3559 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003560 SDE_ERROR_PLANE(psde,
3561 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003562 src.w, src_deci_w, max_linewidth);
3563 ret = -E2BIG;
3564
3565 /* check max scaler capability */
3566 } else if (((src_deci_w * max_upscale) < dst.w) ||
3567 ((src_deci_h * max_upscale) < dst.h) ||
3568 ((dst.w * max_downscale) < src_deci_w) ||
3569 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003570 SDE_ERROR_PLANE(psde,
3571 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003572 src_deci_w, src_deci_h, dst.w, dst.h);
3573 ret = -E2BIG;
Clarence Ip172033f2017-06-13 10:52:56 -04003574 } else if (_sde_plane_validate_scaler_v2(psde, pstate, fmt,
Clarence Ip059c8c32017-06-06 17:15:54 -04003575 rstate->out_fb_width,
3576 rstate->out_fb_height,
3577 src.w, src.h, deci_w, deci_h)) {
3578 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003579 }
3580
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003581 /* check excl rect configs */
Clarence Ip059c8c32017-06-06 17:15:54 -04003582 if (!ret && pstate->excl_rect.w && pstate->excl_rect.h) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003583 struct sde_rect intersect;
3584
3585 /*
3586 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003587 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003588 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05003589 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003590 if (intersect.w != pstate->excl_rect.w ||
3591 intersect.h != pstate->excl_rect.h ||
3592 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003593 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07003594 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003595 pstate->excl_rect.x, pstate->excl_rect.y,
3596 pstate->excl_rect.w, pstate->excl_rect.h,
3597 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07003598 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003599 ret = -EINVAL;
3600 }
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003601 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3602 pstate->excl_rect.x, pstate->excl_rect.y,
3603 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003604 }
3605
Jeykumar Sankaran7126ad62017-11-30 11:36:37 -08003606 pstate->const_alpha_en = fmt->alpha_enable &&
3607 (SDE_DRM_BLEND_OP_OPAQUE !=
Dhaval Patel5c4f6bf2018-01-29 09:49:00 -08003608 sde_plane_get_property(pstate, PLANE_PROP_BLEND_OP)) &&
3609 (pstate->stage != SDE_STAGE_0);
Jeykumar Sankaran7126ad62017-11-30 11:36:37 -08003610
Dhaval Patel47302cf2016-08-18 15:04:28 -07003611modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003612 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08003613 _sde_plane_sspp_atomic_check_mode_changed(psde,
3614 state, plane->state);
3615exit:
3616 return ret;
3617}
3618
3619static int sde_plane_atomic_check(struct drm_plane *plane,
3620 struct drm_plane_state *state)
3621{
3622 int ret = 0;
3623 struct sde_plane *psde;
3624 struct sde_plane_state *pstate;
3625
3626 if (!plane || !state) {
3627 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3628 plane != 0, state != 0);
3629 ret = -EINVAL;
3630 goto exit;
3631 }
3632
3633 psde = to_sde_plane(plane);
3634 pstate = to_sde_plane_state(state);
3635
3636 SDE_DEBUG_PLANE(psde, "\n");
3637
3638 ret = sde_plane_rot_atomic_check(plane, state);
3639 if (ret)
3640 goto exit;
3641
3642 ret = sde_plane_sspp_atomic_check(plane, state);
3643
Clarence Ipdbde9832016-06-26 09:48:36 -04003644exit:
3645 return ret;
3646}
3647
Clarence Ipcae1bb62016-07-07 12:07:13 -04003648void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04003649{
Clarence Ipcae1bb62016-07-07 12:07:13 -04003650 struct sde_plane *psde;
Clarence Ipddbf7752017-05-21 18:07:30 -04003651 struct sde_plane_state *pstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -04003652
Clarence Ipddbf7752017-05-21 18:07:30 -04003653 if (!plane || !plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003654 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04003655 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003656 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04003657
3658 psde = to_sde_plane(plane);
Clarence Ipddbf7752017-05-21 18:07:30 -04003659 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003660
3661 /*
3662 * These updates have to be done immediately before the plane flush
3663 * timing, and may not be moved to the atomic_update/mode_set functions.
3664 */
3665 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05003666 /* force white frame with 100% alpha pipe output on error */
3667 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003668 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
3669 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04003670 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003671 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
3672 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
3673
3674 /* flag h/w flush complete */
3675 if (plane->state)
Clarence Ipddbf7752017-05-21 18:07:30 -04003676 pstate->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003677}
3678
Abhijit Kulkarni1b3340c2017-06-22 12:39:37 -07003679/**
3680 * sde_plane_set_error: enable/disable error condition
3681 * @plane: pointer to drm_plane structure
3682 */
3683void sde_plane_set_error(struct drm_plane *plane, bool error)
3684{
3685 struct sde_plane *psde;
3686
3687 if (!plane)
3688 return;
3689
3690 psde = to_sde_plane(plane);
3691 psde->is_error = error;
3692}
3693
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003694static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
3695 struct drm_plane_state *old_state)
3696{
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003697 uint32_t nplanes, src_flags;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003698 struct sde_plane *psde;
3699 struct drm_plane_state *state;
3700 struct sde_plane_state *pstate;
3701 struct sde_plane_state *old_pstate;
3702 struct sde_plane_rot_state *rstate;
3703 const struct sde_format *fmt;
3704 struct drm_crtc *crtc;
3705 struct drm_framebuffer *fb;
3706 struct sde_rect src, dst;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003707 bool q16_data = true;
3708 int idx;
3709
3710 if (!plane) {
3711 SDE_ERROR("invalid plane\n");
3712 return -EINVAL;
3713 } else if (!plane->state) {
3714 SDE_ERROR("invalid plane state\n");
3715 return -EINVAL;
3716 } else if (!old_state) {
3717 SDE_ERROR("invalid old state\n");
3718 return -EINVAL;
3719 }
3720
3721 psde = to_sde_plane(plane);
3722 state = plane->state;
3723
3724 pstate = to_sde_plane_state(state);
3725 rstate = &pstate->rot;
3726
3727 old_pstate = to_sde_plane_state(old_state);
3728
3729 crtc = state->crtc;
3730 fb = rstate->out_fb;
3731 if (!crtc || !fb) {
3732 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
3733 crtc != 0, fb != 0);
3734 return -EINVAL;
3735 }
3736 fmt = to_sde_format(msm_framebuffer_format(fb));
3737 nplanes = fmt->num_planes;
3738
3739 SDE_DEBUG(
3740 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
3741 plane->base.id, rstate->sequence_id,
3742 rstate->out_fb_width, rstate->out_fb_height,
3743 (char *) &rstate->out_fb_pixel_format,
3744 rstate->out_fb_modifier[0],
3745 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3746 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3747 rstate->out_rotation,
3748 state->crtc_w, state->crtc_h,
3749 state->crtc_x, state->crtc_y);
3750
3751 /* force reprogramming of all the parameters, if the flag is set */
3752 if (psde->revalidate) {
3753 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
3754 plane->base.id);
3755 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3756 psde->revalidate = false;
3757 }
3758
3759 /* determine what needs to be refreshed */
Clarence Ip4a2955d2017-07-04 18:04:33 -04003760 while ((idx = msm_property_pop_dirty(&psde->property_info,
3761 &pstate->property_state)) >= 0) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003762 switch (idx) {
3763 case PLANE_PROP_SCALER_V1:
3764 case PLANE_PROP_SCALER_V2:
Clarence Ip059c8c32017-06-06 17:15:54 -04003765 case PLANE_PROP_SCALER_LUT_ED:
3766 case PLANE_PROP_SCALER_LUT_CIR:
3767 case PLANE_PROP_SCALER_LUT_SEP:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003768 case PLANE_PROP_H_DECIMATE:
3769 case PLANE_PROP_V_DECIMATE:
3770 case PLANE_PROP_SRC_CONFIG:
3771 case PLANE_PROP_ZPOS:
3772 case PLANE_PROP_EXCL_RECT_V1:
3773 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3774 break;
3775 case PLANE_PROP_CSC_V1:
3776 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3777 break;
Steve Cohen13924772017-08-10 19:10:55 -04003778 case PLANE_PROP_MULTIRECT_MODE:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003779 case PLANE_PROP_COLOR_FILL:
3780 /* potentially need to refresh everything */
3781 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3782 break;
3783 case PLANE_PROP_ROTATION:
3784 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3785 break;
3786 case PLANE_PROP_INFO:
3787 case PLANE_PROP_ALPHA:
3788 case PLANE_PROP_INPUT_FENCE:
3789 case PLANE_PROP_BLEND_OP:
3790 /* no special action required */
3791 break;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003792 case PLANE_PROP_FB_TRANSLATION_MODE:
3793 pstate->dirty |= SDE_PLANE_DIRTY_FB_TRANSLATION_MODE;
3794 break;
Alan Kwong2349d742017-04-20 08:27:30 -07003795 case PLANE_PROP_PREFILL_SIZE:
3796 case PLANE_PROP_PREFILL_TIME:
3797 pstate->dirty |= SDE_PLANE_DIRTY_PERF;
3798 break;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003799 case PLANE_PROP_ROT_DST_X:
3800 case PLANE_PROP_ROT_DST_Y:
3801 case PLANE_PROP_ROT_DST_W:
3802 case PLANE_PROP_ROT_DST_H:
3803 /* handled by rotator atomic update */
3804 break;
3805 default:
3806 /* unknown property, refresh everything */
3807 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
3808 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
3809 break;
3810 }
3811 }
3812
3813 /**
3814 * since plane_atomic_check is invoked before crtc_atomic_check
3815 * in the commit sequence, all the parameters for updating the
3816 * plane dirty flag will not be available during
3817 * plane_atomic_check as some features params are updated
3818 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
3819 * before sspp update.
3820 */
3821 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
3822 old_state);
3823
Lloyd Atkinsonb0e0c2b2017-11-21 09:20:35 -05003824 /* re-program the output rects always if partial update roi changed */
3825 if (sde_crtc_is_crtc_roi_dirty(crtc->state))
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003826 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3827
3828 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
3829 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
3830
3831 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
3832
3833 /* early out if nothing dirty */
3834 if (!pstate->dirty)
3835 return 0;
3836 pstate->pending = true;
3837
3838 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
3839 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3840
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003841 /* update secure session flag */
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003842 if (pstate->dirty & SDE_PLANE_DIRTY_FB_TRANSLATION_MODE) {
3843 bool enable = false;
3844 int mode = sde_plane_get_property(pstate,
3845 PLANE_PROP_FB_TRANSLATION_MODE);
3846
3847 if ((mode == SDE_DRM_FB_SEC) ||
3848 (mode == SDE_DRM_FB_SEC_DIR_TRANS))
3849 enable = true;
3850 /* update secure session flag */
3851 psde->pipe_hw->ops.setup_secure_address(psde->pipe_hw,
3852 pstate->multirect_index,
3853 enable);
3854 }
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003855
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003856 /* update roi config */
3857 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
Lloyd Atkinsonb0e0c2b2017-11-21 09:20:35 -05003858 const struct sde_rect *crtc_roi;
3859
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003860 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3861 rstate->out_src_w, rstate->out_src_h, q16_data);
3862 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
3863 state->crtc_w, state->crtc_h, !q16_data);
3864
3865 SDE_DEBUG_PLANE(psde,
3866 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
3867 fb->base.id, src.x, src.y, src.w, src.h,
3868 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
3869 (char *)&fmt->base.pixel_format,
3870 SDE_FORMAT_IS_UBWC(fmt));
3871
3872 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
3873 BIT(SDE_DRM_DEINTERLACE)) {
3874 SDE_DEBUG_PLANE(psde, "deinterlace\n");
3875 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
3876 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
3877 src.h /= 2;
3878 src.y = DIV_ROUND_UP(src.y, 2);
3879 src.y &= ~0x1;
3880 }
3881
3882 /*
3883 * adjust layer mixer position of the sspp in the presence
3884 * of a partial update to the active lm origin
3885 */
Lloyd Atkinsonb0e0c2b2017-11-21 09:20:35 -05003886 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003887 dst.x -= crtc_roi->x;
3888 dst.y -= crtc_roi->y;
3889
3890 psde->pipe_cfg.src_rect = src;
3891 psde->pipe_cfg.dst_rect = dst;
3892
Clarence Ip172033f2017-06-13 10:52:56 -04003893 _sde_plane_setup_scaler(psde, pstate, fmt, false);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003894
3895 /* check for color fill */
3896 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
3897 PLANE_PROP_COLOR_FILL);
3898 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
3899 /* skip remaining processing on color fill */
3900 pstate->dirty = 0x0;
3901 } else if (psde->pipe_hw->ops.setup_rects) {
3902 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
3903 &psde->pipe_cfg,
3904 pstate->multirect_index);
3905 }
3906
Jeykumar Sankaran0532e0a2017-06-11 20:34:44 -07003907 if (psde->pipe_hw->ops.setup_pe &&
3908 (pstate->multirect_index != SDE_SSPP_RECT_1))
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003909 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04003910 &pstate->pixel_ext);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003911
3912 /**
3913 * when programmed in multirect mode, scalar block will be
3914 * bypassed. Still we need to update alpha and bitwidth
3915 * ONLY for RECT0
3916 */
3917 if (psde->pipe_hw->ops.setup_scaler &&
3918 pstate->multirect_index != SDE_SSPP_RECT_1)
3919 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04003920 &psde->pipe_cfg, &pstate->pixel_ext,
3921 &pstate->scaler3_cfg);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003922
3923 /* update excl rect */
3924 if (psde->pipe_hw->ops.setup_excl_rect)
3925 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
3926 &pstate->excl_rect,
3927 pstate->multirect_index);
3928
3929 if (psde->pipe_hw->ops.setup_multirect)
3930 psde->pipe_hw->ops.setup_multirect(
3931 psde->pipe_hw,
3932 pstate->multirect_index,
3933 pstate->multirect_mode);
3934 }
3935
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003936 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003937 psde->pipe_hw->ops.setup_format) {
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003938 src_flags = 0x0;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003939 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
3940 if (rstate->out_rotation & DRM_REFLECT_X)
3941 src_flags |= SDE_SSPP_FLIP_LR;
3942 if (rstate->out_rotation & DRM_REFLECT_Y)
3943 src_flags |= SDE_SSPP_FLIP_UD;
3944
3945 /* update format */
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07003946 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt,
Jeykumar Sankaran7126ad62017-11-30 11:36:37 -08003947 pstate->const_alpha_en, src_flags,
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003948 pstate->multirect_index);
3949
Alan Kwong143f50c2017-04-28 07:34:28 -07003950 if (psde->pipe_hw->ops.setup_cdp) {
3951 struct sde_hw_pipe_cdp_cfg *cdp_cfg = &pstate->cdp_cfg;
3952
3953 memset(cdp_cfg, 0, sizeof(struct sde_hw_pipe_cdp_cfg));
3954
3955 cdp_cfg->enable = psde->catalog->perf.cdp_cfg
3956 [SDE_PERF_CDP_USAGE_RT].rd_enable;
3957 cdp_cfg->ubwc_meta_enable =
3958 SDE_FORMAT_IS_UBWC(fmt);
3959 cdp_cfg->tile_amortize_enable =
3960 SDE_FORMAT_IS_UBWC(fmt) ||
3961 SDE_FORMAT_IS_TILE(fmt);
3962 cdp_cfg->preload_ahead = SDE_WB_CDP_PRELOAD_AHEAD_64;
3963
Alan Kwong1b6b4572017-09-25 15:58:14 -04003964 psde->pipe_hw->ops.setup_cdp(psde->pipe_hw, cdp_cfg,
3965 pstate->multirect_index);
Alan Kwong143f50c2017-04-28 07:34:28 -07003966 }
3967
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003968 if (psde->pipe_hw->ops.setup_sys_cache) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04003969 if (rstate->out_sbuf && rstate->rot_hw) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003970 if (rstate->nplane < 2)
3971 pstate->sc_cfg.op_mode =
3972 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
3973 else if (rstate->out_xpos == 0)
3974 pstate->sc_cfg.op_mode =
3975 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
3976 else
3977 pstate->sc_cfg.op_mode =
3978 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
3979
3980 pstate->sc_cfg.rd_en = true;
3981 pstate->sc_cfg.rd_scid =
3982 rstate->rot_hw->caps->scid;
3983 pstate->sc_cfg.rd_noallocate = true;
3984 pstate->sc_cfg.rd_op_type =
3985 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3986 } else {
3987 pstate->sc_cfg.op_mode =
3988 SDE_PIPE_SC_OP_MODE_OFFLINE;
3989 pstate->sc_cfg.rd_en = false;
3990 pstate->sc_cfg.rd_scid = 0;
Clarence Ipd02440b2017-05-21 18:10:01 -04003991 pstate->sc_cfg.rd_noallocate = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003992 pstate->sc_cfg.rd_op_type =
3993 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3994 }
3995
3996 psde->pipe_hw->ops.setup_sys_cache(
3997 psde->pipe_hw, &pstate->sc_cfg);
3998 }
3999
4000 /* update csc */
4001 if (SDE_FORMAT_IS_YUV(fmt))
4002 _sde_plane_setup_csc(psde);
4003 else
4004 psde->csc_ptr = 0;
4005 }
4006
4007 sde_color_process_plane_setup(plane);
4008
4009 /* update sharpening */
4010 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
4011 psde->pipe_hw->ops.setup_sharpening) {
4012 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
4013 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
4014 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
4015 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
4016
4017 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
4018 &psde->sharp_cfg);
4019 }
4020
4021 _sde_plane_set_qos_lut(plane, fb);
4022 _sde_plane_set_danger_lut(plane, fb);
4023
4024 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
4025 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
4026 _sde_plane_set_ot_limit(plane, crtc);
Alan Kwong2349d742017-04-20 08:27:30 -07004027 if (pstate->dirty & SDE_PLANE_DIRTY_PERF)
4028 _sde_plane_set_ts_prefill(plane, pstate);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07004029 }
4030
Alan Kwonga62eeb82017-04-19 08:57:55 -07004031 _sde_plane_set_qos_remap(plane);
4032
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07004033 /* clear dirty */
4034 pstate->dirty = 0x0;
4035
4036 return 0;
4037}
4038
Clarence Ipc652ccf2017-06-28 18:21:18 -04004039static void _sde_plane_atomic_disable(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04004040 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004041{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004042 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04004043 struct drm_plane_state *state;
4044 struct sde_plane_state *pstate;
Clarence Ipc652ccf2017-06-28 18:21:18 -04004045
4046 if (!plane) {
4047 SDE_ERROR("invalid plane\n");
4048 return;
4049 } else if (!plane->state) {
4050 SDE_ERROR("invalid plane state\n");
4051 return;
4052 } else if (!old_state) {
4053 SDE_ERROR("invalid old state\n");
4054 return;
4055 }
4056
4057 psde = to_sde_plane(plane);
4058 state = plane->state;
4059 pstate = to_sde_plane_state(state);
4060
4061 SDE_EVT32(DRMID(plane), is_sde_plane_virtual(plane),
4062 pstate->multirect_mode);
4063
4064 pstate->pending = true;
4065
4066 if (is_sde_plane_virtual(plane) &&
4067 psde->pipe_hw && psde->pipe_hw->ops.setup_multirect)
4068 psde->pipe_hw->ops.setup_multirect(psde->pipe_hw,
4069 SDE_SSPP_RECT_SOLO, SDE_SSPP_MULTIRECT_NONE);
4070}
4071
4072static void sde_plane_atomic_update(struct drm_plane *plane,
4073 struct drm_plane_state *old_state)
4074{
4075 struct sde_plane *psde;
4076 struct drm_plane_state *state;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004077
Clarence Ip13a8cf42016-09-29 17:27:47 -04004078 if (!plane) {
4079 SDE_ERROR("invalid plane\n");
4080 return;
4081 } else if (!plane->state) {
4082 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04004083 return;
4084 }
4085
Clarence Ip13a8cf42016-09-29 17:27:47 -04004086 psde = to_sde_plane(plane);
4087 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04004088 state = plane->state;
Clarence Ip5e2a9222016-06-26 22:38:24 -04004089
Clarence Ip13a8cf42016-09-29 17:27:47 -04004090 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04004091
Alan Kwong4dd64c82017-02-04 18:41:51 -08004092 sde_plane_rot_atomic_update(plane, old_state);
4093
4094 if (!sde_plane_sspp_enabled(state)) {
Clarence Ipc652ccf2017-06-28 18:21:18 -04004095 _sde_plane_atomic_disable(plane, old_state);
Clarence Ip282dad62016-09-27 17:07:35 -04004096 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004097 int ret;
4098
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07004099 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004100 /* atomic_check should have ensured that this doesn't fail */
4101 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004102 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004103}
4104
Alan Kwong346223e2017-06-30 15:29:22 -04004105void sde_plane_restore(struct drm_plane *plane)
4106{
4107 struct sde_plane *psde;
4108
4109 if (!plane || !plane->state) {
4110 SDE_ERROR("invalid plane\n");
4111 return;
4112 }
4113
4114 psde = to_sde_plane(plane);
4115
4116 /*
4117 * Revalidate is only true here if idle PC occurred and
4118 * there is no plane state update in current commit cycle.
4119 */
4120 if (!psde->revalidate)
4121 return;
4122
4123 SDE_DEBUG_PLANE(psde, "\n");
4124
4125 /* last plane state is same as current state */
4126 sde_plane_atomic_update(plane, plane->state);
4127}
Dhaval Patel47302cf2016-08-18 15:04:28 -07004128
Lloyd Atkinsone08229c2017-10-02 17:53:30 -04004129int sde_plane_helper_reset_custom_properties(struct drm_plane *plane,
4130 struct drm_plane_state *plane_state)
4131{
4132 struct sde_plane *psde;
4133 struct sde_plane_state *pstate;
4134 struct drm_property *drm_prop;
4135 enum msm_mdp_plane_property prop_idx;
4136
4137 if (!plane || !plane_state) {
4138 SDE_ERROR("invalid params\n");
4139 return -EINVAL;
4140 }
4141
4142 psde = to_sde_plane(plane);
4143 pstate = to_sde_plane_state(plane_state);
4144
4145 for (prop_idx = 0; prop_idx < PLANE_PROP_COUNT; prop_idx++) {
4146 uint64_t val = pstate->property_values[prop_idx].value;
4147 uint64_t def;
4148 int ret;
4149
4150 drm_prop = msm_property_index_to_drm_property(
4151 &psde->property_info, prop_idx);
4152 if (!drm_prop) {
4153 /* not all props will be installed, based on caps */
4154 SDE_DEBUG_PLANE(psde, "invalid property index %d\n",
4155 prop_idx);
4156 continue;
4157 }
4158
4159 def = msm_property_get_default(&psde->property_info, prop_idx);
4160 if (val == def)
4161 continue;
4162
4163 SDE_DEBUG_PLANE(psde, "set prop %s idx %d from %llu to %llu\n",
4164 drm_prop->name, prop_idx, val, def);
4165
4166 ret = drm_atomic_plane_set_property(plane, plane_state,
4167 drm_prop, def);
4168 if (ret) {
4169 SDE_ERROR_PLANE(psde,
4170 "set property failed, idx %d ret %d\n",
4171 prop_idx, ret);
4172 continue;
4173 }
4174 }
4175
4176 return 0;
4177}
4178
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004179/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07004180static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004181 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004182{
Clarence Ip5e2a9222016-06-26 22:38:24 -04004183 static const struct drm_prop_enum_list e_blend_op[] = {
4184 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
4185 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
4186 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
4187 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
4188 };
4189 static const struct drm_prop_enum_list e_src_config[] = {
4190 {SDE_DRM_DEINTERLACE, "deinterlace"}
4191 };
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07004192 static const struct drm_prop_enum_list e_fb_translation_mode[] = {
4193 {SDE_DRM_FB_NON_SEC, "non_sec"},
4194 {SDE_DRM_FB_SEC, "sec"},
4195 {SDE_DRM_FB_NON_SEC_DIR_TRANS, "non_sec_direct_translation"},
4196 {SDE_DRM_FB_SEC_DIR_TRANS, "sec_direct_translation"},
4197 };
Steve Cohen13924772017-08-10 19:10:55 -04004198 static const struct drm_prop_enum_list e_multirect_mode[] = {
4199 {SDE_SSPP_MULTIRECT_NONE, "none"},
4200 {SDE_SSPP_MULTIRECT_PARALLEL, "parallel"},
4201 {SDE_SSPP_MULTIRECT_TIME_MX, "serial"},
4202 };
Clarence Ipea3d6262016-07-15 16:20:11 -04004203 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07004204 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04004205 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04004206 int zpos_max = 255;
4207 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07004208 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004209
Clarence Ip13a8cf42016-09-29 17:27:47 -04004210 if (!plane || !psde) {
4211 SDE_ERROR("invalid plane\n");
4212 return;
4213 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
4214 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
4215 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004216 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04004217 } else if (!catalog) {
4218 SDE_ERROR("invalid catalog\n");
4219 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04004220 }
4221
Alan Kwong4dd64c82017-02-04 18:41:51 -08004222 psde->catalog = catalog;
4223
Clarence Ipc47a0692016-10-11 10:54:17 -04004224 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04004225 if (catalog->mixer_count && catalog->mixer &&
4226 catalog->mixer[0].sblk->maxblendstages) {
4227 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
4228 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
4229 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
4230 }
Clarence Ipc47a0692016-10-11 10:54:17 -04004231 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
4232 /* reserve zpos == 0 for primary planes */
4233 zpos_def = drm_plane_index(plane) + 1;
4234 }
4235
4236 msm_property_install_range(&psde->property_info, "zpos",
4237 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004238
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04004239 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07004240 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004241
Dhaval Patel47302cf2016-08-18 15:04:28 -07004242 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04004243 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07004244 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004245
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004246 if (!master_plane_id) {
4247 if (psde->pipe_sblk->maxhdeciexp) {
4248 msm_property_install_range(&psde->property_info,
4249 "h_decimate", 0x0, 0,
4250 psde->pipe_sblk->maxhdeciexp, 0,
4251 PLANE_PROP_H_DECIMATE);
4252 }
Clarence Ipdedbba92016-09-27 17:43:10 -04004253
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004254 if (psde->pipe_sblk->maxvdeciexp) {
4255 msm_property_install_range(&psde->property_info,
4256 "v_decimate", 0x0, 0,
4257 psde->pipe_sblk->maxvdeciexp, 0,
4258 PLANE_PROP_V_DECIMATE);
4259 }
Clarence Ipdedbba92016-09-27 17:43:10 -04004260
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004261 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004262 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004263 &psde->property_info, "scaler_v2",
4264 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
4265 msm_property_install_blob(&psde->property_info,
4266 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
4267 msm_property_install_blob(&psde->property_info,
4268 "lut_cir", 0,
4269 PLANE_PROP_SCALER_LUT_CIR);
4270 msm_property_install_blob(&psde->property_info,
4271 "lut_sep", 0,
4272 PLANE_PROP_SCALER_LUT_SEP);
4273 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004274 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004275 &psde->property_info, "scaler_v1", 0x0,
4276 0, ~0, 0, PLANE_PROP_SCALER_V1);
4277 }
Clarence Ipb43d4592016-09-08 14:21:35 -04004278
Dhaval Patel0aee0972017-02-08 19:00:58 -08004279 if (psde->features & BIT(SDE_SSPP_CSC) ||
4280 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004281 msm_property_install_volatile_range(
4282 &psde->property_info, "csc_v1", 0x0,
4283 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004284
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004285 if (psde->features & BIT(SDE_SSPP_HSIC)) {
4286 snprintf(feature_name, sizeof(feature_name), "%s%d",
4287 "SDE_SSPP_HUE_V",
4288 psde->pipe_sblk->hsic_blk.version >> 16);
4289 msm_property_install_range(&psde->property_info,
4290 feature_name, 0, 0, 0xFFFFFFFF, 0,
4291 PLANE_PROP_HUE_ADJUST);
4292 snprintf(feature_name, sizeof(feature_name), "%s%d",
4293 "SDE_SSPP_SATURATION_V",
4294 psde->pipe_sblk->hsic_blk.version >> 16);
4295 msm_property_install_range(&psde->property_info,
4296 feature_name, 0, 0, 0xFFFFFFFF, 0,
4297 PLANE_PROP_SATURATION_ADJUST);
4298 snprintf(feature_name, sizeof(feature_name), "%s%d",
4299 "SDE_SSPP_VALUE_V",
4300 psde->pipe_sblk->hsic_blk.version >> 16);
4301 msm_property_install_range(&psde->property_info,
4302 feature_name, 0, 0, 0xFFFFFFFF, 0,
4303 PLANE_PROP_VALUE_ADJUST);
4304 snprintf(feature_name, sizeof(feature_name), "%s%d",
4305 "SDE_SSPP_CONTRAST_V",
4306 psde->pipe_sblk->hsic_blk.version >> 16);
4307 msm_property_install_range(&psde->property_info,
4308 feature_name, 0, 0, 0xFFFFFFFF, 0,
4309 PLANE_PROP_CONTRAST_ADJUST);
4310 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07004311 }
4312
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004313 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
4314 msm_property_install_volatile_range(&psde->property_info,
4315 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
4316
Alan Kwong4dd64c82017-02-04 18:41:51 -08004317 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004318
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04004319 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07004320 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004321
Dhaval Patel47302cf2016-08-18 15:04:28 -07004322 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
4323 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
4324
4325 if (psde->pipe_hw->ops.setup_solidfill)
4326 msm_property_install_range(&psde->property_info, "color_fill",
4327 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
4328
Alan Kwong2349d742017-04-20 08:27:30 -07004329 msm_property_install_range(&psde->property_info,
4330 "prefill_size", 0x0, 0, ~0, 0,
4331 PLANE_PROP_PREFILL_SIZE);
4332 msm_property_install_range(&psde->property_info,
4333 "prefill_time", 0x0, 0, ~0, 0,
4334 PLANE_PROP_PREFILL_TIME);
4335
Dhaval Patel4e574842016-08-23 15:11:37 -07004336 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004337 if (!info) {
4338 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07004339 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004340 }
Dhaval Patel4e574842016-08-23 15:11:37 -07004341
4342 msm_property_install_blob(&psde->property_info, "capabilities",
4343 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
4344 sde_kms_info_reset(info);
4345
Steve Cohen57428172017-07-18 10:57:17 -04004346 if (!master_plane_id) {
4347 format_list = psde->pipe_sblk->format_list;
4348 } else {
4349 format_list = psde->pipe_sblk->virt_format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004350 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004351 master_plane_id);
Steve Cohen13924772017-08-10 19:10:55 -04004352 msm_property_install_enum(&psde->property_info,
4353 "multirect_mode", 0x0, 0, e_multirect_mode,
4354 ARRAY_SIZE(e_multirect_mode),
4355 PLANE_PROP_MULTIRECT_MODE);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004356 }
4357
Clarence Ipea3d6262016-07-15 16:20:11 -04004358 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04004359 sde_kms_info_start(info, "pixel_formats");
4360 while (format_list->fourcc_format) {
4361 sde_kms_info_append_format(info,
4362 format_list->fourcc_format,
4363 format_list->modifier);
4364 ++format_list;
4365 }
4366 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04004367 }
Dhaval Patel4e574842016-08-23 15:11:37 -07004368
Clarence Ip1db00c12017-07-21 17:42:56 -04004369 if (psde->pipe_hw && psde->pipe_hw->ops.get_scaler_ver)
4370 sde_kms_info_add_keyint(info, "scaler_step_ver",
4371 psde->pipe_hw->ops.get_scaler_ver(psde->pipe_hw));
4372
Dhaval Patel4e574842016-08-23 15:11:37 -07004373 sde_kms_info_add_keyint(info, "max_linewidth",
4374 psde->pipe_sblk->maxlinewidth);
4375 sde_kms_info_add_keyint(info, "max_upscale",
4376 psde->pipe_sblk->maxupscale);
4377 sde_kms_info_add_keyint(info, "max_downscale",
4378 psde->pipe_sblk->maxdwnscale);
4379 sde_kms_info_add_keyint(info, "max_horizontal_deci",
4380 psde->pipe_sblk->maxhdeciexp);
4381 sde_kms_info_add_keyint(info, "max_vertical_deci",
4382 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07004383 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
4384 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Veera Sundaram Sankaran7b121cb2018-03-02 08:43:04 -08004385 if (psde->features & BIT(SDE_SSPP_SEC_UI_ALLOWED))
4386 sde_kms_info_add_keyint(info, "sec_ui_allowed", 1);
Dhaval Patel4e574842016-08-23 15:11:37 -07004387 msm_property_set_blob(&psde->property_info, &psde->blob_info,
Narendra Muppalla22d17252017-05-31 15:13:39 -07004388 info->data, SDE_KMS_INFO_DATALEN(info),
4389 PLANE_PROP_INFO);
Dhaval Patel4e574842016-08-23 15:11:37 -07004390
4391 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07004392
4393 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
4394 snprintf(feature_name, sizeof(feature_name), "%s%d",
4395 "SDE_SSPP_SKIN_COLOR_V",
4396 psde->pipe_sblk->memcolor_blk.version >> 16);
4397 msm_property_install_blob(&psde->property_info, feature_name, 0,
4398 PLANE_PROP_SKIN_COLOR);
4399 snprintf(feature_name, sizeof(feature_name), "%s%d",
4400 "SDE_SSPP_SKY_COLOR_V",
4401 psde->pipe_sblk->memcolor_blk.version >> 16);
4402 msm_property_install_blob(&psde->property_info, feature_name, 0,
4403 PLANE_PROP_SKY_COLOR);
4404 snprintf(feature_name, sizeof(feature_name), "%s%d",
4405 "SDE_SSPP_FOLIAGE_COLOR_V",
4406 psde->pipe_sblk->memcolor_blk.version >> 16);
4407 msm_property_install_blob(&psde->property_info, feature_name, 0,
4408 PLANE_PROP_FOLIAGE_COLOR);
4409 }
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07004410
4411 msm_property_install_enum(&psde->property_info, "fb_translation_mode",
4412 0x0,
4413 0, e_fb_translation_mode,
4414 ARRAY_SIZE(e_fb_translation_mode),
4415 PLANE_PROP_FB_TRANSLATION_MODE);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004416}
4417
Clarence Ip5fc00c52016-09-23 15:03:34 -04004418static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
4419{
4420 struct sde_drm_csc_v1 csc_v1;
4421 int i;
4422
4423 if (!psde) {
4424 SDE_ERROR("invalid plane\n");
4425 return;
4426 }
4427
4428 psde->csc_usr_ptr = NULL;
4429 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004430 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04004431 return;
4432 }
4433
4434 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004435 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04004436 return;
4437 }
4438
Clarence Ipb43d4592016-09-08 14:21:35 -04004439 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04004440 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
4441 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
4442 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
4443 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
4444 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
4445 }
4446 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
4447 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
4448 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
4449 }
4450 psde->csc_usr_ptr = &psde->csc_cfg;
4451}
4452
Clarence Ip172033f2017-06-13 10:52:56 -04004453static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde,
4454 struct sde_plane_state *pstate, void *usr)
Clarence Ipb43d4592016-09-08 14:21:35 -04004455{
4456 struct sde_drm_scaler_v1 scale_v1;
4457 struct sde_hw_pixel_ext *pe;
4458 int i;
4459
Clarence Ip172033f2017-06-13 10:52:56 -04004460 if (!psde || !pstate) {
4461 SDE_ERROR("invalid argument(s)\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004462 return;
4463 }
4464
Clarence Ip172033f2017-06-13 10:52:56 -04004465 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
Clarence Ipb43d4592016-09-08 14:21:35 -04004466 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004467 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004468 return;
4469 }
4470
4471 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004472 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004473 return;
4474 }
4475
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004476 /* force property to be dirty, even if the pointer didn't change */
Clarence Ip4a2955d2017-07-04 18:04:33 -04004477 msm_property_set_dirty(&psde->property_info,
4478 &pstate->property_state, PLANE_PROP_SCALER_V1);
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004479
Clarence Ipb43d4592016-09-08 14:21:35 -04004480 /* populate from user space */
Clarence Ip172033f2017-06-13 10:52:56 -04004481 pe = &pstate->pixel_ext;
Clarence Ipb43d4592016-09-08 14:21:35 -04004482 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
4483 for (i = 0; i < SDE_MAX_PLANES; i++) {
4484 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
4485 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
4486 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
4487 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
4488
4489 pe->horz_filter[i] = scale_v1.horz_filter[i];
4490 pe->vert_filter[i] = scale_v1.vert_filter[i];
4491 }
4492 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05004493 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
4494 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
4495 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
4496 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
4497 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04004498
abeykun41060122016-11-28 13:02:01 -05004499 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
4500 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
4501 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
4502 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
4503 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04004504 }
abeykun41060122016-11-28 13:02:01 -05004505
Clarence Ip172033f2017-06-13 10:52:56 -04004506 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
Clarence Ipb43d4592016-09-08 14:21:35 -04004507
Clarence Ip059c8c32017-06-06 17:15:54 -04004508 SDE_EVT32_VERBOSE(DRMID(&psde->base));
Clarence Ip13a8cf42016-09-29 17:27:47 -04004509 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004510}
4511
abeykun48f407a2016-08-25 12:06:44 -04004512static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
4513 struct sde_plane_state *pstate, void *usr)
4514{
4515 struct sde_drm_scaler_v2 scale_v2;
4516 struct sde_hw_pixel_ext *pe;
4517 int i;
4518 struct sde_hw_scaler3_cfg *cfg;
4519
Clarence Ip172033f2017-06-13 10:52:56 -04004520 if (!psde || !pstate) {
4521 SDE_ERROR("invalid argument(s)\n");
abeykun48f407a2016-08-25 12:06:44 -04004522 return;
4523 }
4524
Clarence Ip172033f2017-06-13 10:52:56 -04004525 cfg = &pstate->scaler3_cfg;
4526 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
abeykun48f407a2016-08-25 12:06:44 -04004527 if (!usr) {
4528 SDE_DEBUG_PLANE(psde, "scale data removed\n");
4529 return;
4530 }
4531
4532 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
4533 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
4534 return;
4535 }
4536
Clarence Ip7e892a02017-06-13 10:16:07 -04004537 /* detach/ignore user data if 'disabled' */
4538 if (!scale_v2.enable) {
4539 SDE_DEBUG_PLANE(psde, "scale data removed\n");
4540 return;
4541 }
4542
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004543 /* force property to be dirty, even if the pointer didn't change */
Clarence Ip4a2955d2017-07-04 18:04:33 -04004544 msm_property_set_dirty(&psde->property_info,
4545 &pstate->property_state, PLANE_PROP_SCALER_V2);
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004546
abeykun48f407a2016-08-25 12:06:44 -04004547 /* populate from user space */
Sravanthi Kollukuduru55b24f02017-06-22 15:11:31 +05304548 sde_set_scaler_v2(cfg, &scale_v2);
4549
Clarence Ip172033f2017-06-13 10:52:56 -04004550 pe = &pstate->pixel_ext;
abeykun48f407a2016-08-25 12:06:44 -04004551 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
abeykun48f407a2016-08-25 12:06:44 -04004552
abeykun48f407a2016-08-25 12:06:44 -04004553 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05004554 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
4555 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
4556 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
4557 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
4558 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04004559
abeykun41060122016-11-28 13:02:01 -05004560 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
4561 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
4562 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
4563 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
4564 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04004565 }
Clarence Ip172033f2017-06-13 10:52:56 -04004566 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
abeykun48f407a2016-08-25 12:06:44 -04004567
Clarence Ip059c8c32017-06-06 17:15:54 -04004568 SDE_EVT32_VERBOSE(DRMID(&psde->base), cfg->enable, cfg->de.enable,
4569 cfg->src_width[0], cfg->src_height[0],
4570 cfg->dst_width, cfg->dst_height);
abeykun48f407a2016-08-25 12:06:44 -04004571 SDE_DEBUG_PLANE(psde, "user property data copied\n");
4572}
4573
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004574static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
4575 struct sde_plane_state *pstate, void *usr_ptr)
4576{
4577 struct drm_clip_rect excl_rect_v1;
4578
4579 if (!psde) {
4580 SDE_ERROR("invalid plane\n");
4581 return;
4582 }
4583
4584 if (!usr_ptr) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004585 SDE_DEBUG_PLANE(psde, "invalid excl_rect user data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004586 return;
4587 }
4588
4589 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004590 SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004591 return;
4592 }
4593
4594 /* populate from user space */
4595 pstate->excl_rect.x = excl_rect_v1.x1;
4596 pstate->excl_rect.y = excl_rect_v1.y1;
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004597 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
4598 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
4599
4600 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
4601 pstate->excl_rect.x, pstate->excl_rect.y,
4602 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004603}
4604
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004605static int sde_plane_atomic_set_property(struct drm_plane *plane,
4606 struct drm_plane_state *state, struct drm_property *property,
4607 uint64_t val)
4608{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004609 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004610 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004611 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004612
Clarence Ip13a8cf42016-09-29 17:27:47 -04004613 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004614
4615 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004616 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004617 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004618 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004619 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04004620 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004621 ret = msm_property_atomic_set(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004622 &pstate->property_state, property, val);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004623 if (!ret) {
4624 idx = msm_property_index(&psde->property_info,
4625 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004626 switch (idx) {
4627 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04004628 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004629 break;
4630 case PLANE_PROP_CSC_V1:
4631 _sde_plane_set_csc_v1(psde, (void *)val);
4632 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04004633 case PLANE_PROP_SCALER_V1:
Clarence Ip172033f2017-06-13 10:52:56 -04004634 _sde_plane_set_scaler_v1(psde, pstate,
4635 (void *)val);
Clarence Ipb43d4592016-09-08 14:21:35 -04004636 break;
abeykun48f407a2016-08-25 12:06:44 -04004637 case PLANE_PROP_SCALER_V2:
4638 _sde_plane_set_scaler_v2(psde, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004639 (void *)val);
abeykun48f407a2016-08-25 12:06:44 -04004640 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004641 case PLANE_PROP_EXCL_RECT_V1:
4642 _sde_plane_set_excl_rect_v1(psde, pstate,
4643 (void *)val);
4644 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04004645 default:
4646 /* nothing to do */
4647 break;
4648 }
Clarence Ipe78efb72016-06-24 18:35:21 -04004649 }
4650 }
4651
Alan Kwong4dd64c82017-02-04 18:41:51 -08004652 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
4653 property->name, property->base.id, val, ret);
4654
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004655 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004656}
4657
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004658static int sde_plane_atomic_get_property(struct drm_plane *plane,
4659 const struct drm_plane_state *state,
4660 struct drm_property *property, uint64_t *val)
4661{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004662 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004663 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04004664 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004665
Clarence Ipaa0faf42016-05-30 12:07:48 -04004666 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004667 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004668 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004669 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004670 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004671 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04004672 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004673 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004674 ret = msm_property_atomic_get(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004675 &pstate->property_state, property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04004676 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004677
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004678 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004679}
4680
4681static void sde_plane_destroy(struct drm_plane *plane)
4682{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004683 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004684
Clarence Ip13a8cf42016-09-29 17:27:47 -04004685 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004686
Clarence Ip13a8cf42016-09-29 17:27:47 -04004687 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04004688 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
4689
Dhaval Patel4e574842016-08-23 15:11:37 -07004690 if (psde->blob_info)
4691 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004692 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04004693 mutex_destroy(&psde->lock);
4694
Clarence Ip4ce59322016-06-26 22:27:51 -04004695 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004696
Clarence Ip4ce59322016-06-26 22:27:51 -04004697 /* this will destroy the states as well */
4698 drm_plane_cleanup(plane);
4699
Clarence Ip4c1d9772016-06-26 09:35:38 -04004700 if (psde->pipe_hw)
4701 sde_hw_sspp_destroy(psde->pipe_hw);
4702
Clarence Ip4ce59322016-06-26 22:27:51 -04004703 kfree(psde);
4704 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004705}
4706
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004707static void sde_plane_destroy_state(struct drm_plane *plane,
4708 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004709{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004710 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04004711 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004712
Clarence Ipae4e60c2016-06-26 22:44:04 -04004713 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004714 SDE_ERROR("invalid arg(s), plane %d state %d\n",
4715 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004716 return;
4717 }
4718
Clarence Ipaa0faf42016-05-30 12:07:48 -04004719 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04004720 pstate = to_sde_plane_state(state);
4721
Clarence Ip13a8cf42016-09-29 17:27:47 -04004722 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004723
Alan Kwong4dd64c82017-02-04 18:41:51 -08004724 sde_plane_rot_destroy_state(plane, &pstate->base);
4725
Clarence Ipe78efb72016-06-24 18:35:21 -04004726 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004727 if (state->fb)
4728 drm_framebuffer_unreference(state->fb);
4729
Clarence Ipae4e60c2016-06-26 22:44:04 -04004730 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04004731 if (pstate->input_fence)
4732 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004733
Clarence Ipaa0faf42016-05-30 12:07:48 -04004734 /* destroy value helper */
4735 msm_property_destroy_state(&psde->property_info, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004736 &pstate->property_state);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004737}
4738
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004739static struct drm_plane_state *
4740sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004741{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004742 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004743 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04004744 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04004745 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004746
Clarence Ip13a8cf42016-09-29 17:27:47 -04004747 if (!plane) {
4748 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004749 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004750 } else if (!plane->state) {
4751 SDE_ERROR("invalid plane state\n");
4752 return NULL;
4753 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004754
Clarence Ip730e7192016-06-26 22:45:09 -04004755 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004756 psde = to_sde_plane(plane);
4757 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004758 if (!pstate) {
4759 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004760 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004761 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004762
Clarence Ip13a8cf42016-09-29 17:27:47 -04004763 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004764
4765 /* duplicate value helper */
4766 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004767 &pstate->property_state, pstate->property_values);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004768
Clarence Ip17e908b2016-09-29 15:58:00 -04004769 /* clear out any input fence */
4770 pstate->input_fence = 0;
4771 input_fence_default = msm_property_get_default(
4772 &psde->property_info, PLANE_PROP_INPUT_FENCE);
Clarence Ip4a2955d2017-07-04 18:04:33 -04004773 msm_property_set_property(&psde->property_info,
4774 &pstate->property_state,
Clarence Ip17e908b2016-09-29 15:58:00 -04004775 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004776
Clarence Ip282dad62016-09-27 17:07:35 -04004777 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04004778 pstate->pending = false;
4779
Alan Kwongcdb2f282017-03-18 13:42:06 -07004780 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
4781
Alan Kwong4dd64c82017-02-04 18:41:51 -08004782 sde_plane_rot_duplicate_state(plane, &pstate->base);
4783
Clarence Ip730e7192016-06-26 22:45:09 -04004784 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004785}
4786
4787static void sde_plane_reset(struct drm_plane *plane)
4788{
Clarence Ipae4e60c2016-06-26 22:44:04 -04004789 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004790 struct sde_plane_state *pstate;
4791
Clarence Ipae4e60c2016-06-26 22:44:04 -04004792 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004793 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04004794 return;
4795 }
4796
Clarence Ip730e7192016-06-26 22:45:09 -04004797 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004798 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004799
Veera Sundaram Sankarandb43e282017-09-19 18:32:52 -07004800 if (plane->state && !sde_crtc_is_reset_required(plane->state->crtc)) {
4801 SDE_DEBUG_PLANE(psde, "avoid reset for plane\n");
4802 return;
4803 }
4804
Clarence Ipae4e60c2016-06-26 22:44:04 -04004805 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04004806 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04004807 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004808 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04004809 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004810
Clarence Ipaa0faf42016-05-30 12:07:48 -04004811 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004812 if (!pstate) {
4813 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004814 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004815 }
Clarence Ip730e7192016-06-26 22:45:09 -04004816
Clarence Ipaa0faf42016-05-30 12:07:48 -04004817 /* reset value helper */
4818 msm_property_reset_state(&psde->property_info, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004819 &pstate->property_state,
4820 pstate->property_values);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004821
4822 pstate->base.plane = plane;
4823
4824 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004825}
4826
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004827#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04004828static ssize_t _sde_plane_danger_read(struct file *file,
4829 char __user *buff, size_t count, loff_t *ppos)
4830{
4831 struct sde_kms *kms = file->private_data;
4832 struct sde_mdss_cfg *cfg = kms->catalog;
4833 int len = 0;
4834 char buf[40] = {'\0'};
4835
4836 if (!cfg)
4837 return -ENODEV;
4838
4839 if (*ppos)
4840 return 0; /* the end */
4841
4842 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
4843 if (len < 0 || len >= sizeof(buf))
4844 return 0;
4845
4846 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
4847 return -EFAULT;
4848
4849 *ppos += len; /* increase offset */
4850
4851 return len;
4852}
4853
4854static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
4855{
4856 struct drm_plane *plane;
4857
4858 drm_for_each_plane(plane, kms->dev) {
4859 if (plane->fb && plane->state) {
4860 sde_plane_danger_signal_ctrl(plane, enable);
4861 SDE_DEBUG("plane:%d img:%dx%d ",
4862 plane->base.id, plane->fb->width,
4863 plane->fb->height);
4864 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
4865 plane->state->src_x >> 16,
4866 plane->state->src_y >> 16,
4867 plane->state->src_w >> 16,
4868 plane->state->src_h >> 16,
4869 plane->state->crtc_x, plane->state->crtc_y,
4870 plane->state->crtc_w, plane->state->crtc_h);
4871 } else {
4872 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
4873 }
4874 }
4875}
4876
4877static ssize_t _sde_plane_danger_write(struct file *file,
4878 const char __user *user_buf, size_t count, loff_t *ppos)
4879{
4880 struct sde_kms *kms = file->private_data;
4881 struct sde_mdss_cfg *cfg = kms->catalog;
4882 int disable_panic;
4883 char buf[10];
4884
4885 if (!cfg)
4886 return -EFAULT;
4887
4888 if (count >= sizeof(buf))
4889 return -EFAULT;
4890
4891 if (copy_from_user(buf, user_buf, count))
4892 return -EFAULT;
4893
4894 buf[count] = 0; /* end of string */
4895
4896 if (kstrtoint(buf, 0, &disable_panic))
4897 return -EFAULT;
4898
4899 if (disable_panic) {
4900 /* Disable panic signal for all active pipes */
4901 SDE_DEBUG("Disabling danger:\n");
4902 _sde_plane_set_danger_state(kms, false);
4903 kms->has_danger_ctrl = false;
4904 } else {
4905 /* Enable panic signal for all active pipes */
4906 SDE_DEBUG("Enabling danger:\n");
4907 kms->has_danger_ctrl = true;
4908 _sde_plane_set_danger_state(kms, true);
4909 }
4910
4911 return count;
4912}
4913
4914static const struct file_operations sde_plane_danger_enable = {
4915 .open = simple_open,
4916 .read = _sde_plane_danger_read,
4917 .write = _sde_plane_danger_write,
4918};
4919
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004920static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04004921{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004922 struct sde_plane *psde;
4923 struct sde_kms *kms;
4924 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04004925 const struct sde_sspp_sub_blks *sblk = 0;
4926 const struct sde_sspp_cfg *cfg = 0;
4927
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004928 if (!plane || !plane->dev) {
4929 SDE_ERROR("invalid arguments\n");
4930 return -EINVAL;
4931 }
4932
4933 priv = plane->dev->dev_private;
4934 if (!priv || !priv->kms) {
4935 SDE_ERROR("invalid KMS reference\n");
4936 return -EINVAL;
4937 }
4938
4939 kms = to_sde_kms(priv->kms);
4940 psde = to_sde_plane(plane);
4941
Clarence Ip4ce59322016-06-26 22:27:51 -04004942 if (psde && psde->pipe_hw)
4943 cfg = psde->pipe_hw->cap;
4944 if (cfg)
4945 sblk = cfg->sblk;
4946
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004947 if (!sblk)
4948 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04004949
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004950 /* create overall sub-directory for the pipe */
4951 psde->debugfs_root =
4952 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07004953 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04004954
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004955 if (!psde->debugfs_root)
4956 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04004957
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004958 /* don't error check these */
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004959 debugfs_create_x32("features", 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004960 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004961
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004962 /* add register dump support */
4963 sde_debugfs_setup_regset32(&psde->debugfs_src,
4964 sblk->src_blk.base + cfg->base,
4965 sblk->src_blk.len,
4966 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004967 sde_debugfs_create_regset32("src_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004968 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004969
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004970 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
4971 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
4972 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
4973 sblk->scaler_blk.base + cfg->base,
4974 sblk->scaler_blk.len,
4975 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004976 sde_debugfs_create_regset32("scaler_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004977 psde->debugfs_root,
4978 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07004979 debugfs_create_bool("default_scaling",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004980 0600,
Clarence Ip716ab662017-03-20 06:51:24 -07004981 psde->debugfs_root,
4982 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04004983 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004984
4985 if (cfg->features & BIT(SDE_SSPP_CSC) ||
4986 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
4987 sde_debugfs_setup_regset32(&psde->debugfs_csc,
4988 sblk->csc_blk.base + cfg->base,
4989 sblk->csc_blk.len,
4990 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004991 sde_debugfs_create_regset32("csc_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004992 psde->debugfs_root, &psde->debugfs_csc);
4993 }
4994
4995 debugfs_create_u32("xin_id",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004996 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004997 psde->debugfs_root,
4998 (u32 *) &cfg->xin_id);
4999 debugfs_create_u32("clk_ctrl",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04005000 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07005001 psde->debugfs_root,
5002 (u32 *) &cfg->clk_ctrl);
5003 debugfs_create_x32("creq_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04005004 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07005005 psde->debugfs_root,
5006 (u32 *) &sblk->creq_vblank);
5007 debugfs_create_x32("danger_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04005008 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07005009 psde->debugfs_root,
5010 (u32 *) &sblk->danger_vblank);
5011
5012 debugfs_create_file("disable_danger",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04005013 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07005014 psde->debugfs_root,
5015 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08005016 debugfs_create_u32("sbuf_mode",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04005017 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08005018 psde->debugfs_root, &psde->sbuf_mode);
5019 debugfs_create_u32("sbuf_writeback",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04005020 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08005021 psde->debugfs_root,
5022 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07005023
5024 return 0;
5025}
5026
5027static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
5028{
5029 struct sde_plane *psde;
5030
5031 if (!plane)
5032 return;
5033 psde = to_sde_plane(plane);
5034
5035 debugfs_remove_recursive(psde->debugfs_root);
5036}
5037#else
5038static int _sde_plane_init_debugfs(struct drm_plane *plane)
5039{
5040 return 0;
5041}
5042static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
5043{
5044}
5045#endif
5046
5047static int sde_plane_late_register(struct drm_plane *plane)
5048{
5049 return _sde_plane_init_debugfs(plane);
5050}
5051
5052static void sde_plane_early_unregister(struct drm_plane *plane)
5053{
5054 _sde_plane_destroy_debugfs(plane);
5055}
5056
5057static const struct drm_plane_funcs sde_plane_funcs = {
5058 .update_plane = drm_atomic_helper_update_plane,
5059 .disable_plane = drm_atomic_helper_disable_plane,
5060 .destroy = sde_plane_destroy,
Clarence Ip569d5af2017-10-14 21:09:01 -04005061 .set_property = drm_atomic_helper_plane_set_property,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07005062 .atomic_set_property = sde_plane_atomic_set_property,
5063 .atomic_get_property = sde_plane_atomic_get_property,
5064 .reset = sde_plane_reset,
5065 .atomic_duplicate_state = sde_plane_duplicate_state,
5066 .atomic_destroy_state = sde_plane_destroy_state,
5067 .late_register = sde_plane_late_register,
5068 .early_unregister = sde_plane_early_unregister,
5069};
5070
5071static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
5072 .prepare_fb = sde_plane_prepare_fb,
5073 .cleanup_fb = sde_plane_cleanup_fb,
5074 .atomic_check = sde_plane_atomic_check,
5075 .atomic_update = sde_plane_atomic_update,
5076};
5077
5078enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
5079{
5080 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
5081}
5082
5083bool is_sde_plane_virtual(struct drm_plane *plane)
5084{
5085 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04005086}
5087
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005088/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04005089struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04005090 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08005091 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005092{
Alan Kwongdce56da2017-04-27 15:50:34 -07005093 struct drm_plane *plane = NULL, *master_plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08005094 const struct sde_format_extended *format_list;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005095 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005096 struct msm_drm_private *priv;
5097 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005098 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04005099 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04005100
5101 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07005102 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04005103 goto exit;
5104 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005105
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005106 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04005107 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07005108 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04005109 goto exit;
5110 }
5111
5112 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07005113 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04005114 goto exit;
5115 }
5116 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005117
Clarence Ip4c1d9772016-06-26 09:35:38 -04005118 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07005119 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04005120 goto exit;
5121 }
5122
Clarence Ip4ce59322016-06-26 22:27:51 -04005123 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005124 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
5125 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07005126 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005127 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04005128 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005129 }
5130
Clarence Ip4c1d9772016-06-26 09:35:38 -04005131 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005132 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005133 psde->pipe = pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08005134 psde->is_virtual = (master_plane_id != 0);
Alan Kwongdce56da2017-04-27 15:50:34 -07005135 INIT_LIST_HEAD(&psde->mplane_list);
5136 master_plane = drm_plane_find(dev, master_plane_id);
5137 if (master_plane) {
5138 struct sde_plane *mpsde = to_sde_plane(master_plane);
5139
5140 list_add_tail(&psde->mplane_list, &mpsde->mplane_list);
5141 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005142
Clarence Ip4c1d9772016-06-26 09:35:38 -04005143 /* initialize underlying h/w driver */
Dhaval Pateld850b222017-06-16 17:37:37 -07005144 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog,
5145 master_plane_id != 0);
Clarence Ip4c1d9772016-06-26 09:35:38 -04005146 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07005147 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04005148 ret = PTR_ERR(psde->pipe_hw);
5149 goto clean_plane;
5150 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07005151 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04005152 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005153 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04005154
5155 /* cache features mask for later */
5156 psde->features = psde->pipe_hw->cap->features;
5157 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04005158 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04005159 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04005160 goto clean_sspp;
5161 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04005162
Steve Cohen57428172017-07-18 10:57:17 -04005163 if (!master_plane_id)
5164 format_list = psde->pipe_sblk->format_list;
5165 else
5166 format_list = psde->pipe_sblk->virt_format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08005167
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07005168 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08005169 psde->formats,
5170 0,
5171 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005172
Clarence Ip4c1d9772016-06-26 09:35:38 -04005173 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07005174 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04005175 goto clean_sspp;
5176 }
5177
5178 if (psde->features & BIT(SDE_SSPP_CURSOR))
5179 type = DRM_PLANE_TYPE_CURSOR;
5180 else if (primary_plane)
5181 type = DRM_PLANE_TYPE_PRIMARY;
5182 else
5183 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07005184 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
5185 psde->formats, psde->nformats,
5186 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005187 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04005188 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005189
Clarence Ip4c1d9772016-06-26 09:35:38 -04005190 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005191 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005192
Clarence Ipaa0faf42016-05-30 12:07:48 -04005193 msm_property_init(&psde->property_info, &plane->base, dev,
5194 priv->plane_property, psde->property_data,
5195 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
5196 sizeof(struct sde_plane_state));
5197
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08005198 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04005199
Clarence Ip4ce59322016-06-26 22:27:51 -04005200 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04005201 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04005202
Clarence Ip730e7192016-06-26 22:45:09 -04005203 mutex_init(&psde->lock);
5204
Dhaval Patel572cfd22017-06-12 19:33:39 -07005205 SDE_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", psde->pipe_name,
5206 pipe, plane->base.id, master_plane_id);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005207 return plane;
5208
Clarence Ip4c1d9772016-06-26 09:35:38 -04005209clean_sspp:
5210 if (psde && psde->pipe_hw)
5211 sde_hw_sspp_destroy(psde->pipe_hw);
5212clean_plane:
5213 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04005214exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005215 return ERR_PTR(ret);
5216}