blob: d2884f07260e6732ffe8a6a2ccb1495e7c5a9246 [file] [log] [blame]
Clarence Ipaac9f332016-08-31 15:46:35 -04001/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
Alan Kwong1a00e4d2016-07-18 09:42:30 -040012
13#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
14
Clarence Ip4ce59322016-06-26 22:27:51 -040015#include <linux/debugfs.h>
Clarence Ip5e2a9222016-06-26 22:38:24 -040016#include <uapi/drm/sde_drm.h>
Benet Clarkd009b1d2016-06-27 14:45:59 -070017#include <uapi/drm/msm_drm_pp.h>
Clarence Ipaa0faf42016-05-30 12:07:48 -040018
19#include "msm_prop.h"
20
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070021#include "sde_kms.h"
Clarence Ipae4e60c2016-06-26 22:44:04 -040022#include "sde_fence.h"
Clarence Ipc475b082016-06-26 09:27:23 -040023#include "sde_formats.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040024#include "sde_hw_sspp.h"
Alan Kwong1a00e4d2016-07-18 09:42:30 -040025#include "sde_trace.h"
Dhaval Patel48c76022016-09-01 17:51:23 -070026#include "sde_crtc.h"
Lloyd Atkinson8772e202016-09-26 17:52:16 -040027#include "sde_vbif.h"
Alan Kwong83285fb2016-10-21 20:51:17 -040028#include "sde_plane.h"
Benet Clarkd009b1d2016-06-27 14:45:59 -070029#include "sde_color_processing.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040030
Clarence Ip13a8cf42016-09-29 17:27:47 -040031#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
32 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
33
34#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
35 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
36
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040037#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
38#define PHASE_STEP_SHIFT 21
39#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
40#define PHASE_RESIDUAL 15
41
Clarence Ipe78efb72016-06-24 18:35:21 -040042#define SHARP_STRENGTH_DEFAULT 32
43#define SHARP_EDGE_THR_DEFAULT 112
44#define SHARP_SMOOTH_THR_DEFAULT 8
45#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040046
Clarence Ip5e2a9222016-06-26 22:38:24 -040047#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070048
Clarence Ipcae1bb62016-07-07 12:07:13 -040049#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
50
Clarence Ip282dad62016-09-27 17:07:35 -040051/* dirty bits for update function */
52#define SDE_PLANE_DIRTY_RECTS 0x1
53#define SDE_PLANE_DIRTY_FORMAT 0x2
54#define SDE_PLANE_DIRTY_SHARPEN 0x4
55#define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF
56
Alan Kwong1a00e4d2016-07-18 09:42:30 -040057/**
58 * enum sde_plane_qos - Different qos configurations for each pipe
59 *
60 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
61 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
62 * this configuration is mutually exclusive from VBLANK_CTRL.
63 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
64 */
65enum sde_plane_qos {
66 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
67 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
68 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
69};
70
Clarence Ip5fc00c52016-09-23 15:03:34 -040071/*
72 * struct sde_plane - local sde plane structure
73 * @csc_cfg: Decoded user configuration for csc
74 * @csc_usr_ptr: Points to csc_cfg if valid user config available
75 * @csc_ptr: Points to sde_csc_cfg structure to use for current
76 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070077struct sde_plane {
78 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040079
80 int mmu_id;
81
Clarence Ip730e7192016-06-26 22:45:09 -040082 struct mutex lock;
83
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040084 enum sde_sspp pipe;
85 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070086 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -040087 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040088
89 struct sde_hw_pipe *pipe_hw;
90 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -040091 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -040092 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040093 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -040094 uint32_t color_fill;
95 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040096 bool is_rt_pipe;
Clarence Ip4ce59322016-06-26 22:27:51 -040097
Clarence Ipb43d4592016-09-08 14:21:35 -040098 struct sde_hw_pixel_ext pixel_ext;
99 bool pixel_ext_usr;
100
Clarence Ip373f8592016-05-26 00:58:42 -0400101 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400102 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400103 struct sde_csc_cfg *csc_ptr;
104
Clarence Ip4c1d9772016-06-26 09:35:38 -0400105 const struct sde_sspp_sub_blks *pipe_sblk;
106
Clarence Ip5e2a9222016-06-26 22:38:24 -0400107 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400108
Clarence Ipaa0faf42016-05-30 12:07:48 -0400109 struct msm_property_info property_info;
110 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700111 struct drm_property_blob *blob_info;
Clarence Ip730e7192016-06-26 22:45:09 -0400112
Clarence Ip4ce59322016-06-26 22:27:51 -0400113 /* debugfs related stuff */
114 struct dentry *debugfs_root;
115 struct sde_debugfs_regset32 debugfs_src;
116 struct sde_debugfs_regset32 debugfs_scaler;
117 struct sde_debugfs_regset32 debugfs_csc;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700118};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700119
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700120#define to_sde_plane(x) container_of(x, struct sde_plane, base)
121
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400122static bool sde_plane_enabled(struct drm_plane_state *state)
123{
Clarence Ipdbde9832016-06-26 09:48:36 -0400124 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400125}
126
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400127/**
128 * _sde_plane_calc_fill_level - calculate fill level of the given source format
129 * @plane: Pointer to drm plane
130 * @fmt: Pointer to source buffer format
131 * @src_wdith: width of source buffer
132 * Return: fill level corresponding to the source buffer/format or 0 if error
133 */
134static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
135 const struct sde_format *fmt, u32 src_width)
136{
137 struct sde_plane *psde;
138 u32 fixed_buff_size;
139 u32 total_fl;
140
141 if (!plane || !fmt) {
142 SDE_ERROR("invalid arguments\n");
143 return 0;
144 }
145
146 psde = to_sde_plane(plane);
147 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
148
149 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
150 if (fmt->chroma_sample == SDE_CHROMA_420) {
151 /* NV12 */
152 total_fl = (fixed_buff_size / 2) /
153 ((src_width + 32) * fmt->bpp);
154 } else {
155 /* non NV12 */
156 total_fl = (fixed_buff_size) /
157 ((src_width + 32) * fmt->bpp);
158 }
159 } else {
160 total_fl = (fixed_buff_size * 2) /
161 ((src_width + 32) * fmt->bpp);
162 }
163
164 SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n",
165 plane->base.id, psde->pipe - SSPP_VIG0,
166 fmt->base.pixel_format, src_width, total_fl);
167
168 return total_fl;
169}
170
171/**
172 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
173 * @total_fl: fill level
174 * Return: LUT setting corresponding to the fill level
175 */
176static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
177{
178 u32 qos_lut;
179
180 if (total_fl <= 4)
181 qos_lut = 0x1B;
182 else if (total_fl <= 5)
183 qos_lut = 0x5B;
184 else if (total_fl <= 6)
185 qos_lut = 0x15B;
186 else if (total_fl <= 7)
187 qos_lut = 0x55B;
188 else if (total_fl <= 8)
189 qos_lut = 0x155B;
190 else if (total_fl <= 9)
191 qos_lut = 0x555B;
192 else if (total_fl <= 10)
193 qos_lut = 0x1555B;
194 else if (total_fl <= 11)
195 qos_lut = 0x5555B;
196 else if (total_fl <= 12)
197 qos_lut = 0x15555B;
198 else
199 qos_lut = 0x55555B;
200
201 return qos_lut;
202}
203
204/**
205 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
206 * @total_fl: fill level
207 * Return: LUT setting corresponding to the fill level
208 */
209static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
210{
211 u32 qos_lut;
212
213 if (total_fl <= 10)
214 qos_lut = 0x1AAff;
215 else if (total_fl <= 11)
216 qos_lut = 0x5AAFF;
217 else if (total_fl <= 12)
218 qos_lut = 0x15AAFF;
219 else
220 qos_lut = 0x55AAFF;
221
222 return qos_lut;
223}
224
225/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400226 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
227 * @plane: Pointer to drm plane
228 * @fb: Pointer to framebuffer associated with the given plane
229 */
230static void _sde_plane_set_qos_lut(struct drm_plane *plane,
231 struct drm_framebuffer *fb)
232{
233 struct sde_plane *psde;
234 const struct sde_format *fmt = NULL;
235 u32 qos_lut;
236 u32 total_fl = 0;
237
238 if (!plane || !fb) {
239 SDE_ERROR("invalid arguments plane %d fb %d\n",
240 plane != 0, fb != 0);
241 return;
242 }
243
244 psde = to_sde_plane(plane);
245
246 if (!psde->pipe_hw || !psde->pipe_sblk) {
247 SDE_ERROR("invalid arguments\n");
248 return;
249 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
250 return;
251 }
252
253 if (!psde->is_rt_pipe) {
254 qos_lut = psde->pipe_sblk->creq_lut_nrt;
255 } else {
256 fmt = sde_get_sde_format_ext(
257 fb->pixel_format,
258 fb->modifier,
259 drm_format_num_planes(fb->pixel_format));
260 total_fl = _sde_plane_calc_fill_level(plane, fmt,
261 psde->pipe_cfg.src_rect.w);
262
263 if (SDE_FORMAT_IS_LINEAR(fmt))
264 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
265 else
266 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
267 }
268
269 psde->pipe_qos_cfg.creq_lut = qos_lut;
270
271 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
272 (fmt) ? fmt->base.pixel_format : 0,
273 psde->is_rt_pipe, total_fl, qos_lut,
274 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
275
276 SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n",
277 plane->base.id,
278 psde->pipe - SSPP_VIG0,
279 (fmt) ? fmt->base.pixel_format : 0,
280 psde->is_rt_pipe, total_fl, qos_lut);
281
282 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
283}
284
285/**
286 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
287 * @plane: Pointer to drm plane
288 * @fb: Pointer to framebuffer associated with the given plane
289 */
290static void _sde_plane_set_danger_lut(struct drm_plane *plane,
291 struct drm_framebuffer *fb)
292{
293 struct sde_plane *psde;
294 const struct sde_format *fmt = NULL;
295 u32 danger_lut, safe_lut;
296
297 if (!plane || !fb) {
298 SDE_ERROR("invalid arguments\n");
299 return;
300 }
301
302 psde = to_sde_plane(plane);
303
304 if (!psde->pipe_hw || !psde->pipe_sblk) {
305 SDE_ERROR("invalid arguments\n");
306 return;
307 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
308 return;
309 }
310
311 if (!psde->is_rt_pipe) {
312 danger_lut = psde->pipe_sblk->danger_lut_nrt;
313 safe_lut = psde->pipe_sblk->safe_lut_nrt;
314 } else {
315 fmt = sde_get_sde_format_ext(
316 fb->pixel_format,
317 fb->modifier,
318 drm_format_num_planes(fb->pixel_format));
319
320 if (SDE_FORMAT_IS_LINEAR(fmt)) {
321 danger_lut = psde->pipe_sblk->danger_lut_linear;
322 safe_lut = psde->pipe_sblk->safe_lut_linear;
323 } else {
324 danger_lut = psde->pipe_sblk->danger_lut_tile;
325 safe_lut = psde->pipe_sblk->safe_lut_tile;
326 }
327 }
328
329 psde->pipe_qos_cfg.danger_lut = danger_lut;
330 psde->pipe_qos_cfg.safe_lut = safe_lut;
331
332 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
333 (fmt) ? fmt->base.pixel_format : 0,
334 (fmt) ? fmt->fetch_mode : 0,
335 psde->pipe_qos_cfg.danger_lut,
336 psde->pipe_qos_cfg.safe_lut);
337
338 SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n",
339 plane->base.id,
340 psde->pipe - SSPP_VIG0,
341 fmt ? fmt->base.pixel_format : 0,
342 fmt ? fmt->fetch_mode : -1,
343 psde->pipe_qos_cfg.danger_lut,
344 psde->pipe_qos_cfg.safe_lut);
345
346 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
347 &psde->pipe_qos_cfg);
348}
349
350/**
351 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
352 * @plane: Pointer to drm plane
353 * @enable: true to enable QoS control
354 * @flags: QoS control mode (enum sde_plane_qos)
355 */
356static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
357 bool enable, u32 flags)
358{
359 struct sde_plane *psde;
360
361 if (!plane) {
362 SDE_ERROR("invalid arguments\n");
363 return;
364 }
365
366 psde = to_sde_plane(plane);
367
368 if (!psde->pipe_hw || !psde->pipe_sblk) {
369 SDE_ERROR("invalid arguments\n");
370 return;
371 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
372 return;
373 }
374
375 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
376 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
377 psde->pipe_qos_cfg.danger_vblank =
378 psde->pipe_sblk->danger_vblank;
379 psde->pipe_qos_cfg.vblank_en = enable;
380 }
381
382 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
383 /* this feature overrules previous VBLANK_CTRL */
384 psde->pipe_qos_cfg.vblank_en = false;
385 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
386 }
387
388 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
389 psde->pipe_qos_cfg.danger_safe_en = enable;
390
391 if (!psde->is_rt_pipe) {
392 psde->pipe_qos_cfg.vblank_en = false;
393 psde->pipe_qos_cfg.danger_safe_en = false;
394 }
395
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400396 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 -0400397 plane->base.id,
398 psde->pipe - SSPP_VIG0,
399 psde->pipe_qos_cfg.danger_safe_en,
400 psde->pipe_qos_cfg.vblank_en,
401 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400402 psde->pipe_qos_cfg.danger_vblank,
403 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400404
405 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
406 &psde->pipe_qos_cfg);
407}
408
Alan Kwongf0fd8512016-10-24 21:39:26 -0400409int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
410{
411 struct sde_plane *psde;
412 struct msm_drm_private *priv;
413 struct sde_kms *sde_kms;
414
415 if (!plane || !plane->dev) {
416 SDE_ERROR("invalid arguments\n");
417 return -EINVAL;
418 }
419
420 priv = plane->dev->dev_private;
421 if (!priv || !priv->kms) {
422 SDE_ERROR("invalid KMS reference\n");
423 return -EINVAL;
424 }
425
426 sde_kms = to_sde_kms(priv->kms);
427 psde = to_sde_plane(plane);
428
429 if (!psde->is_rt_pipe)
430 goto end;
431
432 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
433
434 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
435
436 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
437
438end:
439 return 0;
440}
441
Alan Kwong5d324e42016-07-28 22:56:18 -0400442/**
443 * _sde_plane_set_ot_limit - set OT limit for the given plane
444 * @plane: Pointer to drm plane
445 * @crtc: Pointer to drm crtc
446 */
447static void _sde_plane_set_ot_limit(struct drm_plane *plane,
448 struct drm_crtc *crtc)
449{
450 struct sde_plane *psde;
451 struct sde_vbif_set_ot_params ot_params;
452 struct msm_drm_private *priv;
453 struct sde_kms *sde_kms;
454
455 if (!plane || !plane->dev || !crtc) {
456 SDE_ERROR("invalid arguments plane %d crtc %d\n",
457 plane != 0, crtc != 0);
458 return;
459 }
460
461 priv = plane->dev->dev_private;
462 if (!priv || !priv->kms) {
463 SDE_ERROR("invalid KMS reference\n");
464 return;
465 }
466
467 sde_kms = to_sde_kms(priv->kms);
468 psde = to_sde_plane(plane);
469 if (!psde->pipe_hw) {
470 SDE_ERROR("invalid pipe reference\n");
471 return;
472 }
473
474 memset(&ot_params, 0, sizeof(ot_params));
475 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
476 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
477 ot_params.width = psde->pipe_cfg.src_rect.w;
478 ot_params.height = psde->pipe_cfg.src_rect.h;
479 ot_params.is_wfd = !psde->is_rt_pipe;
480 ot_params.frame_rate = crtc->mode.vrefresh;
481 ot_params.vbif_idx = VBIF_RT;
482 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
483 ot_params.rd = true;
484
485 sde_vbif_set_ot_limit(sde_kms, &ot_params);
486}
487
Clarence Ipcae1bb62016-07-07 12:07:13 -0400488/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400489static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400490 struct sde_plane_state *pstate, uint64_t fd)
491{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400492 if (!psde || !pstate) {
493 SDE_ERROR("invalid arg(s), plane %d state %d\n",
494 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400495 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400496 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400497
498 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400499 if (pstate->input_fence)
500 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400501
502 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400503 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400504
Clarence Ip13a8cf42016-09-29 17:27:47 -0400505 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400506}
507
Clarence Ipcae1bb62016-07-07 12:07:13 -0400508int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400509{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400510 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400511 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400512 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400513 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400514 int ret = -EINVAL;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400515
516 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700517 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400518 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400519 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400520 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400521 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400522 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400523 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400524
Clarence Ipcae1bb62016-07-07 12:07:13 -0400525 if (input_fence) {
Clarence Ip78a04ed2016-10-04 15:57:45 -0400526 prefix = sde_sync_get_name_prefix(input_fence);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400527 ret = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400528
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400529 SDE_EVT32(DRMID(plane), -ret, prefix);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400530
Clarence Ipcae1bb62016-07-07 12:07:13 -0400531 switch (ret) {
532 case 0:
Clarence Ip13a8cf42016-09-29 17:27:47 -0400533 SDE_DEBUG_PLANE(psde, "signaled\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400534 break;
535 case -ETIME:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400536 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
537 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400538 psde->is_error = true;
539 break;
540 default:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400541 SDE_ERROR_PLANE(psde, "error %d on %08X\n",
542 ret, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400543 psde->is_error = true;
544 break;
545 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400546 } else {
547 ret = 0;
548 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400549 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400550 return ret;
551}
552
Clarence Ip282dad62016-09-27 17:07:35 -0400553static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400554 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400555 struct sde_hw_pipe_cfg *pipe_cfg,
556 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400557{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400558 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400559 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400560
Clarence Ip13a8cf42016-09-29 17:27:47 -0400561 if (!plane || !pstate || !pipe_cfg || !fb) {
562 SDE_ERROR(
563 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
564 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400565 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400566 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400567
568 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400569 if (!psde->pipe_hw) {
570 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400571 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400572 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400573
Clarence Ipb6eb2362016-09-08 16:18:13 -0400574 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
575 if (ret == -EAGAIN)
576 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
577 else if (ret)
578 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
579 else if (psde->pipe_hw->ops.setup_sourceaddress)
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400580 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400581}
582
abeykun48f407a2016-08-25 12:06:44 -0400583static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
584 struct sde_plane_state *pstate)
585{
586 struct sde_hw_scaler3_cfg *cfg = psde->scaler3_cfg;
587 int ret = 0;
588
589 cfg->dir_lut = msm_property_get_blob(
590 &psde->property_info,
591 pstate->property_blobs, &cfg->dir_len,
592 PLANE_PROP_SCALER_LUT_ED);
593 cfg->cir_lut = msm_property_get_blob(
594 &psde->property_info,
595 pstate->property_blobs, &cfg->cir_len,
596 PLANE_PROP_SCALER_LUT_CIR);
597 cfg->sep_lut = msm_property_get_blob(
598 &psde->property_info,
599 pstate->property_blobs, &cfg->sep_len,
600 PLANE_PROP_SCALER_LUT_SEP);
601 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
602 ret = -ENODATA;
603 return ret;
604}
605
Clarence Ipcb410d42016-06-26 22:52:33 -0400606static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400607 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
608 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400609 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400610 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
611{
612}
613
Clarence Ipcb410d42016-06-26 22:52:33 -0400614/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400615 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400616 * @psde: Pointer to SDE plane object
617 * @src: Source size
618 * @dst: Destination size
619 * @phase_steps: Pointer to output array for phase steps
620 * @filter: Pointer to output array for filter type
621 * @fmt: Pointer to format definition
622 * @chroma_subsampling: Subsampling amount for chroma channel
623 *
624 * Returns: 0 on success
625 */
626static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400627 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400628 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400629 uint32_t chroma_subsampling)
630{
Clarence Ipcb410d42016-06-26 22:52:33 -0400631 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400632 SDE_ERROR(
633 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
634 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400635 return -EINVAL;
636 }
637
Clarence Ip4c1d9772016-06-26 09:35:38 -0400638 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400639 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400640 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400641 phase_steps[SDE_SSPP_COMP_1_2] =
642 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
643 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
644 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400645
646 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400647 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400648 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400649 (src <= dst) ? SDE_SCALE_FILTER_BIL :
650 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400651
Clarence Ipdbde9832016-06-26 09:48:36 -0400652 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400653 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400654 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
655 } else {
656 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
657 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400658 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400659 }
660 } else {
661 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400662 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
663 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
664 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400665 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400666 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400667}
668
Clarence Ipcb410d42016-06-26 22:52:33 -0400669/**
670 * _sde_plane_setup_pixel_ext - determine default pixel extension values
671 * @psde: Pointer to SDE plane object
672 * @src: Source size
673 * @dst: Destination size
674 * @decimated_src: Source size after decimation, if any
675 * @phase_steps: Pointer to output array for phase steps
676 * @out_src: Output array for pixel extension values
677 * @out_edge1: Output array for pixel extension first edge
678 * @out_edge2: Output array for pixel extension second edge
679 * @filter: Pointer to array for filter type
680 * @fmt: Pointer to format definition
681 * @chroma_subsampling: Subsampling amount for chroma channel
682 * @post_compare: Whether to chroma subsampled source size for comparisions
683 */
684static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400685 uint32_t src, uint32_t dst, uint32_t decimated_src,
686 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400687 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400688 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400689 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400690{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400691 int64_t edge1, edge2, caf;
692 uint32_t src_work;
693 int i, tmp;
694
Clarence Ipcb410d42016-06-26 22:52:33 -0400695 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400696 out_edge2 && filter && fmt) {
697 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400698 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400699 caf = PHASE_STEP_UNIT_SCALE;
700 else
701 caf = 0;
702
703 for (i = 0; i < SDE_MAX_PLANES; i++) {
704 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400705 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400706 src_work /= chroma_subsampling;
707 if (post_compare)
708 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400709 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400710 /* unity */
711 edge1 = 0;
712 edge2 = 0;
713 } else if (dst >= src) {
714 /* upscale */
715 edge1 = (1 << PHASE_RESIDUAL);
716 edge1 -= caf;
717 edge2 = (1 << PHASE_RESIDUAL);
718 edge2 += (dst - 1) * *(phase_steps + i);
719 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
720 edge2 += caf;
721 edge2 = -(edge2);
722 } else {
723 /* downscale */
724 edge1 = 0;
725 edge2 = (dst - 1) * *(phase_steps + i);
726 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
727 edge2 += *(phase_steps + i);
728 edge2 = -(edge2);
729 }
730
731 /* only enable CAF for luma plane */
732 caf = 0;
733
734 /* populate output arrays */
735 *(out_src + i) = src_work;
736
737 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400738 if (edge1 >= 0) {
739 tmp = (uint32_t)edge1;
740 tmp >>= PHASE_STEP_SHIFT;
741 *(out_edge1 + i) = -tmp;
742 } else {
743 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400744 *(out_edge1 + i) =
745 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
746 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400747 }
748 if (edge2 >= 0) {
749 tmp = (uint32_t)edge2;
750 tmp >>= PHASE_STEP_SHIFT;
751 *(out_edge2 + i) = -tmp;
752 } else {
753 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400754 *(out_edge2 + i) =
755 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
756 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400757 }
758 }
759 }
760}
761
Clarence Ip5fc00c52016-09-23 15:03:34 -0400762static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400763{
764 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
765 {
Clarence Ip373f8592016-05-26 00:58:42 -0400766 /* S15.16 format */
767 0x00012A00, 0x00000000, 0x00019880,
768 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
769 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400770 },
Clarence Ip373f8592016-05-26 00:58:42 -0400771 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400772 { 0xfff0, 0xff80, 0xff80,},
773 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400774 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400775 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400776 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400777 };
abeykun1c312f62016-08-26 09:47:12 -0400778 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
779 {
780 /* S15.16 format */
781 0x00012A00, 0x00000000, 0x00019880,
782 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
783 0x00012A00, 0x00020480, 0x00000000,
784 },
785 /* signed bias */
786 { 0xffc0, 0xfe00, 0xfe00,},
787 { 0x0, 0x0, 0x0,},
788 /* unsigned clamp */
789 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
790 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
791 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400792
Clarence Ip5fc00c52016-09-23 15:03:34 -0400793 if (!psde) {
794 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400795 return;
796 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400797
Clarence Ipcae1bb62016-07-07 12:07:13 -0400798 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400799 if (psde->csc_usr_ptr)
800 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400801 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
802 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400803 else
Clarence Ip373f8592016-05-26 00:58:42 -0400804 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400805
Clarence Ip13a8cf42016-09-29 17:27:47 -0400806 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400807 psde->csc_ptr->csc_mv[0],
808 psde->csc_ptr->csc_mv[1],
809 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400810}
811
Benet Clarkeb1b4462016-06-27 14:43:06 -0700812static void sde_color_process_plane_setup(struct drm_plane *plane)
813{
814 struct sde_plane *psde;
815 struct sde_plane_state *pstate;
816 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -0700817 struct drm_msm_memcol *memcol = NULL;
818 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -0700819
820 psde = to_sde_plane(plane);
821 pstate = to_sde_plane_state(plane->state);
822
823 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
824 if (psde->pipe_hw->ops.setup_pa_hue)
825 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
826 saturation = (uint32_t) sde_plane_get_property(pstate,
827 PLANE_PROP_SATURATION_ADJUST);
828 if (psde->pipe_hw->ops.setup_pa_sat)
829 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
830 value = (uint32_t) sde_plane_get_property(pstate,
831 PLANE_PROP_VALUE_ADJUST);
832 if (psde->pipe_hw->ops.setup_pa_val)
833 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
834 contrast = (uint32_t) sde_plane_get_property(pstate,
835 PLANE_PROP_CONTRAST_ADJUST);
836 if (psde->pipe_hw->ops.setup_pa_cont)
837 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -0700838
Benet Clarkd009b1d2016-06-27 14:45:59 -0700839 if (psde->pipe_hw->ops.setup_pa_memcolor) {
840 /* Skin memory color setup */
841 memcol = msm_property_get_blob(&psde->property_info,
842 pstate->property_blobs,
843 &memcol_sz,
844 PLANE_PROP_SKIN_COLOR);
845 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
846 MEMCOLOR_SKIN, memcol);
847
848 /* Sky memory color setup */
849 memcol = msm_property_get_blob(&psde->property_info,
850 pstate->property_blobs,
851 &memcol_sz,
852 PLANE_PROP_SKY_COLOR);
853 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
854 MEMCOLOR_SKY, memcol);
855
856 /* Foliage memory color setup */
857 memcol = msm_property_get_blob(&psde->property_info,
858 pstate->property_blobs,
859 &memcol_sz,
860 PLANE_PROP_FOLIAGE_COLOR);
861 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
862 MEMCOLOR_FOLIAGE, memcol);
863 }
864}
Benet Clarkeb1b4462016-06-27 14:43:06 -0700865
Clarence Ipcb410d42016-06-26 22:52:33 -0400866static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400867 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -0400868 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700869{
Clarence Ipb43d4592016-09-08 14:21:35 -0400870 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -0400871 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400872
Clarence Ipb43d4592016-09-08 14:21:35 -0400873 if (!psde || !fmt) {
874 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
875 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400876 return;
Clarence Ipb43d4592016-09-08 14:21:35 -0400877 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400878
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400879 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400880
Clarence Ipdedbba92016-09-27 17:43:10 -0400881 psde->pipe_cfg.horz_decimation =
882 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
883 psde->pipe_cfg.vert_decimation =
884 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400885
886 /* don't chroma subsample if decimating */
887 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400888 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400889 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400890 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400891
Clarence Ip5e2a9222016-06-26 22:38:24 -0400892 /* update scaler */
893 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -0400894 int error;
895
896 error = _sde_plane_setup_scaler3_lut(psde, pstate);
897 if (error || !psde->pixel_ext_usr) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400898 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -0400899 _sde_plane_setup_scaler3(psde,
900 psde->pipe_cfg.src_rect.w,
901 psde->pipe_cfg.src_rect.h,
902 psde->pipe_cfg.dst_rect.w,
903 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -0400904 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400905 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400906 }
Clarence Ipb43d4592016-09-08 14:21:35 -0400907 } else if (!psde->pixel_ext_usr) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500908 uint32_t deci_dim, i;
909
Clarence Ipb43d4592016-09-08 14:21:35 -0400910 /* calculate default configuration for QSEED2 */
911 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400912
Clarence Ip13a8cf42016-09-29 17:27:47 -0400913 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500914 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
915 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -0400916 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500917 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -0400918 psde->pipe_cfg.dst_rect.w,
919 pe->phase_step_x,
920 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400921
Clarence Ipdbde9832016-06-26 09:48:36 -0400922 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500923 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -0400924 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500925 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400926 pe->phase_step_x,
927 pe->roi_w,
928 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -0400929 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400930 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400931
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500932 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400933 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500934 _sde_plane_setup_scaler2(psde,
935 deci_dim,
936 psde->pipe_cfg.dst_rect.h,
937 pe->phase_step_y,
938 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -0400939 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -0500940 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400941 pe->phase_step_y,
942 pe->roi_h,
943 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -0400944 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400945 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400946
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400947 for (i = 0; i < SDE_MAX_PLANES; i++) {
948 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400949 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400950 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400951 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400952
953 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400954 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400955 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400956 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400957
958 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400959 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400960 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400961 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400962
963 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400964 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400965 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400966 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400967 }
968 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400969}
970
Clarence Ipcae1bb62016-07-07 12:07:13 -0400971/**
972 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -0400973 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -0400974 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
975 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
976 * Returns: 0 on success
977 */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400978static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -0400979 uint32_t color, uint32_t alpha)
980{
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400981 const struct sde_format *fmt;
Clarence Ipcb410d42016-06-26 22:52:33 -0400982
Clarence Ip13a8cf42016-09-29 17:27:47 -0400983 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700984 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400985 return -EINVAL;
986 }
987
Clarence Ipcb410d42016-06-26 22:52:33 -0400988 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400989 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400990 return -EINVAL;
991 }
992
Clarence Ip13a8cf42016-09-29 17:27:47 -0400993 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400994
Clarence Ipcb410d42016-06-26 22:52:33 -0400995 /*
996 * select fill format to match user property expectation,
997 * h/w only supports RGB variants
998 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400999 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001000
1001 /* update sspp */
1002 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1003 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
1004 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
1005
1006 /* override scaler/decimation if solid fill */
1007 psde->pipe_cfg.src_rect.x = 0;
1008 psde->pipe_cfg.src_rect.y = 0;
1009 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1010 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
1011
1012 _sde_plane_setup_scaler(psde, fmt, 0);
1013
1014 if (psde->pipe_hw->ops.setup_format)
1015 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
1016 fmt, SDE_SSPP_SOLID_FILL);
1017
1018 if (psde->pipe_hw->ops.setup_rects)
1019 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -04001020 &psde->pipe_cfg, &psde->pixel_ext,
1021 psde->scaler3_cfg);
Clarence Ipcb410d42016-06-26 22:52:33 -04001022 }
1023
1024 return 0;
1025}
1026
1027static int _sde_plane_mode_set(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001028 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -04001029{
Clarence Ipc47a0692016-10-11 10:54:17 -04001030 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -04001031 struct sde_plane *psde;
1032 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001033 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001034 struct drm_crtc *crtc;
1035 struct drm_framebuffer *fb;
1036 struct sde_rect src, dst;
1037 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001038 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -04001039
Clarence Ip13a8cf42016-09-29 17:27:47 -04001040 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -04001041 SDE_ERROR("invalid plane\n");
1042 return -EINVAL;
1043 } else if (!plane->state) {
1044 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001045 return -EINVAL;
1046 }
1047
1048 psde = to_sde_plane(plane);
1049 pstate = to_sde_plane_state(plane->state);
Clarence Ipcb410d42016-06-26 22:52:33 -04001050
Dhaval Patel47302cf2016-08-18 15:04:28 -07001051 crtc = state->crtc;
1052 fb = state->fb;
1053 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001054 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
1055 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -07001056 return -EINVAL;
1057 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001058 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001059 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -04001060
Clarence Ip282dad62016-09-27 17:07:35 -04001061 /* determine what needs to be refreshed */
1062 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
1063 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001064 case PLANE_PROP_SCALER_V1:
abeykun48f407a2016-08-25 12:06:44 -04001065 case PLANE_PROP_SCALER_V2:
Clarence Ipdedbba92016-09-27 17:43:10 -04001066 case PLANE_PROP_H_DECIMATE:
1067 case PLANE_PROP_V_DECIMATE:
1068 case PLANE_PROP_SRC_CONFIG:
1069 case PLANE_PROP_ZPOS:
Clarence Ip282dad62016-09-27 17:07:35 -04001070 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1071 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001072 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -04001073 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
1074 break;
1075 case PLANE_PROP_COLOR_FILL:
1076 /* potentially need to refresh everything */
1077 pstate->dirty = SDE_PLANE_DIRTY_ALL;
1078 break;
1079 case PLANE_PROP_ROTATION:
1080 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
1081 break;
Clarence Ip282dad62016-09-27 17:07:35 -04001082 case PLANE_PROP_INFO:
1083 case PLANE_PROP_ALPHA:
1084 case PLANE_PROP_INPUT_FENCE:
1085 case PLANE_PROP_BLEND_OP:
1086 /* no special action required */
1087 break;
1088 default:
1089 /* unknown property, refresh everything */
1090 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
1091 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
1092 break;
1093 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001094 }
1095
Clarence Ip282dad62016-09-27 17:07:35 -04001096 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
1097 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -04001098
1099 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
1100
Clarence Ip282dad62016-09-27 17:07:35 -04001101 /* early out if nothing dirty */
1102 if (!pstate->dirty)
1103 return 0;
1104 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001105
Clarence Ip0d0e96d2016-10-24 18:13:13 -04001106 psde->is_rt_pipe = sde_crtc_is_rt(crtc);
Clarence Ip282dad62016-09-27 17:07:35 -04001107 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1108
1109 /* update roi config */
1110 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
1111 POPULATE_RECT(&src, state->src_x, state->src_y,
1112 state->src_w, state->src_h, q16_data);
1113 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
1114 state->crtc_w, state->crtc_h, !q16_data);
1115
Clarence Ip13a8cf42016-09-29 17:27:47 -04001116 SDE_DEBUG_PLANE(psde,
1117 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001118 fb->base.id, src.x, src.y, src.w, src.h,
1119 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
1120 drm_get_format_name(fmt->base.pixel_format),
1121 SDE_FORMAT_IS_UBWC(fmt));
1122
1123 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
1124 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001125 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001126 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
1127 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
1128 src.h /= 2;
1129 src.y = DIV_ROUND_UP(src.y, 2);
1130 src.y &= ~0x1;
1131 }
1132
1133 psde->pipe_cfg.src_rect = src;
1134 psde->pipe_cfg.dst_rect = dst;
1135
1136 /* check for color fill */
1137 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
1138 PLANE_PROP_COLOR_FILL);
1139 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
1140 /* skip remaining processing on color fill */
1141 pstate->dirty = 0x0;
1142 } else if (psde->pipe_hw->ops.setup_rects) {
1143 _sde_plane_setup_scaler(psde, fmt, pstate);
1144
Clarence Ip282dad62016-09-27 17:07:35 -04001145 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -04001146 &psde->pipe_cfg, &psde->pixel_ext,
1147 psde->scaler3_cfg);
Clarence Ip282dad62016-09-27 17:07:35 -04001148 }
Dhaval Patel48c76022016-09-01 17:51:23 -07001149 }
1150
Clarence Ip282dad62016-09-27 17:07:35 -04001151 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
1152 psde->pipe_hw->ops.setup_format) {
1153 src_flags = 0x0;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001154 SDE_DEBUG_PLANE(psde, "rotation 0x%llX\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001155 sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
1156 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1157 BIT(DRM_REFLECT_X))
1158 src_flags |= SDE_SSPP_FLIP_LR;
1159 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1160 BIT(DRM_REFLECT_Y))
1161 src_flags |= SDE_SSPP_FLIP_UD;
1162
1163 /* update format */
1164 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags);
1165
1166 /* update csc */
1167 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04001168 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04001169 else
1170 psde->csc_ptr = 0;
1171 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001172
Benet Clarkeb1b4462016-06-27 14:43:06 -07001173 sde_color_process_plane_setup(plane);
1174
Clarence Ipe78efb72016-06-24 18:35:21 -04001175 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04001176 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
1177 psde->pipe_hw->ops.setup_sharpening) {
1178 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
1179 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
1180 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
1181 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04001182
Clarence Ipe78efb72016-06-24 18:35:21 -04001183 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04001184 &psde->sharp_cfg);
1185 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001186
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001187 _sde_plane_set_qos_lut(plane, fb);
1188 _sde_plane_set_danger_lut(plane, fb);
1189
Alan Kwong5d324e42016-07-28 22:56:18 -04001190 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001191 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04001192 _sde_plane_set_ot_limit(plane, crtc);
1193 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001194
Clarence Ip282dad62016-09-27 17:07:35 -04001195 /* clear dirty */
1196 pstate->dirty = 0x0;
1197
Clarence Ip5e2a9222016-06-26 22:38:24 -04001198 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001199}
1200
1201static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001202 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001203{
1204 struct drm_framebuffer *fb = new_state->fb;
1205 struct sde_plane *psde = to_sde_plane(plane);
1206
1207 if (!new_state->fb)
1208 return 0;
1209
Clarence Ip13a8cf42016-09-29 17:27:47 -04001210 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001211 return msm_framebuffer_prepare(fb, psde->mmu_id);
1212}
1213
1214static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001215 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001216{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001217 struct drm_framebuffer *fb = old_state ? old_state->fb : NULL;
1218 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001219
1220 if (!fb)
1221 return;
1222
Clarence Ip13a8cf42016-09-29 17:27:47 -04001223 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001224 msm_framebuffer_cleanup(fb, psde->mmu_id);
1225}
1226
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001227static void _sde_plane_atomic_check_mode_changed(struct sde_plane *psde,
1228 struct drm_plane_state *state,
1229 struct drm_plane_state *old_state)
1230{
1231 struct sde_plane_state *pstate = to_sde_plane_state(state);
1232
Dhaval Patel47302cf2016-08-18 15:04:28 -07001233 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04001234 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001235 return;
1236
Clarence Ip282dad62016-09-27 17:07:35 -04001237 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
1238 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001239 SDE_DEBUG_PLANE(psde,
1240 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001241 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001242 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001243 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001244 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001245 } else if (state->src_w != old_state->src_w ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07001246 state->src_h != old_state->src_h ||
1247 state->src_x != old_state->src_x ||
1248 state->src_y != old_state->src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001249 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001250 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001251 } else if (state->crtc_w != old_state->crtc_w ||
1252 state->crtc_h != old_state->crtc_h ||
1253 state->crtc_x != old_state->crtc_x ||
1254 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001255 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001256 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1257 }
1258
1259 if (!state->fb || !old_state->fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001260 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001261 } else if (state->fb->pixel_format != old_state->fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001262 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001263 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001264 } else {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001265 uint64_t *new_mods = state->fb->modifier;
1266 uint64_t *old_mods = old_state->fb->modifier;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001267 uint32_t *new_pitches = state->fb->pitches;
1268 uint32_t *old_pitches = old_state->fb->pitches;
1269 uint32_t *new_offset = state->fb->offsets;
1270 uint32_t *old_offset = old_state->fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001271 int i;
1272
1273 for (i = 0; i < ARRAY_SIZE(state->fb->modifier); i++) {
1274 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001275 SDE_DEBUG_PLANE(psde,
1276 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001277 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001278 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001279 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1280 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001281 break;
1282 }
1283 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001284 for (i = 0; i < ARRAY_SIZE(state->fb->pitches); i++) {
1285 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001286 SDE_DEBUG_PLANE(psde,
1287 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001288 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001289 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001290 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001291 break;
1292 }
1293 }
Dhaval Patel47302cf2016-08-18 15:04:28 -07001294 for (i = 0; i < ARRAY_SIZE(state->fb->offsets); i++) {
1295 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001296 SDE_DEBUG_PLANE(psde,
1297 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001298 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001299 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001300 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1301 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001302 break;
1303 }
1304 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001305 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001306}
1307
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001308static int sde_plane_atomic_check(struct drm_plane *plane,
1309 struct drm_plane_state *state)
1310{
Clarence Ipdedbba92016-09-27 17:43:10 -04001311 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04001312 struct sde_plane *psde;
1313 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001314 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001315 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04001316 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001317 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
1318 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04001319
1320 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001321 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1322 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04001323 ret = -EINVAL;
1324 goto exit;
1325 }
1326
1327 psde = to_sde_plane(plane);
1328 pstate = to_sde_plane_state(state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001329
1330 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001331 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001332 ret = -EINVAL;
1333 goto exit;
1334 }
1335
Clarence Ipdedbba92016-09-27 17:43:10 -04001336 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1337 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04001338
1339 /* src values are in Q16 fixed point, convert to integer */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001340 POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w,
1341 state->src_h, q16_data);
1342 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
1343 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04001344
Dhaval Patel47302cf2016-08-18 15:04:28 -07001345 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
1346 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04001347
Dhaval Patel47302cf2016-08-18 15:04:28 -07001348 max_upscale = psde->pipe_sblk->maxupscale;
1349 max_downscale = psde->pipe_sblk->maxdwnscale;
1350 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04001351
Clarence Ip13a8cf42016-09-29 17:27:47 -04001352 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001353 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001354
Dhaval Patel47302cf2016-08-18 15:04:28 -07001355 if (!sde_plane_enabled(state))
1356 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04001357
Dhaval Patel47302cf2016-08-18 15:04:28 -07001358 fmt = to_sde_format(msm_framebuffer_format(state->fb));
1359
1360 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
1361
1362 if (SDE_FORMAT_IS_YUV(fmt) &&
1363 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04001364 !(psde->features & (BIT(SDE_SSPP_CSC)
1365 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001366 SDE_ERROR_PLANE(psde,
1367 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07001368 ret = -EINVAL;
1369
1370 /* check src bounds */
1371 } else if (state->fb->width > MAX_IMG_WIDTH ||
1372 state->fb->height > MAX_IMG_HEIGHT ||
1373 src.w < min_src_size || src.h < min_src_size ||
1374 CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) ||
1375 CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001376 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001377 src.x, src.y, src.w, src.h);
1378 ret = -E2BIG;
1379
1380 /* valid yuv image */
1381 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
1382 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001383 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001384 src.x, src.y, src.w, src.h);
1385 ret = -EINVAL;
1386
1387 /* min dst support */
1388 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001389 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001390 dst.x, dst.y, dst.w, dst.h);
1391 ret = -EINVAL;
1392
1393 /* decimation validation */
1394 } else if (deci_w || deci_h) {
1395 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
1396 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001397 SDE_ERROR_PLANE(psde,
1398 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001399 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001400 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001401 SDE_ERROR_PLANE(psde,
1402 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001403 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001404 }
1405
Dhaval Patel47302cf2016-08-18 15:04:28 -07001406 } else if (!(psde->features & SDE_SSPP_SCALER) &&
1407 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001408 SDE_ERROR_PLANE(psde,
1409 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001410 src.w, src.h, dst.w, dst.h);
1411 ret = -EINVAL;
1412
1413 /* check decimated source width */
1414 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001415 SDE_ERROR_PLANE(psde,
1416 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001417 src.w, src_deci_w, max_linewidth);
1418 ret = -E2BIG;
1419
1420 /* check max scaler capability */
1421 } else if (((src_deci_w * max_upscale) < dst.w) ||
1422 ((src_deci_h * max_upscale) < dst.h) ||
1423 ((dst.w * max_downscale) < src_deci_w) ||
1424 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001425 SDE_ERROR_PLANE(psde,
1426 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001427 src_deci_w, src_deci_h, dst.w, dst.h);
1428 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001429 }
1430
Dhaval Patel47302cf2016-08-18 15:04:28 -07001431modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001432 if (!ret)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001433 _sde_plane_atomic_check_mode_changed(psde, state, plane->state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001434exit:
1435 return ret;
1436}
1437
Clarence Ipcae1bb62016-07-07 12:07:13 -04001438/**
1439 * sde_plane_flush - final plane operations before commit flush
1440 * @plane: Pointer to drm plane structure
1441 */
1442void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04001443{
Clarence Ipcae1bb62016-07-07 12:07:13 -04001444 struct sde_plane *psde;
1445
Clarence Ip13a8cf42016-09-29 17:27:47 -04001446 if (!plane) {
1447 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001448 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001449 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04001450
1451 psde = to_sde_plane(plane);
1452
1453 /*
1454 * These updates have to be done immediately before the plane flush
1455 * timing, and may not be moved to the atomic_update/mode_set functions.
1456 */
1457 if (psde->is_error)
1458 /* force white frame with 0% alpha pipe output on error */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001459 _sde_plane_color_fill(psde, 0xFFFFFF, 0x0);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001460 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
1461 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001462 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001463 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
1464 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
1465
1466 /* flag h/w flush complete */
1467 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04001468 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001469}
1470
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001471static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04001472 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001473{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001474 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001475 struct drm_plane_state *state;
1476 struct sde_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001477
Clarence Ip13a8cf42016-09-29 17:27:47 -04001478 if (!plane) {
1479 SDE_ERROR("invalid plane\n");
1480 return;
1481 } else if (!plane->state) {
1482 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04001483 return;
1484 }
1485
Clarence Ip13a8cf42016-09-29 17:27:47 -04001486 psde = to_sde_plane(plane);
1487 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001488 state = plane->state;
1489 pstate = to_sde_plane_state(state);
1490
Clarence Ip13a8cf42016-09-29 17:27:47 -04001491 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001492
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001493 if (!sde_plane_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04001494 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001495 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001496 int ret;
1497
Dhaval Patel47302cf2016-08-18 15:04:28 -07001498 ret = _sde_plane_mode_set(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001499 /* atomic_check should have ensured that this doesn't fail */
1500 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001501 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001502}
1503
Dhaval Patel47302cf2016-08-18 15:04:28 -07001504
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001505/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001506static void _sde_plane_install_properties(struct drm_plane *plane,
Clarence Ipc47a0692016-10-11 10:54:17 -04001507 struct sde_mdss_cfg *catalog)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001508{
Clarence Ip5e2a9222016-06-26 22:38:24 -04001509 static const struct drm_prop_enum_list e_blend_op[] = {
1510 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
1511 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
1512 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
1513 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
1514 };
1515 static const struct drm_prop_enum_list e_src_config[] = {
1516 {SDE_DRM_DEINTERLACE, "deinterlace"}
1517 };
Clarence Ipea3d6262016-07-15 16:20:11 -04001518 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07001519 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001520 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04001521 int zpos_max = 255;
1522 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001523 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001524
Clarence Ip13a8cf42016-09-29 17:27:47 -04001525 if (!plane || !psde) {
1526 SDE_ERROR("invalid plane\n");
1527 return;
1528 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
1529 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
1530 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001531 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04001532 } else if (!catalog) {
1533 SDE_ERROR("invalid catalog\n");
1534 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001535 }
1536
Clarence Ipc47a0692016-10-11 10:54:17 -04001537 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04001538 if (catalog->mixer_count && catalog->mixer &&
1539 catalog->mixer[0].sblk->maxblendstages) {
1540 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
1541 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
1542 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
1543 }
Clarence Ipc47a0692016-10-11 10:54:17 -04001544 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
1545 /* reserve zpos == 0 for primary planes */
1546 zpos_def = drm_plane_index(plane) + 1;
1547 }
1548
1549 msm_property_install_range(&psde->property_info, "zpos",
1550 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001551
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001552 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001553 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001554
Dhaval Patel47302cf2016-08-18 15:04:28 -07001555 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001556 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07001557 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001558
Clarence Ipdedbba92016-09-27 17:43:10 -04001559 if (psde->pipe_sblk->maxhdeciexp) {
1560 msm_property_install_range(&psde->property_info, "h_decimate",
1561 0x0, 0, psde->pipe_sblk->maxhdeciexp, 0,
1562 PLANE_PROP_H_DECIMATE);
1563 }
1564
1565 if (psde->pipe_sblk->maxvdeciexp) {
1566 msm_property_install_range(&psde->property_info, "v_decimate",
1567 0x0, 0, psde->pipe_sblk->maxvdeciexp, 0,
1568 PLANE_PROP_V_DECIMATE);
1569 }
1570
abeykun48f407a2016-08-25 12:06:44 -04001571 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
1572 msm_property_install_volatile_range(&psde->property_info,
1573 "scaler_v2", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
1574 msm_property_install_blob(&psde->property_info, "lut_ed", 0,
1575 PLANE_PROP_SCALER_LUT_ED);
1576 msm_property_install_blob(&psde->property_info, "lut_cir", 0,
1577 PLANE_PROP_SCALER_LUT_CIR);
1578 msm_property_install_blob(&psde->property_info, "lut_sep", 0,
1579 PLANE_PROP_SCALER_LUT_SEP);
1580 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001581 msm_property_install_volatile_range(&psde->property_info,
1582 "scaler_v1", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V1);
1583 }
1584
Clarence Ip5fc00c52016-09-23 15:03:34 -04001585 if (psde->features & BIT(SDE_SSPP_CSC)) {
1586 msm_property_install_volatile_range(&psde->property_info,
1587 "csc_v1", 0x0, 0, ~0, 0, PLANE_PROP_CSC_V1);
1588 }
1589
Benet Clarkeb1b4462016-06-27 14:43:06 -07001590 if (psde->features & BIT(SDE_SSPP_HSIC)) {
1591 snprintf(feature_name, sizeof(feature_name), "%s%d",
1592 "SDE_SSPP_HUE_V",
1593 psde->pipe_sblk->hsic_blk.version >> 16);
1594 msm_property_install_range(&psde->property_info,
1595 feature_name, 0, 0, 0xFFFFFFFF, 0,
1596 PLANE_PROP_HUE_ADJUST);
1597 snprintf(feature_name, sizeof(feature_name), "%s%d",
1598 "SDE_SSPP_SATURATION_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_SATURATION_ADJUST);
1603 snprintf(feature_name, sizeof(feature_name), "%s%d",
1604 "SDE_SSPP_VALUE_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_VALUE_ADJUST);
1609 snprintf(feature_name, sizeof(feature_name), "%s%d",
1610 "SDE_SSPP_CONTRAST_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_CONTRAST_ADJUST);
1615 }
1616
Clarence Ip5e2a9222016-06-26 22:38:24 -04001617 /* standard properties */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001618 msm_property_install_rotation(&psde->property_info,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07001619 (unsigned int) (BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y)),
1620 PLANE_PROP_ROTATION);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001621
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001622 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001623 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001624
Dhaval Patel47302cf2016-08-18 15:04:28 -07001625 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
1626 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
1627
1628 if (psde->pipe_hw->ops.setup_solidfill)
1629 msm_property_install_range(&psde->property_info, "color_fill",
1630 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
1631
Dhaval Patel4e574842016-08-23 15:11:37 -07001632 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001633 if (!info) {
1634 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07001635 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001636 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001637
1638 msm_property_install_blob(&psde->property_info, "capabilities",
1639 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
1640 sde_kms_info_reset(info);
1641
Clarence Ipea3d6262016-07-15 16:20:11 -04001642 format_list = psde->pipe_sblk->format_list;
1643 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04001644 sde_kms_info_start(info, "pixel_formats");
1645 while (format_list->fourcc_format) {
1646 sde_kms_info_append_format(info,
1647 format_list->fourcc_format,
1648 format_list->modifier);
1649 ++format_list;
1650 }
1651 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04001652 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001653
1654 sde_kms_info_add_keyint(info, "max_linewidth",
1655 psde->pipe_sblk->maxlinewidth);
1656 sde_kms_info_add_keyint(info, "max_upscale",
1657 psde->pipe_sblk->maxupscale);
1658 sde_kms_info_add_keyint(info, "max_downscale",
1659 psde->pipe_sblk->maxdwnscale);
1660 sde_kms_info_add_keyint(info, "max_horizontal_deci",
1661 psde->pipe_sblk->maxhdeciexp);
1662 sde_kms_info_add_keyint(info, "max_vertical_deci",
1663 psde->pipe_sblk->maxvdeciexp);
1664 msm_property_set_blob(&psde->property_info, &psde->blob_info,
1665 info->data, info->len, PLANE_PROP_INFO);
1666
1667 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07001668
1669 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
1670 snprintf(feature_name, sizeof(feature_name), "%s%d",
1671 "SDE_SSPP_SKIN_COLOR_V",
1672 psde->pipe_sblk->memcolor_blk.version >> 16);
1673 msm_property_install_blob(&psde->property_info, feature_name, 0,
1674 PLANE_PROP_SKIN_COLOR);
1675 snprintf(feature_name, sizeof(feature_name), "%s%d",
1676 "SDE_SSPP_SKY_COLOR_V",
1677 psde->pipe_sblk->memcolor_blk.version >> 16);
1678 msm_property_install_blob(&psde->property_info, feature_name, 0,
1679 PLANE_PROP_SKY_COLOR);
1680 snprintf(feature_name, sizeof(feature_name), "%s%d",
1681 "SDE_SSPP_FOLIAGE_COLOR_V",
1682 psde->pipe_sblk->memcolor_blk.version >> 16);
1683 msm_property_install_blob(&psde->property_info, feature_name, 0,
1684 PLANE_PROP_FOLIAGE_COLOR);
1685 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001686}
1687
Clarence Ip5fc00c52016-09-23 15:03:34 -04001688static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
1689{
1690 struct sde_drm_csc_v1 csc_v1;
1691 int i;
1692
1693 if (!psde) {
1694 SDE_ERROR("invalid plane\n");
1695 return;
1696 }
1697
1698 psde->csc_usr_ptr = NULL;
1699 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001700 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001701 return;
1702 }
1703
1704 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001705 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001706 return;
1707 }
1708
Clarence Ipb43d4592016-09-08 14:21:35 -04001709 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001710 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
1711 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
1712 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
1713 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
1714 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
1715 }
1716 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
1717 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
1718 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
1719 }
1720 psde->csc_usr_ptr = &psde->csc_cfg;
1721}
1722
Clarence Ipb43d4592016-09-08 14:21:35 -04001723static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
1724{
1725 struct sde_drm_scaler_v1 scale_v1;
1726 struct sde_hw_pixel_ext *pe;
1727 int i;
1728
1729 if (!psde) {
1730 SDE_ERROR("invalid plane\n");
1731 return;
1732 }
1733
1734 psde->pixel_ext_usr = false;
1735 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001736 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001737 return;
1738 }
1739
1740 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001741 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001742 return;
1743 }
1744
1745 /* populate from user space */
1746 pe = &(psde->pixel_ext);
1747 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1748 for (i = 0; i < SDE_MAX_PLANES; i++) {
1749 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
1750 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
1751 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
1752 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
1753
1754 pe->horz_filter[i] = scale_v1.horz_filter[i];
1755 pe->vert_filter[i] = scale_v1.vert_filter[i];
1756 }
1757 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05001758 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
1759 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
1760 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
1761 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
1762 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04001763
abeykun41060122016-11-28 13:02:01 -05001764 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
1765 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
1766 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
1767 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
1768 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04001769 }
abeykun41060122016-11-28 13:02:01 -05001770
Clarence Ipb43d4592016-09-08 14:21:35 -04001771 psde->pixel_ext_usr = true;
1772
Clarence Ip13a8cf42016-09-29 17:27:47 -04001773 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001774}
1775
abeykun48f407a2016-08-25 12:06:44 -04001776static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
1777 struct sde_plane_state *pstate, void *usr)
1778{
1779 struct sde_drm_scaler_v2 scale_v2;
1780 struct sde_hw_pixel_ext *pe;
1781 int i;
1782 struct sde_hw_scaler3_cfg *cfg;
1783
1784 if (!psde) {
1785 SDE_ERROR("invalid plane\n");
1786 return;
1787 }
1788
1789 cfg = psde->scaler3_cfg;
1790 psde->pixel_ext_usr = false;
1791 if (!usr) {
1792 SDE_DEBUG_PLANE(psde, "scale data removed\n");
1793 return;
1794 }
1795
1796 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
1797 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
1798 return;
1799 }
1800
1801 /* populate from user space */
1802 pe = &(psde->pixel_ext);
1803 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1804 cfg->enable = scale_v2.enable;
1805 cfg->dir_en = scale_v2.dir_en;
1806 for (i = 0; i < SDE_MAX_PLANES; i++) {
1807 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
1808 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
1809 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
1810 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
1811
1812 cfg->preload_x[i] = scale_v2.preload_x[i];
1813 cfg->preload_y[i] = scale_v2.preload_y[i];
1814 cfg->src_width[i] = scale_v2.src_width[i];
1815 cfg->src_height[i] = scale_v2.src_height[i];
1816 }
1817 cfg->dst_width = scale_v2.dst_width;
1818 cfg->dst_height = scale_v2.dst_height;
1819
1820 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
1821 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
1822 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
1823 cfg->blend_cfg = scale_v2.blend_cfg;
1824
1825 cfg->lut_flag = scale_v2.lut_flag;
1826 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
1827 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
1828 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
1829 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
1830 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
1831
1832 cfg->de.enable = scale_v2.de.enable;
1833 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
1834 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
1835 cfg->de.clip = scale_v2.de.clip;
1836 cfg->de.limit = scale_v2.de.limit;
1837 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
1838 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
1839 cfg->de.thr_low = scale_v2.de.thr_low;
1840 cfg->de.thr_high = scale_v2.de.thr_high;
1841 cfg->de.prec_shift = scale_v2.de.prec_shift;
1842 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
1843 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
1844 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
1845 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
1846 }
1847 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05001848 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
1849 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
1850 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
1851 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
1852 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04001853
abeykun41060122016-11-28 13:02:01 -05001854 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
1855 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
1856 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
1857 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
1858 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04001859 }
1860 psde->pixel_ext_usr = true;
1861
1862 SDE_DEBUG_PLANE(psde, "user property data copied\n");
1863}
1864
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001865static int sde_plane_atomic_set_property(struct drm_plane *plane,
1866 struct drm_plane_state *state, struct drm_property *property,
1867 uint64_t val)
1868{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001869 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001870 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001871 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001872
Clarence Ip13a8cf42016-09-29 17:27:47 -04001873 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001874
1875 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001876 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001877 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001878 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001879 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04001880 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001881 ret = msm_property_atomic_set(&psde->property_info,
1882 pstate->property_values, pstate->property_blobs,
1883 property, val);
1884 if (!ret) {
1885 idx = msm_property_index(&psde->property_info,
1886 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001887 switch (idx) {
1888 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04001889 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001890 break;
1891 case PLANE_PROP_CSC_V1:
1892 _sde_plane_set_csc_v1(psde, (void *)val);
1893 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04001894 case PLANE_PROP_SCALER_V1:
1895 _sde_plane_set_scaler_v1(psde, (void *)val);
1896 break;
abeykun48f407a2016-08-25 12:06:44 -04001897 case PLANE_PROP_SCALER_V2:
1898 _sde_plane_set_scaler_v2(psde, pstate,
1899 (void *)val);
1900 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001901 default:
1902 /* nothing to do */
1903 break;
1904 }
Clarence Ipe78efb72016-06-24 18:35:21 -04001905 }
1906 }
1907
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001908 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001909}
1910
1911static int sde_plane_set_property(struct drm_plane *plane,
1912 struct drm_property *property, uint64_t val)
1913{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001914 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001915
Clarence Ipae4e60c2016-06-26 22:44:04 -04001916 return sde_plane_atomic_set_property(plane,
1917 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001918}
1919
1920static int sde_plane_atomic_get_property(struct drm_plane *plane,
1921 const struct drm_plane_state *state,
1922 struct drm_property *property, uint64_t *val)
1923{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001924 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001925 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04001926 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001927
Clarence Ipaa0faf42016-05-30 12:07:48 -04001928 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001929 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001930 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001931 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001932 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001933 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001934 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001935 ret = msm_property_atomic_get(&psde->property_info,
1936 pstate->property_values, pstate->property_blobs,
1937 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04001938 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001939
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001940 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001941}
1942
1943static void sde_plane_destroy(struct drm_plane *plane)
1944{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001945 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001946
Clarence Ip13a8cf42016-09-29 17:27:47 -04001947 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001948
Clarence Ip13a8cf42016-09-29 17:27:47 -04001949 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001950 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1951
Clarence Ip4ce59322016-06-26 22:27:51 -04001952 debugfs_remove_recursive(psde->debugfs_root);
Clarence Ipe78efb72016-06-24 18:35:21 -04001953
Dhaval Patel4e574842016-08-23 15:11:37 -07001954 if (psde->blob_info)
1955 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001956 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04001957 mutex_destroy(&psde->lock);
1958
Clarence Ip4ce59322016-06-26 22:27:51 -04001959 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001960
Clarence Ip4ce59322016-06-26 22:27:51 -04001961 /* this will destroy the states as well */
1962 drm_plane_cleanup(plane);
1963
Clarence Ip4c1d9772016-06-26 09:35:38 -04001964 if (psde->pipe_hw)
1965 sde_hw_sspp_destroy(psde->pipe_hw);
1966
Clarence Ip4ce59322016-06-26 22:27:51 -04001967 kfree(psde);
1968 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001969}
1970
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001971static void sde_plane_destroy_state(struct drm_plane *plane,
1972 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001973{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001974 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04001975 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001976
Clarence Ipae4e60c2016-06-26 22:44:04 -04001977 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001978 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1979 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001980 return;
1981 }
1982
Clarence Ipaa0faf42016-05-30 12:07:48 -04001983 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04001984 pstate = to_sde_plane_state(state);
1985
Clarence Ip13a8cf42016-09-29 17:27:47 -04001986 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001987
Clarence Ipe78efb72016-06-24 18:35:21 -04001988 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001989 if (state->fb)
1990 drm_framebuffer_unreference(state->fb);
1991
Clarence Ipae4e60c2016-06-26 22:44:04 -04001992 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001993 if (pstate->input_fence)
1994 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001995
Clarence Ipaa0faf42016-05-30 12:07:48 -04001996 /* destroy value helper */
1997 msm_property_destroy_state(&psde->property_info, pstate,
1998 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001999}
2000
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002001static struct drm_plane_state *
2002sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002003{
Clarence Ipaa0faf42016-05-30 12:07:48 -04002004 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002005 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04002006 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04002007 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002008
Clarence Ip13a8cf42016-09-29 17:27:47 -04002009 if (!plane) {
2010 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002011 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002012 } else if (!plane->state) {
2013 SDE_ERROR("invalid plane state\n");
2014 return NULL;
2015 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002016
Clarence Ip730e7192016-06-26 22:45:09 -04002017 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002018 psde = to_sde_plane(plane);
2019 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002020 if (!pstate) {
2021 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002022 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002023 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002024
Clarence Ip13a8cf42016-09-29 17:27:47 -04002025 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002026
2027 /* duplicate value helper */
2028 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
2029 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04002030
Clarence Ip730e7192016-06-26 22:45:09 -04002031 /* add ref count for frame buffer */
2032 if (pstate->base.fb)
2033 drm_framebuffer_reference(pstate->base.fb);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002034
Clarence Ip17e908b2016-09-29 15:58:00 -04002035 /* clear out any input fence */
2036 pstate->input_fence = 0;
2037 input_fence_default = msm_property_get_default(
2038 &psde->property_info, PLANE_PROP_INPUT_FENCE);
2039 msm_property_set_property(&psde->property_info, pstate->property_values,
2040 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002041
Clarence Ip282dad62016-09-27 17:07:35 -04002042 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04002043 pstate->pending = false;
2044
2045 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002046}
2047
2048static void sde_plane_reset(struct drm_plane *plane)
2049{
Clarence Ipae4e60c2016-06-26 22:44:04 -04002050 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002051 struct sde_plane_state *pstate;
2052
Clarence Ipae4e60c2016-06-26 22:44:04 -04002053 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002054 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04002055 return;
2056 }
2057
Clarence Ip730e7192016-06-26 22:45:09 -04002058 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002059 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04002060
Clarence Ipae4e60c2016-06-26 22:44:04 -04002061 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04002062 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04002063 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04002064 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04002065 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002066
Clarence Ipaa0faf42016-05-30 12:07:48 -04002067 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04002068 if (!pstate) {
2069 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04002070 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002071 }
Clarence Ip730e7192016-06-26 22:45:09 -04002072
Clarence Ipaa0faf42016-05-30 12:07:48 -04002073 /* reset value helper */
2074 msm_property_reset_state(&psde->property_info, pstate,
2075 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002076
2077 pstate->base.plane = plane;
2078
2079 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002080}
2081
2082static const struct drm_plane_funcs sde_plane_funcs = {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002083 .update_plane = drm_atomic_helper_update_plane,
2084 .disable_plane = drm_atomic_helper_disable_plane,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002085 .destroy = sde_plane_destroy,
2086 .set_property = sde_plane_set_property,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002087 .atomic_set_property = sde_plane_atomic_set_property,
2088 .atomic_get_property = sde_plane_atomic_get_property,
2089 .reset = sde_plane_reset,
2090 .atomic_duplicate_state = sde_plane_duplicate_state,
2091 .atomic_destroy_state = sde_plane_destroy_state,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002092};
2093
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002094static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
2095 .prepare_fb = sde_plane_prepare_fb,
2096 .cleanup_fb = sde_plane_cleanup_fb,
2097 .atomic_check = sde_plane_atomic_check,
2098 .atomic_update = sde_plane_atomic_update,
2099};
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002100
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002101enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002102{
Clarence Ip13a8cf42016-09-29 17:27:47 -04002103 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002104}
2105
Alan Kwongf0fd8512016-10-24 21:39:26 -04002106static ssize_t _sde_plane_danger_read(struct file *file,
2107 char __user *buff, size_t count, loff_t *ppos)
2108{
2109 struct sde_kms *kms = file->private_data;
2110 struct sde_mdss_cfg *cfg = kms->catalog;
2111 int len = 0;
2112 char buf[40] = {'\0'};
2113
2114 if (!cfg)
2115 return -ENODEV;
2116
2117 if (*ppos)
2118 return 0; /* the end */
2119
2120 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
2121 if (len < 0 || len >= sizeof(buf))
2122 return 0;
2123
2124 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
2125 return -EFAULT;
2126
2127 *ppos += len; /* increase offset */
2128
2129 return len;
2130}
2131
2132static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
2133{
2134 struct drm_plane *plane;
2135
2136 drm_for_each_plane(plane, kms->dev) {
2137 if (plane->fb && plane->state) {
2138 sde_plane_danger_signal_ctrl(plane, enable);
2139 SDE_DEBUG("plane:%d img:%dx%d ",
2140 plane->base.id, plane->fb->width,
2141 plane->fb->height);
2142 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
2143 plane->state->src_x >> 16,
2144 plane->state->src_y >> 16,
2145 plane->state->src_w >> 16,
2146 plane->state->src_h >> 16,
2147 plane->state->crtc_x, plane->state->crtc_y,
2148 plane->state->crtc_w, plane->state->crtc_h);
2149 } else {
2150 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
2151 }
2152 }
2153}
2154
2155static ssize_t _sde_plane_danger_write(struct file *file,
2156 const char __user *user_buf, size_t count, loff_t *ppos)
2157{
2158 struct sde_kms *kms = file->private_data;
2159 struct sde_mdss_cfg *cfg = kms->catalog;
2160 int disable_panic;
2161 char buf[10];
2162
2163 if (!cfg)
2164 return -EFAULT;
2165
2166 if (count >= sizeof(buf))
2167 return -EFAULT;
2168
2169 if (copy_from_user(buf, user_buf, count))
2170 return -EFAULT;
2171
2172 buf[count] = 0; /* end of string */
2173
2174 if (kstrtoint(buf, 0, &disable_panic))
2175 return -EFAULT;
2176
2177 if (disable_panic) {
2178 /* Disable panic signal for all active pipes */
2179 SDE_DEBUG("Disabling danger:\n");
2180 _sde_plane_set_danger_state(kms, false);
2181 kms->has_danger_ctrl = false;
2182 } else {
2183 /* Enable panic signal for all active pipes */
2184 SDE_DEBUG("Enabling danger:\n");
2185 kms->has_danger_ctrl = true;
2186 _sde_plane_set_danger_state(kms, true);
2187 }
2188
2189 return count;
2190}
2191
2192static const struct file_operations sde_plane_danger_enable = {
2193 .open = simple_open,
2194 .read = _sde_plane_danger_read,
2195 .write = _sde_plane_danger_write,
2196};
2197
Clarence Ip4ce59322016-06-26 22:27:51 -04002198static void _sde_plane_init_debugfs(struct sde_plane *psde, struct sde_kms *kms)
2199{
2200 const struct sde_sspp_sub_blks *sblk = 0;
2201 const struct sde_sspp_cfg *cfg = 0;
2202
2203 if (psde && psde->pipe_hw)
2204 cfg = psde->pipe_hw->cap;
2205 if (cfg)
2206 sblk = cfg->sblk;
2207
2208 if (kms && sblk) {
2209 /* create overall sub-directory for the pipe */
2210 psde->debugfs_root =
2211 debugfs_create_dir(psde->pipe_name,
2212 sde_debugfs_get_root(kms));
2213 if (psde->debugfs_root) {
2214 /* don't error check these */
Clarence Ip4c1d9772016-06-26 09:35:38 -04002215 debugfs_create_x32("features", 0644,
Clarence Ip4ce59322016-06-26 22:27:51 -04002216 psde->debugfs_root, &psde->features);
2217
2218 /* add register dump support */
2219 sde_debugfs_setup_regset32(&psde->debugfs_src,
2220 sblk->src_blk.base + cfg->base,
2221 sblk->src_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002222 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002223 sde_debugfs_create_regset32("src_blk", 0444,
2224 psde->debugfs_root, &psde->debugfs_src);
2225
2226 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
2227 sblk->scaler_blk.base + cfg->base,
2228 sblk->scaler_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002229 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002230 sde_debugfs_create_regset32("scaler_blk", 0444,
2231 psde->debugfs_root,
2232 &psde->debugfs_scaler);
2233
2234 sde_debugfs_setup_regset32(&psde->debugfs_csc,
2235 sblk->csc_blk.base + cfg->base,
2236 sblk->csc_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002237 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002238 sde_debugfs_create_regset32("csc_blk", 0444,
2239 psde->debugfs_root, &psde->debugfs_csc);
Alan Kwongf0fd8512016-10-24 21:39:26 -04002240
2241 debugfs_create_u32("xin_id",
2242 0444,
2243 psde->debugfs_root,
2244 (u32 *) &cfg->xin_id);
2245 debugfs_create_u32("clk_ctrl",
2246 0444,
2247 psde->debugfs_root,
2248 (u32 *) &cfg->clk_ctrl);
2249 debugfs_create_x32("creq_vblank",
2250 0644,
2251 psde->debugfs_root,
2252 (u32 *) &sblk->creq_vblank);
2253 debugfs_create_x32("danger_vblank",
2254 0644,
2255 psde->debugfs_root,
2256 (u32 *) &sblk->danger_vblank);
2257
2258 debugfs_create_file("disable_danger",
2259 0644,
2260 psde->debugfs_root,
2261 kms, &sde_plane_danger_enable);
Clarence Ip4ce59322016-06-26 22:27:51 -04002262 }
2263 }
2264}
2265
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002266/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04002267struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002268 uint32_t pipe, bool primary_plane,
2269 unsigned long possible_crtcs)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002270{
2271 struct drm_plane *plane = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002272 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002273 struct msm_drm_private *priv;
2274 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002275 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04002276 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002277
2278 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002279 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002280 goto exit;
2281 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002282
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002283 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04002284 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002285 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002286 goto exit;
2287 }
2288
2289 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002290 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002291 goto exit;
2292 }
2293 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002294
Clarence Ip4c1d9772016-06-26 09:35:38 -04002295 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002296 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002297 goto exit;
2298 }
2299
Clarence Ip4ce59322016-06-26 22:27:51 -04002300 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002301 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
2302 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002303 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002304 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002305 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002306 }
2307
Clarence Ip4c1d9772016-06-26 09:35:38 -04002308 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002309 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002310 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04002311 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002312
Clarence Ip4c1d9772016-06-26 09:35:38 -04002313 /* initialize underlying h/w driver */
2314 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
2315 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002316 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002317 ret = PTR_ERR(psde->pipe_hw);
2318 goto clean_plane;
2319 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002320 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002321 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002322 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002323
2324 /* cache features mask for later */
2325 psde->features = psde->pipe_hw->cap->features;
2326 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04002327 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002328 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04002329 goto clean_sspp;
2330 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002331
abeykun48f407a2016-08-25 12:06:44 -04002332 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
2333 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
2334 GFP_KERNEL);
2335 if (!psde->scaler3_cfg) {
2336 SDE_ERROR("[%u]failed to allocate scale struct\n",
2337 pipe);
2338 ret = -ENOMEM;
2339 goto clean_sspp;
2340 }
2341 }
2342
Clarence Ip4c1d9772016-06-26 09:35:38 -04002343 /* add plane to DRM framework */
Clarence Ipea3d6262016-07-15 16:20:11 -04002344 psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
2345 psde->formats,
2346 0,
2347 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002348
Clarence Ip4c1d9772016-06-26 09:35:38 -04002349 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002350 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002351 goto clean_sspp;
2352 }
2353
2354 if (psde->features & BIT(SDE_SSPP_CURSOR))
2355 type = DRM_PLANE_TYPE_CURSOR;
2356 else if (primary_plane)
2357 type = DRM_PLANE_TYPE_PRIMARY;
2358 else
2359 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002360 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
2361 psde->formats, psde->nformats,
2362 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002363 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04002364 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002365
Clarence Ip4c1d9772016-06-26 09:35:38 -04002366 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002367 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002368
Clarence Ipaa0faf42016-05-30 12:07:48 -04002369 msm_property_init(&psde->property_info, &plane->base, dev,
2370 priv->plane_property, psde->property_data,
2371 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
2372 sizeof(struct sde_plane_state));
2373
Clarence Ipc47a0692016-10-11 10:54:17 -04002374 _sde_plane_install_properties(plane, kms->catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002375
Clarence Ip4ce59322016-06-26 22:27:51 -04002376 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04002377 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04002378
Clarence Ip730e7192016-06-26 22:45:09 -04002379 mutex_init(&psde->lock);
2380
Clarence Ip4ce59322016-06-26 22:27:51 -04002381 _sde_plane_init_debugfs(psde, kms);
2382
Clarence Ip13a8cf42016-09-29 17:27:47 -04002383 DRM_INFO("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002384 return plane;
2385
Clarence Ip4c1d9772016-06-26 09:35:38 -04002386clean_sspp:
2387 if (psde && psde->pipe_hw)
2388 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04002389
2390 if (psde && psde->scaler3_cfg)
2391 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002392clean_plane:
2393 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04002394exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002395 return ERR_PTR(ret);
2396}