blob: 908926c813bcbf040768d78fbebddf5936ef82c3 [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;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700139};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700140
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700141#define to_sde_plane(x) container_of(x, struct sde_plane, base)
142
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400143static bool sde_plane_enabled(struct drm_plane_state *state)
144{
Clarence Ipdbde9832016-06-26 09:48:36 -0400145 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400146}
147
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400148/**
149 * _sde_plane_calc_fill_level - calculate fill level of the given source format
150 * @plane: Pointer to drm plane
151 * @fmt: Pointer to source buffer format
152 * @src_wdith: width of source buffer
153 * Return: fill level corresponding to the source buffer/format or 0 if error
154 */
155static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
156 const struct sde_format *fmt, u32 src_width)
157{
158 struct sde_plane *psde;
159 u32 fixed_buff_size;
160 u32 total_fl;
161
162 if (!plane || !fmt) {
163 SDE_ERROR("invalid arguments\n");
164 return 0;
165 }
166
167 psde = to_sde_plane(plane);
168 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
169
170 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
171 if (fmt->chroma_sample == SDE_CHROMA_420) {
172 /* NV12 */
173 total_fl = (fixed_buff_size / 2) /
174 ((src_width + 32) * fmt->bpp);
175 } else {
176 /* non NV12 */
177 total_fl = (fixed_buff_size) /
178 ((src_width + 32) * fmt->bpp);
179 }
180 } else {
181 total_fl = (fixed_buff_size * 2) /
182 ((src_width + 32) * fmt->bpp);
183 }
184
185 SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n",
186 plane->base.id, psde->pipe - SSPP_VIG0,
187 fmt->base.pixel_format, src_width, total_fl);
188
189 return total_fl;
190}
191
192/**
193 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
194 * @total_fl: fill level
195 * Return: LUT setting corresponding to the fill level
196 */
197static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
198{
199 u32 qos_lut;
200
201 if (total_fl <= 4)
202 qos_lut = 0x1B;
203 else if (total_fl <= 5)
204 qos_lut = 0x5B;
205 else if (total_fl <= 6)
206 qos_lut = 0x15B;
207 else if (total_fl <= 7)
208 qos_lut = 0x55B;
209 else if (total_fl <= 8)
210 qos_lut = 0x155B;
211 else if (total_fl <= 9)
212 qos_lut = 0x555B;
213 else if (total_fl <= 10)
214 qos_lut = 0x1555B;
215 else if (total_fl <= 11)
216 qos_lut = 0x5555B;
217 else if (total_fl <= 12)
218 qos_lut = 0x15555B;
219 else
220 qos_lut = 0x55555B;
221
222 return qos_lut;
223}
224
225/**
226 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
227 * @total_fl: fill level
228 * Return: LUT setting corresponding to the fill level
229 */
230static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
231{
232 u32 qos_lut;
233
234 if (total_fl <= 10)
235 qos_lut = 0x1AAff;
236 else if (total_fl <= 11)
237 qos_lut = 0x5AAFF;
238 else if (total_fl <= 12)
239 qos_lut = 0x15AAFF;
240 else
241 qos_lut = 0x55AAFF;
242
243 return qos_lut;
244}
245
246/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400247 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
248 * @plane: Pointer to drm plane
249 * @fb: Pointer to framebuffer associated with the given plane
250 */
251static void _sde_plane_set_qos_lut(struct drm_plane *plane,
252 struct drm_framebuffer *fb)
253{
254 struct sde_plane *psde;
255 const struct sde_format *fmt = NULL;
256 u32 qos_lut;
257 u32 total_fl = 0;
258
259 if (!plane || !fb) {
260 SDE_ERROR("invalid arguments plane %d fb %d\n",
261 plane != 0, fb != 0);
262 return;
263 }
264
265 psde = to_sde_plane(plane);
266
267 if (!psde->pipe_hw || !psde->pipe_sblk) {
268 SDE_ERROR("invalid arguments\n");
269 return;
270 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
271 return;
272 }
273
274 if (!psde->is_rt_pipe) {
275 qos_lut = psde->pipe_sblk->creq_lut_nrt;
276 } else {
277 fmt = sde_get_sde_format_ext(
278 fb->pixel_format,
279 fb->modifier,
280 drm_format_num_planes(fb->pixel_format));
281 total_fl = _sde_plane_calc_fill_level(plane, fmt,
282 psde->pipe_cfg.src_rect.w);
283
284 if (SDE_FORMAT_IS_LINEAR(fmt))
285 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
286 else
287 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
288 }
289
290 psde->pipe_qos_cfg.creq_lut = qos_lut;
291
292 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
293 (fmt) ? fmt->base.pixel_format : 0,
294 psde->is_rt_pipe, total_fl, qos_lut,
295 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
296
297 SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n",
298 plane->base.id,
299 psde->pipe - SSPP_VIG0,
300 (fmt) ? fmt->base.pixel_format : 0,
301 psde->is_rt_pipe, total_fl, qos_lut);
302
303 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
304}
305
306/**
307 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
308 * @plane: Pointer to drm plane
309 * @fb: Pointer to framebuffer associated with the given plane
310 */
311static void _sde_plane_set_danger_lut(struct drm_plane *plane,
312 struct drm_framebuffer *fb)
313{
314 struct sde_plane *psde;
315 const struct sde_format *fmt = NULL;
316 u32 danger_lut, safe_lut;
317
318 if (!plane || !fb) {
319 SDE_ERROR("invalid arguments\n");
320 return;
321 }
322
323 psde = to_sde_plane(plane);
324
325 if (!psde->pipe_hw || !psde->pipe_sblk) {
326 SDE_ERROR("invalid arguments\n");
327 return;
328 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
329 return;
330 }
331
332 if (!psde->is_rt_pipe) {
333 danger_lut = psde->pipe_sblk->danger_lut_nrt;
334 safe_lut = psde->pipe_sblk->safe_lut_nrt;
335 } else {
336 fmt = sde_get_sde_format_ext(
337 fb->pixel_format,
338 fb->modifier,
339 drm_format_num_planes(fb->pixel_format));
340
341 if (SDE_FORMAT_IS_LINEAR(fmt)) {
342 danger_lut = psde->pipe_sblk->danger_lut_linear;
343 safe_lut = psde->pipe_sblk->safe_lut_linear;
344 } else {
345 danger_lut = psde->pipe_sblk->danger_lut_tile;
346 safe_lut = psde->pipe_sblk->safe_lut_tile;
347 }
348 }
349
350 psde->pipe_qos_cfg.danger_lut = danger_lut;
351 psde->pipe_qos_cfg.safe_lut = safe_lut;
352
353 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
354 (fmt) ? fmt->base.pixel_format : 0,
355 (fmt) ? fmt->fetch_mode : 0,
356 psde->pipe_qos_cfg.danger_lut,
357 psde->pipe_qos_cfg.safe_lut);
358
359 SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n",
360 plane->base.id,
361 psde->pipe - SSPP_VIG0,
362 fmt ? fmt->base.pixel_format : 0,
363 fmt ? fmt->fetch_mode : -1,
364 psde->pipe_qos_cfg.danger_lut,
365 psde->pipe_qos_cfg.safe_lut);
366
367 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
368 &psde->pipe_qos_cfg);
369}
370
371/**
372 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
373 * @plane: Pointer to drm plane
374 * @enable: true to enable QoS control
375 * @flags: QoS control mode (enum sde_plane_qos)
376 */
377static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
378 bool enable, u32 flags)
379{
380 struct sde_plane *psde;
381
382 if (!plane) {
383 SDE_ERROR("invalid arguments\n");
384 return;
385 }
386
387 psde = to_sde_plane(plane);
388
389 if (!psde->pipe_hw || !psde->pipe_sblk) {
390 SDE_ERROR("invalid arguments\n");
391 return;
392 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
393 return;
394 }
395
396 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
397 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
398 psde->pipe_qos_cfg.danger_vblank =
399 psde->pipe_sblk->danger_vblank;
400 psde->pipe_qos_cfg.vblank_en = enable;
401 }
402
403 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
404 /* this feature overrules previous VBLANK_CTRL */
405 psde->pipe_qos_cfg.vblank_en = false;
406 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
407 }
408
409 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
410 psde->pipe_qos_cfg.danger_safe_en = enable;
411
412 if (!psde->is_rt_pipe) {
413 psde->pipe_qos_cfg.vblank_en = false;
414 psde->pipe_qos_cfg.danger_safe_en = false;
415 }
416
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400417 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 -0400418 plane->base.id,
419 psde->pipe - SSPP_VIG0,
420 psde->pipe_qos_cfg.danger_safe_en,
421 psde->pipe_qos_cfg.vblank_en,
422 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400423 psde->pipe_qos_cfg.danger_vblank,
424 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400425
426 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
427 &psde->pipe_qos_cfg);
428}
429
Alan Kwongf0fd8512016-10-24 21:39:26 -0400430int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
431{
432 struct sde_plane *psde;
433 struct msm_drm_private *priv;
434 struct sde_kms *sde_kms;
435
436 if (!plane || !plane->dev) {
437 SDE_ERROR("invalid arguments\n");
438 return -EINVAL;
439 }
440
441 priv = plane->dev->dev_private;
442 if (!priv || !priv->kms) {
443 SDE_ERROR("invalid KMS reference\n");
444 return -EINVAL;
445 }
446
447 sde_kms = to_sde_kms(priv->kms);
448 psde = to_sde_plane(plane);
449
450 if (!psde->is_rt_pipe)
451 goto end;
452
453 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
454
455 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
456
457 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
458
459end:
460 return 0;
461}
462
Alan Kwong5d324e42016-07-28 22:56:18 -0400463/**
464 * _sde_plane_set_ot_limit - set OT limit for the given plane
465 * @plane: Pointer to drm plane
466 * @crtc: Pointer to drm crtc
467 */
468static void _sde_plane_set_ot_limit(struct drm_plane *plane,
469 struct drm_crtc *crtc)
470{
471 struct sde_plane *psde;
472 struct sde_vbif_set_ot_params ot_params;
473 struct msm_drm_private *priv;
474 struct sde_kms *sde_kms;
475
476 if (!plane || !plane->dev || !crtc) {
477 SDE_ERROR("invalid arguments plane %d crtc %d\n",
478 plane != 0, crtc != 0);
479 return;
480 }
481
482 priv = plane->dev->dev_private;
483 if (!priv || !priv->kms) {
484 SDE_ERROR("invalid KMS reference\n");
485 return;
486 }
487
488 sde_kms = to_sde_kms(priv->kms);
489 psde = to_sde_plane(plane);
490 if (!psde->pipe_hw) {
491 SDE_ERROR("invalid pipe reference\n");
492 return;
493 }
494
495 memset(&ot_params, 0, sizeof(ot_params));
496 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
497 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
498 ot_params.width = psde->pipe_cfg.src_rect.w;
499 ot_params.height = psde->pipe_cfg.src_rect.h;
500 ot_params.is_wfd = !psde->is_rt_pipe;
501 ot_params.frame_rate = crtc->mode.vrefresh;
502 ot_params.vbif_idx = VBIF_RT;
503 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
504 ot_params.rd = true;
505
506 sde_vbif_set_ot_limit(sde_kms, &ot_params);
507}
508
Clarence Ipcae1bb62016-07-07 12:07:13 -0400509/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400510static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400511 struct sde_plane_state *pstate, uint64_t fd)
512{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400513 if (!psde || !pstate) {
514 SDE_ERROR("invalid arg(s), plane %d state %d\n",
515 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400516 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400517 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400518
519 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400520 if (pstate->input_fence)
521 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400522
523 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400524 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400525
Clarence Ip13a8cf42016-09-29 17:27:47 -0400526 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400527}
528
Clarence Ipcae1bb62016-07-07 12:07:13 -0400529int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400530{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400531 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400532 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400533 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400534 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400535 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800536 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400537
538 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700539 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400540 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400541 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400542 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400543 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400544 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400545 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400546
Clarence Ipcae1bb62016-07-07 12:07:13 -0400547 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800548 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400549 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800550 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400551
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400552 SDE_EVT32(DRMID(plane), -ret, prefix);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400553
Dhaval Patel39323d42017-03-01 23:48:24 -0800554 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400555 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400556 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
557 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400558 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800559 ret = -ETIMEDOUT;
560 break;
561 case -ERESTARTSYS:
562 SDE_ERROR_PLANE(psde,
563 "%ums wait interrupted on %08X\n",
564 wait_ms, prefix);
565 psde->is_error = true;
566 ret = -ERESTARTSYS;
567 break;
568 case -EINVAL:
569 SDE_ERROR_PLANE(psde,
570 "invalid fence param for %08X\n",
571 prefix);
572 psde->is_error = true;
573 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400574 break;
575 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800576 SDE_DEBUG_PLANE(psde, "signaled\n");
577 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400578 break;
579 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400580 } else {
581 ret = 0;
582 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400583 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400584 return ret;
585}
586
Clarence Ip282dad62016-09-27 17:07:35 -0400587static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400588 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400589 struct sde_hw_pipe_cfg *pipe_cfg,
590 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400591{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400592 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400593 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400594
Clarence Ip13a8cf42016-09-29 17:27:47 -0400595 if (!plane || !pstate || !pipe_cfg || !fb) {
596 SDE_ERROR(
597 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
598 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400599 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400600 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400601
602 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400603 if (!psde->pipe_hw) {
604 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400605 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400606 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400607
Clarence Ipb6eb2362016-09-08 16:18:13 -0400608 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
609 if (ret == -EAGAIN)
610 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
611 else if (ret)
612 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
613 else if (psde->pipe_hw->ops.setup_sourceaddress)
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800614 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
615 pstate->multirect_index);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400616}
617
abeykun48f407a2016-08-25 12:06:44 -0400618static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
619 struct sde_plane_state *pstate)
620{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500621 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400622 int ret = 0;
623
Clarence Ip3bf8d872017-02-16 15:25:38 -0500624 if (!psde || !psde->scaler3_cfg) {
625 SDE_ERROR("invalid args\n");
626 return -EINVAL;
627 } else if (!pstate) {
628 /* pstate is expected to be null on forced color fill */
629 SDE_DEBUG("null pstate\n");
630 return -EINVAL;
631 }
632
633 cfg = psde->scaler3_cfg;
634
abeykun48f407a2016-08-25 12:06:44 -0400635 cfg->dir_lut = msm_property_get_blob(
636 &psde->property_info,
637 pstate->property_blobs, &cfg->dir_len,
638 PLANE_PROP_SCALER_LUT_ED);
639 cfg->cir_lut = msm_property_get_blob(
640 &psde->property_info,
641 pstate->property_blobs, &cfg->cir_len,
642 PLANE_PROP_SCALER_LUT_CIR);
643 cfg->sep_lut = msm_property_get_blob(
644 &psde->property_info,
645 pstate->property_blobs, &cfg->sep_len,
646 PLANE_PROP_SCALER_LUT_SEP);
647 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
648 ret = -ENODATA;
649 return ret;
650}
651
Clarence Ipcb410d42016-06-26 22:52:33 -0400652static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400653 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
654 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400655 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400656 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
657{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700658 uint32_t decimated, i;
659
660 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
661 !chroma_subsmpl_v) {
662 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
663 , psde, scale_cfg, fmt, chroma_subsmpl_h,
664 chroma_subsmpl_v);
665 return;
666 }
667
668 memset(scale_cfg, 0, sizeof(*scale_cfg));
669
670 decimated = DECIMATED_DIMENSION(src_w,
671 psde->pipe_cfg.horz_decimation);
672 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
673 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
674 decimated = DECIMATED_DIMENSION(src_h,
675 psde->pipe_cfg.vert_decimation);
676 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
677 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
678
679
680 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
681 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
682 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
683 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
684
685 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
686 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
687 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
688 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
689
690 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
691 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
692 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
693 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
694
695 for (i = 0; i < SDE_MAX_PLANES; i++) {
696 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
697 psde->pipe_cfg.horz_decimation);
698 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
699 psde->pipe_cfg.vert_decimation);
700 if (SDE_FORMAT_IS_YUV(fmt))
701 scale_cfg->src_width[i] &= ~0x1;
702 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
703 scale_cfg->src_width[i] /= chroma_subsmpl_h;
704 scale_cfg->src_height[i] /= chroma_subsmpl_v;
705 }
706 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
707 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
708 psde->pixel_ext.num_ext_pxls_top[i] =
709 scale_cfg->src_height[i];
710 psde->pixel_ext.num_ext_pxls_left[i] =
711 scale_cfg->src_width[i];
712 }
713 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
714 && (src_w == dst_w))
715 return;
716
717 scale_cfg->dst_width = dst_w;
718 scale_cfg->dst_height = dst_h;
719 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
720 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
721 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
722 scale_cfg->lut_flag = 0;
723 scale_cfg->blend_cfg = 1;
724 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -0400725}
726
Clarence Ipcb410d42016-06-26 22:52:33 -0400727/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400728 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400729 * @psde: Pointer to SDE plane object
730 * @src: Source size
731 * @dst: Destination size
732 * @phase_steps: Pointer to output array for phase steps
733 * @filter: Pointer to output array for filter type
734 * @fmt: Pointer to format definition
735 * @chroma_subsampling: Subsampling amount for chroma channel
736 *
737 * Returns: 0 on success
738 */
739static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400740 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400741 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400742 uint32_t chroma_subsampling)
743{
Clarence Ipcb410d42016-06-26 22:52:33 -0400744 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400745 SDE_ERROR(
746 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
747 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400748 return -EINVAL;
749 }
750
Clarence Ip4c1d9772016-06-26 09:35:38 -0400751 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400752 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400753 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400754 phase_steps[SDE_SSPP_COMP_1_2] =
755 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
756 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
757 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400758
759 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400760 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400761 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400762 (src <= dst) ? SDE_SCALE_FILTER_BIL :
763 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400764
Clarence Ipdbde9832016-06-26 09:48:36 -0400765 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400766 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400767 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
768 } else {
769 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
770 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400771 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400772 }
773 } else {
774 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400775 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
776 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
777 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400778 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400779 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400780}
781
Clarence Ipcb410d42016-06-26 22:52:33 -0400782/**
783 * _sde_plane_setup_pixel_ext - determine default pixel extension values
784 * @psde: Pointer to SDE plane object
785 * @src: Source size
786 * @dst: Destination size
787 * @decimated_src: Source size after decimation, if any
788 * @phase_steps: Pointer to output array for phase steps
789 * @out_src: Output array for pixel extension values
790 * @out_edge1: Output array for pixel extension first edge
791 * @out_edge2: Output array for pixel extension second edge
792 * @filter: Pointer to array for filter type
793 * @fmt: Pointer to format definition
794 * @chroma_subsampling: Subsampling amount for chroma channel
795 * @post_compare: Whether to chroma subsampled source size for comparisions
796 */
797static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400798 uint32_t src, uint32_t dst, uint32_t decimated_src,
799 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400800 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400801 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400802 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400803{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400804 int64_t edge1, edge2, caf;
805 uint32_t src_work;
806 int i, tmp;
807
Clarence Ipcb410d42016-06-26 22:52:33 -0400808 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400809 out_edge2 && filter && fmt) {
810 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400811 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400812 caf = PHASE_STEP_UNIT_SCALE;
813 else
814 caf = 0;
815
816 for (i = 0; i < SDE_MAX_PLANES; i++) {
817 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400818 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400819 src_work /= chroma_subsampling;
820 if (post_compare)
821 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400822 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400823 /* unity */
824 edge1 = 0;
825 edge2 = 0;
826 } else if (dst >= src) {
827 /* upscale */
828 edge1 = (1 << PHASE_RESIDUAL);
829 edge1 -= caf;
830 edge2 = (1 << PHASE_RESIDUAL);
831 edge2 += (dst - 1) * *(phase_steps + i);
832 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
833 edge2 += caf;
834 edge2 = -(edge2);
835 } else {
836 /* downscale */
837 edge1 = 0;
838 edge2 = (dst - 1) * *(phase_steps + i);
839 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
840 edge2 += *(phase_steps + i);
841 edge2 = -(edge2);
842 }
843
844 /* only enable CAF for luma plane */
845 caf = 0;
846
847 /* populate output arrays */
848 *(out_src + i) = src_work;
849
850 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400851 if (edge1 >= 0) {
852 tmp = (uint32_t)edge1;
853 tmp >>= PHASE_STEP_SHIFT;
854 *(out_edge1 + i) = -tmp;
855 } else {
856 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400857 *(out_edge1 + i) =
858 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
859 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400860 }
861 if (edge2 >= 0) {
862 tmp = (uint32_t)edge2;
863 tmp >>= PHASE_STEP_SHIFT;
864 *(out_edge2 + i) = -tmp;
865 } else {
866 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400867 *(out_edge2 + i) =
868 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
869 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400870 }
871 }
872 }
873}
874
Clarence Ip5fc00c52016-09-23 15:03:34 -0400875static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400876{
877 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
878 {
Clarence Ip373f8592016-05-26 00:58:42 -0400879 /* S15.16 format */
880 0x00012A00, 0x00000000, 0x00019880,
881 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
882 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400883 },
Clarence Ip373f8592016-05-26 00:58:42 -0400884 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400885 { 0xfff0, 0xff80, 0xff80,},
886 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400887 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400888 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400889 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400890 };
abeykun1c312f62016-08-26 09:47:12 -0400891 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
892 {
893 /* S15.16 format */
894 0x00012A00, 0x00000000, 0x00019880,
895 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
896 0x00012A00, 0x00020480, 0x00000000,
897 },
898 /* signed bias */
899 { 0xffc0, 0xfe00, 0xfe00,},
900 { 0x0, 0x0, 0x0,},
901 /* unsigned clamp */
902 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
903 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
904 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400905
Clarence Ip5fc00c52016-09-23 15:03:34 -0400906 if (!psde) {
907 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400908 return;
909 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400910
Clarence Ipcae1bb62016-07-07 12:07:13 -0400911 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400912 if (psde->csc_usr_ptr)
913 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400914 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
915 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400916 else
Clarence Ip373f8592016-05-26 00:58:42 -0400917 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400918
Clarence Ip13a8cf42016-09-29 17:27:47 -0400919 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400920 psde->csc_ptr->csc_mv[0],
921 psde->csc_ptr->csc_mv[1],
922 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400923}
924
Benet Clarkeb1b4462016-06-27 14:43:06 -0700925static void sde_color_process_plane_setup(struct drm_plane *plane)
926{
927 struct sde_plane *psde;
928 struct sde_plane_state *pstate;
929 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -0700930 struct drm_msm_memcol *memcol = NULL;
931 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -0700932
933 psde = to_sde_plane(plane);
934 pstate = to_sde_plane_state(plane->state);
935
936 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
937 if (psde->pipe_hw->ops.setup_pa_hue)
938 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
939 saturation = (uint32_t) sde_plane_get_property(pstate,
940 PLANE_PROP_SATURATION_ADJUST);
941 if (psde->pipe_hw->ops.setup_pa_sat)
942 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
943 value = (uint32_t) sde_plane_get_property(pstate,
944 PLANE_PROP_VALUE_ADJUST);
945 if (psde->pipe_hw->ops.setup_pa_val)
946 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
947 contrast = (uint32_t) sde_plane_get_property(pstate,
948 PLANE_PROP_CONTRAST_ADJUST);
949 if (psde->pipe_hw->ops.setup_pa_cont)
950 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -0700951
Benet Clarkd009b1d2016-06-27 14:45:59 -0700952 if (psde->pipe_hw->ops.setup_pa_memcolor) {
953 /* Skin memory color setup */
954 memcol = msm_property_get_blob(&psde->property_info,
955 pstate->property_blobs,
956 &memcol_sz,
957 PLANE_PROP_SKIN_COLOR);
958 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
959 MEMCOLOR_SKIN, memcol);
960
961 /* Sky memory color setup */
962 memcol = msm_property_get_blob(&psde->property_info,
963 pstate->property_blobs,
964 &memcol_sz,
965 PLANE_PROP_SKY_COLOR);
966 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
967 MEMCOLOR_SKY, memcol);
968
969 /* Foliage memory color setup */
970 memcol = msm_property_get_blob(&psde->property_info,
971 pstate->property_blobs,
972 &memcol_sz,
973 PLANE_PROP_FOLIAGE_COLOR);
974 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
975 MEMCOLOR_FOLIAGE, memcol);
976 }
977}
Benet Clarkeb1b4462016-06-27 14:43:06 -0700978
Clarence Ipcb410d42016-06-26 22:52:33 -0400979static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400980 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -0400981 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700982{
Clarence Ipb43d4592016-09-08 14:21:35 -0400983 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -0400984 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400985
Clarence Ipb43d4592016-09-08 14:21:35 -0400986 if (!psde || !fmt) {
987 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
988 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400989 return;
Clarence Ipb43d4592016-09-08 14:21:35 -0400990 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400991
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400992 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400993
Clarence Ipdedbba92016-09-27 17:43:10 -0400994 psde->pipe_cfg.horz_decimation =
995 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
996 psde->pipe_cfg.vert_decimation =
997 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400998
999 /* don't chroma subsample if decimating */
1000 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001001 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001002 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001003 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001004
Clarence Ip5e2a9222016-06-26 22:38:24 -04001005 /* update scaler */
1006 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001007 int error;
1008
1009 error = _sde_plane_setup_scaler3_lut(psde, pstate);
1010 if (error || !psde->pixel_ext_usr) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001011 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001012 _sde_plane_setup_scaler3(psde,
1013 psde->pipe_cfg.src_rect.w,
1014 psde->pipe_cfg.src_rect.h,
1015 psde->pipe_cfg.dst_rect.w,
1016 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001017 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001018 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001019 }
Clarence Ip3bf8d872017-02-16 15:25:38 -05001020 } else if (!psde->pixel_ext_usr || !pstate) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001021 uint32_t deci_dim, i;
1022
Clarence Ipb43d4592016-09-08 14:21:35 -04001023 /* calculate default configuration for QSEED2 */
1024 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001025
Clarence Ip13a8cf42016-09-29 17:27:47 -04001026 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001027 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1028 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001029 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001030 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001031 psde->pipe_cfg.dst_rect.w,
1032 pe->phase_step_x,
1033 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001034
Clarence Ipdbde9832016-06-26 09:48:36 -04001035 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001036 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001037 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001038 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001039 pe->phase_step_x,
1040 pe->roi_w,
1041 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001042 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001043 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001044
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001045 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001046 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001047 _sde_plane_setup_scaler2(psde,
1048 deci_dim,
1049 psde->pipe_cfg.dst_rect.h,
1050 pe->phase_step_y,
1051 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001052 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001053 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001054 pe->phase_step_y,
1055 pe->roi_h,
1056 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001057 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001058 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001059
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001060 for (i = 0; i < SDE_MAX_PLANES; i++) {
1061 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001062 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001063 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001064 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001065
1066 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001067 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001068 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001069 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001070
1071 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001072 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001073 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001074 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001075
1076 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001077 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001078 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001079 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001080 }
1081 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001082}
1083
Clarence Ipcae1bb62016-07-07 12:07:13 -04001084/**
1085 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001086 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001087 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1088 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1089 * Returns: 0 on success
1090 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001091static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001092 uint32_t color, uint32_t alpha)
1093{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001094 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001095 const struct drm_plane *plane;
1096 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001097
Clarence Ip13a8cf42016-09-29 17:27:47 -04001098 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001099 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001100 return -EINVAL;
1101 }
1102
Clarence Ipcb410d42016-06-26 22:52:33 -04001103 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001104 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001105 return -EINVAL;
1106 }
1107
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001108 plane = &psde->base;
1109 pstate = to_sde_plane_state(plane->state);
1110
Clarence Ip13a8cf42016-09-29 17:27:47 -04001111 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001112
Clarence Ipcb410d42016-06-26 22:52:33 -04001113 /*
1114 * select fill format to match user property expectation,
1115 * h/w only supports RGB variants
1116 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001117 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001118
1119 /* update sspp */
1120 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1121 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001122 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1123 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001124
1125 /* override scaler/decimation if solid fill */
1126 psde->pipe_cfg.src_rect.x = 0;
1127 psde->pipe_cfg.src_rect.y = 0;
1128 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1129 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
1130
Clarence Ipcb410d42016-06-26 22:52:33 -04001131 if (psde->pipe_hw->ops.setup_format)
1132 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001133 fmt, SDE_SSPP_SOLID_FILL,
1134 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001135
1136 if (psde->pipe_hw->ops.setup_rects)
1137 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001138 &psde->pipe_cfg,
1139 pstate->multirect_index);
1140
1141 _sde_plane_setup_scaler(psde, fmt, 0);
1142 if (psde->pipe_hw->ops.setup_pe)
1143 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1144 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001145 }
1146
1147 return 0;
1148}
1149
1150static int _sde_plane_mode_set(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001151 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -04001152{
Clarence Ipc47a0692016-10-11 10:54:17 -04001153 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -04001154 struct sde_plane *psde;
1155 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001156 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001157 struct drm_crtc *crtc;
1158 struct drm_framebuffer *fb;
1159 struct sde_rect src, dst;
1160 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001161 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -04001162
Clarence Ip13a8cf42016-09-29 17:27:47 -04001163 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -04001164 SDE_ERROR("invalid plane\n");
1165 return -EINVAL;
1166 } else if (!plane->state) {
1167 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001168 return -EINVAL;
1169 }
1170
1171 psde = to_sde_plane(plane);
1172 pstate = to_sde_plane_state(plane->state);
Clarence Ipcb410d42016-06-26 22:52:33 -04001173
Dhaval Patel47302cf2016-08-18 15:04:28 -07001174 crtc = state->crtc;
1175 fb = state->fb;
1176 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001177 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
1178 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -07001179 return -EINVAL;
1180 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001181 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001182 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -04001183
Clarence Ip282dad62016-09-27 17:07:35 -04001184 /* determine what needs to be refreshed */
1185 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
1186 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001187 case PLANE_PROP_SCALER_V1:
abeykun48f407a2016-08-25 12:06:44 -04001188 case PLANE_PROP_SCALER_V2:
Clarence Ipdedbba92016-09-27 17:43:10 -04001189 case PLANE_PROP_H_DECIMATE:
1190 case PLANE_PROP_V_DECIMATE:
1191 case PLANE_PROP_SRC_CONFIG:
1192 case PLANE_PROP_ZPOS:
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001193 case PLANE_PROP_EXCL_RECT_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04001194 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1195 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001196 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04001197 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
1198 break;
1199 case PLANE_PROP_COLOR_FILL:
1200 /* potentially need to refresh everything */
1201 pstate->dirty = SDE_PLANE_DIRTY_ALL;
1202 break;
1203 case PLANE_PROP_ROTATION:
1204 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
1205 break;
Clarence Ip282dad62016-09-27 17:07:35 -04001206 case PLANE_PROP_INFO:
1207 case PLANE_PROP_ALPHA:
1208 case PLANE_PROP_INPUT_FENCE:
1209 case PLANE_PROP_BLEND_OP:
1210 /* no special action required */
1211 break;
1212 default:
1213 /* unknown property, refresh everything */
1214 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
1215 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
1216 break;
1217 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001218 }
1219
Clarence Ip282dad62016-09-27 17:07:35 -04001220 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
1221 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -04001222
1223 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
1224
Clarence Ip282dad62016-09-27 17:07:35 -04001225 /* early out if nothing dirty */
1226 if (!pstate->dirty)
1227 return 0;
1228 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001229
Dhaval Patel4d424602017-02-18 19:40:14 -08001230 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
Clarence Ip282dad62016-09-27 17:07:35 -04001231 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1232
1233 /* update roi config */
1234 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
1235 POPULATE_RECT(&src, state->src_x, state->src_y,
1236 state->src_w, state->src_h, q16_data);
1237 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
1238 state->crtc_w, state->crtc_h, !q16_data);
1239
Clarence Ip13a8cf42016-09-29 17:27:47 -04001240 SDE_DEBUG_PLANE(psde,
1241 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001242 fb->base.id, src.x, src.y, src.w, src.h,
1243 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
1244 drm_get_format_name(fmt->base.pixel_format),
1245 SDE_FORMAT_IS_UBWC(fmt));
1246
1247 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
1248 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001249 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001250 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
1251 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
1252 src.h /= 2;
1253 src.y = DIV_ROUND_UP(src.y, 2);
1254 src.y &= ~0x1;
1255 }
1256
1257 psde->pipe_cfg.src_rect = src;
1258 psde->pipe_cfg.dst_rect = dst;
1259
1260 /* check for color fill */
1261 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
1262 PLANE_PROP_COLOR_FILL);
1263 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
1264 /* skip remaining processing on color fill */
1265 pstate->dirty = 0x0;
1266 } else if (psde->pipe_hw->ops.setup_rects) {
Clarence Ip282dad62016-09-27 17:07:35 -04001267 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001268 &psde->pipe_cfg,
1269 pstate->multirect_index);
Clarence Ip282dad62016-09-27 17:07:35 -04001270 }
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001271
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001272 _sde_plane_setup_scaler(psde, fmt, pstate);
1273 if (psde->pipe_hw->ops.setup_pe)
1274 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1275 &psde->pixel_ext);
1276
1277 if (psde->pipe_hw->ops.setup_scaler)
1278 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
1279 &psde->pipe_cfg, &psde->pixel_ext,
1280 psde->scaler3_cfg);
1281
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001282 /* update excl rect */
1283 if (psde->pipe_hw->ops.setup_excl_rect)
1284 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001285 &pstate->excl_rect,
1286 pstate->multirect_index);
1287
1288 if (psde->pipe_hw->ops.setup_multirect)
1289 psde->pipe_hw->ops.setup_multirect(
1290 psde->pipe_hw,
1291 pstate->multirect_index,
1292 pstate->multirect_mode);
Dhaval Patel48c76022016-09-01 17:51:23 -07001293 }
1294
Clarence Ip282dad62016-09-27 17:07:35 -04001295 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
1296 psde->pipe_hw->ops.setup_format) {
1297 src_flags = 0x0;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001298 SDE_DEBUG_PLANE(psde, "rotation 0x%llX\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001299 sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
1300 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
Clarence Ip531f5572017-01-24 10:10:05 -08001301 DRM_REFLECT_X)
Clarence Ip282dad62016-09-27 17:07:35 -04001302 src_flags |= SDE_SSPP_FLIP_LR;
1303 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
Clarence Ip531f5572017-01-24 10:10:05 -08001304 DRM_REFLECT_Y)
Clarence Ip282dad62016-09-27 17:07:35 -04001305 src_flags |= SDE_SSPP_FLIP_UD;
1306
1307 /* update format */
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001308 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
1309 pstate->multirect_index);
Clarence Ip282dad62016-09-27 17:07:35 -04001310
1311 /* update csc */
1312 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04001313 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04001314 else
1315 psde->csc_ptr = 0;
1316 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001317
Benet Clarkeb1b4462016-06-27 14:43:06 -07001318 sde_color_process_plane_setup(plane);
1319
Clarence Ipe78efb72016-06-24 18:35:21 -04001320 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04001321 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
1322 psde->pipe_hw->ops.setup_sharpening) {
1323 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
1324 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
1325 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
1326 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04001327
Clarence Ipe78efb72016-06-24 18:35:21 -04001328 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04001329 &psde->sharp_cfg);
1330 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001331
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001332 _sde_plane_set_qos_lut(plane, fb);
1333 _sde_plane_set_danger_lut(plane, fb);
1334
Alan Kwong5d324e42016-07-28 22:56:18 -04001335 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001336 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04001337 _sde_plane_set_ot_limit(plane, crtc);
1338 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001339
Clarence Ip282dad62016-09-27 17:07:35 -04001340 /* clear dirty */
1341 pstate->dirty = 0x0;
1342
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001343 /* clear multirect mode*/
1344 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
1345 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
1346 return 0;
1347}
1348
1349int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
1350{
1351 struct sde_plane_state *pstate[R_MAX];
1352 const struct drm_plane_state *drm_state[R_MAX];
1353 struct sde_rect src[R_MAX], dst[R_MAX];
1354 struct sde_plane *sde_plane[R_MAX];
1355 const struct sde_format *fmt[R_MAX];
1356 bool q16_data = true;
1357 int i, max_sspp_linewidth;
1358 int buffer_lines = TX_MODE_BUFFER_LINE_THRES;
1359
1360 for (i = 0; i < R_MAX; i++) {
1361 const struct msm_format *msm_fmt;
1362
1363 drm_state[i] = i ? plane->r1 : plane->r0;
1364 pstate[i] = to_sde_plane_state(drm_state[i]);
1365 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
1366
1367 if (pstate[i] == NULL) {
1368 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
1369 drm_state[i]->plane->base.id);
1370 return -EINVAL;
1371 }
1372
1373 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
1374 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
1375 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
1376 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
1377 drm_state[i]->crtc_h, !q16_data);
1378
1379 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
1380 SDE_ERROR_PLANE(sde_plane[i],
1381 "scaling is not supported in multirect mode\n");
1382 return -EINVAL;
1383 }
1384
1385 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
1386 fmt[i] = to_sde_format(msm_fmt);
1387 if (SDE_FORMAT_IS_YUV(fmt[i])) {
1388 SDE_ERROR_PLANE(sde_plane[i],
1389 "Unsupported format for multirect mode\n");
1390 return -EINVAL;
1391 }
1392 }
1393
1394 max_sspp_linewidth = sde_plane[R0]->pipe_sblk->maxlinewidth;
1395
1396 /* Validate RECT's and set the mode */
1397
1398 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
1399 if (src[R0].w <= max_sspp_linewidth/2 &&
1400 src[R1].w <= max_sspp_linewidth/2) {
1401 if (dst[R0].x <= dst[R1].x) {
1402 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
1403 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
1404 } else {
1405 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
1406 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
1407 }
1408
1409 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
1410 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
1411 goto done;
1412 }
1413
1414 /* TIME_MX Mode */
1415 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
1416 buffer_lines = 2 * fmt[R0]->tile_height;
1417
1418 if (dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) {
1419 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
1420 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
1421 } else if (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines) {
1422 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
1423 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
1424 } else {
1425 SDE_ERROR(
1426 "No multirect mode possible for the planes (%d - %d)\n",
1427 drm_state[R0]->plane->base.id,
1428 drm_state[R1]->plane->base.id);
1429 return -EINVAL;
1430 }
1431
1432 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
1433 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
1434done:
Clarence Ip5e2a9222016-06-26 22:38:24 -04001435 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001436}
1437
1438static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001439 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001440{
1441 struct drm_framebuffer *fb = new_state->fb;
1442 struct sde_plane *psde = to_sde_plane(plane);
1443
1444 if (!new_state->fb)
1445 return 0;
1446
Clarence Ip13a8cf42016-09-29 17:27:47 -04001447 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001448 return msm_framebuffer_prepare(fb, psde->mmu_id);
1449}
1450
1451static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001452 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001453{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001454 struct drm_framebuffer *fb = old_state ? old_state->fb : NULL;
1455 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001456
1457 if (!fb)
1458 return;
1459
Clarence Ip13a8cf42016-09-29 17:27:47 -04001460 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001461 msm_framebuffer_cleanup(fb, psde->mmu_id);
1462}
1463
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001464static void _sde_plane_atomic_check_mode_changed(struct sde_plane *psde,
1465 struct drm_plane_state *state,
1466 struct drm_plane_state *old_state)
1467{
1468 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001469 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001470
Dhaval Patel47302cf2016-08-18 15:04:28 -07001471 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04001472 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001473 return;
1474
Clarence Ip282dad62016-09-27 17:07:35 -04001475 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
1476 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001477 SDE_DEBUG_PLANE(psde,
1478 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001479 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001480 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001481 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001482 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001483 } else if (state->src_w != old_state->src_w ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07001484 state->src_h != old_state->src_h ||
1485 state->src_x != old_state->src_x ||
1486 state->src_y != old_state->src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001487 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001488 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001489 } else if (state->crtc_w != old_state->crtc_w ||
1490 state->crtc_h != old_state->crtc_h ||
1491 state->crtc_x != old_state->crtc_x ||
1492 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001493 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001494 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001495 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
1496 pstate->excl_rect.h != old_pstate->excl_rect.h ||
1497 pstate->excl_rect.x != old_pstate->excl_rect.x ||
1498 pstate->excl_rect.y != old_pstate->excl_rect.y) {
1499 SDE_DEBUG_PLANE(psde, "excl rect updated\n");
1500 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001501 } else if (pstate->multirect_index != old_pstate->multirect_index ||
1502 pstate->multirect_mode != old_pstate->multirect_mode) {
1503 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
1504 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04001505 }
1506
1507 if (!state->fb || !old_state->fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001508 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001509 } else if (state->fb->pixel_format != old_state->fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001510 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001511 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001512 } else {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001513 uint64_t *new_mods = state->fb->modifier;
1514 uint64_t *old_mods = old_state->fb->modifier;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001515 uint32_t *new_pitches = state->fb->pitches;
1516 uint32_t *old_pitches = old_state->fb->pitches;
1517 uint32_t *new_offset = state->fb->offsets;
1518 uint32_t *old_offset = old_state->fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001519 int i;
1520
1521 for (i = 0; i < ARRAY_SIZE(state->fb->modifier); i++) {
1522 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001523 SDE_DEBUG_PLANE(psde,
1524 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001525 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001526 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001527 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1528 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001529 break;
1530 }
1531 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001532 for (i = 0; i < ARRAY_SIZE(state->fb->pitches); i++) {
1533 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001534 SDE_DEBUG_PLANE(psde,
1535 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001536 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001537 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001538 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001539 break;
1540 }
1541 }
Dhaval Patel47302cf2016-08-18 15:04:28 -07001542 for (i = 0; i < ARRAY_SIZE(state->fb->offsets); i++) {
1543 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001544 SDE_DEBUG_PLANE(psde,
1545 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001546 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001547 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001548 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1549 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001550 break;
1551 }
1552 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001553 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001554}
1555
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001556static int sde_plane_atomic_check(struct drm_plane *plane,
1557 struct drm_plane_state *state)
1558{
Clarence Ipdedbba92016-09-27 17:43:10 -04001559 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04001560 struct sde_plane *psde;
1561 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001562 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001563 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04001564 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001565 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
1566 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04001567
1568 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001569 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1570 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04001571 ret = -EINVAL;
1572 goto exit;
1573 }
1574
1575 psde = to_sde_plane(plane);
1576 pstate = to_sde_plane_state(state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001577
1578 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001579 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001580 ret = -EINVAL;
1581 goto exit;
1582 }
1583
Clarence Ipdedbba92016-09-27 17:43:10 -04001584 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1585 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04001586
1587 /* src values are in Q16 fixed point, convert to integer */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001588 POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w,
1589 state->src_h, q16_data);
1590 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
1591 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04001592
Dhaval Patel47302cf2016-08-18 15:04:28 -07001593 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
1594 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04001595
Dhaval Patel47302cf2016-08-18 15:04:28 -07001596 max_upscale = psde->pipe_sblk->maxupscale;
1597 max_downscale = psde->pipe_sblk->maxdwnscale;
1598 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04001599
Clarence Ip13a8cf42016-09-29 17:27:47 -04001600 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001601 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001602
Dhaval Patel47302cf2016-08-18 15:04:28 -07001603 if (!sde_plane_enabled(state))
1604 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04001605
Dhaval Patel47302cf2016-08-18 15:04:28 -07001606 fmt = to_sde_format(msm_framebuffer_format(state->fb));
1607
1608 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
1609
1610 if (SDE_FORMAT_IS_YUV(fmt) &&
1611 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04001612 !(psde->features & (BIT(SDE_SSPP_CSC)
1613 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001614 SDE_ERROR_PLANE(psde,
1615 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07001616 ret = -EINVAL;
1617
1618 /* check src bounds */
1619 } else if (state->fb->width > MAX_IMG_WIDTH ||
1620 state->fb->height > MAX_IMG_HEIGHT ||
1621 src.w < min_src_size || src.h < min_src_size ||
1622 CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) ||
1623 CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001624 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001625 src.x, src.y, src.w, src.h);
1626 ret = -E2BIG;
1627
1628 /* valid yuv image */
1629 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
1630 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001631 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001632 src.x, src.y, src.w, src.h);
1633 ret = -EINVAL;
1634
1635 /* min dst support */
1636 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001637 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001638 dst.x, dst.y, dst.w, dst.h);
1639 ret = -EINVAL;
1640
1641 /* decimation validation */
1642 } else if (deci_w || deci_h) {
1643 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
1644 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001645 SDE_ERROR_PLANE(psde,
1646 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001647 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001648 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001649 SDE_ERROR_PLANE(psde,
1650 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001651 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001652 }
1653
Dhaval Patel47302cf2016-08-18 15:04:28 -07001654 } else if (!(psde->features & SDE_SSPP_SCALER) &&
1655 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001656 SDE_ERROR_PLANE(psde,
1657 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001658 src.w, src.h, dst.w, dst.h);
1659 ret = -EINVAL;
1660
1661 /* check decimated source width */
1662 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001663 SDE_ERROR_PLANE(psde,
1664 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001665 src.w, src_deci_w, max_linewidth);
1666 ret = -E2BIG;
1667
1668 /* check max scaler capability */
1669 } else if (((src_deci_w * max_upscale) < dst.w) ||
1670 ((src_deci_h * max_upscale) < dst.h) ||
1671 ((dst.w * max_downscale) < src_deci_w) ||
1672 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001673 SDE_ERROR_PLANE(psde,
1674 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001675 src_deci_w, src_deci_h, dst.w, dst.h);
1676 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001677 }
1678
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001679 /* check excl rect configs */
1680 if (pstate->excl_rect.w && pstate->excl_rect.h) {
1681 struct sde_rect intersect;
1682
1683 /*
1684 * Check exclusion rect against src rect.
1685 * Cropping is not required as hardware will consider only the
1686 * intersecting region with the src rect.
1687 */
1688 sde_kms_rect_intersect(&intersect, &src, &pstate->excl_rect);
1689 if (!intersect.w || !intersect.h || SDE_FORMAT_IS_YUV(fmt)) {
1690 SDE_ERROR_PLANE(psde,
1691 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt:%s\n",
1692 pstate->excl_rect.x, pstate->excl_rect.y,
1693 pstate->excl_rect.w, pstate->excl_rect.h,
1694 src.x, src.y, src.w, src.h,
1695 drm_get_format_name(fmt->base.pixel_format));
1696 ret = -EINVAL;
1697 }
1698 }
1699
Dhaval Patel47302cf2016-08-18 15:04:28 -07001700modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001701 if (!ret)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001702 _sde_plane_atomic_check_mode_changed(psde, state, plane->state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001703exit:
1704 return ret;
1705}
1706
Clarence Ipcae1bb62016-07-07 12:07:13 -04001707/**
1708 * sde_plane_flush - final plane operations before commit flush
1709 * @plane: Pointer to drm plane structure
1710 */
1711void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04001712{
Clarence Ipcae1bb62016-07-07 12:07:13 -04001713 struct sde_plane *psde;
1714
Clarence Ip13a8cf42016-09-29 17:27:47 -04001715 if (!plane) {
1716 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001717 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001718 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04001719
1720 psde = to_sde_plane(plane);
1721
1722 /*
1723 * These updates have to be done immediately before the plane flush
1724 * timing, and may not be moved to the atomic_update/mode_set functions.
1725 */
1726 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05001727 /* force white frame with 100% alpha pipe output on error */
1728 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001729 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
1730 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001731 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001732 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
1733 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
1734
1735 /* flag h/w flush complete */
1736 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04001737 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001738}
1739
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001740static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04001741 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001742{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001743 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001744 struct drm_plane_state *state;
1745 struct sde_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001746
Clarence Ip13a8cf42016-09-29 17:27:47 -04001747 if (!plane) {
1748 SDE_ERROR("invalid plane\n");
1749 return;
1750 } else if (!plane->state) {
1751 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04001752 return;
1753 }
1754
Clarence Ip13a8cf42016-09-29 17:27:47 -04001755 psde = to_sde_plane(plane);
1756 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001757 state = plane->state;
1758 pstate = to_sde_plane_state(state);
1759
Clarence Ip13a8cf42016-09-29 17:27:47 -04001760 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001761
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001762 if (!sde_plane_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04001763 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001764 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001765 int ret;
1766
Dhaval Patel47302cf2016-08-18 15:04:28 -07001767 ret = _sde_plane_mode_set(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001768 /* atomic_check should have ensured that this doesn't fail */
1769 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001770 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001771}
1772
Dhaval Patel47302cf2016-08-18 15:04:28 -07001773
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001774/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001775static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001776 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001777{
Clarence Ip5e2a9222016-06-26 22:38:24 -04001778 static const struct drm_prop_enum_list e_blend_op[] = {
1779 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
1780 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
1781 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
1782 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
1783 };
1784 static const struct drm_prop_enum_list e_src_config[] = {
1785 {SDE_DRM_DEINTERLACE, "deinterlace"}
1786 };
Clarence Ipea3d6262016-07-15 16:20:11 -04001787 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07001788 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001789 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04001790 int zpos_max = 255;
1791 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001792 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001793
Clarence Ip13a8cf42016-09-29 17:27:47 -04001794 if (!plane || !psde) {
1795 SDE_ERROR("invalid plane\n");
1796 return;
1797 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
1798 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
1799 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001800 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04001801 } else if (!catalog) {
1802 SDE_ERROR("invalid catalog\n");
1803 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001804 }
1805
Clarence Ipc47a0692016-10-11 10:54:17 -04001806 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04001807 if (catalog->mixer_count && catalog->mixer &&
1808 catalog->mixer[0].sblk->maxblendstages) {
1809 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
1810 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
1811 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
1812 }
Clarence Ipc47a0692016-10-11 10:54:17 -04001813 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
1814 /* reserve zpos == 0 for primary planes */
1815 zpos_def = drm_plane_index(plane) + 1;
1816 }
1817
1818 msm_property_install_range(&psde->property_info, "zpos",
1819 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001820
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001821 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001822 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001823
Dhaval Patel47302cf2016-08-18 15:04:28 -07001824 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001825 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07001826 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001827
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001828 if (!master_plane_id) {
1829 if (psde->pipe_sblk->maxhdeciexp) {
1830 msm_property_install_range(&psde->property_info,
1831 "h_decimate", 0x0, 0,
1832 psde->pipe_sblk->maxhdeciexp, 0,
1833 PLANE_PROP_H_DECIMATE);
1834 }
Clarence Ipdedbba92016-09-27 17:43:10 -04001835
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001836 if (psde->pipe_sblk->maxvdeciexp) {
1837 msm_property_install_range(&psde->property_info,
1838 "v_decimate", 0x0, 0,
1839 psde->pipe_sblk->maxvdeciexp, 0,
1840 PLANE_PROP_V_DECIMATE);
1841 }
Clarence Ipdedbba92016-09-27 17:43:10 -04001842
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001843 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
1844 msm_property_install_volatile_range(
1845 &psde->property_info, "scaler_v2",
1846 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
1847 msm_property_install_blob(&psde->property_info,
1848 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
1849 msm_property_install_blob(&psde->property_info,
1850 "lut_cir", 0,
1851 PLANE_PROP_SCALER_LUT_CIR);
1852 msm_property_install_blob(&psde->property_info,
1853 "lut_sep", 0,
1854 PLANE_PROP_SCALER_LUT_SEP);
1855 } else if (psde->features & SDE_SSPP_SCALER) {
1856 msm_property_install_volatile_range(
1857 &psde->property_info, "scaler_v1", 0x0,
1858 0, ~0, 0, PLANE_PROP_SCALER_V1);
1859 }
Clarence Ipb43d4592016-09-08 14:21:35 -04001860
Dhaval Patel0aee0972017-02-08 19:00:58 -08001861 if (psde->features & BIT(SDE_SSPP_CSC) ||
1862 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001863 msm_property_install_volatile_range(
1864 &psde->property_info, "csc_v1", 0x0,
1865 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001866
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001867 if (psde->features & BIT(SDE_SSPP_HSIC)) {
1868 snprintf(feature_name, sizeof(feature_name), "%s%d",
1869 "SDE_SSPP_HUE_V",
1870 psde->pipe_sblk->hsic_blk.version >> 16);
1871 msm_property_install_range(&psde->property_info,
1872 feature_name, 0, 0, 0xFFFFFFFF, 0,
1873 PLANE_PROP_HUE_ADJUST);
1874 snprintf(feature_name, sizeof(feature_name), "%s%d",
1875 "SDE_SSPP_SATURATION_V",
1876 psde->pipe_sblk->hsic_blk.version >> 16);
1877 msm_property_install_range(&psde->property_info,
1878 feature_name, 0, 0, 0xFFFFFFFF, 0,
1879 PLANE_PROP_SATURATION_ADJUST);
1880 snprintf(feature_name, sizeof(feature_name), "%s%d",
1881 "SDE_SSPP_VALUE_V",
1882 psde->pipe_sblk->hsic_blk.version >> 16);
1883 msm_property_install_range(&psde->property_info,
1884 feature_name, 0, 0, 0xFFFFFFFF, 0,
1885 PLANE_PROP_VALUE_ADJUST);
1886 snprintf(feature_name, sizeof(feature_name), "%s%d",
1887 "SDE_SSPP_CONTRAST_V",
1888 psde->pipe_sblk->hsic_blk.version >> 16);
1889 msm_property_install_range(&psde->property_info,
1890 feature_name, 0, 0, 0xFFFFFFFF, 0,
1891 PLANE_PROP_CONTRAST_ADJUST);
1892 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07001893 }
1894
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08001895 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
1896 msm_property_install_volatile_range(&psde->property_info,
1897 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
1898
Clarence Ip5e2a9222016-06-26 22:38:24 -04001899 /* standard properties */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001900 msm_property_install_rotation(&psde->property_info,
Clarence Ip531f5572017-01-24 10:10:05 -08001901 (unsigned int) (DRM_REFLECT_X | DRM_REFLECT_Y),
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001902 PLANE_PROP_ROTATION);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001903
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001904 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001905 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001906
Dhaval Patel47302cf2016-08-18 15:04:28 -07001907 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
1908 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
1909
1910 if (psde->pipe_hw->ops.setup_solidfill)
1911 msm_property_install_range(&psde->property_info, "color_fill",
1912 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
1913
Dhaval Patel4e574842016-08-23 15:11:37 -07001914 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001915 if (!info) {
1916 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07001917 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001918 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001919
1920 msm_property_install_blob(&psde->property_info, "capabilities",
1921 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
1922 sde_kms_info_reset(info);
1923
Clarence Ipea3d6262016-07-15 16:20:11 -04001924 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001925
1926 if (master_plane_id) {
1927 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
1928 master_plane_id);
1929 format_list = plane_formats;
1930 }
1931
Clarence Ipea3d6262016-07-15 16:20:11 -04001932 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04001933 sde_kms_info_start(info, "pixel_formats");
1934 while (format_list->fourcc_format) {
1935 sde_kms_info_append_format(info,
1936 format_list->fourcc_format,
1937 format_list->modifier);
1938 ++format_list;
1939 }
1940 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04001941 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001942
1943 sde_kms_info_add_keyint(info, "max_linewidth",
1944 psde->pipe_sblk->maxlinewidth);
1945 sde_kms_info_add_keyint(info, "max_upscale",
1946 psde->pipe_sblk->maxupscale);
1947 sde_kms_info_add_keyint(info, "max_downscale",
1948 psde->pipe_sblk->maxdwnscale);
1949 sde_kms_info_add_keyint(info, "max_horizontal_deci",
1950 psde->pipe_sblk->maxhdeciexp);
1951 sde_kms_info_add_keyint(info, "max_vertical_deci",
1952 psde->pipe_sblk->maxvdeciexp);
1953 msm_property_set_blob(&psde->property_info, &psde->blob_info,
1954 info->data, info->len, PLANE_PROP_INFO);
1955
1956 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07001957
1958 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
1959 snprintf(feature_name, sizeof(feature_name), "%s%d",
1960 "SDE_SSPP_SKIN_COLOR_V",
1961 psde->pipe_sblk->memcolor_blk.version >> 16);
1962 msm_property_install_blob(&psde->property_info, feature_name, 0,
1963 PLANE_PROP_SKIN_COLOR);
1964 snprintf(feature_name, sizeof(feature_name), "%s%d",
1965 "SDE_SSPP_SKY_COLOR_V",
1966 psde->pipe_sblk->memcolor_blk.version >> 16);
1967 msm_property_install_blob(&psde->property_info, feature_name, 0,
1968 PLANE_PROP_SKY_COLOR);
1969 snprintf(feature_name, sizeof(feature_name), "%s%d",
1970 "SDE_SSPP_FOLIAGE_COLOR_V",
1971 psde->pipe_sblk->memcolor_blk.version >> 16);
1972 msm_property_install_blob(&psde->property_info, feature_name, 0,
1973 PLANE_PROP_FOLIAGE_COLOR);
1974 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001975}
1976
Clarence Ip5fc00c52016-09-23 15:03:34 -04001977static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
1978{
1979 struct sde_drm_csc_v1 csc_v1;
1980 int i;
1981
1982 if (!psde) {
1983 SDE_ERROR("invalid plane\n");
1984 return;
1985 }
1986
1987 psde->csc_usr_ptr = NULL;
1988 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001989 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001990 return;
1991 }
1992
1993 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001994 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001995 return;
1996 }
1997
Clarence Ipb43d4592016-09-08 14:21:35 -04001998 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001999 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
2000 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
2001 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
2002 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
2003 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
2004 }
2005 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
2006 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
2007 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
2008 }
2009 psde->csc_usr_ptr = &psde->csc_cfg;
2010}
2011
Clarence Ipb43d4592016-09-08 14:21:35 -04002012static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
2013{
2014 struct sde_drm_scaler_v1 scale_v1;
2015 struct sde_hw_pixel_ext *pe;
2016 int i;
2017
2018 if (!psde) {
2019 SDE_ERROR("invalid plane\n");
2020 return;
2021 }
2022
2023 psde->pixel_ext_usr = false;
2024 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002025 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04002026 return;
2027 }
2028
2029 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002030 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04002031 return;
2032 }
2033
2034 /* populate from user space */
2035 pe = &(psde->pixel_ext);
2036 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
2037 for (i = 0; i < SDE_MAX_PLANES; i++) {
2038 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
2039 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
2040 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
2041 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
2042
2043 pe->horz_filter[i] = scale_v1.horz_filter[i];
2044 pe->vert_filter[i] = scale_v1.vert_filter[i];
2045 }
2046 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05002047 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
2048 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
2049 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
2050 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
2051 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04002052
abeykun41060122016-11-28 13:02:01 -05002053 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
2054 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
2055 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
2056 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
2057 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04002058 }
abeykun41060122016-11-28 13:02:01 -05002059
Clarence Ipb43d4592016-09-08 14:21:35 -04002060 psde->pixel_ext_usr = true;
2061
Clarence Ip13a8cf42016-09-29 17:27:47 -04002062 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04002063}
2064
abeykun48f407a2016-08-25 12:06:44 -04002065static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
2066 struct sde_plane_state *pstate, void *usr)
2067{
2068 struct sde_drm_scaler_v2 scale_v2;
2069 struct sde_hw_pixel_ext *pe;
2070 int i;
2071 struct sde_hw_scaler3_cfg *cfg;
2072
2073 if (!psde) {
2074 SDE_ERROR("invalid plane\n");
2075 return;
2076 }
2077
2078 cfg = psde->scaler3_cfg;
2079 psde->pixel_ext_usr = false;
2080 if (!usr) {
2081 SDE_DEBUG_PLANE(psde, "scale data removed\n");
2082 return;
2083 }
2084
2085 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
2086 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
2087 return;
2088 }
2089
2090 /* populate from user space */
2091 pe = &(psde->pixel_ext);
2092 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
2093 cfg->enable = scale_v2.enable;
2094 cfg->dir_en = scale_v2.dir_en;
2095 for (i = 0; i < SDE_MAX_PLANES; i++) {
2096 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
2097 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
2098 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
2099 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
2100
2101 cfg->preload_x[i] = scale_v2.preload_x[i];
2102 cfg->preload_y[i] = scale_v2.preload_y[i];
2103 cfg->src_width[i] = scale_v2.src_width[i];
2104 cfg->src_height[i] = scale_v2.src_height[i];
2105 }
2106 cfg->dst_width = scale_v2.dst_width;
2107 cfg->dst_height = scale_v2.dst_height;
2108
2109 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
2110 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
2111 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
2112 cfg->blend_cfg = scale_v2.blend_cfg;
2113
2114 cfg->lut_flag = scale_v2.lut_flag;
2115 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
2116 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
2117 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
2118 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
2119 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
2120
2121 cfg->de.enable = scale_v2.de.enable;
2122 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
2123 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
2124 cfg->de.clip = scale_v2.de.clip;
2125 cfg->de.limit = scale_v2.de.limit;
2126 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
2127 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
2128 cfg->de.thr_low = scale_v2.de.thr_low;
2129 cfg->de.thr_high = scale_v2.de.thr_high;
2130 cfg->de.prec_shift = scale_v2.de.prec_shift;
2131 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
2132 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
2133 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
2134 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
2135 }
2136 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05002137 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
2138 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
2139 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
2140 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
2141 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04002142
abeykun41060122016-11-28 13:02:01 -05002143 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
2144 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
2145 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
2146 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
2147 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04002148 }
2149 psde->pixel_ext_usr = true;
2150
2151 SDE_DEBUG_PLANE(psde, "user property data copied\n");
2152}
2153
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002154static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
2155 struct sde_plane_state *pstate, void *usr_ptr)
2156{
2157 struct drm_clip_rect excl_rect_v1;
2158
2159 if (!psde) {
2160 SDE_ERROR("invalid plane\n");
2161 return;
2162 }
2163
2164 if (!usr_ptr) {
2165 SDE_DEBUG_PLANE(psde, "excl rect data removed\n");
2166 return;
2167 }
2168
2169 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
2170 SDE_ERROR_PLANE(psde, "failed to copy excl rect data\n");
2171 return;
2172 }
2173
2174 /* populate from user space */
2175 pstate->excl_rect.x = excl_rect_v1.x1;
2176 pstate->excl_rect.y = excl_rect_v1.y1;
2177 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1 + 1;
2178 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1 + 1;
2179}
2180
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002181static int sde_plane_atomic_set_property(struct drm_plane *plane,
2182 struct drm_plane_state *state, struct drm_property *property,
2183 uint64_t val)
2184{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002185 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002186 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04002187 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002188
Clarence Ip13a8cf42016-09-29 17:27:47 -04002189 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002190
2191 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002192 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002193 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002194 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002195 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04002196 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002197 ret = msm_property_atomic_set(&psde->property_info,
2198 pstate->property_values, pstate->property_blobs,
2199 property, val);
2200 if (!ret) {
2201 idx = msm_property_index(&psde->property_info,
2202 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04002203 switch (idx) {
2204 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04002205 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04002206 break;
2207 case PLANE_PROP_CSC_V1:
2208 _sde_plane_set_csc_v1(psde, (void *)val);
2209 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04002210 case PLANE_PROP_SCALER_V1:
2211 _sde_plane_set_scaler_v1(psde, (void *)val);
2212 break;
abeykun48f407a2016-08-25 12:06:44 -04002213 case PLANE_PROP_SCALER_V2:
2214 _sde_plane_set_scaler_v2(psde, pstate,
2215 (void *)val);
2216 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002217 case PLANE_PROP_EXCL_RECT_V1:
2218 _sde_plane_set_excl_rect_v1(psde, pstate,
2219 (void *)val);
2220 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04002221 default:
2222 /* nothing to do */
2223 break;
2224 }
Clarence Ipe78efb72016-06-24 18:35:21 -04002225 }
2226 }
2227
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002228 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002229}
2230
2231static int sde_plane_set_property(struct drm_plane *plane,
2232 struct drm_property *property, uint64_t val)
2233{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002234 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04002235
Clarence Ipae4e60c2016-06-26 22:44:04 -04002236 return sde_plane_atomic_set_property(plane,
2237 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002238}
2239
2240static int sde_plane_atomic_get_property(struct drm_plane *plane,
2241 const struct drm_plane_state *state,
2242 struct drm_property *property, uint64_t *val)
2243{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002244 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002245 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04002246 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002247
Clarence Ipaa0faf42016-05-30 12:07:48 -04002248 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002249 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002250 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002251 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002252 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002253 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04002254 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002255 ret = msm_property_atomic_get(&psde->property_info,
2256 pstate->property_values, pstate->property_blobs,
2257 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04002258 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002259
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002260 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002261}
2262
2263static void sde_plane_destroy(struct drm_plane *plane)
2264{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002265 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002266
Clarence Ip13a8cf42016-09-29 17:27:47 -04002267 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002268
Clarence Ip13a8cf42016-09-29 17:27:47 -04002269 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04002270 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
2271
Dhaval Patel4e574842016-08-23 15:11:37 -07002272 if (psde->blob_info)
2273 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002274 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04002275 mutex_destroy(&psde->lock);
2276
Clarence Ip4ce59322016-06-26 22:27:51 -04002277 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002278
Clarence Ip4ce59322016-06-26 22:27:51 -04002279 /* this will destroy the states as well */
2280 drm_plane_cleanup(plane);
2281
Clarence Ip4c1d9772016-06-26 09:35:38 -04002282 if (psde->pipe_hw)
2283 sde_hw_sspp_destroy(psde->pipe_hw);
2284
Clarence Ip4ce59322016-06-26 22:27:51 -04002285 kfree(psde);
2286 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002287}
2288
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002289static void sde_plane_destroy_state(struct drm_plane *plane,
2290 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002291{
Clarence Ipaa0faf42016-05-30 12:07:48 -04002292 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04002293 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04002294
Clarence Ipae4e60c2016-06-26 22:44:04 -04002295 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002296 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2297 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04002298 return;
2299 }
2300
Clarence Ipaa0faf42016-05-30 12:07:48 -04002301 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04002302 pstate = to_sde_plane_state(state);
2303
Clarence Ip13a8cf42016-09-29 17:27:47 -04002304 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002305
Clarence Ipe78efb72016-06-24 18:35:21 -04002306 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002307 if (state->fb)
2308 drm_framebuffer_unreference(state->fb);
2309
Clarence Ipae4e60c2016-06-26 22:44:04 -04002310 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04002311 if (pstate->input_fence)
2312 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04002313
Clarence Ipaa0faf42016-05-30 12:07:48 -04002314 /* destroy value helper */
2315 msm_property_destroy_state(&psde->property_info, pstate,
2316 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002317}
2318
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002319static struct drm_plane_state *
2320sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002321{
Clarence Ipaa0faf42016-05-30 12:07:48 -04002322 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002323 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04002324 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04002325 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002326
Clarence Ip13a8cf42016-09-29 17:27:47 -04002327 if (!plane) {
2328 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002329 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002330 } else if (!plane->state) {
2331 SDE_ERROR("invalid plane state\n");
2332 return NULL;
2333 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002334
Clarence Ip730e7192016-06-26 22:45:09 -04002335 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002336 psde = to_sde_plane(plane);
2337 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002338 if (!pstate) {
2339 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002340 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002341 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002342
Clarence Ip13a8cf42016-09-29 17:27:47 -04002343 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002344
2345 /* duplicate value helper */
2346 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
2347 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04002348
Clarence Ip730e7192016-06-26 22:45:09 -04002349 /* add ref count for frame buffer */
2350 if (pstate->base.fb)
2351 drm_framebuffer_reference(pstate->base.fb);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002352
Clarence Ip17e908b2016-09-29 15:58:00 -04002353 /* clear out any input fence */
2354 pstate->input_fence = 0;
2355 input_fence_default = msm_property_get_default(
2356 &psde->property_info, PLANE_PROP_INPUT_FENCE);
2357 msm_property_set_property(&psde->property_info, pstate->property_values,
2358 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002359
Clarence Ip282dad62016-09-27 17:07:35 -04002360 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04002361 pstate->pending = false;
2362
2363 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002364}
2365
2366static void sde_plane_reset(struct drm_plane *plane)
2367{
Clarence Ipae4e60c2016-06-26 22:44:04 -04002368 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002369 struct sde_plane_state *pstate;
2370
Clarence Ipae4e60c2016-06-26 22:44:04 -04002371 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002372 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04002373 return;
2374 }
2375
Clarence Ip730e7192016-06-26 22:45:09 -04002376 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002377 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002378
Clarence Ipae4e60c2016-06-26 22:44:04 -04002379 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04002380 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04002381 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002382 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04002383 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002384
Clarence Ipaa0faf42016-05-30 12:07:48 -04002385 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002386 if (!pstate) {
2387 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002388 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002389 }
Clarence Ip730e7192016-06-26 22:45:09 -04002390
Clarence Ipaa0faf42016-05-30 12:07:48 -04002391 /* reset value helper */
2392 msm_property_reset_state(&psde->property_info, pstate,
2393 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002394
2395 pstate->base.plane = plane;
2396
2397 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002398}
2399
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002400#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04002401static ssize_t _sde_plane_danger_read(struct file *file,
2402 char __user *buff, size_t count, loff_t *ppos)
2403{
2404 struct sde_kms *kms = file->private_data;
2405 struct sde_mdss_cfg *cfg = kms->catalog;
2406 int len = 0;
2407 char buf[40] = {'\0'};
2408
2409 if (!cfg)
2410 return -ENODEV;
2411
2412 if (*ppos)
2413 return 0; /* the end */
2414
2415 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
2416 if (len < 0 || len >= sizeof(buf))
2417 return 0;
2418
2419 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
2420 return -EFAULT;
2421
2422 *ppos += len; /* increase offset */
2423
2424 return len;
2425}
2426
2427static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
2428{
2429 struct drm_plane *plane;
2430
2431 drm_for_each_plane(plane, kms->dev) {
2432 if (plane->fb && plane->state) {
2433 sde_plane_danger_signal_ctrl(plane, enable);
2434 SDE_DEBUG("plane:%d img:%dx%d ",
2435 plane->base.id, plane->fb->width,
2436 plane->fb->height);
2437 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
2438 plane->state->src_x >> 16,
2439 plane->state->src_y >> 16,
2440 plane->state->src_w >> 16,
2441 plane->state->src_h >> 16,
2442 plane->state->crtc_x, plane->state->crtc_y,
2443 plane->state->crtc_w, plane->state->crtc_h);
2444 } else {
2445 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
2446 }
2447 }
2448}
2449
2450static ssize_t _sde_plane_danger_write(struct file *file,
2451 const char __user *user_buf, size_t count, loff_t *ppos)
2452{
2453 struct sde_kms *kms = file->private_data;
2454 struct sde_mdss_cfg *cfg = kms->catalog;
2455 int disable_panic;
2456 char buf[10];
2457
2458 if (!cfg)
2459 return -EFAULT;
2460
2461 if (count >= sizeof(buf))
2462 return -EFAULT;
2463
2464 if (copy_from_user(buf, user_buf, count))
2465 return -EFAULT;
2466
2467 buf[count] = 0; /* end of string */
2468
2469 if (kstrtoint(buf, 0, &disable_panic))
2470 return -EFAULT;
2471
2472 if (disable_panic) {
2473 /* Disable panic signal for all active pipes */
2474 SDE_DEBUG("Disabling danger:\n");
2475 _sde_plane_set_danger_state(kms, false);
2476 kms->has_danger_ctrl = false;
2477 } else {
2478 /* Enable panic signal for all active pipes */
2479 SDE_DEBUG("Enabling danger:\n");
2480 kms->has_danger_ctrl = true;
2481 _sde_plane_set_danger_state(kms, true);
2482 }
2483
2484 return count;
2485}
2486
2487static const struct file_operations sde_plane_danger_enable = {
2488 .open = simple_open,
2489 .read = _sde_plane_danger_read,
2490 .write = _sde_plane_danger_write,
2491};
2492
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002493static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04002494{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002495 struct sde_plane *psde;
2496 struct sde_kms *kms;
2497 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04002498 const struct sde_sspp_sub_blks *sblk = 0;
2499 const struct sde_sspp_cfg *cfg = 0;
2500
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002501 if (!plane || !plane->dev) {
2502 SDE_ERROR("invalid arguments\n");
2503 return -EINVAL;
2504 }
2505
2506 priv = plane->dev->dev_private;
2507 if (!priv || !priv->kms) {
2508 SDE_ERROR("invalid KMS reference\n");
2509 return -EINVAL;
2510 }
2511
2512 kms = to_sde_kms(priv->kms);
2513 psde = to_sde_plane(plane);
2514
Clarence Ip4ce59322016-06-26 22:27:51 -04002515 if (psde && psde->pipe_hw)
2516 cfg = psde->pipe_hw->cap;
2517 if (cfg)
2518 sblk = cfg->sblk;
2519
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002520 if (!sblk)
2521 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04002522
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002523 /* create overall sub-directory for the pipe */
2524 psde->debugfs_root =
2525 debugfs_create_dir(psde->pipe_name,
2526 sde_debugfs_get_root(kms));
Clarence Ip4ce59322016-06-26 22:27:51 -04002527
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002528 if (!psde->debugfs_root)
2529 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04002530
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002531 /* don't error check these */
2532 debugfs_create_x32("features", 0644,
2533 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04002534
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002535 /* add register dump support */
2536 sde_debugfs_setup_regset32(&psde->debugfs_src,
2537 sblk->src_blk.base + cfg->base,
2538 sblk->src_blk.len,
2539 kms);
2540 sde_debugfs_create_regset32("src_blk", 0444,
2541 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04002542
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002543 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
2544 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
2545 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
2546 sblk->scaler_blk.base + cfg->base,
2547 sblk->scaler_blk.len,
2548 kms);
2549 sde_debugfs_create_regset32("scaler_blk", 0444,
2550 psde->debugfs_root,
2551 &psde->debugfs_scaler);
Clarence Ip4ce59322016-06-26 22:27:51 -04002552 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07002553
2554 if (cfg->features & BIT(SDE_SSPP_CSC) ||
2555 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
2556 sde_debugfs_setup_regset32(&psde->debugfs_csc,
2557 sblk->csc_blk.base + cfg->base,
2558 sblk->csc_blk.len,
2559 kms);
2560 sde_debugfs_create_regset32("csc_blk", 0444,
2561 psde->debugfs_root, &psde->debugfs_csc);
2562 }
2563
2564 debugfs_create_u32("xin_id",
2565 0444,
2566 psde->debugfs_root,
2567 (u32 *) &cfg->xin_id);
2568 debugfs_create_u32("clk_ctrl",
2569 0444,
2570 psde->debugfs_root,
2571 (u32 *) &cfg->clk_ctrl);
2572 debugfs_create_x32("creq_vblank",
2573 0644,
2574 psde->debugfs_root,
2575 (u32 *) &sblk->creq_vblank);
2576 debugfs_create_x32("danger_vblank",
2577 0644,
2578 psde->debugfs_root,
2579 (u32 *) &sblk->danger_vblank);
2580
2581 debugfs_create_file("disable_danger",
2582 0644,
2583 psde->debugfs_root,
2584 kms, &sde_plane_danger_enable);
2585
2586 return 0;
2587}
2588
2589static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
2590{
2591 struct sde_plane *psde;
2592
2593 if (!plane)
2594 return;
2595 psde = to_sde_plane(plane);
2596
2597 debugfs_remove_recursive(psde->debugfs_root);
2598}
2599#else
2600static int _sde_plane_init_debugfs(struct drm_plane *plane)
2601{
2602 return 0;
2603}
2604static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
2605{
2606}
2607#endif
2608
2609static int sde_plane_late_register(struct drm_plane *plane)
2610{
2611 return _sde_plane_init_debugfs(plane);
2612}
2613
2614static void sde_plane_early_unregister(struct drm_plane *plane)
2615{
2616 _sde_plane_destroy_debugfs(plane);
2617}
2618
2619static const struct drm_plane_funcs sde_plane_funcs = {
2620 .update_plane = drm_atomic_helper_update_plane,
2621 .disable_plane = drm_atomic_helper_disable_plane,
2622 .destroy = sde_plane_destroy,
2623 .set_property = sde_plane_set_property,
2624 .atomic_set_property = sde_plane_atomic_set_property,
2625 .atomic_get_property = sde_plane_atomic_get_property,
2626 .reset = sde_plane_reset,
2627 .atomic_duplicate_state = sde_plane_duplicate_state,
2628 .atomic_destroy_state = sde_plane_destroy_state,
2629 .late_register = sde_plane_late_register,
2630 .early_unregister = sde_plane_early_unregister,
2631};
2632
2633static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
2634 .prepare_fb = sde_plane_prepare_fb,
2635 .cleanup_fb = sde_plane_cleanup_fb,
2636 .atomic_check = sde_plane_atomic_check,
2637 .atomic_update = sde_plane_atomic_update,
2638};
2639
2640enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
2641{
2642 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
2643}
2644
2645bool is_sde_plane_virtual(struct drm_plane *plane)
2646{
2647 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04002648}
2649
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002650/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04002651struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002652 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002653 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002654{
2655 struct drm_plane *plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002656 const struct sde_format_extended *format_list;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002657 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002658 struct msm_drm_private *priv;
2659 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002660 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04002661 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002662
2663 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002664 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002665 goto exit;
2666 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002667
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002668 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04002669 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002670 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002671 goto exit;
2672 }
2673
2674 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002675 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002676 goto exit;
2677 }
2678 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002679
Clarence Ip4c1d9772016-06-26 09:35:38 -04002680 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002681 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002682 goto exit;
2683 }
2684
Clarence Ip4ce59322016-06-26 22:27:51 -04002685 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002686 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
2687 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002688 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002689 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002690 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002691 }
2692
Clarence Ip4c1d9772016-06-26 09:35:38 -04002693 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002694 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002695 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04002696 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002697 psde->is_virtual = (master_plane_id != 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002698
Clarence Ip4c1d9772016-06-26 09:35:38 -04002699 /* initialize underlying h/w driver */
2700 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
2701 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002702 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002703 ret = PTR_ERR(psde->pipe_hw);
2704 goto clean_plane;
2705 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002706 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002707 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002708 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002709
2710 /* cache features mask for later */
2711 psde->features = psde->pipe_hw->cap->features;
2712 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04002713 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002714 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04002715 goto clean_sspp;
2716 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002717
abeykun48f407a2016-08-25 12:06:44 -04002718 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
2719 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
2720 GFP_KERNEL);
2721 if (!psde->scaler3_cfg) {
2722 SDE_ERROR("[%u]failed to allocate scale struct\n",
2723 pipe);
2724 ret = -ENOMEM;
2725 goto clean_sspp;
2726 }
2727 }
2728
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002729 format_list = psde->pipe_sblk->format_list;
2730
2731 if (master_plane_id)
2732 format_list = plane_formats;
2733
2734 psde->nformats = sde_populate_formats(plane_formats,
2735 psde->formats,
2736 0,
2737 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002738
Clarence Ip4c1d9772016-06-26 09:35:38 -04002739 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002740 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002741 goto clean_sspp;
2742 }
2743
2744 if (psde->features & BIT(SDE_SSPP_CURSOR))
2745 type = DRM_PLANE_TYPE_CURSOR;
2746 else if (primary_plane)
2747 type = DRM_PLANE_TYPE_PRIMARY;
2748 else
2749 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002750 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
2751 psde->formats, psde->nformats,
2752 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002753 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04002754 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002755
Clarence Ip4c1d9772016-06-26 09:35:38 -04002756 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002757 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002758
Clarence Ipaa0faf42016-05-30 12:07:48 -04002759 msm_property_init(&psde->property_info, &plane->base, dev,
2760 priv->plane_property, psde->property_data,
2761 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
2762 sizeof(struct sde_plane_state));
2763
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002764 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002765
Clarence Ip4ce59322016-06-26 22:27:51 -04002766 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04002767 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04002768
Clarence Ip730e7192016-06-26 22:45:09 -04002769 mutex_init(&psde->lock);
2770
Dhaval Patel82c8dbc2017-02-18 23:15:10 -08002771 SDE_DEBUG("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002772 return plane;
2773
Clarence Ip4c1d9772016-06-26 09:35:38 -04002774clean_sspp:
2775 if (psde && psde->pipe_hw)
2776 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04002777
2778 if (psde && psde->scaler3_cfg)
2779 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002780clean_plane:
2781 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04002782exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002783 return ERR_PTR(ret);
2784}