blob: 78c596d7326e7566d02e429da5b5da3262016b65 [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>
Clarence Ip5e2a9222016-06-26 22:38:24 -040022#include <uapi/drm/sde_drm.h>
Benet Clarkd009b1d2016-06-27 14:45:59 -070023#include <uapi/drm/msm_drm_pp.h>
Clarence Ipaa0faf42016-05-30 12:07:48 -040024
25#include "msm_prop.h"
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080026#include "msm_drv.h"
Clarence Ipaa0faf42016-05-30 12:07:48 -040027
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070028#include "sde_kms.h"
Clarence Ipae4e60c2016-06-26 22:44:04 -040029#include "sde_fence.h"
Clarence Ipc475b082016-06-26 09:27:23 -040030#include "sde_formats.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040031#include "sde_hw_sspp.h"
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080032#include "sde_hw_catalog_format.h"
Alan Kwong1a00e4d2016-07-18 09:42:30 -040033#include "sde_trace.h"
Dhaval Patel48c76022016-09-01 17:51:23 -070034#include "sde_crtc.h"
Lloyd Atkinson8772e202016-09-26 17:52:16 -040035#include "sde_vbif.h"
Alan Kwong83285fb2016-10-21 20:51:17 -040036#include "sde_plane.h"
Benet Clarkd009b1d2016-06-27 14:45:59 -070037#include "sde_color_processing.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040038
Clarence Ip13a8cf42016-09-29 17:27:47 -040039#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
40 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
41
42#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
43 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
44
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040045#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
46#define PHASE_STEP_SHIFT 21
47#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
48#define PHASE_RESIDUAL 15
49
Clarence Ipe78efb72016-06-24 18:35:21 -040050#define SHARP_STRENGTH_DEFAULT 32
51#define SHARP_EDGE_THR_DEFAULT 112
52#define SHARP_SMOOTH_THR_DEFAULT 8
53#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040054
Clarence Ip5e2a9222016-06-26 22:38:24 -040055#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070056
Clarence Ipcae1bb62016-07-07 12:07:13 -040057#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
58
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080059/* multirect rect index */
60enum {
61 R0,
62 R1,
63 R_MAX
64};
65
66#define TX_MODE_BUFFER_LINE_THRES 2
67
Clarence Ip282dad62016-09-27 17:07:35 -040068/* dirty bits for update function */
69#define SDE_PLANE_DIRTY_RECTS 0x1
70#define SDE_PLANE_DIRTY_FORMAT 0x2
71#define SDE_PLANE_DIRTY_SHARPEN 0x4
72#define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF
73
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -070074#define SDE_QSEED3_DEFAULT_PRELOAD_H 0x4
75#define SDE_QSEED3_DEFAULT_PRELOAD_V 0x3
76
Alan Kwong1a00e4d2016-07-18 09:42:30 -040077/**
78 * enum sde_plane_qos - Different qos configurations for each pipe
79 *
80 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
81 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
82 * this configuration is mutually exclusive from VBLANK_CTRL.
83 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
84 */
85enum sde_plane_qos {
86 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
87 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
88 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
89};
90
Clarence Ip5fc00c52016-09-23 15:03:34 -040091/*
92 * struct sde_plane - local sde plane structure
93 * @csc_cfg: Decoded user configuration for csc
94 * @csc_usr_ptr: Points to csc_cfg if valid user config available
95 * @csc_ptr: Points to sde_csc_cfg structure to use for current
96 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070097struct sde_plane {
98 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040099
100 int mmu_id;
101
Clarence Ip730e7192016-06-26 22:45:09 -0400102 struct mutex lock;
103
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400104 enum sde_sspp pipe;
105 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700106 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400107 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400108
109 struct sde_hw_pipe *pipe_hw;
110 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -0400111 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -0400112 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400113 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400114 uint32_t color_fill;
115 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400116 bool is_rt_pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800117 bool is_virtual;
Clarence Ip4ce59322016-06-26 22:27:51 -0400118
Clarence Ipb43d4592016-09-08 14:21:35 -0400119 struct sde_hw_pixel_ext pixel_ext;
120 bool pixel_ext_usr;
121
Clarence Ip373f8592016-05-26 00:58:42 -0400122 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400123 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400124 struct sde_csc_cfg *csc_ptr;
125
Clarence Ip4c1d9772016-06-26 09:35:38 -0400126 const struct sde_sspp_sub_blks *pipe_sblk;
127
Clarence Ip5e2a9222016-06-26 22:38:24 -0400128 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400129
Clarence Ipaa0faf42016-05-30 12:07:48 -0400130 struct msm_property_info property_info;
131 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700132 struct drm_property_blob *blob_info;
Clarence Ip730e7192016-06-26 22:45:09 -0400133
Clarence Ip4ce59322016-06-26 22:27:51 -0400134 /* debugfs related stuff */
135 struct dentry *debugfs_root;
136 struct sde_debugfs_regset32 debugfs_src;
137 struct sde_debugfs_regset32 debugfs_scaler;
138 struct sde_debugfs_regset32 debugfs_csc;
Clarence Ip716ab662017-03-20 06:51:24 -0700139 bool debugfs_default_scale;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700140};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700141
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700142#define to_sde_plane(x) container_of(x, struct sde_plane, base)
143
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400144static bool sde_plane_enabled(struct drm_plane_state *state)
145{
Clarence Ipdbde9832016-06-26 09:48:36 -0400146 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400147}
148
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400149/**
150 * _sde_plane_calc_fill_level - calculate fill level of the given source format
151 * @plane: Pointer to drm plane
152 * @fmt: Pointer to source buffer format
153 * @src_wdith: width of source buffer
154 * Return: fill level corresponding to the source buffer/format or 0 if error
155 */
156static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
157 const struct sde_format *fmt, u32 src_width)
158{
159 struct sde_plane *psde;
160 u32 fixed_buff_size;
161 u32 total_fl;
162
163 if (!plane || !fmt) {
164 SDE_ERROR("invalid arguments\n");
165 return 0;
166 }
167
168 psde = to_sde_plane(plane);
169 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
170
171 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
172 if (fmt->chroma_sample == SDE_CHROMA_420) {
173 /* NV12 */
174 total_fl = (fixed_buff_size / 2) /
175 ((src_width + 32) * fmt->bpp);
176 } else {
177 /* non NV12 */
178 total_fl = (fixed_buff_size) /
179 ((src_width + 32) * fmt->bpp);
180 }
181 } else {
182 total_fl = (fixed_buff_size * 2) /
183 ((src_width + 32) * fmt->bpp);
184 }
185
186 SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n",
187 plane->base.id, psde->pipe - SSPP_VIG0,
188 fmt->base.pixel_format, src_width, total_fl);
189
190 return total_fl;
191}
192
193/**
194 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
195 * @total_fl: fill level
196 * Return: LUT setting corresponding to the fill level
197 */
198static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
199{
200 u32 qos_lut;
201
202 if (total_fl <= 4)
203 qos_lut = 0x1B;
204 else if (total_fl <= 5)
205 qos_lut = 0x5B;
206 else if (total_fl <= 6)
207 qos_lut = 0x15B;
208 else if (total_fl <= 7)
209 qos_lut = 0x55B;
210 else if (total_fl <= 8)
211 qos_lut = 0x155B;
212 else if (total_fl <= 9)
213 qos_lut = 0x555B;
214 else if (total_fl <= 10)
215 qos_lut = 0x1555B;
216 else if (total_fl <= 11)
217 qos_lut = 0x5555B;
218 else if (total_fl <= 12)
219 qos_lut = 0x15555B;
220 else
221 qos_lut = 0x55555B;
222
223 return qos_lut;
224}
225
226/**
227 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
228 * @total_fl: fill level
229 * Return: LUT setting corresponding to the fill level
230 */
231static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
232{
233 u32 qos_lut;
234
235 if (total_fl <= 10)
236 qos_lut = 0x1AAff;
237 else if (total_fl <= 11)
238 qos_lut = 0x5AAFF;
239 else if (total_fl <= 12)
240 qos_lut = 0x15AAFF;
241 else
242 qos_lut = 0x55AAFF;
243
244 return qos_lut;
245}
246
247/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400248 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
249 * @plane: Pointer to drm plane
250 * @fb: Pointer to framebuffer associated with the given plane
251 */
252static void _sde_plane_set_qos_lut(struct drm_plane *plane,
253 struct drm_framebuffer *fb)
254{
255 struct sde_plane *psde;
256 const struct sde_format *fmt = NULL;
257 u32 qos_lut;
258 u32 total_fl = 0;
259
260 if (!plane || !fb) {
261 SDE_ERROR("invalid arguments plane %d fb %d\n",
262 plane != 0, fb != 0);
263 return;
264 }
265
266 psde = to_sde_plane(plane);
267
268 if (!psde->pipe_hw || !psde->pipe_sblk) {
269 SDE_ERROR("invalid arguments\n");
270 return;
271 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
272 return;
273 }
274
275 if (!psde->is_rt_pipe) {
276 qos_lut = psde->pipe_sblk->creq_lut_nrt;
277 } else {
278 fmt = sde_get_sde_format_ext(
279 fb->pixel_format,
280 fb->modifier,
281 drm_format_num_planes(fb->pixel_format));
282 total_fl = _sde_plane_calc_fill_level(plane, fmt,
283 psde->pipe_cfg.src_rect.w);
284
285 if (SDE_FORMAT_IS_LINEAR(fmt))
286 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
287 else
288 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
289 }
290
291 psde->pipe_qos_cfg.creq_lut = qos_lut;
292
293 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
294 (fmt) ? fmt->base.pixel_format : 0,
295 psde->is_rt_pipe, total_fl, qos_lut,
296 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
297
298 SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n",
299 plane->base.id,
300 psde->pipe - SSPP_VIG0,
301 (fmt) ? fmt->base.pixel_format : 0,
302 psde->is_rt_pipe, total_fl, qos_lut);
303
304 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
305}
306
307/**
308 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
309 * @plane: Pointer to drm plane
310 * @fb: Pointer to framebuffer associated with the given plane
311 */
312static void _sde_plane_set_danger_lut(struct drm_plane *plane,
313 struct drm_framebuffer *fb)
314{
315 struct sde_plane *psde;
316 const struct sde_format *fmt = NULL;
317 u32 danger_lut, safe_lut;
318
319 if (!plane || !fb) {
320 SDE_ERROR("invalid arguments\n");
321 return;
322 }
323
324 psde = to_sde_plane(plane);
325
326 if (!psde->pipe_hw || !psde->pipe_sblk) {
327 SDE_ERROR("invalid arguments\n");
328 return;
329 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
330 return;
331 }
332
333 if (!psde->is_rt_pipe) {
334 danger_lut = psde->pipe_sblk->danger_lut_nrt;
335 safe_lut = psde->pipe_sblk->safe_lut_nrt;
336 } else {
337 fmt = sde_get_sde_format_ext(
338 fb->pixel_format,
339 fb->modifier,
340 drm_format_num_planes(fb->pixel_format));
341
342 if (SDE_FORMAT_IS_LINEAR(fmt)) {
343 danger_lut = psde->pipe_sblk->danger_lut_linear;
344 safe_lut = psde->pipe_sblk->safe_lut_linear;
345 } else {
346 danger_lut = psde->pipe_sblk->danger_lut_tile;
347 safe_lut = psde->pipe_sblk->safe_lut_tile;
348 }
349 }
350
351 psde->pipe_qos_cfg.danger_lut = danger_lut;
352 psde->pipe_qos_cfg.safe_lut = safe_lut;
353
354 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
355 (fmt) ? fmt->base.pixel_format : 0,
356 (fmt) ? fmt->fetch_mode : 0,
357 psde->pipe_qos_cfg.danger_lut,
358 psde->pipe_qos_cfg.safe_lut);
359
360 SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n",
361 plane->base.id,
362 psde->pipe - SSPP_VIG0,
363 fmt ? fmt->base.pixel_format : 0,
364 fmt ? fmt->fetch_mode : -1,
365 psde->pipe_qos_cfg.danger_lut,
366 psde->pipe_qos_cfg.safe_lut);
367
368 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
369 &psde->pipe_qos_cfg);
370}
371
372/**
373 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
374 * @plane: Pointer to drm plane
375 * @enable: true to enable QoS control
376 * @flags: QoS control mode (enum sde_plane_qos)
377 */
378static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
379 bool enable, u32 flags)
380{
381 struct sde_plane *psde;
382
383 if (!plane) {
384 SDE_ERROR("invalid arguments\n");
385 return;
386 }
387
388 psde = to_sde_plane(plane);
389
390 if (!psde->pipe_hw || !psde->pipe_sblk) {
391 SDE_ERROR("invalid arguments\n");
392 return;
393 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
394 return;
395 }
396
397 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
398 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
399 psde->pipe_qos_cfg.danger_vblank =
400 psde->pipe_sblk->danger_vblank;
401 psde->pipe_qos_cfg.vblank_en = enable;
402 }
403
404 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
405 /* this feature overrules previous VBLANK_CTRL */
406 psde->pipe_qos_cfg.vblank_en = false;
407 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
408 }
409
410 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
411 psde->pipe_qos_cfg.danger_safe_en = enable;
412
413 if (!psde->is_rt_pipe) {
414 psde->pipe_qos_cfg.vblank_en = false;
415 psde->pipe_qos_cfg.danger_safe_en = false;
416 }
417
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400418 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 -0400419 plane->base.id,
420 psde->pipe - SSPP_VIG0,
421 psde->pipe_qos_cfg.danger_safe_en,
422 psde->pipe_qos_cfg.vblank_en,
423 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400424 psde->pipe_qos_cfg.danger_vblank,
425 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400426
427 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
428 &psde->pipe_qos_cfg);
429}
430
Alan Kwongf0fd8512016-10-24 21:39:26 -0400431int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
432{
433 struct sde_plane *psde;
434 struct msm_drm_private *priv;
435 struct sde_kms *sde_kms;
436
437 if (!plane || !plane->dev) {
438 SDE_ERROR("invalid arguments\n");
439 return -EINVAL;
440 }
441
442 priv = plane->dev->dev_private;
443 if (!priv || !priv->kms) {
444 SDE_ERROR("invalid KMS reference\n");
445 return -EINVAL;
446 }
447
448 sde_kms = to_sde_kms(priv->kms);
449 psde = to_sde_plane(plane);
450
451 if (!psde->is_rt_pipe)
452 goto end;
453
454 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
455
456 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
457
458 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
459
460end:
461 return 0;
462}
463
Alan Kwong5d324e42016-07-28 22:56:18 -0400464/**
465 * _sde_plane_set_ot_limit - set OT limit for the given plane
466 * @plane: Pointer to drm plane
467 * @crtc: Pointer to drm crtc
468 */
469static void _sde_plane_set_ot_limit(struct drm_plane *plane,
470 struct drm_crtc *crtc)
471{
472 struct sde_plane *psde;
473 struct sde_vbif_set_ot_params ot_params;
474 struct msm_drm_private *priv;
475 struct sde_kms *sde_kms;
476
477 if (!plane || !plane->dev || !crtc) {
478 SDE_ERROR("invalid arguments plane %d crtc %d\n",
479 plane != 0, crtc != 0);
480 return;
481 }
482
483 priv = plane->dev->dev_private;
484 if (!priv || !priv->kms) {
485 SDE_ERROR("invalid KMS reference\n");
486 return;
487 }
488
489 sde_kms = to_sde_kms(priv->kms);
490 psde = to_sde_plane(plane);
491 if (!psde->pipe_hw) {
492 SDE_ERROR("invalid pipe reference\n");
493 return;
494 }
495
496 memset(&ot_params, 0, sizeof(ot_params));
497 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
498 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
499 ot_params.width = psde->pipe_cfg.src_rect.w;
500 ot_params.height = psde->pipe_cfg.src_rect.h;
501 ot_params.is_wfd = !psde->is_rt_pipe;
502 ot_params.frame_rate = crtc->mode.vrefresh;
503 ot_params.vbif_idx = VBIF_RT;
504 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
505 ot_params.rd = true;
506
507 sde_vbif_set_ot_limit(sde_kms, &ot_params);
508}
509
Clarence Ipcae1bb62016-07-07 12:07:13 -0400510/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400511static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400512 struct sde_plane_state *pstate, uint64_t fd)
513{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400514 if (!psde || !pstate) {
515 SDE_ERROR("invalid arg(s), plane %d state %d\n",
516 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400517 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400518 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400519
520 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400521 if (pstate->input_fence)
522 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400523
524 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400525 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400526
Clarence Ip13a8cf42016-09-29 17:27:47 -0400527 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400528}
529
Clarence Ipcae1bb62016-07-07 12:07:13 -0400530int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400531{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400532 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400533 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400534 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400535 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400536 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800537 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400538
539 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700540 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400541 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400542 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400543 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400544 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400545 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400546 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400547
Clarence Ipcae1bb62016-07-07 12:07:13 -0400548 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800549 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400550 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800551 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400552
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400553 SDE_EVT32(DRMID(plane), -ret, prefix);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400554
Dhaval Patel39323d42017-03-01 23:48:24 -0800555 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400556 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400557 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
558 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400559 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800560 ret = -ETIMEDOUT;
561 break;
562 case -ERESTARTSYS:
563 SDE_ERROR_PLANE(psde,
564 "%ums wait interrupted on %08X\n",
565 wait_ms, prefix);
566 psde->is_error = true;
567 ret = -ERESTARTSYS;
568 break;
569 case -EINVAL:
570 SDE_ERROR_PLANE(psde,
571 "invalid fence param for %08X\n",
572 prefix);
573 psde->is_error = true;
574 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400575 break;
576 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800577 SDE_DEBUG_PLANE(psde, "signaled\n");
578 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400579 break;
580 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400581 } else {
582 ret = 0;
583 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400584 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400585 return ret;
586}
587
Clarence Ip282dad62016-09-27 17:07:35 -0400588static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400589 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400590 struct sde_hw_pipe_cfg *pipe_cfg,
591 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400592{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400593 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400594 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400595
Clarence Ip13a8cf42016-09-29 17:27:47 -0400596 if (!plane || !pstate || !pipe_cfg || !fb) {
597 SDE_ERROR(
598 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
599 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400600 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400601 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400602
603 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400604 if (!psde->pipe_hw) {
605 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400606 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400607 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400608
Clarence Ipb6eb2362016-09-08 16:18:13 -0400609 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
610 if (ret == -EAGAIN)
611 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
612 else if (ret)
613 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
614 else if (psde->pipe_hw->ops.setup_sourceaddress)
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800615 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
616 pstate->multirect_index);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400617}
618
abeykun48f407a2016-08-25 12:06:44 -0400619static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
620 struct sde_plane_state *pstate)
621{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500622 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400623 int ret = 0;
624
Clarence Ip3bf8d872017-02-16 15:25:38 -0500625 if (!psde || !psde->scaler3_cfg) {
626 SDE_ERROR("invalid args\n");
627 return -EINVAL;
628 } else if (!pstate) {
629 /* pstate is expected to be null on forced color fill */
630 SDE_DEBUG("null pstate\n");
631 return -EINVAL;
632 }
633
634 cfg = psde->scaler3_cfg;
635
abeykun48f407a2016-08-25 12:06:44 -0400636 cfg->dir_lut = msm_property_get_blob(
637 &psde->property_info,
638 pstate->property_blobs, &cfg->dir_len,
639 PLANE_PROP_SCALER_LUT_ED);
640 cfg->cir_lut = msm_property_get_blob(
641 &psde->property_info,
642 pstate->property_blobs, &cfg->cir_len,
643 PLANE_PROP_SCALER_LUT_CIR);
644 cfg->sep_lut = msm_property_get_blob(
645 &psde->property_info,
646 pstate->property_blobs, &cfg->sep_len,
647 PLANE_PROP_SCALER_LUT_SEP);
648 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
649 ret = -ENODATA;
650 return ret;
651}
652
Clarence Ipcb410d42016-06-26 22:52:33 -0400653static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400654 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
655 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400656 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400657 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
658{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700659 uint32_t decimated, i;
660
661 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
662 !chroma_subsmpl_v) {
663 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
664 , psde, scale_cfg, fmt, chroma_subsmpl_h,
665 chroma_subsmpl_v);
666 return;
667 }
668
669 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip716ab662017-03-20 06:51:24 -0700670 memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700671
672 decimated = DECIMATED_DIMENSION(src_w,
673 psde->pipe_cfg.horz_decimation);
674 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
675 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
676 decimated = DECIMATED_DIMENSION(src_h,
677 psde->pipe_cfg.vert_decimation);
678 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
679 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
680
681
682 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
683 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
684 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
685 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
686
687 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
688 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
689 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
690 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
691
692 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
693 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
694 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
695 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
696
697 for (i = 0; i < SDE_MAX_PLANES; i++) {
698 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
699 psde->pipe_cfg.horz_decimation);
700 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
701 psde->pipe_cfg.vert_decimation);
702 if (SDE_FORMAT_IS_YUV(fmt))
703 scale_cfg->src_width[i] &= ~0x1;
704 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
705 scale_cfg->src_width[i] /= chroma_subsmpl_h;
706 scale_cfg->src_height[i] /= chroma_subsmpl_v;
707 }
708 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
709 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
710 psde->pixel_ext.num_ext_pxls_top[i] =
711 scale_cfg->src_height[i];
712 psde->pixel_ext.num_ext_pxls_left[i] =
713 scale_cfg->src_width[i];
714 }
715 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
716 && (src_w == dst_w))
717 return;
718
719 scale_cfg->dst_width = dst_w;
720 scale_cfg->dst_height = dst_h;
721 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
722 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
723 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
724 scale_cfg->lut_flag = 0;
725 scale_cfg->blend_cfg = 1;
726 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -0400727}
728
Clarence Ipcb410d42016-06-26 22:52:33 -0400729/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400730 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400731 * @psde: Pointer to SDE plane object
732 * @src: Source size
733 * @dst: Destination size
734 * @phase_steps: Pointer to output array for phase steps
735 * @filter: Pointer to output array for filter type
736 * @fmt: Pointer to format definition
737 * @chroma_subsampling: Subsampling amount for chroma channel
738 *
739 * Returns: 0 on success
740 */
741static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400742 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400743 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400744 uint32_t chroma_subsampling)
745{
Clarence Ipcb410d42016-06-26 22:52:33 -0400746 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400747 SDE_ERROR(
748 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
749 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400750 return -EINVAL;
751 }
752
Clarence Ip4c1d9772016-06-26 09:35:38 -0400753 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400754 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400755 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400756 phase_steps[SDE_SSPP_COMP_1_2] =
757 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
758 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
759 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400760
761 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400762 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400763 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400764 (src <= dst) ? SDE_SCALE_FILTER_BIL :
765 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400766
Clarence Ipdbde9832016-06-26 09:48:36 -0400767 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400768 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400769 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
770 } else {
771 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
772 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400773 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400774 }
775 } else {
776 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400777 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
778 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
779 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400780 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400781 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400782}
783
Clarence Ipcb410d42016-06-26 22:52:33 -0400784/**
785 * _sde_plane_setup_pixel_ext - determine default pixel extension values
786 * @psde: Pointer to SDE plane object
787 * @src: Source size
788 * @dst: Destination size
789 * @decimated_src: Source size after decimation, if any
790 * @phase_steps: Pointer to output array for phase steps
791 * @out_src: Output array for pixel extension values
792 * @out_edge1: Output array for pixel extension first edge
793 * @out_edge2: Output array for pixel extension second edge
794 * @filter: Pointer to array for filter type
795 * @fmt: Pointer to format definition
796 * @chroma_subsampling: Subsampling amount for chroma channel
797 * @post_compare: Whether to chroma subsampled source size for comparisions
798 */
799static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400800 uint32_t src, uint32_t dst, uint32_t decimated_src,
801 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400802 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400803 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400804 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400805{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400806 int64_t edge1, edge2, caf;
807 uint32_t src_work;
808 int i, tmp;
809
Clarence Ipcb410d42016-06-26 22:52:33 -0400810 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400811 out_edge2 && filter && fmt) {
812 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400813 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400814 caf = PHASE_STEP_UNIT_SCALE;
815 else
816 caf = 0;
817
818 for (i = 0; i < SDE_MAX_PLANES; i++) {
819 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400820 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400821 src_work /= chroma_subsampling;
822 if (post_compare)
823 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400824 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400825 /* unity */
826 edge1 = 0;
827 edge2 = 0;
828 } else if (dst >= src) {
829 /* upscale */
830 edge1 = (1 << PHASE_RESIDUAL);
831 edge1 -= caf;
832 edge2 = (1 << PHASE_RESIDUAL);
833 edge2 += (dst - 1) * *(phase_steps + i);
834 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
835 edge2 += caf;
836 edge2 = -(edge2);
837 } else {
838 /* downscale */
839 edge1 = 0;
840 edge2 = (dst - 1) * *(phase_steps + i);
841 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
842 edge2 += *(phase_steps + i);
843 edge2 = -(edge2);
844 }
845
846 /* only enable CAF for luma plane */
847 caf = 0;
848
849 /* populate output arrays */
850 *(out_src + i) = src_work;
851
852 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400853 if (edge1 >= 0) {
854 tmp = (uint32_t)edge1;
855 tmp >>= PHASE_STEP_SHIFT;
856 *(out_edge1 + i) = -tmp;
857 } else {
858 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400859 *(out_edge1 + i) =
860 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
861 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400862 }
863 if (edge2 >= 0) {
864 tmp = (uint32_t)edge2;
865 tmp >>= PHASE_STEP_SHIFT;
866 *(out_edge2 + i) = -tmp;
867 } else {
868 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400869 *(out_edge2 + i) =
870 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
871 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400872 }
873 }
874 }
875}
876
Clarence Ip5fc00c52016-09-23 15:03:34 -0400877static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400878{
879 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
880 {
Clarence Ip373f8592016-05-26 00:58:42 -0400881 /* S15.16 format */
882 0x00012A00, 0x00000000, 0x00019880,
883 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
884 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400885 },
Clarence Ip373f8592016-05-26 00:58:42 -0400886 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400887 { 0xfff0, 0xff80, 0xff80,},
888 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400889 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400890 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400891 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400892 };
abeykun1c312f62016-08-26 09:47:12 -0400893 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
894 {
895 /* S15.16 format */
896 0x00012A00, 0x00000000, 0x00019880,
897 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
898 0x00012A00, 0x00020480, 0x00000000,
899 },
900 /* signed bias */
901 { 0xffc0, 0xfe00, 0xfe00,},
902 { 0x0, 0x0, 0x0,},
903 /* unsigned clamp */
904 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
905 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
906 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400907
Clarence Ip5fc00c52016-09-23 15:03:34 -0400908 if (!psde) {
909 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400910 return;
911 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400912
Clarence Ipcae1bb62016-07-07 12:07:13 -0400913 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400914 if (psde->csc_usr_ptr)
915 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400916 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
917 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400918 else
Clarence Ip373f8592016-05-26 00:58:42 -0400919 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400920
Clarence Ip13a8cf42016-09-29 17:27:47 -0400921 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400922 psde->csc_ptr->csc_mv[0],
923 psde->csc_ptr->csc_mv[1],
924 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400925}
926
Benet Clarkeb1b4462016-06-27 14:43:06 -0700927static void sde_color_process_plane_setup(struct drm_plane *plane)
928{
929 struct sde_plane *psde;
930 struct sde_plane_state *pstate;
931 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -0700932 struct drm_msm_memcol *memcol = NULL;
933 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -0700934
935 psde = to_sde_plane(plane);
936 pstate = to_sde_plane_state(plane->state);
937
938 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
939 if (psde->pipe_hw->ops.setup_pa_hue)
940 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
941 saturation = (uint32_t) sde_plane_get_property(pstate,
942 PLANE_PROP_SATURATION_ADJUST);
943 if (psde->pipe_hw->ops.setup_pa_sat)
944 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
945 value = (uint32_t) sde_plane_get_property(pstate,
946 PLANE_PROP_VALUE_ADJUST);
947 if (psde->pipe_hw->ops.setup_pa_val)
948 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
949 contrast = (uint32_t) sde_plane_get_property(pstate,
950 PLANE_PROP_CONTRAST_ADJUST);
951 if (psde->pipe_hw->ops.setup_pa_cont)
952 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -0700953
Benet Clarkd009b1d2016-06-27 14:45:59 -0700954 if (psde->pipe_hw->ops.setup_pa_memcolor) {
955 /* Skin memory color setup */
956 memcol = msm_property_get_blob(&psde->property_info,
957 pstate->property_blobs,
958 &memcol_sz,
959 PLANE_PROP_SKIN_COLOR);
960 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
961 MEMCOLOR_SKIN, memcol);
962
963 /* Sky memory color setup */
964 memcol = msm_property_get_blob(&psde->property_info,
965 pstate->property_blobs,
966 &memcol_sz,
967 PLANE_PROP_SKY_COLOR);
968 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
969 MEMCOLOR_SKY, memcol);
970
971 /* Foliage memory color setup */
972 memcol = msm_property_get_blob(&psde->property_info,
973 pstate->property_blobs,
974 &memcol_sz,
975 PLANE_PROP_FOLIAGE_COLOR);
976 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
977 MEMCOLOR_FOLIAGE, memcol);
978 }
979}
Benet Clarkeb1b4462016-06-27 14:43:06 -0700980
Clarence Ipcb410d42016-06-26 22:52:33 -0400981static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400982 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -0400983 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700984{
Clarence Ipb43d4592016-09-08 14:21:35 -0400985 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -0400986 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400987
Clarence Ipb43d4592016-09-08 14:21:35 -0400988 if (!psde || !fmt) {
989 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
990 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400991 return;
Clarence Ipb43d4592016-09-08 14:21:35 -0400992 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400993
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400994 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400995
Clarence Ipdedbba92016-09-27 17:43:10 -0400996 psde->pipe_cfg.horz_decimation =
997 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
998 psde->pipe_cfg.vert_decimation =
999 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001000
1001 /* don't chroma subsample if decimating */
1002 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001003 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001004 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001005 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001006
Clarence Ip5e2a9222016-06-26 22:38:24 -04001007 /* update scaler */
1008 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001009 int error;
1010
1011 error = _sde_plane_setup_scaler3_lut(psde, pstate);
Clarence Ip716ab662017-03-20 06:51:24 -07001012 if (error || !psde->pixel_ext_usr ||
1013 psde->debugfs_default_scale) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001014 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001015 _sde_plane_setup_scaler3(psde,
1016 psde->pipe_cfg.src_rect.w,
1017 psde->pipe_cfg.src_rect.h,
1018 psde->pipe_cfg.dst_rect.w,
1019 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001020 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001021 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001022 }
Clarence Ip716ab662017-03-20 06:51:24 -07001023 } else if (!psde->pixel_ext_usr || !pstate ||
1024 psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001025 uint32_t deci_dim, i;
1026
Clarence Ipb43d4592016-09-08 14:21:35 -04001027 /* calculate default configuration for QSEED2 */
1028 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001029
Clarence Ip13a8cf42016-09-29 17:27:47 -04001030 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001031 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1032 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001033 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001034 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001035 psde->pipe_cfg.dst_rect.w,
1036 pe->phase_step_x,
1037 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001038
Clarence Ipdbde9832016-06-26 09:48:36 -04001039 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001040 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001041 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001042 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001043 pe->phase_step_x,
1044 pe->roi_w,
1045 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001046 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001047 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001048
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001049 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001050 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001051 _sde_plane_setup_scaler2(psde,
1052 deci_dim,
1053 psde->pipe_cfg.dst_rect.h,
1054 pe->phase_step_y,
1055 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001056 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001057 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001058 pe->phase_step_y,
1059 pe->roi_h,
1060 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001061 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001062 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001063
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001064 for (i = 0; i < SDE_MAX_PLANES; i++) {
1065 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001066 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001067 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001068 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001069
1070 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001071 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001072 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001073 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001074
1075 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001076 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001077 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001078 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001079
1080 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001081 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001082 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001083 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001084 }
1085 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001086}
1087
Clarence Ipcae1bb62016-07-07 12:07:13 -04001088/**
1089 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001090 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001091 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1092 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1093 * Returns: 0 on success
1094 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001095static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001096 uint32_t color, uint32_t alpha)
1097{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001098 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001099 const struct drm_plane *plane;
1100 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001101
Clarence Ip13a8cf42016-09-29 17:27:47 -04001102 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001103 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001104 return -EINVAL;
1105 }
1106
Clarence Ipcb410d42016-06-26 22:52:33 -04001107 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001108 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001109 return -EINVAL;
1110 }
1111
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001112 plane = &psde->base;
1113 pstate = to_sde_plane_state(plane->state);
1114
Clarence Ip13a8cf42016-09-29 17:27:47 -04001115 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001116
Clarence Ipcb410d42016-06-26 22:52:33 -04001117 /*
1118 * select fill format to match user property expectation,
1119 * h/w only supports RGB variants
1120 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001121 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001122
1123 /* update sspp */
1124 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1125 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001126 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1127 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001128
1129 /* override scaler/decimation if solid fill */
1130 psde->pipe_cfg.src_rect.x = 0;
1131 psde->pipe_cfg.src_rect.y = 0;
1132 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1133 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
1134
Clarence Ipcb410d42016-06-26 22:52:33 -04001135 if (psde->pipe_hw->ops.setup_format)
1136 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001137 fmt, SDE_SSPP_SOLID_FILL,
1138 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001139
1140 if (psde->pipe_hw->ops.setup_rects)
1141 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001142 &psde->pipe_cfg,
1143 pstate->multirect_index);
1144
1145 _sde_plane_setup_scaler(psde, fmt, 0);
1146 if (psde->pipe_hw->ops.setup_pe)
1147 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1148 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001149 }
1150
1151 return 0;
1152}
1153
1154static int _sde_plane_mode_set(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001155 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -04001156{
Clarence Ipc47a0692016-10-11 10:54:17 -04001157 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -04001158 struct sde_plane *psde;
1159 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001160 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001161 struct drm_crtc *crtc;
1162 struct drm_framebuffer *fb;
1163 struct sde_rect src, dst;
1164 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001165 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -04001166
Clarence Ip13a8cf42016-09-29 17:27:47 -04001167 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -04001168 SDE_ERROR("invalid plane\n");
1169 return -EINVAL;
1170 } else if (!plane->state) {
1171 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001172 return -EINVAL;
1173 }
1174
1175 psde = to_sde_plane(plane);
1176 pstate = to_sde_plane_state(plane->state);
Clarence Ipcb410d42016-06-26 22:52:33 -04001177
Dhaval Patel47302cf2016-08-18 15:04:28 -07001178 crtc = state->crtc;
1179 fb = state->fb;
1180 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001181 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
1182 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -07001183 return -EINVAL;
1184 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001185 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001186 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -04001187
Clarence Ip282dad62016-09-27 17:07:35 -04001188 /* determine what needs to be refreshed */
1189 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
1190 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001191 case PLANE_PROP_SCALER_V1:
abeykun48f407a2016-08-25 12:06:44 -04001192 case PLANE_PROP_SCALER_V2:
Clarence Ipdedbba92016-09-27 17:43:10 -04001193 case PLANE_PROP_H_DECIMATE:
1194 case PLANE_PROP_V_DECIMATE:
1195 case PLANE_PROP_SRC_CONFIG:
1196 case PLANE_PROP_ZPOS:
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001197 case PLANE_PROP_EXCL_RECT_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04001198 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1199 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001200 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04001201 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
1202 break;
1203 case PLANE_PROP_COLOR_FILL:
1204 /* potentially need to refresh everything */
1205 pstate->dirty = SDE_PLANE_DIRTY_ALL;
1206 break;
1207 case PLANE_PROP_ROTATION:
1208 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
1209 break;
Clarence Ip282dad62016-09-27 17:07:35 -04001210 case PLANE_PROP_INFO:
1211 case PLANE_PROP_ALPHA:
1212 case PLANE_PROP_INPUT_FENCE:
1213 case PLANE_PROP_BLEND_OP:
1214 /* no special action required */
1215 break;
1216 default:
1217 /* unknown property, refresh everything */
1218 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
1219 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
1220 break;
1221 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001222 }
1223
Clarence Ip282dad62016-09-27 17:07:35 -04001224 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
1225 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -04001226
1227 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
1228
Clarence Ip282dad62016-09-27 17:07:35 -04001229 /* early out if nothing dirty */
1230 if (!pstate->dirty)
1231 return 0;
1232 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001233
Dhaval Patel4d424602017-02-18 19:40:14 -08001234 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
Clarence Ip282dad62016-09-27 17:07:35 -04001235 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1236
1237 /* update roi config */
1238 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
1239 POPULATE_RECT(&src, state->src_x, state->src_y,
1240 state->src_w, state->src_h, q16_data);
1241 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
1242 state->crtc_w, state->crtc_h, !q16_data);
1243
Clarence Ip13a8cf42016-09-29 17:27:47 -04001244 SDE_DEBUG_PLANE(psde,
1245 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001246 fb->base.id, src.x, src.y, src.w, src.h,
1247 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
1248 drm_get_format_name(fmt->base.pixel_format),
1249 SDE_FORMAT_IS_UBWC(fmt));
1250
1251 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
1252 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001253 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001254 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
1255 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
1256 src.h /= 2;
1257 src.y = DIV_ROUND_UP(src.y, 2);
1258 src.y &= ~0x1;
1259 }
1260
1261 psde->pipe_cfg.src_rect = src;
1262 psde->pipe_cfg.dst_rect = dst;
1263
1264 /* check for color fill */
1265 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
1266 PLANE_PROP_COLOR_FILL);
1267 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
1268 /* skip remaining processing on color fill */
1269 pstate->dirty = 0x0;
1270 } else if (psde->pipe_hw->ops.setup_rects) {
Clarence Ip282dad62016-09-27 17:07:35 -04001271 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001272 &psde->pipe_cfg,
1273 pstate->multirect_index);
Clarence Ip282dad62016-09-27 17:07:35 -04001274 }
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001275
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001276 _sde_plane_setup_scaler(psde, fmt, pstate);
1277 if (psde->pipe_hw->ops.setup_pe)
1278 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1279 &psde->pixel_ext);
1280
1281 if (psde->pipe_hw->ops.setup_scaler)
1282 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
1283 &psde->pipe_cfg, &psde->pixel_ext,
1284 psde->scaler3_cfg);
1285
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001286 /* update excl rect */
1287 if (psde->pipe_hw->ops.setup_excl_rect)
1288 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001289 &pstate->excl_rect,
1290 pstate->multirect_index);
1291
1292 if (psde->pipe_hw->ops.setup_multirect)
1293 psde->pipe_hw->ops.setup_multirect(
1294 psde->pipe_hw,
1295 pstate->multirect_index,
1296 pstate->multirect_mode);
Dhaval Patel48c76022016-09-01 17:51:23 -07001297 }
1298
Clarence Ip282dad62016-09-27 17:07:35 -04001299 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
1300 psde->pipe_hw->ops.setup_format) {
1301 src_flags = 0x0;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001302 SDE_DEBUG_PLANE(psde, "rotation 0x%llX\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001303 sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
1304 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
Clarence Ip531f5572017-01-24 10:10:05 -08001305 DRM_REFLECT_X)
Clarence Ip282dad62016-09-27 17:07:35 -04001306 src_flags |= SDE_SSPP_FLIP_LR;
1307 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
Clarence Ip531f5572017-01-24 10:10:05 -08001308 DRM_REFLECT_Y)
Clarence Ip282dad62016-09-27 17:07:35 -04001309 src_flags |= SDE_SSPP_FLIP_UD;
1310
1311 /* update format */
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001312 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
1313 pstate->multirect_index);
Clarence Ip282dad62016-09-27 17:07:35 -04001314
1315 /* update csc */
1316 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04001317 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04001318 else
1319 psde->csc_ptr = 0;
1320 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001321
Benet Clarkeb1b4462016-06-27 14:43:06 -07001322 sde_color_process_plane_setup(plane);
1323
Clarence Ipe78efb72016-06-24 18:35:21 -04001324 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04001325 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
1326 psde->pipe_hw->ops.setup_sharpening) {
1327 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
1328 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
1329 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
1330 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04001331
Clarence Ipe78efb72016-06-24 18:35:21 -04001332 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04001333 &psde->sharp_cfg);
1334 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001335
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001336 _sde_plane_set_qos_lut(plane, fb);
1337 _sde_plane_set_danger_lut(plane, fb);
1338
Alan Kwong5d324e42016-07-28 22:56:18 -04001339 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001340 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04001341 _sde_plane_set_ot_limit(plane, crtc);
1342 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001343
Clarence Ip282dad62016-09-27 17:07:35 -04001344 /* clear dirty */
1345 pstate->dirty = 0x0;
1346
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001347 /* clear multirect mode*/
1348 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
1349 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
1350 return 0;
1351}
1352
1353int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
1354{
1355 struct sde_plane_state *pstate[R_MAX];
1356 const struct drm_plane_state *drm_state[R_MAX];
1357 struct sde_rect src[R_MAX], dst[R_MAX];
1358 struct sde_plane *sde_plane[R_MAX];
1359 const struct sde_format *fmt[R_MAX];
1360 bool q16_data = true;
1361 int i, max_sspp_linewidth;
1362 int buffer_lines = TX_MODE_BUFFER_LINE_THRES;
1363
1364 for (i = 0; i < R_MAX; i++) {
1365 const struct msm_format *msm_fmt;
1366
1367 drm_state[i] = i ? plane->r1 : plane->r0;
1368 pstate[i] = to_sde_plane_state(drm_state[i]);
1369 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
1370
1371 if (pstate[i] == NULL) {
1372 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
1373 drm_state[i]->plane->base.id);
1374 return -EINVAL;
1375 }
1376
1377 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
1378 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
1379 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
1380 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
1381 drm_state[i]->crtc_h, !q16_data);
1382
1383 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
1384 SDE_ERROR_PLANE(sde_plane[i],
1385 "scaling is not supported in multirect mode\n");
1386 return -EINVAL;
1387 }
1388
1389 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
1390 fmt[i] = to_sde_format(msm_fmt);
1391 if (SDE_FORMAT_IS_YUV(fmt[i])) {
1392 SDE_ERROR_PLANE(sde_plane[i],
1393 "Unsupported format for multirect mode\n");
1394 return -EINVAL;
1395 }
1396 }
1397
1398 max_sspp_linewidth = sde_plane[R0]->pipe_sblk->maxlinewidth;
1399
1400 /* Validate RECT's and set the mode */
1401
1402 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
1403 if (src[R0].w <= max_sspp_linewidth/2 &&
1404 src[R1].w <= max_sspp_linewidth/2) {
1405 if (dst[R0].x <= dst[R1].x) {
1406 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
1407 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
1408 } else {
1409 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
1410 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
1411 }
1412
1413 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
1414 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
1415 goto done;
1416 }
1417
1418 /* TIME_MX Mode */
1419 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
1420 buffer_lines = 2 * fmt[R0]->tile_height;
1421
1422 if (dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) {
1423 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
1424 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
1425 } else if (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines) {
1426 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
1427 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
1428 } else {
1429 SDE_ERROR(
1430 "No multirect mode possible for the planes (%d - %d)\n",
1431 drm_state[R0]->plane->base.id,
1432 drm_state[R1]->plane->base.id);
1433 return -EINVAL;
1434 }
1435
1436 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
1437 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
1438done:
Clarence Ip5e2a9222016-06-26 22:38:24 -04001439 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001440}
1441
1442static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001443 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001444{
1445 struct drm_framebuffer *fb = new_state->fb;
1446 struct sde_plane *psde = to_sde_plane(plane);
1447
1448 if (!new_state->fb)
1449 return 0;
1450
Clarence Ip13a8cf42016-09-29 17:27:47 -04001451 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001452 return msm_framebuffer_prepare(fb, psde->mmu_id);
1453}
1454
1455static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001456 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001457{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001458 struct drm_framebuffer *fb = old_state ? old_state->fb : NULL;
1459 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001460
1461 if (!fb)
1462 return;
1463
Clarence Ip13a8cf42016-09-29 17:27:47 -04001464 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001465 msm_framebuffer_cleanup(fb, psde->mmu_id);
1466}
1467
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001468static void _sde_plane_atomic_check_mode_changed(struct sde_plane *psde,
1469 struct drm_plane_state *state,
1470 struct drm_plane_state *old_state)
1471{
1472 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001473 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001474
Dhaval Patel47302cf2016-08-18 15:04:28 -07001475 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04001476 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001477 return;
1478
Clarence Ip282dad62016-09-27 17:07:35 -04001479 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
1480 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001481 SDE_DEBUG_PLANE(psde,
1482 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001483 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001484 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001485 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001486 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001487 } else if (state->src_w != old_state->src_w ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07001488 state->src_h != old_state->src_h ||
1489 state->src_x != old_state->src_x ||
1490 state->src_y != old_state->src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001491 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001492 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001493 } else if (state->crtc_w != old_state->crtc_w ||
1494 state->crtc_h != old_state->crtc_h ||
1495 state->crtc_x != old_state->crtc_x ||
1496 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001497 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001498 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001499 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
1500 pstate->excl_rect.h != old_pstate->excl_rect.h ||
1501 pstate->excl_rect.x != old_pstate->excl_rect.x ||
1502 pstate->excl_rect.y != old_pstate->excl_rect.y) {
1503 SDE_DEBUG_PLANE(psde, "excl rect updated\n");
1504 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001505 } else if (pstate->multirect_index != old_pstate->multirect_index ||
1506 pstate->multirect_mode != old_pstate->multirect_mode) {
1507 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
1508 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04001509 }
1510
1511 if (!state->fb || !old_state->fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001512 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001513 } else if (state->fb->pixel_format != old_state->fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001514 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001515 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001516 } else {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001517 uint64_t *new_mods = state->fb->modifier;
1518 uint64_t *old_mods = old_state->fb->modifier;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001519 uint32_t *new_pitches = state->fb->pitches;
1520 uint32_t *old_pitches = old_state->fb->pitches;
1521 uint32_t *new_offset = state->fb->offsets;
1522 uint32_t *old_offset = old_state->fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001523 int i;
1524
1525 for (i = 0; i < ARRAY_SIZE(state->fb->modifier); i++) {
1526 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001527 SDE_DEBUG_PLANE(psde,
1528 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001529 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001530 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001531 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1532 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001533 break;
1534 }
1535 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001536 for (i = 0; i < ARRAY_SIZE(state->fb->pitches); i++) {
1537 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001538 SDE_DEBUG_PLANE(psde,
1539 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001540 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001541 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001542 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001543 break;
1544 }
1545 }
Dhaval Patel47302cf2016-08-18 15:04:28 -07001546 for (i = 0; i < ARRAY_SIZE(state->fb->offsets); i++) {
1547 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001548 SDE_DEBUG_PLANE(psde,
1549 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001550 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001551 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001552 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1553 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001554 break;
1555 }
1556 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001557 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001558}
1559
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001560static int sde_plane_atomic_check(struct drm_plane *plane,
1561 struct drm_plane_state *state)
1562{
Clarence Ipdedbba92016-09-27 17:43:10 -04001563 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04001564 struct sde_plane *psde;
1565 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001566 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001567 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04001568 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001569 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
1570 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04001571
1572 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001573 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1574 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04001575 ret = -EINVAL;
1576 goto exit;
1577 }
1578
1579 psde = to_sde_plane(plane);
1580 pstate = to_sde_plane_state(state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001581
1582 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001583 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001584 ret = -EINVAL;
1585 goto exit;
1586 }
1587
Clarence Ipdedbba92016-09-27 17:43:10 -04001588 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1589 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04001590
1591 /* src values are in Q16 fixed point, convert to integer */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001592 POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w,
1593 state->src_h, q16_data);
1594 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
1595 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04001596
Dhaval Patel47302cf2016-08-18 15:04:28 -07001597 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
1598 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04001599
Dhaval Patel47302cf2016-08-18 15:04:28 -07001600 max_upscale = psde->pipe_sblk->maxupscale;
1601 max_downscale = psde->pipe_sblk->maxdwnscale;
1602 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04001603
Clarence Ip13a8cf42016-09-29 17:27:47 -04001604 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001605 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001606
Dhaval Patel47302cf2016-08-18 15:04:28 -07001607 if (!sde_plane_enabled(state))
1608 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04001609
Dhaval Patel47302cf2016-08-18 15:04:28 -07001610 fmt = to_sde_format(msm_framebuffer_format(state->fb));
1611
1612 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
1613
1614 if (SDE_FORMAT_IS_YUV(fmt) &&
1615 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04001616 !(psde->features & (BIT(SDE_SSPP_CSC)
1617 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001618 SDE_ERROR_PLANE(psde,
1619 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07001620 ret = -EINVAL;
1621
1622 /* check src bounds */
1623 } else if (state->fb->width > MAX_IMG_WIDTH ||
1624 state->fb->height > MAX_IMG_HEIGHT ||
1625 src.w < min_src_size || src.h < min_src_size ||
1626 CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) ||
1627 CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001628 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001629 src.x, src.y, src.w, src.h);
1630 ret = -E2BIG;
1631
1632 /* valid yuv image */
1633 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
1634 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001635 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001636 src.x, src.y, src.w, src.h);
1637 ret = -EINVAL;
1638
1639 /* min dst support */
1640 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001641 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001642 dst.x, dst.y, dst.w, dst.h);
1643 ret = -EINVAL;
1644
1645 /* decimation validation */
1646 } else if (deci_w || deci_h) {
1647 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
1648 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001649 SDE_ERROR_PLANE(psde,
1650 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001651 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001652 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001653 SDE_ERROR_PLANE(psde,
1654 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001655 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001656 }
1657
Dhaval Patel47302cf2016-08-18 15:04:28 -07001658 } else if (!(psde->features & SDE_SSPP_SCALER) &&
1659 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001660 SDE_ERROR_PLANE(psde,
1661 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001662 src.w, src.h, dst.w, dst.h);
1663 ret = -EINVAL;
1664
1665 /* check decimated source width */
1666 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001667 SDE_ERROR_PLANE(psde,
1668 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001669 src.w, src_deci_w, max_linewidth);
1670 ret = -E2BIG;
1671
1672 /* check max scaler capability */
1673 } else if (((src_deci_w * max_upscale) < dst.w) ||
1674 ((src_deci_h * max_upscale) < dst.h) ||
1675 ((dst.w * max_downscale) < src_deci_w) ||
1676 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001677 SDE_ERROR_PLANE(psde,
1678 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001679 src_deci_w, src_deci_h, dst.w, dst.h);
1680 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001681 }
1682
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001683 /* check excl rect configs */
1684 if (pstate->excl_rect.w && pstate->excl_rect.h) {
1685 struct sde_rect intersect;
1686
1687 /*
1688 * Check exclusion rect against src rect.
1689 * Cropping is not required as hardware will consider only the
1690 * intersecting region with the src rect.
1691 */
1692 sde_kms_rect_intersect(&intersect, &src, &pstate->excl_rect);
1693 if (!intersect.w || !intersect.h || SDE_FORMAT_IS_YUV(fmt)) {
1694 SDE_ERROR_PLANE(psde,
1695 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt:%s\n",
1696 pstate->excl_rect.x, pstate->excl_rect.y,
1697 pstate->excl_rect.w, pstate->excl_rect.h,
1698 src.x, src.y, src.w, src.h,
1699 drm_get_format_name(fmt->base.pixel_format));
1700 ret = -EINVAL;
1701 }
1702 }
1703
Dhaval Patel47302cf2016-08-18 15:04:28 -07001704modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001705 if (!ret)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001706 _sde_plane_atomic_check_mode_changed(psde, state, plane->state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001707exit:
1708 return ret;
1709}
1710
Clarence Ipcae1bb62016-07-07 12:07:13 -04001711/**
1712 * sde_plane_flush - final plane operations before commit flush
1713 * @plane: Pointer to drm plane structure
1714 */
1715void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04001716{
Clarence Ipcae1bb62016-07-07 12:07:13 -04001717 struct sde_plane *psde;
1718
Clarence Ip13a8cf42016-09-29 17:27:47 -04001719 if (!plane) {
1720 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001721 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001722 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04001723
1724 psde = to_sde_plane(plane);
1725
1726 /*
1727 * These updates have to be done immediately before the plane flush
1728 * timing, and may not be moved to the atomic_update/mode_set functions.
1729 */
1730 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05001731 /* force white frame with 100% alpha pipe output on error */
1732 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001733 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
1734 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001735 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001736 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
1737 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
1738
1739 /* flag h/w flush complete */
1740 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04001741 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001742}
1743
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001744static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04001745 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001746{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001747 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001748 struct drm_plane_state *state;
1749 struct sde_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001750
Clarence Ip13a8cf42016-09-29 17:27:47 -04001751 if (!plane) {
1752 SDE_ERROR("invalid plane\n");
1753 return;
1754 } else if (!plane->state) {
1755 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04001756 return;
1757 }
1758
Clarence Ip13a8cf42016-09-29 17:27:47 -04001759 psde = to_sde_plane(plane);
1760 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001761 state = plane->state;
1762 pstate = to_sde_plane_state(state);
1763
Clarence Ip13a8cf42016-09-29 17:27:47 -04001764 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001765
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001766 if (!sde_plane_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04001767 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001768 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001769 int ret;
1770
Dhaval Patel47302cf2016-08-18 15:04:28 -07001771 ret = _sde_plane_mode_set(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001772 /* atomic_check should have ensured that this doesn't fail */
1773 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001774 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001775}
1776
Dhaval Patel47302cf2016-08-18 15:04:28 -07001777
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001778/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001779static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001780 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001781{
Clarence Ip5e2a9222016-06-26 22:38:24 -04001782 static const struct drm_prop_enum_list e_blend_op[] = {
1783 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
1784 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
1785 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
1786 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
1787 };
1788 static const struct drm_prop_enum_list e_src_config[] = {
1789 {SDE_DRM_DEINTERLACE, "deinterlace"}
1790 };
Clarence Ipea3d6262016-07-15 16:20:11 -04001791 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07001792 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001793 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04001794 int zpos_max = 255;
1795 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001796 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001797
Clarence Ip13a8cf42016-09-29 17:27:47 -04001798 if (!plane || !psde) {
1799 SDE_ERROR("invalid plane\n");
1800 return;
1801 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
1802 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
1803 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001804 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04001805 } else if (!catalog) {
1806 SDE_ERROR("invalid catalog\n");
1807 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001808 }
1809
Clarence Ipc47a0692016-10-11 10:54:17 -04001810 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04001811 if (catalog->mixer_count && catalog->mixer &&
1812 catalog->mixer[0].sblk->maxblendstages) {
1813 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
1814 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
1815 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
1816 }
Clarence Ipc47a0692016-10-11 10:54:17 -04001817 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
1818 /* reserve zpos == 0 for primary planes */
1819 zpos_def = drm_plane_index(plane) + 1;
1820 }
1821
1822 msm_property_install_range(&psde->property_info, "zpos",
1823 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001824
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001825 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001826 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001827
Dhaval Patel47302cf2016-08-18 15:04:28 -07001828 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001829 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07001830 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001831
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001832 if (!master_plane_id) {
1833 if (psde->pipe_sblk->maxhdeciexp) {
1834 msm_property_install_range(&psde->property_info,
1835 "h_decimate", 0x0, 0,
1836 psde->pipe_sblk->maxhdeciexp, 0,
1837 PLANE_PROP_H_DECIMATE);
1838 }
Clarence Ipdedbba92016-09-27 17:43:10 -04001839
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001840 if (psde->pipe_sblk->maxvdeciexp) {
1841 msm_property_install_range(&psde->property_info,
1842 "v_decimate", 0x0, 0,
1843 psde->pipe_sblk->maxvdeciexp, 0,
1844 PLANE_PROP_V_DECIMATE);
1845 }
Clarence Ipdedbba92016-09-27 17:43:10 -04001846
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001847 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
1848 msm_property_install_volatile_range(
1849 &psde->property_info, "scaler_v2",
1850 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
1851 msm_property_install_blob(&psde->property_info,
1852 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
1853 msm_property_install_blob(&psde->property_info,
1854 "lut_cir", 0,
1855 PLANE_PROP_SCALER_LUT_CIR);
1856 msm_property_install_blob(&psde->property_info,
1857 "lut_sep", 0,
1858 PLANE_PROP_SCALER_LUT_SEP);
1859 } else if (psde->features & SDE_SSPP_SCALER) {
1860 msm_property_install_volatile_range(
1861 &psde->property_info, "scaler_v1", 0x0,
1862 0, ~0, 0, PLANE_PROP_SCALER_V1);
1863 }
Clarence Ipb43d4592016-09-08 14:21:35 -04001864
Dhaval Patel0aee0972017-02-08 19:00:58 -08001865 if (psde->features & BIT(SDE_SSPP_CSC) ||
1866 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001867 msm_property_install_volatile_range(
1868 &psde->property_info, "csc_v1", 0x0,
1869 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001870
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001871 if (psde->features & BIT(SDE_SSPP_HSIC)) {
1872 snprintf(feature_name, sizeof(feature_name), "%s%d",
1873 "SDE_SSPP_HUE_V",
1874 psde->pipe_sblk->hsic_blk.version >> 16);
1875 msm_property_install_range(&psde->property_info,
1876 feature_name, 0, 0, 0xFFFFFFFF, 0,
1877 PLANE_PROP_HUE_ADJUST);
1878 snprintf(feature_name, sizeof(feature_name), "%s%d",
1879 "SDE_SSPP_SATURATION_V",
1880 psde->pipe_sblk->hsic_blk.version >> 16);
1881 msm_property_install_range(&psde->property_info,
1882 feature_name, 0, 0, 0xFFFFFFFF, 0,
1883 PLANE_PROP_SATURATION_ADJUST);
1884 snprintf(feature_name, sizeof(feature_name), "%s%d",
1885 "SDE_SSPP_VALUE_V",
1886 psde->pipe_sblk->hsic_blk.version >> 16);
1887 msm_property_install_range(&psde->property_info,
1888 feature_name, 0, 0, 0xFFFFFFFF, 0,
1889 PLANE_PROP_VALUE_ADJUST);
1890 snprintf(feature_name, sizeof(feature_name), "%s%d",
1891 "SDE_SSPP_CONTRAST_V",
1892 psde->pipe_sblk->hsic_blk.version >> 16);
1893 msm_property_install_range(&psde->property_info,
1894 feature_name, 0, 0, 0xFFFFFFFF, 0,
1895 PLANE_PROP_CONTRAST_ADJUST);
1896 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07001897 }
1898
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001899 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
1900 msm_property_install_volatile_range(&psde->property_info,
1901 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
1902
Clarence Ip5e2a9222016-06-26 22:38:24 -04001903 /* standard properties */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001904 msm_property_install_rotation(&psde->property_info,
Clarence Ip531f5572017-01-24 10:10:05 -08001905 (unsigned int) (DRM_REFLECT_X | DRM_REFLECT_Y),
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001906 PLANE_PROP_ROTATION);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001907
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001908 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001909 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001910
Dhaval Patel47302cf2016-08-18 15:04:28 -07001911 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
1912 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
1913
1914 if (psde->pipe_hw->ops.setup_solidfill)
1915 msm_property_install_range(&psde->property_info, "color_fill",
1916 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
1917
Dhaval Patel4e574842016-08-23 15:11:37 -07001918 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001919 if (!info) {
1920 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07001921 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001922 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001923
1924 msm_property_install_blob(&psde->property_info, "capabilities",
1925 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
1926 sde_kms_info_reset(info);
1927
Clarence Ipea3d6262016-07-15 16:20:11 -04001928 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001929
1930 if (master_plane_id) {
1931 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
1932 master_plane_id);
1933 format_list = plane_formats;
1934 }
1935
Clarence Ipea3d6262016-07-15 16:20:11 -04001936 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04001937 sde_kms_info_start(info, "pixel_formats");
1938 while (format_list->fourcc_format) {
1939 sde_kms_info_append_format(info,
1940 format_list->fourcc_format,
1941 format_list->modifier);
1942 ++format_list;
1943 }
1944 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04001945 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001946
1947 sde_kms_info_add_keyint(info, "max_linewidth",
1948 psde->pipe_sblk->maxlinewidth);
1949 sde_kms_info_add_keyint(info, "max_upscale",
1950 psde->pipe_sblk->maxupscale);
1951 sde_kms_info_add_keyint(info, "max_downscale",
1952 psde->pipe_sblk->maxdwnscale);
1953 sde_kms_info_add_keyint(info, "max_horizontal_deci",
1954 psde->pipe_sblk->maxhdeciexp);
1955 sde_kms_info_add_keyint(info, "max_vertical_deci",
1956 psde->pipe_sblk->maxvdeciexp);
1957 msm_property_set_blob(&psde->property_info, &psde->blob_info,
1958 info->data, info->len, PLANE_PROP_INFO);
1959
1960 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07001961
1962 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
1963 snprintf(feature_name, sizeof(feature_name), "%s%d",
1964 "SDE_SSPP_SKIN_COLOR_V",
1965 psde->pipe_sblk->memcolor_blk.version >> 16);
1966 msm_property_install_blob(&psde->property_info, feature_name, 0,
1967 PLANE_PROP_SKIN_COLOR);
1968 snprintf(feature_name, sizeof(feature_name), "%s%d",
1969 "SDE_SSPP_SKY_COLOR_V",
1970 psde->pipe_sblk->memcolor_blk.version >> 16);
1971 msm_property_install_blob(&psde->property_info, feature_name, 0,
1972 PLANE_PROP_SKY_COLOR);
1973 snprintf(feature_name, sizeof(feature_name), "%s%d",
1974 "SDE_SSPP_FOLIAGE_COLOR_V",
1975 psde->pipe_sblk->memcolor_blk.version >> 16);
1976 msm_property_install_blob(&psde->property_info, feature_name, 0,
1977 PLANE_PROP_FOLIAGE_COLOR);
1978 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001979}
1980
Clarence Ip5fc00c52016-09-23 15:03:34 -04001981static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
1982{
1983 struct sde_drm_csc_v1 csc_v1;
1984 int i;
1985
1986 if (!psde) {
1987 SDE_ERROR("invalid plane\n");
1988 return;
1989 }
1990
1991 psde->csc_usr_ptr = NULL;
1992 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001993 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001994 return;
1995 }
1996
1997 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001998 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001999 return;
2000 }
2001
Clarence Ipb43d4592016-09-08 14:21:35 -04002002 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04002003 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
2004 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
2005 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
2006 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
2007 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
2008 }
2009 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
2010 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
2011 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
2012 }
2013 psde->csc_usr_ptr = &psde->csc_cfg;
2014}
2015
Clarence Ipb43d4592016-09-08 14:21:35 -04002016static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
2017{
2018 struct sde_drm_scaler_v1 scale_v1;
2019 struct sde_hw_pixel_ext *pe;
2020 int i;
2021
2022 if (!psde) {
2023 SDE_ERROR("invalid plane\n");
2024 return;
2025 }
2026
2027 psde->pixel_ext_usr = false;
2028 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002029 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04002030 return;
2031 }
2032
2033 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002034 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04002035 return;
2036 }
2037
2038 /* populate from user space */
2039 pe = &(psde->pixel_ext);
2040 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
2041 for (i = 0; i < SDE_MAX_PLANES; i++) {
2042 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
2043 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
2044 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
2045 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
2046
2047 pe->horz_filter[i] = scale_v1.horz_filter[i];
2048 pe->vert_filter[i] = scale_v1.vert_filter[i];
2049 }
2050 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05002051 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
2052 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
2053 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
2054 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
2055 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04002056
abeykun41060122016-11-28 13:02:01 -05002057 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
2058 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
2059 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
2060 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
2061 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04002062 }
abeykun41060122016-11-28 13:02:01 -05002063
Clarence Ipb43d4592016-09-08 14:21:35 -04002064 psde->pixel_ext_usr = true;
2065
Clarence Ip13a8cf42016-09-29 17:27:47 -04002066 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04002067}
2068
abeykun48f407a2016-08-25 12:06:44 -04002069static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
2070 struct sde_plane_state *pstate, void *usr)
2071{
2072 struct sde_drm_scaler_v2 scale_v2;
2073 struct sde_hw_pixel_ext *pe;
2074 int i;
2075 struct sde_hw_scaler3_cfg *cfg;
2076
2077 if (!psde) {
2078 SDE_ERROR("invalid plane\n");
2079 return;
2080 }
2081
2082 cfg = psde->scaler3_cfg;
2083 psde->pixel_ext_usr = false;
2084 if (!usr) {
2085 SDE_DEBUG_PLANE(psde, "scale data removed\n");
2086 return;
2087 }
2088
2089 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
2090 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
2091 return;
2092 }
2093
2094 /* populate from user space */
2095 pe = &(psde->pixel_ext);
2096 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
2097 cfg->enable = scale_v2.enable;
2098 cfg->dir_en = scale_v2.dir_en;
2099 for (i = 0; i < SDE_MAX_PLANES; i++) {
2100 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
2101 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
2102 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
2103 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
2104
2105 cfg->preload_x[i] = scale_v2.preload_x[i];
2106 cfg->preload_y[i] = scale_v2.preload_y[i];
2107 cfg->src_width[i] = scale_v2.src_width[i];
2108 cfg->src_height[i] = scale_v2.src_height[i];
2109 }
2110 cfg->dst_width = scale_v2.dst_width;
2111 cfg->dst_height = scale_v2.dst_height;
2112
2113 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
2114 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
2115 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
2116 cfg->blend_cfg = scale_v2.blend_cfg;
2117
2118 cfg->lut_flag = scale_v2.lut_flag;
2119 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
2120 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
2121 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
2122 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
2123 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
2124
2125 cfg->de.enable = scale_v2.de.enable;
2126 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
2127 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
2128 cfg->de.clip = scale_v2.de.clip;
2129 cfg->de.limit = scale_v2.de.limit;
2130 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
2131 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
2132 cfg->de.thr_low = scale_v2.de.thr_low;
2133 cfg->de.thr_high = scale_v2.de.thr_high;
2134 cfg->de.prec_shift = scale_v2.de.prec_shift;
2135 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
2136 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
2137 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
2138 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
2139 }
2140 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05002141 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
2142 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
2143 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
2144 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
2145 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04002146
abeykun41060122016-11-28 13:02:01 -05002147 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
2148 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
2149 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
2150 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
2151 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04002152 }
2153 psde->pixel_ext_usr = true;
2154
2155 SDE_DEBUG_PLANE(psde, "user property data copied\n");
2156}
2157
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002158static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
2159 struct sde_plane_state *pstate, void *usr_ptr)
2160{
2161 struct drm_clip_rect excl_rect_v1;
2162
2163 if (!psde) {
2164 SDE_ERROR("invalid plane\n");
2165 return;
2166 }
2167
2168 if (!usr_ptr) {
2169 SDE_DEBUG_PLANE(psde, "excl rect data removed\n");
2170 return;
2171 }
2172
2173 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
2174 SDE_ERROR_PLANE(psde, "failed to copy excl rect data\n");
2175 return;
2176 }
2177
2178 /* populate from user space */
2179 pstate->excl_rect.x = excl_rect_v1.x1;
2180 pstate->excl_rect.y = excl_rect_v1.y1;
2181 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1 + 1;
2182 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1 + 1;
2183}
2184
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002185static int sde_plane_atomic_set_property(struct drm_plane *plane,
2186 struct drm_plane_state *state, struct drm_property *property,
2187 uint64_t val)
2188{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002189 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002190 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04002191 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002192
Clarence Ip13a8cf42016-09-29 17:27:47 -04002193 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002194
2195 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002196 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002197 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002198 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002199 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04002200 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002201 ret = msm_property_atomic_set(&psde->property_info,
2202 pstate->property_values, pstate->property_blobs,
2203 property, val);
2204 if (!ret) {
2205 idx = msm_property_index(&psde->property_info,
2206 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04002207 switch (idx) {
2208 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04002209 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04002210 break;
2211 case PLANE_PROP_CSC_V1:
2212 _sde_plane_set_csc_v1(psde, (void *)val);
2213 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04002214 case PLANE_PROP_SCALER_V1:
2215 _sde_plane_set_scaler_v1(psde, (void *)val);
2216 break;
abeykun48f407a2016-08-25 12:06:44 -04002217 case PLANE_PROP_SCALER_V2:
2218 _sde_plane_set_scaler_v2(psde, pstate,
2219 (void *)val);
2220 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002221 case PLANE_PROP_EXCL_RECT_V1:
2222 _sde_plane_set_excl_rect_v1(psde, pstate,
2223 (void *)val);
2224 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04002225 default:
2226 /* nothing to do */
2227 break;
2228 }
Clarence Ipe78efb72016-06-24 18:35:21 -04002229 }
2230 }
2231
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002232 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002233}
2234
2235static int sde_plane_set_property(struct drm_plane *plane,
2236 struct drm_property *property, uint64_t val)
2237{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002238 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04002239
Clarence Ipae4e60c2016-06-26 22:44:04 -04002240 return sde_plane_atomic_set_property(plane,
2241 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002242}
2243
2244static int sde_plane_atomic_get_property(struct drm_plane *plane,
2245 const struct drm_plane_state *state,
2246 struct drm_property *property, uint64_t *val)
2247{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002248 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002249 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04002250 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002251
Clarence Ipaa0faf42016-05-30 12:07:48 -04002252 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002253 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002254 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002255 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002256 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002257 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04002258 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002259 ret = msm_property_atomic_get(&psde->property_info,
2260 pstate->property_values, pstate->property_blobs,
2261 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04002262 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002263
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002264 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002265}
2266
2267static void sde_plane_destroy(struct drm_plane *plane)
2268{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002269 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002270
Clarence Ip13a8cf42016-09-29 17:27:47 -04002271 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002272
Clarence Ip13a8cf42016-09-29 17:27:47 -04002273 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04002274 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
2275
Dhaval Patel4e574842016-08-23 15:11:37 -07002276 if (psde->blob_info)
2277 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002278 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04002279 mutex_destroy(&psde->lock);
2280
Clarence Ip4ce59322016-06-26 22:27:51 -04002281 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002282
Clarence Ip4ce59322016-06-26 22:27:51 -04002283 /* this will destroy the states as well */
2284 drm_plane_cleanup(plane);
2285
Clarence Ip4c1d9772016-06-26 09:35:38 -04002286 if (psde->pipe_hw)
2287 sde_hw_sspp_destroy(psde->pipe_hw);
2288
Clarence Ip4ce59322016-06-26 22:27:51 -04002289 kfree(psde);
2290 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002291}
2292
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002293static void sde_plane_destroy_state(struct drm_plane *plane,
2294 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002295{
Clarence Ipaa0faf42016-05-30 12:07:48 -04002296 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04002297 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04002298
Clarence Ipae4e60c2016-06-26 22:44:04 -04002299 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002300 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2301 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04002302 return;
2303 }
2304
Clarence Ipaa0faf42016-05-30 12:07:48 -04002305 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04002306 pstate = to_sde_plane_state(state);
2307
Clarence Ip13a8cf42016-09-29 17:27:47 -04002308 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002309
Clarence Ipe78efb72016-06-24 18:35:21 -04002310 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002311 if (state->fb)
2312 drm_framebuffer_unreference(state->fb);
2313
Clarence Ipae4e60c2016-06-26 22:44:04 -04002314 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04002315 if (pstate->input_fence)
2316 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04002317
Clarence Ipaa0faf42016-05-30 12:07:48 -04002318 /* destroy value helper */
2319 msm_property_destroy_state(&psde->property_info, pstate,
2320 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002321}
2322
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002323static struct drm_plane_state *
2324sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002325{
Clarence Ipaa0faf42016-05-30 12:07:48 -04002326 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002327 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04002328 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04002329 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002330
Clarence Ip13a8cf42016-09-29 17:27:47 -04002331 if (!plane) {
2332 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002333 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002334 } else if (!plane->state) {
2335 SDE_ERROR("invalid plane state\n");
2336 return NULL;
2337 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002338
Clarence Ip730e7192016-06-26 22:45:09 -04002339 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002340 psde = to_sde_plane(plane);
2341 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002342 if (!pstate) {
2343 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002344 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002345 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002346
Clarence Ip13a8cf42016-09-29 17:27:47 -04002347 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002348
2349 /* duplicate value helper */
2350 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
2351 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04002352
Clarence Ip730e7192016-06-26 22:45:09 -04002353 /* add ref count for frame buffer */
2354 if (pstate->base.fb)
2355 drm_framebuffer_reference(pstate->base.fb);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002356
Clarence Ip17e908b2016-09-29 15:58:00 -04002357 /* clear out any input fence */
2358 pstate->input_fence = 0;
2359 input_fence_default = msm_property_get_default(
2360 &psde->property_info, PLANE_PROP_INPUT_FENCE);
2361 msm_property_set_property(&psde->property_info, pstate->property_values,
2362 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002363
Clarence Ip282dad62016-09-27 17:07:35 -04002364 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04002365 pstate->pending = false;
2366
2367 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002368}
2369
2370static void sde_plane_reset(struct drm_plane *plane)
2371{
Clarence Ipae4e60c2016-06-26 22:44:04 -04002372 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002373 struct sde_plane_state *pstate;
2374
Clarence Ipae4e60c2016-06-26 22:44:04 -04002375 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002376 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04002377 return;
2378 }
2379
Clarence Ip730e7192016-06-26 22:45:09 -04002380 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002381 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002382
Clarence Ipae4e60c2016-06-26 22:44:04 -04002383 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04002384 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04002385 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002386 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04002387 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002388
Clarence Ipaa0faf42016-05-30 12:07:48 -04002389 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002390 if (!pstate) {
2391 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002392 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002393 }
Clarence Ip730e7192016-06-26 22:45:09 -04002394
Clarence Ipaa0faf42016-05-30 12:07:48 -04002395 /* reset value helper */
2396 msm_property_reset_state(&psde->property_info, pstate,
2397 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002398
2399 pstate->base.plane = plane;
2400
2401 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002402}
2403
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002404#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04002405static ssize_t _sde_plane_danger_read(struct file *file,
2406 char __user *buff, size_t count, loff_t *ppos)
2407{
2408 struct sde_kms *kms = file->private_data;
2409 struct sde_mdss_cfg *cfg = kms->catalog;
2410 int len = 0;
2411 char buf[40] = {'\0'};
2412
2413 if (!cfg)
2414 return -ENODEV;
2415
2416 if (*ppos)
2417 return 0; /* the end */
2418
2419 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
2420 if (len < 0 || len >= sizeof(buf))
2421 return 0;
2422
2423 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
2424 return -EFAULT;
2425
2426 *ppos += len; /* increase offset */
2427
2428 return len;
2429}
2430
2431static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
2432{
2433 struct drm_plane *plane;
2434
2435 drm_for_each_plane(plane, kms->dev) {
2436 if (plane->fb && plane->state) {
2437 sde_plane_danger_signal_ctrl(plane, enable);
2438 SDE_DEBUG("plane:%d img:%dx%d ",
2439 plane->base.id, plane->fb->width,
2440 plane->fb->height);
2441 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
2442 plane->state->src_x >> 16,
2443 plane->state->src_y >> 16,
2444 plane->state->src_w >> 16,
2445 plane->state->src_h >> 16,
2446 plane->state->crtc_x, plane->state->crtc_y,
2447 plane->state->crtc_w, plane->state->crtc_h);
2448 } else {
2449 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
2450 }
2451 }
2452}
2453
2454static ssize_t _sde_plane_danger_write(struct file *file,
2455 const char __user *user_buf, size_t count, loff_t *ppos)
2456{
2457 struct sde_kms *kms = file->private_data;
2458 struct sde_mdss_cfg *cfg = kms->catalog;
2459 int disable_panic;
2460 char buf[10];
2461
2462 if (!cfg)
2463 return -EFAULT;
2464
2465 if (count >= sizeof(buf))
2466 return -EFAULT;
2467
2468 if (copy_from_user(buf, user_buf, count))
2469 return -EFAULT;
2470
2471 buf[count] = 0; /* end of string */
2472
2473 if (kstrtoint(buf, 0, &disable_panic))
2474 return -EFAULT;
2475
2476 if (disable_panic) {
2477 /* Disable panic signal for all active pipes */
2478 SDE_DEBUG("Disabling danger:\n");
2479 _sde_plane_set_danger_state(kms, false);
2480 kms->has_danger_ctrl = false;
2481 } else {
2482 /* Enable panic signal for all active pipes */
2483 SDE_DEBUG("Enabling danger:\n");
2484 kms->has_danger_ctrl = true;
2485 _sde_plane_set_danger_state(kms, true);
2486 }
2487
2488 return count;
2489}
2490
2491static const struct file_operations sde_plane_danger_enable = {
2492 .open = simple_open,
2493 .read = _sde_plane_danger_read,
2494 .write = _sde_plane_danger_write,
2495};
2496
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002497static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04002498{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002499 struct sde_plane *psde;
2500 struct sde_kms *kms;
2501 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04002502 const struct sde_sspp_sub_blks *sblk = 0;
2503 const struct sde_sspp_cfg *cfg = 0;
2504
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002505 if (!plane || !plane->dev) {
2506 SDE_ERROR("invalid arguments\n");
2507 return -EINVAL;
2508 }
2509
2510 priv = plane->dev->dev_private;
2511 if (!priv || !priv->kms) {
2512 SDE_ERROR("invalid KMS reference\n");
2513 return -EINVAL;
2514 }
2515
2516 kms = to_sde_kms(priv->kms);
2517 psde = to_sde_plane(plane);
2518
Clarence Ip4ce59322016-06-26 22:27:51 -04002519 if (psde && psde->pipe_hw)
2520 cfg = psde->pipe_hw->cap;
2521 if (cfg)
2522 sblk = cfg->sblk;
2523
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002524 if (!sblk)
2525 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04002526
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002527 /* create overall sub-directory for the pipe */
2528 psde->debugfs_root =
2529 debugfs_create_dir(psde->pipe_name,
2530 sde_debugfs_get_root(kms));
Clarence Ip4ce59322016-06-26 22:27:51 -04002531
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002532 if (!psde->debugfs_root)
2533 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04002534
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002535 /* don't error check these */
2536 debugfs_create_x32("features", 0644,
2537 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04002538
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002539 /* add register dump support */
2540 sde_debugfs_setup_regset32(&psde->debugfs_src,
2541 sblk->src_blk.base + cfg->base,
2542 sblk->src_blk.len,
2543 kms);
2544 sde_debugfs_create_regset32("src_blk", 0444,
2545 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04002546
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002547 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
2548 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
2549 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
2550 sblk->scaler_blk.base + cfg->base,
2551 sblk->scaler_blk.len,
2552 kms);
2553 sde_debugfs_create_regset32("scaler_blk", 0444,
2554 psde->debugfs_root,
2555 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07002556 debugfs_create_bool("default_scaling",
2557 0644,
2558 psde->debugfs_root,
2559 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04002560 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002561
2562 if (cfg->features & BIT(SDE_SSPP_CSC) ||
2563 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
2564 sde_debugfs_setup_regset32(&psde->debugfs_csc,
2565 sblk->csc_blk.base + cfg->base,
2566 sblk->csc_blk.len,
2567 kms);
2568 sde_debugfs_create_regset32("csc_blk", 0444,
2569 psde->debugfs_root, &psde->debugfs_csc);
2570 }
2571
2572 debugfs_create_u32("xin_id",
2573 0444,
2574 psde->debugfs_root,
2575 (u32 *) &cfg->xin_id);
2576 debugfs_create_u32("clk_ctrl",
2577 0444,
2578 psde->debugfs_root,
2579 (u32 *) &cfg->clk_ctrl);
2580 debugfs_create_x32("creq_vblank",
2581 0644,
2582 psde->debugfs_root,
2583 (u32 *) &sblk->creq_vblank);
2584 debugfs_create_x32("danger_vblank",
2585 0644,
2586 psde->debugfs_root,
2587 (u32 *) &sblk->danger_vblank);
2588
2589 debugfs_create_file("disable_danger",
2590 0644,
2591 psde->debugfs_root,
2592 kms, &sde_plane_danger_enable);
2593
2594 return 0;
2595}
2596
2597static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
2598{
2599 struct sde_plane *psde;
2600
2601 if (!plane)
2602 return;
2603 psde = to_sde_plane(plane);
2604
2605 debugfs_remove_recursive(psde->debugfs_root);
2606}
2607#else
2608static int _sde_plane_init_debugfs(struct drm_plane *plane)
2609{
2610 return 0;
2611}
2612static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
2613{
2614}
2615#endif
2616
2617static int sde_plane_late_register(struct drm_plane *plane)
2618{
2619 return _sde_plane_init_debugfs(plane);
2620}
2621
2622static void sde_plane_early_unregister(struct drm_plane *plane)
2623{
2624 _sde_plane_destroy_debugfs(plane);
2625}
2626
2627static const struct drm_plane_funcs sde_plane_funcs = {
2628 .update_plane = drm_atomic_helper_update_plane,
2629 .disable_plane = drm_atomic_helper_disable_plane,
2630 .destroy = sde_plane_destroy,
2631 .set_property = sde_plane_set_property,
2632 .atomic_set_property = sde_plane_atomic_set_property,
2633 .atomic_get_property = sde_plane_atomic_get_property,
2634 .reset = sde_plane_reset,
2635 .atomic_duplicate_state = sde_plane_duplicate_state,
2636 .atomic_destroy_state = sde_plane_destroy_state,
2637 .late_register = sde_plane_late_register,
2638 .early_unregister = sde_plane_early_unregister,
2639};
2640
2641static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
2642 .prepare_fb = sde_plane_prepare_fb,
2643 .cleanup_fb = sde_plane_cleanup_fb,
2644 .atomic_check = sde_plane_atomic_check,
2645 .atomic_update = sde_plane_atomic_update,
2646};
2647
2648enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
2649{
2650 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
2651}
2652
2653bool is_sde_plane_virtual(struct drm_plane *plane)
2654{
2655 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04002656}
2657
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002658/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04002659struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002660 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002661 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002662{
2663 struct drm_plane *plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002664 const struct sde_format_extended *format_list;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002665 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002666 struct msm_drm_private *priv;
2667 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002668 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04002669 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002670
2671 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002672 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002673 goto exit;
2674 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002675
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002676 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04002677 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002678 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002679 goto exit;
2680 }
2681
2682 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002683 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002684 goto exit;
2685 }
2686 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002687
Clarence Ip4c1d9772016-06-26 09:35:38 -04002688 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002689 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002690 goto exit;
2691 }
2692
Clarence Ip4ce59322016-06-26 22:27:51 -04002693 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002694 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
2695 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002696 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002697 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002698 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002699 }
2700
Clarence Ip4c1d9772016-06-26 09:35:38 -04002701 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002702 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002703 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04002704 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002705 psde->is_virtual = (master_plane_id != 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002706
Clarence Ip4c1d9772016-06-26 09:35:38 -04002707 /* initialize underlying h/w driver */
2708 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
2709 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002710 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002711 ret = PTR_ERR(psde->pipe_hw);
2712 goto clean_plane;
2713 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002714 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002715 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002716 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002717
2718 /* cache features mask for later */
2719 psde->features = psde->pipe_hw->cap->features;
2720 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04002721 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002722 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04002723 goto clean_sspp;
2724 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002725
abeykun48f407a2016-08-25 12:06:44 -04002726 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
2727 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
2728 GFP_KERNEL);
2729 if (!psde->scaler3_cfg) {
2730 SDE_ERROR("[%u]failed to allocate scale struct\n",
2731 pipe);
2732 ret = -ENOMEM;
2733 goto clean_sspp;
2734 }
2735 }
2736
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002737 format_list = psde->pipe_sblk->format_list;
2738
2739 if (master_plane_id)
2740 format_list = plane_formats;
2741
2742 psde->nformats = sde_populate_formats(plane_formats,
2743 psde->formats,
2744 0,
2745 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002746
Clarence Ip4c1d9772016-06-26 09:35:38 -04002747 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002748 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002749 goto clean_sspp;
2750 }
2751
2752 if (psde->features & BIT(SDE_SSPP_CURSOR))
2753 type = DRM_PLANE_TYPE_CURSOR;
2754 else if (primary_plane)
2755 type = DRM_PLANE_TYPE_PRIMARY;
2756 else
2757 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002758 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
2759 psde->formats, psde->nformats,
2760 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002761 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04002762 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002763
Clarence Ip4c1d9772016-06-26 09:35:38 -04002764 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002765 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002766
Clarence Ipaa0faf42016-05-30 12:07:48 -04002767 msm_property_init(&psde->property_info, &plane->base, dev,
2768 priv->plane_property, psde->property_data,
2769 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
2770 sizeof(struct sde_plane_state));
2771
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002772 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002773
Clarence Ip4ce59322016-06-26 22:27:51 -04002774 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04002775 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04002776
Clarence Ip730e7192016-06-26 22:45:09 -04002777 mutex_init(&psde->lock);
2778
Dhaval Patel82c8dbc2017-02-18 23:15:10 -08002779 SDE_DEBUG("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002780 return plane;
2781
Clarence Ip4c1d9772016-06-26 09:35:38 -04002782clean_sspp:
2783 if (psde && psde->pipe_hw)
2784 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04002785
2786 if (psde && psde->scaler3_cfg)
2787 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002788clean_plane:
2789 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04002790exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002791 return ERR_PTR(ret);
2792}