blob: 143bbe9cb464cecd948876b8c4af7a6816d82477 [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"
26
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070027#include "sde_kms.h"
Clarence Ipae4e60c2016-06-26 22:44:04 -040028#include "sde_fence.h"
Clarence Ipc475b082016-06-26 09:27:23 -040029#include "sde_formats.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040030#include "sde_hw_sspp.h"
Alan Kwong1a00e4d2016-07-18 09:42:30 -040031#include "sde_trace.h"
Dhaval Patel48c76022016-09-01 17:51:23 -070032#include "sde_crtc.h"
Lloyd Atkinson8772e202016-09-26 17:52:16 -040033#include "sde_vbif.h"
Alan Kwong83285fb2016-10-21 20:51:17 -040034#include "sde_plane.h"
Benet Clarkd009b1d2016-06-27 14:45:59 -070035#include "sde_color_processing.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040036
Clarence Ip13a8cf42016-09-29 17:27:47 -040037#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
38 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
39
40#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
41 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
42
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040043#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
44#define PHASE_STEP_SHIFT 21
45#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
46#define PHASE_RESIDUAL 15
47
Clarence Ipe78efb72016-06-24 18:35:21 -040048#define SHARP_STRENGTH_DEFAULT 32
49#define SHARP_EDGE_THR_DEFAULT 112
50#define SHARP_SMOOTH_THR_DEFAULT 8
51#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040052
Clarence Ip5e2a9222016-06-26 22:38:24 -040053#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070054
Clarence Ipcae1bb62016-07-07 12:07:13 -040055#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
56
Clarence Ip282dad62016-09-27 17:07:35 -040057/* dirty bits for update function */
58#define SDE_PLANE_DIRTY_RECTS 0x1
59#define SDE_PLANE_DIRTY_FORMAT 0x2
60#define SDE_PLANE_DIRTY_SHARPEN 0x4
61#define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF
62
Alan Kwong1a00e4d2016-07-18 09:42:30 -040063/**
64 * enum sde_plane_qos - Different qos configurations for each pipe
65 *
66 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
67 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
68 * this configuration is mutually exclusive from VBLANK_CTRL.
69 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
70 */
71enum sde_plane_qos {
72 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
73 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
74 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
75};
76
Clarence Ip5fc00c52016-09-23 15:03:34 -040077/*
78 * struct sde_plane - local sde plane structure
79 * @csc_cfg: Decoded user configuration for csc
80 * @csc_usr_ptr: Points to csc_cfg if valid user config available
81 * @csc_ptr: Points to sde_csc_cfg structure to use for current
82 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070083struct sde_plane {
84 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040085
86 int mmu_id;
87
Clarence Ip730e7192016-06-26 22:45:09 -040088 struct mutex lock;
89
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040090 enum sde_sspp pipe;
91 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070092 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -040093 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040094
95 struct sde_hw_pipe *pipe_hw;
96 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -040097 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -040098 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040099 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400100 uint32_t color_fill;
101 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400102 bool is_rt_pipe;
Clarence Ip4ce59322016-06-26 22:27:51 -0400103
Clarence Ipb43d4592016-09-08 14:21:35 -0400104 struct sde_hw_pixel_ext pixel_ext;
105 bool pixel_ext_usr;
106
Clarence Ip373f8592016-05-26 00:58:42 -0400107 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400108 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400109 struct sde_csc_cfg *csc_ptr;
110
Clarence Ip4c1d9772016-06-26 09:35:38 -0400111 const struct sde_sspp_sub_blks *pipe_sblk;
112
Clarence Ip5e2a9222016-06-26 22:38:24 -0400113 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400114
Clarence Ipaa0faf42016-05-30 12:07:48 -0400115 struct msm_property_info property_info;
116 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700117 struct drm_property_blob *blob_info;
Clarence Ip730e7192016-06-26 22:45:09 -0400118
Clarence Ip4ce59322016-06-26 22:27:51 -0400119 /* debugfs related stuff */
120 struct dentry *debugfs_root;
121 struct sde_debugfs_regset32 debugfs_src;
122 struct sde_debugfs_regset32 debugfs_scaler;
123 struct sde_debugfs_regset32 debugfs_csc;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700124};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700125
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700126#define to_sde_plane(x) container_of(x, struct sde_plane, base)
127
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400128static bool sde_plane_enabled(struct drm_plane_state *state)
129{
Clarence Ipdbde9832016-06-26 09:48:36 -0400130 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400131}
132
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400133/**
134 * _sde_plane_calc_fill_level - calculate fill level of the given source format
135 * @plane: Pointer to drm plane
136 * @fmt: Pointer to source buffer format
137 * @src_wdith: width of source buffer
138 * Return: fill level corresponding to the source buffer/format or 0 if error
139 */
140static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
141 const struct sde_format *fmt, u32 src_width)
142{
143 struct sde_plane *psde;
144 u32 fixed_buff_size;
145 u32 total_fl;
146
147 if (!plane || !fmt) {
148 SDE_ERROR("invalid arguments\n");
149 return 0;
150 }
151
152 psde = to_sde_plane(plane);
153 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
154
155 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
156 if (fmt->chroma_sample == SDE_CHROMA_420) {
157 /* NV12 */
158 total_fl = (fixed_buff_size / 2) /
159 ((src_width + 32) * fmt->bpp);
160 } else {
161 /* non NV12 */
162 total_fl = (fixed_buff_size) /
163 ((src_width + 32) * fmt->bpp);
164 }
165 } else {
166 total_fl = (fixed_buff_size * 2) /
167 ((src_width + 32) * fmt->bpp);
168 }
169
170 SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n",
171 plane->base.id, psde->pipe - SSPP_VIG0,
172 fmt->base.pixel_format, src_width, total_fl);
173
174 return total_fl;
175}
176
177/**
178 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
179 * @total_fl: fill level
180 * Return: LUT setting corresponding to the fill level
181 */
182static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
183{
184 u32 qos_lut;
185
186 if (total_fl <= 4)
187 qos_lut = 0x1B;
188 else if (total_fl <= 5)
189 qos_lut = 0x5B;
190 else if (total_fl <= 6)
191 qos_lut = 0x15B;
192 else if (total_fl <= 7)
193 qos_lut = 0x55B;
194 else if (total_fl <= 8)
195 qos_lut = 0x155B;
196 else if (total_fl <= 9)
197 qos_lut = 0x555B;
198 else if (total_fl <= 10)
199 qos_lut = 0x1555B;
200 else if (total_fl <= 11)
201 qos_lut = 0x5555B;
202 else if (total_fl <= 12)
203 qos_lut = 0x15555B;
204 else
205 qos_lut = 0x55555B;
206
207 return qos_lut;
208}
209
210/**
211 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
212 * @total_fl: fill level
213 * Return: LUT setting corresponding to the fill level
214 */
215static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
216{
217 u32 qos_lut;
218
219 if (total_fl <= 10)
220 qos_lut = 0x1AAff;
221 else if (total_fl <= 11)
222 qos_lut = 0x5AAFF;
223 else if (total_fl <= 12)
224 qos_lut = 0x15AAFF;
225 else
226 qos_lut = 0x55AAFF;
227
228 return qos_lut;
229}
230
231/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400232 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
233 * @plane: Pointer to drm plane
234 * @fb: Pointer to framebuffer associated with the given plane
235 */
236static void _sde_plane_set_qos_lut(struct drm_plane *plane,
237 struct drm_framebuffer *fb)
238{
239 struct sde_plane *psde;
240 const struct sde_format *fmt = NULL;
241 u32 qos_lut;
242 u32 total_fl = 0;
243
244 if (!plane || !fb) {
245 SDE_ERROR("invalid arguments plane %d fb %d\n",
246 plane != 0, fb != 0);
247 return;
248 }
249
250 psde = to_sde_plane(plane);
251
252 if (!psde->pipe_hw || !psde->pipe_sblk) {
253 SDE_ERROR("invalid arguments\n");
254 return;
255 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
256 return;
257 }
258
259 if (!psde->is_rt_pipe) {
260 qos_lut = psde->pipe_sblk->creq_lut_nrt;
261 } else {
262 fmt = sde_get_sde_format_ext(
263 fb->pixel_format,
264 fb->modifier,
265 drm_format_num_planes(fb->pixel_format));
266 total_fl = _sde_plane_calc_fill_level(plane, fmt,
267 psde->pipe_cfg.src_rect.w);
268
269 if (SDE_FORMAT_IS_LINEAR(fmt))
270 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
271 else
272 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
273 }
274
275 psde->pipe_qos_cfg.creq_lut = qos_lut;
276
277 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
278 (fmt) ? fmt->base.pixel_format : 0,
279 psde->is_rt_pipe, total_fl, qos_lut,
280 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
281
282 SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n",
283 plane->base.id,
284 psde->pipe - SSPP_VIG0,
285 (fmt) ? fmt->base.pixel_format : 0,
286 psde->is_rt_pipe, total_fl, qos_lut);
287
288 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
289}
290
291/**
292 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
293 * @plane: Pointer to drm plane
294 * @fb: Pointer to framebuffer associated with the given plane
295 */
296static void _sde_plane_set_danger_lut(struct drm_plane *plane,
297 struct drm_framebuffer *fb)
298{
299 struct sde_plane *psde;
300 const struct sde_format *fmt = NULL;
301 u32 danger_lut, safe_lut;
302
303 if (!plane || !fb) {
304 SDE_ERROR("invalid arguments\n");
305 return;
306 }
307
308 psde = to_sde_plane(plane);
309
310 if (!psde->pipe_hw || !psde->pipe_sblk) {
311 SDE_ERROR("invalid arguments\n");
312 return;
313 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
314 return;
315 }
316
317 if (!psde->is_rt_pipe) {
318 danger_lut = psde->pipe_sblk->danger_lut_nrt;
319 safe_lut = psde->pipe_sblk->safe_lut_nrt;
320 } else {
321 fmt = sde_get_sde_format_ext(
322 fb->pixel_format,
323 fb->modifier,
324 drm_format_num_planes(fb->pixel_format));
325
326 if (SDE_FORMAT_IS_LINEAR(fmt)) {
327 danger_lut = psde->pipe_sblk->danger_lut_linear;
328 safe_lut = psde->pipe_sblk->safe_lut_linear;
329 } else {
330 danger_lut = psde->pipe_sblk->danger_lut_tile;
331 safe_lut = psde->pipe_sblk->safe_lut_tile;
332 }
333 }
334
335 psde->pipe_qos_cfg.danger_lut = danger_lut;
336 psde->pipe_qos_cfg.safe_lut = safe_lut;
337
338 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
339 (fmt) ? fmt->base.pixel_format : 0,
340 (fmt) ? fmt->fetch_mode : 0,
341 psde->pipe_qos_cfg.danger_lut,
342 psde->pipe_qos_cfg.safe_lut);
343
344 SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n",
345 plane->base.id,
346 psde->pipe - SSPP_VIG0,
347 fmt ? fmt->base.pixel_format : 0,
348 fmt ? fmt->fetch_mode : -1,
349 psde->pipe_qos_cfg.danger_lut,
350 psde->pipe_qos_cfg.safe_lut);
351
352 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
353 &psde->pipe_qos_cfg);
354}
355
356/**
357 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
358 * @plane: Pointer to drm plane
359 * @enable: true to enable QoS control
360 * @flags: QoS control mode (enum sde_plane_qos)
361 */
362static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
363 bool enable, u32 flags)
364{
365 struct sde_plane *psde;
366
367 if (!plane) {
368 SDE_ERROR("invalid arguments\n");
369 return;
370 }
371
372 psde = to_sde_plane(plane);
373
374 if (!psde->pipe_hw || !psde->pipe_sblk) {
375 SDE_ERROR("invalid arguments\n");
376 return;
377 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
378 return;
379 }
380
381 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
382 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
383 psde->pipe_qos_cfg.danger_vblank =
384 psde->pipe_sblk->danger_vblank;
385 psde->pipe_qos_cfg.vblank_en = enable;
386 }
387
388 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
389 /* this feature overrules previous VBLANK_CTRL */
390 psde->pipe_qos_cfg.vblank_en = false;
391 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
392 }
393
394 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
395 psde->pipe_qos_cfg.danger_safe_en = enable;
396
397 if (!psde->is_rt_pipe) {
398 psde->pipe_qos_cfg.vblank_en = false;
399 psde->pipe_qos_cfg.danger_safe_en = false;
400 }
401
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400402 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 -0400403 plane->base.id,
404 psde->pipe - SSPP_VIG0,
405 psde->pipe_qos_cfg.danger_safe_en,
406 psde->pipe_qos_cfg.vblank_en,
407 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400408 psde->pipe_qos_cfg.danger_vblank,
409 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400410
411 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
412 &psde->pipe_qos_cfg);
413}
414
Alan Kwongf0fd8512016-10-24 21:39:26 -0400415int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
416{
417 struct sde_plane *psde;
418 struct msm_drm_private *priv;
419 struct sde_kms *sde_kms;
420
421 if (!plane || !plane->dev) {
422 SDE_ERROR("invalid arguments\n");
423 return -EINVAL;
424 }
425
426 priv = plane->dev->dev_private;
427 if (!priv || !priv->kms) {
428 SDE_ERROR("invalid KMS reference\n");
429 return -EINVAL;
430 }
431
432 sde_kms = to_sde_kms(priv->kms);
433 psde = to_sde_plane(plane);
434
435 if (!psde->is_rt_pipe)
436 goto end;
437
438 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
439
440 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
441
442 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
443
444end:
445 return 0;
446}
447
Alan Kwong5d324e42016-07-28 22:56:18 -0400448/**
449 * _sde_plane_set_ot_limit - set OT limit for the given plane
450 * @plane: Pointer to drm plane
451 * @crtc: Pointer to drm crtc
452 */
453static void _sde_plane_set_ot_limit(struct drm_plane *plane,
454 struct drm_crtc *crtc)
455{
456 struct sde_plane *psde;
457 struct sde_vbif_set_ot_params ot_params;
458 struct msm_drm_private *priv;
459 struct sde_kms *sde_kms;
460
461 if (!plane || !plane->dev || !crtc) {
462 SDE_ERROR("invalid arguments plane %d crtc %d\n",
463 plane != 0, crtc != 0);
464 return;
465 }
466
467 priv = plane->dev->dev_private;
468 if (!priv || !priv->kms) {
469 SDE_ERROR("invalid KMS reference\n");
470 return;
471 }
472
473 sde_kms = to_sde_kms(priv->kms);
474 psde = to_sde_plane(plane);
475 if (!psde->pipe_hw) {
476 SDE_ERROR("invalid pipe reference\n");
477 return;
478 }
479
480 memset(&ot_params, 0, sizeof(ot_params));
481 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
482 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
483 ot_params.width = psde->pipe_cfg.src_rect.w;
484 ot_params.height = psde->pipe_cfg.src_rect.h;
485 ot_params.is_wfd = !psde->is_rt_pipe;
486 ot_params.frame_rate = crtc->mode.vrefresh;
487 ot_params.vbif_idx = VBIF_RT;
488 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
489 ot_params.rd = true;
490
491 sde_vbif_set_ot_limit(sde_kms, &ot_params);
492}
493
Clarence Ipcae1bb62016-07-07 12:07:13 -0400494/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400495static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400496 struct sde_plane_state *pstate, uint64_t fd)
497{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400498 if (!psde || !pstate) {
499 SDE_ERROR("invalid arg(s), plane %d state %d\n",
500 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400501 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400502 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400503
504 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400505 if (pstate->input_fence)
506 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400507
508 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400509 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400510
Clarence Ip13a8cf42016-09-29 17:27:47 -0400511 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400512}
513
Clarence Ipcae1bb62016-07-07 12:07:13 -0400514int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400515{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400516 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400517 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400518 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400519 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400520 int ret = -EINVAL;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400521
522 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700523 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400524 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400525 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400526 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400527 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400528 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400529 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400530
Clarence Ipcae1bb62016-07-07 12:07:13 -0400531 if (input_fence) {
Clarence Ip78a04ed2016-10-04 15:57:45 -0400532 prefix = sde_sync_get_name_prefix(input_fence);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400533 ret = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400534
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400535 SDE_EVT32(DRMID(plane), -ret, prefix);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400536
Clarence Ipcae1bb62016-07-07 12:07:13 -0400537 switch (ret) {
538 case 0:
Clarence Ip13a8cf42016-09-29 17:27:47 -0400539 SDE_DEBUG_PLANE(psde, "signaled\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400540 break;
541 case -ETIME:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400542 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
543 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400544 psde->is_error = true;
545 break;
546 default:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400547 SDE_ERROR_PLANE(psde, "error %d on %08X\n",
548 ret, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400549 psde->is_error = true;
550 break;
551 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400552 } else {
553 ret = 0;
554 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400555 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400556 return ret;
557}
558
Clarence Ip282dad62016-09-27 17:07:35 -0400559static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400560 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400561 struct sde_hw_pipe_cfg *pipe_cfg,
562 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400563{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400564 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400565 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400566
Clarence Ip13a8cf42016-09-29 17:27:47 -0400567 if (!plane || !pstate || !pipe_cfg || !fb) {
568 SDE_ERROR(
569 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
570 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400571 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400572 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400573
574 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400575 if (!psde->pipe_hw) {
576 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400577 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400578 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400579
Clarence Ipb6eb2362016-09-08 16:18:13 -0400580 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
581 if (ret == -EAGAIN)
582 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
583 else if (ret)
584 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
585 else if (psde->pipe_hw->ops.setup_sourceaddress)
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400586 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400587}
588
abeykun48f407a2016-08-25 12:06:44 -0400589static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
590 struct sde_plane_state *pstate)
591{
592 struct sde_hw_scaler3_cfg *cfg = psde->scaler3_cfg;
593 int ret = 0;
594
595 cfg->dir_lut = msm_property_get_blob(
596 &psde->property_info,
597 pstate->property_blobs, &cfg->dir_len,
598 PLANE_PROP_SCALER_LUT_ED);
599 cfg->cir_lut = msm_property_get_blob(
600 &psde->property_info,
601 pstate->property_blobs, &cfg->cir_len,
602 PLANE_PROP_SCALER_LUT_CIR);
603 cfg->sep_lut = msm_property_get_blob(
604 &psde->property_info,
605 pstate->property_blobs, &cfg->sep_len,
606 PLANE_PROP_SCALER_LUT_SEP);
607 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
608 ret = -ENODATA;
609 return ret;
610}
611
Clarence Ipcb410d42016-06-26 22:52:33 -0400612static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400613 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
614 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400615 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400616 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
617{
618}
619
Clarence Ipcb410d42016-06-26 22:52:33 -0400620/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400621 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400622 * @psde: Pointer to SDE plane object
623 * @src: Source size
624 * @dst: Destination size
625 * @phase_steps: Pointer to output array for phase steps
626 * @filter: Pointer to output array for filter type
627 * @fmt: Pointer to format definition
628 * @chroma_subsampling: Subsampling amount for chroma channel
629 *
630 * Returns: 0 on success
631 */
632static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400633 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400634 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400635 uint32_t chroma_subsampling)
636{
Clarence Ipcb410d42016-06-26 22:52:33 -0400637 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400638 SDE_ERROR(
639 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
640 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400641 return -EINVAL;
642 }
643
Clarence Ip4c1d9772016-06-26 09:35:38 -0400644 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400645 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400646 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400647 phase_steps[SDE_SSPP_COMP_1_2] =
648 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
649 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
650 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400651
652 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400653 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400654 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400655 (src <= dst) ? SDE_SCALE_FILTER_BIL :
656 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400657
Clarence Ipdbde9832016-06-26 09:48:36 -0400658 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400659 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400660 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
661 } else {
662 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
663 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400664 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400665 }
666 } else {
667 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400668 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
669 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
670 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400671 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400672 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400673}
674
Clarence Ipcb410d42016-06-26 22:52:33 -0400675/**
676 * _sde_plane_setup_pixel_ext - determine default pixel extension values
677 * @psde: Pointer to SDE plane object
678 * @src: Source size
679 * @dst: Destination size
680 * @decimated_src: Source size after decimation, if any
681 * @phase_steps: Pointer to output array for phase steps
682 * @out_src: Output array for pixel extension values
683 * @out_edge1: Output array for pixel extension first edge
684 * @out_edge2: Output array for pixel extension second edge
685 * @filter: Pointer to array for filter type
686 * @fmt: Pointer to format definition
687 * @chroma_subsampling: Subsampling amount for chroma channel
688 * @post_compare: Whether to chroma subsampled source size for comparisions
689 */
690static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400691 uint32_t src, uint32_t dst, uint32_t decimated_src,
692 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400693 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400694 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400695 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400696{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400697 int64_t edge1, edge2, caf;
698 uint32_t src_work;
699 int i, tmp;
700
Clarence Ipcb410d42016-06-26 22:52:33 -0400701 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400702 out_edge2 && filter && fmt) {
703 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400704 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400705 caf = PHASE_STEP_UNIT_SCALE;
706 else
707 caf = 0;
708
709 for (i = 0; i < SDE_MAX_PLANES; i++) {
710 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400711 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400712 src_work /= chroma_subsampling;
713 if (post_compare)
714 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400715 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400716 /* unity */
717 edge1 = 0;
718 edge2 = 0;
719 } else if (dst >= src) {
720 /* upscale */
721 edge1 = (1 << PHASE_RESIDUAL);
722 edge1 -= caf;
723 edge2 = (1 << PHASE_RESIDUAL);
724 edge2 += (dst - 1) * *(phase_steps + i);
725 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
726 edge2 += caf;
727 edge2 = -(edge2);
728 } else {
729 /* downscale */
730 edge1 = 0;
731 edge2 = (dst - 1) * *(phase_steps + i);
732 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
733 edge2 += *(phase_steps + i);
734 edge2 = -(edge2);
735 }
736
737 /* only enable CAF for luma plane */
738 caf = 0;
739
740 /* populate output arrays */
741 *(out_src + i) = src_work;
742
743 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400744 if (edge1 >= 0) {
745 tmp = (uint32_t)edge1;
746 tmp >>= PHASE_STEP_SHIFT;
747 *(out_edge1 + i) = -tmp;
748 } else {
749 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400750 *(out_edge1 + i) =
751 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
752 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400753 }
754 if (edge2 >= 0) {
755 tmp = (uint32_t)edge2;
756 tmp >>= PHASE_STEP_SHIFT;
757 *(out_edge2 + i) = -tmp;
758 } else {
759 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400760 *(out_edge2 + i) =
761 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
762 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400763 }
764 }
765 }
766}
767
Clarence Ip5fc00c52016-09-23 15:03:34 -0400768static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400769{
770 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
771 {
Clarence Ip373f8592016-05-26 00:58:42 -0400772 /* S15.16 format */
773 0x00012A00, 0x00000000, 0x00019880,
774 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
775 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400776 },
Clarence Ip373f8592016-05-26 00:58:42 -0400777 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400778 { 0xfff0, 0xff80, 0xff80,},
779 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400780 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400781 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400782 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400783 };
abeykun1c312f62016-08-26 09:47:12 -0400784 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
785 {
786 /* S15.16 format */
787 0x00012A00, 0x00000000, 0x00019880,
788 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
789 0x00012A00, 0x00020480, 0x00000000,
790 },
791 /* signed bias */
792 { 0xffc0, 0xfe00, 0xfe00,},
793 { 0x0, 0x0, 0x0,},
794 /* unsigned clamp */
795 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
796 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
797 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400798
Clarence Ip5fc00c52016-09-23 15:03:34 -0400799 if (!psde) {
800 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400801 return;
802 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400803
Clarence Ipcae1bb62016-07-07 12:07:13 -0400804 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400805 if (psde->csc_usr_ptr)
806 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400807 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
808 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400809 else
Clarence Ip373f8592016-05-26 00:58:42 -0400810 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400811
Clarence Ip13a8cf42016-09-29 17:27:47 -0400812 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400813 psde->csc_ptr->csc_mv[0],
814 psde->csc_ptr->csc_mv[1],
815 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400816}
817
Benet Clarkeb1b4462016-06-27 14:43:06 -0700818static void sde_color_process_plane_setup(struct drm_plane *plane)
819{
820 struct sde_plane *psde;
821 struct sde_plane_state *pstate;
822 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -0700823 struct drm_msm_memcol *memcol = NULL;
824 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -0700825
826 psde = to_sde_plane(plane);
827 pstate = to_sde_plane_state(plane->state);
828
829 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
830 if (psde->pipe_hw->ops.setup_pa_hue)
831 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
832 saturation = (uint32_t) sde_plane_get_property(pstate,
833 PLANE_PROP_SATURATION_ADJUST);
834 if (psde->pipe_hw->ops.setup_pa_sat)
835 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
836 value = (uint32_t) sde_plane_get_property(pstate,
837 PLANE_PROP_VALUE_ADJUST);
838 if (psde->pipe_hw->ops.setup_pa_val)
839 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
840 contrast = (uint32_t) sde_plane_get_property(pstate,
841 PLANE_PROP_CONTRAST_ADJUST);
842 if (psde->pipe_hw->ops.setup_pa_cont)
843 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -0700844
Benet Clarkd009b1d2016-06-27 14:45:59 -0700845 if (psde->pipe_hw->ops.setup_pa_memcolor) {
846 /* Skin memory color setup */
847 memcol = msm_property_get_blob(&psde->property_info,
848 pstate->property_blobs,
849 &memcol_sz,
850 PLANE_PROP_SKIN_COLOR);
851 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
852 MEMCOLOR_SKIN, memcol);
853
854 /* Sky memory color setup */
855 memcol = msm_property_get_blob(&psde->property_info,
856 pstate->property_blobs,
857 &memcol_sz,
858 PLANE_PROP_SKY_COLOR);
859 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
860 MEMCOLOR_SKY, memcol);
861
862 /* Foliage memory color setup */
863 memcol = msm_property_get_blob(&psde->property_info,
864 pstate->property_blobs,
865 &memcol_sz,
866 PLANE_PROP_FOLIAGE_COLOR);
867 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
868 MEMCOLOR_FOLIAGE, memcol);
869 }
870}
Benet Clarkeb1b4462016-06-27 14:43:06 -0700871
Clarence Ipcb410d42016-06-26 22:52:33 -0400872static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400873 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -0400874 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700875{
Clarence Ipb43d4592016-09-08 14:21:35 -0400876 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -0400877 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400878
Clarence Ipb43d4592016-09-08 14:21:35 -0400879 if (!psde || !fmt) {
880 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
881 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400882 return;
Clarence Ipb43d4592016-09-08 14:21:35 -0400883 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400884
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400885 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400886
Clarence Ipdedbba92016-09-27 17:43:10 -0400887 psde->pipe_cfg.horz_decimation =
888 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
889 psde->pipe_cfg.vert_decimation =
890 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400891
892 /* don't chroma subsample if decimating */
893 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400894 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400895 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400896 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400897
Clarence Ip5e2a9222016-06-26 22:38:24 -0400898 /* update scaler */
899 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -0400900 int error;
901
902 error = _sde_plane_setup_scaler3_lut(psde, pstate);
903 if (error || !psde->pixel_ext_usr) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400904 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -0400905 _sde_plane_setup_scaler3(psde,
906 psde->pipe_cfg.src_rect.w,
907 psde->pipe_cfg.src_rect.h,
908 psde->pipe_cfg.dst_rect.w,
909 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -0400910 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400911 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400912 }
Clarence Ipb43d4592016-09-08 14:21:35 -0400913 } else if (!psde->pixel_ext_usr) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500914 uint32_t deci_dim, i;
915
Clarence Ipb43d4592016-09-08 14:21:35 -0400916 /* calculate default configuration for QSEED2 */
917 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400918
Clarence Ip13a8cf42016-09-29 17:27:47 -0400919 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500920 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
921 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -0400922 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500923 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -0400924 psde->pipe_cfg.dst_rect.w,
925 pe->phase_step_x,
926 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400927
Clarence Ipdbde9832016-06-26 09:48:36 -0400928 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500929 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -0400930 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500931 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400932 pe->phase_step_x,
933 pe->roi_w,
934 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -0400935 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400936 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400937
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500938 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400939 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500940 _sde_plane_setup_scaler2(psde,
941 deci_dim,
942 psde->pipe_cfg.dst_rect.h,
943 pe->phase_step_y,
944 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -0400945 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500946 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400947 pe->phase_step_y,
948 pe->roi_h,
949 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -0400950 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400951 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400952
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400953 for (i = 0; i < SDE_MAX_PLANES; i++) {
954 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400955 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400956 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400957 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400958
959 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400960 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400961 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400962 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400963
964 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400965 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400966 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400967 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400968
969 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400970 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400971 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400972 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400973 }
974 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400975}
976
Clarence Ipcae1bb62016-07-07 12:07:13 -0400977/**
978 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -0400979 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -0400980 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
981 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
982 * Returns: 0 on success
983 */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400984static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -0400985 uint32_t color, uint32_t alpha)
986{
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400987 const struct sde_format *fmt;
Clarence Ipcb410d42016-06-26 22:52:33 -0400988
Clarence Ip13a8cf42016-09-29 17:27:47 -0400989 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700990 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400991 return -EINVAL;
992 }
993
Clarence Ipcb410d42016-06-26 22:52:33 -0400994 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400995 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400996 return -EINVAL;
997 }
998
Clarence Ip13a8cf42016-09-29 17:27:47 -0400999 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001000
Clarence Ipcb410d42016-06-26 22:52:33 -04001001 /*
1002 * select fill format to match user property expectation,
1003 * h/w only supports RGB variants
1004 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001005 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001006
1007 /* update sspp */
1008 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1009 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
1010 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
1011
1012 /* override scaler/decimation if solid fill */
1013 psde->pipe_cfg.src_rect.x = 0;
1014 psde->pipe_cfg.src_rect.y = 0;
1015 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1016 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
1017
1018 _sde_plane_setup_scaler(psde, fmt, 0);
1019
1020 if (psde->pipe_hw->ops.setup_format)
1021 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
1022 fmt, SDE_SSPP_SOLID_FILL);
1023
1024 if (psde->pipe_hw->ops.setup_rects)
1025 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -04001026 &psde->pipe_cfg, &psde->pixel_ext,
1027 psde->scaler3_cfg);
Clarence Ipcb410d42016-06-26 22:52:33 -04001028 }
1029
1030 return 0;
1031}
1032
1033static int _sde_plane_mode_set(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001034 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -04001035{
Clarence Ipc47a0692016-10-11 10:54:17 -04001036 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -04001037 struct sde_plane *psde;
1038 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001039 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001040 struct drm_crtc *crtc;
1041 struct drm_framebuffer *fb;
1042 struct sde_rect src, dst;
1043 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001044 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -04001045
Clarence Ip13a8cf42016-09-29 17:27:47 -04001046 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -04001047 SDE_ERROR("invalid plane\n");
1048 return -EINVAL;
1049 } else if (!plane->state) {
1050 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001051 return -EINVAL;
1052 }
1053
1054 psde = to_sde_plane(plane);
1055 pstate = to_sde_plane_state(plane->state);
Clarence Ipcb410d42016-06-26 22:52:33 -04001056
Dhaval Patel47302cf2016-08-18 15:04:28 -07001057 crtc = state->crtc;
1058 fb = state->fb;
1059 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001060 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
1061 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -07001062 return -EINVAL;
1063 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001064 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001065 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -04001066
Clarence Ip282dad62016-09-27 17:07:35 -04001067 /* determine what needs to be refreshed */
1068 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
1069 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001070 case PLANE_PROP_SCALER_V1:
abeykun48f407a2016-08-25 12:06:44 -04001071 case PLANE_PROP_SCALER_V2:
Clarence Ipdedbba92016-09-27 17:43:10 -04001072 case PLANE_PROP_H_DECIMATE:
1073 case PLANE_PROP_V_DECIMATE:
1074 case PLANE_PROP_SRC_CONFIG:
1075 case PLANE_PROP_ZPOS:
Clarence Ip282dad62016-09-27 17:07:35 -04001076 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1077 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001078 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04001079 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
1080 break;
1081 case PLANE_PROP_COLOR_FILL:
1082 /* potentially need to refresh everything */
1083 pstate->dirty = SDE_PLANE_DIRTY_ALL;
1084 break;
1085 case PLANE_PROP_ROTATION:
1086 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
1087 break;
Clarence Ip282dad62016-09-27 17:07:35 -04001088 case PLANE_PROP_INFO:
1089 case PLANE_PROP_ALPHA:
1090 case PLANE_PROP_INPUT_FENCE:
1091 case PLANE_PROP_BLEND_OP:
1092 /* no special action required */
1093 break;
1094 default:
1095 /* unknown property, refresh everything */
1096 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
1097 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
1098 break;
1099 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001100 }
1101
Clarence Ip282dad62016-09-27 17:07:35 -04001102 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
1103 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -04001104
1105 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
1106
Clarence Ip282dad62016-09-27 17:07:35 -04001107 /* early out if nothing dirty */
1108 if (!pstate->dirty)
1109 return 0;
1110 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001111
Clarence Ip0d0e96d2016-10-24 18:13:13 -04001112 psde->is_rt_pipe = sde_crtc_is_rt(crtc);
Clarence Ip282dad62016-09-27 17:07:35 -04001113 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1114
1115 /* update roi config */
1116 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
1117 POPULATE_RECT(&src, state->src_x, state->src_y,
1118 state->src_w, state->src_h, q16_data);
1119 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
1120 state->crtc_w, state->crtc_h, !q16_data);
1121
Clarence Ip13a8cf42016-09-29 17:27:47 -04001122 SDE_DEBUG_PLANE(psde,
1123 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001124 fb->base.id, src.x, src.y, src.w, src.h,
1125 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
1126 drm_get_format_name(fmt->base.pixel_format),
1127 SDE_FORMAT_IS_UBWC(fmt));
1128
1129 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
1130 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001131 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001132 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
1133 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
1134 src.h /= 2;
1135 src.y = DIV_ROUND_UP(src.y, 2);
1136 src.y &= ~0x1;
1137 }
1138
1139 psde->pipe_cfg.src_rect = src;
1140 psde->pipe_cfg.dst_rect = dst;
1141
1142 /* check for color fill */
1143 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
1144 PLANE_PROP_COLOR_FILL);
1145 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
1146 /* skip remaining processing on color fill */
1147 pstate->dirty = 0x0;
1148 } else if (psde->pipe_hw->ops.setup_rects) {
1149 _sde_plane_setup_scaler(psde, fmt, pstate);
1150
Clarence Ip282dad62016-09-27 17:07:35 -04001151 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -04001152 &psde->pipe_cfg, &psde->pixel_ext,
1153 psde->scaler3_cfg);
Clarence Ip282dad62016-09-27 17:07:35 -04001154 }
Dhaval Patel48c76022016-09-01 17:51:23 -07001155 }
1156
Clarence Ip282dad62016-09-27 17:07:35 -04001157 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
1158 psde->pipe_hw->ops.setup_format) {
1159 src_flags = 0x0;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001160 SDE_DEBUG_PLANE(psde, "rotation 0x%llX\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001161 sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
1162 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1163 BIT(DRM_REFLECT_X))
1164 src_flags |= SDE_SSPP_FLIP_LR;
1165 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1166 BIT(DRM_REFLECT_Y))
1167 src_flags |= SDE_SSPP_FLIP_UD;
1168
1169 /* update format */
1170 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags);
1171
1172 /* update csc */
1173 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04001174 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04001175 else
1176 psde->csc_ptr = 0;
1177 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001178
Benet Clarkeb1b4462016-06-27 14:43:06 -07001179 sde_color_process_plane_setup(plane);
1180
Clarence Ipe78efb72016-06-24 18:35:21 -04001181 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04001182 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
1183 psde->pipe_hw->ops.setup_sharpening) {
1184 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
1185 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
1186 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
1187 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04001188
Clarence Ipe78efb72016-06-24 18:35:21 -04001189 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04001190 &psde->sharp_cfg);
1191 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001192
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001193 _sde_plane_set_qos_lut(plane, fb);
1194 _sde_plane_set_danger_lut(plane, fb);
1195
Alan Kwong5d324e42016-07-28 22:56:18 -04001196 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001197 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04001198 _sde_plane_set_ot_limit(plane, crtc);
1199 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001200
Clarence Ip282dad62016-09-27 17:07:35 -04001201 /* clear dirty */
1202 pstate->dirty = 0x0;
1203
Clarence Ip5e2a9222016-06-26 22:38:24 -04001204 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001205}
1206
1207static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001208 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001209{
1210 struct drm_framebuffer *fb = new_state->fb;
1211 struct sde_plane *psde = to_sde_plane(plane);
1212
1213 if (!new_state->fb)
1214 return 0;
1215
Clarence Ip13a8cf42016-09-29 17:27:47 -04001216 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001217 return msm_framebuffer_prepare(fb, psde->mmu_id);
1218}
1219
1220static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001221 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001222{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001223 struct drm_framebuffer *fb = old_state ? old_state->fb : NULL;
1224 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001225
1226 if (!fb)
1227 return;
1228
Clarence Ip13a8cf42016-09-29 17:27:47 -04001229 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001230 msm_framebuffer_cleanup(fb, psde->mmu_id);
1231}
1232
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001233static void _sde_plane_atomic_check_mode_changed(struct sde_plane *psde,
1234 struct drm_plane_state *state,
1235 struct drm_plane_state *old_state)
1236{
1237 struct sde_plane_state *pstate = to_sde_plane_state(state);
1238
Dhaval Patel47302cf2016-08-18 15:04:28 -07001239 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04001240 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001241 return;
1242
Clarence Ip282dad62016-09-27 17:07:35 -04001243 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
1244 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001245 SDE_DEBUG_PLANE(psde,
1246 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001247 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001248 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001249 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001250 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001251 } else if (state->src_w != old_state->src_w ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07001252 state->src_h != old_state->src_h ||
1253 state->src_x != old_state->src_x ||
1254 state->src_y != old_state->src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001255 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001256 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001257 } else if (state->crtc_w != old_state->crtc_w ||
1258 state->crtc_h != old_state->crtc_h ||
1259 state->crtc_x != old_state->crtc_x ||
1260 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001261 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001262 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1263 }
1264
1265 if (!state->fb || !old_state->fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001266 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001267 } else if (state->fb->pixel_format != old_state->fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001268 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001269 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001270 } else {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001271 uint64_t *new_mods = state->fb->modifier;
1272 uint64_t *old_mods = old_state->fb->modifier;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001273 uint32_t *new_pitches = state->fb->pitches;
1274 uint32_t *old_pitches = old_state->fb->pitches;
1275 uint32_t *new_offset = state->fb->offsets;
1276 uint32_t *old_offset = old_state->fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001277 int i;
1278
1279 for (i = 0; i < ARRAY_SIZE(state->fb->modifier); i++) {
1280 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001281 SDE_DEBUG_PLANE(psde,
1282 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001283 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001284 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001285 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1286 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001287 break;
1288 }
1289 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001290 for (i = 0; i < ARRAY_SIZE(state->fb->pitches); i++) {
1291 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001292 SDE_DEBUG_PLANE(psde,
1293 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001294 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001295 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001296 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001297 break;
1298 }
1299 }
Dhaval Patel47302cf2016-08-18 15:04:28 -07001300 for (i = 0; i < ARRAY_SIZE(state->fb->offsets); i++) {
1301 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001302 SDE_DEBUG_PLANE(psde,
1303 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001304 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001305 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001306 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1307 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001308 break;
1309 }
1310 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001311 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001312}
1313
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001314static int sde_plane_atomic_check(struct drm_plane *plane,
1315 struct drm_plane_state *state)
1316{
Clarence Ipdedbba92016-09-27 17:43:10 -04001317 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04001318 struct sde_plane *psde;
1319 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001320 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001321 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04001322 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001323 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
1324 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04001325
1326 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001327 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1328 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04001329 ret = -EINVAL;
1330 goto exit;
1331 }
1332
1333 psde = to_sde_plane(plane);
1334 pstate = to_sde_plane_state(state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001335
1336 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001337 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001338 ret = -EINVAL;
1339 goto exit;
1340 }
1341
Clarence Ipdedbba92016-09-27 17:43:10 -04001342 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1343 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04001344
1345 /* src values are in Q16 fixed point, convert to integer */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001346 POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w,
1347 state->src_h, q16_data);
1348 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
1349 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04001350
Dhaval Patel47302cf2016-08-18 15:04:28 -07001351 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
1352 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04001353
Dhaval Patel47302cf2016-08-18 15:04:28 -07001354 max_upscale = psde->pipe_sblk->maxupscale;
1355 max_downscale = psde->pipe_sblk->maxdwnscale;
1356 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04001357
Clarence Ip13a8cf42016-09-29 17:27:47 -04001358 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001359 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001360
Dhaval Patel47302cf2016-08-18 15:04:28 -07001361 if (!sde_plane_enabled(state))
1362 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04001363
Dhaval Patel47302cf2016-08-18 15:04:28 -07001364 fmt = to_sde_format(msm_framebuffer_format(state->fb));
1365
1366 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
1367
1368 if (SDE_FORMAT_IS_YUV(fmt) &&
1369 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04001370 !(psde->features & (BIT(SDE_SSPP_CSC)
1371 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001372 SDE_ERROR_PLANE(psde,
1373 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07001374 ret = -EINVAL;
1375
1376 /* check src bounds */
1377 } else if (state->fb->width > MAX_IMG_WIDTH ||
1378 state->fb->height > MAX_IMG_HEIGHT ||
1379 src.w < min_src_size || src.h < min_src_size ||
1380 CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) ||
1381 CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001382 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001383 src.x, src.y, src.w, src.h);
1384 ret = -E2BIG;
1385
1386 /* valid yuv image */
1387 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
1388 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001389 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001390 src.x, src.y, src.w, src.h);
1391 ret = -EINVAL;
1392
1393 /* min dst support */
1394 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001395 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001396 dst.x, dst.y, dst.w, dst.h);
1397 ret = -EINVAL;
1398
1399 /* decimation validation */
1400 } else if (deci_w || deci_h) {
1401 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
1402 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001403 SDE_ERROR_PLANE(psde,
1404 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001405 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001406 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001407 SDE_ERROR_PLANE(psde,
1408 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001409 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001410 }
1411
Dhaval Patel47302cf2016-08-18 15:04:28 -07001412 } else if (!(psde->features & SDE_SSPP_SCALER) &&
1413 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001414 SDE_ERROR_PLANE(psde,
1415 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001416 src.w, src.h, dst.w, dst.h);
1417 ret = -EINVAL;
1418
1419 /* check decimated source width */
1420 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001421 SDE_ERROR_PLANE(psde,
1422 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001423 src.w, src_deci_w, max_linewidth);
1424 ret = -E2BIG;
1425
1426 /* check max scaler capability */
1427 } else if (((src_deci_w * max_upscale) < dst.w) ||
1428 ((src_deci_h * max_upscale) < dst.h) ||
1429 ((dst.w * max_downscale) < src_deci_w) ||
1430 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001431 SDE_ERROR_PLANE(psde,
1432 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001433 src_deci_w, src_deci_h, dst.w, dst.h);
1434 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001435 }
1436
Dhaval Patel47302cf2016-08-18 15:04:28 -07001437modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001438 if (!ret)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001439 _sde_plane_atomic_check_mode_changed(psde, state, plane->state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001440exit:
1441 return ret;
1442}
1443
Clarence Ipcae1bb62016-07-07 12:07:13 -04001444/**
1445 * sde_plane_flush - final plane operations before commit flush
1446 * @plane: Pointer to drm plane structure
1447 */
1448void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04001449{
Clarence Ipcae1bb62016-07-07 12:07:13 -04001450 struct sde_plane *psde;
1451
Clarence Ip13a8cf42016-09-29 17:27:47 -04001452 if (!plane) {
1453 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001454 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001455 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04001456
1457 psde = to_sde_plane(plane);
1458
1459 /*
1460 * These updates have to be done immediately before the plane flush
1461 * timing, and may not be moved to the atomic_update/mode_set functions.
1462 */
1463 if (psde->is_error)
1464 /* force white frame with 0% alpha pipe output on error */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001465 _sde_plane_color_fill(psde, 0xFFFFFF, 0x0);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001466 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
1467 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001468 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001469 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
1470 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
1471
1472 /* flag h/w flush complete */
1473 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04001474 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001475}
1476
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001477static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04001478 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001479{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001480 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001481 struct drm_plane_state *state;
1482 struct sde_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001483
Clarence Ip13a8cf42016-09-29 17:27:47 -04001484 if (!plane) {
1485 SDE_ERROR("invalid plane\n");
1486 return;
1487 } else if (!plane->state) {
1488 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04001489 return;
1490 }
1491
Clarence Ip13a8cf42016-09-29 17:27:47 -04001492 psde = to_sde_plane(plane);
1493 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001494 state = plane->state;
1495 pstate = to_sde_plane_state(state);
1496
Clarence Ip13a8cf42016-09-29 17:27:47 -04001497 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001498
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001499 if (!sde_plane_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04001500 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001501 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001502 int ret;
1503
Dhaval Patel47302cf2016-08-18 15:04:28 -07001504 ret = _sde_plane_mode_set(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001505 /* atomic_check should have ensured that this doesn't fail */
1506 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001507 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001508}
1509
Dhaval Patel47302cf2016-08-18 15:04:28 -07001510
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001511/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001512static void _sde_plane_install_properties(struct drm_plane *plane,
Clarence Ipc47a0692016-10-11 10:54:17 -04001513 struct sde_mdss_cfg *catalog)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001514{
Clarence Ip5e2a9222016-06-26 22:38:24 -04001515 static const struct drm_prop_enum_list e_blend_op[] = {
1516 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
1517 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
1518 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
1519 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
1520 };
1521 static const struct drm_prop_enum_list e_src_config[] = {
1522 {SDE_DRM_DEINTERLACE, "deinterlace"}
1523 };
Clarence Ipea3d6262016-07-15 16:20:11 -04001524 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07001525 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001526 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04001527 int zpos_max = 255;
1528 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001529 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001530
Clarence Ip13a8cf42016-09-29 17:27:47 -04001531 if (!plane || !psde) {
1532 SDE_ERROR("invalid plane\n");
1533 return;
1534 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
1535 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
1536 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001537 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04001538 } else if (!catalog) {
1539 SDE_ERROR("invalid catalog\n");
1540 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001541 }
1542
Clarence Ipc47a0692016-10-11 10:54:17 -04001543 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04001544 if (catalog->mixer_count && catalog->mixer &&
1545 catalog->mixer[0].sblk->maxblendstages) {
1546 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
1547 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
1548 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
1549 }
Clarence Ipc47a0692016-10-11 10:54:17 -04001550 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
1551 /* reserve zpos == 0 for primary planes */
1552 zpos_def = drm_plane_index(plane) + 1;
1553 }
1554
1555 msm_property_install_range(&psde->property_info, "zpos",
1556 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001557
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001558 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001559 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001560
Dhaval Patel47302cf2016-08-18 15:04:28 -07001561 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001562 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07001563 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001564
Clarence Ipdedbba92016-09-27 17:43:10 -04001565 if (psde->pipe_sblk->maxhdeciexp) {
1566 msm_property_install_range(&psde->property_info, "h_decimate",
1567 0x0, 0, psde->pipe_sblk->maxhdeciexp, 0,
1568 PLANE_PROP_H_DECIMATE);
1569 }
1570
1571 if (psde->pipe_sblk->maxvdeciexp) {
1572 msm_property_install_range(&psde->property_info, "v_decimate",
1573 0x0, 0, psde->pipe_sblk->maxvdeciexp, 0,
1574 PLANE_PROP_V_DECIMATE);
1575 }
1576
abeykun48f407a2016-08-25 12:06:44 -04001577 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
1578 msm_property_install_volatile_range(&psde->property_info,
1579 "scaler_v2", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
1580 msm_property_install_blob(&psde->property_info, "lut_ed", 0,
1581 PLANE_PROP_SCALER_LUT_ED);
1582 msm_property_install_blob(&psde->property_info, "lut_cir", 0,
1583 PLANE_PROP_SCALER_LUT_CIR);
1584 msm_property_install_blob(&psde->property_info, "lut_sep", 0,
1585 PLANE_PROP_SCALER_LUT_SEP);
1586 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001587 msm_property_install_volatile_range(&psde->property_info,
1588 "scaler_v1", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V1);
1589 }
1590
Clarence Ip5fc00c52016-09-23 15:03:34 -04001591 if (psde->features & BIT(SDE_SSPP_CSC)) {
1592 msm_property_install_volatile_range(&psde->property_info,
1593 "csc_v1", 0x0, 0, ~0, 0, PLANE_PROP_CSC_V1);
1594 }
1595
Benet Clarkeb1b4462016-06-27 14:43:06 -07001596 if (psde->features & BIT(SDE_SSPP_HSIC)) {
1597 snprintf(feature_name, sizeof(feature_name), "%s%d",
1598 "SDE_SSPP_HUE_V",
1599 psde->pipe_sblk->hsic_blk.version >> 16);
1600 msm_property_install_range(&psde->property_info,
1601 feature_name, 0, 0, 0xFFFFFFFF, 0,
1602 PLANE_PROP_HUE_ADJUST);
1603 snprintf(feature_name, sizeof(feature_name), "%s%d",
1604 "SDE_SSPP_SATURATION_V",
1605 psde->pipe_sblk->hsic_blk.version >> 16);
1606 msm_property_install_range(&psde->property_info,
1607 feature_name, 0, 0, 0xFFFFFFFF, 0,
1608 PLANE_PROP_SATURATION_ADJUST);
1609 snprintf(feature_name, sizeof(feature_name), "%s%d",
1610 "SDE_SSPP_VALUE_V",
1611 psde->pipe_sblk->hsic_blk.version >> 16);
1612 msm_property_install_range(&psde->property_info,
1613 feature_name, 0, 0, 0xFFFFFFFF, 0,
1614 PLANE_PROP_VALUE_ADJUST);
1615 snprintf(feature_name, sizeof(feature_name), "%s%d",
1616 "SDE_SSPP_CONTRAST_V",
1617 psde->pipe_sblk->hsic_blk.version >> 16);
1618 msm_property_install_range(&psde->property_info,
1619 feature_name, 0, 0, 0xFFFFFFFF, 0,
1620 PLANE_PROP_CONTRAST_ADJUST);
1621 }
1622
Clarence Ip5e2a9222016-06-26 22:38:24 -04001623 /* standard properties */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001624 msm_property_install_rotation(&psde->property_info,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001625 (unsigned int) (BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y)),
1626 PLANE_PROP_ROTATION);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001627
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001628 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001629 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001630
Dhaval Patel47302cf2016-08-18 15:04:28 -07001631 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
1632 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
1633
1634 if (psde->pipe_hw->ops.setup_solidfill)
1635 msm_property_install_range(&psde->property_info, "color_fill",
1636 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
1637
Dhaval Patel4e574842016-08-23 15:11:37 -07001638 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001639 if (!info) {
1640 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07001641 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001642 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001643
1644 msm_property_install_blob(&psde->property_info, "capabilities",
1645 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
1646 sde_kms_info_reset(info);
1647
Clarence Ipea3d6262016-07-15 16:20:11 -04001648 format_list = psde->pipe_sblk->format_list;
1649 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04001650 sde_kms_info_start(info, "pixel_formats");
1651 while (format_list->fourcc_format) {
1652 sde_kms_info_append_format(info,
1653 format_list->fourcc_format,
1654 format_list->modifier);
1655 ++format_list;
1656 }
1657 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04001658 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001659
1660 sde_kms_info_add_keyint(info, "max_linewidth",
1661 psde->pipe_sblk->maxlinewidth);
1662 sde_kms_info_add_keyint(info, "max_upscale",
1663 psde->pipe_sblk->maxupscale);
1664 sde_kms_info_add_keyint(info, "max_downscale",
1665 psde->pipe_sblk->maxdwnscale);
1666 sde_kms_info_add_keyint(info, "max_horizontal_deci",
1667 psde->pipe_sblk->maxhdeciexp);
1668 sde_kms_info_add_keyint(info, "max_vertical_deci",
1669 psde->pipe_sblk->maxvdeciexp);
1670 msm_property_set_blob(&psde->property_info, &psde->blob_info,
1671 info->data, info->len, PLANE_PROP_INFO);
1672
1673 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07001674
1675 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
1676 snprintf(feature_name, sizeof(feature_name), "%s%d",
1677 "SDE_SSPP_SKIN_COLOR_V",
1678 psde->pipe_sblk->memcolor_blk.version >> 16);
1679 msm_property_install_blob(&psde->property_info, feature_name, 0,
1680 PLANE_PROP_SKIN_COLOR);
1681 snprintf(feature_name, sizeof(feature_name), "%s%d",
1682 "SDE_SSPP_SKY_COLOR_V",
1683 psde->pipe_sblk->memcolor_blk.version >> 16);
1684 msm_property_install_blob(&psde->property_info, feature_name, 0,
1685 PLANE_PROP_SKY_COLOR);
1686 snprintf(feature_name, sizeof(feature_name), "%s%d",
1687 "SDE_SSPP_FOLIAGE_COLOR_V",
1688 psde->pipe_sblk->memcolor_blk.version >> 16);
1689 msm_property_install_blob(&psde->property_info, feature_name, 0,
1690 PLANE_PROP_FOLIAGE_COLOR);
1691 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001692}
1693
Clarence Ip5fc00c52016-09-23 15:03:34 -04001694static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
1695{
1696 struct sde_drm_csc_v1 csc_v1;
1697 int i;
1698
1699 if (!psde) {
1700 SDE_ERROR("invalid plane\n");
1701 return;
1702 }
1703
1704 psde->csc_usr_ptr = NULL;
1705 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001706 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001707 return;
1708 }
1709
1710 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001711 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001712 return;
1713 }
1714
Clarence Ipb43d4592016-09-08 14:21:35 -04001715 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001716 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
1717 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
1718 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
1719 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
1720 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
1721 }
1722 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
1723 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
1724 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
1725 }
1726 psde->csc_usr_ptr = &psde->csc_cfg;
1727}
1728
Clarence Ipb43d4592016-09-08 14:21:35 -04001729static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
1730{
1731 struct sde_drm_scaler_v1 scale_v1;
1732 struct sde_hw_pixel_ext *pe;
1733 int i;
1734
1735 if (!psde) {
1736 SDE_ERROR("invalid plane\n");
1737 return;
1738 }
1739
1740 psde->pixel_ext_usr = false;
1741 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001742 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001743 return;
1744 }
1745
1746 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001747 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001748 return;
1749 }
1750
1751 /* populate from user space */
1752 pe = &(psde->pixel_ext);
1753 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1754 for (i = 0; i < SDE_MAX_PLANES; i++) {
1755 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
1756 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
1757 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
1758 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
1759
1760 pe->horz_filter[i] = scale_v1.horz_filter[i];
1761 pe->vert_filter[i] = scale_v1.vert_filter[i];
1762 }
1763 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05001764 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
1765 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
1766 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
1767 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
1768 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04001769
abeykun41060122016-11-28 13:02:01 -05001770 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
1771 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
1772 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
1773 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
1774 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04001775 }
abeykun41060122016-11-28 13:02:01 -05001776
Clarence Ipb43d4592016-09-08 14:21:35 -04001777 psde->pixel_ext_usr = true;
1778
Clarence Ip13a8cf42016-09-29 17:27:47 -04001779 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001780}
1781
abeykun48f407a2016-08-25 12:06:44 -04001782static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
1783 struct sde_plane_state *pstate, void *usr)
1784{
1785 struct sde_drm_scaler_v2 scale_v2;
1786 struct sde_hw_pixel_ext *pe;
1787 int i;
1788 struct sde_hw_scaler3_cfg *cfg;
1789
1790 if (!psde) {
1791 SDE_ERROR("invalid plane\n");
1792 return;
1793 }
1794
1795 cfg = psde->scaler3_cfg;
1796 psde->pixel_ext_usr = false;
1797 if (!usr) {
1798 SDE_DEBUG_PLANE(psde, "scale data removed\n");
1799 return;
1800 }
1801
1802 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
1803 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
1804 return;
1805 }
1806
1807 /* populate from user space */
1808 pe = &(psde->pixel_ext);
1809 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1810 cfg->enable = scale_v2.enable;
1811 cfg->dir_en = scale_v2.dir_en;
1812 for (i = 0; i < SDE_MAX_PLANES; i++) {
1813 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
1814 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
1815 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
1816 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
1817
1818 cfg->preload_x[i] = scale_v2.preload_x[i];
1819 cfg->preload_y[i] = scale_v2.preload_y[i];
1820 cfg->src_width[i] = scale_v2.src_width[i];
1821 cfg->src_height[i] = scale_v2.src_height[i];
1822 }
1823 cfg->dst_width = scale_v2.dst_width;
1824 cfg->dst_height = scale_v2.dst_height;
1825
1826 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
1827 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
1828 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
1829 cfg->blend_cfg = scale_v2.blend_cfg;
1830
1831 cfg->lut_flag = scale_v2.lut_flag;
1832 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
1833 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
1834 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
1835 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
1836 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
1837
1838 cfg->de.enable = scale_v2.de.enable;
1839 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
1840 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
1841 cfg->de.clip = scale_v2.de.clip;
1842 cfg->de.limit = scale_v2.de.limit;
1843 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
1844 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
1845 cfg->de.thr_low = scale_v2.de.thr_low;
1846 cfg->de.thr_high = scale_v2.de.thr_high;
1847 cfg->de.prec_shift = scale_v2.de.prec_shift;
1848 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
1849 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
1850 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
1851 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
1852 }
1853 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05001854 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
1855 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
1856 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
1857 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
1858 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04001859
abeykun41060122016-11-28 13:02:01 -05001860 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
1861 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
1862 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
1863 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
1864 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04001865 }
1866 psde->pixel_ext_usr = true;
1867
1868 SDE_DEBUG_PLANE(psde, "user property data copied\n");
1869}
1870
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001871static int sde_plane_atomic_set_property(struct drm_plane *plane,
1872 struct drm_plane_state *state, struct drm_property *property,
1873 uint64_t val)
1874{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001875 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001876 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001877 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001878
Clarence Ip13a8cf42016-09-29 17:27:47 -04001879 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001880
1881 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001882 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001883 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001884 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001885 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04001886 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001887 ret = msm_property_atomic_set(&psde->property_info,
1888 pstate->property_values, pstate->property_blobs,
1889 property, val);
1890 if (!ret) {
1891 idx = msm_property_index(&psde->property_info,
1892 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001893 switch (idx) {
1894 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04001895 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001896 break;
1897 case PLANE_PROP_CSC_V1:
1898 _sde_plane_set_csc_v1(psde, (void *)val);
1899 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04001900 case PLANE_PROP_SCALER_V1:
1901 _sde_plane_set_scaler_v1(psde, (void *)val);
1902 break;
abeykun48f407a2016-08-25 12:06:44 -04001903 case PLANE_PROP_SCALER_V2:
1904 _sde_plane_set_scaler_v2(psde, pstate,
1905 (void *)val);
1906 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001907 default:
1908 /* nothing to do */
1909 break;
1910 }
Clarence Ipe78efb72016-06-24 18:35:21 -04001911 }
1912 }
1913
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001914 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001915}
1916
1917static int sde_plane_set_property(struct drm_plane *plane,
1918 struct drm_property *property, uint64_t val)
1919{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001920 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001921
Clarence Ipae4e60c2016-06-26 22:44:04 -04001922 return sde_plane_atomic_set_property(plane,
1923 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001924}
1925
1926static int sde_plane_atomic_get_property(struct drm_plane *plane,
1927 const struct drm_plane_state *state,
1928 struct drm_property *property, uint64_t *val)
1929{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001930 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001931 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04001932 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001933
Clarence Ipaa0faf42016-05-30 12:07:48 -04001934 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001935 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001936 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001937 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001938 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001939 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001940 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001941 ret = msm_property_atomic_get(&psde->property_info,
1942 pstate->property_values, pstate->property_blobs,
1943 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04001944 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001945
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001946 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001947}
1948
1949static void sde_plane_destroy(struct drm_plane *plane)
1950{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001951 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001952
Clarence Ip13a8cf42016-09-29 17:27:47 -04001953 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001954
Clarence Ip13a8cf42016-09-29 17:27:47 -04001955 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001956 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1957
Clarence Ip4ce59322016-06-26 22:27:51 -04001958 debugfs_remove_recursive(psde->debugfs_root);
Clarence Ipe78efb72016-06-24 18:35:21 -04001959
Dhaval Patel4e574842016-08-23 15:11:37 -07001960 if (psde->blob_info)
1961 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001962 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04001963 mutex_destroy(&psde->lock);
1964
Clarence Ip4ce59322016-06-26 22:27:51 -04001965 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001966
Clarence Ip4ce59322016-06-26 22:27:51 -04001967 /* this will destroy the states as well */
1968 drm_plane_cleanup(plane);
1969
Clarence Ip4c1d9772016-06-26 09:35:38 -04001970 if (psde->pipe_hw)
1971 sde_hw_sspp_destroy(psde->pipe_hw);
1972
Clarence Ip4ce59322016-06-26 22:27:51 -04001973 kfree(psde);
1974 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001975}
1976
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001977static void sde_plane_destroy_state(struct drm_plane *plane,
1978 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001979{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001980 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04001981 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001982
Clarence Ipae4e60c2016-06-26 22:44:04 -04001983 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001984 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1985 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001986 return;
1987 }
1988
Clarence Ipaa0faf42016-05-30 12:07:48 -04001989 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04001990 pstate = to_sde_plane_state(state);
1991
Clarence Ip13a8cf42016-09-29 17:27:47 -04001992 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001993
Clarence Ipe78efb72016-06-24 18:35:21 -04001994 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001995 if (state->fb)
1996 drm_framebuffer_unreference(state->fb);
1997
Clarence Ipae4e60c2016-06-26 22:44:04 -04001998 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001999 if (pstate->input_fence)
2000 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04002001
Clarence Ipaa0faf42016-05-30 12:07:48 -04002002 /* destroy value helper */
2003 msm_property_destroy_state(&psde->property_info, pstate,
2004 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002005}
2006
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002007static struct drm_plane_state *
2008sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002009{
Clarence Ipaa0faf42016-05-30 12:07:48 -04002010 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002011 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04002012 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04002013 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002014
Clarence Ip13a8cf42016-09-29 17:27:47 -04002015 if (!plane) {
2016 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002017 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002018 } else if (!plane->state) {
2019 SDE_ERROR("invalid plane state\n");
2020 return NULL;
2021 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002022
Clarence Ip730e7192016-06-26 22:45:09 -04002023 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002024 psde = to_sde_plane(plane);
2025 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002026 if (!pstate) {
2027 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002028 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002029 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002030
Clarence Ip13a8cf42016-09-29 17:27:47 -04002031 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002032
2033 /* duplicate value helper */
2034 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
2035 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04002036
Clarence Ip730e7192016-06-26 22:45:09 -04002037 /* add ref count for frame buffer */
2038 if (pstate->base.fb)
2039 drm_framebuffer_reference(pstate->base.fb);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002040
Clarence Ip17e908b2016-09-29 15:58:00 -04002041 /* clear out any input fence */
2042 pstate->input_fence = 0;
2043 input_fence_default = msm_property_get_default(
2044 &psde->property_info, PLANE_PROP_INPUT_FENCE);
2045 msm_property_set_property(&psde->property_info, pstate->property_values,
2046 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002047
Clarence Ip282dad62016-09-27 17:07:35 -04002048 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04002049 pstate->pending = false;
2050
2051 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002052}
2053
2054static void sde_plane_reset(struct drm_plane *plane)
2055{
Clarence Ipae4e60c2016-06-26 22:44:04 -04002056 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002057 struct sde_plane_state *pstate;
2058
Clarence Ipae4e60c2016-06-26 22:44:04 -04002059 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002060 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04002061 return;
2062 }
2063
Clarence Ip730e7192016-06-26 22:45:09 -04002064 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002065 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002066
Clarence Ipae4e60c2016-06-26 22:44:04 -04002067 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04002068 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04002069 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002070 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04002071 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002072
Clarence Ipaa0faf42016-05-30 12:07:48 -04002073 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002074 if (!pstate) {
2075 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002076 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002077 }
Clarence Ip730e7192016-06-26 22:45:09 -04002078
Clarence Ipaa0faf42016-05-30 12:07:48 -04002079 /* reset value helper */
2080 msm_property_reset_state(&psde->property_info, pstate,
2081 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002082
2083 pstate->base.plane = plane;
2084
2085 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002086}
2087
2088static const struct drm_plane_funcs sde_plane_funcs = {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002089 .update_plane = drm_atomic_helper_update_plane,
2090 .disable_plane = drm_atomic_helper_disable_plane,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002091 .destroy = sde_plane_destroy,
2092 .set_property = sde_plane_set_property,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002093 .atomic_set_property = sde_plane_atomic_set_property,
2094 .atomic_get_property = sde_plane_atomic_get_property,
2095 .reset = sde_plane_reset,
2096 .atomic_duplicate_state = sde_plane_duplicate_state,
2097 .atomic_destroy_state = sde_plane_destroy_state,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002098};
2099
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002100static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
2101 .prepare_fb = sde_plane_prepare_fb,
2102 .cleanup_fb = sde_plane_cleanup_fb,
2103 .atomic_check = sde_plane_atomic_check,
2104 .atomic_update = sde_plane_atomic_update,
2105};
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002106
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002107enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002108{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002109 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002110}
2111
Alan Kwongf0fd8512016-10-24 21:39:26 -04002112static ssize_t _sde_plane_danger_read(struct file *file,
2113 char __user *buff, size_t count, loff_t *ppos)
2114{
2115 struct sde_kms *kms = file->private_data;
2116 struct sde_mdss_cfg *cfg = kms->catalog;
2117 int len = 0;
2118 char buf[40] = {'\0'};
2119
2120 if (!cfg)
2121 return -ENODEV;
2122
2123 if (*ppos)
2124 return 0; /* the end */
2125
2126 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
2127 if (len < 0 || len >= sizeof(buf))
2128 return 0;
2129
2130 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
2131 return -EFAULT;
2132
2133 *ppos += len; /* increase offset */
2134
2135 return len;
2136}
2137
2138static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
2139{
2140 struct drm_plane *plane;
2141
2142 drm_for_each_plane(plane, kms->dev) {
2143 if (plane->fb && plane->state) {
2144 sde_plane_danger_signal_ctrl(plane, enable);
2145 SDE_DEBUG("plane:%d img:%dx%d ",
2146 plane->base.id, plane->fb->width,
2147 plane->fb->height);
2148 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
2149 plane->state->src_x >> 16,
2150 plane->state->src_y >> 16,
2151 plane->state->src_w >> 16,
2152 plane->state->src_h >> 16,
2153 plane->state->crtc_x, plane->state->crtc_y,
2154 plane->state->crtc_w, plane->state->crtc_h);
2155 } else {
2156 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
2157 }
2158 }
2159}
2160
2161static ssize_t _sde_plane_danger_write(struct file *file,
2162 const char __user *user_buf, size_t count, loff_t *ppos)
2163{
2164 struct sde_kms *kms = file->private_data;
2165 struct sde_mdss_cfg *cfg = kms->catalog;
2166 int disable_panic;
2167 char buf[10];
2168
2169 if (!cfg)
2170 return -EFAULT;
2171
2172 if (count >= sizeof(buf))
2173 return -EFAULT;
2174
2175 if (copy_from_user(buf, user_buf, count))
2176 return -EFAULT;
2177
2178 buf[count] = 0; /* end of string */
2179
2180 if (kstrtoint(buf, 0, &disable_panic))
2181 return -EFAULT;
2182
2183 if (disable_panic) {
2184 /* Disable panic signal for all active pipes */
2185 SDE_DEBUG("Disabling danger:\n");
2186 _sde_plane_set_danger_state(kms, false);
2187 kms->has_danger_ctrl = false;
2188 } else {
2189 /* Enable panic signal for all active pipes */
2190 SDE_DEBUG("Enabling danger:\n");
2191 kms->has_danger_ctrl = true;
2192 _sde_plane_set_danger_state(kms, true);
2193 }
2194
2195 return count;
2196}
2197
2198static const struct file_operations sde_plane_danger_enable = {
2199 .open = simple_open,
2200 .read = _sde_plane_danger_read,
2201 .write = _sde_plane_danger_write,
2202};
2203
Clarence Ip4ce59322016-06-26 22:27:51 -04002204static void _sde_plane_init_debugfs(struct sde_plane *psde, struct sde_kms *kms)
2205{
2206 const struct sde_sspp_sub_blks *sblk = 0;
2207 const struct sde_sspp_cfg *cfg = 0;
2208
2209 if (psde && psde->pipe_hw)
2210 cfg = psde->pipe_hw->cap;
2211 if (cfg)
2212 sblk = cfg->sblk;
2213
2214 if (kms && sblk) {
2215 /* create overall sub-directory for the pipe */
2216 psde->debugfs_root =
2217 debugfs_create_dir(psde->pipe_name,
2218 sde_debugfs_get_root(kms));
2219 if (psde->debugfs_root) {
2220 /* don't error check these */
Clarence Ip4c1d9772016-06-26 09:35:38 -04002221 debugfs_create_x32("features", 0644,
Clarence Ip4ce59322016-06-26 22:27:51 -04002222 psde->debugfs_root, &psde->features);
2223
2224 /* add register dump support */
2225 sde_debugfs_setup_regset32(&psde->debugfs_src,
2226 sblk->src_blk.base + cfg->base,
2227 sblk->src_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002228 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002229 sde_debugfs_create_regset32("src_blk", 0444,
2230 psde->debugfs_root, &psde->debugfs_src);
2231
2232 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
2233 sblk->scaler_blk.base + cfg->base,
2234 sblk->scaler_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002235 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002236 sde_debugfs_create_regset32("scaler_blk", 0444,
2237 psde->debugfs_root,
2238 &psde->debugfs_scaler);
2239
2240 sde_debugfs_setup_regset32(&psde->debugfs_csc,
2241 sblk->csc_blk.base + cfg->base,
2242 sblk->csc_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002243 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002244 sde_debugfs_create_regset32("csc_blk", 0444,
2245 psde->debugfs_root, &psde->debugfs_csc);
Alan Kwongf0fd8512016-10-24 21:39:26 -04002246
2247 debugfs_create_u32("xin_id",
2248 0444,
2249 psde->debugfs_root,
2250 (u32 *) &cfg->xin_id);
2251 debugfs_create_u32("clk_ctrl",
2252 0444,
2253 psde->debugfs_root,
2254 (u32 *) &cfg->clk_ctrl);
2255 debugfs_create_x32("creq_vblank",
2256 0644,
2257 psde->debugfs_root,
2258 (u32 *) &sblk->creq_vblank);
2259 debugfs_create_x32("danger_vblank",
2260 0644,
2261 psde->debugfs_root,
2262 (u32 *) &sblk->danger_vblank);
2263
2264 debugfs_create_file("disable_danger",
2265 0644,
2266 psde->debugfs_root,
2267 kms, &sde_plane_danger_enable);
Clarence Ip4ce59322016-06-26 22:27:51 -04002268 }
2269 }
2270}
2271
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002272/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04002273struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002274 uint32_t pipe, bool primary_plane,
2275 unsigned long possible_crtcs)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002276{
2277 struct drm_plane *plane = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002278 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002279 struct msm_drm_private *priv;
2280 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002281 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04002282 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002283
2284 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002285 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002286 goto exit;
2287 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002288
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002289 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04002290 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002291 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002292 goto exit;
2293 }
2294
2295 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002296 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002297 goto exit;
2298 }
2299 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002300
Clarence Ip4c1d9772016-06-26 09:35:38 -04002301 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002302 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002303 goto exit;
2304 }
2305
Clarence Ip4ce59322016-06-26 22:27:51 -04002306 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002307 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
2308 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002309 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002310 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002311 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002312 }
2313
Clarence Ip4c1d9772016-06-26 09:35:38 -04002314 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002315 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002316 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04002317 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002318
Clarence Ip4c1d9772016-06-26 09:35:38 -04002319 /* initialize underlying h/w driver */
2320 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
2321 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002322 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002323 ret = PTR_ERR(psde->pipe_hw);
2324 goto clean_plane;
2325 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002326 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002327 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002328 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002329
2330 /* cache features mask for later */
2331 psde->features = psde->pipe_hw->cap->features;
2332 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04002333 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002334 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04002335 goto clean_sspp;
2336 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002337
abeykun48f407a2016-08-25 12:06:44 -04002338 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
2339 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
2340 GFP_KERNEL);
2341 if (!psde->scaler3_cfg) {
2342 SDE_ERROR("[%u]failed to allocate scale struct\n",
2343 pipe);
2344 ret = -ENOMEM;
2345 goto clean_sspp;
2346 }
2347 }
2348
Clarence Ip4c1d9772016-06-26 09:35:38 -04002349 /* add plane to DRM framework */
Clarence Ipea3d6262016-07-15 16:20:11 -04002350 psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
2351 psde->formats,
2352 0,
2353 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002354
Clarence Ip4c1d9772016-06-26 09:35:38 -04002355 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002356 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002357 goto clean_sspp;
2358 }
2359
2360 if (psde->features & BIT(SDE_SSPP_CURSOR))
2361 type = DRM_PLANE_TYPE_CURSOR;
2362 else if (primary_plane)
2363 type = DRM_PLANE_TYPE_PRIMARY;
2364 else
2365 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002366 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
2367 psde->formats, psde->nformats,
2368 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002369 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04002370 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002371
Clarence Ip4c1d9772016-06-26 09:35:38 -04002372 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002373 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002374
Clarence Ipaa0faf42016-05-30 12:07:48 -04002375 msm_property_init(&psde->property_info, &plane->base, dev,
2376 priv->plane_property, psde->property_data,
2377 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
2378 sizeof(struct sde_plane_state));
2379
Clarence Ipc47a0692016-10-11 10:54:17 -04002380 _sde_plane_install_properties(plane, kms->catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002381
Clarence Ip4ce59322016-06-26 22:27:51 -04002382 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04002383 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04002384
Clarence Ip730e7192016-06-26 22:45:09 -04002385 mutex_init(&psde->lock);
2386
Clarence Ip4ce59322016-06-26 22:27:51 -04002387 _sde_plane_init_debugfs(psde, kms);
2388
Clarence Ip13a8cf42016-09-29 17:27:47 -04002389 DRM_INFO("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002390 return plane;
2391
Clarence Ip4c1d9772016-06-26 09:35:38 -04002392clean_sspp:
2393 if (psde && psde->pipe_hw)
2394 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04002395
2396 if (psde && psde->scaler3_cfg)
2397 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002398clean_plane:
2399 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04002400exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002401 return ERR_PTR(ret);
2402}