blob: 78ac3b7e493036ef532a2f5739fee1f5b1101fb8 [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>
Clarence Ipaa0faf42016-05-30 12:07:48 -040017
18#include "msm_prop.h"
19
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070020#include "sde_kms.h"
Clarence Ipae4e60c2016-06-26 22:44:04 -040021#include "sde_fence.h"
Clarence Ipc475b082016-06-26 09:27:23 -040022#include "sde_formats.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040023#include "sde_hw_sspp.h"
Alan Kwong1a00e4d2016-07-18 09:42:30 -040024#include "sde_trace.h"
Dhaval Patel48c76022016-09-01 17:51:23 -070025#include "sde_crtc.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040026
Clarence Ip13a8cf42016-09-29 17:27:47 -040027#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
28 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
29
30#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
31 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
32
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040033#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
34#define PHASE_STEP_SHIFT 21
35#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
36#define PHASE_RESIDUAL 15
37
Clarence Ipe78efb72016-06-24 18:35:21 -040038#define SHARP_STRENGTH_DEFAULT 32
39#define SHARP_EDGE_THR_DEFAULT 112
40#define SHARP_SMOOTH_THR_DEFAULT 8
41#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040042
Clarence Ip5e2a9222016-06-26 22:38:24 -040043#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070044
Clarence Ipcae1bb62016-07-07 12:07:13 -040045#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
46
Clarence Ip282dad62016-09-27 17:07:35 -040047/* dirty bits for update function */
48#define SDE_PLANE_DIRTY_RECTS 0x1
49#define SDE_PLANE_DIRTY_FORMAT 0x2
50#define SDE_PLANE_DIRTY_SHARPEN 0x4
51#define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF
52
Alan Kwong1a00e4d2016-07-18 09:42:30 -040053/**
54 * enum sde_plane_qos - Different qos configurations for each pipe
55 *
56 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
57 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
58 * this configuration is mutually exclusive from VBLANK_CTRL.
59 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
60 */
61enum sde_plane_qos {
62 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
63 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
64 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
65};
66
Clarence Ip5fc00c52016-09-23 15:03:34 -040067/*
68 * struct sde_plane - local sde plane structure
69 * @csc_cfg: Decoded user configuration for csc
70 * @csc_usr_ptr: Points to csc_cfg if valid user config available
71 * @csc_ptr: Points to sde_csc_cfg structure to use for current
72 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070073struct sde_plane {
74 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040075
76 int mmu_id;
77
Clarence Ip730e7192016-06-26 22:45:09 -040078 struct mutex lock;
79
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040080 enum sde_sspp pipe;
81 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070082 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -040083 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040084
85 struct sde_hw_pipe *pipe_hw;
86 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -040087 struct sde_hw_sharp_cfg sharp_cfg;
Clarence Ip5e2a9222016-06-26 22:38:24 -040088 struct sde_hw_scaler3_cfg scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040089 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -040090 uint32_t color_fill;
91 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040092 bool is_rt_pipe;
Clarence Ip4ce59322016-06-26 22:27:51 -040093
Clarence Ipb43d4592016-09-08 14:21:35 -040094 struct sde_hw_pixel_ext pixel_ext;
95 bool pixel_ext_usr;
96
Clarence Ip373f8592016-05-26 00:58:42 -040097 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -040098 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -040099 struct sde_csc_cfg *csc_ptr;
100
Clarence Ip4c1d9772016-06-26 09:35:38 -0400101 const struct sde_sspp_sub_blks *pipe_sblk;
102
Clarence Ip5e2a9222016-06-26 22:38:24 -0400103 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400104
Clarence Ipaa0faf42016-05-30 12:07:48 -0400105 struct msm_property_info property_info;
106 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700107 struct drm_property_blob *blob_info;
Clarence Ip730e7192016-06-26 22:45:09 -0400108
Clarence Ip4ce59322016-06-26 22:27:51 -0400109 /* debugfs related stuff */
110 struct dentry *debugfs_root;
111 struct sde_debugfs_regset32 debugfs_src;
112 struct sde_debugfs_regset32 debugfs_scaler;
113 struct sde_debugfs_regset32 debugfs_csc;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700114};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700115
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700116#define to_sde_plane(x) container_of(x, struct sde_plane, base)
117
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400118static bool sde_plane_enabled(struct drm_plane_state *state)
119{
Clarence Ipdbde9832016-06-26 09:48:36 -0400120 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400121}
122
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400123/**
124 * _sde_plane_calc_fill_level - calculate fill level of the given source format
125 * @plane: Pointer to drm plane
126 * @fmt: Pointer to source buffer format
127 * @src_wdith: width of source buffer
128 * Return: fill level corresponding to the source buffer/format or 0 if error
129 */
130static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
131 const struct sde_format *fmt, u32 src_width)
132{
133 struct sde_plane *psde;
134 u32 fixed_buff_size;
135 u32 total_fl;
136
137 if (!plane || !fmt) {
138 SDE_ERROR("invalid arguments\n");
139 return 0;
140 }
141
142 psde = to_sde_plane(plane);
143 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
144
145 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
146 if (fmt->chroma_sample == SDE_CHROMA_420) {
147 /* NV12 */
148 total_fl = (fixed_buff_size / 2) /
149 ((src_width + 32) * fmt->bpp);
150 } else {
151 /* non NV12 */
152 total_fl = (fixed_buff_size) /
153 ((src_width + 32) * fmt->bpp);
154 }
155 } else {
156 total_fl = (fixed_buff_size * 2) /
157 ((src_width + 32) * fmt->bpp);
158 }
159
160 SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n",
161 plane->base.id, psde->pipe - SSPP_VIG0,
162 fmt->base.pixel_format, src_width, total_fl);
163
164 return total_fl;
165}
166
167/**
168 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
169 * @total_fl: fill level
170 * Return: LUT setting corresponding to the fill level
171 */
172static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
173{
174 u32 qos_lut;
175
176 if (total_fl <= 4)
177 qos_lut = 0x1B;
178 else if (total_fl <= 5)
179 qos_lut = 0x5B;
180 else if (total_fl <= 6)
181 qos_lut = 0x15B;
182 else if (total_fl <= 7)
183 qos_lut = 0x55B;
184 else if (total_fl <= 8)
185 qos_lut = 0x155B;
186 else if (total_fl <= 9)
187 qos_lut = 0x555B;
188 else if (total_fl <= 10)
189 qos_lut = 0x1555B;
190 else if (total_fl <= 11)
191 qos_lut = 0x5555B;
192 else if (total_fl <= 12)
193 qos_lut = 0x15555B;
194 else
195 qos_lut = 0x55555B;
196
197 return qos_lut;
198}
199
200/**
201 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
202 * @total_fl: fill level
203 * Return: LUT setting corresponding to the fill level
204 */
205static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
206{
207 u32 qos_lut;
208
209 if (total_fl <= 10)
210 qos_lut = 0x1AAff;
211 else if (total_fl <= 11)
212 qos_lut = 0x5AAFF;
213 else if (total_fl <= 12)
214 qos_lut = 0x15AAFF;
215 else
216 qos_lut = 0x55AAFF;
217
218 return qos_lut;
219}
220
221/**
222 * _sde_plane_is_rt_pipe - check if the given plane requires real-time QoS
223 * @plane: Pointer to drm plane
224 * @crtc: Pointer to drm crtc associated with the given plane
225 */
226static bool _sde_plane_is_rt_pipe(struct drm_plane *plane,
227 struct drm_crtc *crtc)
228{
229 struct sde_plane *psde = to_sde_plane(plane);
230 struct drm_connector *connector;
231 bool is_rt = false;
232
233 /* check if this plane has a physical connector interface */
Alan Kwong894837a2016-09-29 01:15:23 -0400234 mutex_lock(&plane->dev->mode_config.mutex);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400235 drm_for_each_connector(connector, plane->dev)
236 if (connector->state &&
237 (connector->state->crtc == crtc) &&
238 (connector->connector_type
239 != DRM_MODE_CONNECTOR_VIRTUAL)) {
240 is_rt = true;
241 break;
242 }
Alan Kwong894837a2016-09-29 01:15:23 -0400243 mutex_unlock(&plane->dev->mode_config.mutex);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400244
245 SDE_DEBUG("plane%u: pnum:%d rt:%d\n",
246 plane->base.id, psde->pipe - SSPP_VIG0, is_rt);
247
248 return is_rt;
249}
250
251/**
252 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
253 * @plane: Pointer to drm plane
254 * @fb: Pointer to framebuffer associated with the given plane
255 */
256static void _sde_plane_set_qos_lut(struct drm_plane *plane,
257 struct drm_framebuffer *fb)
258{
259 struct sde_plane *psde;
260 const struct sde_format *fmt = NULL;
261 u32 qos_lut;
262 u32 total_fl = 0;
263
264 if (!plane || !fb) {
265 SDE_ERROR("invalid arguments plane %d fb %d\n",
266 plane != 0, fb != 0);
267 return;
268 }
269
270 psde = to_sde_plane(plane);
271
272 if (!psde->pipe_hw || !psde->pipe_sblk) {
273 SDE_ERROR("invalid arguments\n");
274 return;
275 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
276 return;
277 }
278
279 if (!psde->is_rt_pipe) {
280 qos_lut = psde->pipe_sblk->creq_lut_nrt;
281 } else {
282 fmt = sde_get_sde_format_ext(
283 fb->pixel_format,
284 fb->modifier,
285 drm_format_num_planes(fb->pixel_format));
286 total_fl = _sde_plane_calc_fill_level(plane, fmt,
287 psde->pipe_cfg.src_rect.w);
288
289 if (SDE_FORMAT_IS_LINEAR(fmt))
290 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
291 else
292 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
293 }
294
295 psde->pipe_qos_cfg.creq_lut = qos_lut;
296
297 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
298 (fmt) ? fmt->base.pixel_format : 0,
299 psde->is_rt_pipe, total_fl, qos_lut,
300 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
301
302 SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n",
303 plane->base.id,
304 psde->pipe - SSPP_VIG0,
305 (fmt) ? fmt->base.pixel_format : 0,
306 psde->is_rt_pipe, total_fl, qos_lut);
307
308 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
309}
310
311/**
312 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
313 * @plane: Pointer to drm plane
314 * @fb: Pointer to framebuffer associated with the given plane
315 */
316static void _sde_plane_set_danger_lut(struct drm_plane *plane,
317 struct drm_framebuffer *fb)
318{
319 struct sde_plane *psde;
320 const struct sde_format *fmt = NULL;
321 u32 danger_lut, safe_lut;
322
323 if (!plane || !fb) {
324 SDE_ERROR("invalid arguments\n");
325 return;
326 }
327
328 psde = to_sde_plane(plane);
329
330 if (!psde->pipe_hw || !psde->pipe_sblk) {
331 SDE_ERROR("invalid arguments\n");
332 return;
333 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
334 return;
335 }
336
337 if (!psde->is_rt_pipe) {
338 danger_lut = psde->pipe_sblk->danger_lut_nrt;
339 safe_lut = psde->pipe_sblk->safe_lut_nrt;
340 } else {
341 fmt = sde_get_sde_format_ext(
342 fb->pixel_format,
343 fb->modifier,
344 drm_format_num_planes(fb->pixel_format));
345
346 if (SDE_FORMAT_IS_LINEAR(fmt)) {
347 danger_lut = psde->pipe_sblk->danger_lut_linear;
348 safe_lut = psde->pipe_sblk->safe_lut_linear;
349 } else {
350 danger_lut = psde->pipe_sblk->danger_lut_tile;
351 safe_lut = psde->pipe_sblk->safe_lut_tile;
352 }
353 }
354
355 psde->pipe_qos_cfg.danger_lut = danger_lut;
356 psde->pipe_qos_cfg.safe_lut = safe_lut;
357
358 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
359 (fmt) ? fmt->base.pixel_format : 0,
360 (fmt) ? fmt->fetch_mode : 0,
361 psde->pipe_qos_cfg.danger_lut,
362 psde->pipe_qos_cfg.safe_lut);
363
364 SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n",
365 plane->base.id,
366 psde->pipe - SSPP_VIG0,
367 fmt ? fmt->base.pixel_format : 0,
368 fmt ? fmt->fetch_mode : -1,
369 psde->pipe_qos_cfg.danger_lut,
370 psde->pipe_qos_cfg.safe_lut);
371
372 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
373 &psde->pipe_qos_cfg);
374}
375
376/**
377 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
378 * @plane: Pointer to drm plane
379 * @enable: true to enable QoS control
380 * @flags: QoS control mode (enum sde_plane_qos)
381 */
382static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
383 bool enable, u32 flags)
384{
385 struct sde_plane *psde;
386
387 if (!plane) {
388 SDE_ERROR("invalid arguments\n");
389 return;
390 }
391
392 psde = to_sde_plane(plane);
393
394 if (!psde->pipe_hw || !psde->pipe_sblk) {
395 SDE_ERROR("invalid arguments\n");
396 return;
397 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
398 return;
399 }
400
401 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
402 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
403 psde->pipe_qos_cfg.danger_vblank =
404 psde->pipe_sblk->danger_vblank;
405 psde->pipe_qos_cfg.vblank_en = enable;
406 }
407
408 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
409 /* this feature overrules previous VBLANK_CTRL */
410 psde->pipe_qos_cfg.vblank_en = false;
411 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
412 }
413
414 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
415 psde->pipe_qos_cfg.danger_safe_en = enable;
416
417 if (!psde->is_rt_pipe) {
418 psde->pipe_qos_cfg.vblank_en = false;
419 psde->pipe_qos_cfg.danger_safe_en = false;
420 }
421
422 SDE_DEBUG("plane%u: pnum:%d ds:%d vb:%d pri[0x%x, 0x%x]\n",
423 plane->base.id,
424 psde->pipe - SSPP_VIG0,
425 psde->pipe_qos_cfg.danger_safe_en,
426 psde->pipe_qos_cfg.vblank_en,
427 psde->pipe_qos_cfg.creq_vblank,
428 psde->pipe_qos_cfg.danger_vblank);
429
430 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
431 &psde->pipe_qos_cfg);
432}
433
Alan Kwong5d324e42016-07-28 22:56:18 -0400434/**
435 * _sde_plane_set_ot_limit - set OT limit for the given plane
436 * @plane: Pointer to drm plane
437 * @crtc: Pointer to drm crtc
438 */
439static void _sde_plane_set_ot_limit(struct drm_plane *plane,
440 struct drm_crtc *crtc)
441{
442 struct sde_plane *psde;
443 struct sde_vbif_set_ot_params ot_params;
444 struct msm_drm_private *priv;
445 struct sde_kms *sde_kms;
446
447 if (!plane || !plane->dev || !crtc) {
448 SDE_ERROR("invalid arguments plane %d crtc %d\n",
449 plane != 0, crtc != 0);
450 return;
451 }
452
453 priv = plane->dev->dev_private;
454 if (!priv || !priv->kms) {
455 SDE_ERROR("invalid KMS reference\n");
456 return;
457 }
458
459 sde_kms = to_sde_kms(priv->kms);
460 psde = to_sde_plane(plane);
461 if (!psde->pipe_hw) {
462 SDE_ERROR("invalid pipe reference\n");
463 return;
464 }
465
466 memset(&ot_params, 0, sizeof(ot_params));
467 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
468 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
469 ot_params.width = psde->pipe_cfg.src_rect.w;
470 ot_params.height = psde->pipe_cfg.src_rect.h;
471 ot_params.is_wfd = !psde->is_rt_pipe;
472 ot_params.frame_rate = crtc->mode.vrefresh;
473 ot_params.vbif_idx = VBIF_RT;
474 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
475 ot_params.rd = true;
476
477 sde_vbif_set_ot_limit(sde_kms, &ot_params);
478}
479
Clarence Ipcae1bb62016-07-07 12:07:13 -0400480/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400481static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400482 struct sde_plane_state *pstate, uint64_t fd)
483{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400484 if (!psde || !pstate) {
485 SDE_ERROR("invalid arg(s), plane %d state %d\n",
486 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400487 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400488 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400489
490 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400491 if (pstate->input_fence)
492 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400493
494 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400495 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400496
Clarence Ip13a8cf42016-09-29 17:27:47 -0400497 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400498}
499
Clarence Ipcae1bb62016-07-07 12:07:13 -0400500int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400501{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400502 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400503 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400504 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400505 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400506 int ret = -EINVAL;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400507
508 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700509 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400510 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400511 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400512 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400513 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400514 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400515 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400516
Clarence Ipcae1bb62016-07-07 12:07:13 -0400517 if (input_fence) {
Clarence Ip78a04ed2016-10-04 15:57:45 -0400518 prefix = sde_sync_get_name_prefix(input_fence);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400519 ret = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400520
521 MSM_EVT(plane->dev,
522 plane->base.id,
523 (uint64_t)-ret << (sizeof(uint32_t) * CHAR_BIT)
524 | prefix);
525
Clarence Ipcae1bb62016-07-07 12:07:13 -0400526 switch (ret) {
527 case 0:
Clarence Ip13a8cf42016-09-29 17:27:47 -0400528 SDE_DEBUG_PLANE(psde, "signaled\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400529 break;
530 case -ETIME:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400531 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
532 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400533 psde->is_error = true;
534 break;
535 default:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400536 SDE_ERROR_PLANE(psde, "error %d on %08X\n",
537 ret, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400538 psde->is_error = true;
539 break;
540 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400541 } else {
542 ret = 0;
543 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400544 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400545 return ret;
546}
547
Clarence Ip282dad62016-09-27 17:07:35 -0400548static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400549 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400550 struct sde_hw_pipe_cfg *pipe_cfg,
551 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400552{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400553 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400554 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400555
Clarence Ip13a8cf42016-09-29 17:27:47 -0400556 if (!plane || !pstate || !pipe_cfg || !fb) {
557 SDE_ERROR(
558 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
559 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400560 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400561 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400562
563 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400564 if (!psde->pipe_hw) {
565 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400566 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400567 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400568
Clarence Ipb6eb2362016-09-08 16:18:13 -0400569 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
570 if (ret == -EAGAIN)
571 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
572 else if (ret)
573 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
574 else if (psde->pipe_hw->ops.setup_sourceaddress)
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400575 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400576}
577
Clarence Ipcb410d42016-06-26 22:52:33 -0400578static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400579 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
580 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400581 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400582 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
583{
584}
585
Clarence Ipcb410d42016-06-26 22:52:33 -0400586/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400587 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400588 * @psde: Pointer to SDE plane object
589 * @src: Source size
590 * @dst: Destination size
591 * @phase_steps: Pointer to output array for phase steps
592 * @filter: Pointer to output array for filter type
593 * @fmt: Pointer to format definition
594 * @chroma_subsampling: Subsampling amount for chroma channel
595 *
596 * Returns: 0 on success
597 */
598static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400599 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400600 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400601 uint32_t chroma_subsampling)
602{
Clarence Ipcb410d42016-06-26 22:52:33 -0400603 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400604 SDE_ERROR(
605 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
606 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400607 return -EINVAL;
608 }
609
Clarence Ip4c1d9772016-06-26 09:35:38 -0400610 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400611 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400612 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400613 phase_steps[SDE_SSPP_COMP_1_2] =
614 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
615 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
616 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400617
618 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400619 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400620 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400621 (src <= dst) ? SDE_SCALE_FILTER_BIL :
622 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400623
Clarence Ipdbde9832016-06-26 09:48:36 -0400624 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400625 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400626 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
627 } else {
628 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
629 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400630 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400631 }
632 } else {
633 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400634 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
635 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
636 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400637 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400638 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400639}
640
Clarence Ipcb410d42016-06-26 22:52:33 -0400641/**
642 * _sde_plane_setup_pixel_ext - determine default pixel extension values
643 * @psde: Pointer to SDE plane object
644 * @src: Source size
645 * @dst: Destination size
646 * @decimated_src: Source size after decimation, if any
647 * @phase_steps: Pointer to output array for phase steps
648 * @out_src: Output array for pixel extension values
649 * @out_edge1: Output array for pixel extension first edge
650 * @out_edge2: Output array for pixel extension second edge
651 * @filter: Pointer to array for filter type
652 * @fmt: Pointer to format definition
653 * @chroma_subsampling: Subsampling amount for chroma channel
654 * @post_compare: Whether to chroma subsampled source size for comparisions
655 */
656static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400657 uint32_t src, uint32_t dst, uint32_t decimated_src,
658 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400659 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400660 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400661 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400662{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400663 int64_t edge1, edge2, caf;
664 uint32_t src_work;
665 int i, tmp;
666
Clarence Ipcb410d42016-06-26 22:52:33 -0400667 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400668 out_edge2 && filter && fmt) {
669 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400670 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400671 caf = PHASE_STEP_UNIT_SCALE;
672 else
673 caf = 0;
674
675 for (i = 0; i < SDE_MAX_PLANES; i++) {
676 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400677 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400678 src_work /= chroma_subsampling;
679 if (post_compare)
680 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400681 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400682 /* unity */
683 edge1 = 0;
684 edge2 = 0;
685 } else if (dst >= src) {
686 /* upscale */
687 edge1 = (1 << PHASE_RESIDUAL);
688 edge1 -= caf;
689 edge2 = (1 << PHASE_RESIDUAL);
690 edge2 += (dst - 1) * *(phase_steps + i);
691 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
692 edge2 += caf;
693 edge2 = -(edge2);
694 } else {
695 /* downscale */
696 edge1 = 0;
697 edge2 = (dst - 1) * *(phase_steps + i);
698 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
699 edge2 += *(phase_steps + i);
700 edge2 = -(edge2);
701 }
702
703 /* only enable CAF for luma plane */
704 caf = 0;
705
706 /* populate output arrays */
707 *(out_src + i) = src_work;
708
709 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400710 if (edge1 >= 0) {
711 tmp = (uint32_t)edge1;
712 tmp >>= PHASE_STEP_SHIFT;
713 *(out_edge1 + i) = -tmp;
714 } else {
715 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400716 *(out_edge1 + i) =
717 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
718 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400719 }
720 if (edge2 >= 0) {
721 tmp = (uint32_t)edge2;
722 tmp >>= PHASE_STEP_SHIFT;
723 *(out_edge2 + i) = -tmp;
724 } else {
725 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400726 *(out_edge2 + i) =
727 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
728 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400729 }
730 }
731 }
732}
733
Clarence Ip5fc00c52016-09-23 15:03:34 -0400734static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400735{
736 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
737 {
Clarence Ip373f8592016-05-26 00:58:42 -0400738 /* S15.16 format */
739 0x00012A00, 0x00000000, 0x00019880,
740 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
741 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400742 },
Clarence Ip373f8592016-05-26 00:58:42 -0400743 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400744 { 0xfff0, 0xff80, 0xff80,},
745 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400746 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400747 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400748 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400749 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400750
Clarence Ip5fc00c52016-09-23 15:03:34 -0400751 if (!psde) {
752 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400753 return;
754 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400755
Clarence Ipcae1bb62016-07-07 12:07:13 -0400756 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400757 if (psde->csc_usr_ptr)
758 psde->csc_ptr = psde->csc_usr_ptr;
759 else
Clarence Ip373f8592016-05-26 00:58:42 -0400760 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400761
Clarence Ip13a8cf42016-09-29 17:27:47 -0400762 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400763 psde->csc_ptr->csc_mv[0],
764 psde->csc_ptr->csc_mv[1],
765 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400766}
767
Clarence Ipcb410d42016-06-26 22:52:33 -0400768static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400769 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -0400770 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700771{
Clarence Ipb43d4592016-09-08 14:21:35 -0400772 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -0400773 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Clarence Ipb43d4592016-09-08 14:21:35 -0400774 uint32_t tmp, i;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400775
Clarence Ipb43d4592016-09-08 14:21:35 -0400776 if (!psde || !fmt) {
777 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
778 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400779 return;
Clarence Ipb43d4592016-09-08 14:21:35 -0400780 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400781
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400782 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400783
Clarence Ipdedbba92016-09-27 17:43:10 -0400784 psde->pipe_cfg.horz_decimation =
785 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
786 psde->pipe_cfg.vert_decimation =
787 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400788
789 /* don't chroma subsample if decimating */
790 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400791 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400792 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400793 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400794
Clarence Ip5e2a9222016-06-26 22:38:24 -0400795 /* update scaler */
796 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400797 if (!psde->pixel_ext_usr) {
798 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -0400799 _sde_plane_setup_scaler3(psde,
800 psde->pipe_cfg.src_rect.w,
801 psde->pipe_cfg.src_rect.h,
802 psde->pipe_cfg.dst_rect.w,
803 psde->pipe_cfg.dst_rect.h,
804 &psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400805 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400806 }
Clarence Ipb43d4592016-09-08 14:21:35 -0400807 } else if (!psde->pixel_ext_usr) {
808 /* calculate default configuration for QSEED2 */
809 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400810
Clarence Ip13a8cf42016-09-29 17:27:47 -0400811 SDE_DEBUG_PLANE(psde, "default config\n");
Clarence Ipb43d4592016-09-08 14:21:35 -0400812 _sde_plane_setup_scaler2(psde,
813 psde->pipe_cfg.src_rect.w,
814 psde->pipe_cfg.dst_rect.w,
815 pe->phase_step_x,
816 pe->horz_filter, fmt, chroma_subsmpl_h);
817 _sde_plane_setup_scaler2(psde,
818 psde->pipe_cfg.src_rect.h,
819 psde->pipe_cfg.dst_rect.h,
820 pe->phase_step_y,
821 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400822
Clarence Ip5e2a9222016-06-26 22:38:24 -0400823 /* calculate left/right/top/bottom pixel extensions */
Clarence Ipcb410d42016-06-26 22:52:33 -0400824 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400825 psde->pipe_cfg.horz_decimation);
Clarence Ipdbde9832016-06-26 09:48:36 -0400826 if (SDE_FORMAT_IS_YUV(fmt))
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400827 tmp &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -0400828 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
829 psde->pipe_cfg.dst_rect.w, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400830 pe->phase_step_x,
831 pe->roi_w,
832 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -0400833 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400834 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400835
Clarence Ipcb410d42016-06-26 22:52:33 -0400836 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400837 psde->pipe_cfg.vert_decimation);
Clarence Ipcb410d42016-06-26 22:52:33 -0400838 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
839 psde->pipe_cfg.dst_rect.h, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400840 pe->phase_step_y,
841 pe->roi_h,
842 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -0400843 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400844 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400845
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400846 for (i = 0; i < SDE_MAX_PLANES; i++) {
847 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400848 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400849 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400850 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400851
852 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400853 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400854 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400855 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400856
857 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400858 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400859 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400860 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400861
862 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400863 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400864 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400865 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400866 }
867 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400868}
869
Clarence Ipcae1bb62016-07-07 12:07:13 -0400870/**
871 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -0400872 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -0400873 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
874 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
875 * Returns: 0 on success
876 */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400877static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -0400878 uint32_t color, uint32_t alpha)
879{
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400880 const struct sde_format *fmt;
Clarence Ipcb410d42016-06-26 22:52:33 -0400881
Clarence Ip13a8cf42016-09-29 17:27:47 -0400882 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700883 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400884 return -EINVAL;
885 }
886
Clarence Ipcb410d42016-06-26 22:52:33 -0400887 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400888 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400889 return -EINVAL;
890 }
891
Clarence Ip13a8cf42016-09-29 17:27:47 -0400892 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400893
Clarence Ipcb410d42016-06-26 22:52:33 -0400894 /*
895 * select fill format to match user property expectation,
896 * h/w only supports RGB variants
897 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400898 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -0400899
900 /* update sspp */
901 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
902 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
903 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
904
905 /* override scaler/decimation if solid fill */
906 psde->pipe_cfg.src_rect.x = 0;
907 psde->pipe_cfg.src_rect.y = 0;
908 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
909 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
910
911 _sde_plane_setup_scaler(psde, fmt, 0);
912
913 if (psde->pipe_hw->ops.setup_format)
914 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
915 fmt, SDE_SSPP_SOLID_FILL);
916
917 if (psde->pipe_hw->ops.setup_rects)
918 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
919 &psde->pipe_cfg, &psde->pixel_ext);
920 }
921
922 return 0;
923}
924
925static int _sde_plane_mode_set(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -0700926 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -0400927{
Clarence Ipc47a0692016-10-11 10:54:17 -0400928 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -0400929 struct sde_plane *psde;
930 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400931 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -0700932 struct drm_crtc *crtc;
933 struct drm_framebuffer *fb;
934 struct sde_rect src, dst;
935 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -0400936 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -0400937
Clarence Ip13a8cf42016-09-29 17:27:47 -0400938 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -0400939 SDE_ERROR("invalid plane\n");
940 return -EINVAL;
941 } else if (!plane->state) {
942 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400943 return -EINVAL;
944 }
945
946 psde = to_sde_plane(plane);
947 pstate = to_sde_plane_state(plane->state);
Clarence Ipcb410d42016-06-26 22:52:33 -0400948
Dhaval Patel47302cf2016-08-18 15:04:28 -0700949 crtc = state->crtc;
950 fb = state->fb;
951 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400952 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
953 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -0700954 return -EINVAL;
955 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400956 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400957 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -0400958
Clarence Ip282dad62016-09-27 17:07:35 -0400959 /* determine what needs to be refreshed */
960 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
961 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400962 case PLANE_PROP_SCALER_V1:
Clarence Ipdedbba92016-09-27 17:43:10 -0400963 case PLANE_PROP_H_DECIMATE:
964 case PLANE_PROP_V_DECIMATE:
965 case PLANE_PROP_SRC_CONFIG:
966 case PLANE_PROP_ZPOS:
Clarence Ip282dad62016-09-27 17:07:35 -0400967 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
968 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400969 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -0400970 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
971 break;
972 case PLANE_PROP_COLOR_FILL:
973 /* potentially need to refresh everything */
974 pstate->dirty = SDE_PLANE_DIRTY_ALL;
975 break;
976 case PLANE_PROP_ROTATION:
977 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
978 break;
Clarence Ip282dad62016-09-27 17:07:35 -0400979 case PLANE_PROP_INFO:
980 case PLANE_PROP_ALPHA:
981 case PLANE_PROP_INPUT_FENCE:
982 case PLANE_PROP_BLEND_OP:
983 /* no special action required */
984 break;
985 default:
986 /* unknown property, refresh everything */
987 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
988 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
989 break;
990 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400991 }
992
Clarence Ip282dad62016-09-27 17:07:35 -0400993 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
994 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -0400995
996 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
997
Clarence Ip282dad62016-09-27 17:07:35 -0400998 /* early out if nothing dirty */
999 if (!pstate->dirty)
1000 return 0;
1001 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001002
Clarence Ip282dad62016-09-27 17:07:35 -04001003 psde->is_rt_pipe = _sde_plane_is_rt_pipe(plane, crtc);
1004 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1005
1006 /* update roi config */
1007 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
1008 POPULATE_RECT(&src, state->src_x, state->src_y,
1009 state->src_w, state->src_h, q16_data);
1010 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
1011 state->crtc_w, state->crtc_h, !q16_data);
1012
Clarence Ip13a8cf42016-09-29 17:27:47 -04001013 SDE_DEBUG_PLANE(psde,
1014 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001015 fb->base.id, src.x, src.y, src.w, src.h,
1016 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
1017 drm_get_format_name(fmt->base.pixel_format),
1018 SDE_FORMAT_IS_UBWC(fmt));
1019
1020 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
1021 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001022 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001023 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
1024 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
1025 src.h /= 2;
1026 src.y = DIV_ROUND_UP(src.y, 2);
1027 src.y &= ~0x1;
1028 }
1029
1030 psde->pipe_cfg.src_rect = src;
1031 psde->pipe_cfg.dst_rect = dst;
1032
1033 /* check for color fill */
1034 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
1035 PLANE_PROP_COLOR_FILL);
1036 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
1037 /* skip remaining processing on color fill */
1038 pstate->dirty = 0x0;
1039 } else if (psde->pipe_hw->ops.setup_rects) {
1040 _sde_plane_setup_scaler(psde, fmt, pstate);
1041
Clarence Ip282dad62016-09-27 17:07:35 -04001042 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
1043 &psde->pipe_cfg, &psde->pixel_ext);
1044 }
Dhaval Patel48c76022016-09-01 17:51:23 -07001045 }
1046
Clarence Ip282dad62016-09-27 17:07:35 -04001047 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
1048 psde->pipe_hw->ops.setup_format) {
1049 src_flags = 0x0;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001050 SDE_DEBUG_PLANE(psde, "rotation 0x%llX\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001051 sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
1052 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1053 BIT(DRM_REFLECT_X))
1054 src_flags |= SDE_SSPP_FLIP_LR;
1055 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1056 BIT(DRM_REFLECT_Y))
1057 src_flags |= SDE_SSPP_FLIP_UD;
1058
1059 /* update format */
1060 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags);
1061
1062 /* update csc */
1063 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04001064 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04001065 else
1066 psde->csc_ptr = 0;
1067 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001068
Clarence Ipe78efb72016-06-24 18:35:21 -04001069 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04001070 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
1071 psde->pipe_hw->ops.setup_sharpening) {
1072 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
1073 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
1074 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
1075 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04001076
Clarence Ipe78efb72016-06-24 18:35:21 -04001077 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04001078 &psde->sharp_cfg);
1079 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001080
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001081 _sde_plane_set_qos_lut(plane, fb);
1082 _sde_plane_set_danger_lut(plane, fb);
1083
Alan Kwong5d324e42016-07-28 22:56:18 -04001084 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001085 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04001086 _sde_plane_set_ot_limit(plane, crtc);
1087 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001088
Clarence Ip282dad62016-09-27 17:07:35 -04001089 /* clear dirty */
1090 pstate->dirty = 0x0;
1091
Clarence Ip5e2a9222016-06-26 22:38:24 -04001092 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001093}
1094
1095static int sde_plane_prepare_fb(struct drm_plane *plane,
1096 const struct drm_plane_state *new_state)
1097{
1098 struct drm_framebuffer *fb = new_state->fb;
1099 struct sde_plane *psde = to_sde_plane(plane);
1100
1101 if (!new_state->fb)
1102 return 0;
1103
Clarence Ip13a8cf42016-09-29 17:27:47 -04001104 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001105 return msm_framebuffer_prepare(fb, psde->mmu_id);
1106}
1107
1108static void sde_plane_cleanup_fb(struct drm_plane *plane,
1109 const struct drm_plane_state *old_state)
1110{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001111 struct drm_framebuffer *fb = old_state ? old_state->fb : NULL;
1112 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001113
1114 if (!fb)
1115 return;
1116
Clarence Ip13a8cf42016-09-29 17:27:47 -04001117 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001118 msm_framebuffer_cleanup(fb, psde->mmu_id);
1119}
1120
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001121static void _sde_plane_atomic_check_mode_changed(struct sde_plane *psde,
1122 struct drm_plane_state *state,
1123 struct drm_plane_state *old_state)
1124{
1125 struct sde_plane_state *pstate = to_sde_plane_state(state);
1126
Dhaval Patel47302cf2016-08-18 15:04:28 -07001127 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04001128 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001129 return;
1130
Clarence Ip282dad62016-09-27 17:07:35 -04001131 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
1132 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001133 SDE_DEBUG_PLANE(psde,
1134 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001135 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001136 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001137 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001138 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001139 } else if (state->src_w != old_state->src_w ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07001140 state->src_h != old_state->src_h ||
1141 state->src_x != old_state->src_x ||
1142 state->src_y != old_state->src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001143 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001144 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001145 } else if (state->crtc_w != old_state->crtc_w ||
1146 state->crtc_h != old_state->crtc_h ||
1147 state->crtc_x != old_state->crtc_x ||
1148 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001149 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001150 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1151 }
1152
1153 if (!state->fb || !old_state->fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001154 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001155 } else if (state->fb->pixel_format != old_state->fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001156 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001157 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001158 } else {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001159 uint64_t *new_mods = state->fb->modifier;
1160 uint64_t *old_mods = old_state->fb->modifier;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001161 uint32_t *new_pitches = state->fb->pitches;
1162 uint32_t *old_pitches = old_state->fb->pitches;
1163 uint32_t *new_offset = state->fb->offsets;
1164 uint32_t *old_offset = old_state->fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001165 int i;
1166
1167 for (i = 0; i < ARRAY_SIZE(state->fb->modifier); i++) {
1168 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001169 SDE_DEBUG_PLANE(psde,
1170 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001171 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001172 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001173 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1174 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001175 break;
1176 }
1177 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001178 for (i = 0; i < ARRAY_SIZE(state->fb->pitches); i++) {
1179 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001180 SDE_DEBUG_PLANE(psde,
1181 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001182 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001183 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001184 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001185 break;
1186 }
1187 }
Dhaval Patel47302cf2016-08-18 15:04:28 -07001188 for (i = 0; i < ARRAY_SIZE(state->fb->offsets); i++) {
1189 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001190 SDE_DEBUG_PLANE(psde,
1191 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001192 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001193 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001194 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1195 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001196 break;
1197 }
1198 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001199 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001200}
1201
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001202static int sde_plane_atomic_check(struct drm_plane *plane,
1203 struct drm_plane_state *state)
1204{
Clarence Ipdedbba92016-09-27 17:43:10 -04001205 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04001206 struct sde_plane *psde;
1207 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001208 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001209 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04001210 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001211 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
1212 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04001213
1214 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001215 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1216 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04001217 ret = -EINVAL;
1218 goto exit;
1219 }
1220
1221 psde = to_sde_plane(plane);
1222 pstate = to_sde_plane_state(state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001223
1224 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001225 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001226 ret = -EINVAL;
1227 goto exit;
1228 }
1229
Clarence Ipdedbba92016-09-27 17:43:10 -04001230 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1231 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04001232
1233 /* src values are in Q16 fixed point, convert to integer */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001234 POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w,
1235 state->src_h, q16_data);
1236 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
1237 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04001238
Dhaval Patel47302cf2016-08-18 15:04:28 -07001239 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
1240 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04001241
Dhaval Patel47302cf2016-08-18 15:04:28 -07001242 max_upscale = psde->pipe_sblk->maxupscale;
1243 max_downscale = psde->pipe_sblk->maxdwnscale;
1244 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04001245
Clarence Ip13a8cf42016-09-29 17:27:47 -04001246 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001247 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001248
Dhaval Patel47302cf2016-08-18 15:04:28 -07001249 if (!sde_plane_enabled(state))
1250 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04001251
Dhaval Patel47302cf2016-08-18 15:04:28 -07001252 fmt = to_sde_format(msm_framebuffer_format(state->fb));
1253
1254 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
1255
1256 if (SDE_FORMAT_IS_YUV(fmt) &&
1257 (!(psde->features & SDE_SSPP_SCALER) ||
1258 !(psde->features & BIT(SDE_SSPP_CSC)))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001259 SDE_ERROR_PLANE(psde,
1260 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07001261 ret = -EINVAL;
1262
1263 /* check src bounds */
1264 } else if (state->fb->width > MAX_IMG_WIDTH ||
1265 state->fb->height > MAX_IMG_HEIGHT ||
1266 src.w < min_src_size || src.h < min_src_size ||
1267 CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) ||
1268 CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001269 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001270 src.x, src.y, src.w, src.h);
1271 ret = -E2BIG;
1272
1273 /* valid yuv image */
1274 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
1275 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001276 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001277 src.x, src.y, src.w, src.h);
1278 ret = -EINVAL;
1279
1280 /* min dst support */
1281 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001282 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001283 dst.x, dst.y, dst.w, dst.h);
1284 ret = -EINVAL;
1285
1286 /* decimation validation */
1287 } else if (deci_w || deci_h) {
1288 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
1289 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001290 SDE_ERROR_PLANE(psde,
1291 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001292 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001293 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001294 SDE_ERROR_PLANE(psde,
1295 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001296 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001297 }
1298
Dhaval Patel47302cf2016-08-18 15:04:28 -07001299 } else if (!(psde->features & SDE_SSPP_SCALER) &&
1300 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001301 SDE_ERROR_PLANE(psde,
1302 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001303 src.w, src.h, dst.w, dst.h);
1304 ret = -EINVAL;
1305
1306 /* check decimated source width */
1307 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001308 SDE_ERROR_PLANE(psde,
1309 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001310 src.w, src_deci_w, max_linewidth);
1311 ret = -E2BIG;
1312
1313 /* check max scaler capability */
1314 } else if (((src_deci_w * max_upscale) < dst.w) ||
1315 ((src_deci_h * max_upscale) < dst.h) ||
1316 ((dst.w * max_downscale) < src_deci_w) ||
1317 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001318 SDE_ERROR_PLANE(psde,
1319 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001320 src_deci_w, src_deci_h, dst.w, dst.h);
1321 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001322 }
1323
Dhaval Patel47302cf2016-08-18 15:04:28 -07001324modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001325 if (!ret)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001326 _sde_plane_atomic_check_mode_changed(psde, state, plane->state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001327exit:
1328 return ret;
1329}
1330
Clarence Ipcae1bb62016-07-07 12:07:13 -04001331/**
1332 * sde_plane_flush - final plane operations before commit flush
1333 * @plane: Pointer to drm plane structure
1334 */
1335void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04001336{
Clarence Ipcae1bb62016-07-07 12:07:13 -04001337 struct sde_plane *psde;
1338
Clarence Ip13a8cf42016-09-29 17:27:47 -04001339 if (!plane) {
1340 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001341 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001342 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04001343
1344 psde = to_sde_plane(plane);
1345
1346 /*
1347 * These updates have to be done immediately before the plane flush
1348 * timing, and may not be moved to the atomic_update/mode_set functions.
1349 */
1350 if (psde->is_error)
1351 /* force white frame with 0% alpha pipe output on error */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001352 _sde_plane_color_fill(psde, 0xFFFFFF, 0x0);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001353 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
1354 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001355 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001356 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
1357 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
1358
1359 /* flag h/w flush complete */
1360 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04001361 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001362}
1363
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001364static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04001365 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001366{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001367 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001368 struct drm_plane_state *state;
1369 struct sde_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001370
Clarence Ip13a8cf42016-09-29 17:27:47 -04001371 if (!plane) {
1372 SDE_ERROR("invalid plane\n");
1373 return;
1374 } else if (!plane->state) {
1375 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04001376 return;
1377 }
1378
Clarence Ip13a8cf42016-09-29 17:27:47 -04001379 psde = to_sde_plane(plane);
1380 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001381 state = plane->state;
1382 pstate = to_sde_plane_state(state);
1383
Clarence Ip13a8cf42016-09-29 17:27:47 -04001384 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001385
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001386 if (!sde_plane_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04001387 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001388 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001389 int ret;
1390
Dhaval Patel47302cf2016-08-18 15:04:28 -07001391 ret = _sde_plane_mode_set(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001392 /* atomic_check should have ensured that this doesn't fail */
1393 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001394 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001395}
1396
Dhaval Patel47302cf2016-08-18 15:04:28 -07001397
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001398/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001399static void _sde_plane_install_properties(struct drm_plane *plane,
Clarence Ipc47a0692016-10-11 10:54:17 -04001400 struct sde_mdss_cfg *catalog)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001401{
Clarence Ip5e2a9222016-06-26 22:38:24 -04001402 static const struct drm_prop_enum_list e_blend_op[] = {
1403 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
1404 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
1405 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
1406 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
1407 };
1408 static const struct drm_prop_enum_list e_src_config[] = {
1409 {SDE_DRM_DEINTERLACE, "deinterlace"}
1410 };
Clarence Ipea3d6262016-07-15 16:20:11 -04001411 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07001412 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001413 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04001414 int zpos_max = 255;
1415 int zpos_def = 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001416
Clarence Ip13a8cf42016-09-29 17:27:47 -04001417 if (!plane || !psde) {
1418 SDE_ERROR("invalid plane\n");
1419 return;
1420 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
1421 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
1422 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001423 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04001424 } else if (!catalog) {
1425 SDE_ERROR("invalid catalog\n");
1426 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001427 }
1428
Clarence Ipc47a0692016-10-11 10:54:17 -04001429 if (sde_is_custom_client()) {
1430 if (catalog->mixer_count && catalog->mixer)
1431 zpos_max = catalog->mixer[0].sblk->maxblendstages;
1432 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
1433 /* reserve zpos == 0 for primary planes */
1434 zpos_def = drm_plane_index(plane) + 1;
1435 }
1436
1437 msm_property_install_range(&psde->property_info, "zpos",
1438 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001439
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001440 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001441 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001442
Dhaval Patel47302cf2016-08-18 15:04:28 -07001443 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001444 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07001445 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001446
Clarence Ipdedbba92016-09-27 17:43:10 -04001447 if (psde->pipe_sblk->maxhdeciexp) {
1448 msm_property_install_range(&psde->property_info, "h_decimate",
1449 0x0, 0, psde->pipe_sblk->maxhdeciexp, 0,
1450 PLANE_PROP_H_DECIMATE);
1451 }
1452
1453 if (psde->pipe_sblk->maxvdeciexp) {
1454 msm_property_install_range(&psde->property_info, "v_decimate",
1455 0x0, 0, psde->pipe_sblk->maxvdeciexp, 0,
1456 PLANE_PROP_V_DECIMATE);
1457 }
1458
Clarence Ipb43d4592016-09-08 14:21:35 -04001459 if (psde->features & SDE_SSPP_SCALER) {
1460 msm_property_install_volatile_range(&psde->property_info,
1461 "scaler_v1", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V1);
1462 }
1463
Clarence Ip5fc00c52016-09-23 15:03:34 -04001464 if (psde->features & BIT(SDE_SSPP_CSC)) {
1465 msm_property_install_volatile_range(&psde->property_info,
1466 "csc_v1", 0x0, 0, ~0, 0, PLANE_PROP_CSC_V1);
1467 }
1468
Clarence Ip5e2a9222016-06-26 22:38:24 -04001469 /* standard properties */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001470 msm_property_install_rotation(&psde->property_info,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001471 BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y), PLANE_PROP_ROTATION);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001472
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001473 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001474 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001475
Dhaval Patel47302cf2016-08-18 15:04:28 -07001476 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
1477 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
1478
1479 if (psde->pipe_hw->ops.setup_solidfill)
1480 msm_property_install_range(&psde->property_info, "color_fill",
1481 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
1482
Dhaval Patel4e574842016-08-23 15:11:37 -07001483 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001484 if (!info) {
1485 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07001486 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001487 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001488
1489 msm_property_install_blob(&psde->property_info, "capabilities",
1490 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
1491 sde_kms_info_reset(info);
1492
Clarence Ipea3d6262016-07-15 16:20:11 -04001493 format_list = psde->pipe_sblk->format_list;
1494 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04001495 sde_kms_info_start(info, "pixel_formats");
1496 while (format_list->fourcc_format) {
1497 sde_kms_info_append_format(info,
1498 format_list->fourcc_format,
1499 format_list->modifier);
1500 ++format_list;
1501 }
1502 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04001503 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001504
1505 sde_kms_info_add_keyint(info, "max_linewidth",
1506 psde->pipe_sblk->maxlinewidth);
1507 sde_kms_info_add_keyint(info, "max_upscale",
1508 psde->pipe_sblk->maxupscale);
1509 sde_kms_info_add_keyint(info, "max_downscale",
1510 psde->pipe_sblk->maxdwnscale);
1511 sde_kms_info_add_keyint(info, "max_horizontal_deci",
1512 psde->pipe_sblk->maxhdeciexp);
1513 sde_kms_info_add_keyint(info, "max_vertical_deci",
1514 psde->pipe_sblk->maxvdeciexp);
1515 msm_property_set_blob(&psde->property_info, &psde->blob_info,
1516 info->data, info->len, PLANE_PROP_INFO);
1517
1518 kfree(info);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001519}
1520
Clarence Ip5fc00c52016-09-23 15:03:34 -04001521static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
1522{
1523 struct sde_drm_csc_v1 csc_v1;
1524 int i;
1525
1526 if (!psde) {
1527 SDE_ERROR("invalid plane\n");
1528 return;
1529 }
1530
1531 psde->csc_usr_ptr = NULL;
1532 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001533 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001534 return;
1535 }
1536
1537 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001538 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001539 return;
1540 }
1541
Clarence Ipb43d4592016-09-08 14:21:35 -04001542 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001543 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
1544 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
1545 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
1546 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
1547 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
1548 }
1549 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
1550 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
1551 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
1552 }
1553 psde->csc_usr_ptr = &psde->csc_cfg;
1554}
1555
Clarence Ipb43d4592016-09-08 14:21:35 -04001556static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
1557{
1558 struct sde_drm_scaler_v1 scale_v1;
1559 struct sde_hw_pixel_ext *pe;
1560 int i;
1561
1562 if (!psde) {
1563 SDE_ERROR("invalid plane\n");
1564 return;
1565 }
1566
1567 psde->pixel_ext_usr = false;
1568 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001569 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001570 return;
1571 }
1572
1573 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001574 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001575 return;
1576 }
1577
1578 /* populate from user space */
1579 pe = &(psde->pixel_ext);
1580 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1581 for (i = 0; i < SDE_MAX_PLANES; i++) {
1582 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
1583 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
1584 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
1585 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
1586
1587 pe->horz_filter[i] = scale_v1.horz_filter[i];
1588 pe->vert_filter[i] = scale_v1.vert_filter[i];
1589 }
1590 for (i = 0; i < SDE_MAX_PLANES; i++) {
1591 pe->num_ext_pxls_left[i] = scale_v1.lr.num_pxls_start[i];
1592 pe->num_ext_pxls_right[i] = scale_v1.lr.num_pxls_end[i];
1593 pe->left_ftch[i] = scale_v1.lr.ftch_start[i];
1594 pe->right_ftch[i] = scale_v1.lr.ftch_end[i];
1595 pe->left_rpt[i] = scale_v1.lr.rpt_start[i];
1596 pe->right_rpt[i] = scale_v1.lr.rpt_end[i];
1597 pe->roi_w[i] = scale_v1.lr.roi[i];
1598
1599 pe->num_ext_pxls_top[i] = scale_v1.tb.num_pxls_start[i];
1600 pe->num_ext_pxls_btm[i] = scale_v1.tb.num_pxls_end[i];
1601 pe->top_ftch[i] = scale_v1.tb.ftch_start[i];
1602 pe->btm_ftch[i] = scale_v1.tb.ftch_end[i];
1603 pe->top_rpt[i] = scale_v1.tb.rpt_start[i];
1604 pe->btm_rpt[i] = scale_v1.tb.rpt_end[i];
1605 pe->roi_h[i] = scale_v1.tb.roi[i];
1606 }
1607 psde->pixel_ext_usr = true;
1608
Clarence Ip13a8cf42016-09-29 17:27:47 -04001609 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001610}
1611
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001612static int sde_plane_atomic_set_property(struct drm_plane *plane,
1613 struct drm_plane_state *state, struct drm_property *property,
1614 uint64_t val)
1615{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001616 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001617 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001618 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001619
Clarence Ip13a8cf42016-09-29 17:27:47 -04001620 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001621
1622 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001623 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001624 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001625 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001626 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04001627 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001628 ret = msm_property_atomic_set(&psde->property_info,
1629 pstate->property_values, pstate->property_blobs,
1630 property, val);
1631 if (!ret) {
1632 idx = msm_property_index(&psde->property_info,
1633 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001634 switch (idx) {
1635 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04001636 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001637 break;
1638 case PLANE_PROP_CSC_V1:
1639 _sde_plane_set_csc_v1(psde, (void *)val);
1640 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04001641 case PLANE_PROP_SCALER_V1:
1642 _sde_plane_set_scaler_v1(psde, (void *)val);
1643 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001644 default:
1645 /* nothing to do */
1646 break;
1647 }
Clarence Ipe78efb72016-06-24 18:35:21 -04001648 }
1649 }
1650
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001651 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001652}
1653
1654static int sde_plane_set_property(struct drm_plane *plane,
1655 struct drm_property *property, uint64_t val)
1656{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001657 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001658
Clarence Ipae4e60c2016-06-26 22:44:04 -04001659 return sde_plane_atomic_set_property(plane,
1660 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001661}
1662
1663static int sde_plane_atomic_get_property(struct drm_plane *plane,
1664 const struct drm_plane_state *state,
1665 struct drm_property *property, uint64_t *val)
1666{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001667 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001668 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04001669 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001670
Clarence Ipaa0faf42016-05-30 12:07:48 -04001671 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001672 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001673 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001674 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001675 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001676 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001677 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001678 ret = msm_property_atomic_get(&psde->property_info,
1679 pstate->property_values, pstate->property_blobs,
1680 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04001681 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001682
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001683 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001684}
1685
1686static void sde_plane_destroy(struct drm_plane *plane)
1687{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001688 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001689
Clarence Ip13a8cf42016-09-29 17:27:47 -04001690 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001691
Clarence Ip13a8cf42016-09-29 17:27:47 -04001692 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001693 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1694
Clarence Ip4ce59322016-06-26 22:27:51 -04001695 debugfs_remove_recursive(psde->debugfs_root);
Clarence Ipe78efb72016-06-24 18:35:21 -04001696
Dhaval Patel4e574842016-08-23 15:11:37 -07001697 if (psde->blob_info)
1698 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001699 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04001700 mutex_destroy(&psde->lock);
1701
Clarence Ip4ce59322016-06-26 22:27:51 -04001702 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001703
Clarence Ip4ce59322016-06-26 22:27:51 -04001704 /* this will destroy the states as well */
1705 drm_plane_cleanup(plane);
1706
Clarence Ip4c1d9772016-06-26 09:35:38 -04001707 if (psde->pipe_hw)
1708 sde_hw_sspp_destroy(psde->pipe_hw);
1709
Clarence Ip4ce59322016-06-26 22:27:51 -04001710 kfree(psde);
1711 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001712}
1713
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001714static void sde_plane_destroy_state(struct drm_plane *plane,
1715 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001716{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001717 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04001718 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001719
Clarence Ipae4e60c2016-06-26 22:44:04 -04001720 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001721 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1722 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001723 return;
1724 }
1725
Clarence Ipaa0faf42016-05-30 12:07:48 -04001726 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04001727 pstate = to_sde_plane_state(state);
1728
Clarence Ip13a8cf42016-09-29 17:27:47 -04001729 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001730
Clarence Ipe78efb72016-06-24 18:35:21 -04001731 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001732 if (state->fb)
1733 drm_framebuffer_unreference(state->fb);
1734
Clarence Ipae4e60c2016-06-26 22:44:04 -04001735 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001736 if (pstate->input_fence)
1737 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001738
Clarence Ipaa0faf42016-05-30 12:07:48 -04001739 /* destroy value helper */
1740 msm_property_destroy_state(&psde->property_info, pstate,
1741 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001742}
1743
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001744static struct drm_plane_state *
1745sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001746{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001747 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001748 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04001749 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04001750 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001751
Clarence Ip13a8cf42016-09-29 17:27:47 -04001752 if (!plane) {
1753 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001754 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001755 } else if (!plane->state) {
1756 SDE_ERROR("invalid plane state\n");
1757 return NULL;
1758 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001759
Clarence Ip730e7192016-06-26 22:45:09 -04001760 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001761 psde = to_sde_plane(plane);
1762 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001763 if (!pstate) {
1764 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001765 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001766 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001767
Clarence Ip13a8cf42016-09-29 17:27:47 -04001768 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001769
1770 /* duplicate value helper */
1771 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
1772 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001773
Clarence Ip730e7192016-06-26 22:45:09 -04001774 /* add ref count for frame buffer */
1775 if (pstate->base.fb)
1776 drm_framebuffer_reference(pstate->base.fb);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001777
Clarence Ip17e908b2016-09-29 15:58:00 -04001778 /* clear out any input fence */
1779 pstate->input_fence = 0;
1780 input_fence_default = msm_property_get_default(
1781 &psde->property_info, PLANE_PROP_INPUT_FENCE);
1782 msm_property_set_property(&psde->property_info, pstate->property_values,
1783 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001784
Clarence Ip282dad62016-09-27 17:07:35 -04001785 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04001786 pstate->pending = false;
1787
1788 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001789}
1790
1791static void sde_plane_reset(struct drm_plane *plane)
1792{
Clarence Ipae4e60c2016-06-26 22:44:04 -04001793 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001794 struct sde_plane_state *pstate;
1795
Clarence Ipae4e60c2016-06-26 22:44:04 -04001796 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001797 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001798 return;
1799 }
1800
Clarence Ip730e7192016-06-26 22:45:09 -04001801 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001802 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001803
Clarence Ipae4e60c2016-06-26 22:44:04 -04001804 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001805 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04001806 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001807 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04001808 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001809
Clarence Ipaa0faf42016-05-30 12:07:48 -04001810 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001811 if (!pstate) {
1812 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001813 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001814 }
Clarence Ip730e7192016-06-26 22:45:09 -04001815
Clarence Ipaa0faf42016-05-30 12:07:48 -04001816 /* reset value helper */
1817 msm_property_reset_state(&psde->property_info, pstate,
1818 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001819
1820 pstate->base.plane = plane;
1821
1822 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001823}
1824
1825static const struct drm_plane_funcs sde_plane_funcs = {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001826 .update_plane = drm_atomic_helper_update_plane,
1827 .disable_plane = drm_atomic_helper_disable_plane,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001828 .destroy = sde_plane_destroy,
1829 .set_property = sde_plane_set_property,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001830 .atomic_set_property = sde_plane_atomic_set_property,
1831 .atomic_get_property = sde_plane_atomic_get_property,
1832 .reset = sde_plane_reset,
1833 .atomic_duplicate_state = sde_plane_duplicate_state,
1834 .atomic_destroy_state = sde_plane_destroy_state,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001835};
1836
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001837static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
1838 .prepare_fb = sde_plane_prepare_fb,
1839 .cleanup_fb = sde_plane_cleanup_fb,
1840 .atomic_check = sde_plane_atomic_check,
1841 .atomic_update = sde_plane_atomic_update,
1842};
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001843
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001844enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001845{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001846 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001847}
1848
Clarence Ip4ce59322016-06-26 22:27:51 -04001849static void _sde_plane_init_debugfs(struct sde_plane *psde, struct sde_kms *kms)
1850{
1851 const struct sde_sspp_sub_blks *sblk = 0;
1852 const struct sde_sspp_cfg *cfg = 0;
1853
1854 if (psde && psde->pipe_hw)
1855 cfg = psde->pipe_hw->cap;
1856 if (cfg)
1857 sblk = cfg->sblk;
1858
1859 if (kms && sblk) {
1860 /* create overall sub-directory for the pipe */
1861 psde->debugfs_root =
1862 debugfs_create_dir(psde->pipe_name,
1863 sde_debugfs_get_root(kms));
1864 if (psde->debugfs_root) {
1865 /* don't error check these */
Clarence Ip4c1d9772016-06-26 09:35:38 -04001866 debugfs_create_x32("features", 0644,
Clarence Ip4ce59322016-06-26 22:27:51 -04001867 psde->debugfs_root, &psde->features);
1868
1869 /* add register dump support */
1870 sde_debugfs_setup_regset32(&psde->debugfs_src,
1871 sblk->src_blk.base + cfg->base,
1872 sblk->src_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04001873 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04001874 sde_debugfs_create_regset32("src_blk", 0444,
1875 psde->debugfs_root, &psde->debugfs_src);
1876
1877 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
1878 sblk->scaler_blk.base + cfg->base,
1879 sblk->scaler_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04001880 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04001881 sde_debugfs_create_regset32("scaler_blk", 0444,
1882 psde->debugfs_root,
1883 &psde->debugfs_scaler);
1884
1885 sde_debugfs_setup_regset32(&psde->debugfs_csc,
1886 sblk->csc_blk.base + cfg->base,
1887 sblk->csc_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04001888 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04001889 sde_debugfs_create_regset32("csc_blk", 0444,
1890 psde->debugfs_root, &psde->debugfs_csc);
1891 }
1892 }
1893}
1894
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001895/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04001896struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04001897 uint32_t pipe, bool primary_plane,
1898 unsigned long possible_crtcs)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001899{
1900 struct drm_plane *plane = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001901 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001902 struct msm_drm_private *priv;
1903 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001904 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04001905 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04001906
1907 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001908 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001909 goto exit;
1910 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001911
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001912 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04001913 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001914 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04001915 goto exit;
1916 }
1917
1918 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001919 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04001920 goto exit;
1921 }
1922 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001923
Clarence Ip4c1d9772016-06-26 09:35:38 -04001924 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001925 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001926 goto exit;
1927 }
1928
Clarence Ip4ce59322016-06-26 22:27:51 -04001929 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001930 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
1931 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001932 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001933 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04001934 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001935 }
1936
Clarence Ip4c1d9772016-06-26 09:35:38 -04001937 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001938 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001939 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04001940 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001941
Clarence Ip4c1d9772016-06-26 09:35:38 -04001942 /* initialize underlying h/w driver */
1943 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
1944 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001945 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001946 ret = PTR_ERR(psde->pipe_hw);
1947 goto clean_plane;
1948 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001949 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001950 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001951 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04001952
1953 /* cache features mask for later */
1954 psde->features = psde->pipe_hw->cap->features;
1955 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04001956 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001957 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04001958 goto clean_sspp;
1959 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04001960
1961 /* add plane to DRM framework */
Clarence Ipea3d6262016-07-15 16:20:11 -04001962 psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
1963 psde->formats,
1964 0,
1965 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001966
Clarence Ip4c1d9772016-06-26 09:35:38 -04001967 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001968 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001969 goto clean_sspp;
1970 }
1971
1972 if (psde->features & BIT(SDE_SSPP_CURSOR))
1973 type = DRM_PLANE_TYPE_CURSOR;
1974 else if (primary_plane)
1975 type = DRM_PLANE_TYPE_PRIMARY;
1976 else
1977 type = DRM_PLANE_TYPE_OVERLAY;
Clarence Ip2bbf7b32016-09-23 15:07:16 -04001978 ret = drm_universal_plane_init(dev, plane, possible_crtcs,
1979 &sde_plane_funcs, psde->formats, psde->nformats, type);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001980 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04001981 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001982
Clarence Ip4c1d9772016-06-26 09:35:38 -04001983 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001984 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001985
Clarence Ipaa0faf42016-05-30 12:07:48 -04001986 msm_property_init(&psde->property_info, &plane->base, dev,
1987 priv->plane_property, psde->property_data,
1988 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
1989 sizeof(struct sde_plane_state));
1990
Clarence Ipc47a0692016-10-11 10:54:17 -04001991 _sde_plane_install_properties(plane, kms->catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001992
Clarence Ip4ce59322016-06-26 22:27:51 -04001993 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04001994 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04001995
Clarence Ip730e7192016-06-26 22:45:09 -04001996 mutex_init(&psde->lock);
1997
Clarence Ip4ce59322016-06-26 22:27:51 -04001998 _sde_plane_init_debugfs(psde, kms);
1999
Clarence Ip13a8cf42016-09-29 17:27:47 -04002000 DRM_INFO("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002001 return plane;
2002
Clarence Ip4c1d9772016-06-26 09:35:38 -04002003clean_sspp:
2004 if (psde && psde->pipe_hw)
2005 sde_hw_sspp_destroy(psde->pipe_hw);
2006clean_plane:
2007 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04002008exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002009 return ERR_PTR(ret);
2010}