blob: 6e1fe33bc3782571b8946047ae71011fe4c04ba7 [file] [log] [blame]
Dhaval Patel14d46ce2017-01-17 16:28:12 -08001/*
2 * Copyright (C) 2014-2017 The Linux Foundation. All rights reserved.
3 * 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 Ip56902792017-03-17 15:22:07 -040041static bool suspend_blank = true;
42module_param(suspend_blank, bool, 0400);
43MODULE_PARM_DESC(suspend_blank,
44 "If set, active planes will force their outputs to black,\n"
45 "by temporarily enabling the color fill, when recovering\n"
46 "from a system resume instead of attempting to display the\n"
47 "last provided frame buffer.");
48
Clarence Ip13a8cf42016-09-29 17:27:47 -040049#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
50 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
51
52#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
53 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
54
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040055#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
56#define PHASE_STEP_SHIFT 21
57#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
58#define PHASE_RESIDUAL 15
59
Clarence Ipe78efb72016-06-24 18:35:21 -040060#define SHARP_STRENGTH_DEFAULT 32
61#define SHARP_EDGE_THR_DEFAULT 112
62#define SHARP_SMOOTH_THR_DEFAULT 8
63#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040064
Clarence Ip5e2a9222016-06-26 22:38:24 -040065#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070066
Clarence Ipcae1bb62016-07-07 12:07:13 -040067#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
68
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080069/* multirect rect index */
70enum {
71 R0,
72 R1,
73 R_MAX
74};
75
76#define TX_MODE_BUFFER_LINE_THRES 2
77
Clarence Ip282dad62016-09-27 17:07:35 -040078/* dirty bits for update function */
79#define SDE_PLANE_DIRTY_RECTS 0x1
80#define SDE_PLANE_DIRTY_FORMAT 0x2
81#define SDE_PLANE_DIRTY_SHARPEN 0x4
82#define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF
83
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -070084#define SDE_QSEED3_DEFAULT_PRELOAD_H 0x4
85#define SDE_QSEED3_DEFAULT_PRELOAD_V 0x3
86
Alan Kwong4dd64c82017-02-04 18:41:51 -080087#define DEFAULT_REFRESH_RATE 60
88
Alan Kwong1a00e4d2016-07-18 09:42:30 -040089/**
90 * enum sde_plane_qos - Different qos configurations for each pipe
91 *
92 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
93 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
94 * this configuration is mutually exclusive from VBLANK_CTRL.
95 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
96 */
97enum sde_plane_qos {
98 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
99 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
100 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
101};
102
Clarence Ip5fc00c52016-09-23 15:03:34 -0400103/*
104 * struct sde_plane - local sde plane structure
105 * @csc_cfg: Decoded user configuration for csc
106 * @csc_usr_ptr: Points to csc_cfg if valid user config available
107 * @csc_ptr: Points to sde_csc_cfg structure to use for current
Alan Kwong4dd64c82017-02-04 18:41:51 -0800108 * @catalog: Points to sde catalog structure
109 * @sbuf_mode: force stream buffer mode if set
110 * @sbuf_writeback: fource stream buffer writeback if set
111 * @blob_rot_caps: Pointer to rotator capability blob
Clarence Ip5fc00c52016-09-23 15:03:34 -0400112 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700113struct sde_plane {
114 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400115
116 int mmu_id;
117
Clarence Ip730e7192016-06-26 22:45:09 -0400118 struct mutex lock;
119
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400120 enum sde_sspp pipe;
121 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700122 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400123 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400124
125 struct sde_hw_pipe *pipe_hw;
126 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -0400127 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -0400128 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400129 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400130 uint32_t color_fill;
131 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400132 bool is_rt_pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800133 bool is_virtual;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800134 struct sde_mdss_cfg *catalog;
135 u32 sbuf_mode;
136 u32 sbuf_writeback;
Clarence Ip4ce59322016-06-26 22:27:51 -0400137
Clarence Ipb43d4592016-09-08 14:21:35 -0400138 struct sde_hw_pixel_ext pixel_ext;
139 bool pixel_ext_usr;
140
Clarence Ip373f8592016-05-26 00:58:42 -0400141 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400142 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400143 struct sde_csc_cfg *csc_ptr;
144
Clarence Ip4c1d9772016-06-26 09:35:38 -0400145 const struct sde_sspp_sub_blks *pipe_sblk;
146
Clarence Ip5e2a9222016-06-26 22:38:24 -0400147 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400148
Clarence Ipaa0faf42016-05-30 12:07:48 -0400149 struct msm_property_info property_info;
150 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700151 struct drm_property_blob *blob_info;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800152 struct drm_property_blob *blob_rot_caps;
Clarence Ip730e7192016-06-26 22:45:09 -0400153
Clarence Ip4ce59322016-06-26 22:27:51 -0400154 /* debugfs related stuff */
155 struct dentry *debugfs_root;
156 struct sde_debugfs_regset32 debugfs_src;
157 struct sde_debugfs_regset32 debugfs_scaler;
158 struct sde_debugfs_regset32 debugfs_csc;
Clarence Ip716ab662017-03-20 06:51:24 -0700159 bool debugfs_default_scale;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700160};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700161
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700162#define to_sde_plane(x) container_of(x, struct sde_plane, base)
163
Alan Kwong4dd64c82017-02-04 18:41:51 -0800164static struct sde_kms *_sde_plane_get_kms(struct drm_plane *plane)
165{
166 struct msm_drm_private *priv;
167
168 if (!plane || !plane->dev)
169 return NULL;
170 priv = plane->dev->dev_private;
171 if (!priv)
172 return NULL;
173 return to_sde_kms(priv->kms);
174}
175
Alan Kwong4aacd532017-02-04 18:51:33 -0800176/**
177 * _sde_plane_get_crtc_state - obtain crtc state attached to given plane state
178 * @pstate: Pointer to drm plane state
179 * return: Pointer to crtc state if success; pointer error, otherwise
180 */
181static struct drm_crtc_state *_sde_plane_get_crtc_state(
182 struct drm_plane_state *pstate)
183{
184 struct drm_crtc_state *cstate;
185
186 if (!pstate || !pstate->crtc)
187 return NULL;
188
189 if (pstate->state)
190 cstate = drm_atomic_get_crtc_state(pstate->state, pstate->crtc);
191 else
192 cstate = pstate->crtc->state;
193
194 return cstate;
195}
196
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400197static bool sde_plane_enabled(struct drm_plane_state *state)
198{
Clarence Ipdbde9832016-06-26 09:48:36 -0400199 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400200}
201
Alan Kwong4dd64c82017-02-04 18:41:51 -0800202static bool sde_plane_sspp_enabled(struct drm_plane_state *state)
203{
204 return state && to_sde_plane_state(state)->rot.out_fb && state->crtc;
205}
206
207/**
208 * sde_plane_crtc_enabled - determine if crtc of given plane state is enabled
209 * @state: Pointer to drm plane state
210 * return: true if plane and the associated crtc are both enabled
211 */
212static bool sde_plane_crtc_enabled(struct drm_plane_state *state)
213{
214 return sde_plane_enabled(state) && state->crtc->state &&
215 state->crtc->state->active &&
216 state->crtc->state->enable;
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{
229 struct sde_plane *psde;
230 u32 fixed_buff_size;
231 u32 total_fl;
232
233 if (!plane || !fmt) {
234 SDE_ERROR("invalid arguments\n");
235 return 0;
236 }
237
238 psde = to_sde_plane(plane);
239 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
240
241 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
242 if (fmt->chroma_sample == SDE_CHROMA_420) {
243 /* NV12 */
244 total_fl = (fixed_buff_size / 2) /
245 ((src_width + 32) * fmt->bpp);
246 } else {
247 /* non NV12 */
248 total_fl = (fixed_buff_size) /
249 ((src_width + 32) * fmt->bpp);
250 }
251 } else {
252 total_fl = (fixed_buff_size * 2) /
253 ((src_width + 32) * fmt->bpp);
254 }
255
256 SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n",
257 plane->base.id, psde->pipe - SSPP_VIG0,
258 fmt->base.pixel_format, src_width, total_fl);
259
260 return total_fl;
261}
262
263/**
264 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
265 * @total_fl: fill level
266 * Return: LUT setting corresponding to the fill level
267 */
268static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
269{
270 u32 qos_lut;
271
272 if (total_fl <= 4)
273 qos_lut = 0x1B;
274 else if (total_fl <= 5)
275 qos_lut = 0x5B;
276 else if (total_fl <= 6)
277 qos_lut = 0x15B;
278 else if (total_fl <= 7)
279 qos_lut = 0x55B;
280 else if (total_fl <= 8)
281 qos_lut = 0x155B;
282 else if (total_fl <= 9)
283 qos_lut = 0x555B;
284 else if (total_fl <= 10)
285 qos_lut = 0x1555B;
286 else if (total_fl <= 11)
287 qos_lut = 0x5555B;
288 else if (total_fl <= 12)
289 qos_lut = 0x15555B;
290 else
291 qos_lut = 0x55555B;
292
293 return qos_lut;
294}
295
296/**
297 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
298 * @total_fl: fill level
299 * Return: LUT setting corresponding to the fill level
300 */
301static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
302{
303 u32 qos_lut;
304
305 if (total_fl <= 10)
306 qos_lut = 0x1AAff;
307 else if (total_fl <= 11)
308 qos_lut = 0x5AAFF;
309 else if (total_fl <= 12)
310 qos_lut = 0x15AAFF;
311 else
312 qos_lut = 0x55AAFF;
313
314 return qos_lut;
315}
316
317/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400318 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
319 * @plane: Pointer to drm plane
320 * @fb: Pointer to framebuffer associated with the given plane
321 */
322static void _sde_plane_set_qos_lut(struct drm_plane *plane,
323 struct drm_framebuffer *fb)
324{
325 struct sde_plane *psde;
326 const struct sde_format *fmt = NULL;
327 u32 qos_lut;
328 u32 total_fl = 0;
329
330 if (!plane || !fb) {
331 SDE_ERROR("invalid arguments plane %d fb %d\n",
332 plane != 0, fb != 0);
333 return;
334 }
335
336 psde = to_sde_plane(plane);
337
338 if (!psde->pipe_hw || !psde->pipe_sblk) {
339 SDE_ERROR("invalid arguments\n");
340 return;
341 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
342 return;
343 }
344
345 if (!psde->is_rt_pipe) {
346 qos_lut = psde->pipe_sblk->creq_lut_nrt;
347 } else {
348 fmt = sde_get_sde_format_ext(
349 fb->pixel_format,
350 fb->modifier,
351 drm_format_num_planes(fb->pixel_format));
352 total_fl = _sde_plane_calc_fill_level(plane, fmt,
353 psde->pipe_cfg.src_rect.w);
354
355 if (SDE_FORMAT_IS_LINEAR(fmt))
356 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
357 else
358 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
359 }
360
361 psde->pipe_qos_cfg.creq_lut = qos_lut;
362
363 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
364 (fmt) ? fmt->base.pixel_format : 0,
365 psde->is_rt_pipe, total_fl, qos_lut,
366 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
367
368 SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n",
369 plane->base.id,
370 psde->pipe - SSPP_VIG0,
371 (fmt) ? fmt->base.pixel_format : 0,
372 psde->is_rt_pipe, total_fl, qos_lut);
373
374 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
375}
376
377/**
378 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
379 * @plane: Pointer to drm plane
380 * @fb: Pointer to framebuffer associated with the given plane
381 */
382static void _sde_plane_set_danger_lut(struct drm_plane *plane,
383 struct drm_framebuffer *fb)
384{
385 struct sde_plane *psde;
386 const struct sde_format *fmt = NULL;
387 u32 danger_lut, safe_lut;
388
389 if (!plane || !fb) {
390 SDE_ERROR("invalid arguments\n");
391 return;
392 }
393
394 psde = to_sde_plane(plane);
395
396 if (!psde->pipe_hw || !psde->pipe_sblk) {
397 SDE_ERROR("invalid arguments\n");
398 return;
399 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
400 return;
401 }
402
403 if (!psde->is_rt_pipe) {
404 danger_lut = psde->pipe_sblk->danger_lut_nrt;
405 safe_lut = psde->pipe_sblk->safe_lut_nrt;
406 } else {
407 fmt = sde_get_sde_format_ext(
408 fb->pixel_format,
409 fb->modifier,
410 drm_format_num_planes(fb->pixel_format));
411
412 if (SDE_FORMAT_IS_LINEAR(fmt)) {
413 danger_lut = psde->pipe_sblk->danger_lut_linear;
414 safe_lut = psde->pipe_sblk->safe_lut_linear;
415 } else {
416 danger_lut = psde->pipe_sblk->danger_lut_tile;
417 safe_lut = psde->pipe_sblk->safe_lut_tile;
418 }
419 }
420
421 psde->pipe_qos_cfg.danger_lut = danger_lut;
422 psde->pipe_qos_cfg.safe_lut = safe_lut;
423
424 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
425 (fmt) ? fmt->base.pixel_format : 0,
426 (fmt) ? fmt->fetch_mode : 0,
427 psde->pipe_qos_cfg.danger_lut,
428 psde->pipe_qos_cfg.safe_lut);
429
430 SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n",
431 plane->base.id,
432 psde->pipe - SSPP_VIG0,
433 fmt ? fmt->base.pixel_format : 0,
434 fmt ? fmt->fetch_mode : -1,
435 psde->pipe_qos_cfg.danger_lut,
436 psde->pipe_qos_cfg.safe_lut);
437
438 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
439 &psde->pipe_qos_cfg);
440}
441
442/**
443 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
444 * @plane: Pointer to drm plane
445 * @enable: true to enable QoS control
446 * @flags: QoS control mode (enum sde_plane_qos)
447 */
448static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
449 bool enable, u32 flags)
450{
451 struct sde_plane *psde;
452
453 if (!plane) {
454 SDE_ERROR("invalid arguments\n");
455 return;
456 }
457
458 psde = to_sde_plane(plane);
459
460 if (!psde->pipe_hw || !psde->pipe_sblk) {
461 SDE_ERROR("invalid arguments\n");
462 return;
463 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
464 return;
465 }
466
467 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
468 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
469 psde->pipe_qos_cfg.danger_vblank =
470 psde->pipe_sblk->danger_vblank;
471 psde->pipe_qos_cfg.vblank_en = enable;
472 }
473
474 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
475 /* this feature overrules previous VBLANK_CTRL */
476 psde->pipe_qos_cfg.vblank_en = false;
477 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
478 }
479
480 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
481 psde->pipe_qos_cfg.danger_safe_en = enable;
482
483 if (!psde->is_rt_pipe) {
484 psde->pipe_qos_cfg.vblank_en = false;
485 psde->pipe_qos_cfg.danger_safe_en = false;
486 }
487
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400488 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 -0400489 plane->base.id,
490 psde->pipe - SSPP_VIG0,
491 psde->pipe_qos_cfg.danger_safe_en,
492 psde->pipe_qos_cfg.vblank_en,
493 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400494 psde->pipe_qos_cfg.danger_vblank,
495 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400496
497 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
498 &psde->pipe_qos_cfg);
499}
500
Alan Kwongf0fd8512016-10-24 21:39:26 -0400501int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
502{
503 struct sde_plane *psde;
504 struct msm_drm_private *priv;
505 struct sde_kms *sde_kms;
506
507 if (!plane || !plane->dev) {
508 SDE_ERROR("invalid arguments\n");
509 return -EINVAL;
510 }
511
512 priv = plane->dev->dev_private;
513 if (!priv || !priv->kms) {
514 SDE_ERROR("invalid KMS reference\n");
515 return -EINVAL;
516 }
517
518 sde_kms = to_sde_kms(priv->kms);
519 psde = to_sde_plane(plane);
520
521 if (!psde->is_rt_pipe)
522 goto end;
523
524 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
525
526 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
527
528 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
529
530end:
531 return 0;
532}
533
Alan Kwong5d324e42016-07-28 22:56:18 -0400534/**
535 * _sde_plane_set_ot_limit - set OT limit for the given plane
536 * @plane: Pointer to drm plane
537 * @crtc: Pointer to drm crtc
538 */
539static void _sde_plane_set_ot_limit(struct drm_plane *plane,
540 struct drm_crtc *crtc)
541{
542 struct sde_plane *psde;
543 struct sde_vbif_set_ot_params ot_params;
544 struct msm_drm_private *priv;
545 struct sde_kms *sde_kms;
546
547 if (!plane || !plane->dev || !crtc) {
548 SDE_ERROR("invalid arguments plane %d crtc %d\n",
549 plane != 0, crtc != 0);
550 return;
551 }
552
553 priv = plane->dev->dev_private;
554 if (!priv || !priv->kms) {
555 SDE_ERROR("invalid KMS reference\n");
556 return;
557 }
558
559 sde_kms = to_sde_kms(priv->kms);
560 psde = to_sde_plane(plane);
561 if (!psde->pipe_hw) {
562 SDE_ERROR("invalid pipe reference\n");
563 return;
564 }
565
566 memset(&ot_params, 0, sizeof(ot_params));
567 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
568 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
569 ot_params.width = psde->pipe_cfg.src_rect.w;
570 ot_params.height = psde->pipe_cfg.src_rect.h;
571 ot_params.is_wfd = !psde->is_rt_pipe;
572 ot_params.frame_rate = crtc->mode.vrefresh;
573 ot_params.vbif_idx = VBIF_RT;
574 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
575 ot_params.rd = true;
576
577 sde_vbif_set_ot_limit(sde_kms, &ot_params);
578}
579
Clarence Ipcae1bb62016-07-07 12:07:13 -0400580/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400581static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400582 struct sde_plane_state *pstate, uint64_t fd)
583{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400584 if (!psde || !pstate) {
585 SDE_ERROR("invalid arg(s), plane %d state %d\n",
586 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400587 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400588 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400589
590 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400591 if (pstate->input_fence)
592 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400593
594 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400595 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400596
Clarence Ip13a8cf42016-09-29 17:27:47 -0400597 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400598}
599
Clarence Ipcae1bb62016-07-07 12:07:13 -0400600int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400601{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400602 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400603 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400604 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400605 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400606 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800607 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400608
609 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700610 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400611 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400612 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400613 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400614 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400615 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400616 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400617
Clarence Ipcae1bb62016-07-07 12:07:13 -0400618 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800619 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400620 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800621 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400622
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400623 SDE_EVT32(DRMID(plane), -ret, prefix);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400624
Dhaval Patel39323d42017-03-01 23:48:24 -0800625 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400626 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400627 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
628 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400629 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800630 ret = -ETIMEDOUT;
631 break;
632 case -ERESTARTSYS:
633 SDE_ERROR_PLANE(psde,
634 "%ums wait interrupted on %08X\n",
635 wait_ms, prefix);
636 psde->is_error = true;
637 ret = -ERESTARTSYS;
638 break;
639 case -EINVAL:
640 SDE_ERROR_PLANE(psde,
641 "invalid fence param for %08X\n",
642 prefix);
643 psde->is_error = true;
644 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400645 break;
646 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800647 SDE_DEBUG_PLANE(psde, "signaled\n");
648 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400649 break;
650 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400651 } else {
652 ret = 0;
653 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400654 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400655 return ret;
656}
657
Clarence Ip282dad62016-09-27 17:07:35 -0400658static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400659 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400660 struct sde_hw_pipe_cfg *pipe_cfg,
661 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400662{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400663 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400664 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400665
Clarence Ip13a8cf42016-09-29 17:27:47 -0400666 if (!plane || !pstate || !pipe_cfg || !fb) {
667 SDE_ERROR(
668 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
669 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400670 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400671 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400672
673 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400674 if (!psde->pipe_hw) {
675 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400676 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400677 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400678
Clarence Ipb6eb2362016-09-08 16:18:13 -0400679 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
680 if (ret == -EAGAIN)
681 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
682 else if (ret)
683 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
684 else if (psde->pipe_hw->ops.setup_sourceaddress)
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800685 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
686 pstate->multirect_index);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400687}
688
abeykun48f407a2016-08-25 12:06:44 -0400689static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
690 struct sde_plane_state *pstate)
691{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500692 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400693 int ret = 0;
694
Clarence Ip3bf8d872017-02-16 15:25:38 -0500695 if (!psde || !psde->scaler3_cfg) {
696 SDE_ERROR("invalid args\n");
697 return -EINVAL;
698 } else if (!pstate) {
699 /* pstate is expected to be null on forced color fill */
700 SDE_DEBUG("null pstate\n");
701 return -EINVAL;
702 }
703
704 cfg = psde->scaler3_cfg;
705
abeykun48f407a2016-08-25 12:06:44 -0400706 cfg->dir_lut = msm_property_get_blob(
707 &psde->property_info,
708 pstate->property_blobs, &cfg->dir_len,
709 PLANE_PROP_SCALER_LUT_ED);
710 cfg->cir_lut = msm_property_get_blob(
711 &psde->property_info,
712 pstate->property_blobs, &cfg->cir_len,
713 PLANE_PROP_SCALER_LUT_CIR);
714 cfg->sep_lut = msm_property_get_blob(
715 &psde->property_info,
716 pstate->property_blobs, &cfg->sep_len,
717 PLANE_PROP_SCALER_LUT_SEP);
718 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
719 ret = -ENODATA;
720 return ret;
721}
722
Clarence Ipcb410d42016-06-26 22:52:33 -0400723static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400724 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
725 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400726 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400727 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
728{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700729 uint32_t decimated, i;
730
731 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
732 !chroma_subsmpl_v) {
733 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
734 , psde, scale_cfg, fmt, chroma_subsmpl_h,
735 chroma_subsmpl_v);
736 return;
737 }
738
739 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip716ab662017-03-20 06:51:24 -0700740 memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700741
742 decimated = DECIMATED_DIMENSION(src_w,
743 psde->pipe_cfg.horz_decimation);
744 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
745 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
746 decimated = DECIMATED_DIMENSION(src_h,
747 psde->pipe_cfg.vert_decimation);
748 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
749 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
750
751
752 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
753 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
754 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
755 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
756
757 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
758 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
759 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
760 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
761
762 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
763 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
764 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
765 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
766
767 for (i = 0; i < SDE_MAX_PLANES; i++) {
768 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
769 psde->pipe_cfg.horz_decimation);
770 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
771 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700772 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
773 scale_cfg->src_width[i] /= chroma_subsmpl_h;
774 scale_cfg->src_height[i] /= chroma_subsmpl_v;
775 }
776 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
777 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
778 psde->pixel_ext.num_ext_pxls_top[i] =
779 scale_cfg->src_height[i];
780 psde->pixel_ext.num_ext_pxls_left[i] =
781 scale_cfg->src_width[i];
782 }
783 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
784 && (src_w == dst_w))
785 return;
786
787 scale_cfg->dst_width = dst_w;
788 scale_cfg->dst_height = dst_h;
789 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
790 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
791 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
792 scale_cfg->lut_flag = 0;
793 scale_cfg->blend_cfg = 1;
794 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -0400795}
796
Clarence Ipcb410d42016-06-26 22:52:33 -0400797/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400798 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400799 * @psde: Pointer to SDE plane object
800 * @src: Source size
801 * @dst: Destination size
802 * @phase_steps: Pointer to output array for phase steps
803 * @filter: Pointer to output array for filter type
804 * @fmt: Pointer to format definition
805 * @chroma_subsampling: Subsampling amount for chroma channel
806 *
807 * Returns: 0 on success
808 */
809static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400810 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400811 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400812 uint32_t chroma_subsampling)
813{
Clarence Ipcb410d42016-06-26 22:52:33 -0400814 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400815 SDE_ERROR(
816 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
817 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400818 return -EINVAL;
819 }
820
Clarence Ip4c1d9772016-06-26 09:35:38 -0400821 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400822 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400823 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400824 phase_steps[SDE_SSPP_COMP_1_2] =
825 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
826 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
827 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400828
829 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400830 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400831 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400832 (src <= dst) ? SDE_SCALE_FILTER_BIL :
833 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400834
Clarence Ipdbde9832016-06-26 09:48:36 -0400835 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400836 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400837 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
838 } else {
839 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
840 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400841 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400842 }
843 } else {
844 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400845 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
846 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
847 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400848 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400849 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400850}
851
Clarence Ipcb410d42016-06-26 22:52:33 -0400852/**
853 * _sde_plane_setup_pixel_ext - determine default pixel extension values
854 * @psde: Pointer to SDE plane object
855 * @src: Source size
856 * @dst: Destination size
857 * @decimated_src: Source size after decimation, if any
858 * @phase_steps: Pointer to output array for phase steps
859 * @out_src: Output array for pixel extension values
860 * @out_edge1: Output array for pixel extension first edge
861 * @out_edge2: Output array for pixel extension second edge
862 * @filter: Pointer to array for filter type
863 * @fmt: Pointer to format definition
864 * @chroma_subsampling: Subsampling amount for chroma channel
865 * @post_compare: Whether to chroma subsampled source size for comparisions
866 */
867static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400868 uint32_t src, uint32_t dst, uint32_t decimated_src,
869 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400870 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400871 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400872 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400873{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400874 int64_t edge1, edge2, caf;
875 uint32_t src_work;
876 int i, tmp;
877
Clarence Ipcb410d42016-06-26 22:52:33 -0400878 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400879 out_edge2 && filter && fmt) {
880 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400881 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400882 caf = PHASE_STEP_UNIT_SCALE;
883 else
884 caf = 0;
885
886 for (i = 0; i < SDE_MAX_PLANES; i++) {
887 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400888 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400889 src_work /= chroma_subsampling;
890 if (post_compare)
891 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400892 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400893 /* unity */
894 edge1 = 0;
895 edge2 = 0;
896 } else if (dst >= src) {
897 /* upscale */
898 edge1 = (1 << PHASE_RESIDUAL);
899 edge1 -= caf;
900 edge2 = (1 << PHASE_RESIDUAL);
901 edge2 += (dst - 1) * *(phase_steps + i);
902 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
903 edge2 += caf;
904 edge2 = -(edge2);
905 } else {
906 /* downscale */
907 edge1 = 0;
908 edge2 = (dst - 1) * *(phase_steps + i);
909 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
910 edge2 += *(phase_steps + i);
911 edge2 = -(edge2);
912 }
913
914 /* only enable CAF for luma plane */
915 caf = 0;
916
917 /* populate output arrays */
918 *(out_src + i) = src_work;
919
920 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400921 if (edge1 >= 0) {
922 tmp = (uint32_t)edge1;
923 tmp >>= PHASE_STEP_SHIFT;
924 *(out_edge1 + i) = -tmp;
925 } else {
926 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400927 *(out_edge1 + i) =
928 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
929 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400930 }
931 if (edge2 >= 0) {
932 tmp = (uint32_t)edge2;
933 tmp >>= PHASE_STEP_SHIFT;
934 *(out_edge2 + i) = -tmp;
935 } else {
936 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400937 *(out_edge2 + i) =
938 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
939 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400940 }
941 }
942 }
943}
944
Clarence Ip5fc00c52016-09-23 15:03:34 -0400945static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400946{
947 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
948 {
Clarence Ip373f8592016-05-26 00:58:42 -0400949 /* S15.16 format */
950 0x00012A00, 0x00000000, 0x00019880,
951 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
952 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400953 },
Clarence Ip373f8592016-05-26 00:58:42 -0400954 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400955 { 0xfff0, 0xff80, 0xff80,},
956 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400957 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400958 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400959 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400960 };
abeykun1c312f62016-08-26 09:47:12 -0400961 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
962 {
963 /* S15.16 format */
964 0x00012A00, 0x00000000, 0x00019880,
965 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
966 0x00012A00, 0x00020480, 0x00000000,
967 },
968 /* signed bias */
969 { 0xffc0, 0xfe00, 0xfe00,},
970 { 0x0, 0x0, 0x0,},
971 /* unsigned clamp */
972 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
973 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
974 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400975
Clarence Ip5fc00c52016-09-23 15:03:34 -0400976 if (!psde) {
977 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400978 return;
979 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400980
Clarence Ipcae1bb62016-07-07 12:07:13 -0400981 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400982 if (psde->csc_usr_ptr)
983 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400984 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
985 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400986 else
Clarence Ip373f8592016-05-26 00:58:42 -0400987 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400988
Clarence Ip13a8cf42016-09-29 17:27:47 -0400989 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400990 psde->csc_ptr->csc_mv[0],
991 psde->csc_ptr->csc_mv[1],
992 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400993}
994
Benet Clarkeb1b4462016-06-27 14:43:06 -0700995static void sde_color_process_plane_setup(struct drm_plane *plane)
996{
997 struct sde_plane *psde;
998 struct sde_plane_state *pstate;
999 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001000 struct drm_msm_memcol *memcol = NULL;
1001 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001002
1003 psde = to_sde_plane(plane);
1004 pstate = to_sde_plane_state(plane->state);
1005
1006 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1007 if (psde->pipe_hw->ops.setup_pa_hue)
1008 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1009 saturation = (uint32_t) sde_plane_get_property(pstate,
1010 PLANE_PROP_SATURATION_ADJUST);
1011 if (psde->pipe_hw->ops.setup_pa_sat)
1012 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1013 value = (uint32_t) sde_plane_get_property(pstate,
1014 PLANE_PROP_VALUE_ADJUST);
1015 if (psde->pipe_hw->ops.setup_pa_val)
1016 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1017 contrast = (uint32_t) sde_plane_get_property(pstate,
1018 PLANE_PROP_CONTRAST_ADJUST);
1019 if (psde->pipe_hw->ops.setup_pa_cont)
1020 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001021
Benet Clarkd009b1d2016-06-27 14:45:59 -07001022 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1023 /* Skin memory color setup */
1024 memcol = msm_property_get_blob(&psde->property_info,
1025 pstate->property_blobs,
1026 &memcol_sz,
1027 PLANE_PROP_SKIN_COLOR);
1028 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1029 MEMCOLOR_SKIN, memcol);
1030
1031 /* Sky memory color setup */
1032 memcol = msm_property_get_blob(&psde->property_info,
1033 pstate->property_blobs,
1034 &memcol_sz,
1035 PLANE_PROP_SKY_COLOR);
1036 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1037 MEMCOLOR_SKY, memcol);
1038
1039 /* Foliage memory color setup */
1040 memcol = msm_property_get_blob(&psde->property_info,
1041 pstate->property_blobs,
1042 &memcol_sz,
1043 PLANE_PROP_FOLIAGE_COLOR);
1044 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1045 MEMCOLOR_FOLIAGE, memcol);
1046 }
1047}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001048
Clarence Ipcb410d42016-06-26 22:52:33 -04001049static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001050 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -04001051 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001052{
Clarence Ipb43d4592016-09-08 14:21:35 -04001053 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001054 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001055
Clarence Ipb43d4592016-09-08 14:21:35 -04001056 if (!psde || !fmt) {
1057 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1058 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001059 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001060 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001061
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001062 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001063
Clarence Ipdedbba92016-09-27 17:43:10 -04001064 psde->pipe_cfg.horz_decimation =
1065 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1066 psde->pipe_cfg.vert_decimation =
1067 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001068
1069 /* don't chroma subsample if decimating */
1070 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001071 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001072 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001073 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001074
Clarence Ip5e2a9222016-06-26 22:38:24 -04001075 /* update scaler */
1076 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001077 int error;
1078
1079 error = _sde_plane_setup_scaler3_lut(psde, pstate);
Clarence Ip716ab662017-03-20 06:51:24 -07001080 if (error || !psde->pixel_ext_usr ||
1081 psde->debugfs_default_scale) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001082 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001083 _sde_plane_setup_scaler3(psde,
1084 psde->pipe_cfg.src_rect.w,
1085 psde->pipe_cfg.src_rect.h,
1086 psde->pipe_cfg.dst_rect.w,
1087 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001088 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001089 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001090 }
Clarence Ip716ab662017-03-20 06:51:24 -07001091 } else if (!psde->pixel_ext_usr || !pstate ||
1092 psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001093 uint32_t deci_dim, i;
1094
Clarence Ipb43d4592016-09-08 14:21:35 -04001095 /* calculate default configuration for QSEED2 */
1096 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001097
Clarence Ip13a8cf42016-09-29 17:27:47 -04001098 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001099 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1100 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001101 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001102 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001103 psde->pipe_cfg.dst_rect.w,
1104 pe->phase_step_x,
1105 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001106
Clarence Ipdbde9832016-06-26 09:48:36 -04001107 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001108 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001109 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001110 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001111 pe->phase_step_x,
1112 pe->roi_w,
1113 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001114 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001115 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001116
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001117 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001118 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001119 _sde_plane_setup_scaler2(psde,
1120 deci_dim,
1121 psde->pipe_cfg.dst_rect.h,
1122 pe->phase_step_y,
1123 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001124 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001125 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001126 pe->phase_step_y,
1127 pe->roi_h,
1128 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001129 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001130 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001131
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001132 for (i = 0; i < SDE_MAX_PLANES; i++) {
1133 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001134 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001135 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001136 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001137
1138 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001139 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001140 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001141 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001142
1143 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001144 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001145 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001146 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001147
1148 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001149 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001150 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001151 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001152 }
1153 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001154}
1155
Clarence Ipcae1bb62016-07-07 12:07:13 -04001156/**
1157 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001158 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001159 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1160 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1161 * Returns: 0 on success
1162 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001163static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001164 uint32_t color, uint32_t alpha)
1165{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001166 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001167 const struct drm_plane *plane;
1168 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001169
Clarence Ip13a8cf42016-09-29 17:27:47 -04001170 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001171 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001172 return -EINVAL;
1173 }
1174
Clarence Ipcb410d42016-06-26 22:52:33 -04001175 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001176 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001177 return -EINVAL;
1178 }
1179
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001180 plane = &psde->base;
1181 pstate = to_sde_plane_state(plane->state);
1182
Clarence Ip13a8cf42016-09-29 17:27:47 -04001183 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001184
Clarence Ipcb410d42016-06-26 22:52:33 -04001185 /*
1186 * select fill format to match user property expectation,
1187 * h/w only supports RGB variants
1188 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001189 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001190
1191 /* update sspp */
1192 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1193 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001194 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1195 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001196
1197 /* override scaler/decimation if solid fill */
1198 psde->pipe_cfg.src_rect.x = 0;
1199 psde->pipe_cfg.src_rect.y = 0;
1200 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1201 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Dhaval Patele4b6bb22017-03-27 17:22:21 -07001202 _sde_plane_setup_scaler(psde, fmt, 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001203
Clarence Ipcb410d42016-06-26 22:52:33 -04001204 if (psde->pipe_hw->ops.setup_format)
1205 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001206 fmt, SDE_SSPP_SOLID_FILL,
1207 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001208
1209 if (psde->pipe_hw->ops.setup_rects)
1210 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001211 &psde->pipe_cfg,
1212 pstate->multirect_index);
1213
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001214 if (psde->pipe_hw->ops.setup_pe)
1215 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1216 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001217 }
1218
1219 return 0;
1220}
1221
Alan Kwong4dd64c82017-02-04 18:41:51 -08001222/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001223 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1224 */
1225static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1226{
1227 drm_framebuffer_reference(fb);
1228 return fb;
1229}
1230static void _sde_plane_fb_put(void *fb)
1231{
1232 drm_framebuffer_unreference(fb);
1233}
1234static struct sde_crtc_res_ops fb_res_ops = {
1235 .put = _sde_plane_fb_put,
1236 .get = _sde_plane_fb_get,
1237};
1238
1239/**
1240 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1241 */
1242static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1243{
1244 sde_kms_fbo_reference(fbo);
1245 return fbo;
1246}
1247static void _sde_plane_fbo_put(void *fbo)
1248{
1249 sde_kms_fbo_unreference(fbo);
1250}
1251static struct sde_crtc_res_ops fbo_res_ops = {
1252 .put = _sde_plane_fbo_put,
1253 .get = _sde_plane_fbo_get,
1254};
1255
1256/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001257 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001258 * @plane: Pointer to drm plane
1259 * return: prefill time in line
1260 */
1261static u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
1262{
1263 struct drm_plane_state *state;
1264 struct drm_crtc_state *cstate;
1265 struct sde_plane_state *pstate;
1266 struct sde_plane_rot_state *rstate;
1267 struct sde_kms *sde_kms;
1268 u32 blocksize = 128;
1269 u32 prefill_line = 0;
1270
1271 if (!plane || !plane->state || !plane->state->fb ||
1272 !plane->state->crtc || !plane->state->crtc->state) {
1273 SDE_ERROR("invalid parameters\n");
1274 return 0;
1275 }
1276
1277 sde_kms = _sde_plane_get_kms(plane);
1278 state = plane->state;
1279 cstate = state->crtc->state;
1280 pstate = to_sde_plane_state(state);
1281 rstate = &pstate->rot;
1282
1283 if (!rstate->rot_hw || !rstate->rot_hw->caps || !rstate->out_src_h ||
1284 !sde_kms || !sde_kms->catalog) {
1285 SDE_ERROR("invalid parameters\n");
1286 return 0;
1287 }
1288
Alan Kwong4aacd532017-02-04 18:51:33 -08001289 sde_format_get_block_size(rstate->out_fb_format, &blocksize,
1290 &blocksize);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001291 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
1292
1293 SDE_DEBUG("plane%d prefill:%u\n", plane->base.id, prefill_line);
1294
1295 return prefill_line;
1296}
1297
1298/**
1299 * sde_plane_is_sbuf_mode - check if sspp of given plane is in streaming
1300 * buffer mode
1301 * @plane: Pointer to drm plane
1302 * @prefill: Pointer to prefill line count
1303 * return: true if sspp is in stream buffer mode
1304 */
1305bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill)
1306{
1307 struct sde_plane_state *pstate = plane && plane->state ?
1308 to_sde_plane_state(plane->state) : NULL;
1309 struct sde_plane_rot_state *rstate = pstate ? &pstate->rot : NULL;
1310 bool sbuf_mode = rstate ? rstate->out_sbuf : false;
1311
1312 if (prefill && sbuf_mode)
1313 *prefill = sde_plane_rot_calc_prefill(plane);
1314
1315 return sbuf_mode;
1316}
1317
1318/**
1319 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1320 * enumerating over all planes attached to the same rotator
1321 * @plane: Pointer to drm plane
1322 * @state: Pointer to drm state to be updated
1323 * return: none
1324 */
1325static void sde_plane_rot_calc_cfg(struct drm_plane *plane,
1326 struct drm_plane_state *state)
1327{
1328 struct sde_plane_state *pstate;
1329 struct sde_plane_rot_state *rstate;
1330 struct sde_hw_blk *hw_blk;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001331 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001332 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001333 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001334 u32 dst_x, dst_y, dst_w, dst_h;
1335 int found = 0;
1336 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001337 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001338
1339 if (!plane || !state || !state->state) {
1340 SDE_ERROR("invalid parameters\n");
1341 return;
1342 }
1343
Alan Kwongcdb2f282017-03-18 13:42:06 -07001344 cstate = _sde_plane_get_crtc_state(state);
1345 if (IS_ERR_OR_NULL(cstate)) {
1346 ret = PTR_ERR(cstate);
1347 SDE_ERROR("invalid crtc state %d\n", ret);
1348 return;
1349 }
1350
Alan Kwong4dd64c82017-02-04 18:41:51 -08001351 pstate = to_sde_plane_state(state);
1352 rstate = &pstate->rot;
1353
1354 if (!rstate->rot_hw) {
1355 SDE_ERROR("invalid rotator hw\n");
1356 return;
1357 }
1358
1359 in_rot = &rstate->in_rot_rect;
1360 in_rot->x1 = state->src_x;
1361 in_rot->y1 = state->src_y;
1362 in_rot->x2 = state->src_x + state->src_w;
1363 in_rot->y2 = state->src_y + state->src_h;
1364
1365 out_rot = &rstate->out_rot_rect;
1366 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1367 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1368 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1369 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1370
1371 if (!dst_w && !dst_h) {
1372 rstate->out_rot_rect = rstate->in_rot_rect;
1373 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1374 state->fb->height << 16, rstate->in_rotation);
1375 } else {
1376 out_rot->x1 = dst_x;
1377 out_rot->y1 = dst_y;
1378 out_rot->x2 = dst_x + dst_w;
1379 out_rot->y2 = dst_y + dst_h;
1380 }
1381
1382 rstate->out_src_rect = rstate->out_rot_rect;
1383
1384 hw_blk = &rstate->rot_hw->base;
1385
1386 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001387 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001388 struct drm_plane_state *attached_state;
1389 struct sde_plane_state *attached_pstate;
1390 struct sde_plane_rot_state *attached_rstate;
1391 struct drm_rect attached_out_rect;
1392
Alan Kwong4dd64c82017-02-04 18:41:51 -08001393 attached_state = drm_atomic_get_existing_plane_state(
1394 state->state, attached_plane);
1395
1396 if (!attached_state)
1397 continue;
1398
1399 attached_pstate = to_sde_plane_state(attached_state);
1400 attached_rstate = &attached_pstate->rot;
1401
Alan Kwongcdb2f282017-03-18 13:42:06 -07001402 if (attached_rstate->rot_hw != rstate->rot_hw)
1403 continue;
1404
1405 found++;
1406
1407 /* skip itself */
1408 if (attached_plane == plane)
1409 continue;
1410
Alan Kwong4dd64c82017-02-04 18:41:51 -08001411 /* find bounding rotator source roi */
1412 if (attached_state->src_x < in_rot->x1)
1413 in_rot->x1 = attached_state->src_x;
1414
1415 if (attached_state->src_y < in_rot->y1)
1416 in_rot->y1 = attached_state->src_y;
1417
1418 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1419 in_rot->x2 = attached_state->src_x +
1420 attached_state->src_w;
1421
1422 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1423 in_rot->y2 = attached_state->src_y +
1424 attached_state->src_h;
1425
1426 /* find bounding rotator destination roi */
1427 dst_x = sde_plane_get_property(attached_pstate,
1428 PLANE_PROP_ROT_DST_X);
1429 dst_y = sde_plane_get_property(attached_pstate,
1430 PLANE_PROP_ROT_DST_Y);
1431 dst_w = sde_plane_get_property(attached_pstate,
1432 PLANE_PROP_ROT_DST_W);
1433 dst_h = sde_plane_get_property(attached_pstate,
1434 PLANE_PROP_ROT_DST_H);
1435 if (!dst_w && !dst_h) {
1436 attached_out_rect.x1 = attached_state->src_x;
1437 attached_out_rect.y1 = attached_state->src_y;
1438 attached_out_rect.x2 = attached_out_rect.x1 +
1439 attached_state->src_w;
1440 attached_out_rect.y2 = attached_out_rect.y1 +
1441 attached_state->src_h;
1442 drm_rect_rotate(&attached_out_rect,
1443 state->fb->width << 16,
1444 state->fb->height << 16,
1445 rstate->in_rotation);
1446 } else {
1447 attached_out_rect.x1 = dst_x;
1448 attached_out_rect.y1 = dst_y;
1449 attached_out_rect.x2 = dst_x + dst_w;
1450 attached_out_rect.y2 = dst_y + dst_h;
1451 }
1452
1453 /* find relative sspp position */
1454 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1455 xpos++;
1456
1457 if (attached_out_rect.x1 < out_rot->x1)
1458 out_rot->x1 = attached_out_rect.x1;
1459
1460 if (attached_out_rect.y1 < out_rot->y1)
1461 out_rot->y1 = attached_out_rect.y1;
1462
1463 if (attached_out_rect.x2 > out_rot->x2)
1464 out_rot->x2 = attached_out_rect.x2;
1465
1466 if (attached_out_rect.y2 > out_rot->y2)
1467 out_rot->y2 = attached_out_rect.y2;
1468
1469 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1470 attached_plane->base.id,
1471 attached_rstate->sequence_id,
1472 attached_rstate->out_src_rect.x1 >> 16,
1473 attached_state->src_w >> 16,
1474 attached_state->src_h >> 16,
1475 attached_state->src_x >> 16,
1476 attached_state->src_y >> 16,
1477 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1478 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1479 attached_rstate->out_src_rect.x1 >> 16,
1480 attached_rstate->out_src_rect.y1 >> 16);
1481 }
1482
1483 rstate->out_xpos = xpos;
1484 rstate->nplane = found;
1485
1486 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1487 plane->base.id, rstate->sequence_id,
1488 rstate->out_xpos, rstate->nplane,
1489 drm_rect_width(in_rot) >> 16,
1490 drm_rect_height(in_rot) >> 16,
1491 in_rot->x1 >> 16, in_rot->y1 >> 16,
1492 drm_rect_width(&rstate->out_rot_rect) >> 16,
1493 drm_rect_height(&rstate->out_rot_rect) >> 16,
1494 rstate->out_rot_rect.x1 >> 16,
1495 rstate->out_rot_rect.y1 >> 16);
1496}
1497
1498/**
1499 * sde_plane_rot_submit_command - commit given state for the rotator stage
1500 * @plane: Pointer to drm plane
1501 * @state: Pointer to the state to be committed
1502 * @hw_cmd: rotator command type
1503 * return: 0 if success; error code otherwise
1504 */
1505static int sde_plane_rot_submit_command(struct drm_plane *plane,
1506 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1507{
1508 struct sde_plane *psde = to_sde_plane(plane);
1509 struct sde_plane_state *pstate = to_sde_plane_state(state);
1510 struct sde_plane_rot_state *rstate = &pstate->rot;
1511 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001512 struct drm_crtc_state *cstate;
1513 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001514 int ret, i;
1515
1516 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1517 SDE_ERROR("invalid parameters\n");
1518 return -EINVAL;
1519 }
1520
Alan Kwong4aacd532017-02-04 18:51:33 -08001521 cstate = _sde_plane_get_crtc_state(state);
1522 if (IS_ERR_OR_NULL(cstate)) {
1523 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1524 return -EINVAL;
1525 }
1526 sde_cstate = to_sde_crtc_state(cstate);
1527
Alan Kwong4dd64c82017-02-04 18:41:51 -08001528 rot_cmd = &rstate->rot_cmd;
1529
1530 rot_cmd->master = (rstate->out_xpos == 0);
1531 rot_cmd->sequence_id = rstate->sequence_id;
1532 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1533 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1534 DEFAULT_REFRESH_RATE;
1535 rot_cmd->rot90 = rstate->rot90;
1536 rot_cmd->hflip = rstate->hflip;
1537 rot_cmd->vflip = rstate->vflip;
1538 rot_cmd->secure = state->fb->flags & DRM_MODE_FB_SECURE ? true : false;
Alan Kwong4aacd532017-02-04 18:51:33 -08001539 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1540 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001541 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1542 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001543 rot_cmd->dst_writeback = psde->sbuf_writeback;
1544
1545 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1546 rot_cmd->video_mode = true;
1547 else
1548 rot_cmd->video_mode = false;
1549
1550 rot_cmd->src_pixel_format = state->fb->pixel_format;
1551 rot_cmd->src_modifier = state->fb->modifier[0];
1552 rot_cmd->src_stride = state->fb->pitches[0];
1553
1554 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1555 if (!rot_cmd->src_format) {
1556 SDE_ERROR("failed to get src format\n");
1557 return -EINVAL;
1558 }
1559
1560 rot_cmd->src_width = state->fb->width;
1561 rot_cmd->src_height = state->fb->height;
1562 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1563 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1564 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1565 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
1566 rot_cmd->dst_rect_x = rstate->out_rot_rect.x1 >> 16;
1567 rot_cmd->dst_rect_y = rstate->out_rot_rect.y1 >> 16;
1568 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1569 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1570
1571 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1572 struct sde_hw_fmt_layout layout;
1573
1574 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1575 sde_format_populate_layout(rstate->mmu_id, state->fb,
1576 &layout);
1577 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1578 rot_cmd->src_iova[i] = layout.plane_addr[i];
1579 rot_cmd->src_len[i] = layout.plane_size[i];
1580 }
1581 rot_cmd->src_planes = layout.num_planes;
1582
1583 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1584 sde_format_populate_layout(rstate->mmu_id, rstate->out_fb,
1585 &layout);
1586 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1587 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1588 rot_cmd->dst_len[i] = layout.plane_size[i];
1589 }
1590 rot_cmd->dst_planes = layout.num_planes;
1591 }
1592
1593 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
1594 if (ret) {
1595 SDE_ERROR("failed to commit rotator %d\n", ret);
1596 return ret;
1597 }
1598
1599 rstate->out_rotation = rstate->in_rotation;
1600 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1601 DRM_MODE_FB_MODIFIERS : 0;
1602 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1603 rstate->out_fb_format = rot_cmd->dst_format;
1604 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1605
1606 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1607 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1608
1609 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1610 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1611 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1612 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1613 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1614 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1615
1616 if (rot_cmd->rot90)
1617 rstate->out_rotation &= ~DRM_ROTATE_90;
1618
1619 if (rot_cmd->hflip)
1620 rstate->out_rotation &= ~DRM_REFLECT_X;
1621
1622 if (rot_cmd->vflip)
1623 rstate->out_rotation &= ~DRM_REFLECT_Y;
1624
1625 SDE_DEBUG(
1626 "plane%d.%d rot:%d/%c%c%c%c/%dx%d/%c%c%c%c/%llx/%dx%d+%d+%d\n",
1627 plane->base.id, rstate->sequence_id, hw_cmd,
1628 rot_cmd->rot90 ? 'r' : '_',
1629 rot_cmd->hflip ? 'h' : '_',
1630 rot_cmd->vflip ? 'v' : '_',
1631 rot_cmd->video_mode ? 'V' : 'C',
1632 state->fb->width, state->fb->height,
1633 state->fb->pixel_format >> 0,
1634 state->fb->pixel_format >> 8,
1635 state->fb->pixel_format >> 16,
1636 state->fb->pixel_format >> 24,
1637 state->fb->modifier[0],
1638 drm_rect_width(&rstate->in_rot_rect) >> 16,
1639 drm_rect_height(&rstate->in_rot_rect) >> 16,
1640 rstate->in_rot_rect.x1 >> 16,
1641 rstate->in_rot_rect.y1 >> 16);
1642
1643 SDE_DEBUG("plane%d.%d sspp:%d/%x/%dx%d/%c%c%c%c/%llx/%dx%d+%d+%d\n",
1644 plane->base.id, rstate->sequence_id, hw_cmd,
1645 rstate->out_rotation,
1646 rstate->out_fb_width, rstate->out_fb_height,
1647 rstate->out_fb_pixel_format >> 0,
1648 rstate->out_fb_pixel_format >> 8,
1649 rstate->out_fb_pixel_format >> 16,
1650 rstate->out_fb_pixel_format >> 24,
1651 rstate->out_fb_modifier[0],
1652 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
1653 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
1654
1655 return ret;
1656}
1657
1658/**
1659 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
1660 * for rotator (pre-sspp) stage
1661 * @plane: Pointer to drm plane
1662 * @new_state: Pointer to new drm plane state
1663 * return: 0 if success; error code otherwise
1664 */
1665static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
1666 struct drm_plane_state *new_state)
1667{
1668 struct drm_framebuffer *fb = new_state->fb;
1669 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
1670 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001671 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001672 int ret;
1673
1674 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
1675 plane->base.id,
1676 new_rstate->sequence_id, fb ? fb->base.id : 0,
1677 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
1678 sde_plane_crtc_enabled(new_state));
1679
1680 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
1681 return 0;
1682
Alan Kwongcdb2f282017-03-18 13:42:06 -07001683 cstate = _sde_plane_get_crtc_state(new_state);
1684 if (IS_ERR(cstate)) {
1685 ret = PTR_ERR(cstate);
1686 SDE_ERROR("invalid crtc state %d\n", ret);
1687 return ret;
1688 }
1689
Alan Kwong4dd64c82017-02-04 18:41:51 -08001690 /* need to re-calc based on all newly validated plane states */
1691 sde_plane_rot_calc_cfg(plane, new_state);
1692
1693 /* check if stream buffer is already attached to rotator */
1694 if (sde_plane_enabled(new_state)) {
1695 struct sde_kms_fbo *fbo;
1696 struct drm_framebuffer *fb;
1697
Alan Kwongcdb2f282017-03-18 13:42:06 -07001698 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1699 (u64) &new_rstate->rot_hw->base);
1700 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1701 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001702 if (fb && fbo) {
1703 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
1704 new_rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001705 } else if (fbo) {
1706 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1707 (u64) &new_rstate->rot_hw->base);
1708 fbo = NULL;
1709 } else if (fb) {
1710 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1711 (u64) &new_rstate->rot_hw->base);
1712 fb = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001713 }
Alan Kwongcdb2f282017-03-18 13:42:06 -07001714
1715 new_rstate->out_fbo = fbo;
1716 new_rstate->out_fb = fb;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001717 }
1718
1719 /* release buffer if output format configuration changes */
1720 if (new_rstate->out_fb &&
1721 ((new_rstate->out_fb_height != new_rstate->out_fb->height) ||
1722 (new_rstate->out_fb_width != new_rstate->out_fb->width) ||
1723 (new_rstate->out_fb_pixel_format !=
1724 new_rstate->out_fb->pixel_format) ||
1725 (new_rstate->out_fb_modifier[0] !=
1726 new_rstate->out_fb->modifier[0]) ||
1727 (new_rstate->out_fb_flags != new_rstate->out_fb->flags))) {
1728
1729 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
1730 new_rstate->sequence_id);
1731
Alan Kwongcdb2f282017-03-18 13:42:06 -07001732 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1733 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001734 new_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001735 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1736 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001737 new_rstate->out_fbo = NULL;
1738 }
1739
1740 /* create new stream buffer if it is not available */
1741 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
1742 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
1743 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
1744
1745 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
1746 new_rstate->sequence_id);
1747
1748 if (new_state->fb->flags & DRM_MODE_FB_SECURE)
1749 new_rstate->mmu_id = MSM_SMMU_DOMAIN_SECURE;
1750 else
1751 new_rstate->mmu_id = MSM_SMMU_DOMAIN_UNSECURE;
1752
1753 /* check if out_fb is already attached to rotator */
1754 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
1755 new_rstate->out_fb_pixel_format,
1756 new_rstate->out_fb_modifier,
1757 new_rstate->out_fb_flags);
1758 if (!new_rstate->out_fbo) {
1759 SDE_ERROR("failed to allocate inline buffer object\n");
1760 ret = -EINVAL;
1761 goto error_create_fbo;
1762 }
1763
Alan Kwongcdb2f282017-03-18 13:42:06 -07001764 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1765 (u64) &new_rstate->rot_hw->base,
1766 new_rstate->out_fbo, &fbo_res_ops);
1767 if (ret) {
1768 SDE_ERROR("failed to add crtc resource\n");
1769 goto error_create_fbo_res;
1770 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001771
1772 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
1773 new_rstate->out_fbo);
1774 if (!new_rstate->out_fb) {
1775 SDE_ERROR("failed to create inline framebuffer\n");
1776 ret = -EINVAL;
1777 goto error_create_fb;
1778 }
1779
Alan Kwongcdb2f282017-03-18 13:42:06 -07001780 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1781 (u64) &new_rstate->rot_hw->base,
1782 new_rstate->out_fb, &fb_res_ops);
1783 if (ret) {
1784 SDE_ERROR("failed to add crtc resource %d\n", ret);
1785 goto error_create_fb_res;
1786 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001787 }
1788
1789 /* prepare rotator input buffer */
1790 ret = msm_framebuffer_prepare(new_state->fb, new_rstate->mmu_id);
1791 if (ret) {
1792 SDE_ERROR("failed to prepare input framebuffer\n");
1793 goto error_prepare_input_buffer;
1794 }
1795
1796 /* prepare rotator output buffer */
1797 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
1798 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
1799 new_rstate->sequence_id);
1800
1801 ret = msm_framebuffer_prepare(new_rstate->out_fb,
1802 new_rstate->mmu_id);
1803 if (ret) {
1804 SDE_ERROR("failed to prepare inline framebuffer\n");
1805 goto error_prepare_output_buffer;
1806 }
1807 }
1808
1809 return 0;
1810
1811error_prepare_output_buffer:
1812 msm_framebuffer_cleanup(new_state->fb, new_rstate->mmu_id);
1813error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001814 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1815 (u64) &new_rstate->rot_hw->base);
1816error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001817 new_rstate->out_fb = NULL;
1818error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001819 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1820 (u64) &new_rstate->rot_hw->base);
1821error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001822 new_rstate->out_fbo = NULL;
1823error_create_fbo:
1824 return ret;
1825}
1826
1827/**
1828 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
1829 * rotator (pre-sspp) stage
1830 * @plane: Pointer to drm plane
1831 * @old_state: Pointer to previous drm plane state
1832 * return: none
1833 */
1834static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
1835 struct drm_plane_state *old_state)
1836{
1837 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
1838 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
1839 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001840 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001841 int ret;
1842
1843 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1844 old_rstate->sequence_id, old_state->fb->base.id,
1845 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
1846 sde_plane_crtc_enabled(old_state));
1847
1848 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
1849 return;
1850
Alan Kwongcdb2f282017-03-18 13:42:06 -07001851 cstate = _sde_plane_get_crtc_state(old_state);
1852 if (IS_ERR(cstate)) {
1853 ret = PTR_ERR(cstate);
1854 SDE_ERROR("invalid crtc state %d\n", ret);
1855 return;
1856 }
1857
Alan Kwong4dd64c82017-02-04 18:41:51 -08001858 if (sde_plane_crtc_enabled(old_state)) {
1859 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
1860 SDE_HW_ROT_CMD_CLEANUP);
1861 if (ret)
1862 SDE_ERROR("failed to cleanup rotator buffers\n");
1863 }
1864
1865 if (sde_plane_enabled(old_state)) {
1866 if (old_rstate->out_fb) {
1867 msm_framebuffer_cleanup(old_rstate->out_fb,
1868 old_rstate->mmu_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001869 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1870 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001871 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001872 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1873 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001874 old_rstate->out_fbo = NULL;
1875 }
1876
1877 msm_framebuffer_cleanup(old_state->fb, old_rstate->mmu_id);
1878 }
1879}
1880
1881/**
1882 * sde_plane_rot_atomic_check - verify rotator update of the given state
1883 * @plane: Pointer to drm plane
1884 * @state: Pointer to drm plane state to be validated
1885 * return: 0 if success; error code otherwise
1886 */
1887static int sde_plane_rot_atomic_check(struct drm_plane *plane,
1888 struct drm_plane_state *state)
1889{
1890 struct sde_plane *psde;
1891 struct sde_plane_state *pstate, *old_pstate;
1892 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001893 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001894 struct sde_hw_blk *hw_blk;
1895 int i, ret = 0;
1896
1897 if (!plane || !state) {
1898 SDE_ERROR("invalid plane/state\n");
1899 return -EINVAL;
1900 }
1901
1902 psde = to_sde_plane(plane);
1903 pstate = to_sde_plane_state(state);
1904 old_pstate = to_sde_plane_state(plane->state);
1905 rstate = &pstate->rot;
1906 old_rstate = &old_pstate->rot;
1907
Alan Kwongcdb2f282017-03-18 13:42:06 -07001908 /* cstate will be null if crtc is disconnected from plane */
1909 cstate = _sde_plane_get_crtc_state(state);
1910 if (IS_ERR(cstate)) {
1911 ret = PTR_ERR(cstate);
1912 SDE_ERROR("invalid crtc state %d\n", ret);
1913 return ret;
1914 }
1915
Alan Kwong4dd64c82017-02-04 18:41:51 -08001916 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1917 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
1918 !!rstate->out_sbuf, !!rstate->rot_hw,
1919 sde_plane_crtc_enabled(state));
1920
1921 rstate->in_rotation = drm_rotation_simplify(
1922 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07001923 DRM_ROTATE_0 | DRM_ROTATE_90 |
1924 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001925 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
1926 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
1927 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
1928 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
1929
Alan Kwongcdb2f282017-03-18 13:42:06 -07001930 if (sde_plane_enabled(state) && rstate->out_sbuf) {
1931 SDE_DEBUG("plane%d.%d acquire rotator\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001932 plane->base.id, rstate->sequence_id);
1933
Alan Kwongcdb2f282017-03-18 13:42:06 -07001934 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
1935 (u64) state->fb);
1936 if (!hw_blk) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001937 SDE_ERROR("plane%d no available rotator\n",
1938 plane->base.id);
1939 return -EINVAL;
1940 }
1941
Alan Kwongcdb2f282017-03-18 13:42:06 -07001942 rstate->rot_hw = to_sde_hw_rot(hw_blk);
1943
Alan Kwong4dd64c82017-02-04 18:41:51 -08001944 if (!rstate->rot_hw->ops.commit) {
1945 SDE_ERROR("plane%d invalid rotator ops\n",
1946 plane->base.id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001947 sde_crtc_res_put(cstate,
1948 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001949 rstate->rot_hw = NULL;
1950 return -EINVAL;
1951 }
1952
1953 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001954 } else {
1955 rstate->in_fb = NULL;
1956 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001957 }
1958
1959 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
1960
1961 SDE_DEBUG("plane%d.%d use rotator\n",
1962 plane->base.id, rstate->sequence_id);
1963
1964 sde_plane_rot_calc_cfg(plane, state);
1965
1966 ret = sde_plane_rot_submit_command(plane, state,
1967 SDE_HW_ROT_CMD_VALIDATE);
1968
1969 } else if (sde_plane_enabled(state)) {
1970
1971 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
1972 rstate->sequence_id);
1973
1974 /* bypass rotator - initialize output setting as input */
1975 rstate->out_rotation = rstate->in_rotation;
1976 rstate->out_fb_pixel_format = state->fb->pixel_format;
1977
1978 for (i = 0.; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1979 rstate->out_fb_modifier[i] = state->fb->modifier[i];
1980
1981 rstate->out_fb_flags = state->fb->flags;
1982 rstate->out_fb_width = state->fb->width;
1983 rstate->out_fb_height = state->fb->height;
1984 rstate->out_src_x = state->src_x;
1985 rstate->out_src_y = state->src_y;
1986 rstate->out_src_w = state->src_w;
1987 rstate->out_src_h = state->src_h;
1988
1989 rstate->out_fb_format = NULL;
1990 rstate->out_sbuf = false;
1991 rstate->out_fb = state->fb;
1992 }
1993
1994 return ret;
1995}
1996
1997/**
1998 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
1999 * @plane: Pointer to drm plane
2000 * @old_state: Pointer to previous state
2001 * return: none
2002 */
2003static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2004 struct drm_plane_state *old_state)
2005{
2006 struct drm_plane_state *state;
2007 struct sde_plane_state *pstate;
2008 struct sde_plane_rot_state *rstate;
2009
2010 if (!plane || !plane->state) {
2011 SDE_ERROR("invalid plane/state\n");
2012 return;
2013 }
2014
2015 state = plane->state;
2016 pstate = to_sde_plane_state(state);
2017 rstate = &pstate->rot;
2018
2019 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2020 rstate->sequence_id,
2021 !!rstate->out_sbuf, !!rstate->rot_hw,
2022 sde_plane_crtc_enabled(plane->state));
2023
2024 if (!sde_plane_crtc_enabled(state))
2025 return;
2026
2027 if (!rstate->out_sbuf || !rstate->rot_hw)
2028 return;
2029
2030 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
2031}
2032
2033/**
2034 * sde_plane_rot_destroy_state - destroy state for rotator stage
2035 * @plane: Pointer to drm plane
2036 * @state: Pointer to state to be destroyed
2037 * return: none
2038 */
2039static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2040 struct drm_plane_state *state)
2041{
2042 struct sde_plane_state *pstate = to_sde_plane_state(state);
2043 struct sde_plane_rot_state *rstate = &pstate->rot;
2044
2045 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2046 rstate->sequence_id,
2047 !!rstate->out_sbuf, !!rstate->rot_hw,
2048 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002049}
2050
2051/**
2052 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2053 * @plane: Pointer to drm plane
2054 * @new_state: Pointer to duplicated state
2055 * return: 0 if success; error code otherwise
2056 */
2057static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2058 struct drm_plane_state *new_state)
2059{
2060 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2061 struct sde_plane_rot_state *rstate = &pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002062 struct drm_crtc_state *cstate;
2063 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002064
2065 rstate->sequence_id++;
2066
2067 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2068 rstate->sequence_id,
2069 !!rstate->out_sbuf, !!rstate->rot_hw);
2070
Alan Kwongcdb2f282017-03-18 13:42:06 -07002071 cstate = _sde_plane_get_crtc_state(new_state);
2072 if (IS_ERR(cstate)) {
2073 ret = PTR_ERR(cstate);
2074 SDE_ERROR("invalid crtc state %d\n", ret);
2075 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002076 }
2077
Alan Kwongcdb2f282017-03-18 13:42:06 -07002078 if (rstate->rot_hw && cstate)
2079 sde_crtc_res_get(cstate, SDE_HW_BLK_ROT, (u64) rstate->in_fb);
2080 else if (rstate->rot_hw && !cstate)
2081 SDE_ERROR("plane%d.%d zombie rotator hw\n",
2082 plane->base.id, rstate->sequence_id);
2083
Alan Kwong4dd64c82017-02-04 18:41:51 -08002084 rstate->out_fb = NULL;
2085 rstate->out_fbo = NULL;
2086
2087 return 0;
2088}
2089
2090/**
2091 * sde_plane_rot_install_caps - install plane rotator capabilities
2092 * @plane: Pointer to drm plane
2093 * return: none
2094 */
2095static void sde_plane_rot_install_caps(struct drm_plane *plane)
2096{
2097 struct sde_plane *psde = to_sde_plane(plane);
2098 const struct sde_format_extended *format_list;
2099 struct sde_kms_info *info;
2100 struct sde_hw_rot *rot_hw;
2101 const char *downscale_caps;
2102
2103 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2104 !psde->catalog->rot_count)
2105 return;
2106
2107 if (psde->blob_rot_caps)
2108 return;
2109
2110 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2111 if (!info)
2112 return;
2113
2114 rot_hw = sde_hw_rot_get(NULL);
2115 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2116 !rot_hw->ops.get_downscale_caps) {
2117 SDE_ERROR("invalid rotator hw\n");
2118 goto error_rot;
2119 }
2120
2121 sde_kms_info_reset(info);
2122
2123 format_list = rot_hw->ops.get_format_caps(rot_hw);
2124 if (format_list) {
2125 sde_kms_info_start(info, "pixel_formats");
2126 while (format_list->fourcc_format) {
2127 sde_kms_info_append_format(info,
2128 format_list->fourcc_format,
2129 format_list->modifier);
2130 ++format_list;
2131 }
2132 sde_kms_info_stop(info);
2133 }
2134
2135 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2136 if (downscale_caps) {
2137 sde_kms_info_start(info, "downscale_ratios");
2138 sde_kms_info_append(info, downscale_caps);
2139 sde_kms_info_stop(info);
2140 }
2141
2142 if (rot_hw->ops.get_cache_size)
2143 sde_kms_info_add_keyint(info, "cache_size",
2144 rot_hw->ops.get_cache_size(rot_hw));
2145
Alan Kwong1a915802017-03-31 12:55:46 -07002146 if (rot_hw->ops.get_maxlinewidth)
2147 sde_kms_info_add_keyint(info, "max_linewidth",
2148 rot_hw->ops.get_maxlinewidth(rot_hw));
2149
Alan Kwong4dd64c82017-02-04 18:41:51 -08002150 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
2151 info->data, info->len, PLANE_PROP_ROT_CAPS_V1);
2152
2153 sde_hw_rot_put(rot_hw);
2154error_rot:
2155 kfree(info);
2156}
2157
2158/**
2159 * sde_plane_rot_install_properties - install plane rotator properties
2160 * @plane: Pointer to drm plane
2161 * @catalog: Pointer to mdss configuration
2162 * return: none
2163 */
2164static void sde_plane_rot_install_properties(struct drm_plane *plane,
2165 struct sde_mdss_cfg *catalog)
2166{
2167 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002168 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2169 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002170
2171 if (!plane || !psde) {
2172 SDE_ERROR("invalid plane\n");
2173 return;
2174 } else if (!catalog) {
2175 SDE_ERROR("invalid catalog\n");
2176 return;
2177 }
2178
2179 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2180 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2181 DRM_ROTATE_180 | DRM_ROTATE_270;
2182
2183 msm_property_install_rotation(&psde->property_info,
2184 supported_rotations, PLANE_PROP_ROTATION);
2185
2186 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2187 return;
2188
2189 msm_property_install_range(&psde->property_info, "rot_dst_x",
2190 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2191 msm_property_install_range(&psde->property_info, "rot_dst_y",
2192 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2193 msm_property_install_range(&psde->property_info, "rot_dst_w",
2194 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2195 msm_property_install_range(&psde->property_info, "rot_dst_h",
2196 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2197 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2198 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2199}
2200
2201static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -07002202 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002203{
Clarence Ipc47a0692016-10-11 10:54:17 -04002204 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -04002205 struct sde_plane *psde;
2206 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002207 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002208 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002209 struct drm_crtc *crtc;
2210 struct drm_framebuffer *fb;
2211 struct sde_rect src, dst;
2212 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -04002213 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -04002214
Clarence Ip13a8cf42016-09-29 17:27:47 -04002215 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -04002216 SDE_ERROR("invalid plane\n");
2217 return -EINVAL;
2218 } else if (!plane->state) {
2219 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04002220 return -EINVAL;
2221 }
2222
2223 psde = to_sde_plane(plane);
2224 pstate = to_sde_plane_state(plane->state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002225 rstate = &pstate->rot;
Clarence Ipcb410d42016-06-26 22:52:33 -04002226
Dhaval Patel47302cf2016-08-18 15:04:28 -07002227 crtc = state->crtc;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002228 fb = rstate->out_fb;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002229 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002230 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
2231 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002232 return -EINVAL;
2233 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002234 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002235 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -04002236
Alan Kwong4dd64c82017-02-04 18:41:51 -08002237 SDE_DEBUG(
2238 "plane%d.%d sspp:%dx%d/%c%c%c%c/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
2239 plane->base.id, rstate->sequence_id,
2240 rstate->out_fb_width, rstate->out_fb_height,
2241 rstate->out_fb_pixel_format >> 0,
2242 rstate->out_fb_pixel_format >> 8,
2243 rstate->out_fb_pixel_format >> 16,
2244 rstate->out_fb_pixel_format >> 24,
2245 rstate->out_fb_modifier[0],
2246 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2247 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2248 rstate->out_rotation,
2249 state->crtc_w, state->crtc_h,
2250 state->crtc_x, state->crtc_y);
2251
Clarence Ip282dad62016-09-27 17:07:35 -04002252 /* determine what needs to be refreshed */
2253 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
2254 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -04002255 case PLANE_PROP_SCALER_V1:
abeykun48f407a2016-08-25 12:06:44 -04002256 case PLANE_PROP_SCALER_V2:
Clarence Ipdedbba92016-09-27 17:43:10 -04002257 case PLANE_PROP_H_DECIMATE:
2258 case PLANE_PROP_V_DECIMATE:
2259 case PLANE_PROP_SRC_CONFIG:
2260 case PLANE_PROP_ZPOS:
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002261 case PLANE_PROP_EXCL_RECT_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04002262 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2263 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04002264 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04002265 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2266 break;
2267 case PLANE_PROP_COLOR_FILL:
2268 /* potentially need to refresh everything */
2269 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2270 break;
2271 case PLANE_PROP_ROTATION:
2272 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2273 break;
Clarence Ip282dad62016-09-27 17:07:35 -04002274 case PLANE_PROP_INFO:
2275 case PLANE_PROP_ALPHA:
2276 case PLANE_PROP_INPUT_FENCE:
2277 case PLANE_PROP_BLEND_OP:
2278 /* no special action required */
2279 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002280 case PLANE_PROP_ROT_DST_X:
2281 case PLANE_PROP_ROT_DST_Y:
2282 case PLANE_PROP_ROT_DST_W:
2283 case PLANE_PROP_ROT_DST_H:
2284 /* handled by rotator atomic update */
2285 break;
Clarence Ip282dad62016-09-27 17:07:35 -04002286 default:
2287 /* unknown property, refresh everything */
2288 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
2289 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
2290 break;
2291 }
Clarence Ipcb410d42016-06-26 22:52:33 -04002292 }
2293
Clarence Ip282dad62016-09-27 17:07:35 -04002294 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
2295 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -04002296
2297 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
2298
Clarence Ip282dad62016-09-27 17:07:35 -04002299 /* early out if nothing dirty */
2300 if (!pstate->dirty)
2301 return 0;
2302 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002303
Dhaval Patel4d424602017-02-18 19:40:14 -08002304 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
Clarence Ip282dad62016-09-27 17:07:35 -04002305 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
2306
2307 /* update roi config */
2308 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002309 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2310 rstate->out_src_w, rstate->out_src_h, q16_data);
Clarence Ip282dad62016-09-27 17:07:35 -04002311 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
2312 state->crtc_w, state->crtc_h, !q16_data);
2313
Clarence Ip13a8cf42016-09-29 17:27:47 -04002314 SDE_DEBUG_PLANE(psde,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002315 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %c%c%c%c ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04002316 fb->base.id, src.x, src.y, src.w, src.h,
2317 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002318 fmt->base.pixel_format >> 0,
2319 fmt->base.pixel_format >> 8,
2320 fmt->base.pixel_format >> 16,
2321 fmt->base.pixel_format >> 24,
Clarence Ip282dad62016-09-27 17:07:35 -04002322 SDE_FORMAT_IS_UBWC(fmt));
2323
2324 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
2325 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002326 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002327 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
2328 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
2329 src.h /= 2;
2330 src.y = DIV_ROUND_UP(src.y, 2);
2331 src.y &= ~0x1;
2332 }
2333
2334 psde->pipe_cfg.src_rect = src;
2335 psde->pipe_cfg.dst_rect = dst;
2336
Dhaval Patele4b6bb22017-03-27 17:22:21 -07002337 _sde_plane_setup_scaler(psde, fmt, pstate);
2338
Clarence Ip282dad62016-09-27 17:07:35 -04002339 /* check for color fill */
2340 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
2341 PLANE_PROP_COLOR_FILL);
2342 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
2343 /* skip remaining processing on color fill */
2344 pstate->dirty = 0x0;
2345 } else if (psde->pipe_hw->ops.setup_rects) {
Clarence Ip282dad62016-09-27 17:07:35 -04002346 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08002347 &psde->pipe_cfg,
2348 pstate->multirect_index);
Clarence Ip282dad62016-09-27 17:07:35 -04002349 }
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002350
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08002351 if (psde->pipe_hw->ops.setup_pe)
2352 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
2353 &psde->pixel_ext);
2354
2355 if (psde->pipe_hw->ops.setup_scaler)
2356 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
2357 &psde->pipe_cfg, &psde->pixel_ext,
2358 psde->scaler3_cfg);
2359
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002360 /* update excl rect */
2361 if (psde->pipe_hw->ops.setup_excl_rect)
2362 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002363 &pstate->excl_rect,
2364 pstate->multirect_index);
2365
2366 if (psde->pipe_hw->ops.setup_multirect)
2367 psde->pipe_hw->ops.setup_multirect(
2368 psde->pipe_hw,
2369 pstate->multirect_index,
2370 pstate->multirect_mode);
Dhaval Patel48c76022016-09-01 17:51:23 -07002371 }
2372
Clarence Ip282dad62016-09-27 17:07:35 -04002373 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
2374 psde->pipe_hw->ops.setup_format) {
2375 src_flags = 0x0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002376 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
2377 if (rstate->out_rotation & DRM_REFLECT_X)
Clarence Ip282dad62016-09-27 17:07:35 -04002378 src_flags |= SDE_SSPP_FLIP_LR;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002379 if (rstate->out_rotation & DRM_REFLECT_Y)
Clarence Ip282dad62016-09-27 17:07:35 -04002380 src_flags |= SDE_SSPP_FLIP_UD;
2381
2382 /* update format */
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002383 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
2384 pstate->multirect_index);
Clarence Ip282dad62016-09-27 17:07:35 -04002385
Alan Kwong4dd64c82017-02-04 18:41:51 -08002386 if (psde->pipe_hw->ops.setup_sys_cache) {
2387 if (rstate->out_sbuf) {
2388 if (rstate->nplane < 2)
2389 pstate->sc_cfg.op_mode =
2390 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
2391 else if (rstate->out_xpos == 0)
2392 pstate->sc_cfg.op_mode =
2393 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
2394 else
2395 pstate->sc_cfg.op_mode =
2396 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
2397
2398 pstate->sc_cfg.rd_en = true;
2399 pstate->sc_cfg.rd_scid =
2400 rstate->rot_hw->caps->scid;
2401 pstate->sc_cfg.rd_noallocate = true;
2402 pstate->sc_cfg.rd_op_type =
2403 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
2404 } else {
2405 pstate->sc_cfg.op_mode =
2406 SDE_PIPE_SC_OP_MODE_OFFLINE;
2407 pstate->sc_cfg.rd_en = false;
2408 pstate->sc_cfg.rd_scid = 0;
2409 pstate->sc_cfg.rd_noallocate = false;
2410 pstate->sc_cfg.rd_op_type =
2411 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
2412 }
2413
2414 psde->pipe_hw->ops.setup_sys_cache(
2415 psde->pipe_hw, &pstate->sc_cfg);
2416 }
2417
Clarence Ip282dad62016-09-27 17:07:35 -04002418 /* update csc */
2419 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04002420 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04002421 else
2422 psde->csc_ptr = 0;
2423 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002424
Benet Clarkeb1b4462016-06-27 14:43:06 -07002425 sde_color_process_plane_setup(plane);
2426
Clarence Ipe78efb72016-06-24 18:35:21 -04002427 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04002428 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
2429 psde->pipe_hw->ops.setup_sharpening) {
2430 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
2431 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
2432 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
2433 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04002434
Clarence Ipe78efb72016-06-24 18:35:21 -04002435 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04002436 &psde->sharp_cfg);
2437 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002438
Alan Kwong1a00e4d2016-07-18 09:42:30 -04002439 _sde_plane_set_qos_lut(plane, fb);
2440 _sde_plane_set_danger_lut(plane, fb);
2441
Alan Kwong5d324e42016-07-28 22:56:18 -04002442 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04002443 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04002444 _sde_plane_set_ot_limit(plane, crtc);
2445 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04002446
Clarence Ip282dad62016-09-27 17:07:35 -04002447 /* clear dirty */
2448 pstate->dirty = 0x0;
2449
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002450 /* clear multirect mode*/
2451 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2452 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
2453 return 0;
2454}
2455
2456int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2457{
2458 struct sde_plane_state *pstate[R_MAX];
2459 const struct drm_plane_state *drm_state[R_MAX];
2460 struct sde_rect src[R_MAX], dst[R_MAX];
2461 struct sde_plane *sde_plane[R_MAX];
2462 const struct sde_format *fmt[R_MAX];
2463 bool q16_data = true;
2464 int i, max_sspp_linewidth;
2465 int buffer_lines = TX_MODE_BUFFER_LINE_THRES;
2466
2467 for (i = 0; i < R_MAX; i++) {
2468 const struct msm_format *msm_fmt;
2469
2470 drm_state[i] = i ? plane->r1 : plane->r0;
2471 pstate[i] = to_sde_plane_state(drm_state[i]);
2472 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2473
2474 if (pstate[i] == NULL) {
2475 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2476 drm_state[i]->plane->base.id);
2477 return -EINVAL;
2478 }
2479
2480 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2481 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2482 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2483 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2484 drm_state[i]->crtc_h, !q16_data);
2485
2486 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2487 SDE_ERROR_PLANE(sde_plane[i],
2488 "scaling is not supported in multirect mode\n");
2489 return -EINVAL;
2490 }
2491
2492 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2493 fmt[i] = to_sde_format(msm_fmt);
2494 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2495 SDE_ERROR_PLANE(sde_plane[i],
2496 "Unsupported format for multirect mode\n");
2497 return -EINVAL;
2498 }
2499 }
2500
2501 max_sspp_linewidth = sde_plane[R0]->pipe_sblk->maxlinewidth;
2502
2503 /* Validate RECT's and set the mode */
2504
2505 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
2506 if (src[R0].w <= max_sspp_linewidth/2 &&
2507 src[R1].w <= max_sspp_linewidth/2) {
2508 if (dst[R0].x <= dst[R1].x) {
2509 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2510 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2511 } else {
2512 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2513 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2514 }
2515
2516 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2517 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2518 goto done;
2519 }
2520
2521 /* TIME_MX Mode */
2522 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
2523 buffer_lines = 2 * fmt[R0]->tile_height;
2524
2525 if (dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) {
2526 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2527 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2528 } else if (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines) {
2529 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2530 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2531 } else {
2532 SDE_ERROR(
2533 "No multirect mode possible for the planes (%d - %d)\n",
2534 drm_state[R0]->plane->base.id,
2535 drm_state[R1]->plane->base.id);
2536 return -EINVAL;
2537 }
2538
2539 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2540 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2541done:
Clarence Ip5e2a9222016-06-26 22:38:24 -04002542 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002543}
2544
Alan Kwong4dd64c82017-02-04 18:41:51 -08002545/**
2546 * sde_plane_get_ctl_flush - get control flush for the given plane
2547 * @plane: Pointer to drm plane structure
2548 * @ctl: Pointer to hardware control driver
2549 * @flush: Pointer to flush control word
2550 */
2551void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
2552 u32 *flush)
2553{
2554 struct sde_plane_state *pstate;
2555 struct sde_plane_rot_state *rstate;
2556 u32 bitmask;
2557
2558 if (!plane || !flush) {
2559 SDE_ERROR("invalid parameters\n");
2560 return;
2561 }
2562
2563 pstate = to_sde_plane_state(plane->state);
2564 rstate = &pstate->rot;
2565
2566 bitmask = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
2567
2568 if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
2569 ctl->ops.get_bitmask_rot)
2570 ctl->ops.get_bitmask_rot(ctl, &bitmask, rstate->rot_hw->idx);
2571
2572 *flush = bitmask;
2573}
2574
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002575static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002576 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002577{
2578 struct drm_framebuffer *fb = new_state->fb;
2579 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002580 struct sde_plane_rot_state *new_rstate;
2581 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002582
2583 if (!new_state->fb)
2584 return 0;
2585
Clarence Ip13a8cf42016-09-29 17:27:47 -04002586 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002587
2588 ret = sde_plane_rot_prepare_fb(plane, new_state);
2589 if (ret) {
2590 SDE_ERROR("failed to prepare rot framebuffer\n");
2591 return ret;
2592 }
2593
2594 new_rstate = &to_sde_plane_state(new_state)->rot;
2595
2596 ret = msm_framebuffer_prepare(new_rstate->out_fb, new_rstate->mmu_id);
2597 if (ret) {
2598 SDE_ERROR("failed to prepare framebuffer\n");
2599 return ret;
2600 }
2601
2602 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002603}
2604
2605static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002606 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002607{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002608 struct sde_plane *psde = to_sde_plane(plane);
2609 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002610
Alan Kwong4dd64c82017-02-04 18:41:51 -08002611 if (!old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002612 return;
2613
Alan Kwong4dd64c82017-02-04 18:41:51 -08002614 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2615
2616 old_rstate = &to_sde_plane_state(old_state)->rot;
2617
2618 msm_framebuffer_cleanup(old_rstate->out_fb, old_rstate->mmu_id);
2619
2620 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002621}
2622
Alan Kwong4dd64c82017-02-04 18:41:51 -08002623static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002624 struct drm_plane_state *state,
2625 struct drm_plane_state *old_state)
2626{
2627 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002628 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002629 struct sde_plane_rot_state *rstate = &pstate->rot;
2630 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2631 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002632
Dhaval Patel47302cf2016-08-18 15:04:28 -07002633 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002634 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002635 return;
2636
Clarence Ip282dad62016-09-27 17:07:35 -04002637 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2638 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002639 SDE_DEBUG_PLANE(psde,
2640 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002641 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002642 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002643 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002644 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002645 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2646 rstate->out_src_h != old_rstate->out_src_h ||
2647 rstate->out_src_x != old_rstate->out_src_x ||
2648 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002649 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002650 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002651 } else if (state->crtc_w != old_state->crtc_w ||
2652 state->crtc_h != old_state->crtc_h ||
2653 state->crtc_x != old_state->crtc_x ||
2654 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002655 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002656 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002657 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2658 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2659 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2660 pstate->excl_rect.y != old_pstate->excl_rect.y) {
2661 SDE_DEBUG_PLANE(psde, "excl rect updated\n");
2662 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002663 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2664 pstate->multirect_mode != old_pstate->multirect_mode) {
2665 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2666 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002667 }
2668
Alan Kwong4dd64c82017-02-04 18:41:51 -08002669 fb = rstate->out_fb;
2670 old_fb = old_rstate->out_fb;
2671
2672 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002673 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002674 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002675 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002676 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002677 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002678 uint64_t *new_mods = fb->modifier;
2679 uint64_t *old_mods = old_fb->modifier;
2680 uint32_t *new_pitches = fb->pitches;
2681 uint32_t *old_pitches = old_fb->pitches;
2682 uint32_t *new_offset = fb->offsets;
2683 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002684 int i;
2685
Alan Kwong4dd64c82017-02-04 18:41:51 -08002686 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002687 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002688 SDE_DEBUG_PLANE(psde,
2689 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002690 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002691 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002692 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2693 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002694 break;
2695 }
2696 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002697 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002698 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002699 SDE_DEBUG_PLANE(psde,
2700 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002701 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002702 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002703 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002704 break;
2705 }
2706 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002707 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002708 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002709 SDE_DEBUG_PLANE(psde,
2710 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002711 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002712 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002713 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2714 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002715 break;
2716 }
2717 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002718 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002719}
2720
Alan Kwong4dd64c82017-02-04 18:41:51 -08002721static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002722 struct drm_plane_state *state)
2723{
Clarence Ipdedbba92016-09-27 17:43:10 -04002724 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04002725 struct sde_plane *psde;
2726 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002727 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002728 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002729 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04002730 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002731 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
2732 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04002733
2734 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002735 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2736 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04002737 ret = -EINVAL;
2738 goto exit;
2739 }
2740
2741 psde = to_sde_plane(plane);
2742 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002743 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04002744
2745 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002746 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002747 ret = -EINVAL;
2748 goto exit;
2749 }
2750
Clarence Ipdedbba92016-09-27 17:43:10 -04002751 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
2752 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04002753
2754 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002755 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2756 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002757 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
2758 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04002759
Dhaval Patel47302cf2016-08-18 15:04:28 -07002760 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
2761 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04002762
Dhaval Patel47302cf2016-08-18 15:04:28 -07002763 max_upscale = psde->pipe_sblk->maxupscale;
2764 max_downscale = psde->pipe_sblk->maxdwnscale;
2765 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04002766
Clarence Ip13a8cf42016-09-29 17:27:47 -04002767 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002768 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002769
Dhaval Patel47302cf2016-08-18 15:04:28 -07002770 if (!sde_plane_enabled(state))
2771 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04002772
Alan Kwong4dd64c82017-02-04 18:41:51 -08002773 SDE_DEBUG(
2774 "plane%d.%u sspp:%x/%dx%d/%c%c%c%c/%llx/%dx%d+%d+%d crtc:%dx%d+%d+%d\n",
2775 plane->base.id, rstate->sequence_id,
2776 rstate->out_rotation,
2777 rstate->out_fb_width, rstate->out_fb_height,
2778 rstate->out_fb_pixel_format >> 0,
2779 rstate->out_fb_pixel_format >> 8,
2780 rstate->out_fb_pixel_format >> 16,
2781 rstate->out_fb_pixel_format >> 24,
2782 rstate->out_fb_modifier[0],
2783 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2784 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2785 state->crtc_w, state->crtc_h,
2786 state->crtc_x, state->crtc_y);
2787
Dhaval Patel47302cf2016-08-18 15:04:28 -07002788 fmt = to_sde_format(msm_framebuffer_format(state->fb));
2789
2790 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
2791
2792 if (SDE_FORMAT_IS_YUV(fmt) &&
2793 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04002794 !(psde->features & (BIT(SDE_SSPP_CSC)
2795 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002796 SDE_ERROR_PLANE(psde,
2797 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07002798 ret = -EINVAL;
2799
2800 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002801 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
2802 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07002803 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08002804 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
2805 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002806 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002807 src.x, src.y, src.w, src.h);
2808 ret = -E2BIG;
2809
2810 /* valid yuv image */
2811 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
2812 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002813 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002814 src.x, src.y, src.w, src.h);
2815 ret = -EINVAL;
2816
2817 /* min dst support */
2818 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002819 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002820 dst.x, dst.y, dst.w, dst.h);
2821 ret = -EINVAL;
2822
2823 /* decimation validation */
2824 } else if (deci_w || deci_h) {
2825 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
2826 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002827 SDE_ERROR_PLANE(psde,
2828 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002829 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002830 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002831 SDE_ERROR_PLANE(psde,
2832 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002833 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002834 }
2835
Dhaval Patel47302cf2016-08-18 15:04:28 -07002836 } else if (!(psde->features & SDE_SSPP_SCALER) &&
2837 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002838 SDE_ERROR_PLANE(psde,
2839 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002840 src.w, src.h, dst.w, dst.h);
2841 ret = -EINVAL;
2842
2843 /* check decimated source width */
2844 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002845 SDE_ERROR_PLANE(psde,
2846 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002847 src.w, src_deci_w, max_linewidth);
2848 ret = -E2BIG;
2849
2850 /* check max scaler capability */
2851 } else if (((src_deci_w * max_upscale) < dst.w) ||
2852 ((src_deci_h * max_upscale) < dst.h) ||
2853 ((dst.w * max_downscale) < src_deci_w) ||
2854 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002855 SDE_ERROR_PLANE(psde,
2856 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002857 src_deci_w, src_deci_h, dst.w, dst.h);
2858 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002859 }
2860
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002861 /* check excl rect configs */
2862 if (pstate->excl_rect.w && pstate->excl_rect.h) {
2863 struct sde_rect intersect;
2864
2865 /*
2866 * Check exclusion rect against src rect.
2867 * Cropping is not required as hardware will consider only the
2868 * intersecting region with the src rect.
2869 */
2870 sde_kms_rect_intersect(&intersect, &src, &pstate->excl_rect);
2871 if (!intersect.w || !intersect.h || SDE_FORMAT_IS_YUV(fmt)) {
2872 SDE_ERROR_PLANE(psde,
2873 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt:%s\n",
2874 pstate->excl_rect.x, pstate->excl_rect.y,
2875 pstate->excl_rect.w, pstate->excl_rect.h,
2876 src.x, src.y, src.w, src.h,
2877 drm_get_format_name(fmt->base.pixel_format));
2878 ret = -EINVAL;
2879 }
2880 }
2881
Dhaval Patel47302cf2016-08-18 15:04:28 -07002882modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002883 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002884 _sde_plane_sspp_atomic_check_mode_changed(psde,
2885 state, plane->state);
2886exit:
2887 return ret;
2888}
2889
2890static int sde_plane_atomic_check(struct drm_plane *plane,
2891 struct drm_plane_state *state)
2892{
2893 int ret = 0;
2894 struct sde_plane *psde;
2895 struct sde_plane_state *pstate;
2896
2897 if (!plane || !state) {
2898 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2899 plane != 0, state != 0);
2900 ret = -EINVAL;
2901 goto exit;
2902 }
2903
2904 psde = to_sde_plane(plane);
2905 pstate = to_sde_plane_state(state);
2906
2907 SDE_DEBUG_PLANE(psde, "\n");
2908
2909 ret = sde_plane_rot_atomic_check(plane, state);
2910 if (ret)
2911 goto exit;
2912
2913 ret = sde_plane_sspp_atomic_check(plane, state);
2914
Clarence Ipdbde9832016-06-26 09:48:36 -04002915exit:
2916 return ret;
2917}
2918
Clarence Ipcae1bb62016-07-07 12:07:13 -04002919/**
2920 * sde_plane_flush - final plane operations before commit flush
2921 * @plane: Pointer to drm plane structure
2922 */
2923void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04002924{
Clarence Ipcae1bb62016-07-07 12:07:13 -04002925 struct sde_plane *psde;
2926
Clarence Ip13a8cf42016-09-29 17:27:47 -04002927 if (!plane) {
2928 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04002929 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002930 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04002931
2932 psde = to_sde_plane(plane);
2933
2934 /*
2935 * These updates have to be done immediately before the plane flush
2936 * timing, and may not be moved to the atomic_update/mode_set functions.
2937 */
2938 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05002939 /* force white frame with 100% alpha pipe output on error */
2940 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002941 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
2942 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04002943 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002944 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
2945 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
2946
Clarence Ip56902792017-03-17 15:22:07 -04002947 /* force black color fill during suspend */
2948 if (msm_is_suspend_state(plane->dev) && suspend_blank)
2949 _sde_plane_color_fill(psde, 0x0, 0x0);
2950
Clarence Ipcae1bb62016-07-07 12:07:13 -04002951 /* flag h/w flush complete */
2952 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04002953 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002954}
2955
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002956static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04002957 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002958{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002959 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04002960 struct drm_plane_state *state;
2961 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002962 struct sde_plane_state *old_pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002963
Clarence Ip13a8cf42016-09-29 17:27:47 -04002964 if (!plane) {
2965 SDE_ERROR("invalid plane\n");
2966 return;
2967 } else if (!plane->state) {
2968 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04002969 return;
2970 }
2971
Clarence Ip13a8cf42016-09-29 17:27:47 -04002972 psde = to_sde_plane(plane);
2973 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04002974 state = plane->state;
2975 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002976 old_pstate = to_sde_plane_state(old_state);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002977
Clarence Ip13a8cf42016-09-29 17:27:47 -04002978 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04002979
Alan Kwong4dd64c82017-02-04 18:41:51 -08002980 sde_plane_rot_atomic_update(plane, old_state);
2981
2982 if (!sde_plane_sspp_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04002983 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04002984 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002985 int ret;
2986
Alan Kwong4dd64c82017-02-04 18:41:51 -08002987 ret = sde_plane_sspp_atomic_update(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002988 /* atomic_check should have ensured that this doesn't fail */
2989 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002990 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002991}
2992
Dhaval Patel47302cf2016-08-18 15:04:28 -07002993
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002994/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07002995static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002996 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002997{
Clarence Ip5e2a9222016-06-26 22:38:24 -04002998 static const struct drm_prop_enum_list e_blend_op[] = {
2999 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3000 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3001 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3002 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3003 };
3004 static const struct drm_prop_enum_list e_src_config[] = {
3005 {SDE_DRM_DEINTERLACE, "deinterlace"}
3006 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003007 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07003008 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003009 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003010 int zpos_max = 255;
3011 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003012 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003013
Clarence Ip13a8cf42016-09-29 17:27:47 -04003014 if (!plane || !psde) {
3015 SDE_ERROR("invalid plane\n");
3016 return;
3017 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3018 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3019 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003020 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003021 } else if (!catalog) {
3022 SDE_ERROR("invalid catalog\n");
3023 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003024 }
3025
Alan Kwong4dd64c82017-02-04 18:41:51 -08003026 psde->catalog = catalog;
3027
Clarence Ipc47a0692016-10-11 10:54:17 -04003028 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003029 if (catalog->mixer_count && catalog->mixer &&
3030 catalog->mixer[0].sblk->maxblendstages) {
3031 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3032 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3033 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3034 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003035 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3036 /* reserve zpos == 0 for primary planes */
3037 zpos_def = drm_plane_index(plane) + 1;
3038 }
3039
3040 msm_property_install_range(&psde->property_info, "zpos",
3041 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003042
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003043 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003044 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003045
Dhaval Patel47302cf2016-08-18 15:04:28 -07003046 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003047 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003048 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003049
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003050 if (!master_plane_id) {
3051 if (psde->pipe_sblk->maxhdeciexp) {
3052 msm_property_install_range(&psde->property_info,
3053 "h_decimate", 0x0, 0,
3054 psde->pipe_sblk->maxhdeciexp, 0,
3055 PLANE_PROP_H_DECIMATE);
3056 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003057
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003058 if (psde->pipe_sblk->maxvdeciexp) {
3059 msm_property_install_range(&psde->property_info,
3060 "v_decimate", 0x0, 0,
3061 psde->pipe_sblk->maxvdeciexp, 0,
3062 PLANE_PROP_V_DECIMATE);
3063 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003064
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003065 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
3066 msm_property_install_volatile_range(
3067 &psde->property_info, "scaler_v2",
3068 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3069 msm_property_install_blob(&psde->property_info,
3070 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3071 msm_property_install_blob(&psde->property_info,
3072 "lut_cir", 0,
3073 PLANE_PROP_SCALER_LUT_CIR);
3074 msm_property_install_blob(&psde->property_info,
3075 "lut_sep", 0,
3076 PLANE_PROP_SCALER_LUT_SEP);
3077 } else if (psde->features & SDE_SSPP_SCALER) {
3078 msm_property_install_volatile_range(
3079 &psde->property_info, "scaler_v1", 0x0,
3080 0, ~0, 0, PLANE_PROP_SCALER_V1);
3081 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003082
Dhaval Patel0aee0972017-02-08 19:00:58 -08003083 if (psde->features & BIT(SDE_SSPP_CSC) ||
3084 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003085 msm_property_install_volatile_range(
3086 &psde->property_info, "csc_v1", 0x0,
3087 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003088
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003089 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3090 snprintf(feature_name, sizeof(feature_name), "%s%d",
3091 "SDE_SSPP_HUE_V",
3092 psde->pipe_sblk->hsic_blk.version >> 16);
3093 msm_property_install_range(&psde->property_info,
3094 feature_name, 0, 0, 0xFFFFFFFF, 0,
3095 PLANE_PROP_HUE_ADJUST);
3096 snprintf(feature_name, sizeof(feature_name), "%s%d",
3097 "SDE_SSPP_SATURATION_V",
3098 psde->pipe_sblk->hsic_blk.version >> 16);
3099 msm_property_install_range(&psde->property_info,
3100 feature_name, 0, 0, 0xFFFFFFFF, 0,
3101 PLANE_PROP_SATURATION_ADJUST);
3102 snprintf(feature_name, sizeof(feature_name), "%s%d",
3103 "SDE_SSPP_VALUE_V",
3104 psde->pipe_sblk->hsic_blk.version >> 16);
3105 msm_property_install_range(&psde->property_info,
3106 feature_name, 0, 0, 0xFFFFFFFF, 0,
3107 PLANE_PROP_VALUE_ADJUST);
3108 snprintf(feature_name, sizeof(feature_name), "%s%d",
3109 "SDE_SSPP_CONTRAST_V",
3110 psde->pipe_sblk->hsic_blk.version >> 16);
3111 msm_property_install_range(&psde->property_info,
3112 feature_name, 0, 0, 0xFFFFFFFF, 0,
3113 PLANE_PROP_CONTRAST_ADJUST);
3114 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003115 }
3116
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003117 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3118 msm_property_install_volatile_range(&psde->property_info,
3119 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3120
Alan Kwong4dd64c82017-02-04 18:41:51 -08003121 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003122
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003123 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003124 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003125
Dhaval Patel47302cf2016-08-18 15:04:28 -07003126 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3127 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3128
3129 if (psde->pipe_hw->ops.setup_solidfill)
3130 msm_property_install_range(&psde->property_info, "color_fill",
3131 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3132
Dhaval Patel4e574842016-08-23 15:11:37 -07003133 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003134 if (!info) {
3135 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003136 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003137 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003138
3139 msm_property_install_blob(&psde->property_info, "capabilities",
3140 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3141 sde_kms_info_reset(info);
3142
Clarence Ipea3d6262016-07-15 16:20:11 -04003143 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003144
3145 if (master_plane_id) {
3146 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
3147 master_plane_id);
3148 format_list = plane_formats;
3149 }
3150
Clarence Ipea3d6262016-07-15 16:20:11 -04003151 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003152 sde_kms_info_start(info, "pixel_formats");
3153 while (format_list->fourcc_format) {
3154 sde_kms_info_append_format(info,
3155 format_list->fourcc_format,
3156 format_list->modifier);
3157 ++format_list;
3158 }
3159 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003160 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003161
3162 sde_kms_info_add_keyint(info, "max_linewidth",
3163 psde->pipe_sblk->maxlinewidth);
3164 sde_kms_info_add_keyint(info, "max_upscale",
3165 psde->pipe_sblk->maxupscale);
3166 sde_kms_info_add_keyint(info, "max_downscale",
3167 psde->pipe_sblk->maxdwnscale);
3168 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3169 psde->pipe_sblk->maxhdeciexp);
3170 sde_kms_info_add_keyint(info, "max_vertical_deci",
3171 psde->pipe_sblk->maxvdeciexp);
3172 msm_property_set_blob(&psde->property_info, &psde->blob_info,
3173 info->data, info->len, PLANE_PROP_INFO);
3174
3175 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003176
3177 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3178 snprintf(feature_name, sizeof(feature_name), "%s%d",
3179 "SDE_SSPP_SKIN_COLOR_V",
3180 psde->pipe_sblk->memcolor_blk.version >> 16);
3181 msm_property_install_blob(&psde->property_info, feature_name, 0,
3182 PLANE_PROP_SKIN_COLOR);
3183 snprintf(feature_name, sizeof(feature_name), "%s%d",
3184 "SDE_SSPP_SKY_COLOR_V",
3185 psde->pipe_sblk->memcolor_blk.version >> 16);
3186 msm_property_install_blob(&psde->property_info, feature_name, 0,
3187 PLANE_PROP_SKY_COLOR);
3188 snprintf(feature_name, sizeof(feature_name), "%s%d",
3189 "SDE_SSPP_FOLIAGE_COLOR_V",
3190 psde->pipe_sblk->memcolor_blk.version >> 16);
3191 msm_property_install_blob(&psde->property_info, feature_name, 0,
3192 PLANE_PROP_FOLIAGE_COLOR);
3193 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003194}
3195
Clarence Ip5fc00c52016-09-23 15:03:34 -04003196static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
3197{
3198 struct sde_drm_csc_v1 csc_v1;
3199 int i;
3200
3201 if (!psde) {
3202 SDE_ERROR("invalid plane\n");
3203 return;
3204 }
3205
3206 psde->csc_usr_ptr = NULL;
3207 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003208 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003209 return;
3210 }
3211
3212 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003213 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003214 return;
3215 }
3216
Clarence Ipb43d4592016-09-08 14:21:35 -04003217 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04003218 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
3219 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
3220 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
3221 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
3222 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
3223 }
3224 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
3225 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
3226 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
3227 }
3228 psde->csc_usr_ptr = &psde->csc_cfg;
3229}
3230
Clarence Ipb43d4592016-09-08 14:21:35 -04003231static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
3232{
3233 struct sde_drm_scaler_v1 scale_v1;
3234 struct sde_hw_pixel_ext *pe;
3235 int i;
3236
3237 if (!psde) {
3238 SDE_ERROR("invalid plane\n");
3239 return;
3240 }
3241
3242 psde->pixel_ext_usr = false;
3243 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003244 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003245 return;
3246 }
3247
3248 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003249 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003250 return;
3251 }
3252
3253 /* populate from user space */
3254 pe = &(psde->pixel_ext);
3255 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3256 for (i = 0; i < SDE_MAX_PLANES; i++) {
3257 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
3258 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
3259 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
3260 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
3261
3262 pe->horz_filter[i] = scale_v1.horz_filter[i];
3263 pe->vert_filter[i] = scale_v1.vert_filter[i];
3264 }
3265 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003266 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
3267 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
3268 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
3269 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
3270 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003271
abeykun41060122016-11-28 13:02:01 -05003272 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
3273 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
3274 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
3275 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
3276 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003277 }
abeykun41060122016-11-28 13:02:01 -05003278
Clarence Ipb43d4592016-09-08 14:21:35 -04003279 psde->pixel_ext_usr = true;
3280
Clarence Ip13a8cf42016-09-29 17:27:47 -04003281 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003282}
3283
abeykun48f407a2016-08-25 12:06:44 -04003284static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
3285 struct sde_plane_state *pstate, void *usr)
3286{
3287 struct sde_drm_scaler_v2 scale_v2;
3288 struct sde_hw_pixel_ext *pe;
3289 int i;
3290 struct sde_hw_scaler3_cfg *cfg;
3291
3292 if (!psde) {
3293 SDE_ERROR("invalid plane\n");
3294 return;
3295 }
3296
3297 cfg = psde->scaler3_cfg;
3298 psde->pixel_ext_usr = false;
3299 if (!usr) {
3300 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3301 return;
3302 }
3303
3304 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
3305 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
3306 return;
3307 }
3308
3309 /* populate from user space */
3310 pe = &(psde->pixel_ext);
3311 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3312 cfg->enable = scale_v2.enable;
3313 cfg->dir_en = scale_v2.dir_en;
3314 for (i = 0; i < SDE_MAX_PLANES; i++) {
3315 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
3316 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
3317 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
3318 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
3319
3320 cfg->preload_x[i] = scale_v2.preload_x[i];
3321 cfg->preload_y[i] = scale_v2.preload_y[i];
3322 cfg->src_width[i] = scale_v2.src_width[i];
3323 cfg->src_height[i] = scale_v2.src_height[i];
3324 }
3325 cfg->dst_width = scale_v2.dst_width;
3326 cfg->dst_height = scale_v2.dst_height;
3327
3328 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
3329 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
3330 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
3331 cfg->blend_cfg = scale_v2.blend_cfg;
3332
3333 cfg->lut_flag = scale_v2.lut_flag;
3334 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
3335 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
3336 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
3337 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
3338 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
3339
3340 cfg->de.enable = scale_v2.de.enable;
3341 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
3342 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
3343 cfg->de.clip = scale_v2.de.clip;
3344 cfg->de.limit = scale_v2.de.limit;
3345 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
3346 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
3347 cfg->de.thr_low = scale_v2.de.thr_low;
3348 cfg->de.thr_high = scale_v2.de.thr_high;
3349 cfg->de.prec_shift = scale_v2.de.prec_shift;
3350 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
3351 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
3352 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
3353 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
3354 }
3355 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003356 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
3357 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
3358 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
3359 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
3360 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04003361
abeykun41060122016-11-28 13:02:01 -05003362 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
3363 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
3364 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
3365 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
3366 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04003367 }
3368 psde->pixel_ext_usr = true;
3369
3370 SDE_DEBUG_PLANE(psde, "user property data copied\n");
3371}
3372
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003373static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
3374 struct sde_plane_state *pstate, void *usr_ptr)
3375{
3376 struct drm_clip_rect excl_rect_v1;
3377
3378 if (!psde) {
3379 SDE_ERROR("invalid plane\n");
3380 return;
3381 }
3382
3383 if (!usr_ptr) {
3384 SDE_DEBUG_PLANE(psde, "excl rect data removed\n");
3385 return;
3386 }
3387
3388 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
3389 SDE_ERROR_PLANE(psde, "failed to copy excl rect data\n");
3390 return;
3391 }
3392
3393 /* populate from user space */
3394 pstate->excl_rect.x = excl_rect_v1.x1;
3395 pstate->excl_rect.y = excl_rect_v1.y1;
3396 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1 + 1;
3397 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1 + 1;
3398}
3399
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003400static int sde_plane_atomic_set_property(struct drm_plane *plane,
3401 struct drm_plane_state *state, struct drm_property *property,
3402 uint64_t val)
3403{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003404 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003405 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003406 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003407
Clarence Ip13a8cf42016-09-29 17:27:47 -04003408 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003409
3410 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003411 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003412 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003413 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003414 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04003415 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003416 ret = msm_property_atomic_set(&psde->property_info,
3417 pstate->property_values, pstate->property_blobs,
3418 property, val);
3419 if (!ret) {
3420 idx = msm_property_index(&psde->property_info,
3421 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003422 switch (idx) {
3423 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04003424 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003425 break;
3426 case PLANE_PROP_CSC_V1:
3427 _sde_plane_set_csc_v1(psde, (void *)val);
3428 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04003429 case PLANE_PROP_SCALER_V1:
3430 _sde_plane_set_scaler_v1(psde, (void *)val);
3431 break;
abeykun48f407a2016-08-25 12:06:44 -04003432 case PLANE_PROP_SCALER_V2:
3433 _sde_plane_set_scaler_v2(psde, pstate,
3434 (void *)val);
3435 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003436 case PLANE_PROP_EXCL_RECT_V1:
3437 _sde_plane_set_excl_rect_v1(psde, pstate,
3438 (void *)val);
3439 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04003440 default:
3441 /* nothing to do */
3442 break;
3443 }
Clarence Ipe78efb72016-06-24 18:35:21 -04003444 }
3445 }
3446
Alan Kwong4dd64c82017-02-04 18:41:51 -08003447 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
3448 property->name, property->base.id, val, ret);
3449
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003450 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003451}
3452
3453static int sde_plane_set_property(struct drm_plane *plane,
3454 struct drm_property *property, uint64_t val)
3455{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003456 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003457
Clarence Ipae4e60c2016-06-26 22:44:04 -04003458 return sde_plane_atomic_set_property(plane,
3459 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003460}
3461
3462static int sde_plane_atomic_get_property(struct drm_plane *plane,
3463 const struct drm_plane_state *state,
3464 struct drm_property *property, uint64_t *val)
3465{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003466 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003467 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04003468 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003469
Clarence Ipaa0faf42016-05-30 12:07:48 -04003470 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003471 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003472 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003473 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003474 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003475 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003476 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003477 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003478 ret = msm_property_atomic_get(&psde->property_info,
3479 pstate->property_values, pstate->property_blobs,
3480 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04003481 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003482
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003483 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003484}
3485
3486static void sde_plane_destroy(struct drm_plane *plane)
3487{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003488 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003489
Clarence Ip13a8cf42016-09-29 17:27:47 -04003490 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003491
Clarence Ip13a8cf42016-09-29 17:27:47 -04003492 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04003493 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3494
Dhaval Patel4e574842016-08-23 15:11:37 -07003495 if (psde->blob_info)
3496 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003497 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04003498 mutex_destroy(&psde->lock);
3499
Clarence Ip4ce59322016-06-26 22:27:51 -04003500 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003501
Clarence Ip4ce59322016-06-26 22:27:51 -04003502 /* this will destroy the states as well */
3503 drm_plane_cleanup(plane);
3504
Clarence Ip4c1d9772016-06-26 09:35:38 -04003505 if (psde->pipe_hw)
3506 sde_hw_sspp_destroy(psde->pipe_hw);
3507
Clarence Ip4ce59322016-06-26 22:27:51 -04003508 kfree(psde);
3509 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003510}
3511
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003512static void sde_plane_destroy_state(struct drm_plane *plane,
3513 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003514{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003515 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04003516 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003517
Clarence Ipae4e60c2016-06-26 22:44:04 -04003518 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003519 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3520 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003521 return;
3522 }
3523
Clarence Ipaa0faf42016-05-30 12:07:48 -04003524 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04003525 pstate = to_sde_plane_state(state);
3526
Clarence Ip13a8cf42016-09-29 17:27:47 -04003527 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003528
Alan Kwong4dd64c82017-02-04 18:41:51 -08003529 sde_plane_rot_destroy_state(plane, &pstate->base);
3530
Clarence Ipe78efb72016-06-24 18:35:21 -04003531 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003532 if (state->fb)
3533 drm_framebuffer_unreference(state->fb);
3534
Clarence Ipae4e60c2016-06-26 22:44:04 -04003535 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003536 if (pstate->input_fence)
3537 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003538
Clarence Ipaa0faf42016-05-30 12:07:48 -04003539 /* destroy value helper */
3540 msm_property_destroy_state(&psde->property_info, pstate,
3541 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003542}
3543
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003544static struct drm_plane_state *
3545sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003546{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003547 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003548 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04003549 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04003550 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003551
Clarence Ip13a8cf42016-09-29 17:27:47 -04003552 if (!plane) {
3553 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003554 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003555 } else if (!plane->state) {
3556 SDE_ERROR("invalid plane state\n");
3557 return NULL;
3558 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003559
Clarence Ip730e7192016-06-26 22:45:09 -04003560 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003561 psde = to_sde_plane(plane);
3562 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003563 if (!pstate) {
3564 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003565 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003566 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003567
Clarence Ip13a8cf42016-09-29 17:27:47 -04003568 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003569
3570 /* duplicate value helper */
3571 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
3572 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003573
Clarence Ip17e908b2016-09-29 15:58:00 -04003574 /* clear out any input fence */
3575 pstate->input_fence = 0;
3576 input_fence_default = msm_property_get_default(
3577 &psde->property_info, PLANE_PROP_INPUT_FENCE);
3578 msm_property_set_property(&psde->property_info, pstate->property_values,
3579 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003580
Clarence Ip282dad62016-09-27 17:07:35 -04003581 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04003582 pstate->pending = false;
3583
Alan Kwongcdb2f282017-03-18 13:42:06 -07003584 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
3585
Alan Kwong4dd64c82017-02-04 18:41:51 -08003586 sde_plane_rot_duplicate_state(plane, &pstate->base);
3587
Clarence Ip730e7192016-06-26 22:45:09 -04003588 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003589}
3590
3591static void sde_plane_reset(struct drm_plane *plane)
3592{
Clarence Ipae4e60c2016-06-26 22:44:04 -04003593 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003594 struct sde_plane_state *pstate;
3595
Clarence Ipae4e60c2016-06-26 22:44:04 -04003596 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003597 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003598 return;
3599 }
3600
Clarence Ip730e7192016-06-26 22:45:09 -04003601 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003602 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003603
Clarence Ipae4e60c2016-06-26 22:44:04 -04003604 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04003605 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04003606 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003607 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04003608 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003609
Clarence Ipaa0faf42016-05-30 12:07:48 -04003610 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003611 if (!pstate) {
3612 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003613 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003614 }
Clarence Ip730e7192016-06-26 22:45:09 -04003615
Clarence Ipaa0faf42016-05-30 12:07:48 -04003616 /* reset value helper */
3617 msm_property_reset_state(&psde->property_info, pstate,
3618 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003619
3620 pstate->base.plane = plane;
3621
3622 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003623}
3624
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003625#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04003626static ssize_t _sde_plane_danger_read(struct file *file,
3627 char __user *buff, size_t count, loff_t *ppos)
3628{
3629 struct sde_kms *kms = file->private_data;
3630 struct sde_mdss_cfg *cfg = kms->catalog;
3631 int len = 0;
3632 char buf[40] = {'\0'};
3633
3634 if (!cfg)
3635 return -ENODEV;
3636
3637 if (*ppos)
3638 return 0; /* the end */
3639
3640 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
3641 if (len < 0 || len >= sizeof(buf))
3642 return 0;
3643
3644 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
3645 return -EFAULT;
3646
3647 *ppos += len; /* increase offset */
3648
3649 return len;
3650}
3651
3652static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
3653{
3654 struct drm_plane *plane;
3655
3656 drm_for_each_plane(plane, kms->dev) {
3657 if (plane->fb && plane->state) {
3658 sde_plane_danger_signal_ctrl(plane, enable);
3659 SDE_DEBUG("plane:%d img:%dx%d ",
3660 plane->base.id, plane->fb->width,
3661 plane->fb->height);
3662 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
3663 plane->state->src_x >> 16,
3664 plane->state->src_y >> 16,
3665 plane->state->src_w >> 16,
3666 plane->state->src_h >> 16,
3667 plane->state->crtc_x, plane->state->crtc_y,
3668 plane->state->crtc_w, plane->state->crtc_h);
3669 } else {
3670 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
3671 }
3672 }
3673}
3674
3675static ssize_t _sde_plane_danger_write(struct file *file,
3676 const char __user *user_buf, size_t count, loff_t *ppos)
3677{
3678 struct sde_kms *kms = file->private_data;
3679 struct sde_mdss_cfg *cfg = kms->catalog;
3680 int disable_panic;
3681 char buf[10];
3682
3683 if (!cfg)
3684 return -EFAULT;
3685
3686 if (count >= sizeof(buf))
3687 return -EFAULT;
3688
3689 if (copy_from_user(buf, user_buf, count))
3690 return -EFAULT;
3691
3692 buf[count] = 0; /* end of string */
3693
3694 if (kstrtoint(buf, 0, &disable_panic))
3695 return -EFAULT;
3696
3697 if (disable_panic) {
3698 /* Disable panic signal for all active pipes */
3699 SDE_DEBUG("Disabling danger:\n");
3700 _sde_plane_set_danger_state(kms, false);
3701 kms->has_danger_ctrl = false;
3702 } else {
3703 /* Enable panic signal for all active pipes */
3704 SDE_DEBUG("Enabling danger:\n");
3705 kms->has_danger_ctrl = true;
3706 _sde_plane_set_danger_state(kms, true);
3707 }
3708
3709 return count;
3710}
3711
3712static const struct file_operations sde_plane_danger_enable = {
3713 .open = simple_open,
3714 .read = _sde_plane_danger_read,
3715 .write = _sde_plane_danger_write,
3716};
3717
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003718static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04003719{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003720 struct sde_plane *psde;
3721 struct sde_kms *kms;
3722 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04003723 const struct sde_sspp_sub_blks *sblk = 0;
3724 const struct sde_sspp_cfg *cfg = 0;
3725
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003726 if (!plane || !plane->dev) {
3727 SDE_ERROR("invalid arguments\n");
3728 return -EINVAL;
3729 }
3730
3731 priv = plane->dev->dev_private;
3732 if (!priv || !priv->kms) {
3733 SDE_ERROR("invalid KMS reference\n");
3734 return -EINVAL;
3735 }
3736
3737 kms = to_sde_kms(priv->kms);
3738 psde = to_sde_plane(plane);
3739
Clarence Ip4ce59322016-06-26 22:27:51 -04003740 if (psde && psde->pipe_hw)
3741 cfg = psde->pipe_hw->cap;
3742 if (cfg)
3743 sblk = cfg->sblk;
3744
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003745 if (!sblk)
3746 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04003747
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003748 /* create overall sub-directory for the pipe */
3749 psde->debugfs_root =
3750 debugfs_create_dir(psde->pipe_name,
3751 sde_debugfs_get_root(kms));
Clarence Ip4ce59322016-06-26 22:27:51 -04003752
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003753 if (!psde->debugfs_root)
3754 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04003755
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003756 /* don't error check these */
3757 debugfs_create_x32("features", 0644,
3758 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003759
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003760 /* add register dump support */
3761 sde_debugfs_setup_regset32(&psde->debugfs_src,
3762 sblk->src_blk.base + cfg->base,
3763 sblk->src_blk.len,
3764 kms);
3765 sde_debugfs_create_regset32("src_blk", 0444,
3766 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003767
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003768 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
3769 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
3770 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
3771 sblk->scaler_blk.base + cfg->base,
3772 sblk->scaler_blk.len,
3773 kms);
3774 sde_debugfs_create_regset32("scaler_blk", 0444,
3775 psde->debugfs_root,
3776 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07003777 debugfs_create_bool("default_scaling",
3778 0644,
3779 psde->debugfs_root,
3780 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04003781 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003782
3783 if (cfg->features & BIT(SDE_SSPP_CSC) ||
3784 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
3785 sde_debugfs_setup_regset32(&psde->debugfs_csc,
3786 sblk->csc_blk.base + cfg->base,
3787 sblk->csc_blk.len,
3788 kms);
3789 sde_debugfs_create_regset32("csc_blk", 0444,
3790 psde->debugfs_root, &psde->debugfs_csc);
3791 }
3792
3793 debugfs_create_u32("xin_id",
3794 0444,
3795 psde->debugfs_root,
3796 (u32 *) &cfg->xin_id);
3797 debugfs_create_u32("clk_ctrl",
3798 0444,
3799 psde->debugfs_root,
3800 (u32 *) &cfg->clk_ctrl);
3801 debugfs_create_x32("creq_vblank",
3802 0644,
3803 psde->debugfs_root,
3804 (u32 *) &sblk->creq_vblank);
3805 debugfs_create_x32("danger_vblank",
3806 0644,
3807 psde->debugfs_root,
3808 (u32 *) &sblk->danger_vblank);
3809
3810 debugfs_create_file("disable_danger",
3811 0644,
3812 psde->debugfs_root,
3813 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003814 debugfs_create_u32("sbuf_mode",
3815 0644,
3816 psde->debugfs_root, &psde->sbuf_mode);
3817 debugfs_create_u32("sbuf_writeback",
3818 0644,
3819 psde->debugfs_root,
3820 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003821
3822 return 0;
3823}
3824
3825static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3826{
3827 struct sde_plane *psde;
3828
3829 if (!plane)
3830 return;
3831 psde = to_sde_plane(plane);
3832
3833 debugfs_remove_recursive(psde->debugfs_root);
3834}
3835#else
3836static int _sde_plane_init_debugfs(struct drm_plane *plane)
3837{
3838 return 0;
3839}
3840static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3841{
3842}
3843#endif
3844
3845static int sde_plane_late_register(struct drm_plane *plane)
3846{
3847 return _sde_plane_init_debugfs(plane);
3848}
3849
3850static void sde_plane_early_unregister(struct drm_plane *plane)
3851{
3852 _sde_plane_destroy_debugfs(plane);
3853}
3854
3855static const struct drm_plane_funcs sde_plane_funcs = {
3856 .update_plane = drm_atomic_helper_update_plane,
3857 .disable_plane = drm_atomic_helper_disable_plane,
3858 .destroy = sde_plane_destroy,
3859 .set_property = sde_plane_set_property,
3860 .atomic_set_property = sde_plane_atomic_set_property,
3861 .atomic_get_property = sde_plane_atomic_get_property,
3862 .reset = sde_plane_reset,
3863 .atomic_duplicate_state = sde_plane_duplicate_state,
3864 .atomic_destroy_state = sde_plane_destroy_state,
3865 .late_register = sde_plane_late_register,
3866 .early_unregister = sde_plane_early_unregister,
3867};
3868
3869static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
3870 .prepare_fb = sde_plane_prepare_fb,
3871 .cleanup_fb = sde_plane_cleanup_fb,
3872 .atomic_check = sde_plane_atomic_check,
3873 .atomic_update = sde_plane_atomic_update,
3874};
3875
3876enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
3877{
3878 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
3879}
3880
3881bool is_sde_plane_virtual(struct drm_plane *plane)
3882{
3883 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04003884}
3885
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003886/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04003887struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04003888 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003889 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003890{
3891 struct drm_plane *plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003892 const struct sde_format_extended *format_list;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003893 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003894 struct msm_drm_private *priv;
3895 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003896 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04003897 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04003898
3899 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003900 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003901 goto exit;
3902 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003903
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003904 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04003905 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003906 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04003907 goto exit;
3908 }
3909
3910 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003911 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04003912 goto exit;
3913 }
3914 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003915
Clarence Ip4c1d9772016-06-26 09:35:38 -04003916 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003917 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003918 goto exit;
3919 }
3920
Clarence Ip4ce59322016-06-26 22:27:51 -04003921 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003922 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
3923 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003924 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003925 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04003926 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003927 }
3928
Clarence Ip4c1d9772016-06-26 09:35:38 -04003929 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003930 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003931 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04003932 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003933 psde->is_virtual = (master_plane_id != 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003934
Clarence Ip4c1d9772016-06-26 09:35:38 -04003935 /* initialize underlying h/w driver */
3936 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
3937 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003938 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003939 ret = PTR_ERR(psde->pipe_hw);
3940 goto clean_plane;
3941 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003942 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003943 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003944 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04003945
3946 /* cache features mask for later */
3947 psde->features = psde->pipe_hw->cap->features;
3948 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04003949 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003950 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04003951 goto clean_sspp;
3952 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04003953
abeykun48f407a2016-08-25 12:06:44 -04003954 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
3955 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
3956 GFP_KERNEL);
3957 if (!psde->scaler3_cfg) {
3958 SDE_ERROR("[%u]failed to allocate scale struct\n",
3959 pipe);
3960 ret = -ENOMEM;
3961 goto clean_sspp;
3962 }
3963 }
3964
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003965 format_list = psde->pipe_sblk->format_list;
3966
3967 if (master_plane_id)
3968 format_list = plane_formats;
3969
3970 psde->nformats = sde_populate_formats(plane_formats,
3971 psde->formats,
3972 0,
3973 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003974
Clarence Ip4c1d9772016-06-26 09:35:38 -04003975 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003976 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003977 goto clean_sspp;
3978 }
3979
3980 if (psde->features & BIT(SDE_SSPP_CURSOR))
3981 type = DRM_PLANE_TYPE_CURSOR;
3982 else if (primary_plane)
3983 type = DRM_PLANE_TYPE_PRIMARY;
3984 else
3985 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07003986 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
3987 psde->formats, psde->nformats,
3988 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003989 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04003990 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003991
Clarence Ip4c1d9772016-06-26 09:35:38 -04003992 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003993 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003994
Clarence Ipaa0faf42016-05-30 12:07:48 -04003995 msm_property_init(&psde->property_info, &plane->base, dev,
3996 priv->plane_property, psde->property_data,
3997 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
3998 sizeof(struct sde_plane_state));
3999
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004000 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004001
Clarence Ip4ce59322016-06-26 22:27:51 -04004002 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004003 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004004
Clarence Ip730e7192016-06-26 22:45:09 -04004005 mutex_init(&psde->lock);
4006
Dhaval Patel82c8dbc2017-02-18 23:15:10 -08004007 SDE_DEBUG("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004008 return plane;
4009
Clarence Ip4c1d9772016-06-26 09:35:38 -04004010clean_sspp:
4011 if (psde && psde->pipe_hw)
4012 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04004013
4014 if (psde && psde->scaler3_cfg)
4015 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004016clean_plane:
4017 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004018exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004019 return ERR_PTR(ret);
4020}