blob: 93268be8a4189bf36dee452f832e42aac2cee225 [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
Dhaval Patel6c666622017-03-21 23:02:59 -0700256 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u fl:%u\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400257 plane->base.id, psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700258 (char *)&fmt->base.pixel_format,
259 src_width, total_fl);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400260
261 return total_fl;
262}
263
264/**
265 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
266 * @total_fl: fill level
267 * Return: LUT setting corresponding to the fill level
268 */
269static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
270{
271 u32 qos_lut;
272
273 if (total_fl <= 4)
274 qos_lut = 0x1B;
275 else if (total_fl <= 5)
276 qos_lut = 0x5B;
277 else if (total_fl <= 6)
278 qos_lut = 0x15B;
279 else if (total_fl <= 7)
280 qos_lut = 0x55B;
281 else if (total_fl <= 8)
282 qos_lut = 0x155B;
283 else if (total_fl <= 9)
284 qos_lut = 0x555B;
285 else if (total_fl <= 10)
286 qos_lut = 0x1555B;
287 else if (total_fl <= 11)
288 qos_lut = 0x5555B;
289 else if (total_fl <= 12)
290 qos_lut = 0x15555B;
291 else
292 qos_lut = 0x55555B;
293
294 return qos_lut;
295}
296
297/**
298 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
299 * @total_fl: fill level
300 * Return: LUT setting corresponding to the fill level
301 */
302static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
303{
304 u32 qos_lut;
305
306 if (total_fl <= 10)
307 qos_lut = 0x1AAff;
308 else if (total_fl <= 11)
309 qos_lut = 0x5AAFF;
310 else if (total_fl <= 12)
311 qos_lut = 0x15AAFF;
312 else
313 qos_lut = 0x55AAFF;
314
315 return qos_lut;
316}
317
318/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400319 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
320 * @plane: Pointer to drm plane
321 * @fb: Pointer to framebuffer associated with the given plane
322 */
323static void _sde_plane_set_qos_lut(struct drm_plane *plane,
324 struct drm_framebuffer *fb)
325{
326 struct sde_plane *psde;
327 const struct sde_format *fmt = NULL;
328 u32 qos_lut;
329 u32 total_fl = 0;
330
331 if (!plane || !fb) {
332 SDE_ERROR("invalid arguments plane %d fb %d\n",
333 plane != 0, fb != 0);
334 return;
335 }
336
337 psde = to_sde_plane(plane);
338
339 if (!psde->pipe_hw || !psde->pipe_sblk) {
340 SDE_ERROR("invalid arguments\n");
341 return;
342 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
343 return;
344 }
345
346 if (!psde->is_rt_pipe) {
347 qos_lut = psde->pipe_sblk->creq_lut_nrt;
348 } else {
349 fmt = sde_get_sde_format_ext(
350 fb->pixel_format,
351 fb->modifier,
352 drm_format_num_planes(fb->pixel_format));
353 total_fl = _sde_plane_calc_fill_level(plane, fmt,
354 psde->pipe_cfg.src_rect.w);
355
356 if (SDE_FORMAT_IS_LINEAR(fmt))
357 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
358 else
359 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
360 }
361
362 psde->pipe_qos_cfg.creq_lut = qos_lut;
363
364 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
365 (fmt) ? fmt->base.pixel_format : 0,
366 psde->is_rt_pipe, total_fl, qos_lut,
367 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
368
Dhaval Patel6c666622017-03-21 23:02:59 -0700369 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%x\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400370 plane->base.id,
371 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700372 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400373 psde->is_rt_pipe, total_fl, qos_lut);
374
375 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
376}
377
378/**
379 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
380 * @plane: Pointer to drm plane
381 * @fb: Pointer to framebuffer associated with the given plane
382 */
383static void _sde_plane_set_danger_lut(struct drm_plane *plane,
384 struct drm_framebuffer *fb)
385{
386 struct sde_plane *psde;
387 const struct sde_format *fmt = NULL;
388 u32 danger_lut, safe_lut;
389
390 if (!plane || !fb) {
391 SDE_ERROR("invalid arguments\n");
392 return;
393 }
394
395 psde = to_sde_plane(plane);
396
397 if (!psde->pipe_hw || !psde->pipe_sblk) {
398 SDE_ERROR("invalid arguments\n");
399 return;
400 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
401 return;
402 }
403
404 if (!psde->is_rt_pipe) {
405 danger_lut = psde->pipe_sblk->danger_lut_nrt;
406 safe_lut = psde->pipe_sblk->safe_lut_nrt;
407 } else {
408 fmt = sde_get_sde_format_ext(
409 fb->pixel_format,
410 fb->modifier,
411 drm_format_num_planes(fb->pixel_format));
412
413 if (SDE_FORMAT_IS_LINEAR(fmt)) {
414 danger_lut = psde->pipe_sblk->danger_lut_linear;
415 safe_lut = psde->pipe_sblk->safe_lut_linear;
416 } else {
417 danger_lut = psde->pipe_sblk->danger_lut_tile;
418 safe_lut = psde->pipe_sblk->safe_lut_tile;
419 }
420 }
421
422 psde->pipe_qos_cfg.danger_lut = danger_lut;
423 psde->pipe_qos_cfg.safe_lut = safe_lut;
424
425 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
426 (fmt) ? fmt->base.pixel_format : 0,
427 (fmt) ? fmt->fetch_mode : 0,
428 psde->pipe_qos_cfg.danger_lut,
429 psde->pipe_qos_cfg.safe_lut);
430
Dhaval Patel6c666622017-03-21 23:02:59 -0700431 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400432 plane->base.id,
433 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700434 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400435 fmt ? fmt->fetch_mode : -1,
436 psde->pipe_qos_cfg.danger_lut,
437 psde->pipe_qos_cfg.safe_lut);
438
439 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
440 &psde->pipe_qos_cfg);
441}
442
443/**
444 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
445 * @plane: Pointer to drm plane
446 * @enable: true to enable QoS control
447 * @flags: QoS control mode (enum sde_plane_qos)
448 */
449static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
450 bool enable, u32 flags)
451{
452 struct sde_plane *psde;
453
454 if (!plane) {
455 SDE_ERROR("invalid arguments\n");
456 return;
457 }
458
459 psde = to_sde_plane(plane);
460
461 if (!psde->pipe_hw || !psde->pipe_sblk) {
462 SDE_ERROR("invalid arguments\n");
463 return;
464 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
465 return;
466 }
467
468 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
469 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
470 psde->pipe_qos_cfg.danger_vblank =
471 psde->pipe_sblk->danger_vblank;
472 psde->pipe_qos_cfg.vblank_en = enable;
473 }
474
475 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
476 /* this feature overrules previous VBLANK_CTRL */
477 psde->pipe_qos_cfg.vblank_en = false;
478 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
479 }
480
481 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
482 psde->pipe_qos_cfg.danger_safe_en = enable;
483
484 if (!psde->is_rt_pipe) {
485 psde->pipe_qos_cfg.vblank_en = false;
486 psde->pipe_qos_cfg.danger_safe_en = false;
487 }
488
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400489 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 -0400490 plane->base.id,
491 psde->pipe - SSPP_VIG0,
492 psde->pipe_qos_cfg.danger_safe_en,
493 psde->pipe_qos_cfg.vblank_en,
494 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400495 psde->pipe_qos_cfg.danger_vblank,
496 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400497
498 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
499 &psde->pipe_qos_cfg);
500}
501
Alan Kwongf0fd8512016-10-24 21:39:26 -0400502int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
503{
504 struct sde_plane *psde;
505 struct msm_drm_private *priv;
506 struct sde_kms *sde_kms;
507
508 if (!plane || !plane->dev) {
509 SDE_ERROR("invalid arguments\n");
510 return -EINVAL;
511 }
512
513 priv = plane->dev->dev_private;
514 if (!priv || !priv->kms) {
515 SDE_ERROR("invalid KMS reference\n");
516 return -EINVAL;
517 }
518
519 sde_kms = to_sde_kms(priv->kms);
520 psde = to_sde_plane(plane);
521
522 if (!psde->is_rt_pipe)
523 goto end;
524
525 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
526
527 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
528
529 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
530
531end:
532 return 0;
533}
534
Alan Kwong5d324e42016-07-28 22:56:18 -0400535/**
536 * _sde_plane_set_ot_limit - set OT limit for the given plane
537 * @plane: Pointer to drm plane
538 * @crtc: Pointer to drm crtc
539 */
540static void _sde_plane_set_ot_limit(struct drm_plane *plane,
541 struct drm_crtc *crtc)
542{
543 struct sde_plane *psde;
544 struct sde_vbif_set_ot_params ot_params;
545 struct msm_drm_private *priv;
546 struct sde_kms *sde_kms;
547
548 if (!plane || !plane->dev || !crtc) {
549 SDE_ERROR("invalid arguments plane %d crtc %d\n",
550 plane != 0, crtc != 0);
551 return;
552 }
553
554 priv = plane->dev->dev_private;
555 if (!priv || !priv->kms) {
556 SDE_ERROR("invalid KMS reference\n");
557 return;
558 }
559
560 sde_kms = to_sde_kms(priv->kms);
561 psde = to_sde_plane(plane);
562 if (!psde->pipe_hw) {
563 SDE_ERROR("invalid pipe reference\n");
564 return;
565 }
566
567 memset(&ot_params, 0, sizeof(ot_params));
568 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
569 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
570 ot_params.width = psde->pipe_cfg.src_rect.w;
571 ot_params.height = psde->pipe_cfg.src_rect.h;
572 ot_params.is_wfd = !psde->is_rt_pipe;
573 ot_params.frame_rate = crtc->mode.vrefresh;
574 ot_params.vbif_idx = VBIF_RT;
575 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
576 ot_params.rd = true;
577
578 sde_vbif_set_ot_limit(sde_kms, &ot_params);
579}
580
Clarence Ipcae1bb62016-07-07 12:07:13 -0400581/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400582static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400583 struct sde_plane_state *pstate, uint64_t fd)
584{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400585 if (!psde || !pstate) {
586 SDE_ERROR("invalid arg(s), plane %d state %d\n",
587 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400588 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400589 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400590
591 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400592 if (pstate->input_fence)
593 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400594
595 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400596 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400597
Clarence Ip13a8cf42016-09-29 17:27:47 -0400598 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400599}
600
Clarence Ipcae1bb62016-07-07 12:07:13 -0400601int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400602{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400603 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400604 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400605 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400606 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400607 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800608 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400609
610 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700611 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400612 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400613 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400614 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400615 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400616 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400617 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400618
Clarence Ipcae1bb62016-07-07 12:07:13 -0400619 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800620 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400621 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800622 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400623
Dhaval Patel39323d42017-03-01 23:48:24 -0800624 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400625 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400626 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
627 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400628 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800629 ret = -ETIMEDOUT;
630 break;
631 case -ERESTARTSYS:
632 SDE_ERROR_PLANE(psde,
633 "%ums wait interrupted on %08X\n",
634 wait_ms, prefix);
635 psde->is_error = true;
636 ret = -ERESTARTSYS;
637 break;
638 case -EINVAL:
639 SDE_ERROR_PLANE(psde,
640 "invalid fence param for %08X\n",
641 prefix);
642 psde->is_error = true;
643 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400644 break;
645 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800646 SDE_DEBUG_PLANE(psde, "signaled\n");
647 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400648 break;
649 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700650
651 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400652 } else {
653 ret = 0;
654 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400655 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400656 return ret;
657}
658
Clarence Ip282dad62016-09-27 17:07:35 -0400659static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400660 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400661 struct sde_hw_pipe_cfg *pipe_cfg,
662 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400663{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400664 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400665 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400666
Clarence Ip13a8cf42016-09-29 17:27:47 -0400667 if (!plane || !pstate || !pipe_cfg || !fb) {
668 SDE_ERROR(
669 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
670 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400671 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400672 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400673
674 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400675 if (!psde->pipe_hw) {
676 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400677 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400678 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400679
Clarence Ipb6eb2362016-09-08 16:18:13 -0400680 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
681 if (ret == -EAGAIN)
682 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
683 else if (ret)
684 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
685 else if (psde->pipe_hw->ops.setup_sourceaddress)
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800686 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
687 pstate->multirect_index);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400688}
689
abeykun48f407a2016-08-25 12:06:44 -0400690static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
691 struct sde_plane_state *pstate)
692{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500693 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400694 int ret = 0;
695
Clarence Ip3bf8d872017-02-16 15:25:38 -0500696 if (!psde || !psde->scaler3_cfg) {
697 SDE_ERROR("invalid args\n");
698 return -EINVAL;
699 } else if (!pstate) {
700 /* pstate is expected to be null on forced color fill */
701 SDE_DEBUG("null pstate\n");
702 return -EINVAL;
703 }
704
705 cfg = psde->scaler3_cfg;
706
abeykun48f407a2016-08-25 12:06:44 -0400707 cfg->dir_lut = msm_property_get_blob(
708 &psde->property_info,
709 pstate->property_blobs, &cfg->dir_len,
710 PLANE_PROP_SCALER_LUT_ED);
711 cfg->cir_lut = msm_property_get_blob(
712 &psde->property_info,
713 pstate->property_blobs, &cfg->cir_len,
714 PLANE_PROP_SCALER_LUT_CIR);
715 cfg->sep_lut = msm_property_get_blob(
716 &psde->property_info,
717 pstate->property_blobs, &cfg->sep_len,
718 PLANE_PROP_SCALER_LUT_SEP);
719 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
720 ret = -ENODATA;
721 return ret;
722}
723
Clarence Ipcb410d42016-06-26 22:52:33 -0400724static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400725 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
726 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400727 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400728 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
729{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700730 uint32_t decimated, i;
731
732 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
733 !chroma_subsmpl_v) {
734 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
735 , psde, scale_cfg, fmt, chroma_subsmpl_h,
736 chroma_subsmpl_v);
737 return;
738 }
739
740 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip716ab662017-03-20 06:51:24 -0700741 memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700742
743 decimated = DECIMATED_DIMENSION(src_w,
744 psde->pipe_cfg.horz_decimation);
745 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
746 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
747 decimated = DECIMATED_DIMENSION(src_h,
748 psde->pipe_cfg.vert_decimation);
749 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
750 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
751
752
753 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
754 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
755 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
756 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
757
758 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
759 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
760 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
761 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
762
763 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
764 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
765 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
766 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
767
768 for (i = 0; i < SDE_MAX_PLANES; i++) {
769 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
770 psde->pipe_cfg.horz_decimation);
771 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
772 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700773 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
774 scale_cfg->src_width[i] /= chroma_subsmpl_h;
775 scale_cfg->src_height[i] /= chroma_subsmpl_v;
776 }
777 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
778 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
779 psde->pixel_ext.num_ext_pxls_top[i] =
780 scale_cfg->src_height[i];
781 psde->pixel_ext.num_ext_pxls_left[i] =
782 scale_cfg->src_width[i];
783 }
784 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
785 && (src_w == dst_w))
786 return;
787
788 scale_cfg->dst_width = dst_w;
789 scale_cfg->dst_height = dst_h;
790 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
791 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
792 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
793 scale_cfg->lut_flag = 0;
794 scale_cfg->blend_cfg = 1;
795 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -0400796}
797
Clarence Ipcb410d42016-06-26 22:52:33 -0400798/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400799 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400800 * @psde: Pointer to SDE plane object
801 * @src: Source size
802 * @dst: Destination size
803 * @phase_steps: Pointer to output array for phase steps
804 * @filter: Pointer to output array for filter type
805 * @fmt: Pointer to format definition
806 * @chroma_subsampling: Subsampling amount for chroma channel
807 *
808 * Returns: 0 on success
809 */
810static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400811 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400812 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400813 uint32_t chroma_subsampling)
814{
Clarence Ipcb410d42016-06-26 22:52:33 -0400815 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400816 SDE_ERROR(
817 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
818 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400819 return -EINVAL;
820 }
821
Clarence Ip4c1d9772016-06-26 09:35:38 -0400822 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400823 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400824 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400825 phase_steps[SDE_SSPP_COMP_1_2] =
826 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
827 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
828 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400829
830 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400831 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400832 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400833 (src <= dst) ? SDE_SCALE_FILTER_BIL :
834 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400835
Clarence Ipdbde9832016-06-26 09:48:36 -0400836 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400837 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400838 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
839 } else {
840 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
841 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400842 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400843 }
844 } else {
845 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400846 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
847 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
848 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400849 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400850 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400851}
852
Clarence Ipcb410d42016-06-26 22:52:33 -0400853/**
854 * _sde_plane_setup_pixel_ext - determine default pixel extension values
855 * @psde: Pointer to SDE plane object
856 * @src: Source size
857 * @dst: Destination size
858 * @decimated_src: Source size after decimation, if any
859 * @phase_steps: Pointer to output array for phase steps
860 * @out_src: Output array for pixel extension values
861 * @out_edge1: Output array for pixel extension first edge
862 * @out_edge2: Output array for pixel extension second edge
863 * @filter: Pointer to array for filter type
864 * @fmt: Pointer to format definition
865 * @chroma_subsampling: Subsampling amount for chroma channel
866 * @post_compare: Whether to chroma subsampled source size for comparisions
867 */
868static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400869 uint32_t src, uint32_t dst, uint32_t decimated_src,
870 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400871 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400872 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400873 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400874{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400875 int64_t edge1, edge2, caf;
876 uint32_t src_work;
877 int i, tmp;
878
Clarence Ipcb410d42016-06-26 22:52:33 -0400879 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400880 out_edge2 && filter && fmt) {
881 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400882 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400883 caf = PHASE_STEP_UNIT_SCALE;
884 else
885 caf = 0;
886
887 for (i = 0; i < SDE_MAX_PLANES; i++) {
888 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400889 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400890 src_work /= chroma_subsampling;
891 if (post_compare)
892 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400893 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400894 /* unity */
895 edge1 = 0;
896 edge2 = 0;
897 } else if (dst >= src) {
898 /* upscale */
899 edge1 = (1 << PHASE_RESIDUAL);
900 edge1 -= caf;
901 edge2 = (1 << PHASE_RESIDUAL);
902 edge2 += (dst - 1) * *(phase_steps + i);
903 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
904 edge2 += caf;
905 edge2 = -(edge2);
906 } else {
907 /* downscale */
908 edge1 = 0;
909 edge2 = (dst - 1) * *(phase_steps + i);
910 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
911 edge2 += *(phase_steps + i);
912 edge2 = -(edge2);
913 }
914
915 /* only enable CAF for luma plane */
916 caf = 0;
917
918 /* populate output arrays */
919 *(out_src + i) = src_work;
920
921 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400922 if (edge1 >= 0) {
923 tmp = (uint32_t)edge1;
924 tmp >>= PHASE_STEP_SHIFT;
925 *(out_edge1 + i) = -tmp;
926 } else {
927 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400928 *(out_edge1 + i) =
929 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
930 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400931 }
932 if (edge2 >= 0) {
933 tmp = (uint32_t)edge2;
934 tmp >>= PHASE_STEP_SHIFT;
935 *(out_edge2 + i) = -tmp;
936 } else {
937 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400938 *(out_edge2 + i) =
939 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
940 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400941 }
942 }
943 }
944}
945
Clarence Ip5fc00c52016-09-23 15:03:34 -0400946static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400947{
948 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
949 {
Clarence Ip373f8592016-05-26 00:58:42 -0400950 /* S15.16 format */
951 0x00012A00, 0x00000000, 0x00019880,
952 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
953 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400954 },
Clarence Ip373f8592016-05-26 00:58:42 -0400955 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400956 { 0xfff0, 0xff80, 0xff80,},
957 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400958 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400959 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400960 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400961 };
abeykun1c312f62016-08-26 09:47:12 -0400962 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
963 {
964 /* S15.16 format */
965 0x00012A00, 0x00000000, 0x00019880,
966 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
967 0x00012A00, 0x00020480, 0x00000000,
968 },
969 /* signed bias */
970 { 0xffc0, 0xfe00, 0xfe00,},
971 { 0x0, 0x0, 0x0,},
972 /* unsigned clamp */
973 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
974 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
975 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400976
Clarence Ip5fc00c52016-09-23 15:03:34 -0400977 if (!psde) {
978 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400979 return;
980 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400981
Clarence Ipcae1bb62016-07-07 12:07:13 -0400982 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400983 if (psde->csc_usr_ptr)
984 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400985 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
986 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400987 else
Clarence Ip373f8592016-05-26 00:58:42 -0400988 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400989
Clarence Ip13a8cf42016-09-29 17:27:47 -0400990 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400991 psde->csc_ptr->csc_mv[0],
992 psde->csc_ptr->csc_mv[1],
993 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400994}
995
Benet Clarkeb1b4462016-06-27 14:43:06 -0700996static void sde_color_process_plane_setup(struct drm_plane *plane)
997{
998 struct sde_plane *psde;
999 struct sde_plane_state *pstate;
1000 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001001 struct drm_msm_memcol *memcol = NULL;
1002 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001003
1004 psde = to_sde_plane(plane);
1005 pstate = to_sde_plane_state(plane->state);
1006
1007 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1008 if (psde->pipe_hw->ops.setup_pa_hue)
1009 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1010 saturation = (uint32_t) sde_plane_get_property(pstate,
1011 PLANE_PROP_SATURATION_ADJUST);
1012 if (psde->pipe_hw->ops.setup_pa_sat)
1013 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1014 value = (uint32_t) sde_plane_get_property(pstate,
1015 PLANE_PROP_VALUE_ADJUST);
1016 if (psde->pipe_hw->ops.setup_pa_val)
1017 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1018 contrast = (uint32_t) sde_plane_get_property(pstate,
1019 PLANE_PROP_CONTRAST_ADJUST);
1020 if (psde->pipe_hw->ops.setup_pa_cont)
1021 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001022
Benet Clarkd009b1d2016-06-27 14:45:59 -07001023 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1024 /* Skin memory color setup */
1025 memcol = msm_property_get_blob(&psde->property_info,
1026 pstate->property_blobs,
1027 &memcol_sz,
1028 PLANE_PROP_SKIN_COLOR);
1029 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1030 MEMCOLOR_SKIN, memcol);
1031
1032 /* Sky memory color setup */
1033 memcol = msm_property_get_blob(&psde->property_info,
1034 pstate->property_blobs,
1035 &memcol_sz,
1036 PLANE_PROP_SKY_COLOR);
1037 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1038 MEMCOLOR_SKY, memcol);
1039
1040 /* Foliage memory color setup */
1041 memcol = msm_property_get_blob(&psde->property_info,
1042 pstate->property_blobs,
1043 &memcol_sz,
1044 PLANE_PROP_FOLIAGE_COLOR);
1045 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1046 MEMCOLOR_FOLIAGE, memcol);
1047 }
1048}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001049
Clarence Ipcb410d42016-06-26 22:52:33 -04001050static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001051 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -04001052 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001053{
Clarence Ipb43d4592016-09-08 14:21:35 -04001054 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001055 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001056
Clarence Ipb43d4592016-09-08 14:21:35 -04001057 if (!psde || !fmt) {
1058 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1059 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001060 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001061 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001062
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001063 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001064
Clarence Ipdedbba92016-09-27 17:43:10 -04001065 psde->pipe_cfg.horz_decimation =
1066 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1067 psde->pipe_cfg.vert_decimation =
1068 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001069
1070 /* don't chroma subsample if decimating */
1071 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001072 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001073 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001074 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001075
Clarence Ip5e2a9222016-06-26 22:38:24 -04001076 /* update scaler */
1077 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001078 int error;
1079
1080 error = _sde_plane_setup_scaler3_lut(psde, pstate);
Clarence Ip716ab662017-03-20 06:51:24 -07001081 if (error || !psde->pixel_ext_usr ||
1082 psde->debugfs_default_scale) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001083 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001084 _sde_plane_setup_scaler3(psde,
1085 psde->pipe_cfg.src_rect.w,
1086 psde->pipe_cfg.src_rect.h,
1087 psde->pipe_cfg.dst_rect.w,
1088 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001089 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001090 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001091 }
Clarence Ip716ab662017-03-20 06:51:24 -07001092 } else if (!psde->pixel_ext_usr || !pstate ||
1093 psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001094 uint32_t deci_dim, i;
1095
Clarence Ipb43d4592016-09-08 14:21:35 -04001096 /* calculate default configuration for QSEED2 */
1097 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001098
Clarence Ip13a8cf42016-09-29 17:27:47 -04001099 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001100 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1101 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001102 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001103 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001104 psde->pipe_cfg.dst_rect.w,
1105 pe->phase_step_x,
1106 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001107
Clarence Ipdbde9832016-06-26 09:48:36 -04001108 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001109 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001110 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001111 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001112 pe->phase_step_x,
1113 pe->roi_w,
1114 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001115 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001116 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001117
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001118 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001119 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001120 _sde_plane_setup_scaler2(psde,
1121 deci_dim,
1122 psde->pipe_cfg.dst_rect.h,
1123 pe->phase_step_y,
1124 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001125 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001126 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001127 pe->phase_step_y,
1128 pe->roi_h,
1129 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001130 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001131 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001132
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001133 for (i = 0; i < SDE_MAX_PLANES; i++) {
1134 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001135 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001136 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001137 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001138
1139 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001140 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001141 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001142 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001143
1144 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001145 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001146 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001147 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001148
1149 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001150 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001151 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001152 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001153 }
1154 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001155}
1156
Clarence Ipcae1bb62016-07-07 12:07:13 -04001157/**
1158 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001159 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001160 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1161 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1162 * Returns: 0 on success
1163 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001164static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001165 uint32_t color, uint32_t alpha)
1166{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001167 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001168 const struct drm_plane *plane;
1169 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001170
Clarence Ip13a8cf42016-09-29 17:27:47 -04001171 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001172 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001173 return -EINVAL;
1174 }
1175
Clarence Ipcb410d42016-06-26 22:52:33 -04001176 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001177 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001178 return -EINVAL;
1179 }
1180
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001181 plane = &psde->base;
1182 pstate = to_sde_plane_state(plane->state);
1183
Clarence Ip13a8cf42016-09-29 17:27:47 -04001184 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001185
Clarence Ipcb410d42016-06-26 22:52:33 -04001186 /*
1187 * select fill format to match user property expectation,
1188 * h/w only supports RGB variants
1189 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001190 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001191
1192 /* update sspp */
1193 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1194 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001195 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1196 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001197
1198 /* override scaler/decimation if solid fill */
1199 psde->pipe_cfg.src_rect.x = 0;
1200 psde->pipe_cfg.src_rect.y = 0;
1201 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1202 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Dhaval Patele4b6bb22017-03-27 17:22:21 -07001203 _sde_plane_setup_scaler(psde, fmt, 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001204
Clarence Ipcb410d42016-06-26 22:52:33 -04001205 if (psde->pipe_hw->ops.setup_format)
1206 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001207 fmt, SDE_SSPP_SOLID_FILL,
1208 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001209
1210 if (psde->pipe_hw->ops.setup_rects)
1211 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001212 &psde->pipe_cfg,
1213 pstate->multirect_index);
1214
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001215 if (psde->pipe_hw->ops.setup_pe)
1216 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1217 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001218 }
1219
1220 return 0;
1221}
1222
Alan Kwong4dd64c82017-02-04 18:41:51 -08001223/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001224 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1225 */
1226static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1227{
1228 drm_framebuffer_reference(fb);
1229 return fb;
1230}
1231static void _sde_plane_fb_put(void *fb)
1232{
1233 drm_framebuffer_unreference(fb);
1234}
1235static struct sde_crtc_res_ops fb_res_ops = {
1236 .put = _sde_plane_fb_put,
1237 .get = _sde_plane_fb_get,
1238};
1239
1240/**
1241 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1242 */
1243static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1244{
1245 sde_kms_fbo_reference(fbo);
1246 return fbo;
1247}
1248static void _sde_plane_fbo_put(void *fbo)
1249{
1250 sde_kms_fbo_unreference(fbo);
1251}
1252static struct sde_crtc_res_ops fbo_res_ops = {
1253 .put = _sde_plane_fbo_put,
1254 .get = _sde_plane_fbo_get,
1255};
1256
1257/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001258 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001259 * @plane: Pointer to drm plane
1260 * return: prefill time in line
1261 */
1262static u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
1263{
1264 struct drm_plane_state *state;
1265 struct drm_crtc_state *cstate;
1266 struct sde_plane_state *pstate;
1267 struct sde_plane_rot_state *rstate;
1268 struct sde_kms *sde_kms;
1269 u32 blocksize = 128;
1270 u32 prefill_line = 0;
1271
1272 if (!plane || !plane->state || !plane->state->fb ||
1273 !plane->state->crtc || !plane->state->crtc->state) {
1274 SDE_ERROR("invalid parameters\n");
1275 return 0;
1276 }
1277
1278 sde_kms = _sde_plane_get_kms(plane);
1279 state = plane->state;
1280 cstate = state->crtc->state;
1281 pstate = to_sde_plane_state(state);
1282 rstate = &pstate->rot;
1283
1284 if (!rstate->rot_hw || !rstate->rot_hw->caps || !rstate->out_src_h ||
1285 !sde_kms || !sde_kms->catalog) {
1286 SDE_ERROR("invalid parameters\n");
1287 return 0;
1288 }
1289
Alan Kwong4aacd532017-02-04 18:51:33 -08001290 sde_format_get_block_size(rstate->out_fb_format, &blocksize,
1291 &blocksize);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001292 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
1293
1294 SDE_DEBUG("plane%d prefill:%u\n", plane->base.id, prefill_line);
1295
1296 return prefill_line;
1297}
1298
1299/**
1300 * sde_plane_is_sbuf_mode - check if sspp of given plane is in streaming
1301 * buffer mode
1302 * @plane: Pointer to drm plane
1303 * @prefill: Pointer to prefill line count
1304 * return: true if sspp is in stream buffer mode
1305 */
1306bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill)
1307{
1308 struct sde_plane_state *pstate = plane && plane->state ?
1309 to_sde_plane_state(plane->state) : NULL;
1310 struct sde_plane_rot_state *rstate = pstate ? &pstate->rot : NULL;
1311 bool sbuf_mode = rstate ? rstate->out_sbuf : false;
1312
1313 if (prefill && sbuf_mode)
1314 *prefill = sde_plane_rot_calc_prefill(plane);
1315
1316 return sbuf_mode;
1317}
1318
1319/**
1320 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1321 * enumerating over all planes attached to the same rotator
1322 * @plane: Pointer to drm plane
1323 * @state: Pointer to drm state to be updated
1324 * return: none
1325 */
1326static void sde_plane_rot_calc_cfg(struct drm_plane *plane,
1327 struct drm_plane_state *state)
1328{
1329 struct sde_plane_state *pstate;
1330 struct sde_plane_rot_state *rstate;
1331 struct sde_hw_blk *hw_blk;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001332 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001333 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001334 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001335 u32 dst_x, dst_y, dst_w, dst_h;
1336 int found = 0;
1337 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001338 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001339
1340 if (!plane || !state || !state->state) {
1341 SDE_ERROR("invalid parameters\n");
1342 return;
1343 }
1344
Alan Kwongcdb2f282017-03-18 13:42:06 -07001345 cstate = _sde_plane_get_crtc_state(state);
1346 if (IS_ERR_OR_NULL(cstate)) {
1347 ret = PTR_ERR(cstate);
1348 SDE_ERROR("invalid crtc state %d\n", ret);
1349 return;
1350 }
1351
Alan Kwong4dd64c82017-02-04 18:41:51 -08001352 pstate = to_sde_plane_state(state);
1353 rstate = &pstate->rot;
1354
1355 if (!rstate->rot_hw) {
1356 SDE_ERROR("invalid rotator hw\n");
1357 return;
1358 }
1359
1360 in_rot = &rstate->in_rot_rect;
1361 in_rot->x1 = state->src_x;
1362 in_rot->y1 = state->src_y;
1363 in_rot->x2 = state->src_x + state->src_w;
1364 in_rot->y2 = state->src_y + state->src_h;
1365
1366 out_rot = &rstate->out_rot_rect;
1367 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1368 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1369 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1370 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1371
1372 if (!dst_w && !dst_h) {
1373 rstate->out_rot_rect = rstate->in_rot_rect;
1374 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1375 state->fb->height << 16, rstate->in_rotation);
1376 } else {
1377 out_rot->x1 = dst_x;
1378 out_rot->y1 = dst_y;
1379 out_rot->x2 = dst_x + dst_w;
1380 out_rot->y2 = dst_y + dst_h;
1381 }
1382
1383 rstate->out_src_rect = rstate->out_rot_rect;
1384
1385 hw_blk = &rstate->rot_hw->base;
1386
1387 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001388 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001389 struct drm_plane_state *attached_state;
1390 struct sde_plane_state *attached_pstate;
1391 struct sde_plane_rot_state *attached_rstate;
1392 struct drm_rect attached_out_rect;
1393
Alan Kwong4dd64c82017-02-04 18:41:51 -08001394 attached_state = drm_atomic_get_existing_plane_state(
1395 state->state, attached_plane);
1396
1397 if (!attached_state)
1398 continue;
1399
1400 attached_pstate = to_sde_plane_state(attached_state);
1401 attached_rstate = &attached_pstate->rot;
1402
Alan Kwongcdb2f282017-03-18 13:42:06 -07001403 if (attached_rstate->rot_hw != rstate->rot_hw)
1404 continue;
1405
1406 found++;
1407
1408 /* skip itself */
1409 if (attached_plane == plane)
1410 continue;
1411
Alan Kwong4dd64c82017-02-04 18:41:51 -08001412 /* find bounding rotator source roi */
1413 if (attached_state->src_x < in_rot->x1)
1414 in_rot->x1 = attached_state->src_x;
1415
1416 if (attached_state->src_y < in_rot->y1)
1417 in_rot->y1 = attached_state->src_y;
1418
1419 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1420 in_rot->x2 = attached_state->src_x +
1421 attached_state->src_w;
1422
1423 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1424 in_rot->y2 = attached_state->src_y +
1425 attached_state->src_h;
1426
1427 /* find bounding rotator destination roi */
1428 dst_x = sde_plane_get_property(attached_pstate,
1429 PLANE_PROP_ROT_DST_X);
1430 dst_y = sde_plane_get_property(attached_pstate,
1431 PLANE_PROP_ROT_DST_Y);
1432 dst_w = sde_plane_get_property(attached_pstate,
1433 PLANE_PROP_ROT_DST_W);
1434 dst_h = sde_plane_get_property(attached_pstate,
1435 PLANE_PROP_ROT_DST_H);
1436 if (!dst_w && !dst_h) {
1437 attached_out_rect.x1 = attached_state->src_x;
1438 attached_out_rect.y1 = attached_state->src_y;
1439 attached_out_rect.x2 = attached_out_rect.x1 +
1440 attached_state->src_w;
1441 attached_out_rect.y2 = attached_out_rect.y1 +
1442 attached_state->src_h;
1443 drm_rect_rotate(&attached_out_rect,
1444 state->fb->width << 16,
1445 state->fb->height << 16,
1446 rstate->in_rotation);
1447 } else {
1448 attached_out_rect.x1 = dst_x;
1449 attached_out_rect.y1 = dst_y;
1450 attached_out_rect.x2 = dst_x + dst_w;
1451 attached_out_rect.y2 = dst_y + dst_h;
1452 }
1453
1454 /* find relative sspp position */
1455 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1456 xpos++;
1457
1458 if (attached_out_rect.x1 < out_rot->x1)
1459 out_rot->x1 = attached_out_rect.x1;
1460
1461 if (attached_out_rect.y1 < out_rot->y1)
1462 out_rot->y1 = attached_out_rect.y1;
1463
1464 if (attached_out_rect.x2 > out_rot->x2)
1465 out_rot->x2 = attached_out_rect.x2;
1466
1467 if (attached_out_rect.y2 > out_rot->y2)
1468 out_rot->y2 = attached_out_rect.y2;
1469
1470 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1471 attached_plane->base.id,
1472 attached_rstate->sequence_id,
1473 attached_rstate->out_src_rect.x1 >> 16,
1474 attached_state->src_w >> 16,
1475 attached_state->src_h >> 16,
1476 attached_state->src_x >> 16,
1477 attached_state->src_y >> 16,
1478 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1479 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1480 attached_rstate->out_src_rect.x1 >> 16,
1481 attached_rstate->out_src_rect.y1 >> 16);
1482 }
1483
1484 rstate->out_xpos = xpos;
1485 rstate->nplane = found;
1486
1487 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1488 plane->base.id, rstate->sequence_id,
1489 rstate->out_xpos, rstate->nplane,
1490 drm_rect_width(in_rot) >> 16,
1491 drm_rect_height(in_rot) >> 16,
1492 in_rot->x1 >> 16, in_rot->y1 >> 16,
1493 drm_rect_width(&rstate->out_rot_rect) >> 16,
1494 drm_rect_height(&rstate->out_rot_rect) >> 16,
1495 rstate->out_rot_rect.x1 >> 16,
1496 rstate->out_rot_rect.y1 >> 16);
1497}
1498
1499/**
1500 * sde_plane_rot_submit_command - commit given state for the rotator stage
1501 * @plane: Pointer to drm plane
1502 * @state: Pointer to the state to be committed
1503 * @hw_cmd: rotator command type
1504 * return: 0 if success; error code otherwise
1505 */
1506static int sde_plane_rot_submit_command(struct drm_plane *plane,
1507 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1508{
1509 struct sde_plane *psde = to_sde_plane(plane);
1510 struct sde_plane_state *pstate = to_sde_plane_state(state);
1511 struct sde_plane_rot_state *rstate = &pstate->rot;
1512 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001513 struct drm_crtc_state *cstate;
1514 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001515 int ret, i;
1516
1517 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1518 SDE_ERROR("invalid parameters\n");
1519 return -EINVAL;
1520 }
1521
Alan Kwong4aacd532017-02-04 18:51:33 -08001522 cstate = _sde_plane_get_crtc_state(state);
1523 if (IS_ERR_OR_NULL(cstate)) {
1524 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1525 return -EINVAL;
1526 }
1527 sde_cstate = to_sde_crtc_state(cstate);
1528
Alan Kwong4dd64c82017-02-04 18:41:51 -08001529 rot_cmd = &rstate->rot_cmd;
1530
1531 rot_cmd->master = (rstate->out_xpos == 0);
1532 rot_cmd->sequence_id = rstate->sequence_id;
1533 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1534 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1535 DEFAULT_REFRESH_RATE;
1536 rot_cmd->rot90 = rstate->rot90;
1537 rot_cmd->hflip = rstate->hflip;
1538 rot_cmd->vflip = rstate->vflip;
1539 rot_cmd->secure = state->fb->flags & DRM_MODE_FB_SECURE ? true : false;
Alan Kwong4aacd532017-02-04 18:51:33 -08001540 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1541 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001542 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1543 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001544 rot_cmd->dst_writeback = psde->sbuf_writeback;
1545
1546 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1547 rot_cmd->video_mode = true;
1548 else
1549 rot_cmd->video_mode = false;
1550
1551 rot_cmd->src_pixel_format = state->fb->pixel_format;
1552 rot_cmd->src_modifier = state->fb->modifier[0];
1553 rot_cmd->src_stride = state->fb->pitches[0];
1554
1555 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1556 if (!rot_cmd->src_format) {
1557 SDE_ERROR("failed to get src format\n");
1558 return -EINVAL;
1559 }
1560
1561 rot_cmd->src_width = state->fb->width;
1562 rot_cmd->src_height = state->fb->height;
1563 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1564 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1565 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1566 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
1567 rot_cmd->dst_rect_x = rstate->out_rot_rect.x1 >> 16;
1568 rot_cmd->dst_rect_y = rstate->out_rot_rect.y1 >> 16;
1569 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1570 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1571
1572 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1573 struct sde_hw_fmt_layout layout;
1574
1575 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1576 sde_format_populate_layout(rstate->mmu_id, state->fb,
1577 &layout);
1578 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1579 rot_cmd->src_iova[i] = layout.plane_addr[i];
1580 rot_cmd->src_len[i] = layout.plane_size[i];
1581 }
1582 rot_cmd->src_planes = layout.num_planes;
1583
1584 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1585 sde_format_populate_layout(rstate->mmu_id, rstate->out_fb,
1586 &layout);
1587 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1588 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1589 rot_cmd->dst_len[i] = layout.plane_size[i];
1590 }
1591 rot_cmd->dst_planes = layout.num_planes;
1592 }
1593
1594 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
1595 if (ret) {
1596 SDE_ERROR("failed to commit rotator %d\n", ret);
1597 return ret;
1598 }
1599
1600 rstate->out_rotation = rstate->in_rotation;
1601 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1602 DRM_MODE_FB_MODIFIERS : 0;
1603 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1604 rstate->out_fb_format = rot_cmd->dst_format;
1605 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1606
1607 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1608 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1609
1610 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1611 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1612 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1613 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1614 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1615 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1616
1617 if (rot_cmd->rot90)
1618 rstate->out_rotation &= ~DRM_ROTATE_90;
1619
1620 if (rot_cmd->hflip)
1621 rstate->out_rotation &= ~DRM_REFLECT_X;
1622
1623 if (rot_cmd->vflip)
1624 rstate->out_rotation &= ~DRM_REFLECT_Y;
1625
1626 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07001627 "plane%d.%d rot:%d/%c%c%c%c/%dx%d/%4.4s/%llx/%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001628 plane->base.id, rstate->sequence_id, hw_cmd,
1629 rot_cmd->rot90 ? 'r' : '_',
1630 rot_cmd->hflip ? 'h' : '_',
1631 rot_cmd->vflip ? 'v' : '_',
1632 rot_cmd->video_mode ? 'V' : 'C',
1633 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001634 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001635 state->fb->modifier[0],
1636 drm_rect_width(&rstate->in_rot_rect) >> 16,
1637 drm_rect_height(&rstate->in_rot_rect) >> 16,
1638 rstate->in_rot_rect.x1 >> 16,
1639 rstate->in_rot_rect.y1 >> 16);
1640
Dhaval Patel6c666622017-03-21 23:02:59 -07001641 SDE_DEBUG("plane%d.%d sspp:%d/%x/%dx%d/%4.4s/%llx/%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001642 plane->base.id, rstate->sequence_id, hw_cmd,
1643 rstate->out_rotation,
1644 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001645 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001646 rstate->out_fb_modifier[0],
1647 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
1648 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
1649
1650 return ret;
1651}
1652
1653/**
1654 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
1655 * for rotator (pre-sspp) stage
1656 * @plane: Pointer to drm plane
1657 * @new_state: Pointer to new drm plane state
1658 * return: 0 if success; error code otherwise
1659 */
1660static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
1661 struct drm_plane_state *new_state)
1662{
1663 struct drm_framebuffer *fb = new_state->fb;
1664 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
1665 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001666 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001667 int ret;
1668
1669 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
1670 plane->base.id,
1671 new_rstate->sequence_id, fb ? fb->base.id : 0,
1672 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
1673 sde_plane_crtc_enabled(new_state));
1674
1675 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
1676 return 0;
1677
Alan Kwongcdb2f282017-03-18 13:42:06 -07001678 cstate = _sde_plane_get_crtc_state(new_state);
1679 if (IS_ERR(cstate)) {
1680 ret = PTR_ERR(cstate);
1681 SDE_ERROR("invalid crtc state %d\n", ret);
1682 return ret;
1683 }
1684
Alan Kwong4dd64c82017-02-04 18:41:51 -08001685 /* need to re-calc based on all newly validated plane states */
1686 sde_plane_rot_calc_cfg(plane, new_state);
1687
1688 /* check if stream buffer is already attached to rotator */
1689 if (sde_plane_enabled(new_state)) {
1690 struct sde_kms_fbo *fbo;
1691 struct drm_framebuffer *fb;
1692
Alan Kwongcdb2f282017-03-18 13:42:06 -07001693 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1694 (u64) &new_rstate->rot_hw->base);
1695 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1696 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001697 if (fb && fbo) {
1698 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
1699 new_rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001700 } else if (fbo) {
1701 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1702 (u64) &new_rstate->rot_hw->base);
1703 fbo = NULL;
1704 } else if (fb) {
1705 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1706 (u64) &new_rstate->rot_hw->base);
1707 fb = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001708 }
Alan Kwongcdb2f282017-03-18 13:42:06 -07001709
1710 new_rstate->out_fbo = fbo;
1711 new_rstate->out_fb = fb;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001712 }
1713
1714 /* release buffer if output format configuration changes */
1715 if (new_rstate->out_fb &&
1716 ((new_rstate->out_fb_height != new_rstate->out_fb->height) ||
1717 (new_rstate->out_fb_width != new_rstate->out_fb->width) ||
1718 (new_rstate->out_fb_pixel_format !=
1719 new_rstate->out_fb->pixel_format) ||
1720 (new_rstate->out_fb_modifier[0] !=
1721 new_rstate->out_fb->modifier[0]) ||
1722 (new_rstate->out_fb_flags != new_rstate->out_fb->flags))) {
1723
1724 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
1725 new_rstate->sequence_id);
1726
Alan Kwongcdb2f282017-03-18 13:42:06 -07001727 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1728 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001729 new_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001730 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1731 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001732 new_rstate->out_fbo = NULL;
1733 }
1734
1735 /* create new stream buffer if it is not available */
1736 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
1737 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
1738 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
1739
1740 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
1741 new_rstate->sequence_id);
1742
1743 if (new_state->fb->flags & DRM_MODE_FB_SECURE)
1744 new_rstate->mmu_id = MSM_SMMU_DOMAIN_SECURE;
1745 else
1746 new_rstate->mmu_id = MSM_SMMU_DOMAIN_UNSECURE;
1747
1748 /* check if out_fb is already attached to rotator */
1749 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
1750 new_rstate->out_fb_pixel_format,
1751 new_rstate->out_fb_modifier,
1752 new_rstate->out_fb_flags);
1753 if (!new_rstate->out_fbo) {
1754 SDE_ERROR("failed to allocate inline buffer object\n");
1755 ret = -EINVAL;
1756 goto error_create_fbo;
1757 }
1758
Alan Kwongcdb2f282017-03-18 13:42:06 -07001759 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1760 (u64) &new_rstate->rot_hw->base,
1761 new_rstate->out_fbo, &fbo_res_ops);
1762 if (ret) {
1763 SDE_ERROR("failed to add crtc resource\n");
1764 goto error_create_fbo_res;
1765 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001766
1767 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
1768 new_rstate->out_fbo);
1769 if (!new_rstate->out_fb) {
1770 SDE_ERROR("failed to create inline framebuffer\n");
1771 ret = -EINVAL;
1772 goto error_create_fb;
1773 }
1774
Alan Kwongcdb2f282017-03-18 13:42:06 -07001775 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1776 (u64) &new_rstate->rot_hw->base,
1777 new_rstate->out_fb, &fb_res_ops);
1778 if (ret) {
1779 SDE_ERROR("failed to add crtc resource %d\n", ret);
1780 goto error_create_fb_res;
1781 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001782 }
1783
1784 /* prepare rotator input buffer */
1785 ret = msm_framebuffer_prepare(new_state->fb, new_rstate->mmu_id);
1786 if (ret) {
1787 SDE_ERROR("failed to prepare input framebuffer\n");
1788 goto error_prepare_input_buffer;
1789 }
1790
1791 /* prepare rotator output buffer */
1792 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
1793 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
1794 new_rstate->sequence_id);
1795
1796 ret = msm_framebuffer_prepare(new_rstate->out_fb,
1797 new_rstate->mmu_id);
1798 if (ret) {
1799 SDE_ERROR("failed to prepare inline framebuffer\n");
1800 goto error_prepare_output_buffer;
1801 }
1802 }
1803
1804 return 0;
1805
1806error_prepare_output_buffer:
1807 msm_framebuffer_cleanup(new_state->fb, new_rstate->mmu_id);
1808error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001809 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1810 (u64) &new_rstate->rot_hw->base);
1811error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001812 new_rstate->out_fb = NULL;
1813error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001814 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1815 (u64) &new_rstate->rot_hw->base);
1816error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001817 new_rstate->out_fbo = NULL;
1818error_create_fbo:
1819 return ret;
1820}
1821
1822/**
1823 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
1824 * rotator (pre-sspp) stage
1825 * @plane: Pointer to drm plane
1826 * @old_state: Pointer to previous drm plane state
1827 * return: none
1828 */
1829static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
1830 struct drm_plane_state *old_state)
1831{
1832 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
1833 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
1834 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001835 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001836 int ret;
1837
1838 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1839 old_rstate->sequence_id, old_state->fb->base.id,
1840 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
1841 sde_plane_crtc_enabled(old_state));
1842
1843 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
1844 return;
1845
Alan Kwongcdb2f282017-03-18 13:42:06 -07001846 cstate = _sde_plane_get_crtc_state(old_state);
1847 if (IS_ERR(cstate)) {
1848 ret = PTR_ERR(cstate);
1849 SDE_ERROR("invalid crtc state %d\n", ret);
1850 return;
1851 }
1852
Alan Kwong4dd64c82017-02-04 18:41:51 -08001853 if (sde_plane_crtc_enabled(old_state)) {
1854 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
1855 SDE_HW_ROT_CMD_CLEANUP);
1856 if (ret)
1857 SDE_ERROR("failed to cleanup rotator buffers\n");
1858 }
1859
1860 if (sde_plane_enabled(old_state)) {
1861 if (old_rstate->out_fb) {
1862 msm_framebuffer_cleanup(old_rstate->out_fb,
1863 old_rstate->mmu_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001864 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1865 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001866 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001867 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1868 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001869 old_rstate->out_fbo = NULL;
1870 }
1871
1872 msm_framebuffer_cleanup(old_state->fb, old_rstate->mmu_id);
1873 }
1874}
1875
1876/**
1877 * sde_plane_rot_atomic_check - verify rotator update of the given state
1878 * @plane: Pointer to drm plane
1879 * @state: Pointer to drm plane state to be validated
1880 * return: 0 if success; error code otherwise
1881 */
1882static int sde_plane_rot_atomic_check(struct drm_plane *plane,
1883 struct drm_plane_state *state)
1884{
1885 struct sde_plane *psde;
1886 struct sde_plane_state *pstate, *old_pstate;
1887 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001888 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001889 struct sde_hw_blk *hw_blk;
1890 int i, ret = 0;
1891
1892 if (!plane || !state) {
1893 SDE_ERROR("invalid plane/state\n");
1894 return -EINVAL;
1895 }
1896
1897 psde = to_sde_plane(plane);
1898 pstate = to_sde_plane_state(state);
1899 old_pstate = to_sde_plane_state(plane->state);
1900 rstate = &pstate->rot;
1901 old_rstate = &old_pstate->rot;
1902
Alan Kwongcdb2f282017-03-18 13:42:06 -07001903 /* cstate will be null if crtc is disconnected from plane */
1904 cstate = _sde_plane_get_crtc_state(state);
1905 if (IS_ERR(cstate)) {
1906 ret = PTR_ERR(cstate);
1907 SDE_ERROR("invalid crtc state %d\n", ret);
1908 return ret;
1909 }
1910
Alan Kwong4dd64c82017-02-04 18:41:51 -08001911 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1912 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
1913 !!rstate->out_sbuf, !!rstate->rot_hw,
1914 sde_plane_crtc_enabled(state));
1915
1916 rstate->in_rotation = drm_rotation_simplify(
1917 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07001918 DRM_ROTATE_0 | DRM_ROTATE_90 |
1919 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001920 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
1921 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
1922 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
1923 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
1924
Alan Kwongcdb2f282017-03-18 13:42:06 -07001925 if (sde_plane_enabled(state) && rstate->out_sbuf) {
1926 SDE_DEBUG("plane%d.%d acquire rotator\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001927 plane->base.id, rstate->sequence_id);
1928
Alan Kwongcdb2f282017-03-18 13:42:06 -07001929 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
1930 (u64) state->fb);
1931 if (!hw_blk) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001932 SDE_ERROR("plane%d no available rotator\n",
1933 plane->base.id);
1934 return -EINVAL;
1935 }
1936
Alan Kwongcdb2f282017-03-18 13:42:06 -07001937 rstate->rot_hw = to_sde_hw_rot(hw_blk);
1938
Alan Kwong4dd64c82017-02-04 18:41:51 -08001939 if (!rstate->rot_hw->ops.commit) {
1940 SDE_ERROR("plane%d invalid rotator ops\n",
1941 plane->base.id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001942 sde_crtc_res_put(cstate,
1943 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001944 rstate->rot_hw = NULL;
1945 return -EINVAL;
1946 }
1947
1948 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001949 } else {
1950 rstate->in_fb = NULL;
1951 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001952 }
1953
1954 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
1955
1956 SDE_DEBUG("plane%d.%d use rotator\n",
1957 plane->base.id, rstate->sequence_id);
1958
1959 sde_plane_rot_calc_cfg(plane, state);
1960
1961 ret = sde_plane_rot_submit_command(plane, state,
1962 SDE_HW_ROT_CMD_VALIDATE);
1963
Clarence Ip4475d582017-04-18 11:36:00 -04001964 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001965
1966 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
1967 rstate->sequence_id);
1968
1969 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04001970 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1971 rstate->out_fb_modifier[i] = state->fb ?
1972 state->fb->modifier[i] : 0x0;
1973
1974 if (state->fb) {
1975 rstate->out_fb_pixel_format = state->fb->pixel_format;
1976 rstate->out_fb_flags = state->fb->flags;
1977 rstate->out_fb_width = state->fb->width;
1978 rstate->out_fb_height = state->fb->height;
1979 } else {
1980 rstate->out_fb_pixel_format = 0x0;
1981 rstate->out_fb_flags = 0x0;
1982 rstate->out_fb_width = 0;
1983 rstate->out_fb_height = 0;
1984 }
1985
Alan Kwong4dd64c82017-02-04 18:41:51 -08001986 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001987 rstate->out_src_x = state->src_x;
1988 rstate->out_src_y = state->src_y;
1989 rstate->out_src_w = state->src_w;
1990 rstate->out_src_h = state->src_h;
1991
1992 rstate->out_fb_format = NULL;
1993 rstate->out_sbuf = false;
1994 rstate->out_fb = state->fb;
1995 }
1996
1997 return ret;
1998}
1999
2000/**
2001 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2002 * @plane: Pointer to drm plane
2003 * @old_state: Pointer to previous state
2004 * return: none
2005 */
2006static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2007 struct drm_plane_state *old_state)
2008{
2009 struct drm_plane_state *state;
2010 struct sde_plane_state *pstate;
2011 struct sde_plane_rot_state *rstate;
2012
2013 if (!plane || !plane->state) {
2014 SDE_ERROR("invalid plane/state\n");
2015 return;
2016 }
2017
2018 state = plane->state;
2019 pstate = to_sde_plane_state(state);
2020 rstate = &pstate->rot;
2021
2022 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2023 rstate->sequence_id,
2024 !!rstate->out_sbuf, !!rstate->rot_hw,
2025 sde_plane_crtc_enabled(plane->state));
2026
2027 if (!sde_plane_crtc_enabled(state))
2028 return;
2029
2030 if (!rstate->out_sbuf || !rstate->rot_hw)
2031 return;
2032
2033 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
2034}
2035
2036/**
2037 * sde_plane_rot_destroy_state - destroy state for rotator stage
2038 * @plane: Pointer to drm plane
2039 * @state: Pointer to state to be destroyed
2040 * return: none
2041 */
2042static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2043 struct drm_plane_state *state)
2044{
2045 struct sde_plane_state *pstate = to_sde_plane_state(state);
2046 struct sde_plane_rot_state *rstate = &pstate->rot;
2047
2048 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2049 rstate->sequence_id,
2050 !!rstate->out_sbuf, !!rstate->rot_hw,
2051 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002052}
2053
2054/**
2055 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2056 * @plane: Pointer to drm plane
2057 * @new_state: Pointer to duplicated state
2058 * return: 0 if success; error code otherwise
2059 */
2060static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2061 struct drm_plane_state *new_state)
2062{
2063 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2064 struct sde_plane_rot_state *rstate = &pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002065 struct drm_crtc_state *cstate;
2066 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002067
2068 rstate->sequence_id++;
2069
2070 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2071 rstate->sequence_id,
2072 !!rstate->out_sbuf, !!rstate->rot_hw);
2073
Alan Kwongcdb2f282017-03-18 13:42:06 -07002074 cstate = _sde_plane_get_crtc_state(new_state);
2075 if (IS_ERR(cstate)) {
2076 ret = PTR_ERR(cstate);
2077 SDE_ERROR("invalid crtc state %d\n", ret);
2078 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002079 }
2080
Alan Kwongcdb2f282017-03-18 13:42:06 -07002081 if (rstate->rot_hw && cstate)
2082 sde_crtc_res_get(cstate, SDE_HW_BLK_ROT, (u64) rstate->in_fb);
2083 else if (rstate->rot_hw && !cstate)
2084 SDE_ERROR("plane%d.%d zombie rotator hw\n",
2085 plane->base.id, rstate->sequence_id);
2086
Alan Kwong4dd64c82017-02-04 18:41:51 -08002087 rstate->out_fb = NULL;
2088 rstate->out_fbo = NULL;
2089
2090 return 0;
2091}
2092
2093/**
2094 * sde_plane_rot_install_caps - install plane rotator capabilities
2095 * @plane: Pointer to drm plane
2096 * return: none
2097 */
2098static void sde_plane_rot_install_caps(struct drm_plane *plane)
2099{
2100 struct sde_plane *psde = to_sde_plane(plane);
2101 const struct sde_format_extended *format_list;
2102 struct sde_kms_info *info;
2103 struct sde_hw_rot *rot_hw;
2104 const char *downscale_caps;
2105
2106 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2107 !psde->catalog->rot_count)
2108 return;
2109
2110 if (psde->blob_rot_caps)
2111 return;
2112
2113 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2114 if (!info)
2115 return;
2116
2117 rot_hw = sde_hw_rot_get(NULL);
2118 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2119 !rot_hw->ops.get_downscale_caps) {
2120 SDE_ERROR("invalid rotator hw\n");
2121 goto error_rot;
2122 }
2123
2124 sde_kms_info_reset(info);
2125
2126 format_list = rot_hw->ops.get_format_caps(rot_hw);
2127 if (format_list) {
2128 sde_kms_info_start(info, "pixel_formats");
2129 while (format_list->fourcc_format) {
2130 sde_kms_info_append_format(info,
2131 format_list->fourcc_format,
2132 format_list->modifier);
2133 ++format_list;
2134 }
2135 sde_kms_info_stop(info);
2136 }
2137
2138 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2139 if (downscale_caps) {
2140 sde_kms_info_start(info, "downscale_ratios");
2141 sde_kms_info_append(info, downscale_caps);
2142 sde_kms_info_stop(info);
2143 }
2144
2145 if (rot_hw->ops.get_cache_size)
2146 sde_kms_info_add_keyint(info, "cache_size",
2147 rot_hw->ops.get_cache_size(rot_hw));
2148
Alan Kwong1a915802017-03-31 12:55:46 -07002149 if (rot_hw->ops.get_maxlinewidth)
2150 sde_kms_info_add_keyint(info, "max_linewidth",
2151 rot_hw->ops.get_maxlinewidth(rot_hw));
2152
Alan Kwong4dd64c82017-02-04 18:41:51 -08002153 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
2154 info->data, info->len, PLANE_PROP_ROT_CAPS_V1);
2155
2156 sde_hw_rot_put(rot_hw);
2157error_rot:
2158 kfree(info);
2159}
2160
2161/**
2162 * sde_plane_rot_install_properties - install plane rotator properties
2163 * @plane: Pointer to drm plane
2164 * @catalog: Pointer to mdss configuration
2165 * return: none
2166 */
2167static void sde_plane_rot_install_properties(struct drm_plane *plane,
2168 struct sde_mdss_cfg *catalog)
2169{
2170 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002171 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2172 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002173
2174 if (!plane || !psde) {
2175 SDE_ERROR("invalid plane\n");
2176 return;
2177 } else if (!catalog) {
2178 SDE_ERROR("invalid catalog\n");
2179 return;
2180 }
2181
2182 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2183 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2184 DRM_ROTATE_180 | DRM_ROTATE_270;
2185
2186 msm_property_install_rotation(&psde->property_info,
2187 supported_rotations, PLANE_PROP_ROTATION);
2188
2189 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2190 return;
2191
2192 msm_property_install_range(&psde->property_info, "rot_dst_x",
2193 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2194 msm_property_install_range(&psde->property_info, "rot_dst_y",
2195 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2196 msm_property_install_range(&psde->property_info, "rot_dst_w",
2197 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2198 msm_property_install_range(&psde->property_info, "rot_dst_h",
2199 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2200 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2201 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2202}
2203
2204static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -07002205 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002206{
Clarence Ipc47a0692016-10-11 10:54:17 -04002207 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -04002208 struct sde_plane *psde;
2209 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002210 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002211 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002212 struct drm_crtc *crtc;
2213 struct drm_framebuffer *fb;
2214 struct sde_rect src, dst;
Lloyd Atkinson8ba47032017-03-22 17:13:32 -04002215 const struct sde_rect *crtc_roi;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002216 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -04002217 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -04002218
Clarence Ip13a8cf42016-09-29 17:27:47 -04002219 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -04002220 SDE_ERROR("invalid plane\n");
2221 return -EINVAL;
2222 } else if (!plane->state) {
2223 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04002224 return -EINVAL;
2225 }
2226
2227 psde = to_sde_plane(plane);
2228 pstate = to_sde_plane_state(plane->state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002229 rstate = &pstate->rot;
Clarence Ipcb410d42016-06-26 22:52:33 -04002230
Dhaval Patel47302cf2016-08-18 15:04:28 -07002231 crtc = state->crtc;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002232 fb = rstate->out_fb;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002233 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002234 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
2235 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002236 return -EINVAL;
2237 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002238 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002239 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -04002240
Alan Kwong4dd64c82017-02-04 18:41:51 -08002241 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002242 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08002243 plane->base.id, rstate->sequence_id,
2244 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002245 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002246 rstate->out_fb_modifier[0],
2247 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2248 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2249 rstate->out_rotation,
2250 state->crtc_w, state->crtc_h,
2251 state->crtc_x, state->crtc_y);
2252
Clarence Ip282dad62016-09-27 17:07:35 -04002253 /* determine what needs to be refreshed */
2254 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
2255 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -04002256 case PLANE_PROP_SCALER_V1:
abeykun48f407a2016-08-25 12:06:44 -04002257 case PLANE_PROP_SCALER_V2:
Clarence Ipdedbba92016-09-27 17:43:10 -04002258 case PLANE_PROP_H_DECIMATE:
2259 case PLANE_PROP_V_DECIMATE:
2260 case PLANE_PROP_SRC_CONFIG:
2261 case PLANE_PROP_ZPOS:
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002262 case PLANE_PROP_EXCL_RECT_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04002263 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2264 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04002265 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04002266 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2267 break;
2268 case PLANE_PROP_COLOR_FILL:
2269 /* potentially need to refresh everything */
2270 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2271 break;
2272 case PLANE_PROP_ROTATION:
2273 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2274 break;
Clarence Ip282dad62016-09-27 17:07:35 -04002275 case PLANE_PROP_INFO:
2276 case PLANE_PROP_ALPHA:
2277 case PLANE_PROP_INPUT_FENCE:
2278 case PLANE_PROP_BLEND_OP:
2279 /* no special action required */
2280 break;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002281 case PLANE_PROP_ROT_DST_X:
2282 case PLANE_PROP_ROT_DST_Y:
2283 case PLANE_PROP_ROT_DST_W:
2284 case PLANE_PROP_ROT_DST_H:
2285 /* handled by rotator atomic update */
2286 break;
Clarence Ip282dad62016-09-27 17:07:35 -04002287 default:
2288 /* unknown property, refresh everything */
2289 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
2290 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
2291 break;
2292 }
Clarence Ipcb410d42016-06-26 22:52:33 -04002293 }
2294
Lloyd Atkinson8ba47032017-03-22 17:13:32 -04002295 /* re-program the output rects always in the case of partial update */
2296 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
2297 if (!sde_kms_rect_is_null(crtc_roi))
2298 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2299
Clarence Ip282dad62016-09-27 17:07:35 -04002300 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
2301 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -04002302
2303 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
2304
Clarence Ip282dad62016-09-27 17:07:35 -04002305 /* early out if nothing dirty */
2306 if (!pstate->dirty)
2307 return 0;
2308 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002309
Dhaval Patel4d424602017-02-18 19:40:14 -08002310 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
Clarence Ip282dad62016-09-27 17:07:35 -04002311 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
2312
2313 /* update roi config */
2314 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002315 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2316 rstate->out_src_w, rstate->out_src_h, q16_data);
Clarence Ip282dad62016-09-27 17:07:35 -04002317 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
2318 state->crtc_w, state->crtc_h, !q16_data);
2319
Clarence Ip13a8cf42016-09-29 17:27:47 -04002320 SDE_DEBUG_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07002321 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04002322 fb->base.id, src.x, src.y, src.w, src.h,
2323 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07002324 (char *)&fmt->base.pixel_format,
Clarence Ip282dad62016-09-27 17:07:35 -04002325 SDE_FORMAT_IS_UBWC(fmt));
2326
2327 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
2328 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002329 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002330 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
2331 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
2332 src.h /= 2;
2333 src.y = DIV_ROUND_UP(src.y, 2);
2334 src.y &= ~0x1;
2335 }
2336
Lloyd Atkinson8ba47032017-03-22 17:13:32 -04002337 /*
2338 * adjust layer mixer position of the sspp in the presence
2339 * of a partial update to the active lm origin
2340 */
2341 dst.x -= crtc_roi->x;
2342 dst.y -= crtc_roi->y;
2343
Clarence Ip282dad62016-09-27 17:07:35 -04002344 psde->pipe_cfg.src_rect = src;
2345 psde->pipe_cfg.dst_rect = dst;
2346
Dhaval Patele4b6bb22017-03-27 17:22:21 -07002347 _sde_plane_setup_scaler(psde, fmt, pstate);
2348
Clarence Ip282dad62016-09-27 17:07:35 -04002349 /* check for color fill */
2350 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
2351 PLANE_PROP_COLOR_FILL);
2352 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
2353 /* skip remaining processing on color fill */
2354 pstate->dirty = 0x0;
2355 } else if (psde->pipe_hw->ops.setup_rects) {
Clarence Ip282dad62016-09-27 17:07:35 -04002356 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08002357 &psde->pipe_cfg,
2358 pstate->multirect_index);
Clarence Ip282dad62016-09-27 17:07:35 -04002359 }
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002360
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08002361 if (psde->pipe_hw->ops.setup_pe)
2362 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
2363 &psde->pixel_ext);
2364
2365 if (psde->pipe_hw->ops.setup_scaler)
2366 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
2367 &psde->pipe_cfg, &psde->pixel_ext,
2368 psde->scaler3_cfg);
2369
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002370 /* update excl rect */
2371 if (psde->pipe_hw->ops.setup_excl_rect)
2372 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002373 &pstate->excl_rect,
2374 pstate->multirect_index);
2375
2376 if (psde->pipe_hw->ops.setup_multirect)
2377 psde->pipe_hw->ops.setup_multirect(
2378 psde->pipe_hw,
2379 pstate->multirect_index,
2380 pstate->multirect_mode);
Dhaval Patel48c76022016-09-01 17:51:23 -07002381 }
2382
Clarence Ip282dad62016-09-27 17:07:35 -04002383 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
2384 psde->pipe_hw->ops.setup_format) {
2385 src_flags = 0x0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002386 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
2387 if (rstate->out_rotation & DRM_REFLECT_X)
Clarence Ip282dad62016-09-27 17:07:35 -04002388 src_flags |= SDE_SSPP_FLIP_LR;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002389 if (rstate->out_rotation & DRM_REFLECT_Y)
Clarence Ip282dad62016-09-27 17:07:35 -04002390 src_flags |= SDE_SSPP_FLIP_UD;
2391
2392 /* update format */
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002393 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
2394 pstate->multirect_index);
Clarence Ip282dad62016-09-27 17:07:35 -04002395
Alan Kwong4dd64c82017-02-04 18:41:51 -08002396 if (psde->pipe_hw->ops.setup_sys_cache) {
2397 if (rstate->out_sbuf) {
2398 if (rstate->nplane < 2)
2399 pstate->sc_cfg.op_mode =
2400 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
2401 else if (rstate->out_xpos == 0)
2402 pstate->sc_cfg.op_mode =
2403 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
2404 else
2405 pstate->sc_cfg.op_mode =
2406 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
2407
2408 pstate->sc_cfg.rd_en = true;
2409 pstate->sc_cfg.rd_scid =
2410 rstate->rot_hw->caps->scid;
2411 pstate->sc_cfg.rd_noallocate = true;
2412 pstate->sc_cfg.rd_op_type =
2413 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
2414 } else {
2415 pstate->sc_cfg.op_mode =
2416 SDE_PIPE_SC_OP_MODE_OFFLINE;
2417 pstate->sc_cfg.rd_en = false;
2418 pstate->sc_cfg.rd_scid = 0;
2419 pstate->sc_cfg.rd_noallocate = false;
2420 pstate->sc_cfg.rd_op_type =
2421 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
2422 }
2423
2424 psde->pipe_hw->ops.setup_sys_cache(
2425 psde->pipe_hw, &pstate->sc_cfg);
2426 }
2427
Clarence Ip282dad62016-09-27 17:07:35 -04002428 /* update csc */
2429 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04002430 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04002431 else
2432 psde->csc_ptr = 0;
2433 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002434
Benet Clarkeb1b4462016-06-27 14:43:06 -07002435 sde_color_process_plane_setup(plane);
2436
Clarence Ipe78efb72016-06-24 18:35:21 -04002437 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04002438 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
2439 psde->pipe_hw->ops.setup_sharpening) {
2440 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
2441 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
2442 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
2443 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04002444
Clarence Ipe78efb72016-06-24 18:35:21 -04002445 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04002446 &psde->sharp_cfg);
2447 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002448
Alan Kwong1a00e4d2016-07-18 09:42:30 -04002449 _sde_plane_set_qos_lut(plane, fb);
2450 _sde_plane_set_danger_lut(plane, fb);
2451
Alan Kwong5d324e42016-07-28 22:56:18 -04002452 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04002453 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04002454 _sde_plane_set_ot_limit(plane, crtc);
2455 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04002456
Clarence Ip282dad62016-09-27 17:07:35 -04002457 /* clear dirty */
2458 pstate->dirty = 0x0;
2459
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002460 /* clear multirect mode*/
2461 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2462 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
2463 return 0;
2464}
2465
2466int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2467{
2468 struct sde_plane_state *pstate[R_MAX];
2469 const struct drm_plane_state *drm_state[R_MAX];
2470 struct sde_rect src[R_MAX], dst[R_MAX];
2471 struct sde_plane *sde_plane[R_MAX];
2472 const struct sde_format *fmt[R_MAX];
2473 bool q16_data = true;
2474 int i, max_sspp_linewidth;
2475 int buffer_lines = TX_MODE_BUFFER_LINE_THRES;
2476
2477 for (i = 0; i < R_MAX; i++) {
2478 const struct msm_format *msm_fmt;
2479
2480 drm_state[i] = i ? plane->r1 : plane->r0;
2481 pstate[i] = to_sde_plane_state(drm_state[i]);
2482 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2483
2484 if (pstate[i] == NULL) {
2485 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2486 drm_state[i]->plane->base.id);
2487 return -EINVAL;
2488 }
2489
2490 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2491 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2492 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2493 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2494 drm_state[i]->crtc_h, !q16_data);
2495
2496 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2497 SDE_ERROR_PLANE(sde_plane[i],
2498 "scaling is not supported in multirect mode\n");
2499 return -EINVAL;
2500 }
2501
2502 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2503 fmt[i] = to_sde_format(msm_fmt);
2504 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2505 SDE_ERROR_PLANE(sde_plane[i],
2506 "Unsupported format for multirect mode\n");
2507 return -EINVAL;
2508 }
2509 }
2510
2511 max_sspp_linewidth = sde_plane[R0]->pipe_sblk->maxlinewidth;
2512
2513 /* Validate RECT's and set the mode */
2514
2515 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
2516 if (src[R0].w <= max_sspp_linewidth/2 &&
2517 src[R1].w <= max_sspp_linewidth/2) {
2518 if (dst[R0].x <= dst[R1].x) {
2519 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2520 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2521 } else {
2522 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2523 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2524 }
2525
2526 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2527 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2528 goto done;
2529 }
2530
2531 /* TIME_MX Mode */
2532 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
2533 buffer_lines = 2 * fmt[R0]->tile_height;
2534
2535 if (dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) {
2536 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2537 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2538 } else if (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines) {
2539 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2540 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2541 } else {
2542 SDE_ERROR(
2543 "No multirect mode possible for the planes (%d - %d)\n",
2544 drm_state[R0]->plane->base.id,
2545 drm_state[R1]->plane->base.id);
2546 return -EINVAL;
2547 }
2548
2549 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2550 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2551done:
Clarence Ip5e2a9222016-06-26 22:38:24 -04002552 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002553}
2554
Alan Kwong4dd64c82017-02-04 18:41:51 -08002555/**
2556 * sde_plane_get_ctl_flush - get control flush for the given plane
2557 * @plane: Pointer to drm plane structure
2558 * @ctl: Pointer to hardware control driver
2559 * @flush: Pointer to flush control word
2560 */
2561void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
2562 u32 *flush)
2563{
2564 struct sde_plane_state *pstate;
2565 struct sde_plane_rot_state *rstate;
2566 u32 bitmask;
2567
2568 if (!plane || !flush) {
2569 SDE_ERROR("invalid parameters\n");
2570 return;
2571 }
2572
2573 pstate = to_sde_plane_state(plane->state);
2574 rstate = &pstate->rot;
2575
2576 bitmask = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
2577
2578 if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
2579 ctl->ops.get_bitmask_rot)
2580 ctl->ops.get_bitmask_rot(ctl, &bitmask, rstate->rot_hw->idx);
2581
2582 *flush = bitmask;
2583}
2584
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002585static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002586 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002587{
2588 struct drm_framebuffer *fb = new_state->fb;
2589 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002590 struct sde_plane_rot_state *new_rstate;
2591 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002592
2593 if (!new_state->fb)
2594 return 0;
2595
Clarence Ip13a8cf42016-09-29 17:27:47 -04002596 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002597
2598 ret = sde_plane_rot_prepare_fb(plane, new_state);
2599 if (ret) {
2600 SDE_ERROR("failed to prepare rot framebuffer\n");
2601 return ret;
2602 }
2603
2604 new_rstate = &to_sde_plane_state(new_state)->rot;
2605
2606 ret = msm_framebuffer_prepare(new_rstate->out_fb, new_rstate->mmu_id);
2607 if (ret) {
2608 SDE_ERROR("failed to prepare framebuffer\n");
2609 return ret;
2610 }
2611
2612 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002613}
2614
2615static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002616 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002617{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002618 struct sde_plane *psde = to_sde_plane(plane);
2619 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002620
Alan Kwong4dd64c82017-02-04 18:41:51 -08002621 if (!old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002622 return;
2623
Alan Kwong4dd64c82017-02-04 18:41:51 -08002624 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2625
2626 old_rstate = &to_sde_plane_state(old_state)->rot;
2627
2628 msm_framebuffer_cleanup(old_rstate->out_fb, old_rstate->mmu_id);
2629
2630 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002631}
2632
Alan Kwong4dd64c82017-02-04 18:41:51 -08002633static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002634 struct drm_plane_state *state,
2635 struct drm_plane_state *old_state)
2636{
2637 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002638 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002639 struct sde_plane_rot_state *rstate = &pstate->rot;
2640 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2641 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002642
Dhaval Patel47302cf2016-08-18 15:04:28 -07002643 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002644 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002645 return;
2646
Clarence Ip282dad62016-09-27 17:07:35 -04002647 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2648 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002649 SDE_DEBUG_PLANE(psde,
2650 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002651 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002652 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002653 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002654 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002655 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2656 rstate->out_src_h != old_rstate->out_src_h ||
2657 rstate->out_src_x != old_rstate->out_src_x ||
2658 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002659 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002660 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002661 } else if (state->crtc_w != old_state->crtc_w ||
2662 state->crtc_h != old_state->crtc_h ||
2663 state->crtc_x != old_state->crtc_x ||
2664 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002665 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002666 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002667 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2668 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2669 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2670 pstate->excl_rect.y != old_pstate->excl_rect.y) {
2671 SDE_DEBUG_PLANE(psde, "excl rect updated\n");
2672 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002673 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2674 pstate->multirect_mode != old_pstate->multirect_mode) {
2675 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2676 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002677 }
2678
Alan Kwong4dd64c82017-02-04 18:41:51 -08002679 fb = rstate->out_fb;
2680 old_fb = old_rstate->out_fb;
2681
2682 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002683 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002684 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002685 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002686 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002687 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002688 uint64_t *new_mods = fb->modifier;
2689 uint64_t *old_mods = old_fb->modifier;
2690 uint32_t *new_pitches = fb->pitches;
2691 uint32_t *old_pitches = old_fb->pitches;
2692 uint32_t *new_offset = fb->offsets;
2693 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002694 int i;
2695
Alan Kwong4dd64c82017-02-04 18:41:51 -08002696 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002697 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002698 SDE_DEBUG_PLANE(psde,
2699 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002700 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002701 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002702 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2703 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002704 break;
2705 }
2706 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002707 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002708 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002709 SDE_DEBUG_PLANE(psde,
2710 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002711 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002712 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002713 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002714 break;
2715 }
2716 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002717 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002718 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002719 SDE_DEBUG_PLANE(psde,
2720 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002721 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002722 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002723 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2724 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002725 break;
2726 }
2727 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002728 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002729}
2730
Alan Kwong4dd64c82017-02-04 18:41:51 -08002731static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002732 struct drm_plane_state *state)
2733{
Clarence Ipdedbba92016-09-27 17:43:10 -04002734 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04002735 struct sde_plane *psde;
2736 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002737 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002738 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002739 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04002740 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002741 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
2742 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04002743
2744 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002745 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2746 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04002747 ret = -EINVAL;
2748 goto exit;
2749 }
2750
2751 psde = to_sde_plane(plane);
2752 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002753 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04002754
2755 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002756 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002757 ret = -EINVAL;
2758 goto exit;
2759 }
2760
Clarence Ipdedbba92016-09-27 17:43:10 -04002761 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
2762 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04002763
2764 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002765 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2766 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002767 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
2768 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04002769
Dhaval Patel47302cf2016-08-18 15:04:28 -07002770 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
2771 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04002772
Dhaval Patel47302cf2016-08-18 15:04:28 -07002773 max_upscale = psde->pipe_sblk->maxupscale;
2774 max_downscale = psde->pipe_sblk->maxdwnscale;
2775 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04002776
Clarence Ip13a8cf42016-09-29 17:27:47 -04002777 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002778 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002779
Dhaval Patel47302cf2016-08-18 15:04:28 -07002780 if (!sde_plane_enabled(state))
2781 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04002782
Alan Kwong4dd64c82017-02-04 18:41:51 -08002783 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002784 "plane%d.%u sspp:%x/%dx%d/%4.4s/%llx/%dx%d+%d+%d crtc:%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08002785 plane->base.id, rstate->sequence_id,
2786 rstate->out_rotation,
2787 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002788 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002789 rstate->out_fb_modifier[0],
2790 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2791 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2792 state->crtc_w, state->crtc_h,
2793 state->crtc_x, state->crtc_y);
2794
Dhaval Patel47302cf2016-08-18 15:04:28 -07002795 fmt = to_sde_format(msm_framebuffer_format(state->fb));
2796
2797 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
2798
2799 if (SDE_FORMAT_IS_YUV(fmt) &&
2800 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04002801 !(psde->features & (BIT(SDE_SSPP_CSC)
2802 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002803 SDE_ERROR_PLANE(psde,
2804 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07002805 ret = -EINVAL;
2806
2807 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002808 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
2809 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07002810 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08002811 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
2812 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002813 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002814 src.x, src.y, src.w, src.h);
2815 ret = -E2BIG;
2816
2817 /* valid yuv image */
2818 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
2819 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002820 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002821 src.x, src.y, src.w, src.h);
2822 ret = -EINVAL;
2823
2824 /* min dst support */
2825 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002826 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002827 dst.x, dst.y, dst.w, dst.h);
2828 ret = -EINVAL;
2829
2830 /* decimation validation */
2831 } else if (deci_w || deci_h) {
2832 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
2833 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002834 SDE_ERROR_PLANE(psde,
2835 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002836 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002837 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002838 SDE_ERROR_PLANE(psde,
2839 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002840 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002841 }
2842
Dhaval Patel47302cf2016-08-18 15:04:28 -07002843 } else if (!(psde->features & SDE_SSPP_SCALER) &&
2844 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002845 SDE_ERROR_PLANE(psde,
2846 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002847 src.w, src.h, dst.w, dst.h);
2848 ret = -EINVAL;
2849
2850 /* check decimated source width */
2851 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002852 SDE_ERROR_PLANE(psde,
2853 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002854 src.w, src_deci_w, max_linewidth);
2855 ret = -E2BIG;
2856
2857 /* check max scaler capability */
2858 } else if (((src_deci_w * max_upscale) < dst.w) ||
2859 ((src_deci_h * max_upscale) < dst.h) ||
2860 ((dst.w * max_downscale) < src_deci_w) ||
2861 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002862 SDE_ERROR_PLANE(psde,
2863 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002864 src_deci_w, src_deci_h, dst.w, dst.h);
2865 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002866 }
2867
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002868 /* check excl rect configs */
2869 if (pstate->excl_rect.w && pstate->excl_rect.h) {
2870 struct sde_rect intersect;
2871
2872 /*
2873 * Check exclusion rect against src rect.
2874 * Cropping is not required as hardware will consider only the
2875 * intersecting region with the src rect.
2876 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05002877 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002878 if (!intersect.w || !intersect.h || SDE_FORMAT_IS_YUV(fmt)) {
2879 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07002880 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002881 pstate->excl_rect.x, pstate->excl_rect.y,
2882 pstate->excl_rect.w, pstate->excl_rect.h,
2883 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07002884 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002885 ret = -EINVAL;
2886 }
2887 }
2888
Dhaval Patel47302cf2016-08-18 15:04:28 -07002889modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002890 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002891 _sde_plane_sspp_atomic_check_mode_changed(psde,
2892 state, plane->state);
2893exit:
2894 return ret;
2895}
2896
2897static int sde_plane_atomic_check(struct drm_plane *plane,
2898 struct drm_plane_state *state)
2899{
2900 int ret = 0;
2901 struct sde_plane *psde;
2902 struct sde_plane_state *pstate;
2903
2904 if (!plane || !state) {
2905 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2906 plane != 0, state != 0);
2907 ret = -EINVAL;
2908 goto exit;
2909 }
2910
2911 psde = to_sde_plane(plane);
2912 pstate = to_sde_plane_state(state);
2913
2914 SDE_DEBUG_PLANE(psde, "\n");
2915
2916 ret = sde_plane_rot_atomic_check(plane, state);
2917 if (ret)
2918 goto exit;
2919
2920 ret = sde_plane_sspp_atomic_check(plane, state);
2921
Clarence Ipdbde9832016-06-26 09:48:36 -04002922exit:
2923 return ret;
2924}
2925
Clarence Ipcae1bb62016-07-07 12:07:13 -04002926/**
2927 * sde_plane_flush - final plane operations before commit flush
2928 * @plane: Pointer to drm plane structure
2929 */
2930void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04002931{
Clarence Ipcae1bb62016-07-07 12:07:13 -04002932 struct sde_plane *psde;
2933
Clarence Ip13a8cf42016-09-29 17:27:47 -04002934 if (!plane) {
2935 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04002936 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002937 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04002938
2939 psde = to_sde_plane(plane);
2940
2941 /*
2942 * These updates have to be done immediately before the plane flush
2943 * timing, and may not be moved to the atomic_update/mode_set functions.
2944 */
2945 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05002946 /* force white frame with 100% alpha pipe output on error */
2947 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002948 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
2949 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04002950 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002951 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
2952 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
2953
Clarence Ip56902792017-03-17 15:22:07 -04002954 /* force black color fill during suspend */
2955 if (msm_is_suspend_state(plane->dev) && suspend_blank)
2956 _sde_plane_color_fill(psde, 0x0, 0x0);
2957
Clarence Ipcae1bb62016-07-07 12:07:13 -04002958 /* flag h/w flush complete */
2959 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04002960 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002961}
2962
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002963static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04002964 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002965{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002966 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04002967 struct drm_plane_state *state;
2968 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002969 struct sde_plane_state *old_pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002970
Clarence Ip13a8cf42016-09-29 17:27:47 -04002971 if (!plane) {
2972 SDE_ERROR("invalid plane\n");
2973 return;
2974 } else if (!plane->state) {
2975 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04002976 return;
2977 }
2978
Clarence Ip13a8cf42016-09-29 17:27:47 -04002979 psde = to_sde_plane(plane);
2980 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04002981 state = plane->state;
2982 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002983 old_pstate = to_sde_plane_state(old_state);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002984
Clarence Ip13a8cf42016-09-29 17:27:47 -04002985 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04002986
Alan Kwong4dd64c82017-02-04 18:41:51 -08002987 sde_plane_rot_atomic_update(plane, old_state);
2988
2989 if (!sde_plane_sspp_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04002990 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04002991 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002992 int ret;
2993
Alan Kwong4dd64c82017-02-04 18:41:51 -08002994 ret = sde_plane_sspp_atomic_update(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002995 /* atomic_check should have ensured that this doesn't fail */
2996 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002997 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002998}
2999
Dhaval Patel47302cf2016-08-18 15:04:28 -07003000
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003001/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003002static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003003 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003004{
Clarence Ip5e2a9222016-06-26 22:38:24 -04003005 static const struct drm_prop_enum_list e_blend_op[] = {
3006 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3007 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3008 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3009 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3010 };
3011 static const struct drm_prop_enum_list e_src_config[] = {
3012 {SDE_DRM_DEINTERLACE, "deinterlace"}
3013 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003014 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07003015 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003016 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003017 int zpos_max = 255;
3018 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003019 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003020
Clarence Ip13a8cf42016-09-29 17:27:47 -04003021 if (!plane || !psde) {
3022 SDE_ERROR("invalid plane\n");
3023 return;
3024 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3025 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3026 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003027 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003028 } else if (!catalog) {
3029 SDE_ERROR("invalid catalog\n");
3030 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003031 }
3032
Alan Kwong4dd64c82017-02-04 18:41:51 -08003033 psde->catalog = catalog;
3034
Clarence Ipc47a0692016-10-11 10:54:17 -04003035 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003036 if (catalog->mixer_count && catalog->mixer &&
3037 catalog->mixer[0].sblk->maxblendstages) {
3038 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3039 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3040 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3041 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003042 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3043 /* reserve zpos == 0 for primary planes */
3044 zpos_def = drm_plane_index(plane) + 1;
3045 }
3046
3047 msm_property_install_range(&psde->property_info, "zpos",
3048 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003049
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003050 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003051 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003052
Dhaval Patel47302cf2016-08-18 15:04:28 -07003053 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003054 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003055 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003056
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003057 if (!master_plane_id) {
3058 if (psde->pipe_sblk->maxhdeciexp) {
3059 msm_property_install_range(&psde->property_info,
3060 "h_decimate", 0x0, 0,
3061 psde->pipe_sblk->maxhdeciexp, 0,
3062 PLANE_PROP_H_DECIMATE);
3063 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003064
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003065 if (psde->pipe_sblk->maxvdeciexp) {
3066 msm_property_install_range(&psde->property_info,
3067 "v_decimate", 0x0, 0,
3068 psde->pipe_sblk->maxvdeciexp, 0,
3069 PLANE_PROP_V_DECIMATE);
3070 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003071
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003072 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
3073 msm_property_install_volatile_range(
3074 &psde->property_info, "scaler_v2",
3075 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3076 msm_property_install_blob(&psde->property_info,
3077 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3078 msm_property_install_blob(&psde->property_info,
3079 "lut_cir", 0,
3080 PLANE_PROP_SCALER_LUT_CIR);
3081 msm_property_install_blob(&psde->property_info,
3082 "lut_sep", 0,
3083 PLANE_PROP_SCALER_LUT_SEP);
3084 } else if (psde->features & SDE_SSPP_SCALER) {
3085 msm_property_install_volatile_range(
3086 &psde->property_info, "scaler_v1", 0x0,
3087 0, ~0, 0, PLANE_PROP_SCALER_V1);
3088 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003089
Dhaval Patel0aee0972017-02-08 19:00:58 -08003090 if (psde->features & BIT(SDE_SSPP_CSC) ||
3091 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003092 msm_property_install_volatile_range(
3093 &psde->property_info, "csc_v1", 0x0,
3094 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003095
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003096 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3097 snprintf(feature_name, sizeof(feature_name), "%s%d",
3098 "SDE_SSPP_HUE_V",
3099 psde->pipe_sblk->hsic_blk.version >> 16);
3100 msm_property_install_range(&psde->property_info,
3101 feature_name, 0, 0, 0xFFFFFFFF, 0,
3102 PLANE_PROP_HUE_ADJUST);
3103 snprintf(feature_name, sizeof(feature_name), "%s%d",
3104 "SDE_SSPP_SATURATION_V",
3105 psde->pipe_sblk->hsic_blk.version >> 16);
3106 msm_property_install_range(&psde->property_info,
3107 feature_name, 0, 0, 0xFFFFFFFF, 0,
3108 PLANE_PROP_SATURATION_ADJUST);
3109 snprintf(feature_name, sizeof(feature_name), "%s%d",
3110 "SDE_SSPP_VALUE_V",
3111 psde->pipe_sblk->hsic_blk.version >> 16);
3112 msm_property_install_range(&psde->property_info,
3113 feature_name, 0, 0, 0xFFFFFFFF, 0,
3114 PLANE_PROP_VALUE_ADJUST);
3115 snprintf(feature_name, sizeof(feature_name), "%s%d",
3116 "SDE_SSPP_CONTRAST_V",
3117 psde->pipe_sblk->hsic_blk.version >> 16);
3118 msm_property_install_range(&psde->property_info,
3119 feature_name, 0, 0, 0xFFFFFFFF, 0,
3120 PLANE_PROP_CONTRAST_ADJUST);
3121 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003122 }
3123
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003124 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3125 msm_property_install_volatile_range(&psde->property_info,
3126 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3127
Alan Kwong4dd64c82017-02-04 18:41:51 -08003128 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003129
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003130 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003131 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003132
Dhaval Patel47302cf2016-08-18 15:04:28 -07003133 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3134 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3135
3136 if (psde->pipe_hw->ops.setup_solidfill)
3137 msm_property_install_range(&psde->property_info, "color_fill",
3138 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3139
Dhaval Patel4e574842016-08-23 15:11:37 -07003140 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003141 if (!info) {
3142 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003143 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003144 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003145
3146 msm_property_install_blob(&psde->property_info, "capabilities",
3147 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3148 sde_kms_info_reset(info);
3149
Clarence Ipea3d6262016-07-15 16:20:11 -04003150 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003151
3152 if (master_plane_id) {
3153 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
3154 master_plane_id);
3155 format_list = plane_formats;
3156 }
3157
Clarence Ipea3d6262016-07-15 16:20:11 -04003158 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003159 sde_kms_info_start(info, "pixel_formats");
3160 while (format_list->fourcc_format) {
3161 sde_kms_info_append_format(info,
3162 format_list->fourcc_format,
3163 format_list->modifier);
3164 ++format_list;
3165 }
3166 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003167 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003168
3169 sde_kms_info_add_keyint(info, "max_linewidth",
3170 psde->pipe_sblk->maxlinewidth);
3171 sde_kms_info_add_keyint(info, "max_upscale",
3172 psde->pipe_sblk->maxupscale);
3173 sde_kms_info_add_keyint(info, "max_downscale",
3174 psde->pipe_sblk->maxdwnscale);
3175 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3176 psde->pipe_sblk->maxhdeciexp);
3177 sde_kms_info_add_keyint(info, "max_vertical_deci",
3178 psde->pipe_sblk->maxvdeciexp);
3179 msm_property_set_blob(&psde->property_info, &psde->blob_info,
3180 info->data, info->len, PLANE_PROP_INFO);
3181
3182 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003183
3184 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3185 snprintf(feature_name, sizeof(feature_name), "%s%d",
3186 "SDE_SSPP_SKIN_COLOR_V",
3187 psde->pipe_sblk->memcolor_blk.version >> 16);
3188 msm_property_install_blob(&psde->property_info, feature_name, 0,
3189 PLANE_PROP_SKIN_COLOR);
3190 snprintf(feature_name, sizeof(feature_name), "%s%d",
3191 "SDE_SSPP_SKY_COLOR_V",
3192 psde->pipe_sblk->memcolor_blk.version >> 16);
3193 msm_property_install_blob(&psde->property_info, feature_name, 0,
3194 PLANE_PROP_SKY_COLOR);
3195 snprintf(feature_name, sizeof(feature_name), "%s%d",
3196 "SDE_SSPP_FOLIAGE_COLOR_V",
3197 psde->pipe_sblk->memcolor_blk.version >> 16);
3198 msm_property_install_blob(&psde->property_info, feature_name, 0,
3199 PLANE_PROP_FOLIAGE_COLOR);
3200 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003201}
3202
Clarence Ip5fc00c52016-09-23 15:03:34 -04003203static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
3204{
3205 struct sde_drm_csc_v1 csc_v1;
3206 int i;
3207
3208 if (!psde) {
3209 SDE_ERROR("invalid plane\n");
3210 return;
3211 }
3212
3213 psde->csc_usr_ptr = NULL;
3214 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003215 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003216 return;
3217 }
3218
3219 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003220 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003221 return;
3222 }
3223
Clarence Ipb43d4592016-09-08 14:21:35 -04003224 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04003225 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
3226 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
3227 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
3228 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
3229 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
3230 }
3231 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
3232 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
3233 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
3234 }
3235 psde->csc_usr_ptr = &psde->csc_cfg;
3236}
3237
Clarence Ipb43d4592016-09-08 14:21:35 -04003238static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
3239{
3240 struct sde_drm_scaler_v1 scale_v1;
3241 struct sde_hw_pixel_ext *pe;
3242 int i;
3243
3244 if (!psde) {
3245 SDE_ERROR("invalid plane\n");
3246 return;
3247 }
3248
3249 psde->pixel_ext_usr = false;
3250 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003251 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003252 return;
3253 }
3254
3255 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003256 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003257 return;
3258 }
3259
3260 /* populate from user space */
3261 pe = &(psde->pixel_ext);
3262 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3263 for (i = 0; i < SDE_MAX_PLANES; i++) {
3264 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
3265 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
3266 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
3267 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
3268
3269 pe->horz_filter[i] = scale_v1.horz_filter[i];
3270 pe->vert_filter[i] = scale_v1.vert_filter[i];
3271 }
3272 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003273 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
3274 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
3275 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
3276 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
3277 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003278
abeykun41060122016-11-28 13:02:01 -05003279 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
3280 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
3281 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
3282 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
3283 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003284 }
abeykun41060122016-11-28 13:02:01 -05003285
Clarence Ipb43d4592016-09-08 14:21:35 -04003286 psde->pixel_ext_usr = true;
3287
Clarence Ip13a8cf42016-09-29 17:27:47 -04003288 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003289}
3290
abeykun48f407a2016-08-25 12:06:44 -04003291static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
3292 struct sde_plane_state *pstate, void *usr)
3293{
3294 struct sde_drm_scaler_v2 scale_v2;
3295 struct sde_hw_pixel_ext *pe;
3296 int i;
3297 struct sde_hw_scaler3_cfg *cfg;
3298
3299 if (!psde) {
3300 SDE_ERROR("invalid plane\n");
3301 return;
3302 }
3303
3304 cfg = psde->scaler3_cfg;
3305 psde->pixel_ext_usr = false;
3306 if (!usr) {
3307 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3308 return;
3309 }
3310
3311 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
3312 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
3313 return;
3314 }
3315
3316 /* populate from user space */
3317 pe = &(psde->pixel_ext);
3318 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3319 cfg->enable = scale_v2.enable;
3320 cfg->dir_en = scale_v2.dir_en;
3321 for (i = 0; i < SDE_MAX_PLANES; i++) {
3322 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
3323 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
3324 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
3325 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
3326
3327 cfg->preload_x[i] = scale_v2.preload_x[i];
3328 cfg->preload_y[i] = scale_v2.preload_y[i];
3329 cfg->src_width[i] = scale_v2.src_width[i];
3330 cfg->src_height[i] = scale_v2.src_height[i];
3331 }
3332 cfg->dst_width = scale_v2.dst_width;
3333 cfg->dst_height = scale_v2.dst_height;
3334
3335 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
3336 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
3337 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
3338 cfg->blend_cfg = scale_v2.blend_cfg;
3339
3340 cfg->lut_flag = scale_v2.lut_flag;
3341 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
3342 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
3343 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
3344 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
3345 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
3346
3347 cfg->de.enable = scale_v2.de.enable;
3348 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
3349 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
3350 cfg->de.clip = scale_v2.de.clip;
3351 cfg->de.limit = scale_v2.de.limit;
3352 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
3353 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
3354 cfg->de.thr_low = scale_v2.de.thr_low;
3355 cfg->de.thr_high = scale_v2.de.thr_high;
3356 cfg->de.prec_shift = scale_v2.de.prec_shift;
3357 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
3358 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
3359 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
3360 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
3361 }
3362 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003363 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
3364 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
3365 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
3366 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
3367 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04003368
abeykun41060122016-11-28 13:02:01 -05003369 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
3370 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
3371 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
3372 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
3373 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04003374 }
3375 psde->pixel_ext_usr = true;
3376
3377 SDE_DEBUG_PLANE(psde, "user property data copied\n");
3378}
3379
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003380static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
3381 struct sde_plane_state *pstate, void *usr_ptr)
3382{
3383 struct drm_clip_rect excl_rect_v1;
3384
3385 if (!psde) {
3386 SDE_ERROR("invalid plane\n");
3387 return;
3388 }
3389
3390 if (!usr_ptr) {
3391 SDE_DEBUG_PLANE(psde, "excl rect data removed\n");
3392 return;
3393 }
3394
3395 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
3396 SDE_ERROR_PLANE(psde, "failed to copy excl rect data\n");
3397 return;
3398 }
3399
3400 /* populate from user space */
3401 pstate->excl_rect.x = excl_rect_v1.x1;
3402 pstate->excl_rect.y = excl_rect_v1.y1;
3403 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1 + 1;
3404 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1 + 1;
3405}
3406
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003407static int sde_plane_atomic_set_property(struct drm_plane *plane,
3408 struct drm_plane_state *state, struct drm_property *property,
3409 uint64_t val)
3410{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003411 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003412 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003413 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003414
Clarence Ip13a8cf42016-09-29 17:27:47 -04003415 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003416
3417 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003418 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003419 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003420 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003421 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04003422 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003423 ret = msm_property_atomic_set(&psde->property_info,
3424 pstate->property_values, pstate->property_blobs,
3425 property, val);
3426 if (!ret) {
3427 idx = msm_property_index(&psde->property_info,
3428 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003429 switch (idx) {
3430 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04003431 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003432 break;
3433 case PLANE_PROP_CSC_V1:
3434 _sde_plane_set_csc_v1(psde, (void *)val);
3435 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04003436 case PLANE_PROP_SCALER_V1:
3437 _sde_plane_set_scaler_v1(psde, (void *)val);
3438 break;
abeykun48f407a2016-08-25 12:06:44 -04003439 case PLANE_PROP_SCALER_V2:
3440 _sde_plane_set_scaler_v2(psde, pstate,
3441 (void *)val);
3442 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003443 case PLANE_PROP_EXCL_RECT_V1:
3444 _sde_plane_set_excl_rect_v1(psde, pstate,
3445 (void *)val);
3446 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04003447 default:
3448 /* nothing to do */
3449 break;
3450 }
Clarence Ipe78efb72016-06-24 18:35:21 -04003451 }
3452 }
3453
Alan Kwong4dd64c82017-02-04 18:41:51 -08003454 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
3455 property->name, property->base.id, val, ret);
3456
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003457 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003458}
3459
3460static int sde_plane_set_property(struct drm_plane *plane,
3461 struct drm_property *property, uint64_t val)
3462{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003463 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003464
Clarence Ipae4e60c2016-06-26 22:44:04 -04003465 return sde_plane_atomic_set_property(plane,
3466 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003467}
3468
3469static int sde_plane_atomic_get_property(struct drm_plane *plane,
3470 const struct drm_plane_state *state,
3471 struct drm_property *property, uint64_t *val)
3472{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003473 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003474 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04003475 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003476
Clarence Ipaa0faf42016-05-30 12:07:48 -04003477 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003478 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003479 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003480 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003481 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003482 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003483 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003484 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003485 ret = msm_property_atomic_get(&psde->property_info,
3486 pstate->property_values, pstate->property_blobs,
3487 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04003488 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003489
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003490 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003491}
3492
3493static void sde_plane_destroy(struct drm_plane *plane)
3494{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003495 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003496
Clarence Ip13a8cf42016-09-29 17:27:47 -04003497 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003498
Clarence Ip13a8cf42016-09-29 17:27:47 -04003499 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04003500 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3501
Dhaval Patel4e574842016-08-23 15:11:37 -07003502 if (psde->blob_info)
3503 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003504 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04003505 mutex_destroy(&psde->lock);
3506
Clarence Ip4ce59322016-06-26 22:27:51 -04003507 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003508
Clarence Ip4ce59322016-06-26 22:27:51 -04003509 /* this will destroy the states as well */
3510 drm_plane_cleanup(plane);
3511
Clarence Ip4c1d9772016-06-26 09:35:38 -04003512 if (psde->pipe_hw)
3513 sde_hw_sspp_destroy(psde->pipe_hw);
3514
Clarence Ip4ce59322016-06-26 22:27:51 -04003515 kfree(psde);
3516 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003517}
3518
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003519static void sde_plane_destroy_state(struct drm_plane *plane,
3520 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003521{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003522 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04003523 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003524
Clarence Ipae4e60c2016-06-26 22:44:04 -04003525 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003526 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3527 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003528 return;
3529 }
3530
Clarence Ipaa0faf42016-05-30 12:07:48 -04003531 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04003532 pstate = to_sde_plane_state(state);
3533
Clarence Ip13a8cf42016-09-29 17:27:47 -04003534 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003535
Alan Kwong4dd64c82017-02-04 18:41:51 -08003536 sde_plane_rot_destroy_state(plane, &pstate->base);
3537
Clarence Ipe78efb72016-06-24 18:35:21 -04003538 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003539 if (state->fb)
3540 drm_framebuffer_unreference(state->fb);
3541
Clarence Ipae4e60c2016-06-26 22:44:04 -04003542 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003543 if (pstate->input_fence)
3544 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003545
Clarence Ipaa0faf42016-05-30 12:07:48 -04003546 /* destroy value helper */
3547 msm_property_destroy_state(&psde->property_info, pstate,
3548 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003549}
3550
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003551static struct drm_plane_state *
3552sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003553{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003554 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003555 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04003556 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04003557 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003558
Clarence Ip13a8cf42016-09-29 17:27:47 -04003559 if (!plane) {
3560 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003561 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003562 } else if (!plane->state) {
3563 SDE_ERROR("invalid plane state\n");
3564 return NULL;
3565 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003566
Clarence Ip730e7192016-06-26 22:45:09 -04003567 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003568 psde = to_sde_plane(plane);
3569 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003570 if (!pstate) {
3571 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003572 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003573 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003574
Clarence Ip13a8cf42016-09-29 17:27:47 -04003575 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003576
3577 /* duplicate value helper */
3578 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
3579 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003580
Clarence Ip17e908b2016-09-29 15:58:00 -04003581 /* clear out any input fence */
3582 pstate->input_fence = 0;
3583 input_fence_default = msm_property_get_default(
3584 &psde->property_info, PLANE_PROP_INPUT_FENCE);
3585 msm_property_set_property(&psde->property_info, pstate->property_values,
3586 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003587
Clarence Ip282dad62016-09-27 17:07:35 -04003588 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04003589 pstate->pending = false;
3590
Alan Kwongcdb2f282017-03-18 13:42:06 -07003591 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
3592
Alan Kwong4dd64c82017-02-04 18:41:51 -08003593 sde_plane_rot_duplicate_state(plane, &pstate->base);
3594
Clarence Ip730e7192016-06-26 22:45:09 -04003595 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003596}
3597
3598static void sde_plane_reset(struct drm_plane *plane)
3599{
Clarence Ipae4e60c2016-06-26 22:44:04 -04003600 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003601 struct sde_plane_state *pstate;
3602
Clarence Ipae4e60c2016-06-26 22:44:04 -04003603 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003604 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003605 return;
3606 }
3607
Clarence Ip730e7192016-06-26 22:45:09 -04003608 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003609 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003610
Clarence Ipae4e60c2016-06-26 22:44:04 -04003611 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04003612 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04003613 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003614 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04003615 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003616
Clarence Ipaa0faf42016-05-30 12:07:48 -04003617 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003618 if (!pstate) {
3619 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003620 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003621 }
Clarence Ip730e7192016-06-26 22:45:09 -04003622
Clarence Ipaa0faf42016-05-30 12:07:48 -04003623 /* reset value helper */
3624 msm_property_reset_state(&psde->property_info, pstate,
3625 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003626
3627 pstate->base.plane = plane;
3628
3629 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003630}
3631
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003632#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04003633static ssize_t _sde_plane_danger_read(struct file *file,
3634 char __user *buff, size_t count, loff_t *ppos)
3635{
3636 struct sde_kms *kms = file->private_data;
3637 struct sde_mdss_cfg *cfg = kms->catalog;
3638 int len = 0;
3639 char buf[40] = {'\0'};
3640
3641 if (!cfg)
3642 return -ENODEV;
3643
3644 if (*ppos)
3645 return 0; /* the end */
3646
3647 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
3648 if (len < 0 || len >= sizeof(buf))
3649 return 0;
3650
3651 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
3652 return -EFAULT;
3653
3654 *ppos += len; /* increase offset */
3655
3656 return len;
3657}
3658
3659static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
3660{
3661 struct drm_plane *plane;
3662
3663 drm_for_each_plane(plane, kms->dev) {
3664 if (plane->fb && plane->state) {
3665 sde_plane_danger_signal_ctrl(plane, enable);
3666 SDE_DEBUG("plane:%d img:%dx%d ",
3667 plane->base.id, plane->fb->width,
3668 plane->fb->height);
3669 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
3670 plane->state->src_x >> 16,
3671 plane->state->src_y >> 16,
3672 plane->state->src_w >> 16,
3673 plane->state->src_h >> 16,
3674 plane->state->crtc_x, plane->state->crtc_y,
3675 plane->state->crtc_w, plane->state->crtc_h);
3676 } else {
3677 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
3678 }
3679 }
3680}
3681
3682static ssize_t _sde_plane_danger_write(struct file *file,
3683 const char __user *user_buf, size_t count, loff_t *ppos)
3684{
3685 struct sde_kms *kms = file->private_data;
3686 struct sde_mdss_cfg *cfg = kms->catalog;
3687 int disable_panic;
3688 char buf[10];
3689
3690 if (!cfg)
3691 return -EFAULT;
3692
3693 if (count >= sizeof(buf))
3694 return -EFAULT;
3695
3696 if (copy_from_user(buf, user_buf, count))
3697 return -EFAULT;
3698
3699 buf[count] = 0; /* end of string */
3700
3701 if (kstrtoint(buf, 0, &disable_panic))
3702 return -EFAULT;
3703
3704 if (disable_panic) {
3705 /* Disable panic signal for all active pipes */
3706 SDE_DEBUG("Disabling danger:\n");
3707 _sde_plane_set_danger_state(kms, false);
3708 kms->has_danger_ctrl = false;
3709 } else {
3710 /* Enable panic signal for all active pipes */
3711 SDE_DEBUG("Enabling danger:\n");
3712 kms->has_danger_ctrl = true;
3713 _sde_plane_set_danger_state(kms, true);
3714 }
3715
3716 return count;
3717}
3718
3719static const struct file_operations sde_plane_danger_enable = {
3720 .open = simple_open,
3721 .read = _sde_plane_danger_read,
3722 .write = _sde_plane_danger_write,
3723};
3724
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003725static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04003726{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003727 struct sde_plane *psde;
3728 struct sde_kms *kms;
3729 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04003730 const struct sde_sspp_sub_blks *sblk = 0;
3731 const struct sde_sspp_cfg *cfg = 0;
3732
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003733 if (!plane || !plane->dev) {
3734 SDE_ERROR("invalid arguments\n");
3735 return -EINVAL;
3736 }
3737
3738 priv = plane->dev->dev_private;
3739 if (!priv || !priv->kms) {
3740 SDE_ERROR("invalid KMS reference\n");
3741 return -EINVAL;
3742 }
3743
3744 kms = to_sde_kms(priv->kms);
3745 psde = to_sde_plane(plane);
3746
Clarence Ip4ce59322016-06-26 22:27:51 -04003747 if (psde && psde->pipe_hw)
3748 cfg = psde->pipe_hw->cap;
3749 if (cfg)
3750 sblk = cfg->sblk;
3751
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003752 if (!sblk)
3753 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04003754
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003755 /* create overall sub-directory for the pipe */
3756 psde->debugfs_root =
3757 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07003758 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04003759
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003760 if (!psde->debugfs_root)
3761 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04003762
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003763 /* don't error check these */
3764 debugfs_create_x32("features", 0644,
3765 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003766
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003767 /* add register dump support */
3768 sde_debugfs_setup_regset32(&psde->debugfs_src,
3769 sblk->src_blk.base + cfg->base,
3770 sblk->src_blk.len,
3771 kms);
3772 sde_debugfs_create_regset32("src_blk", 0444,
3773 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003774
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003775 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
3776 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
3777 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
3778 sblk->scaler_blk.base + cfg->base,
3779 sblk->scaler_blk.len,
3780 kms);
3781 sde_debugfs_create_regset32("scaler_blk", 0444,
3782 psde->debugfs_root,
3783 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07003784 debugfs_create_bool("default_scaling",
3785 0644,
3786 psde->debugfs_root,
3787 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04003788 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003789
3790 if (cfg->features & BIT(SDE_SSPP_CSC) ||
3791 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
3792 sde_debugfs_setup_regset32(&psde->debugfs_csc,
3793 sblk->csc_blk.base + cfg->base,
3794 sblk->csc_blk.len,
3795 kms);
3796 sde_debugfs_create_regset32("csc_blk", 0444,
3797 psde->debugfs_root, &psde->debugfs_csc);
3798 }
3799
3800 debugfs_create_u32("xin_id",
3801 0444,
3802 psde->debugfs_root,
3803 (u32 *) &cfg->xin_id);
3804 debugfs_create_u32("clk_ctrl",
3805 0444,
3806 psde->debugfs_root,
3807 (u32 *) &cfg->clk_ctrl);
3808 debugfs_create_x32("creq_vblank",
3809 0644,
3810 psde->debugfs_root,
3811 (u32 *) &sblk->creq_vblank);
3812 debugfs_create_x32("danger_vblank",
3813 0644,
3814 psde->debugfs_root,
3815 (u32 *) &sblk->danger_vblank);
3816
3817 debugfs_create_file("disable_danger",
3818 0644,
3819 psde->debugfs_root,
3820 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003821 debugfs_create_u32("sbuf_mode",
3822 0644,
3823 psde->debugfs_root, &psde->sbuf_mode);
3824 debugfs_create_u32("sbuf_writeback",
3825 0644,
3826 psde->debugfs_root,
3827 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003828
3829 return 0;
3830}
3831
3832static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3833{
3834 struct sde_plane *psde;
3835
3836 if (!plane)
3837 return;
3838 psde = to_sde_plane(plane);
3839
3840 debugfs_remove_recursive(psde->debugfs_root);
3841}
3842#else
3843static int _sde_plane_init_debugfs(struct drm_plane *plane)
3844{
3845 return 0;
3846}
3847static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3848{
3849}
3850#endif
3851
3852static int sde_plane_late_register(struct drm_plane *plane)
3853{
3854 return _sde_plane_init_debugfs(plane);
3855}
3856
3857static void sde_plane_early_unregister(struct drm_plane *plane)
3858{
3859 _sde_plane_destroy_debugfs(plane);
3860}
3861
3862static const struct drm_plane_funcs sde_plane_funcs = {
3863 .update_plane = drm_atomic_helper_update_plane,
3864 .disable_plane = drm_atomic_helper_disable_plane,
3865 .destroy = sde_plane_destroy,
3866 .set_property = sde_plane_set_property,
3867 .atomic_set_property = sde_plane_atomic_set_property,
3868 .atomic_get_property = sde_plane_atomic_get_property,
3869 .reset = sde_plane_reset,
3870 .atomic_duplicate_state = sde_plane_duplicate_state,
3871 .atomic_destroy_state = sde_plane_destroy_state,
3872 .late_register = sde_plane_late_register,
3873 .early_unregister = sde_plane_early_unregister,
3874};
3875
3876static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
3877 .prepare_fb = sde_plane_prepare_fb,
3878 .cleanup_fb = sde_plane_cleanup_fb,
3879 .atomic_check = sde_plane_atomic_check,
3880 .atomic_update = sde_plane_atomic_update,
3881};
3882
3883enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
3884{
3885 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
3886}
3887
3888bool is_sde_plane_virtual(struct drm_plane *plane)
3889{
3890 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04003891}
3892
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003893/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04003894struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04003895 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003896 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003897{
3898 struct drm_plane *plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003899 const struct sde_format_extended *format_list;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003900 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003901 struct msm_drm_private *priv;
3902 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003903 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04003904 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04003905
3906 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003907 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003908 goto exit;
3909 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003910
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003911 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04003912 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003913 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04003914 goto exit;
3915 }
3916
3917 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003918 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04003919 goto exit;
3920 }
3921 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003922
Clarence Ip4c1d9772016-06-26 09:35:38 -04003923 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003924 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003925 goto exit;
3926 }
3927
Clarence Ip4ce59322016-06-26 22:27:51 -04003928 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003929 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
3930 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003931 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003932 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04003933 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003934 }
3935
Clarence Ip4c1d9772016-06-26 09:35:38 -04003936 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003937 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003938 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04003939 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003940 psde->is_virtual = (master_plane_id != 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003941
Clarence Ip4c1d9772016-06-26 09:35:38 -04003942 /* initialize underlying h/w driver */
3943 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
3944 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003945 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003946 ret = PTR_ERR(psde->pipe_hw);
3947 goto clean_plane;
3948 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003949 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003950 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003951 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04003952
3953 /* cache features mask for later */
3954 psde->features = psde->pipe_hw->cap->features;
3955 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04003956 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003957 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04003958 goto clean_sspp;
3959 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04003960
abeykun48f407a2016-08-25 12:06:44 -04003961 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
3962 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
3963 GFP_KERNEL);
3964 if (!psde->scaler3_cfg) {
3965 SDE_ERROR("[%u]failed to allocate scale struct\n",
3966 pipe);
3967 ret = -ENOMEM;
3968 goto clean_sspp;
3969 }
3970 }
3971
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003972 format_list = psde->pipe_sblk->format_list;
3973
3974 if (master_plane_id)
3975 format_list = plane_formats;
3976
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07003977 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003978 psde->formats,
3979 0,
3980 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003981
Clarence Ip4c1d9772016-06-26 09:35:38 -04003982 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003983 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04003984 goto clean_sspp;
3985 }
3986
3987 if (psde->features & BIT(SDE_SSPP_CURSOR))
3988 type = DRM_PLANE_TYPE_CURSOR;
3989 else if (primary_plane)
3990 type = DRM_PLANE_TYPE_PRIMARY;
3991 else
3992 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07003993 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
3994 psde->formats, psde->nformats,
3995 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003996 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04003997 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003998
Clarence Ip4c1d9772016-06-26 09:35:38 -04003999 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004000 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004001
Clarence Ipaa0faf42016-05-30 12:07:48 -04004002 msm_property_init(&psde->property_info, &plane->base, dev,
4003 priv->plane_property, psde->property_data,
4004 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
4005 sizeof(struct sde_plane_state));
4006
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004007 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004008
Clarence Ip4ce59322016-06-26 22:27:51 -04004009 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004010 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004011
Clarence Ip730e7192016-06-26 22:45:09 -04004012 mutex_init(&psde->lock);
4013
Dhaval Patel82c8dbc2017-02-18 23:15:10 -08004014 SDE_DEBUG("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004015 return plane;
4016
Clarence Ip4c1d9772016-06-26 09:35:38 -04004017clean_sspp:
4018 if (psde && psde->pipe_hw)
4019 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04004020
4021 if (psde && psde->scaler3_cfg)
4022 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004023clean_plane:
4024 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004025exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004026 return ERR_PTR(ret);
4027}