blob: ee98bb0b6462a39775458292420c385ad7d58492 [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"
Alan Kwong83285fb2016-10-21 20:51:17 -040027#include "sde_plane.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040028
Clarence Ip13a8cf42016-09-29 17:27:47 -040029#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
30 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
31
32#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
33 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
34
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040035#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
36#define PHASE_STEP_SHIFT 21
37#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
38#define PHASE_RESIDUAL 15
39
Clarence Ipe78efb72016-06-24 18:35:21 -040040#define SHARP_STRENGTH_DEFAULT 32
41#define SHARP_EDGE_THR_DEFAULT 112
42#define SHARP_SMOOTH_THR_DEFAULT 8
43#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040044
Clarence Ip5e2a9222016-06-26 22:38:24 -040045#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070046
Clarence Ipcae1bb62016-07-07 12:07:13 -040047#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
48
Clarence Ip282dad62016-09-27 17:07:35 -040049/* dirty bits for update function */
50#define SDE_PLANE_DIRTY_RECTS 0x1
51#define SDE_PLANE_DIRTY_FORMAT 0x2
52#define SDE_PLANE_DIRTY_SHARPEN 0x4
53#define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF
54
Alan Kwong1a00e4d2016-07-18 09:42:30 -040055/**
56 * enum sde_plane_qos - Different qos configurations for each pipe
57 *
58 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
59 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
60 * this configuration is mutually exclusive from VBLANK_CTRL.
61 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
62 */
63enum sde_plane_qos {
64 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
65 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
66 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
67};
68
Clarence Ip5fc00c52016-09-23 15:03:34 -040069/*
70 * struct sde_plane - local sde plane structure
71 * @csc_cfg: Decoded user configuration for csc
72 * @csc_usr_ptr: Points to csc_cfg if valid user config available
73 * @csc_ptr: Points to sde_csc_cfg structure to use for current
74 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070075struct sde_plane {
76 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040077
78 int mmu_id;
79
Clarence Ip730e7192016-06-26 22:45:09 -040080 struct mutex lock;
81
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040082 enum sde_sspp pipe;
83 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070084 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -040085 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040086
87 struct sde_hw_pipe *pipe_hw;
88 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -040089 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -040090 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040091 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -040092 uint32_t color_fill;
93 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040094 bool is_rt_pipe;
Clarence Ip4ce59322016-06-26 22:27:51 -040095
Clarence Ipb43d4592016-09-08 14:21:35 -040096 struct sde_hw_pixel_ext pixel_ext;
97 bool pixel_ext_usr;
98
Clarence Ip373f8592016-05-26 00:58:42 -040099 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400100 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400101 struct sde_csc_cfg *csc_ptr;
102
Clarence Ip4c1d9772016-06-26 09:35:38 -0400103 const struct sde_sspp_sub_blks *pipe_sblk;
104
Clarence Ip5e2a9222016-06-26 22:38:24 -0400105 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400106
Clarence Ipaa0faf42016-05-30 12:07:48 -0400107 struct msm_property_info property_info;
108 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700109 struct drm_property_blob *blob_info;
Clarence Ip730e7192016-06-26 22:45:09 -0400110
Clarence Ip4ce59322016-06-26 22:27:51 -0400111 /* debugfs related stuff */
112 struct dentry *debugfs_root;
113 struct sde_debugfs_regset32 debugfs_src;
114 struct sde_debugfs_regset32 debugfs_scaler;
115 struct sde_debugfs_regset32 debugfs_csc;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700116};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700117
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700118#define to_sde_plane(x) container_of(x, struct sde_plane, base)
119
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400120static bool sde_plane_enabled(struct drm_plane_state *state)
121{
Clarence Ipdbde9832016-06-26 09:48:36 -0400122 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400123}
124
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400125/**
126 * _sde_plane_calc_fill_level - calculate fill level of the given source format
127 * @plane: Pointer to drm plane
128 * @fmt: Pointer to source buffer format
129 * @src_wdith: width of source buffer
130 * Return: fill level corresponding to the source buffer/format or 0 if error
131 */
132static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
133 const struct sde_format *fmt, u32 src_width)
134{
135 struct sde_plane *psde;
136 u32 fixed_buff_size;
137 u32 total_fl;
138
139 if (!plane || !fmt) {
140 SDE_ERROR("invalid arguments\n");
141 return 0;
142 }
143
144 psde = to_sde_plane(plane);
145 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
146
147 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
148 if (fmt->chroma_sample == SDE_CHROMA_420) {
149 /* NV12 */
150 total_fl = (fixed_buff_size / 2) /
151 ((src_width + 32) * fmt->bpp);
152 } else {
153 /* non NV12 */
154 total_fl = (fixed_buff_size) /
155 ((src_width + 32) * fmt->bpp);
156 }
157 } else {
158 total_fl = (fixed_buff_size * 2) /
159 ((src_width + 32) * fmt->bpp);
160 }
161
162 SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n",
163 plane->base.id, psde->pipe - SSPP_VIG0,
164 fmt->base.pixel_format, src_width, total_fl);
165
166 return total_fl;
167}
168
169/**
170 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
171 * @total_fl: fill level
172 * Return: LUT setting corresponding to the fill level
173 */
174static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
175{
176 u32 qos_lut;
177
178 if (total_fl <= 4)
179 qos_lut = 0x1B;
180 else if (total_fl <= 5)
181 qos_lut = 0x5B;
182 else if (total_fl <= 6)
183 qos_lut = 0x15B;
184 else if (total_fl <= 7)
185 qos_lut = 0x55B;
186 else if (total_fl <= 8)
187 qos_lut = 0x155B;
188 else if (total_fl <= 9)
189 qos_lut = 0x555B;
190 else if (total_fl <= 10)
191 qos_lut = 0x1555B;
192 else if (total_fl <= 11)
193 qos_lut = 0x5555B;
194 else if (total_fl <= 12)
195 qos_lut = 0x15555B;
196 else
197 qos_lut = 0x55555B;
198
199 return qos_lut;
200}
201
202/**
203 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
204 * @total_fl: fill level
205 * Return: LUT setting corresponding to the fill level
206 */
207static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
208{
209 u32 qos_lut;
210
211 if (total_fl <= 10)
212 qos_lut = 0x1AAff;
213 else if (total_fl <= 11)
214 qos_lut = 0x5AAFF;
215 else if (total_fl <= 12)
216 qos_lut = 0x15AAFF;
217 else
218 qos_lut = 0x55AAFF;
219
220 return qos_lut;
221}
222
223/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400224 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
225 * @plane: Pointer to drm plane
226 * @fb: Pointer to framebuffer associated with the given plane
227 */
228static void _sde_plane_set_qos_lut(struct drm_plane *plane,
229 struct drm_framebuffer *fb)
230{
231 struct sde_plane *psde;
232 const struct sde_format *fmt = NULL;
233 u32 qos_lut;
234 u32 total_fl = 0;
235
236 if (!plane || !fb) {
237 SDE_ERROR("invalid arguments plane %d fb %d\n",
238 plane != 0, fb != 0);
239 return;
240 }
241
242 psde = to_sde_plane(plane);
243
244 if (!psde->pipe_hw || !psde->pipe_sblk) {
245 SDE_ERROR("invalid arguments\n");
246 return;
247 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
248 return;
249 }
250
251 if (!psde->is_rt_pipe) {
252 qos_lut = psde->pipe_sblk->creq_lut_nrt;
253 } else {
254 fmt = sde_get_sde_format_ext(
255 fb->pixel_format,
256 fb->modifier,
257 drm_format_num_planes(fb->pixel_format));
258 total_fl = _sde_plane_calc_fill_level(plane, fmt,
259 psde->pipe_cfg.src_rect.w);
260
261 if (SDE_FORMAT_IS_LINEAR(fmt))
262 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
263 else
264 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
265 }
266
267 psde->pipe_qos_cfg.creq_lut = qos_lut;
268
269 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
270 (fmt) ? fmt->base.pixel_format : 0,
271 psde->is_rt_pipe, total_fl, qos_lut,
272 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
273
274 SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n",
275 plane->base.id,
276 psde->pipe - SSPP_VIG0,
277 (fmt) ? fmt->base.pixel_format : 0,
278 psde->is_rt_pipe, total_fl, qos_lut);
279
280 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
281}
282
283/**
284 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
285 * @plane: Pointer to drm plane
286 * @fb: Pointer to framebuffer associated with the given plane
287 */
288static void _sde_plane_set_danger_lut(struct drm_plane *plane,
289 struct drm_framebuffer *fb)
290{
291 struct sde_plane *psde;
292 const struct sde_format *fmt = NULL;
293 u32 danger_lut, safe_lut;
294
295 if (!plane || !fb) {
296 SDE_ERROR("invalid arguments\n");
297 return;
298 }
299
300 psde = to_sde_plane(plane);
301
302 if (!psde->pipe_hw || !psde->pipe_sblk) {
303 SDE_ERROR("invalid arguments\n");
304 return;
305 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
306 return;
307 }
308
309 if (!psde->is_rt_pipe) {
310 danger_lut = psde->pipe_sblk->danger_lut_nrt;
311 safe_lut = psde->pipe_sblk->safe_lut_nrt;
312 } else {
313 fmt = sde_get_sde_format_ext(
314 fb->pixel_format,
315 fb->modifier,
316 drm_format_num_planes(fb->pixel_format));
317
318 if (SDE_FORMAT_IS_LINEAR(fmt)) {
319 danger_lut = psde->pipe_sblk->danger_lut_linear;
320 safe_lut = psde->pipe_sblk->safe_lut_linear;
321 } else {
322 danger_lut = psde->pipe_sblk->danger_lut_tile;
323 safe_lut = psde->pipe_sblk->safe_lut_tile;
324 }
325 }
326
327 psde->pipe_qos_cfg.danger_lut = danger_lut;
328 psde->pipe_qos_cfg.safe_lut = safe_lut;
329
330 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
331 (fmt) ? fmt->base.pixel_format : 0,
332 (fmt) ? fmt->fetch_mode : 0,
333 psde->pipe_qos_cfg.danger_lut,
334 psde->pipe_qos_cfg.safe_lut);
335
336 SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n",
337 plane->base.id,
338 psde->pipe - SSPP_VIG0,
339 fmt ? fmt->base.pixel_format : 0,
340 fmt ? fmt->fetch_mode : -1,
341 psde->pipe_qos_cfg.danger_lut,
342 psde->pipe_qos_cfg.safe_lut);
343
344 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
345 &psde->pipe_qos_cfg);
346}
347
348/**
349 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
350 * @plane: Pointer to drm plane
351 * @enable: true to enable QoS control
352 * @flags: QoS control mode (enum sde_plane_qos)
353 */
354static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
355 bool enable, u32 flags)
356{
357 struct sde_plane *psde;
358
359 if (!plane) {
360 SDE_ERROR("invalid arguments\n");
361 return;
362 }
363
364 psde = to_sde_plane(plane);
365
366 if (!psde->pipe_hw || !psde->pipe_sblk) {
367 SDE_ERROR("invalid arguments\n");
368 return;
369 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
370 return;
371 }
372
373 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
374 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
375 psde->pipe_qos_cfg.danger_vblank =
376 psde->pipe_sblk->danger_vblank;
377 psde->pipe_qos_cfg.vblank_en = enable;
378 }
379
380 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
381 /* this feature overrules previous VBLANK_CTRL */
382 psde->pipe_qos_cfg.vblank_en = false;
383 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
384 }
385
386 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
387 psde->pipe_qos_cfg.danger_safe_en = enable;
388
389 if (!psde->is_rt_pipe) {
390 psde->pipe_qos_cfg.vblank_en = false;
391 psde->pipe_qos_cfg.danger_safe_en = false;
392 }
393
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400394 SDE_DEBUG("plane%u: pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400395 plane->base.id,
396 psde->pipe - SSPP_VIG0,
397 psde->pipe_qos_cfg.danger_safe_en,
398 psde->pipe_qos_cfg.vblank_en,
399 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400400 psde->pipe_qos_cfg.danger_vblank,
401 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400402
403 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
404 &psde->pipe_qos_cfg);
405}
406
Alan Kwong5d324e42016-07-28 22:56:18 -0400407/**
408 * _sde_plane_set_ot_limit - set OT limit for the given plane
409 * @plane: Pointer to drm plane
410 * @crtc: Pointer to drm crtc
411 */
412static void _sde_plane_set_ot_limit(struct drm_plane *plane,
413 struct drm_crtc *crtc)
414{
415 struct sde_plane *psde;
416 struct sde_vbif_set_ot_params ot_params;
417 struct msm_drm_private *priv;
418 struct sde_kms *sde_kms;
419
420 if (!plane || !plane->dev || !crtc) {
421 SDE_ERROR("invalid arguments plane %d crtc %d\n",
422 plane != 0, crtc != 0);
423 return;
424 }
425
426 priv = plane->dev->dev_private;
427 if (!priv || !priv->kms) {
428 SDE_ERROR("invalid KMS reference\n");
429 return;
430 }
431
432 sde_kms = to_sde_kms(priv->kms);
433 psde = to_sde_plane(plane);
434 if (!psde->pipe_hw) {
435 SDE_ERROR("invalid pipe reference\n");
436 return;
437 }
438
439 memset(&ot_params, 0, sizeof(ot_params));
440 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
441 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
442 ot_params.width = psde->pipe_cfg.src_rect.w;
443 ot_params.height = psde->pipe_cfg.src_rect.h;
444 ot_params.is_wfd = !psde->is_rt_pipe;
445 ot_params.frame_rate = crtc->mode.vrefresh;
446 ot_params.vbif_idx = VBIF_RT;
447 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
448 ot_params.rd = true;
449
450 sde_vbif_set_ot_limit(sde_kms, &ot_params);
451}
452
Clarence Ipcae1bb62016-07-07 12:07:13 -0400453/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400454static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400455 struct sde_plane_state *pstate, uint64_t fd)
456{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400457 if (!psde || !pstate) {
458 SDE_ERROR("invalid arg(s), plane %d state %d\n",
459 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400460 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400461 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400462
463 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400464 if (pstate->input_fence)
465 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400466
467 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400468 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400469
Clarence Ip13a8cf42016-09-29 17:27:47 -0400470 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400471}
472
Clarence Ipcae1bb62016-07-07 12:07:13 -0400473int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400474{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400475 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400476 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400477 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400478 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400479 int ret = -EINVAL;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400480
481 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700482 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400483 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400484 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400485 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400486 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400487 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400488 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400489
Clarence Ipcae1bb62016-07-07 12:07:13 -0400490 if (input_fence) {
Clarence Ip78a04ed2016-10-04 15:57:45 -0400491 prefix = sde_sync_get_name_prefix(input_fence);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400492 ret = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400493
494 MSM_EVT(plane->dev,
495 plane->base.id,
496 (uint64_t)-ret << (sizeof(uint32_t) * CHAR_BIT)
497 | prefix);
498
Clarence Ipcae1bb62016-07-07 12:07:13 -0400499 switch (ret) {
500 case 0:
Clarence Ip13a8cf42016-09-29 17:27:47 -0400501 SDE_DEBUG_PLANE(psde, "signaled\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400502 break;
503 case -ETIME:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400504 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
505 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400506 psde->is_error = true;
507 break;
508 default:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400509 SDE_ERROR_PLANE(psde, "error %d on %08X\n",
510 ret, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400511 psde->is_error = true;
512 break;
513 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400514 } else {
515 ret = 0;
516 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400517 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400518 return ret;
519}
520
Clarence Ip282dad62016-09-27 17:07:35 -0400521static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400522 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400523 struct sde_hw_pipe_cfg *pipe_cfg,
524 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400525{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400526 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400527 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400528
Clarence Ip13a8cf42016-09-29 17:27:47 -0400529 if (!plane || !pstate || !pipe_cfg || !fb) {
530 SDE_ERROR(
531 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
532 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400533 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400534 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400535
536 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400537 if (!psde->pipe_hw) {
538 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400539 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400540 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400541
Clarence Ipb6eb2362016-09-08 16:18:13 -0400542 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
543 if (ret == -EAGAIN)
544 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
545 else if (ret)
546 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
547 else if (psde->pipe_hw->ops.setup_sourceaddress)
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400548 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400549}
550
abeykun48f407a2016-08-25 12:06:44 -0400551static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
552 struct sde_plane_state *pstate)
553{
554 struct sde_hw_scaler3_cfg *cfg = psde->scaler3_cfg;
555 int ret = 0;
556
557 cfg->dir_lut = msm_property_get_blob(
558 &psde->property_info,
559 pstate->property_blobs, &cfg->dir_len,
560 PLANE_PROP_SCALER_LUT_ED);
561 cfg->cir_lut = msm_property_get_blob(
562 &psde->property_info,
563 pstate->property_blobs, &cfg->cir_len,
564 PLANE_PROP_SCALER_LUT_CIR);
565 cfg->sep_lut = msm_property_get_blob(
566 &psde->property_info,
567 pstate->property_blobs, &cfg->sep_len,
568 PLANE_PROP_SCALER_LUT_SEP);
569 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
570 ret = -ENODATA;
571 return ret;
572}
573
Clarence Ipcb410d42016-06-26 22:52:33 -0400574static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400575 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
576 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400577 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400578 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
579{
580}
581
Clarence Ipcb410d42016-06-26 22:52:33 -0400582/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400583 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400584 * @psde: Pointer to SDE plane object
585 * @src: Source size
586 * @dst: Destination size
587 * @phase_steps: Pointer to output array for phase steps
588 * @filter: Pointer to output array for filter type
589 * @fmt: Pointer to format definition
590 * @chroma_subsampling: Subsampling amount for chroma channel
591 *
592 * Returns: 0 on success
593 */
594static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400595 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400596 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400597 uint32_t chroma_subsampling)
598{
Clarence Ipcb410d42016-06-26 22:52:33 -0400599 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400600 SDE_ERROR(
601 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
602 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400603 return -EINVAL;
604 }
605
Clarence Ip4c1d9772016-06-26 09:35:38 -0400606 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400607 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400608 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400609 phase_steps[SDE_SSPP_COMP_1_2] =
610 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
611 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
612 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400613
614 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400615 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400616 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400617 (src <= dst) ? SDE_SCALE_FILTER_BIL :
618 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400619
Clarence Ipdbde9832016-06-26 09:48:36 -0400620 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400621 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400622 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
623 } else {
624 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
625 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400626 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400627 }
628 } else {
629 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400630 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
631 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
632 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400633 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400634 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400635}
636
Clarence Ipcb410d42016-06-26 22:52:33 -0400637/**
638 * _sde_plane_setup_pixel_ext - determine default pixel extension values
639 * @psde: Pointer to SDE plane object
640 * @src: Source size
641 * @dst: Destination size
642 * @decimated_src: Source size after decimation, if any
643 * @phase_steps: Pointer to output array for phase steps
644 * @out_src: Output array for pixel extension values
645 * @out_edge1: Output array for pixel extension first edge
646 * @out_edge2: Output array for pixel extension second edge
647 * @filter: Pointer to array for filter type
648 * @fmt: Pointer to format definition
649 * @chroma_subsampling: Subsampling amount for chroma channel
650 * @post_compare: Whether to chroma subsampled source size for comparisions
651 */
652static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400653 uint32_t src, uint32_t dst, uint32_t decimated_src,
654 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400655 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400656 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400657 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400658{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400659 int64_t edge1, edge2, caf;
660 uint32_t src_work;
661 int i, tmp;
662
Clarence Ipcb410d42016-06-26 22:52:33 -0400663 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400664 out_edge2 && filter && fmt) {
665 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400666 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400667 caf = PHASE_STEP_UNIT_SCALE;
668 else
669 caf = 0;
670
671 for (i = 0; i < SDE_MAX_PLANES; i++) {
672 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400673 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400674 src_work /= chroma_subsampling;
675 if (post_compare)
676 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400677 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400678 /* unity */
679 edge1 = 0;
680 edge2 = 0;
681 } else if (dst >= src) {
682 /* upscale */
683 edge1 = (1 << PHASE_RESIDUAL);
684 edge1 -= caf;
685 edge2 = (1 << PHASE_RESIDUAL);
686 edge2 += (dst - 1) * *(phase_steps + i);
687 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
688 edge2 += caf;
689 edge2 = -(edge2);
690 } else {
691 /* downscale */
692 edge1 = 0;
693 edge2 = (dst - 1) * *(phase_steps + i);
694 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
695 edge2 += *(phase_steps + i);
696 edge2 = -(edge2);
697 }
698
699 /* only enable CAF for luma plane */
700 caf = 0;
701
702 /* populate output arrays */
703 *(out_src + i) = src_work;
704
705 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400706 if (edge1 >= 0) {
707 tmp = (uint32_t)edge1;
708 tmp >>= PHASE_STEP_SHIFT;
709 *(out_edge1 + i) = -tmp;
710 } else {
711 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400712 *(out_edge1 + i) =
713 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
714 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400715 }
716 if (edge2 >= 0) {
717 tmp = (uint32_t)edge2;
718 tmp >>= PHASE_STEP_SHIFT;
719 *(out_edge2 + i) = -tmp;
720 } else {
721 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400722 *(out_edge2 + i) =
723 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
724 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400725 }
726 }
727 }
728}
729
Clarence Ip5fc00c52016-09-23 15:03:34 -0400730static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400731{
732 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
733 {
Clarence Ip373f8592016-05-26 00:58:42 -0400734 /* S15.16 format */
735 0x00012A00, 0x00000000, 0x00019880,
736 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
737 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400738 },
Clarence Ip373f8592016-05-26 00:58:42 -0400739 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400740 { 0xfff0, 0xff80, 0xff80,},
741 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400742 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400743 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400744 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400745 };
abeykun1c312f62016-08-26 09:47:12 -0400746 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
747 {
748 /* S15.16 format */
749 0x00012A00, 0x00000000, 0x00019880,
750 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
751 0x00012A00, 0x00020480, 0x00000000,
752 },
753 /* signed bias */
754 { 0xffc0, 0xfe00, 0xfe00,},
755 { 0x0, 0x0, 0x0,},
756 /* unsigned clamp */
757 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
758 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
759 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400760
Clarence Ip5fc00c52016-09-23 15:03:34 -0400761 if (!psde) {
762 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400763 return;
764 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400765
Clarence Ipcae1bb62016-07-07 12:07:13 -0400766 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400767 if (psde->csc_usr_ptr)
768 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400769 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
770 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400771 else
Clarence Ip373f8592016-05-26 00:58:42 -0400772 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400773
Clarence Ip13a8cf42016-09-29 17:27:47 -0400774 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400775 psde->csc_ptr->csc_mv[0],
776 psde->csc_ptr->csc_mv[1],
777 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400778}
779
Clarence Ipcb410d42016-06-26 22:52:33 -0400780static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400781 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -0400782 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700783{
Clarence Ipb43d4592016-09-08 14:21:35 -0400784 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -0400785 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Clarence Ipb43d4592016-09-08 14:21:35 -0400786 uint32_t tmp, i;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400787
Clarence Ipb43d4592016-09-08 14:21:35 -0400788 if (!psde || !fmt) {
789 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
790 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400791 return;
Clarence Ipb43d4592016-09-08 14:21:35 -0400792 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400793
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400794 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400795
Clarence Ipdedbba92016-09-27 17:43:10 -0400796 psde->pipe_cfg.horz_decimation =
797 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
798 psde->pipe_cfg.vert_decimation =
799 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400800
801 /* don't chroma subsample if decimating */
802 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400803 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400804 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400805 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400806
Clarence Ip5e2a9222016-06-26 22:38:24 -0400807 /* update scaler */
808 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -0400809 int error;
810
811 error = _sde_plane_setup_scaler3_lut(psde, pstate);
812 if (error || !psde->pixel_ext_usr) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400813 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -0400814 _sde_plane_setup_scaler3(psde,
815 psde->pipe_cfg.src_rect.w,
816 psde->pipe_cfg.src_rect.h,
817 psde->pipe_cfg.dst_rect.w,
818 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -0400819 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400820 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400821 }
Clarence Ipb43d4592016-09-08 14:21:35 -0400822 } else if (!psde->pixel_ext_usr) {
823 /* calculate default configuration for QSEED2 */
824 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400825
Clarence Ip13a8cf42016-09-29 17:27:47 -0400826 SDE_DEBUG_PLANE(psde, "default config\n");
Clarence Ipb43d4592016-09-08 14:21:35 -0400827 _sde_plane_setup_scaler2(psde,
828 psde->pipe_cfg.src_rect.w,
829 psde->pipe_cfg.dst_rect.w,
830 pe->phase_step_x,
831 pe->horz_filter, fmt, chroma_subsmpl_h);
832 _sde_plane_setup_scaler2(psde,
833 psde->pipe_cfg.src_rect.h,
834 psde->pipe_cfg.dst_rect.h,
835 pe->phase_step_y,
836 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400837
Clarence Ip5e2a9222016-06-26 22:38:24 -0400838 /* calculate left/right/top/bottom pixel extensions */
Clarence Ipcb410d42016-06-26 22:52:33 -0400839 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400840 psde->pipe_cfg.horz_decimation);
Clarence Ipdbde9832016-06-26 09:48:36 -0400841 if (SDE_FORMAT_IS_YUV(fmt))
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400842 tmp &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -0400843 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
844 psde->pipe_cfg.dst_rect.w, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400845 pe->phase_step_x,
846 pe->roi_w,
847 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -0400848 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400849 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400850
Clarence Ipcb410d42016-06-26 22:52:33 -0400851 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400852 psde->pipe_cfg.vert_decimation);
Clarence Ipcb410d42016-06-26 22:52:33 -0400853 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
854 psde->pipe_cfg.dst_rect.h, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400855 pe->phase_step_y,
856 pe->roi_h,
857 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -0400858 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400859 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400860
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400861 for (i = 0; i < SDE_MAX_PLANES; i++) {
862 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400863 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400864 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400865 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400866
867 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400868 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400869 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400870 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400871
872 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400873 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400874 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400875 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400876
877 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400878 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400879 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400880 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400881 }
882 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400883}
884
Clarence Ipcae1bb62016-07-07 12:07:13 -0400885/**
886 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -0400887 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -0400888 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
889 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
890 * Returns: 0 on success
891 */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400892static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -0400893 uint32_t color, uint32_t alpha)
894{
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400895 const struct sde_format *fmt;
Clarence Ipcb410d42016-06-26 22:52:33 -0400896
Clarence Ip13a8cf42016-09-29 17:27:47 -0400897 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700898 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400899 return -EINVAL;
900 }
901
Clarence Ipcb410d42016-06-26 22:52:33 -0400902 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400903 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400904 return -EINVAL;
905 }
906
Clarence Ip13a8cf42016-09-29 17:27:47 -0400907 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400908
Clarence Ipcb410d42016-06-26 22:52:33 -0400909 /*
910 * select fill format to match user property expectation,
911 * h/w only supports RGB variants
912 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400913 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -0400914
915 /* update sspp */
916 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
917 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
918 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
919
920 /* override scaler/decimation if solid fill */
921 psde->pipe_cfg.src_rect.x = 0;
922 psde->pipe_cfg.src_rect.y = 0;
923 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
924 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
925
926 _sde_plane_setup_scaler(psde, fmt, 0);
927
928 if (psde->pipe_hw->ops.setup_format)
929 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
930 fmt, SDE_SSPP_SOLID_FILL);
931
932 if (psde->pipe_hw->ops.setup_rects)
933 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -0400934 &psde->pipe_cfg, &psde->pixel_ext,
935 psde->scaler3_cfg);
Clarence Ipcb410d42016-06-26 22:52:33 -0400936 }
937
938 return 0;
939}
940
941static int _sde_plane_mode_set(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -0700942 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -0400943{
Clarence Ipc47a0692016-10-11 10:54:17 -0400944 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -0400945 struct sde_plane *psde;
946 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400947 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -0700948 struct drm_crtc *crtc;
949 struct drm_framebuffer *fb;
950 struct sde_rect src, dst;
951 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -0400952 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -0400953
Clarence Ip13a8cf42016-09-29 17:27:47 -0400954 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -0400955 SDE_ERROR("invalid plane\n");
956 return -EINVAL;
957 } else if (!plane->state) {
958 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400959 return -EINVAL;
960 }
961
962 psde = to_sde_plane(plane);
963 pstate = to_sde_plane_state(plane->state);
Clarence Ipcb410d42016-06-26 22:52:33 -0400964
Dhaval Patel47302cf2016-08-18 15:04:28 -0700965 crtc = state->crtc;
966 fb = state->fb;
967 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400968 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
969 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -0700970 return -EINVAL;
971 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400972 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400973 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -0400974
Clarence Ip282dad62016-09-27 17:07:35 -0400975 /* determine what needs to be refreshed */
976 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
977 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400978 case PLANE_PROP_SCALER_V1:
abeykun48f407a2016-08-25 12:06:44 -0400979 case PLANE_PROP_SCALER_V2:
Clarence Ipdedbba92016-09-27 17:43:10 -0400980 case PLANE_PROP_H_DECIMATE:
981 case PLANE_PROP_V_DECIMATE:
982 case PLANE_PROP_SRC_CONFIG:
983 case PLANE_PROP_ZPOS:
Clarence Ip282dad62016-09-27 17:07:35 -0400984 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
985 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400986 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -0400987 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
988 break;
989 case PLANE_PROP_COLOR_FILL:
990 /* potentially need to refresh everything */
991 pstate->dirty = SDE_PLANE_DIRTY_ALL;
992 break;
993 case PLANE_PROP_ROTATION:
994 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
995 break;
Clarence Ip282dad62016-09-27 17:07:35 -0400996 case PLANE_PROP_INFO:
997 case PLANE_PROP_ALPHA:
998 case PLANE_PROP_INPUT_FENCE:
999 case PLANE_PROP_BLEND_OP:
1000 /* no special action required */
1001 break;
1002 default:
1003 /* unknown property, refresh everything */
1004 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
1005 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
1006 break;
1007 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001008 }
1009
Clarence Ip282dad62016-09-27 17:07:35 -04001010 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
1011 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -04001012
1013 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
1014
Clarence Ip282dad62016-09-27 17:07:35 -04001015 /* early out if nothing dirty */
1016 if (!pstate->dirty)
1017 return 0;
1018 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001019
Clarence Ip0d0e96d2016-10-24 18:13:13 -04001020 psde->is_rt_pipe = sde_crtc_is_rt(crtc);
Clarence Ip282dad62016-09-27 17:07:35 -04001021 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1022
1023 /* update roi config */
1024 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
1025 POPULATE_RECT(&src, state->src_x, state->src_y,
1026 state->src_w, state->src_h, q16_data);
1027 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
1028 state->crtc_w, state->crtc_h, !q16_data);
1029
Clarence Ip13a8cf42016-09-29 17:27:47 -04001030 SDE_DEBUG_PLANE(psde,
1031 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001032 fb->base.id, src.x, src.y, src.w, src.h,
1033 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
1034 drm_get_format_name(fmt->base.pixel_format),
1035 SDE_FORMAT_IS_UBWC(fmt));
1036
1037 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
1038 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001039 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001040 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
1041 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
1042 src.h /= 2;
1043 src.y = DIV_ROUND_UP(src.y, 2);
1044 src.y &= ~0x1;
1045 }
1046
1047 psde->pipe_cfg.src_rect = src;
1048 psde->pipe_cfg.dst_rect = dst;
1049
1050 /* check for color fill */
1051 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
1052 PLANE_PROP_COLOR_FILL);
1053 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
1054 /* skip remaining processing on color fill */
1055 pstate->dirty = 0x0;
1056 } else if (psde->pipe_hw->ops.setup_rects) {
1057 _sde_plane_setup_scaler(psde, fmt, pstate);
1058
Clarence Ip282dad62016-09-27 17:07:35 -04001059 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -04001060 &psde->pipe_cfg, &psde->pixel_ext,
1061 psde->scaler3_cfg);
Clarence Ip282dad62016-09-27 17:07:35 -04001062 }
Dhaval Patel48c76022016-09-01 17:51:23 -07001063 }
1064
Clarence Ip282dad62016-09-27 17:07:35 -04001065 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
1066 psde->pipe_hw->ops.setup_format) {
1067 src_flags = 0x0;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001068 SDE_DEBUG_PLANE(psde, "rotation 0x%llX\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001069 sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
1070 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1071 BIT(DRM_REFLECT_X))
1072 src_flags |= SDE_SSPP_FLIP_LR;
1073 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1074 BIT(DRM_REFLECT_Y))
1075 src_flags |= SDE_SSPP_FLIP_UD;
1076
1077 /* update format */
1078 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags);
1079
1080 /* update csc */
1081 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04001082 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04001083 else
1084 psde->csc_ptr = 0;
1085 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001086
Clarence Ipe78efb72016-06-24 18:35:21 -04001087 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04001088 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
1089 psde->pipe_hw->ops.setup_sharpening) {
1090 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
1091 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
1092 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
1093 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04001094
Clarence Ipe78efb72016-06-24 18:35:21 -04001095 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04001096 &psde->sharp_cfg);
1097 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001098
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001099 _sde_plane_set_qos_lut(plane, fb);
1100 _sde_plane_set_danger_lut(plane, fb);
1101
Alan Kwong5d324e42016-07-28 22:56:18 -04001102 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001103 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04001104 _sde_plane_set_ot_limit(plane, crtc);
1105 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001106
Clarence Ip282dad62016-09-27 17:07:35 -04001107 /* clear dirty */
1108 pstate->dirty = 0x0;
1109
Clarence Ip5e2a9222016-06-26 22:38:24 -04001110 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001111}
1112
1113static int sde_plane_prepare_fb(struct drm_plane *plane,
1114 const struct drm_plane_state *new_state)
1115{
1116 struct drm_framebuffer *fb = new_state->fb;
1117 struct sde_plane *psde = to_sde_plane(plane);
1118
1119 if (!new_state->fb)
1120 return 0;
1121
Clarence Ip13a8cf42016-09-29 17:27:47 -04001122 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001123 return msm_framebuffer_prepare(fb, psde->mmu_id);
1124}
1125
1126static void sde_plane_cleanup_fb(struct drm_plane *plane,
1127 const struct drm_plane_state *old_state)
1128{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001129 struct drm_framebuffer *fb = old_state ? old_state->fb : NULL;
1130 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001131
1132 if (!fb)
1133 return;
1134
Clarence Ip13a8cf42016-09-29 17:27:47 -04001135 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001136 msm_framebuffer_cleanup(fb, psde->mmu_id);
1137}
1138
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001139static void _sde_plane_atomic_check_mode_changed(struct sde_plane *psde,
1140 struct drm_plane_state *state,
1141 struct drm_plane_state *old_state)
1142{
1143 struct sde_plane_state *pstate = to_sde_plane_state(state);
1144
Dhaval Patel47302cf2016-08-18 15:04:28 -07001145 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04001146 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001147 return;
1148
Clarence Ip282dad62016-09-27 17:07:35 -04001149 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
1150 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001151 SDE_DEBUG_PLANE(psde,
1152 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001153 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001154 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001155 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001156 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001157 } else if (state->src_w != old_state->src_w ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07001158 state->src_h != old_state->src_h ||
1159 state->src_x != old_state->src_x ||
1160 state->src_y != old_state->src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001161 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001162 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001163 } else if (state->crtc_w != old_state->crtc_w ||
1164 state->crtc_h != old_state->crtc_h ||
1165 state->crtc_x != old_state->crtc_x ||
1166 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001167 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001168 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1169 }
1170
1171 if (!state->fb || !old_state->fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001172 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001173 } else if (state->fb->pixel_format != old_state->fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001174 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001175 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001176 } else {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001177 uint64_t *new_mods = state->fb->modifier;
1178 uint64_t *old_mods = old_state->fb->modifier;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001179 uint32_t *new_pitches = state->fb->pitches;
1180 uint32_t *old_pitches = old_state->fb->pitches;
1181 uint32_t *new_offset = state->fb->offsets;
1182 uint32_t *old_offset = old_state->fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001183 int i;
1184
1185 for (i = 0; i < ARRAY_SIZE(state->fb->modifier); i++) {
1186 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001187 SDE_DEBUG_PLANE(psde,
1188 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001189 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001190 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001191 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1192 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001193 break;
1194 }
1195 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001196 for (i = 0; i < ARRAY_SIZE(state->fb->pitches); i++) {
1197 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001198 SDE_DEBUG_PLANE(psde,
1199 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001200 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001201 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001202 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001203 break;
1204 }
1205 }
Dhaval Patel47302cf2016-08-18 15:04:28 -07001206 for (i = 0; i < ARRAY_SIZE(state->fb->offsets); i++) {
1207 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001208 SDE_DEBUG_PLANE(psde,
1209 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001210 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001211 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001212 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1213 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001214 break;
1215 }
1216 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001217 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001218}
1219
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001220static int sde_plane_atomic_check(struct drm_plane *plane,
1221 struct drm_plane_state *state)
1222{
Clarence Ipdedbba92016-09-27 17:43:10 -04001223 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04001224 struct sde_plane *psde;
1225 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001226 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001227 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04001228 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001229 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
1230 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04001231
1232 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001233 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1234 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04001235 ret = -EINVAL;
1236 goto exit;
1237 }
1238
1239 psde = to_sde_plane(plane);
1240 pstate = to_sde_plane_state(state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001241
1242 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001243 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001244 ret = -EINVAL;
1245 goto exit;
1246 }
1247
Clarence Ipdedbba92016-09-27 17:43:10 -04001248 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1249 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04001250
1251 /* src values are in Q16 fixed point, convert to integer */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001252 POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w,
1253 state->src_h, q16_data);
1254 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
1255 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04001256
Dhaval Patel47302cf2016-08-18 15:04:28 -07001257 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
1258 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04001259
Dhaval Patel47302cf2016-08-18 15:04:28 -07001260 max_upscale = psde->pipe_sblk->maxupscale;
1261 max_downscale = psde->pipe_sblk->maxdwnscale;
1262 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04001263
Clarence Ip13a8cf42016-09-29 17:27:47 -04001264 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001265 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001266
Dhaval Patel47302cf2016-08-18 15:04:28 -07001267 if (!sde_plane_enabled(state))
1268 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04001269
Dhaval Patel47302cf2016-08-18 15:04:28 -07001270 fmt = to_sde_format(msm_framebuffer_format(state->fb));
1271
1272 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
1273
1274 if (SDE_FORMAT_IS_YUV(fmt) &&
1275 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04001276 !(psde->features & (BIT(SDE_SSPP_CSC)
1277 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001278 SDE_ERROR_PLANE(psde,
1279 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07001280 ret = -EINVAL;
1281
1282 /* check src bounds */
1283 } else if (state->fb->width > MAX_IMG_WIDTH ||
1284 state->fb->height > MAX_IMG_HEIGHT ||
1285 src.w < min_src_size || src.h < min_src_size ||
1286 CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) ||
1287 CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001288 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001289 src.x, src.y, src.w, src.h);
1290 ret = -E2BIG;
1291
1292 /* valid yuv image */
1293 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
1294 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001295 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001296 src.x, src.y, src.w, src.h);
1297 ret = -EINVAL;
1298
1299 /* min dst support */
1300 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001301 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001302 dst.x, dst.y, dst.w, dst.h);
1303 ret = -EINVAL;
1304
1305 /* decimation validation */
1306 } else if (deci_w || deci_h) {
1307 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
1308 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001309 SDE_ERROR_PLANE(psde,
1310 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001311 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001312 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001313 SDE_ERROR_PLANE(psde,
1314 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001315 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001316 }
1317
Dhaval Patel47302cf2016-08-18 15:04:28 -07001318 } else if (!(psde->features & SDE_SSPP_SCALER) &&
1319 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001320 SDE_ERROR_PLANE(psde,
1321 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001322 src.w, src.h, dst.w, dst.h);
1323 ret = -EINVAL;
1324
1325 /* check decimated source width */
1326 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001327 SDE_ERROR_PLANE(psde,
1328 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001329 src.w, src_deci_w, max_linewidth);
1330 ret = -E2BIG;
1331
1332 /* check max scaler capability */
1333 } else if (((src_deci_w * max_upscale) < dst.w) ||
1334 ((src_deci_h * max_upscale) < dst.h) ||
1335 ((dst.w * max_downscale) < src_deci_w) ||
1336 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001337 SDE_ERROR_PLANE(psde,
1338 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001339 src_deci_w, src_deci_h, dst.w, dst.h);
1340 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001341 }
1342
Dhaval Patel47302cf2016-08-18 15:04:28 -07001343modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001344 if (!ret)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001345 _sde_plane_atomic_check_mode_changed(psde, state, plane->state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001346exit:
1347 return ret;
1348}
1349
Clarence Ipcae1bb62016-07-07 12:07:13 -04001350/**
1351 * sde_plane_flush - final plane operations before commit flush
1352 * @plane: Pointer to drm plane structure
1353 */
1354void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04001355{
Clarence Ipcae1bb62016-07-07 12:07:13 -04001356 struct sde_plane *psde;
1357
Clarence Ip13a8cf42016-09-29 17:27:47 -04001358 if (!plane) {
1359 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001360 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001361 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04001362
1363 psde = to_sde_plane(plane);
1364
1365 /*
1366 * These updates have to be done immediately before the plane flush
1367 * timing, and may not be moved to the atomic_update/mode_set functions.
1368 */
1369 if (psde->is_error)
1370 /* force white frame with 0% alpha pipe output on error */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001371 _sde_plane_color_fill(psde, 0xFFFFFF, 0x0);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001372 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
1373 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001374 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001375 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
1376 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
1377
1378 /* flag h/w flush complete */
1379 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04001380 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001381}
1382
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001383static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04001384 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001385{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001386 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001387 struct drm_plane_state *state;
1388 struct sde_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001389
Clarence Ip13a8cf42016-09-29 17:27:47 -04001390 if (!plane) {
1391 SDE_ERROR("invalid plane\n");
1392 return;
1393 } else if (!plane->state) {
1394 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04001395 return;
1396 }
1397
Clarence Ip13a8cf42016-09-29 17:27:47 -04001398 psde = to_sde_plane(plane);
1399 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001400 state = plane->state;
1401 pstate = to_sde_plane_state(state);
1402
Clarence Ip13a8cf42016-09-29 17:27:47 -04001403 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001404
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001405 if (!sde_plane_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04001406 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001407 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001408 int ret;
1409
Dhaval Patel47302cf2016-08-18 15:04:28 -07001410 ret = _sde_plane_mode_set(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001411 /* atomic_check should have ensured that this doesn't fail */
1412 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001413 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001414}
1415
Dhaval Patel47302cf2016-08-18 15:04:28 -07001416
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001417/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001418static void _sde_plane_install_properties(struct drm_plane *plane,
Clarence Ipc47a0692016-10-11 10:54:17 -04001419 struct sde_mdss_cfg *catalog)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001420{
Clarence Ip5e2a9222016-06-26 22:38:24 -04001421 static const struct drm_prop_enum_list e_blend_op[] = {
1422 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
1423 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
1424 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
1425 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
1426 };
1427 static const struct drm_prop_enum_list e_src_config[] = {
1428 {SDE_DRM_DEINTERLACE, "deinterlace"}
1429 };
Clarence Ipea3d6262016-07-15 16:20:11 -04001430 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07001431 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001432 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04001433 int zpos_max = 255;
1434 int zpos_def = 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001435
Clarence Ip13a8cf42016-09-29 17:27:47 -04001436 if (!plane || !psde) {
1437 SDE_ERROR("invalid plane\n");
1438 return;
1439 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
1440 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
1441 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001442 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04001443 } else if (!catalog) {
1444 SDE_ERROR("invalid catalog\n");
1445 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001446 }
1447
Clarence Ipc47a0692016-10-11 10:54:17 -04001448 if (sde_is_custom_client()) {
1449 if (catalog->mixer_count && catalog->mixer)
1450 zpos_max = catalog->mixer[0].sblk->maxblendstages;
1451 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
1452 /* reserve zpos == 0 for primary planes */
1453 zpos_def = drm_plane_index(plane) + 1;
1454 }
1455
1456 msm_property_install_range(&psde->property_info, "zpos",
1457 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001458
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001459 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001460 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001461
Dhaval Patel47302cf2016-08-18 15:04:28 -07001462 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001463 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07001464 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001465
Clarence Ipdedbba92016-09-27 17:43:10 -04001466 if (psde->pipe_sblk->maxhdeciexp) {
1467 msm_property_install_range(&psde->property_info, "h_decimate",
1468 0x0, 0, psde->pipe_sblk->maxhdeciexp, 0,
1469 PLANE_PROP_H_DECIMATE);
1470 }
1471
1472 if (psde->pipe_sblk->maxvdeciexp) {
1473 msm_property_install_range(&psde->property_info, "v_decimate",
1474 0x0, 0, psde->pipe_sblk->maxvdeciexp, 0,
1475 PLANE_PROP_V_DECIMATE);
1476 }
1477
abeykun48f407a2016-08-25 12:06:44 -04001478 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
1479 msm_property_install_volatile_range(&psde->property_info,
1480 "scaler_v2", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
1481 msm_property_install_blob(&psde->property_info, "lut_ed", 0,
1482 PLANE_PROP_SCALER_LUT_ED);
1483 msm_property_install_blob(&psde->property_info, "lut_cir", 0,
1484 PLANE_PROP_SCALER_LUT_CIR);
1485 msm_property_install_blob(&psde->property_info, "lut_sep", 0,
1486 PLANE_PROP_SCALER_LUT_SEP);
1487 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001488 msm_property_install_volatile_range(&psde->property_info,
1489 "scaler_v1", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V1);
1490 }
1491
Clarence Ip5fc00c52016-09-23 15:03:34 -04001492 if (psde->features & BIT(SDE_SSPP_CSC)) {
1493 msm_property_install_volatile_range(&psde->property_info,
1494 "csc_v1", 0x0, 0, ~0, 0, PLANE_PROP_CSC_V1);
1495 }
1496
Clarence Ip5e2a9222016-06-26 22:38:24 -04001497 /* standard properties */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001498 msm_property_install_rotation(&psde->property_info,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001499 BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y), PLANE_PROP_ROTATION);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001500
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001501 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001502 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001503
Dhaval Patel47302cf2016-08-18 15:04:28 -07001504 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
1505 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
1506
1507 if (psde->pipe_hw->ops.setup_solidfill)
1508 msm_property_install_range(&psde->property_info, "color_fill",
1509 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
1510
Dhaval Patel4e574842016-08-23 15:11:37 -07001511 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001512 if (!info) {
1513 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07001514 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001515 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001516
1517 msm_property_install_blob(&psde->property_info, "capabilities",
1518 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
1519 sde_kms_info_reset(info);
1520
Clarence Ipea3d6262016-07-15 16:20:11 -04001521 format_list = psde->pipe_sblk->format_list;
1522 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04001523 sde_kms_info_start(info, "pixel_formats");
1524 while (format_list->fourcc_format) {
1525 sde_kms_info_append_format(info,
1526 format_list->fourcc_format,
1527 format_list->modifier);
1528 ++format_list;
1529 }
1530 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04001531 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001532
1533 sde_kms_info_add_keyint(info, "max_linewidth",
1534 psde->pipe_sblk->maxlinewidth);
1535 sde_kms_info_add_keyint(info, "max_upscale",
1536 psde->pipe_sblk->maxupscale);
1537 sde_kms_info_add_keyint(info, "max_downscale",
1538 psde->pipe_sblk->maxdwnscale);
1539 sde_kms_info_add_keyint(info, "max_horizontal_deci",
1540 psde->pipe_sblk->maxhdeciexp);
1541 sde_kms_info_add_keyint(info, "max_vertical_deci",
1542 psde->pipe_sblk->maxvdeciexp);
1543 msm_property_set_blob(&psde->property_info, &psde->blob_info,
1544 info->data, info->len, PLANE_PROP_INFO);
1545
1546 kfree(info);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001547}
1548
Clarence Ip5fc00c52016-09-23 15:03:34 -04001549static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
1550{
1551 struct sde_drm_csc_v1 csc_v1;
1552 int i;
1553
1554 if (!psde) {
1555 SDE_ERROR("invalid plane\n");
1556 return;
1557 }
1558
1559 psde->csc_usr_ptr = NULL;
1560 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001561 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001562 return;
1563 }
1564
1565 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001566 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001567 return;
1568 }
1569
Clarence Ipb43d4592016-09-08 14:21:35 -04001570 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001571 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
1572 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
1573 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
1574 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
1575 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
1576 }
1577 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
1578 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
1579 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
1580 }
1581 psde->csc_usr_ptr = &psde->csc_cfg;
1582}
1583
Clarence Ipb43d4592016-09-08 14:21:35 -04001584static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
1585{
1586 struct sde_drm_scaler_v1 scale_v1;
1587 struct sde_hw_pixel_ext *pe;
1588 int i;
1589
1590 if (!psde) {
1591 SDE_ERROR("invalid plane\n");
1592 return;
1593 }
1594
1595 psde->pixel_ext_usr = false;
1596 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001597 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001598 return;
1599 }
1600
1601 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001602 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001603 return;
1604 }
1605
1606 /* populate from user space */
1607 pe = &(psde->pixel_ext);
1608 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1609 for (i = 0; i < SDE_MAX_PLANES; i++) {
1610 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
1611 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
1612 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
1613 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
1614
1615 pe->horz_filter[i] = scale_v1.horz_filter[i];
1616 pe->vert_filter[i] = scale_v1.vert_filter[i];
1617 }
1618 for (i = 0; i < SDE_MAX_PLANES; i++) {
1619 pe->num_ext_pxls_left[i] = scale_v1.lr.num_pxls_start[i];
1620 pe->num_ext_pxls_right[i] = scale_v1.lr.num_pxls_end[i];
1621 pe->left_ftch[i] = scale_v1.lr.ftch_start[i];
1622 pe->right_ftch[i] = scale_v1.lr.ftch_end[i];
1623 pe->left_rpt[i] = scale_v1.lr.rpt_start[i];
1624 pe->right_rpt[i] = scale_v1.lr.rpt_end[i];
1625 pe->roi_w[i] = scale_v1.lr.roi[i];
1626
1627 pe->num_ext_pxls_top[i] = scale_v1.tb.num_pxls_start[i];
1628 pe->num_ext_pxls_btm[i] = scale_v1.tb.num_pxls_end[i];
1629 pe->top_ftch[i] = scale_v1.tb.ftch_start[i];
1630 pe->btm_ftch[i] = scale_v1.tb.ftch_end[i];
1631 pe->top_rpt[i] = scale_v1.tb.rpt_start[i];
1632 pe->btm_rpt[i] = scale_v1.tb.rpt_end[i];
1633 pe->roi_h[i] = scale_v1.tb.roi[i];
1634 }
1635 psde->pixel_ext_usr = true;
1636
Clarence Ip13a8cf42016-09-29 17:27:47 -04001637 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001638}
1639
abeykun48f407a2016-08-25 12:06:44 -04001640static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
1641 struct sde_plane_state *pstate, void *usr)
1642{
1643 struct sde_drm_scaler_v2 scale_v2;
1644 struct sde_hw_pixel_ext *pe;
1645 int i;
1646 struct sde_hw_scaler3_cfg *cfg;
1647
1648 if (!psde) {
1649 SDE_ERROR("invalid plane\n");
1650 return;
1651 }
1652
1653 cfg = psde->scaler3_cfg;
1654 psde->pixel_ext_usr = false;
1655 if (!usr) {
1656 SDE_DEBUG_PLANE(psde, "scale data removed\n");
1657 return;
1658 }
1659
1660 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
1661 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
1662 return;
1663 }
1664
1665 /* populate from user space */
1666 pe = &(psde->pixel_ext);
1667 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1668 cfg->enable = scale_v2.enable;
1669 cfg->dir_en = scale_v2.dir_en;
1670 for (i = 0; i < SDE_MAX_PLANES; i++) {
1671 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
1672 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
1673 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
1674 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
1675
1676 cfg->preload_x[i] = scale_v2.preload_x[i];
1677 cfg->preload_y[i] = scale_v2.preload_y[i];
1678 cfg->src_width[i] = scale_v2.src_width[i];
1679 cfg->src_height[i] = scale_v2.src_height[i];
1680 }
1681 cfg->dst_width = scale_v2.dst_width;
1682 cfg->dst_height = scale_v2.dst_height;
1683
1684 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
1685 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
1686 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
1687 cfg->blend_cfg = scale_v2.blend_cfg;
1688
1689 cfg->lut_flag = scale_v2.lut_flag;
1690 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
1691 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
1692 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
1693 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
1694 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
1695
1696 cfg->de.enable = scale_v2.de.enable;
1697 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
1698 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
1699 cfg->de.clip = scale_v2.de.clip;
1700 cfg->de.limit = scale_v2.de.limit;
1701 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
1702 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
1703 cfg->de.thr_low = scale_v2.de.thr_low;
1704 cfg->de.thr_high = scale_v2.de.thr_high;
1705 cfg->de.prec_shift = scale_v2.de.prec_shift;
1706 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
1707 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
1708 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
1709 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
1710 }
1711 for (i = 0; i < SDE_MAX_PLANES; i++) {
1712 pe->num_ext_pxls_left[i] = scale_v2.lr.num_pxls_start[i];
1713 pe->num_ext_pxls_right[i] = scale_v2.lr.num_pxls_end[i];
1714 pe->left_ftch[i] = scale_v2.lr.ftch_start[i];
1715 pe->right_ftch[i] = scale_v2.lr.ftch_end[i];
1716 pe->left_rpt[i] = scale_v2.lr.rpt_start[i];
1717 pe->right_rpt[i] = scale_v2.lr.rpt_end[i];
1718 pe->roi_w[i] = scale_v2.lr.roi[i];
1719
1720 pe->num_ext_pxls_top[i] = scale_v2.tb.num_pxls_start[i];
1721 pe->num_ext_pxls_btm[i] = scale_v2.tb.num_pxls_end[i];
1722 pe->top_ftch[i] = scale_v2.tb.ftch_start[i];
1723 pe->btm_ftch[i] = scale_v2.tb.ftch_end[i];
1724 pe->top_rpt[i] = scale_v2.tb.rpt_start[i];
1725 pe->btm_rpt[i] = scale_v2.tb.rpt_end[i];
1726 pe->roi_h[i] = scale_v2.tb.roi[i];
1727 }
1728 psde->pixel_ext_usr = true;
1729
1730 SDE_DEBUG_PLANE(psde, "user property data copied\n");
1731}
1732
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001733static int sde_plane_atomic_set_property(struct drm_plane *plane,
1734 struct drm_plane_state *state, struct drm_property *property,
1735 uint64_t val)
1736{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001737 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001738 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001739 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001740
Clarence Ip13a8cf42016-09-29 17:27:47 -04001741 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001742
1743 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001744 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001745 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001746 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001747 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04001748 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001749 ret = msm_property_atomic_set(&psde->property_info,
1750 pstate->property_values, pstate->property_blobs,
1751 property, val);
1752 if (!ret) {
1753 idx = msm_property_index(&psde->property_info,
1754 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001755 switch (idx) {
1756 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04001757 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001758 break;
1759 case PLANE_PROP_CSC_V1:
1760 _sde_plane_set_csc_v1(psde, (void *)val);
1761 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04001762 case PLANE_PROP_SCALER_V1:
1763 _sde_plane_set_scaler_v1(psde, (void *)val);
1764 break;
abeykun48f407a2016-08-25 12:06:44 -04001765 case PLANE_PROP_SCALER_V2:
1766 _sde_plane_set_scaler_v2(psde, pstate,
1767 (void *)val);
1768 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001769 default:
1770 /* nothing to do */
1771 break;
1772 }
Clarence Ipe78efb72016-06-24 18:35:21 -04001773 }
1774 }
1775
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001776 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001777}
1778
1779static int sde_plane_set_property(struct drm_plane *plane,
1780 struct drm_property *property, uint64_t val)
1781{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001782 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001783
Clarence Ipae4e60c2016-06-26 22:44:04 -04001784 return sde_plane_atomic_set_property(plane,
1785 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001786}
1787
1788static int sde_plane_atomic_get_property(struct drm_plane *plane,
1789 const struct drm_plane_state *state,
1790 struct drm_property *property, uint64_t *val)
1791{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001792 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001793 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04001794 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001795
Clarence Ipaa0faf42016-05-30 12:07:48 -04001796 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001797 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001798 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001799 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001800 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001801 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001802 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001803 ret = msm_property_atomic_get(&psde->property_info,
1804 pstate->property_values, pstate->property_blobs,
1805 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04001806 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001807
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001808 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001809}
1810
1811static void sde_plane_destroy(struct drm_plane *plane)
1812{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001813 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001814
Clarence Ip13a8cf42016-09-29 17:27:47 -04001815 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001816
Clarence Ip13a8cf42016-09-29 17:27:47 -04001817 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001818 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1819
Clarence Ip4ce59322016-06-26 22:27:51 -04001820 debugfs_remove_recursive(psde->debugfs_root);
Clarence Ipe78efb72016-06-24 18:35:21 -04001821
Dhaval Patel4e574842016-08-23 15:11:37 -07001822 if (psde->blob_info)
1823 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001824 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04001825 mutex_destroy(&psde->lock);
1826
Clarence Ip4ce59322016-06-26 22:27:51 -04001827 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001828
Clarence Ip4ce59322016-06-26 22:27:51 -04001829 /* this will destroy the states as well */
1830 drm_plane_cleanup(plane);
1831
Clarence Ip4c1d9772016-06-26 09:35:38 -04001832 if (psde->pipe_hw)
1833 sde_hw_sspp_destroy(psde->pipe_hw);
1834
Clarence Ip4ce59322016-06-26 22:27:51 -04001835 kfree(psde);
1836 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001837}
1838
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001839static void sde_plane_destroy_state(struct drm_plane *plane,
1840 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001841{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001842 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04001843 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001844
Clarence Ipae4e60c2016-06-26 22:44:04 -04001845 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001846 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1847 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001848 return;
1849 }
1850
Clarence Ipaa0faf42016-05-30 12:07:48 -04001851 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04001852 pstate = to_sde_plane_state(state);
1853
Clarence Ip13a8cf42016-09-29 17:27:47 -04001854 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001855
Clarence Ipe78efb72016-06-24 18:35:21 -04001856 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001857 if (state->fb)
1858 drm_framebuffer_unreference(state->fb);
1859
Clarence Ipae4e60c2016-06-26 22:44:04 -04001860 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001861 if (pstate->input_fence)
1862 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001863
Clarence Ipaa0faf42016-05-30 12:07:48 -04001864 /* destroy value helper */
1865 msm_property_destroy_state(&psde->property_info, pstate,
1866 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001867}
1868
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001869static struct drm_plane_state *
1870sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001871{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001872 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001873 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04001874 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04001875 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001876
Clarence Ip13a8cf42016-09-29 17:27:47 -04001877 if (!plane) {
1878 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001879 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001880 } else if (!plane->state) {
1881 SDE_ERROR("invalid plane state\n");
1882 return NULL;
1883 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001884
Clarence Ip730e7192016-06-26 22:45:09 -04001885 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001886 psde = to_sde_plane(plane);
1887 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001888 if (!pstate) {
1889 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001890 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001891 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001892
Clarence Ip13a8cf42016-09-29 17:27:47 -04001893 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001894
1895 /* duplicate value helper */
1896 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
1897 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001898
Clarence Ip730e7192016-06-26 22:45:09 -04001899 /* add ref count for frame buffer */
1900 if (pstate->base.fb)
1901 drm_framebuffer_reference(pstate->base.fb);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001902
Clarence Ip17e908b2016-09-29 15:58:00 -04001903 /* clear out any input fence */
1904 pstate->input_fence = 0;
1905 input_fence_default = msm_property_get_default(
1906 &psde->property_info, PLANE_PROP_INPUT_FENCE);
1907 msm_property_set_property(&psde->property_info, pstate->property_values,
1908 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001909
Clarence Ip282dad62016-09-27 17:07:35 -04001910 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04001911 pstate->pending = false;
1912
1913 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001914}
1915
1916static void sde_plane_reset(struct drm_plane *plane)
1917{
Clarence Ipae4e60c2016-06-26 22:44:04 -04001918 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001919 struct sde_plane_state *pstate;
1920
Clarence Ipae4e60c2016-06-26 22:44:04 -04001921 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001922 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001923 return;
1924 }
1925
Clarence Ip730e7192016-06-26 22:45:09 -04001926 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001927 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001928
Clarence Ipae4e60c2016-06-26 22:44:04 -04001929 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001930 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04001931 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001932 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04001933 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001934
Clarence Ipaa0faf42016-05-30 12:07:48 -04001935 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001936 if (!pstate) {
1937 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001938 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001939 }
Clarence Ip730e7192016-06-26 22:45:09 -04001940
Clarence Ipaa0faf42016-05-30 12:07:48 -04001941 /* reset value helper */
1942 msm_property_reset_state(&psde->property_info, pstate,
1943 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001944
1945 pstate->base.plane = plane;
1946
1947 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001948}
1949
1950static const struct drm_plane_funcs sde_plane_funcs = {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001951 .update_plane = drm_atomic_helper_update_plane,
1952 .disable_plane = drm_atomic_helper_disable_plane,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001953 .destroy = sde_plane_destroy,
1954 .set_property = sde_plane_set_property,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001955 .atomic_set_property = sde_plane_atomic_set_property,
1956 .atomic_get_property = sde_plane_atomic_get_property,
1957 .reset = sde_plane_reset,
1958 .atomic_duplicate_state = sde_plane_duplicate_state,
1959 .atomic_destroy_state = sde_plane_destroy_state,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001960};
1961
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001962static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
1963 .prepare_fb = sde_plane_prepare_fb,
1964 .cleanup_fb = sde_plane_cleanup_fb,
1965 .atomic_check = sde_plane_atomic_check,
1966 .atomic_update = sde_plane_atomic_update,
1967};
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001968
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001969enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001970{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001971 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001972}
1973
Clarence Ip4ce59322016-06-26 22:27:51 -04001974static void _sde_plane_init_debugfs(struct sde_plane *psde, struct sde_kms *kms)
1975{
1976 const struct sde_sspp_sub_blks *sblk = 0;
1977 const struct sde_sspp_cfg *cfg = 0;
1978
1979 if (psde && psde->pipe_hw)
1980 cfg = psde->pipe_hw->cap;
1981 if (cfg)
1982 sblk = cfg->sblk;
1983
1984 if (kms && sblk) {
1985 /* create overall sub-directory for the pipe */
1986 psde->debugfs_root =
1987 debugfs_create_dir(psde->pipe_name,
1988 sde_debugfs_get_root(kms));
1989 if (psde->debugfs_root) {
1990 /* don't error check these */
Clarence Ip4c1d9772016-06-26 09:35:38 -04001991 debugfs_create_x32("features", 0644,
Clarence Ip4ce59322016-06-26 22:27:51 -04001992 psde->debugfs_root, &psde->features);
1993
1994 /* add register dump support */
1995 sde_debugfs_setup_regset32(&psde->debugfs_src,
1996 sblk->src_blk.base + cfg->base,
1997 sblk->src_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04001998 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04001999 sde_debugfs_create_regset32("src_blk", 0444,
2000 psde->debugfs_root, &psde->debugfs_src);
2001
2002 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
2003 sblk->scaler_blk.base + cfg->base,
2004 sblk->scaler_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002005 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002006 sde_debugfs_create_regset32("scaler_blk", 0444,
2007 psde->debugfs_root,
2008 &psde->debugfs_scaler);
2009
2010 sde_debugfs_setup_regset32(&psde->debugfs_csc,
2011 sblk->csc_blk.base + cfg->base,
2012 sblk->csc_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002013 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002014 sde_debugfs_create_regset32("csc_blk", 0444,
2015 psde->debugfs_root, &psde->debugfs_csc);
2016 }
2017 }
2018}
2019
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002020/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04002021struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002022 uint32_t pipe, bool primary_plane,
2023 unsigned long possible_crtcs)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002024{
2025 struct drm_plane *plane = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002026 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002027 struct msm_drm_private *priv;
2028 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002029 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04002030 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002031
2032 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002033 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002034 goto exit;
2035 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002036
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002037 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04002038 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002039 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002040 goto exit;
2041 }
2042
2043 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002044 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002045 goto exit;
2046 }
2047 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002048
Clarence Ip4c1d9772016-06-26 09:35:38 -04002049 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002050 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002051 goto exit;
2052 }
2053
Clarence Ip4ce59322016-06-26 22:27:51 -04002054 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002055 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
2056 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002057 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002058 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002059 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002060 }
2061
Clarence Ip4c1d9772016-06-26 09:35:38 -04002062 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002063 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002064 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04002065 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002066
Clarence Ip4c1d9772016-06-26 09:35:38 -04002067 /* initialize underlying h/w driver */
2068 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
2069 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002070 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002071 ret = PTR_ERR(psde->pipe_hw);
2072 goto clean_plane;
2073 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002074 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002075 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002076 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002077
2078 /* cache features mask for later */
2079 psde->features = psde->pipe_hw->cap->features;
2080 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04002081 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002082 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04002083 goto clean_sspp;
2084 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002085
abeykun48f407a2016-08-25 12:06:44 -04002086 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
2087 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
2088 GFP_KERNEL);
2089 if (!psde->scaler3_cfg) {
2090 SDE_ERROR("[%u]failed to allocate scale struct\n",
2091 pipe);
2092 ret = -ENOMEM;
2093 goto clean_sspp;
2094 }
2095 }
2096
Clarence Ip4c1d9772016-06-26 09:35:38 -04002097 /* add plane to DRM framework */
Clarence Ipea3d6262016-07-15 16:20:11 -04002098 psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
2099 psde->formats,
2100 0,
2101 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002102
Clarence Ip4c1d9772016-06-26 09:35:38 -04002103 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002104 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002105 goto clean_sspp;
2106 }
2107
2108 if (psde->features & BIT(SDE_SSPP_CURSOR))
2109 type = DRM_PLANE_TYPE_CURSOR;
2110 else if (primary_plane)
2111 type = DRM_PLANE_TYPE_PRIMARY;
2112 else
2113 type = DRM_PLANE_TYPE_OVERLAY;
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002114 ret = drm_universal_plane_init(dev, plane, possible_crtcs,
2115 &sde_plane_funcs, psde->formats, psde->nformats, type);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002116 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04002117 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002118
Clarence Ip4c1d9772016-06-26 09:35:38 -04002119 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002120 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002121
Clarence Ipaa0faf42016-05-30 12:07:48 -04002122 msm_property_init(&psde->property_info, &plane->base, dev,
2123 priv->plane_property, psde->property_data,
2124 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
2125 sizeof(struct sde_plane_state));
2126
Clarence Ipc47a0692016-10-11 10:54:17 -04002127 _sde_plane_install_properties(plane, kms->catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002128
Clarence Ip4ce59322016-06-26 22:27:51 -04002129 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04002130 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04002131
Clarence Ip730e7192016-06-26 22:45:09 -04002132 mutex_init(&psde->lock);
2133
Clarence Ip4ce59322016-06-26 22:27:51 -04002134 _sde_plane_init_debugfs(psde, kms);
2135
Clarence Ip13a8cf42016-09-29 17:27:47 -04002136 DRM_INFO("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002137 return plane;
2138
Clarence Ip4c1d9772016-06-26 09:35:38 -04002139clean_sspp:
2140 if (psde && psde->pipe_hw)
2141 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04002142
2143 if (psde && psde->scaler3_cfg)
2144 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002145clean_plane:
2146 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04002147exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002148 return ERR_PTR(ret);
2149}