blob: 5257b8da3a23449ca9765732cd14bfd0bff844f2 [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"
Lloyd Atkinson8772e202016-09-26 17:52:16 -040026#include "sde_vbif.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040027
Clarence Ip13a8cf42016-09-29 17:27:47 -040028#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
29 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
30
31#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
32 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
33
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040034#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
35#define PHASE_STEP_SHIFT 21
36#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
37#define PHASE_RESIDUAL 15
38
Clarence Ipe78efb72016-06-24 18:35:21 -040039#define SHARP_STRENGTH_DEFAULT 32
40#define SHARP_EDGE_THR_DEFAULT 112
41#define SHARP_SMOOTH_THR_DEFAULT 8
42#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040043
Clarence Ip5e2a9222016-06-26 22:38:24 -040044#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070045
Clarence Ipcae1bb62016-07-07 12:07:13 -040046#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
47
Clarence Ip282dad62016-09-27 17:07:35 -040048/* dirty bits for update function */
49#define SDE_PLANE_DIRTY_RECTS 0x1
50#define SDE_PLANE_DIRTY_FORMAT 0x2
51#define SDE_PLANE_DIRTY_SHARPEN 0x4
52#define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF
53
Alan Kwong1a00e4d2016-07-18 09:42:30 -040054/**
55 * enum sde_plane_qos - Different qos configurations for each pipe
56 *
57 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
58 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
59 * this configuration is mutually exclusive from VBLANK_CTRL.
60 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
61 */
62enum sde_plane_qos {
63 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
64 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
65 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
66};
67
Clarence Ip5fc00c52016-09-23 15:03:34 -040068/*
69 * struct sde_plane - local sde plane structure
70 * @csc_cfg: Decoded user configuration for csc
71 * @csc_usr_ptr: Points to csc_cfg if valid user config available
72 * @csc_ptr: Points to sde_csc_cfg structure to use for current
73 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070074struct sde_plane {
75 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040076
77 int mmu_id;
78
Clarence Ip730e7192016-06-26 22:45:09 -040079 struct mutex lock;
80
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040081 enum sde_sspp pipe;
82 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070083 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -040084 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040085
86 struct sde_hw_pipe *pipe_hw;
87 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -040088 struct sde_hw_sharp_cfg sharp_cfg;
Clarence Ip5e2a9222016-06-26 22:38:24 -040089 struct sde_hw_scaler3_cfg scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040090 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -040091 uint32_t color_fill;
92 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040093 bool is_rt_pipe;
Clarence Ip4ce59322016-06-26 22:27:51 -040094
Clarence Ipb43d4592016-09-08 14:21:35 -040095 struct sde_hw_pixel_ext pixel_ext;
96 bool pixel_ext_usr;
97
Clarence Ip373f8592016-05-26 00:58:42 -040098 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -040099 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400100 struct sde_csc_cfg *csc_ptr;
101
Clarence Ip4c1d9772016-06-26 09:35:38 -0400102 const struct sde_sspp_sub_blks *pipe_sblk;
103
Clarence Ip5e2a9222016-06-26 22:38:24 -0400104 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400105
Clarence Ipaa0faf42016-05-30 12:07:48 -0400106 struct msm_property_info property_info;
107 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700108 struct drm_property_blob *blob_info;
Clarence Ip730e7192016-06-26 22:45:09 -0400109
Clarence Ip4ce59322016-06-26 22:27:51 -0400110 /* debugfs related stuff */
111 struct dentry *debugfs_root;
112 struct sde_debugfs_regset32 debugfs_src;
113 struct sde_debugfs_regset32 debugfs_scaler;
114 struct sde_debugfs_regset32 debugfs_csc;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700115};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700116
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700117#define to_sde_plane(x) container_of(x, struct sde_plane, base)
118
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400119static bool sde_plane_enabled(struct drm_plane_state *state)
120{
Clarence Ipdbde9832016-06-26 09:48:36 -0400121 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400122}
123
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400124/**
125 * _sde_plane_calc_fill_level - calculate fill level of the given source format
126 * @plane: Pointer to drm plane
127 * @fmt: Pointer to source buffer format
128 * @src_wdith: width of source buffer
129 * Return: fill level corresponding to the source buffer/format or 0 if error
130 */
131static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
132 const struct sde_format *fmt, u32 src_width)
133{
134 struct sde_plane *psde;
135 u32 fixed_buff_size;
136 u32 total_fl;
137
138 if (!plane || !fmt) {
139 SDE_ERROR("invalid arguments\n");
140 return 0;
141 }
142
143 psde = to_sde_plane(plane);
144 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
145
146 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
147 if (fmt->chroma_sample == SDE_CHROMA_420) {
148 /* NV12 */
149 total_fl = (fixed_buff_size / 2) /
150 ((src_width + 32) * fmt->bpp);
151 } else {
152 /* non NV12 */
153 total_fl = (fixed_buff_size) /
154 ((src_width + 32) * fmt->bpp);
155 }
156 } else {
157 total_fl = (fixed_buff_size * 2) /
158 ((src_width + 32) * fmt->bpp);
159 }
160
161 SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n",
162 plane->base.id, psde->pipe - SSPP_VIG0,
163 fmt->base.pixel_format, src_width, total_fl);
164
165 return total_fl;
166}
167
168/**
169 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
170 * @total_fl: fill level
171 * Return: LUT setting corresponding to the fill level
172 */
173static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
174{
175 u32 qos_lut;
176
177 if (total_fl <= 4)
178 qos_lut = 0x1B;
179 else if (total_fl <= 5)
180 qos_lut = 0x5B;
181 else if (total_fl <= 6)
182 qos_lut = 0x15B;
183 else if (total_fl <= 7)
184 qos_lut = 0x55B;
185 else if (total_fl <= 8)
186 qos_lut = 0x155B;
187 else if (total_fl <= 9)
188 qos_lut = 0x555B;
189 else if (total_fl <= 10)
190 qos_lut = 0x1555B;
191 else if (total_fl <= 11)
192 qos_lut = 0x5555B;
193 else if (total_fl <= 12)
194 qos_lut = 0x15555B;
195 else
196 qos_lut = 0x55555B;
197
198 return qos_lut;
199}
200
201/**
202 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
203 * @total_fl: fill level
204 * Return: LUT setting corresponding to the fill level
205 */
206static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
207{
208 u32 qos_lut;
209
210 if (total_fl <= 10)
211 qos_lut = 0x1AAff;
212 else if (total_fl <= 11)
213 qos_lut = 0x5AAFF;
214 else if (total_fl <= 12)
215 qos_lut = 0x15AAFF;
216 else
217 qos_lut = 0x55AAFF;
218
219 return qos_lut;
220}
221
222/**
223 * _sde_plane_is_rt_pipe - check if the given plane requires real-time QoS
224 * @plane: Pointer to drm plane
225 * @crtc: Pointer to drm crtc associated with the given plane
226 */
227static bool _sde_plane_is_rt_pipe(struct drm_plane *plane,
228 struct drm_crtc *crtc)
229{
230 struct sde_plane *psde = to_sde_plane(plane);
231 struct drm_connector *connector;
232 bool is_rt = false;
233
234 /* check if this plane has a physical connector interface */
Alan Kwong894837a2016-09-29 01:15:23 -0400235 mutex_lock(&plane->dev->mode_config.mutex);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400236 drm_for_each_connector(connector, plane->dev)
237 if (connector->state &&
238 (connector->state->crtc == crtc) &&
239 (connector->connector_type
240 != DRM_MODE_CONNECTOR_VIRTUAL)) {
241 is_rt = true;
242 break;
243 }
Alan Kwong894837a2016-09-29 01:15:23 -0400244 mutex_unlock(&plane->dev->mode_config.mutex);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400245
246 SDE_DEBUG("plane%u: pnum:%d rt:%d\n",
247 plane->base.id, psde->pipe - SSPP_VIG0, is_rt);
248
249 return is_rt;
250}
251
252/**
253 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
254 * @plane: Pointer to drm plane
255 * @fb: Pointer to framebuffer associated with the given plane
256 */
257static void _sde_plane_set_qos_lut(struct drm_plane *plane,
258 struct drm_framebuffer *fb)
259{
260 struct sde_plane *psde;
261 const struct sde_format *fmt = NULL;
262 u32 qos_lut;
263 u32 total_fl = 0;
264
265 if (!plane || !fb) {
266 SDE_ERROR("invalid arguments plane %d fb %d\n",
267 plane != 0, fb != 0);
268 return;
269 }
270
271 psde = to_sde_plane(plane);
272
273 if (!psde->pipe_hw || !psde->pipe_sblk) {
274 SDE_ERROR("invalid arguments\n");
275 return;
276 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
277 return;
278 }
279
280 if (!psde->is_rt_pipe) {
281 qos_lut = psde->pipe_sblk->creq_lut_nrt;
282 } else {
283 fmt = sde_get_sde_format_ext(
284 fb->pixel_format,
285 fb->modifier,
286 drm_format_num_planes(fb->pixel_format));
287 total_fl = _sde_plane_calc_fill_level(plane, fmt,
288 psde->pipe_cfg.src_rect.w);
289
290 if (SDE_FORMAT_IS_LINEAR(fmt))
291 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
292 else
293 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
294 }
295
296 psde->pipe_qos_cfg.creq_lut = qos_lut;
297
298 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
299 (fmt) ? fmt->base.pixel_format : 0,
300 psde->is_rt_pipe, total_fl, qos_lut,
301 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
302
303 SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n",
304 plane->base.id,
305 psde->pipe - SSPP_VIG0,
306 (fmt) ? fmt->base.pixel_format : 0,
307 psde->is_rt_pipe, total_fl, qos_lut);
308
309 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
310}
311
312/**
313 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
314 * @plane: Pointer to drm plane
315 * @fb: Pointer to framebuffer associated with the given plane
316 */
317static void _sde_plane_set_danger_lut(struct drm_plane *plane,
318 struct drm_framebuffer *fb)
319{
320 struct sde_plane *psde;
321 const struct sde_format *fmt = NULL;
322 u32 danger_lut, safe_lut;
323
324 if (!plane || !fb) {
325 SDE_ERROR("invalid arguments\n");
326 return;
327 }
328
329 psde = to_sde_plane(plane);
330
331 if (!psde->pipe_hw || !psde->pipe_sblk) {
332 SDE_ERROR("invalid arguments\n");
333 return;
334 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
335 return;
336 }
337
338 if (!psde->is_rt_pipe) {
339 danger_lut = psde->pipe_sblk->danger_lut_nrt;
340 safe_lut = psde->pipe_sblk->safe_lut_nrt;
341 } else {
342 fmt = sde_get_sde_format_ext(
343 fb->pixel_format,
344 fb->modifier,
345 drm_format_num_planes(fb->pixel_format));
346
347 if (SDE_FORMAT_IS_LINEAR(fmt)) {
348 danger_lut = psde->pipe_sblk->danger_lut_linear;
349 safe_lut = psde->pipe_sblk->safe_lut_linear;
350 } else {
351 danger_lut = psde->pipe_sblk->danger_lut_tile;
352 safe_lut = psde->pipe_sblk->safe_lut_tile;
353 }
354 }
355
356 psde->pipe_qos_cfg.danger_lut = danger_lut;
357 psde->pipe_qos_cfg.safe_lut = safe_lut;
358
359 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
360 (fmt) ? fmt->base.pixel_format : 0,
361 (fmt) ? fmt->fetch_mode : 0,
362 psde->pipe_qos_cfg.danger_lut,
363 psde->pipe_qos_cfg.safe_lut);
364
365 SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n",
366 plane->base.id,
367 psde->pipe - SSPP_VIG0,
368 fmt ? fmt->base.pixel_format : 0,
369 fmt ? fmt->fetch_mode : -1,
370 psde->pipe_qos_cfg.danger_lut,
371 psde->pipe_qos_cfg.safe_lut);
372
373 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
374 &psde->pipe_qos_cfg);
375}
376
377/**
378 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
379 * @plane: Pointer to drm plane
380 * @enable: true to enable QoS control
381 * @flags: QoS control mode (enum sde_plane_qos)
382 */
383static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
384 bool enable, u32 flags)
385{
386 struct sde_plane *psde;
387
388 if (!plane) {
389 SDE_ERROR("invalid arguments\n");
390 return;
391 }
392
393 psde = to_sde_plane(plane);
394
395 if (!psde->pipe_hw || !psde->pipe_sblk) {
396 SDE_ERROR("invalid arguments\n");
397 return;
398 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
399 return;
400 }
401
402 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
403 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
404 psde->pipe_qos_cfg.danger_vblank =
405 psde->pipe_sblk->danger_vblank;
406 psde->pipe_qos_cfg.vblank_en = enable;
407 }
408
409 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
410 /* this feature overrules previous VBLANK_CTRL */
411 psde->pipe_qos_cfg.vblank_en = false;
412 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
413 }
414
415 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
416 psde->pipe_qos_cfg.danger_safe_en = enable;
417
418 if (!psde->is_rt_pipe) {
419 psde->pipe_qos_cfg.vblank_en = false;
420 psde->pipe_qos_cfg.danger_safe_en = false;
421 }
422
423 SDE_DEBUG("plane%u: pnum:%d ds:%d vb:%d pri[0x%x, 0x%x]\n",
424 plane->base.id,
425 psde->pipe - SSPP_VIG0,
426 psde->pipe_qos_cfg.danger_safe_en,
427 psde->pipe_qos_cfg.vblank_en,
428 psde->pipe_qos_cfg.creq_vblank,
429 psde->pipe_qos_cfg.danger_vblank);
430
431 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
432 &psde->pipe_qos_cfg);
433}
434
Alan Kwong5d324e42016-07-28 22:56:18 -0400435/**
436 * _sde_plane_set_ot_limit - set OT limit for the given plane
437 * @plane: Pointer to drm plane
438 * @crtc: Pointer to drm crtc
439 */
440static void _sde_plane_set_ot_limit(struct drm_plane *plane,
441 struct drm_crtc *crtc)
442{
443 struct sde_plane *psde;
444 struct sde_vbif_set_ot_params ot_params;
445 struct msm_drm_private *priv;
446 struct sde_kms *sde_kms;
447
448 if (!plane || !plane->dev || !crtc) {
449 SDE_ERROR("invalid arguments plane %d crtc %d\n",
450 plane != 0, crtc != 0);
451 return;
452 }
453
454 priv = plane->dev->dev_private;
455 if (!priv || !priv->kms) {
456 SDE_ERROR("invalid KMS reference\n");
457 return;
458 }
459
460 sde_kms = to_sde_kms(priv->kms);
461 psde = to_sde_plane(plane);
462 if (!psde->pipe_hw) {
463 SDE_ERROR("invalid pipe reference\n");
464 return;
465 }
466
467 memset(&ot_params, 0, sizeof(ot_params));
468 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
469 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
470 ot_params.width = psde->pipe_cfg.src_rect.w;
471 ot_params.height = psde->pipe_cfg.src_rect.h;
472 ot_params.is_wfd = !psde->is_rt_pipe;
473 ot_params.frame_rate = crtc->mode.vrefresh;
474 ot_params.vbif_idx = VBIF_RT;
475 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
476 ot_params.rd = true;
477
478 sde_vbif_set_ot_limit(sde_kms, &ot_params);
479}
480
Clarence Ipcae1bb62016-07-07 12:07:13 -0400481/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400482static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400483 struct sde_plane_state *pstate, uint64_t fd)
484{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400485 if (!psde || !pstate) {
486 SDE_ERROR("invalid arg(s), plane %d state %d\n",
487 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400488 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400489 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400490
491 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400492 if (pstate->input_fence)
493 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400494
495 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400496 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400497
Clarence Ip13a8cf42016-09-29 17:27:47 -0400498 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400499}
500
Clarence Ipcae1bb62016-07-07 12:07:13 -0400501int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400502{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400503 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400504 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400505 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400506 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400507 int ret = -EINVAL;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400508
509 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700510 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400511 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400512 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400513 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400514 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400515 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400516 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400517
Clarence Ipcae1bb62016-07-07 12:07:13 -0400518 if (input_fence) {
Clarence Ip78a04ed2016-10-04 15:57:45 -0400519 prefix = sde_sync_get_name_prefix(input_fence);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400520 ret = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400521
522 MSM_EVT(plane->dev,
523 plane->base.id,
524 (uint64_t)-ret << (sizeof(uint32_t) * CHAR_BIT)
525 | prefix);
526
Clarence Ipcae1bb62016-07-07 12:07:13 -0400527 switch (ret) {
528 case 0:
Clarence Ip13a8cf42016-09-29 17:27:47 -0400529 SDE_DEBUG_PLANE(psde, "signaled\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400530 break;
531 case -ETIME:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400532 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
533 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400534 psde->is_error = true;
535 break;
536 default:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400537 SDE_ERROR_PLANE(psde, "error %d on %08X\n",
538 ret, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400539 psde->is_error = true;
540 break;
541 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400542 } else {
543 ret = 0;
544 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400545 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400546 return ret;
547}
548
Clarence Ip282dad62016-09-27 17:07:35 -0400549static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400550 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400551 struct sde_hw_pipe_cfg *pipe_cfg,
552 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400553{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400554 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400555 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400556
Clarence Ip13a8cf42016-09-29 17:27:47 -0400557 if (!plane || !pstate || !pipe_cfg || !fb) {
558 SDE_ERROR(
559 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
560 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400561 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400562 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400563
564 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400565 if (!psde->pipe_hw) {
566 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400567 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400568 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400569
Clarence Ipb6eb2362016-09-08 16:18:13 -0400570 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
571 if (ret == -EAGAIN)
572 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
573 else if (ret)
574 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
575 else if (psde->pipe_hw->ops.setup_sourceaddress)
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400576 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400577}
578
Clarence Ipcb410d42016-06-26 22:52:33 -0400579static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400580 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
581 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400582 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400583 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
584{
585}
586
Clarence Ipcb410d42016-06-26 22:52:33 -0400587/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400588 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400589 * @psde: Pointer to SDE plane object
590 * @src: Source size
591 * @dst: Destination size
592 * @phase_steps: Pointer to output array for phase steps
593 * @filter: Pointer to output array for filter type
594 * @fmt: Pointer to format definition
595 * @chroma_subsampling: Subsampling amount for chroma channel
596 *
597 * Returns: 0 on success
598 */
599static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400600 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400601 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400602 uint32_t chroma_subsampling)
603{
Clarence Ipcb410d42016-06-26 22:52:33 -0400604 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400605 SDE_ERROR(
606 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
607 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400608 return -EINVAL;
609 }
610
Clarence Ip4c1d9772016-06-26 09:35:38 -0400611 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400612 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400613 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400614 phase_steps[SDE_SSPP_COMP_1_2] =
615 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
616 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
617 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400618
619 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400620 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400621 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400622 (src <= dst) ? SDE_SCALE_FILTER_BIL :
623 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400624
Clarence Ipdbde9832016-06-26 09:48:36 -0400625 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400626 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400627 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
628 } else {
629 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
630 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400631 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400632 }
633 } else {
634 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400635 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
636 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
637 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400638 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400639 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400640}
641
Clarence Ipcb410d42016-06-26 22:52:33 -0400642/**
643 * _sde_plane_setup_pixel_ext - determine default pixel extension values
644 * @psde: Pointer to SDE plane object
645 * @src: Source size
646 * @dst: Destination size
647 * @decimated_src: Source size after decimation, if any
648 * @phase_steps: Pointer to output array for phase steps
649 * @out_src: Output array for pixel extension values
650 * @out_edge1: Output array for pixel extension first edge
651 * @out_edge2: Output array for pixel extension second edge
652 * @filter: Pointer to array for filter type
653 * @fmt: Pointer to format definition
654 * @chroma_subsampling: Subsampling amount for chroma channel
655 * @post_compare: Whether to chroma subsampled source size for comparisions
656 */
657static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400658 uint32_t src, uint32_t dst, uint32_t decimated_src,
659 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400660 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400661 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400662 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400663{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400664 int64_t edge1, edge2, caf;
665 uint32_t src_work;
666 int i, tmp;
667
Clarence Ipcb410d42016-06-26 22:52:33 -0400668 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400669 out_edge2 && filter && fmt) {
670 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400671 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400672 caf = PHASE_STEP_UNIT_SCALE;
673 else
674 caf = 0;
675
676 for (i = 0; i < SDE_MAX_PLANES; i++) {
677 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400678 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400679 src_work /= chroma_subsampling;
680 if (post_compare)
681 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400682 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400683 /* unity */
684 edge1 = 0;
685 edge2 = 0;
686 } else if (dst >= src) {
687 /* upscale */
688 edge1 = (1 << PHASE_RESIDUAL);
689 edge1 -= caf;
690 edge2 = (1 << PHASE_RESIDUAL);
691 edge2 += (dst - 1) * *(phase_steps + i);
692 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
693 edge2 += caf;
694 edge2 = -(edge2);
695 } else {
696 /* downscale */
697 edge1 = 0;
698 edge2 = (dst - 1) * *(phase_steps + i);
699 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
700 edge2 += *(phase_steps + i);
701 edge2 = -(edge2);
702 }
703
704 /* only enable CAF for luma plane */
705 caf = 0;
706
707 /* populate output arrays */
708 *(out_src + i) = src_work;
709
710 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400711 if (edge1 >= 0) {
712 tmp = (uint32_t)edge1;
713 tmp >>= PHASE_STEP_SHIFT;
714 *(out_edge1 + i) = -tmp;
715 } else {
716 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400717 *(out_edge1 + i) =
718 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
719 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400720 }
721 if (edge2 >= 0) {
722 tmp = (uint32_t)edge2;
723 tmp >>= PHASE_STEP_SHIFT;
724 *(out_edge2 + i) = -tmp;
725 } else {
726 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400727 *(out_edge2 + i) =
728 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
729 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400730 }
731 }
732 }
733}
734
Clarence Ip5fc00c52016-09-23 15:03:34 -0400735static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400736{
737 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
738 {
Clarence Ip373f8592016-05-26 00:58:42 -0400739 /* S15.16 format */
740 0x00012A00, 0x00000000, 0x00019880,
741 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
742 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400743 },
Clarence Ip373f8592016-05-26 00:58:42 -0400744 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400745 { 0xfff0, 0xff80, 0xff80,},
746 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400747 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400748 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400749 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400750 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400751
Clarence Ip5fc00c52016-09-23 15:03:34 -0400752 if (!psde) {
753 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400754 return;
755 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400756
Clarence Ipcae1bb62016-07-07 12:07:13 -0400757 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400758 if (psde->csc_usr_ptr)
759 psde->csc_ptr = psde->csc_usr_ptr;
760 else
Clarence Ip373f8592016-05-26 00:58:42 -0400761 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400762
Clarence Ip13a8cf42016-09-29 17:27:47 -0400763 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400764 psde->csc_ptr->csc_mv[0],
765 psde->csc_ptr->csc_mv[1],
766 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400767}
768
Clarence Ipcb410d42016-06-26 22:52:33 -0400769static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400770 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -0400771 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700772{
Clarence Ipb43d4592016-09-08 14:21:35 -0400773 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -0400774 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Clarence Ipb43d4592016-09-08 14:21:35 -0400775 uint32_t tmp, i;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400776
Clarence Ipb43d4592016-09-08 14:21:35 -0400777 if (!psde || !fmt) {
778 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
779 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400780 return;
Clarence Ipb43d4592016-09-08 14:21:35 -0400781 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400782
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400783 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400784
Clarence Ipdedbba92016-09-27 17:43:10 -0400785 psde->pipe_cfg.horz_decimation =
786 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
787 psde->pipe_cfg.vert_decimation =
788 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400789
790 /* don't chroma subsample if decimating */
791 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400792 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400793 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400794 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400795
Clarence Ip5e2a9222016-06-26 22:38:24 -0400796 /* update scaler */
797 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400798 if (!psde->pixel_ext_usr) {
799 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -0400800 _sde_plane_setup_scaler3(psde,
801 psde->pipe_cfg.src_rect.w,
802 psde->pipe_cfg.src_rect.h,
803 psde->pipe_cfg.dst_rect.w,
804 psde->pipe_cfg.dst_rect.h,
805 &psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400806 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400807 }
Clarence Ipb43d4592016-09-08 14:21:35 -0400808 } else if (!psde->pixel_ext_usr) {
809 /* calculate default configuration for QSEED2 */
810 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400811
Clarence Ip13a8cf42016-09-29 17:27:47 -0400812 SDE_DEBUG_PLANE(psde, "default config\n");
Clarence Ipb43d4592016-09-08 14:21:35 -0400813 _sde_plane_setup_scaler2(psde,
814 psde->pipe_cfg.src_rect.w,
815 psde->pipe_cfg.dst_rect.w,
816 pe->phase_step_x,
817 pe->horz_filter, fmt, chroma_subsmpl_h);
818 _sde_plane_setup_scaler2(psde,
819 psde->pipe_cfg.src_rect.h,
820 psde->pipe_cfg.dst_rect.h,
821 pe->phase_step_y,
822 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400823
Clarence Ip5e2a9222016-06-26 22:38:24 -0400824 /* calculate left/right/top/bottom pixel extensions */
Clarence Ipcb410d42016-06-26 22:52:33 -0400825 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400826 psde->pipe_cfg.horz_decimation);
Clarence Ipdbde9832016-06-26 09:48:36 -0400827 if (SDE_FORMAT_IS_YUV(fmt))
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400828 tmp &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -0400829 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
830 psde->pipe_cfg.dst_rect.w, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400831 pe->phase_step_x,
832 pe->roi_w,
833 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -0400834 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400835 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400836
Clarence Ipcb410d42016-06-26 22:52:33 -0400837 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400838 psde->pipe_cfg.vert_decimation);
Clarence Ipcb410d42016-06-26 22:52:33 -0400839 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
840 psde->pipe_cfg.dst_rect.h, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400841 pe->phase_step_y,
842 pe->roi_h,
843 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -0400844 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400845 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400846
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400847 for (i = 0; i < SDE_MAX_PLANES; i++) {
848 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400849 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400850 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400851 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400852
853 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400854 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400855 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400856 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400857
858 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400859 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400860 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400861 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400862
863 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400864 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400865 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400866 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400867 }
868 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400869}
870
Clarence Ipcae1bb62016-07-07 12:07:13 -0400871/**
872 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -0400873 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -0400874 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
875 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
876 * Returns: 0 on success
877 */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400878static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -0400879 uint32_t color, uint32_t alpha)
880{
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400881 const struct sde_format *fmt;
Clarence Ipcb410d42016-06-26 22:52:33 -0400882
Clarence Ip13a8cf42016-09-29 17:27:47 -0400883 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700884 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400885 return -EINVAL;
886 }
887
Clarence Ipcb410d42016-06-26 22:52:33 -0400888 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400889 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400890 return -EINVAL;
891 }
892
Clarence Ip13a8cf42016-09-29 17:27:47 -0400893 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400894
Clarence Ipcb410d42016-06-26 22:52:33 -0400895 /*
896 * select fill format to match user property expectation,
897 * h/w only supports RGB variants
898 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400899 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -0400900
901 /* update sspp */
902 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
903 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
904 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
905
906 /* override scaler/decimation if solid fill */
907 psde->pipe_cfg.src_rect.x = 0;
908 psde->pipe_cfg.src_rect.y = 0;
909 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
910 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
911
912 _sde_plane_setup_scaler(psde, fmt, 0);
913
914 if (psde->pipe_hw->ops.setup_format)
915 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
916 fmt, SDE_SSPP_SOLID_FILL);
917
918 if (psde->pipe_hw->ops.setup_rects)
919 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
920 &psde->pipe_cfg, &psde->pixel_ext);
921 }
922
923 return 0;
924}
925
926static int _sde_plane_mode_set(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -0700927 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -0400928{
Clarence Ipc47a0692016-10-11 10:54:17 -0400929 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -0400930 struct sde_plane *psde;
931 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400932 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -0700933 struct drm_crtc *crtc;
934 struct drm_framebuffer *fb;
935 struct sde_rect src, dst;
936 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -0400937 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -0400938
Clarence Ip13a8cf42016-09-29 17:27:47 -0400939 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -0400940 SDE_ERROR("invalid plane\n");
941 return -EINVAL;
942 } else if (!plane->state) {
943 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400944 return -EINVAL;
945 }
946
947 psde = to_sde_plane(plane);
948 pstate = to_sde_plane_state(plane->state);
Clarence Ipcb410d42016-06-26 22:52:33 -0400949
Dhaval Patel47302cf2016-08-18 15:04:28 -0700950 crtc = state->crtc;
951 fb = state->fb;
952 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400953 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
954 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -0700955 return -EINVAL;
956 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400957 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400958 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -0400959
Clarence Ip282dad62016-09-27 17:07:35 -0400960 /* determine what needs to be refreshed */
961 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
962 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400963 case PLANE_PROP_SCALER_V1:
Clarence Ipdedbba92016-09-27 17:43:10 -0400964 case PLANE_PROP_H_DECIMATE:
965 case PLANE_PROP_V_DECIMATE:
966 case PLANE_PROP_SRC_CONFIG:
967 case PLANE_PROP_ZPOS:
Clarence Ip282dad62016-09-27 17:07:35 -0400968 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
969 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400970 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -0400971 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
972 break;
973 case PLANE_PROP_COLOR_FILL:
974 /* potentially need to refresh everything */
975 pstate->dirty = SDE_PLANE_DIRTY_ALL;
976 break;
977 case PLANE_PROP_ROTATION:
978 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
979 break;
Clarence Ip282dad62016-09-27 17:07:35 -0400980 case PLANE_PROP_INFO:
981 case PLANE_PROP_ALPHA:
982 case PLANE_PROP_INPUT_FENCE:
983 case PLANE_PROP_BLEND_OP:
984 /* no special action required */
985 break;
986 default:
987 /* unknown property, refresh everything */
988 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
989 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
990 break;
991 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400992 }
993
Clarence Ip282dad62016-09-27 17:07:35 -0400994 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
995 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -0400996
997 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
998
Clarence Ip282dad62016-09-27 17:07:35 -0400999 /* early out if nothing dirty */
1000 if (!pstate->dirty)
1001 return 0;
1002 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001003
Clarence Ip282dad62016-09-27 17:07:35 -04001004 psde->is_rt_pipe = _sde_plane_is_rt_pipe(plane, crtc);
1005 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1006
1007 /* update roi config */
1008 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
1009 POPULATE_RECT(&src, state->src_x, state->src_y,
1010 state->src_w, state->src_h, q16_data);
1011 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
1012 state->crtc_w, state->crtc_h, !q16_data);
1013
Clarence Ip13a8cf42016-09-29 17:27:47 -04001014 SDE_DEBUG_PLANE(psde,
1015 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001016 fb->base.id, src.x, src.y, src.w, src.h,
1017 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
1018 drm_get_format_name(fmt->base.pixel_format),
1019 SDE_FORMAT_IS_UBWC(fmt));
1020
1021 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
1022 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001023 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001024 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
1025 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
1026 src.h /= 2;
1027 src.y = DIV_ROUND_UP(src.y, 2);
1028 src.y &= ~0x1;
1029 }
1030
1031 psde->pipe_cfg.src_rect = src;
1032 psde->pipe_cfg.dst_rect = dst;
1033
1034 /* check for color fill */
1035 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
1036 PLANE_PROP_COLOR_FILL);
1037 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
1038 /* skip remaining processing on color fill */
1039 pstate->dirty = 0x0;
1040 } else if (psde->pipe_hw->ops.setup_rects) {
1041 _sde_plane_setup_scaler(psde, fmt, pstate);
1042
Clarence Ip282dad62016-09-27 17:07:35 -04001043 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
1044 &psde->pipe_cfg, &psde->pixel_ext);
1045 }
Dhaval Patel48c76022016-09-01 17:51:23 -07001046 }
1047
Clarence Ip282dad62016-09-27 17:07:35 -04001048 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
1049 psde->pipe_hw->ops.setup_format) {
1050 src_flags = 0x0;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001051 SDE_DEBUG_PLANE(psde, "rotation 0x%llX\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001052 sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
1053 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1054 BIT(DRM_REFLECT_X))
1055 src_flags |= SDE_SSPP_FLIP_LR;
1056 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1057 BIT(DRM_REFLECT_Y))
1058 src_flags |= SDE_SSPP_FLIP_UD;
1059
1060 /* update format */
1061 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags);
1062
1063 /* update csc */
1064 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04001065 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04001066 else
1067 psde->csc_ptr = 0;
1068 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001069
Clarence Ipe78efb72016-06-24 18:35:21 -04001070 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04001071 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
1072 psde->pipe_hw->ops.setup_sharpening) {
1073 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
1074 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
1075 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
1076 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04001077
Clarence Ipe78efb72016-06-24 18:35:21 -04001078 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04001079 &psde->sharp_cfg);
1080 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001081
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001082 _sde_plane_set_qos_lut(plane, fb);
1083 _sde_plane_set_danger_lut(plane, fb);
1084
Alan Kwong5d324e42016-07-28 22:56:18 -04001085 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001086 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04001087 _sde_plane_set_ot_limit(plane, crtc);
1088 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001089
Clarence Ip282dad62016-09-27 17:07:35 -04001090 /* clear dirty */
1091 pstate->dirty = 0x0;
1092
Clarence Ip5e2a9222016-06-26 22:38:24 -04001093 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001094}
1095
1096static int sde_plane_prepare_fb(struct drm_plane *plane,
1097 const struct drm_plane_state *new_state)
1098{
1099 struct drm_framebuffer *fb = new_state->fb;
1100 struct sde_plane *psde = to_sde_plane(plane);
1101
1102 if (!new_state->fb)
1103 return 0;
1104
Clarence Ip13a8cf42016-09-29 17:27:47 -04001105 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001106 return msm_framebuffer_prepare(fb, psde->mmu_id);
1107}
1108
1109static void sde_plane_cleanup_fb(struct drm_plane *plane,
1110 const struct drm_plane_state *old_state)
1111{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001112 struct drm_framebuffer *fb = old_state ? old_state->fb : NULL;
1113 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001114
1115 if (!fb)
1116 return;
1117
Clarence Ip13a8cf42016-09-29 17:27:47 -04001118 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001119 msm_framebuffer_cleanup(fb, psde->mmu_id);
1120}
1121
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001122static void _sde_plane_atomic_check_mode_changed(struct sde_plane *psde,
1123 struct drm_plane_state *state,
1124 struct drm_plane_state *old_state)
1125{
1126 struct sde_plane_state *pstate = to_sde_plane_state(state);
1127
Dhaval Patel47302cf2016-08-18 15:04:28 -07001128 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04001129 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001130 return;
1131
Clarence Ip282dad62016-09-27 17:07:35 -04001132 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
1133 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001134 SDE_DEBUG_PLANE(psde,
1135 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001136 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001137 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001138 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001139 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001140 } else if (state->src_w != old_state->src_w ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07001141 state->src_h != old_state->src_h ||
1142 state->src_x != old_state->src_x ||
1143 state->src_y != old_state->src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001144 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001145 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001146 } else if (state->crtc_w != old_state->crtc_w ||
1147 state->crtc_h != old_state->crtc_h ||
1148 state->crtc_x != old_state->crtc_x ||
1149 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001150 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001151 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1152 }
1153
1154 if (!state->fb || !old_state->fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001155 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001156 } else if (state->fb->pixel_format != old_state->fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001157 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001158 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001159 } else {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001160 uint64_t *new_mods = state->fb->modifier;
1161 uint64_t *old_mods = old_state->fb->modifier;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001162 uint32_t *new_pitches = state->fb->pitches;
1163 uint32_t *old_pitches = old_state->fb->pitches;
1164 uint32_t *new_offset = state->fb->offsets;
1165 uint32_t *old_offset = old_state->fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001166 int i;
1167
1168 for (i = 0; i < ARRAY_SIZE(state->fb->modifier); i++) {
1169 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001170 SDE_DEBUG_PLANE(psde,
1171 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001172 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001173 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001174 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1175 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001176 break;
1177 }
1178 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001179 for (i = 0; i < ARRAY_SIZE(state->fb->pitches); i++) {
1180 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001181 SDE_DEBUG_PLANE(psde,
1182 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001183 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001184 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001185 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001186 break;
1187 }
1188 }
Dhaval Patel47302cf2016-08-18 15:04:28 -07001189 for (i = 0; i < ARRAY_SIZE(state->fb->offsets); i++) {
1190 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001191 SDE_DEBUG_PLANE(psde,
1192 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001193 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001194 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001195 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1196 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001197 break;
1198 }
1199 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001200 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001201}
1202
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001203static int sde_plane_atomic_check(struct drm_plane *plane,
1204 struct drm_plane_state *state)
1205{
Clarence Ipdedbba92016-09-27 17:43:10 -04001206 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04001207 struct sde_plane *psde;
1208 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001209 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001210 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04001211 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001212 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
1213 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04001214
1215 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001216 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1217 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04001218 ret = -EINVAL;
1219 goto exit;
1220 }
1221
1222 psde = to_sde_plane(plane);
1223 pstate = to_sde_plane_state(state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001224
1225 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001226 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001227 ret = -EINVAL;
1228 goto exit;
1229 }
1230
Clarence Ipdedbba92016-09-27 17:43:10 -04001231 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1232 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04001233
1234 /* src values are in Q16 fixed point, convert to integer */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001235 POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w,
1236 state->src_h, q16_data);
1237 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
1238 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04001239
Dhaval Patel47302cf2016-08-18 15:04:28 -07001240 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
1241 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04001242
Dhaval Patel47302cf2016-08-18 15:04:28 -07001243 max_upscale = psde->pipe_sblk->maxupscale;
1244 max_downscale = psde->pipe_sblk->maxdwnscale;
1245 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04001246
Clarence Ip13a8cf42016-09-29 17:27:47 -04001247 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001248 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001249
Dhaval Patel47302cf2016-08-18 15:04:28 -07001250 if (!sde_plane_enabled(state))
1251 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04001252
Dhaval Patel47302cf2016-08-18 15:04:28 -07001253 fmt = to_sde_format(msm_framebuffer_format(state->fb));
1254
1255 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
1256
1257 if (SDE_FORMAT_IS_YUV(fmt) &&
1258 (!(psde->features & SDE_SSPP_SCALER) ||
1259 !(psde->features & BIT(SDE_SSPP_CSC)))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001260 SDE_ERROR_PLANE(psde,
1261 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07001262 ret = -EINVAL;
1263
1264 /* check src bounds */
1265 } else if (state->fb->width > MAX_IMG_WIDTH ||
1266 state->fb->height > MAX_IMG_HEIGHT ||
1267 src.w < min_src_size || src.h < min_src_size ||
1268 CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) ||
1269 CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001270 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001271 src.x, src.y, src.w, src.h);
1272 ret = -E2BIG;
1273
1274 /* valid yuv image */
1275 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
1276 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001277 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001278 src.x, src.y, src.w, src.h);
1279 ret = -EINVAL;
1280
1281 /* min dst support */
1282 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001283 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001284 dst.x, dst.y, dst.w, dst.h);
1285 ret = -EINVAL;
1286
1287 /* decimation validation */
1288 } else if (deci_w || deci_h) {
1289 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
1290 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001291 SDE_ERROR_PLANE(psde,
1292 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001293 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001294 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001295 SDE_ERROR_PLANE(psde,
1296 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001297 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001298 }
1299
Dhaval Patel47302cf2016-08-18 15:04:28 -07001300 } else if (!(psde->features & SDE_SSPP_SCALER) &&
1301 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001302 SDE_ERROR_PLANE(psde,
1303 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001304 src.w, src.h, dst.w, dst.h);
1305 ret = -EINVAL;
1306
1307 /* check decimated source width */
1308 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001309 SDE_ERROR_PLANE(psde,
1310 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001311 src.w, src_deci_w, max_linewidth);
1312 ret = -E2BIG;
1313
1314 /* check max scaler capability */
1315 } else if (((src_deci_w * max_upscale) < dst.w) ||
1316 ((src_deci_h * max_upscale) < dst.h) ||
1317 ((dst.w * max_downscale) < src_deci_w) ||
1318 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001319 SDE_ERROR_PLANE(psde,
1320 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001321 src_deci_w, src_deci_h, dst.w, dst.h);
1322 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001323 }
1324
Dhaval Patel47302cf2016-08-18 15:04:28 -07001325modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001326 if (!ret)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001327 _sde_plane_atomic_check_mode_changed(psde, state, plane->state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001328exit:
1329 return ret;
1330}
1331
Clarence Ipcae1bb62016-07-07 12:07:13 -04001332/**
1333 * sde_plane_flush - final plane operations before commit flush
1334 * @plane: Pointer to drm plane structure
1335 */
1336void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04001337{
Clarence Ipcae1bb62016-07-07 12:07:13 -04001338 struct sde_plane *psde;
1339
Clarence Ip13a8cf42016-09-29 17:27:47 -04001340 if (!plane) {
1341 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001342 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001343 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04001344
1345 psde = to_sde_plane(plane);
1346
1347 /*
1348 * These updates have to be done immediately before the plane flush
1349 * timing, and may not be moved to the atomic_update/mode_set functions.
1350 */
1351 if (psde->is_error)
1352 /* force white frame with 0% alpha pipe output on error */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001353 _sde_plane_color_fill(psde, 0xFFFFFF, 0x0);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001354 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
1355 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001356 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001357 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
1358 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
1359
1360 /* flag h/w flush complete */
1361 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04001362 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001363}
1364
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001365static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04001366 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001367{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001368 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001369 struct drm_plane_state *state;
1370 struct sde_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001371
Clarence Ip13a8cf42016-09-29 17:27:47 -04001372 if (!plane) {
1373 SDE_ERROR("invalid plane\n");
1374 return;
1375 } else if (!plane->state) {
1376 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04001377 return;
1378 }
1379
Clarence Ip13a8cf42016-09-29 17:27:47 -04001380 psde = to_sde_plane(plane);
1381 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001382 state = plane->state;
1383 pstate = to_sde_plane_state(state);
1384
Clarence Ip13a8cf42016-09-29 17:27:47 -04001385 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001386
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001387 if (!sde_plane_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04001388 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001389 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001390 int ret;
1391
Dhaval Patel47302cf2016-08-18 15:04:28 -07001392 ret = _sde_plane_mode_set(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001393 /* atomic_check should have ensured that this doesn't fail */
1394 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001395 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001396}
1397
Dhaval Patel47302cf2016-08-18 15:04:28 -07001398
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001399/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001400static void _sde_plane_install_properties(struct drm_plane *plane,
Clarence Ipc47a0692016-10-11 10:54:17 -04001401 struct sde_mdss_cfg *catalog)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001402{
Clarence Ip5e2a9222016-06-26 22:38:24 -04001403 static const struct drm_prop_enum_list e_blend_op[] = {
1404 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
1405 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
1406 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
1407 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
1408 };
1409 static const struct drm_prop_enum_list e_src_config[] = {
1410 {SDE_DRM_DEINTERLACE, "deinterlace"}
1411 };
Clarence Ipea3d6262016-07-15 16:20:11 -04001412 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07001413 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001414 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04001415 int zpos_max = 255;
1416 int zpos_def = 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001417
Clarence Ip13a8cf42016-09-29 17:27:47 -04001418 if (!plane || !psde) {
1419 SDE_ERROR("invalid plane\n");
1420 return;
1421 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
1422 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
1423 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001424 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04001425 } else if (!catalog) {
1426 SDE_ERROR("invalid catalog\n");
1427 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001428 }
1429
Clarence Ipc47a0692016-10-11 10:54:17 -04001430 if (sde_is_custom_client()) {
1431 if (catalog->mixer_count && catalog->mixer)
1432 zpos_max = catalog->mixer[0].sblk->maxblendstages;
1433 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
1434 /* reserve zpos == 0 for primary planes */
1435 zpos_def = drm_plane_index(plane) + 1;
1436 }
1437
1438 msm_property_install_range(&psde->property_info, "zpos",
1439 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001440
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001441 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001442 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001443
Dhaval Patel47302cf2016-08-18 15:04:28 -07001444 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001445 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07001446 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001447
Clarence Ipdedbba92016-09-27 17:43:10 -04001448 if (psde->pipe_sblk->maxhdeciexp) {
1449 msm_property_install_range(&psde->property_info, "h_decimate",
1450 0x0, 0, psde->pipe_sblk->maxhdeciexp, 0,
1451 PLANE_PROP_H_DECIMATE);
1452 }
1453
1454 if (psde->pipe_sblk->maxvdeciexp) {
1455 msm_property_install_range(&psde->property_info, "v_decimate",
1456 0x0, 0, psde->pipe_sblk->maxvdeciexp, 0,
1457 PLANE_PROP_V_DECIMATE);
1458 }
1459
Clarence Ipb43d4592016-09-08 14:21:35 -04001460 if (psde->features & SDE_SSPP_SCALER) {
1461 msm_property_install_volatile_range(&psde->property_info,
1462 "scaler_v1", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V1);
1463 }
1464
Clarence Ip5fc00c52016-09-23 15:03:34 -04001465 if (psde->features & BIT(SDE_SSPP_CSC)) {
1466 msm_property_install_volatile_range(&psde->property_info,
1467 "csc_v1", 0x0, 0, ~0, 0, PLANE_PROP_CSC_V1);
1468 }
1469
Clarence Ip5e2a9222016-06-26 22:38:24 -04001470 /* standard properties */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001471 msm_property_install_rotation(&psde->property_info,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001472 BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y), PLANE_PROP_ROTATION);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001473
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001474 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001475 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001476
Dhaval Patel47302cf2016-08-18 15:04:28 -07001477 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
1478 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
1479
1480 if (psde->pipe_hw->ops.setup_solidfill)
1481 msm_property_install_range(&psde->property_info, "color_fill",
1482 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
1483
Dhaval Patel4e574842016-08-23 15:11:37 -07001484 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001485 if (!info) {
1486 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07001487 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001488 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001489
1490 msm_property_install_blob(&psde->property_info, "capabilities",
1491 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
1492 sde_kms_info_reset(info);
1493
Clarence Ipea3d6262016-07-15 16:20:11 -04001494 format_list = psde->pipe_sblk->format_list;
1495 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04001496 sde_kms_info_start(info, "pixel_formats");
1497 while (format_list->fourcc_format) {
1498 sde_kms_info_append_format(info,
1499 format_list->fourcc_format,
1500 format_list->modifier);
1501 ++format_list;
1502 }
1503 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04001504 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001505
1506 sde_kms_info_add_keyint(info, "max_linewidth",
1507 psde->pipe_sblk->maxlinewidth);
1508 sde_kms_info_add_keyint(info, "max_upscale",
1509 psde->pipe_sblk->maxupscale);
1510 sde_kms_info_add_keyint(info, "max_downscale",
1511 psde->pipe_sblk->maxdwnscale);
1512 sde_kms_info_add_keyint(info, "max_horizontal_deci",
1513 psde->pipe_sblk->maxhdeciexp);
1514 sde_kms_info_add_keyint(info, "max_vertical_deci",
1515 psde->pipe_sblk->maxvdeciexp);
1516 msm_property_set_blob(&psde->property_info, &psde->blob_info,
1517 info->data, info->len, PLANE_PROP_INFO);
1518
1519 kfree(info);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001520}
1521
Clarence Ip5fc00c52016-09-23 15:03:34 -04001522static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
1523{
1524 struct sde_drm_csc_v1 csc_v1;
1525 int i;
1526
1527 if (!psde) {
1528 SDE_ERROR("invalid plane\n");
1529 return;
1530 }
1531
1532 psde->csc_usr_ptr = NULL;
1533 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001534 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001535 return;
1536 }
1537
1538 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001539 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001540 return;
1541 }
1542
Clarence Ipb43d4592016-09-08 14:21:35 -04001543 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001544 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
1545 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
1546 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
1547 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
1548 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
1549 }
1550 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
1551 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
1552 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
1553 }
1554 psde->csc_usr_ptr = &psde->csc_cfg;
1555}
1556
Clarence Ipb43d4592016-09-08 14:21:35 -04001557static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
1558{
1559 struct sde_drm_scaler_v1 scale_v1;
1560 struct sde_hw_pixel_ext *pe;
1561 int i;
1562
1563 if (!psde) {
1564 SDE_ERROR("invalid plane\n");
1565 return;
1566 }
1567
1568 psde->pixel_ext_usr = false;
1569 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001570 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001571 return;
1572 }
1573
1574 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001575 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001576 return;
1577 }
1578
1579 /* populate from user space */
1580 pe = &(psde->pixel_ext);
1581 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1582 for (i = 0; i < SDE_MAX_PLANES; i++) {
1583 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
1584 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
1585 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
1586 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
1587
1588 pe->horz_filter[i] = scale_v1.horz_filter[i];
1589 pe->vert_filter[i] = scale_v1.vert_filter[i];
1590 }
1591 for (i = 0; i < SDE_MAX_PLANES; i++) {
1592 pe->num_ext_pxls_left[i] = scale_v1.lr.num_pxls_start[i];
1593 pe->num_ext_pxls_right[i] = scale_v1.lr.num_pxls_end[i];
1594 pe->left_ftch[i] = scale_v1.lr.ftch_start[i];
1595 pe->right_ftch[i] = scale_v1.lr.ftch_end[i];
1596 pe->left_rpt[i] = scale_v1.lr.rpt_start[i];
1597 pe->right_rpt[i] = scale_v1.lr.rpt_end[i];
1598 pe->roi_w[i] = scale_v1.lr.roi[i];
1599
1600 pe->num_ext_pxls_top[i] = scale_v1.tb.num_pxls_start[i];
1601 pe->num_ext_pxls_btm[i] = scale_v1.tb.num_pxls_end[i];
1602 pe->top_ftch[i] = scale_v1.tb.ftch_start[i];
1603 pe->btm_ftch[i] = scale_v1.tb.ftch_end[i];
1604 pe->top_rpt[i] = scale_v1.tb.rpt_start[i];
1605 pe->btm_rpt[i] = scale_v1.tb.rpt_end[i];
1606 pe->roi_h[i] = scale_v1.tb.roi[i];
1607 }
1608 psde->pixel_ext_usr = true;
1609
Clarence Ip13a8cf42016-09-29 17:27:47 -04001610 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001611}
1612
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001613static int sde_plane_atomic_set_property(struct drm_plane *plane,
1614 struct drm_plane_state *state, struct drm_property *property,
1615 uint64_t val)
1616{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001617 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001618 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001619 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001620
Clarence Ip13a8cf42016-09-29 17:27:47 -04001621 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001622
1623 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001624 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001625 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001626 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001627 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04001628 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001629 ret = msm_property_atomic_set(&psde->property_info,
1630 pstate->property_values, pstate->property_blobs,
1631 property, val);
1632 if (!ret) {
1633 idx = msm_property_index(&psde->property_info,
1634 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001635 switch (idx) {
1636 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04001637 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001638 break;
1639 case PLANE_PROP_CSC_V1:
1640 _sde_plane_set_csc_v1(psde, (void *)val);
1641 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04001642 case PLANE_PROP_SCALER_V1:
1643 _sde_plane_set_scaler_v1(psde, (void *)val);
1644 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001645 default:
1646 /* nothing to do */
1647 break;
1648 }
Clarence Ipe78efb72016-06-24 18:35:21 -04001649 }
1650 }
1651
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001652 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001653}
1654
1655static int sde_plane_set_property(struct drm_plane *plane,
1656 struct drm_property *property, uint64_t val)
1657{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001658 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001659
Clarence Ipae4e60c2016-06-26 22:44:04 -04001660 return sde_plane_atomic_set_property(plane,
1661 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001662}
1663
1664static int sde_plane_atomic_get_property(struct drm_plane *plane,
1665 const struct drm_plane_state *state,
1666 struct drm_property *property, uint64_t *val)
1667{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001668 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001669 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04001670 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001671
Clarence Ipaa0faf42016-05-30 12:07:48 -04001672 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001673 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001674 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001675 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001676 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001677 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001678 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001679 ret = msm_property_atomic_get(&psde->property_info,
1680 pstate->property_values, pstate->property_blobs,
1681 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04001682 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001683
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001684 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001685}
1686
1687static void sde_plane_destroy(struct drm_plane *plane)
1688{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001689 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001690
Clarence Ip13a8cf42016-09-29 17:27:47 -04001691 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001692
Clarence Ip13a8cf42016-09-29 17:27:47 -04001693 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001694 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1695
Clarence Ip4ce59322016-06-26 22:27:51 -04001696 debugfs_remove_recursive(psde->debugfs_root);
Clarence Ipe78efb72016-06-24 18:35:21 -04001697
Dhaval Patel4e574842016-08-23 15:11:37 -07001698 if (psde->blob_info)
1699 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001700 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04001701 mutex_destroy(&psde->lock);
1702
Clarence Ip4ce59322016-06-26 22:27:51 -04001703 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001704
Clarence Ip4ce59322016-06-26 22:27:51 -04001705 /* this will destroy the states as well */
1706 drm_plane_cleanup(plane);
1707
Clarence Ip4c1d9772016-06-26 09:35:38 -04001708 if (psde->pipe_hw)
1709 sde_hw_sspp_destroy(psde->pipe_hw);
1710
Clarence Ip4ce59322016-06-26 22:27:51 -04001711 kfree(psde);
1712 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001713}
1714
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001715static void sde_plane_destroy_state(struct drm_plane *plane,
1716 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001717{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001718 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04001719 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001720
Clarence Ipae4e60c2016-06-26 22:44:04 -04001721 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001722 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1723 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001724 return;
1725 }
1726
Clarence Ipaa0faf42016-05-30 12:07:48 -04001727 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04001728 pstate = to_sde_plane_state(state);
1729
Clarence Ip13a8cf42016-09-29 17:27:47 -04001730 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001731
Clarence Ipe78efb72016-06-24 18:35:21 -04001732 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001733 if (state->fb)
1734 drm_framebuffer_unreference(state->fb);
1735
Clarence Ipae4e60c2016-06-26 22:44:04 -04001736 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001737 if (pstate->input_fence)
1738 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001739
Clarence Ipaa0faf42016-05-30 12:07:48 -04001740 /* destroy value helper */
1741 msm_property_destroy_state(&psde->property_info, pstate,
1742 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001743}
1744
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001745static struct drm_plane_state *
1746sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001747{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001748 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001749 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04001750 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04001751 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001752
Clarence Ip13a8cf42016-09-29 17:27:47 -04001753 if (!plane) {
1754 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001755 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001756 } else if (!plane->state) {
1757 SDE_ERROR("invalid plane state\n");
1758 return NULL;
1759 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001760
Clarence Ip730e7192016-06-26 22:45:09 -04001761 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001762 psde = to_sde_plane(plane);
1763 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001764 if (!pstate) {
1765 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001766 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001767 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001768
Clarence Ip13a8cf42016-09-29 17:27:47 -04001769 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001770
1771 /* duplicate value helper */
1772 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
1773 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001774
Clarence Ip730e7192016-06-26 22:45:09 -04001775 /* add ref count for frame buffer */
1776 if (pstate->base.fb)
1777 drm_framebuffer_reference(pstate->base.fb);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001778
Clarence Ip17e908b2016-09-29 15:58:00 -04001779 /* clear out any input fence */
1780 pstate->input_fence = 0;
1781 input_fence_default = msm_property_get_default(
1782 &psde->property_info, PLANE_PROP_INPUT_FENCE);
1783 msm_property_set_property(&psde->property_info, pstate->property_values,
1784 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001785
Clarence Ip282dad62016-09-27 17:07:35 -04001786 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04001787 pstate->pending = false;
1788
1789 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001790}
1791
1792static void sde_plane_reset(struct drm_plane *plane)
1793{
Clarence Ipae4e60c2016-06-26 22:44:04 -04001794 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001795 struct sde_plane_state *pstate;
1796
Clarence Ipae4e60c2016-06-26 22:44:04 -04001797 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001798 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001799 return;
1800 }
1801
Clarence Ip730e7192016-06-26 22:45:09 -04001802 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001803 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001804
Clarence Ipae4e60c2016-06-26 22:44:04 -04001805 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001806 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04001807 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001808 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04001809 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001810
Clarence Ipaa0faf42016-05-30 12:07:48 -04001811 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001812 if (!pstate) {
1813 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001814 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001815 }
Clarence Ip730e7192016-06-26 22:45:09 -04001816
Clarence Ipaa0faf42016-05-30 12:07:48 -04001817 /* reset value helper */
1818 msm_property_reset_state(&psde->property_info, pstate,
1819 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001820
1821 pstate->base.plane = plane;
1822
1823 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001824}
1825
1826static const struct drm_plane_funcs sde_plane_funcs = {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001827 .update_plane = drm_atomic_helper_update_plane,
1828 .disable_plane = drm_atomic_helper_disable_plane,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001829 .destroy = sde_plane_destroy,
1830 .set_property = sde_plane_set_property,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001831 .atomic_set_property = sde_plane_atomic_set_property,
1832 .atomic_get_property = sde_plane_atomic_get_property,
1833 .reset = sde_plane_reset,
1834 .atomic_duplicate_state = sde_plane_duplicate_state,
1835 .atomic_destroy_state = sde_plane_destroy_state,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001836};
1837
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001838static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
1839 .prepare_fb = sde_plane_prepare_fb,
1840 .cleanup_fb = sde_plane_cleanup_fb,
1841 .atomic_check = sde_plane_atomic_check,
1842 .atomic_update = sde_plane_atomic_update,
1843};
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001844
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001845enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001846{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001847 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001848}
1849
Clarence Ip4ce59322016-06-26 22:27:51 -04001850static void _sde_plane_init_debugfs(struct sde_plane *psde, struct sde_kms *kms)
1851{
1852 const struct sde_sspp_sub_blks *sblk = 0;
1853 const struct sde_sspp_cfg *cfg = 0;
1854
1855 if (psde && psde->pipe_hw)
1856 cfg = psde->pipe_hw->cap;
1857 if (cfg)
1858 sblk = cfg->sblk;
1859
1860 if (kms && sblk) {
1861 /* create overall sub-directory for the pipe */
1862 psde->debugfs_root =
1863 debugfs_create_dir(psde->pipe_name,
1864 sde_debugfs_get_root(kms));
1865 if (psde->debugfs_root) {
1866 /* don't error check these */
Clarence Ip4c1d9772016-06-26 09:35:38 -04001867 debugfs_create_x32("features", 0644,
Clarence Ip4ce59322016-06-26 22:27:51 -04001868 psde->debugfs_root, &psde->features);
1869
1870 /* add register dump support */
1871 sde_debugfs_setup_regset32(&psde->debugfs_src,
1872 sblk->src_blk.base + cfg->base,
1873 sblk->src_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04001874 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04001875 sde_debugfs_create_regset32("src_blk", 0444,
1876 psde->debugfs_root, &psde->debugfs_src);
1877
1878 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
1879 sblk->scaler_blk.base + cfg->base,
1880 sblk->scaler_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04001881 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04001882 sde_debugfs_create_regset32("scaler_blk", 0444,
1883 psde->debugfs_root,
1884 &psde->debugfs_scaler);
1885
1886 sde_debugfs_setup_regset32(&psde->debugfs_csc,
1887 sblk->csc_blk.base + cfg->base,
1888 sblk->csc_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04001889 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04001890 sde_debugfs_create_regset32("csc_blk", 0444,
1891 psde->debugfs_root, &psde->debugfs_csc);
1892 }
1893 }
1894}
1895
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001896/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04001897struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04001898 uint32_t pipe, bool primary_plane,
1899 unsigned long possible_crtcs)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001900{
1901 struct drm_plane *plane = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001902 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001903 struct msm_drm_private *priv;
1904 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001905 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04001906 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04001907
1908 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001909 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001910 goto exit;
1911 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001912
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001913 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04001914 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001915 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04001916 goto exit;
1917 }
1918
1919 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001920 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04001921 goto exit;
1922 }
1923 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001924
Clarence Ip4c1d9772016-06-26 09:35:38 -04001925 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001926 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001927 goto exit;
1928 }
1929
Clarence Ip4ce59322016-06-26 22:27:51 -04001930 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001931 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
1932 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001933 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001934 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04001935 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001936 }
1937
Clarence Ip4c1d9772016-06-26 09:35:38 -04001938 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001939 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001940 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04001941 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001942
Clarence Ip4c1d9772016-06-26 09:35:38 -04001943 /* initialize underlying h/w driver */
1944 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
1945 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001946 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001947 ret = PTR_ERR(psde->pipe_hw);
1948 goto clean_plane;
1949 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001950 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001951 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001952 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04001953
1954 /* cache features mask for later */
1955 psde->features = psde->pipe_hw->cap->features;
1956 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04001957 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001958 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04001959 goto clean_sspp;
1960 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04001961
1962 /* add plane to DRM framework */
Clarence Ipea3d6262016-07-15 16:20:11 -04001963 psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
1964 psde->formats,
1965 0,
1966 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001967
Clarence Ip4c1d9772016-06-26 09:35:38 -04001968 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001969 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04001970 goto clean_sspp;
1971 }
1972
1973 if (psde->features & BIT(SDE_SSPP_CURSOR))
1974 type = DRM_PLANE_TYPE_CURSOR;
1975 else if (primary_plane)
1976 type = DRM_PLANE_TYPE_PRIMARY;
1977 else
1978 type = DRM_PLANE_TYPE_OVERLAY;
Clarence Ip2bbf7b32016-09-23 15:07:16 -04001979 ret = drm_universal_plane_init(dev, plane, possible_crtcs,
1980 &sde_plane_funcs, psde->formats, psde->nformats, type);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001981 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04001982 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001983
Clarence Ip4c1d9772016-06-26 09:35:38 -04001984 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001985 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001986
Clarence Ipaa0faf42016-05-30 12:07:48 -04001987 msm_property_init(&psde->property_info, &plane->base, dev,
1988 priv->plane_property, psde->property_data,
1989 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
1990 sizeof(struct sde_plane_state));
1991
Clarence Ipc47a0692016-10-11 10:54:17 -04001992 _sde_plane_install_properties(plane, kms->catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001993
Clarence Ip4ce59322016-06-26 22:27:51 -04001994 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04001995 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04001996
Clarence Ip730e7192016-06-26 22:45:09 -04001997 mutex_init(&psde->lock);
1998
Clarence Ip4ce59322016-06-26 22:27:51 -04001999 _sde_plane_init_debugfs(psde, kms);
2000
Clarence Ip13a8cf42016-09-29 17:27:47 -04002001 DRM_INFO("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002002 return plane;
2003
Clarence Ip4c1d9772016-06-26 09:35:38 -04002004clean_sspp:
2005 if (psde && psde->pipe_hw)
2006 sde_hw_sspp_destroy(psde->pipe_hw);
2007clean_plane:
2008 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04002009exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002010 return ERR_PTR(ret);
2011}