blob: 3927515b4879d613d56ab752e840cf1a65d1e049 [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
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400494 SDE_EVT32(DRMID(plane), -ret, prefix);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400495
Clarence Ipcae1bb62016-07-07 12:07:13 -0400496 switch (ret) {
497 case 0:
Clarence Ip13a8cf42016-09-29 17:27:47 -0400498 SDE_DEBUG_PLANE(psde, "signaled\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400499 break;
500 case -ETIME:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400501 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
502 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400503 psde->is_error = true;
504 break;
505 default:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400506 SDE_ERROR_PLANE(psde, "error %d on %08X\n",
507 ret, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400508 psde->is_error = true;
509 break;
510 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400511 } else {
512 ret = 0;
513 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400514 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400515 return ret;
516}
517
Clarence Ip282dad62016-09-27 17:07:35 -0400518static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400519 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400520 struct sde_hw_pipe_cfg *pipe_cfg,
521 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400522{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400523 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400524 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400525
Clarence Ip13a8cf42016-09-29 17:27:47 -0400526 if (!plane || !pstate || !pipe_cfg || !fb) {
527 SDE_ERROR(
528 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
529 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400530 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400531 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400532
533 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400534 if (!psde->pipe_hw) {
535 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400536 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400537 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400538
Clarence Ipb6eb2362016-09-08 16:18:13 -0400539 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
540 if (ret == -EAGAIN)
541 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
542 else if (ret)
543 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
544 else if (psde->pipe_hw->ops.setup_sourceaddress)
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400545 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400546}
547
abeykun48f407a2016-08-25 12:06:44 -0400548static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
549 struct sde_plane_state *pstate)
550{
551 struct sde_hw_scaler3_cfg *cfg = psde->scaler3_cfg;
552 int ret = 0;
553
554 cfg->dir_lut = msm_property_get_blob(
555 &psde->property_info,
556 pstate->property_blobs, &cfg->dir_len,
557 PLANE_PROP_SCALER_LUT_ED);
558 cfg->cir_lut = msm_property_get_blob(
559 &psde->property_info,
560 pstate->property_blobs, &cfg->cir_len,
561 PLANE_PROP_SCALER_LUT_CIR);
562 cfg->sep_lut = msm_property_get_blob(
563 &psde->property_info,
564 pstate->property_blobs, &cfg->sep_len,
565 PLANE_PROP_SCALER_LUT_SEP);
566 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
567 ret = -ENODATA;
568 return ret;
569}
570
Clarence Ipcb410d42016-06-26 22:52:33 -0400571static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400572 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
573 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400574 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400575 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
576{
577}
578
Clarence Ipcb410d42016-06-26 22:52:33 -0400579/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400580 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400581 * @psde: Pointer to SDE plane object
582 * @src: Source size
583 * @dst: Destination size
584 * @phase_steps: Pointer to output array for phase steps
585 * @filter: Pointer to output array for filter type
586 * @fmt: Pointer to format definition
587 * @chroma_subsampling: Subsampling amount for chroma channel
588 *
589 * Returns: 0 on success
590 */
591static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400592 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400593 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400594 uint32_t chroma_subsampling)
595{
Clarence Ipcb410d42016-06-26 22:52:33 -0400596 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400597 SDE_ERROR(
598 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
599 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400600 return -EINVAL;
601 }
602
Clarence Ip4c1d9772016-06-26 09:35:38 -0400603 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400604 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400605 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400606 phase_steps[SDE_SSPP_COMP_1_2] =
607 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
608 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
609 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400610
611 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400612 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400613 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400614 (src <= dst) ? SDE_SCALE_FILTER_BIL :
615 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400616
Clarence Ipdbde9832016-06-26 09:48:36 -0400617 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400618 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400619 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
620 } else {
621 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
622 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400623 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400624 }
625 } else {
626 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400627 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
628 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
629 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400630 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400631 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400632}
633
Clarence Ipcb410d42016-06-26 22:52:33 -0400634/**
635 * _sde_plane_setup_pixel_ext - determine default pixel extension values
636 * @psde: Pointer to SDE plane object
637 * @src: Source size
638 * @dst: Destination size
639 * @decimated_src: Source size after decimation, if any
640 * @phase_steps: Pointer to output array for phase steps
641 * @out_src: Output array for pixel extension values
642 * @out_edge1: Output array for pixel extension first edge
643 * @out_edge2: Output array for pixel extension second edge
644 * @filter: Pointer to array for filter type
645 * @fmt: Pointer to format definition
646 * @chroma_subsampling: Subsampling amount for chroma channel
647 * @post_compare: Whether to chroma subsampled source size for comparisions
648 */
649static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400650 uint32_t src, uint32_t dst, uint32_t decimated_src,
651 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400652 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400653 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400654 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400655{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400656 int64_t edge1, edge2, caf;
657 uint32_t src_work;
658 int i, tmp;
659
Clarence Ipcb410d42016-06-26 22:52:33 -0400660 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400661 out_edge2 && filter && fmt) {
662 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400663 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400664 caf = PHASE_STEP_UNIT_SCALE;
665 else
666 caf = 0;
667
668 for (i = 0; i < SDE_MAX_PLANES; i++) {
669 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400670 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400671 src_work /= chroma_subsampling;
672 if (post_compare)
673 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400674 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400675 /* unity */
676 edge1 = 0;
677 edge2 = 0;
678 } else if (dst >= src) {
679 /* upscale */
680 edge1 = (1 << PHASE_RESIDUAL);
681 edge1 -= caf;
682 edge2 = (1 << PHASE_RESIDUAL);
683 edge2 += (dst - 1) * *(phase_steps + i);
684 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
685 edge2 += caf;
686 edge2 = -(edge2);
687 } else {
688 /* downscale */
689 edge1 = 0;
690 edge2 = (dst - 1) * *(phase_steps + i);
691 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
692 edge2 += *(phase_steps + i);
693 edge2 = -(edge2);
694 }
695
696 /* only enable CAF for luma plane */
697 caf = 0;
698
699 /* populate output arrays */
700 *(out_src + i) = src_work;
701
702 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400703 if (edge1 >= 0) {
704 tmp = (uint32_t)edge1;
705 tmp >>= PHASE_STEP_SHIFT;
706 *(out_edge1 + i) = -tmp;
707 } else {
708 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400709 *(out_edge1 + i) =
710 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
711 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400712 }
713 if (edge2 >= 0) {
714 tmp = (uint32_t)edge2;
715 tmp >>= PHASE_STEP_SHIFT;
716 *(out_edge2 + i) = -tmp;
717 } else {
718 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400719 *(out_edge2 + i) =
720 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
721 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400722 }
723 }
724 }
725}
726
Clarence Ip5fc00c52016-09-23 15:03:34 -0400727static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400728{
729 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
730 {
Clarence Ip373f8592016-05-26 00:58:42 -0400731 /* S15.16 format */
732 0x00012A00, 0x00000000, 0x00019880,
733 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
734 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400735 },
Clarence Ip373f8592016-05-26 00:58:42 -0400736 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400737 { 0xfff0, 0xff80, 0xff80,},
738 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400739 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400740 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400741 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400742 };
abeykun1c312f62016-08-26 09:47:12 -0400743 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
744 {
745 /* S15.16 format */
746 0x00012A00, 0x00000000, 0x00019880,
747 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
748 0x00012A00, 0x00020480, 0x00000000,
749 },
750 /* signed bias */
751 { 0xffc0, 0xfe00, 0xfe00,},
752 { 0x0, 0x0, 0x0,},
753 /* unsigned clamp */
754 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
755 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
756 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400757
Clarence Ip5fc00c52016-09-23 15:03:34 -0400758 if (!psde) {
759 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400760 return;
761 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400762
Clarence Ipcae1bb62016-07-07 12:07:13 -0400763 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400764 if (psde->csc_usr_ptr)
765 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400766 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
767 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400768 else
Clarence Ip373f8592016-05-26 00:58:42 -0400769 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400770
Clarence Ip13a8cf42016-09-29 17:27:47 -0400771 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400772 psde->csc_ptr->csc_mv[0],
773 psde->csc_ptr->csc_mv[1],
774 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400775}
776
Clarence Ipcb410d42016-06-26 22:52:33 -0400777static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400778 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -0400779 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700780{
Clarence Ipb43d4592016-09-08 14:21:35 -0400781 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -0400782 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Clarence Ipb43d4592016-09-08 14:21:35 -0400783 uint32_t tmp, i;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400784
Clarence Ipb43d4592016-09-08 14:21:35 -0400785 if (!psde || !fmt) {
786 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
787 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400788 return;
Clarence Ipb43d4592016-09-08 14:21:35 -0400789 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400790
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400791 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400792
Clarence Ipdedbba92016-09-27 17:43:10 -0400793 psde->pipe_cfg.horz_decimation =
794 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
795 psde->pipe_cfg.vert_decimation =
796 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400797
798 /* don't chroma subsample if decimating */
799 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400800 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400801 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400802 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400803
Clarence Ip5e2a9222016-06-26 22:38:24 -0400804 /* update scaler */
805 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -0400806 int error;
807
808 error = _sde_plane_setup_scaler3_lut(psde, pstate);
809 if (error || !psde->pixel_ext_usr) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400810 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -0400811 _sde_plane_setup_scaler3(psde,
812 psde->pipe_cfg.src_rect.w,
813 psde->pipe_cfg.src_rect.h,
814 psde->pipe_cfg.dst_rect.w,
815 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -0400816 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400817 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400818 }
Clarence Ipb43d4592016-09-08 14:21:35 -0400819 } else if (!psde->pixel_ext_usr) {
820 /* calculate default configuration for QSEED2 */
821 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400822
Clarence Ip13a8cf42016-09-29 17:27:47 -0400823 SDE_DEBUG_PLANE(psde, "default config\n");
Clarence Ipb43d4592016-09-08 14:21:35 -0400824 _sde_plane_setup_scaler2(psde,
825 psde->pipe_cfg.src_rect.w,
826 psde->pipe_cfg.dst_rect.w,
827 pe->phase_step_x,
828 pe->horz_filter, fmt, chroma_subsmpl_h);
829 _sde_plane_setup_scaler2(psde,
830 psde->pipe_cfg.src_rect.h,
831 psde->pipe_cfg.dst_rect.h,
832 pe->phase_step_y,
833 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400834
Clarence Ip5e2a9222016-06-26 22:38:24 -0400835 /* calculate left/right/top/bottom pixel extensions */
Clarence Ipcb410d42016-06-26 22:52:33 -0400836 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400837 psde->pipe_cfg.horz_decimation);
Clarence Ipdbde9832016-06-26 09:48:36 -0400838 if (SDE_FORMAT_IS_YUV(fmt))
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400839 tmp &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -0400840 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
841 psde->pipe_cfg.dst_rect.w, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400842 pe->phase_step_x,
843 pe->roi_w,
844 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -0400845 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400846 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400847
Clarence Ipcb410d42016-06-26 22:52:33 -0400848 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400849 psde->pipe_cfg.vert_decimation);
Clarence Ipcb410d42016-06-26 22:52:33 -0400850 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
851 psde->pipe_cfg.dst_rect.h, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400852 pe->phase_step_y,
853 pe->roi_h,
854 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -0400855 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400856 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400857
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400858 for (i = 0; i < SDE_MAX_PLANES; i++) {
859 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400860 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400861 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400862 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400863
864 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400865 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400866 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400867 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400868
869 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400870 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400871 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400872 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400873
874 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400875 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400876 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400877 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400878 }
879 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400880}
881
Clarence Ipcae1bb62016-07-07 12:07:13 -0400882/**
883 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -0400884 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -0400885 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
886 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
887 * Returns: 0 on success
888 */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400889static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -0400890 uint32_t color, uint32_t alpha)
891{
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400892 const struct sde_format *fmt;
Clarence Ipcb410d42016-06-26 22:52:33 -0400893
Clarence Ip13a8cf42016-09-29 17:27:47 -0400894 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700895 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400896 return -EINVAL;
897 }
898
Clarence Ipcb410d42016-06-26 22:52:33 -0400899 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400900 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400901 return -EINVAL;
902 }
903
Clarence Ip13a8cf42016-09-29 17:27:47 -0400904 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400905
Clarence Ipcb410d42016-06-26 22:52:33 -0400906 /*
907 * select fill format to match user property expectation,
908 * h/w only supports RGB variants
909 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400910 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -0400911
912 /* update sspp */
913 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
914 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
915 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
916
917 /* override scaler/decimation if solid fill */
918 psde->pipe_cfg.src_rect.x = 0;
919 psde->pipe_cfg.src_rect.y = 0;
920 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
921 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
922
923 _sde_plane_setup_scaler(psde, fmt, 0);
924
925 if (psde->pipe_hw->ops.setup_format)
926 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
927 fmt, SDE_SSPP_SOLID_FILL);
928
929 if (psde->pipe_hw->ops.setup_rects)
930 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -0400931 &psde->pipe_cfg, &psde->pixel_ext,
932 psde->scaler3_cfg);
Clarence Ipcb410d42016-06-26 22:52:33 -0400933 }
934
935 return 0;
936}
937
938static int _sde_plane_mode_set(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -0700939 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -0400940{
Clarence Ipc47a0692016-10-11 10:54:17 -0400941 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -0400942 struct sde_plane *psde;
943 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400944 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -0700945 struct drm_crtc *crtc;
946 struct drm_framebuffer *fb;
947 struct sde_rect src, dst;
948 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -0400949 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -0400950
Clarence Ip13a8cf42016-09-29 17:27:47 -0400951 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -0400952 SDE_ERROR("invalid plane\n");
953 return -EINVAL;
954 } else if (!plane->state) {
955 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400956 return -EINVAL;
957 }
958
959 psde = to_sde_plane(plane);
960 pstate = to_sde_plane_state(plane->state);
Clarence Ipcb410d42016-06-26 22:52:33 -0400961
Dhaval Patel47302cf2016-08-18 15:04:28 -0700962 crtc = state->crtc;
963 fb = state->fb;
964 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400965 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
966 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -0700967 return -EINVAL;
968 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400969 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400970 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -0400971
Clarence Ip282dad62016-09-27 17:07:35 -0400972 /* determine what needs to be refreshed */
973 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
974 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400975 case PLANE_PROP_SCALER_V1:
abeykun48f407a2016-08-25 12:06:44 -0400976 case PLANE_PROP_SCALER_V2:
Clarence Ipdedbba92016-09-27 17:43:10 -0400977 case PLANE_PROP_H_DECIMATE:
978 case PLANE_PROP_V_DECIMATE:
979 case PLANE_PROP_SRC_CONFIG:
980 case PLANE_PROP_ZPOS:
Clarence Ip282dad62016-09-27 17:07:35 -0400981 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
982 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400983 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -0400984 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
985 break;
986 case PLANE_PROP_COLOR_FILL:
987 /* potentially need to refresh everything */
988 pstate->dirty = SDE_PLANE_DIRTY_ALL;
989 break;
990 case PLANE_PROP_ROTATION:
991 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
992 break;
Clarence Ip282dad62016-09-27 17:07:35 -0400993 case PLANE_PROP_INFO:
994 case PLANE_PROP_ALPHA:
995 case PLANE_PROP_INPUT_FENCE:
996 case PLANE_PROP_BLEND_OP:
997 /* no special action required */
998 break;
999 default:
1000 /* unknown property, refresh everything */
1001 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
1002 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
1003 break;
1004 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001005 }
1006
Clarence Ip282dad62016-09-27 17:07:35 -04001007 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
1008 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -04001009
1010 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
1011
Clarence Ip282dad62016-09-27 17:07:35 -04001012 /* early out if nothing dirty */
1013 if (!pstate->dirty)
1014 return 0;
1015 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001016
Clarence Ip0d0e96d2016-10-24 18:13:13 -04001017 psde->is_rt_pipe = sde_crtc_is_rt(crtc);
Clarence Ip282dad62016-09-27 17:07:35 -04001018 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1019
1020 /* update roi config */
1021 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
1022 POPULATE_RECT(&src, state->src_x, state->src_y,
1023 state->src_w, state->src_h, q16_data);
1024 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
1025 state->crtc_w, state->crtc_h, !q16_data);
1026
Clarence Ip13a8cf42016-09-29 17:27:47 -04001027 SDE_DEBUG_PLANE(psde,
1028 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001029 fb->base.id, src.x, src.y, src.w, src.h,
1030 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
1031 drm_get_format_name(fmt->base.pixel_format),
1032 SDE_FORMAT_IS_UBWC(fmt));
1033
1034 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
1035 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001036 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001037 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
1038 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
1039 src.h /= 2;
1040 src.y = DIV_ROUND_UP(src.y, 2);
1041 src.y &= ~0x1;
1042 }
1043
1044 psde->pipe_cfg.src_rect = src;
1045 psde->pipe_cfg.dst_rect = dst;
1046
1047 /* check for color fill */
1048 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
1049 PLANE_PROP_COLOR_FILL);
1050 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
1051 /* skip remaining processing on color fill */
1052 pstate->dirty = 0x0;
1053 } else if (psde->pipe_hw->ops.setup_rects) {
1054 _sde_plane_setup_scaler(psde, fmt, pstate);
1055
Clarence Ip282dad62016-09-27 17:07:35 -04001056 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -04001057 &psde->pipe_cfg, &psde->pixel_ext,
1058 psde->scaler3_cfg);
Clarence Ip282dad62016-09-27 17:07:35 -04001059 }
Dhaval Patel48c76022016-09-01 17:51:23 -07001060 }
1061
Clarence Ip282dad62016-09-27 17:07:35 -04001062 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
1063 psde->pipe_hw->ops.setup_format) {
1064 src_flags = 0x0;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001065 SDE_DEBUG_PLANE(psde, "rotation 0x%llX\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001066 sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
1067 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1068 BIT(DRM_REFLECT_X))
1069 src_flags |= SDE_SSPP_FLIP_LR;
1070 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1071 BIT(DRM_REFLECT_Y))
1072 src_flags |= SDE_SSPP_FLIP_UD;
1073
1074 /* update format */
1075 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags);
1076
1077 /* update csc */
1078 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04001079 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04001080 else
1081 psde->csc_ptr = 0;
1082 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001083
Clarence Ipe78efb72016-06-24 18:35:21 -04001084 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04001085 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
1086 psde->pipe_hw->ops.setup_sharpening) {
1087 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
1088 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
1089 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
1090 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04001091
Clarence Ipe78efb72016-06-24 18:35:21 -04001092 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04001093 &psde->sharp_cfg);
1094 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001095
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001096 _sde_plane_set_qos_lut(plane, fb);
1097 _sde_plane_set_danger_lut(plane, fb);
1098
Alan Kwong5d324e42016-07-28 22:56:18 -04001099 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001100 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04001101 _sde_plane_set_ot_limit(plane, crtc);
1102 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001103
Clarence Ip282dad62016-09-27 17:07:35 -04001104 /* clear dirty */
1105 pstate->dirty = 0x0;
1106
Clarence Ip5e2a9222016-06-26 22:38:24 -04001107 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001108}
1109
1110static int sde_plane_prepare_fb(struct drm_plane *plane,
1111 const struct drm_plane_state *new_state)
1112{
1113 struct drm_framebuffer *fb = new_state->fb;
1114 struct sde_plane *psde = to_sde_plane(plane);
1115
1116 if (!new_state->fb)
1117 return 0;
1118
Clarence Ip13a8cf42016-09-29 17:27:47 -04001119 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001120 return msm_framebuffer_prepare(fb, psde->mmu_id);
1121}
1122
1123static void sde_plane_cleanup_fb(struct drm_plane *plane,
1124 const struct drm_plane_state *old_state)
1125{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001126 struct drm_framebuffer *fb = old_state ? old_state->fb : NULL;
1127 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001128
1129 if (!fb)
1130 return;
1131
Clarence Ip13a8cf42016-09-29 17:27:47 -04001132 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001133 msm_framebuffer_cleanup(fb, psde->mmu_id);
1134}
1135
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001136static void _sde_plane_atomic_check_mode_changed(struct sde_plane *psde,
1137 struct drm_plane_state *state,
1138 struct drm_plane_state *old_state)
1139{
1140 struct sde_plane_state *pstate = to_sde_plane_state(state);
1141
Dhaval Patel47302cf2016-08-18 15:04:28 -07001142 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04001143 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001144 return;
1145
Clarence Ip282dad62016-09-27 17:07:35 -04001146 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
1147 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001148 SDE_DEBUG_PLANE(psde,
1149 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001150 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001151 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001152 SDE_DEBUG_PLANE(psde, "still pending\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 (state->src_w != old_state->src_w ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07001155 state->src_h != old_state->src_h ||
1156 state->src_x != old_state->src_x ||
1157 state->src_y != old_state->src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001158 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001159 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001160 } else if (state->crtc_w != old_state->crtc_w ||
1161 state->crtc_h != old_state->crtc_h ||
1162 state->crtc_x != old_state->crtc_x ||
1163 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001164 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001165 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1166 }
1167
1168 if (!state->fb || !old_state->fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001169 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001170 } else if (state->fb->pixel_format != old_state->fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001171 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001172 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001173 } else {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001174 uint64_t *new_mods = state->fb->modifier;
1175 uint64_t *old_mods = old_state->fb->modifier;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001176 uint32_t *new_pitches = state->fb->pitches;
1177 uint32_t *old_pitches = old_state->fb->pitches;
1178 uint32_t *new_offset = state->fb->offsets;
1179 uint32_t *old_offset = old_state->fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001180 int i;
1181
1182 for (i = 0; i < ARRAY_SIZE(state->fb->modifier); i++) {
1183 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001184 SDE_DEBUG_PLANE(psde,
1185 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001186 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001187 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001188 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1189 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001190 break;
1191 }
1192 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001193 for (i = 0; i < ARRAY_SIZE(state->fb->pitches); i++) {
1194 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001195 SDE_DEBUG_PLANE(psde,
1196 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001197 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001198 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001199 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001200 break;
1201 }
1202 }
Dhaval Patel47302cf2016-08-18 15:04:28 -07001203 for (i = 0; i < ARRAY_SIZE(state->fb->offsets); i++) {
1204 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001205 SDE_DEBUG_PLANE(psde,
1206 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001207 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001208 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001209 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1210 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001211 break;
1212 }
1213 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001214 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001215}
1216
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001217static int sde_plane_atomic_check(struct drm_plane *plane,
1218 struct drm_plane_state *state)
1219{
Clarence Ipdedbba92016-09-27 17:43:10 -04001220 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04001221 struct sde_plane *psde;
1222 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001223 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001224 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04001225 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001226 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
1227 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04001228
1229 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001230 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1231 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04001232 ret = -EINVAL;
1233 goto exit;
1234 }
1235
1236 psde = to_sde_plane(plane);
1237 pstate = to_sde_plane_state(state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001238
1239 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001240 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001241 ret = -EINVAL;
1242 goto exit;
1243 }
1244
Clarence Ipdedbba92016-09-27 17:43:10 -04001245 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1246 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04001247
1248 /* src values are in Q16 fixed point, convert to integer */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001249 POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w,
1250 state->src_h, q16_data);
1251 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
1252 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04001253
Dhaval Patel47302cf2016-08-18 15:04:28 -07001254 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
1255 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04001256
Dhaval Patel47302cf2016-08-18 15:04:28 -07001257 max_upscale = psde->pipe_sblk->maxupscale;
1258 max_downscale = psde->pipe_sblk->maxdwnscale;
1259 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04001260
Clarence Ip13a8cf42016-09-29 17:27:47 -04001261 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001262 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001263
Dhaval Patel47302cf2016-08-18 15:04:28 -07001264 if (!sde_plane_enabled(state))
1265 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04001266
Dhaval Patel47302cf2016-08-18 15:04:28 -07001267 fmt = to_sde_format(msm_framebuffer_format(state->fb));
1268
1269 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
1270
1271 if (SDE_FORMAT_IS_YUV(fmt) &&
1272 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04001273 !(psde->features & (BIT(SDE_SSPP_CSC)
1274 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001275 SDE_ERROR_PLANE(psde,
1276 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07001277 ret = -EINVAL;
1278
1279 /* check src bounds */
1280 } else if (state->fb->width > MAX_IMG_WIDTH ||
1281 state->fb->height > MAX_IMG_HEIGHT ||
1282 src.w < min_src_size || src.h < min_src_size ||
1283 CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) ||
1284 CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001285 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001286 src.x, src.y, src.w, src.h);
1287 ret = -E2BIG;
1288
1289 /* valid yuv image */
1290 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
1291 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001292 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001293 src.x, src.y, src.w, src.h);
1294 ret = -EINVAL;
1295
1296 /* min dst support */
1297 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001298 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001299 dst.x, dst.y, dst.w, dst.h);
1300 ret = -EINVAL;
1301
1302 /* decimation validation */
1303 } else if (deci_w || deci_h) {
1304 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
1305 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001306 SDE_ERROR_PLANE(psde,
1307 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001308 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001309 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001310 SDE_ERROR_PLANE(psde,
1311 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001312 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001313 }
1314
Dhaval Patel47302cf2016-08-18 15:04:28 -07001315 } else if (!(psde->features & SDE_SSPP_SCALER) &&
1316 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001317 SDE_ERROR_PLANE(psde,
1318 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001319 src.w, src.h, dst.w, dst.h);
1320 ret = -EINVAL;
1321
1322 /* check decimated source width */
1323 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001324 SDE_ERROR_PLANE(psde,
1325 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001326 src.w, src_deci_w, max_linewidth);
1327 ret = -E2BIG;
1328
1329 /* check max scaler capability */
1330 } else if (((src_deci_w * max_upscale) < dst.w) ||
1331 ((src_deci_h * max_upscale) < dst.h) ||
1332 ((dst.w * max_downscale) < src_deci_w) ||
1333 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001334 SDE_ERROR_PLANE(psde,
1335 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001336 src_deci_w, src_deci_h, dst.w, dst.h);
1337 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001338 }
1339
Dhaval Patel47302cf2016-08-18 15:04:28 -07001340modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001341 if (!ret)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001342 _sde_plane_atomic_check_mode_changed(psde, state, plane->state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001343exit:
1344 return ret;
1345}
1346
Clarence Ipcae1bb62016-07-07 12:07:13 -04001347/**
1348 * sde_plane_flush - final plane operations before commit flush
1349 * @plane: Pointer to drm plane structure
1350 */
1351void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04001352{
Clarence Ipcae1bb62016-07-07 12:07:13 -04001353 struct sde_plane *psde;
1354
Clarence Ip13a8cf42016-09-29 17:27:47 -04001355 if (!plane) {
1356 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001357 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001358 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04001359
1360 psde = to_sde_plane(plane);
1361
1362 /*
1363 * These updates have to be done immediately before the plane flush
1364 * timing, and may not be moved to the atomic_update/mode_set functions.
1365 */
1366 if (psde->is_error)
1367 /* force white frame with 0% alpha pipe output on error */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001368 _sde_plane_color_fill(psde, 0xFFFFFF, 0x0);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001369 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
1370 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001371 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001372 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
1373 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
1374
1375 /* flag h/w flush complete */
1376 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04001377 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001378}
1379
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001380static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04001381 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001382{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001383 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001384 struct drm_plane_state *state;
1385 struct sde_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001386
Clarence Ip13a8cf42016-09-29 17:27:47 -04001387 if (!plane) {
1388 SDE_ERROR("invalid plane\n");
1389 return;
1390 } else if (!plane->state) {
1391 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04001392 return;
1393 }
1394
Clarence Ip13a8cf42016-09-29 17:27:47 -04001395 psde = to_sde_plane(plane);
1396 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001397 state = plane->state;
1398 pstate = to_sde_plane_state(state);
1399
Clarence Ip13a8cf42016-09-29 17:27:47 -04001400 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001401
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001402 if (!sde_plane_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04001403 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001404 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001405 int ret;
1406
Dhaval Patel47302cf2016-08-18 15:04:28 -07001407 ret = _sde_plane_mode_set(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001408 /* atomic_check should have ensured that this doesn't fail */
1409 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001410 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001411}
1412
Dhaval Patel47302cf2016-08-18 15:04:28 -07001413
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001414/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001415static void _sde_plane_install_properties(struct drm_plane *plane,
Clarence Ipc47a0692016-10-11 10:54:17 -04001416 struct sde_mdss_cfg *catalog)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001417{
Clarence Ip5e2a9222016-06-26 22:38:24 -04001418 static const struct drm_prop_enum_list e_blend_op[] = {
1419 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
1420 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
1421 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
1422 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
1423 };
1424 static const struct drm_prop_enum_list e_src_config[] = {
1425 {SDE_DRM_DEINTERLACE, "deinterlace"}
1426 };
Clarence Ipea3d6262016-07-15 16:20:11 -04001427 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07001428 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001429 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04001430 int zpos_max = 255;
1431 int zpos_def = 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001432
Clarence Ip13a8cf42016-09-29 17:27:47 -04001433 if (!plane || !psde) {
1434 SDE_ERROR("invalid plane\n");
1435 return;
1436 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
1437 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
1438 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001439 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04001440 } else if (!catalog) {
1441 SDE_ERROR("invalid catalog\n");
1442 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001443 }
1444
Clarence Ipc47a0692016-10-11 10:54:17 -04001445 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04001446 if (catalog->mixer_count && catalog->mixer &&
1447 catalog->mixer[0].sblk->maxblendstages) {
1448 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
1449 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
1450 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
1451 }
Clarence Ipc47a0692016-10-11 10:54:17 -04001452 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
1453 /* reserve zpos == 0 for primary planes */
1454 zpos_def = drm_plane_index(plane) + 1;
1455 }
1456
1457 msm_property_install_range(&psde->property_info, "zpos",
1458 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001459
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001460 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001461 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001462
Dhaval Patel47302cf2016-08-18 15:04:28 -07001463 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001464 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07001465 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001466
Clarence Ipdedbba92016-09-27 17:43:10 -04001467 if (psde->pipe_sblk->maxhdeciexp) {
1468 msm_property_install_range(&psde->property_info, "h_decimate",
1469 0x0, 0, psde->pipe_sblk->maxhdeciexp, 0,
1470 PLANE_PROP_H_DECIMATE);
1471 }
1472
1473 if (psde->pipe_sblk->maxvdeciexp) {
1474 msm_property_install_range(&psde->property_info, "v_decimate",
1475 0x0, 0, psde->pipe_sblk->maxvdeciexp, 0,
1476 PLANE_PROP_V_DECIMATE);
1477 }
1478
abeykun48f407a2016-08-25 12:06:44 -04001479 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
1480 msm_property_install_volatile_range(&psde->property_info,
1481 "scaler_v2", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
1482 msm_property_install_blob(&psde->property_info, "lut_ed", 0,
1483 PLANE_PROP_SCALER_LUT_ED);
1484 msm_property_install_blob(&psde->property_info, "lut_cir", 0,
1485 PLANE_PROP_SCALER_LUT_CIR);
1486 msm_property_install_blob(&psde->property_info, "lut_sep", 0,
1487 PLANE_PROP_SCALER_LUT_SEP);
1488 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001489 msm_property_install_volatile_range(&psde->property_info,
1490 "scaler_v1", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V1);
1491 }
1492
Clarence Ip5fc00c52016-09-23 15:03:34 -04001493 if (psde->features & BIT(SDE_SSPP_CSC)) {
1494 msm_property_install_volatile_range(&psde->property_info,
1495 "csc_v1", 0x0, 0, ~0, 0, PLANE_PROP_CSC_V1);
1496 }
1497
Clarence Ip5e2a9222016-06-26 22:38:24 -04001498 /* standard properties */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001499 msm_property_install_rotation(&psde->property_info,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001500 BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y), PLANE_PROP_ROTATION);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001501
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001502 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001503 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001504
Dhaval Patel47302cf2016-08-18 15:04:28 -07001505 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
1506 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
1507
1508 if (psde->pipe_hw->ops.setup_solidfill)
1509 msm_property_install_range(&psde->property_info, "color_fill",
1510 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
1511
Dhaval Patel4e574842016-08-23 15:11:37 -07001512 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001513 if (!info) {
1514 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07001515 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001516 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001517
1518 msm_property_install_blob(&psde->property_info, "capabilities",
1519 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
1520 sde_kms_info_reset(info);
1521
Clarence Ipea3d6262016-07-15 16:20:11 -04001522 format_list = psde->pipe_sblk->format_list;
1523 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04001524 sde_kms_info_start(info, "pixel_formats");
1525 while (format_list->fourcc_format) {
1526 sde_kms_info_append_format(info,
1527 format_list->fourcc_format,
1528 format_list->modifier);
1529 ++format_list;
1530 }
1531 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04001532 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001533
1534 sde_kms_info_add_keyint(info, "max_linewidth",
1535 psde->pipe_sblk->maxlinewidth);
1536 sde_kms_info_add_keyint(info, "max_upscale",
1537 psde->pipe_sblk->maxupscale);
1538 sde_kms_info_add_keyint(info, "max_downscale",
1539 psde->pipe_sblk->maxdwnscale);
1540 sde_kms_info_add_keyint(info, "max_horizontal_deci",
1541 psde->pipe_sblk->maxhdeciexp);
1542 sde_kms_info_add_keyint(info, "max_vertical_deci",
1543 psde->pipe_sblk->maxvdeciexp);
1544 msm_property_set_blob(&psde->property_info, &psde->blob_info,
1545 info->data, info->len, PLANE_PROP_INFO);
1546
1547 kfree(info);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001548}
1549
Clarence Ip5fc00c52016-09-23 15:03:34 -04001550static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
1551{
1552 struct sde_drm_csc_v1 csc_v1;
1553 int i;
1554
1555 if (!psde) {
1556 SDE_ERROR("invalid plane\n");
1557 return;
1558 }
1559
1560 psde->csc_usr_ptr = NULL;
1561 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001562 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001563 return;
1564 }
1565
1566 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001567 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001568 return;
1569 }
1570
Clarence Ipb43d4592016-09-08 14:21:35 -04001571 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001572 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
1573 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
1574 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
1575 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
1576 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
1577 }
1578 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
1579 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
1580 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
1581 }
1582 psde->csc_usr_ptr = &psde->csc_cfg;
1583}
1584
Clarence Ipb43d4592016-09-08 14:21:35 -04001585static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
1586{
1587 struct sde_drm_scaler_v1 scale_v1;
1588 struct sde_hw_pixel_ext *pe;
1589 int i;
1590
1591 if (!psde) {
1592 SDE_ERROR("invalid plane\n");
1593 return;
1594 }
1595
1596 psde->pixel_ext_usr = false;
1597 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001598 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001599 return;
1600 }
1601
1602 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001603 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001604 return;
1605 }
1606
1607 /* populate from user space */
1608 pe = &(psde->pixel_ext);
1609 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1610 for (i = 0; i < SDE_MAX_PLANES; i++) {
1611 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
1612 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
1613 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
1614 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
1615
1616 pe->horz_filter[i] = scale_v1.horz_filter[i];
1617 pe->vert_filter[i] = scale_v1.vert_filter[i];
1618 }
1619 for (i = 0; i < SDE_MAX_PLANES; i++) {
1620 pe->num_ext_pxls_left[i] = scale_v1.lr.num_pxls_start[i];
1621 pe->num_ext_pxls_right[i] = scale_v1.lr.num_pxls_end[i];
1622 pe->left_ftch[i] = scale_v1.lr.ftch_start[i];
1623 pe->right_ftch[i] = scale_v1.lr.ftch_end[i];
1624 pe->left_rpt[i] = scale_v1.lr.rpt_start[i];
1625 pe->right_rpt[i] = scale_v1.lr.rpt_end[i];
1626 pe->roi_w[i] = scale_v1.lr.roi[i];
1627
1628 pe->num_ext_pxls_top[i] = scale_v1.tb.num_pxls_start[i];
1629 pe->num_ext_pxls_btm[i] = scale_v1.tb.num_pxls_end[i];
1630 pe->top_ftch[i] = scale_v1.tb.ftch_start[i];
1631 pe->btm_ftch[i] = scale_v1.tb.ftch_end[i];
1632 pe->top_rpt[i] = scale_v1.tb.rpt_start[i];
1633 pe->btm_rpt[i] = scale_v1.tb.rpt_end[i];
1634 pe->roi_h[i] = scale_v1.tb.roi[i];
1635 }
1636 psde->pixel_ext_usr = true;
1637
Clarence Ip13a8cf42016-09-29 17:27:47 -04001638 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001639}
1640
abeykun48f407a2016-08-25 12:06:44 -04001641static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
1642 struct sde_plane_state *pstate, void *usr)
1643{
1644 struct sde_drm_scaler_v2 scale_v2;
1645 struct sde_hw_pixel_ext *pe;
1646 int i;
1647 struct sde_hw_scaler3_cfg *cfg;
1648
1649 if (!psde) {
1650 SDE_ERROR("invalid plane\n");
1651 return;
1652 }
1653
1654 cfg = psde->scaler3_cfg;
1655 psde->pixel_ext_usr = false;
1656 if (!usr) {
1657 SDE_DEBUG_PLANE(psde, "scale data removed\n");
1658 return;
1659 }
1660
1661 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
1662 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
1663 return;
1664 }
1665
1666 /* populate from user space */
1667 pe = &(psde->pixel_ext);
1668 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1669 cfg->enable = scale_v2.enable;
1670 cfg->dir_en = scale_v2.dir_en;
1671 for (i = 0; i < SDE_MAX_PLANES; i++) {
1672 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
1673 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
1674 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
1675 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
1676
1677 cfg->preload_x[i] = scale_v2.preload_x[i];
1678 cfg->preload_y[i] = scale_v2.preload_y[i];
1679 cfg->src_width[i] = scale_v2.src_width[i];
1680 cfg->src_height[i] = scale_v2.src_height[i];
1681 }
1682 cfg->dst_width = scale_v2.dst_width;
1683 cfg->dst_height = scale_v2.dst_height;
1684
1685 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
1686 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
1687 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
1688 cfg->blend_cfg = scale_v2.blend_cfg;
1689
1690 cfg->lut_flag = scale_v2.lut_flag;
1691 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
1692 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
1693 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
1694 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
1695 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
1696
1697 cfg->de.enable = scale_v2.de.enable;
1698 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
1699 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
1700 cfg->de.clip = scale_v2.de.clip;
1701 cfg->de.limit = scale_v2.de.limit;
1702 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
1703 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
1704 cfg->de.thr_low = scale_v2.de.thr_low;
1705 cfg->de.thr_high = scale_v2.de.thr_high;
1706 cfg->de.prec_shift = scale_v2.de.prec_shift;
1707 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
1708 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
1709 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
1710 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
1711 }
1712 for (i = 0; i < SDE_MAX_PLANES; i++) {
1713 pe->num_ext_pxls_left[i] = scale_v2.lr.num_pxls_start[i];
1714 pe->num_ext_pxls_right[i] = scale_v2.lr.num_pxls_end[i];
1715 pe->left_ftch[i] = scale_v2.lr.ftch_start[i];
1716 pe->right_ftch[i] = scale_v2.lr.ftch_end[i];
1717 pe->left_rpt[i] = scale_v2.lr.rpt_start[i];
1718 pe->right_rpt[i] = scale_v2.lr.rpt_end[i];
1719 pe->roi_w[i] = scale_v2.lr.roi[i];
1720
1721 pe->num_ext_pxls_top[i] = scale_v2.tb.num_pxls_start[i];
1722 pe->num_ext_pxls_btm[i] = scale_v2.tb.num_pxls_end[i];
1723 pe->top_ftch[i] = scale_v2.tb.ftch_start[i];
1724 pe->btm_ftch[i] = scale_v2.tb.ftch_end[i];
1725 pe->top_rpt[i] = scale_v2.tb.rpt_start[i];
1726 pe->btm_rpt[i] = scale_v2.tb.rpt_end[i];
1727 pe->roi_h[i] = scale_v2.tb.roi[i];
1728 }
1729 psde->pixel_ext_usr = true;
1730
1731 SDE_DEBUG_PLANE(psde, "user property data copied\n");
1732}
1733
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001734static int sde_plane_atomic_set_property(struct drm_plane *plane,
1735 struct drm_plane_state *state, struct drm_property *property,
1736 uint64_t val)
1737{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001738 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001739 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001740 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001741
Clarence Ip13a8cf42016-09-29 17:27:47 -04001742 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001743
1744 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001745 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001746 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001747 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001748 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04001749 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001750 ret = msm_property_atomic_set(&psde->property_info,
1751 pstate->property_values, pstate->property_blobs,
1752 property, val);
1753 if (!ret) {
1754 idx = msm_property_index(&psde->property_info,
1755 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001756 switch (idx) {
1757 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04001758 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001759 break;
1760 case PLANE_PROP_CSC_V1:
1761 _sde_plane_set_csc_v1(psde, (void *)val);
1762 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04001763 case PLANE_PROP_SCALER_V1:
1764 _sde_plane_set_scaler_v1(psde, (void *)val);
1765 break;
abeykun48f407a2016-08-25 12:06:44 -04001766 case PLANE_PROP_SCALER_V2:
1767 _sde_plane_set_scaler_v2(psde, pstate,
1768 (void *)val);
1769 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001770 default:
1771 /* nothing to do */
1772 break;
1773 }
Clarence Ipe78efb72016-06-24 18:35:21 -04001774 }
1775 }
1776
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001777 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001778}
1779
1780static int sde_plane_set_property(struct drm_plane *plane,
1781 struct drm_property *property, uint64_t val)
1782{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001783 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001784
Clarence Ipae4e60c2016-06-26 22:44:04 -04001785 return sde_plane_atomic_set_property(plane,
1786 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001787}
1788
1789static int sde_plane_atomic_get_property(struct drm_plane *plane,
1790 const struct drm_plane_state *state,
1791 struct drm_property *property, uint64_t *val)
1792{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001793 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001794 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04001795 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001796
Clarence Ipaa0faf42016-05-30 12:07:48 -04001797 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001798 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001799 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001800 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001801 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001802 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001803 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001804 ret = msm_property_atomic_get(&psde->property_info,
1805 pstate->property_values, pstate->property_blobs,
1806 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04001807 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001808
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001809 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001810}
1811
1812static void sde_plane_destroy(struct drm_plane *plane)
1813{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001814 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001815
Clarence Ip13a8cf42016-09-29 17:27:47 -04001816 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001817
Clarence Ip13a8cf42016-09-29 17:27:47 -04001818 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001819 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1820
Clarence Ip4ce59322016-06-26 22:27:51 -04001821 debugfs_remove_recursive(psde->debugfs_root);
Clarence Ipe78efb72016-06-24 18:35:21 -04001822
Dhaval Patel4e574842016-08-23 15:11:37 -07001823 if (psde->blob_info)
1824 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001825 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04001826 mutex_destroy(&psde->lock);
1827
Clarence Ip4ce59322016-06-26 22:27:51 -04001828 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001829
Clarence Ip4ce59322016-06-26 22:27:51 -04001830 /* this will destroy the states as well */
1831 drm_plane_cleanup(plane);
1832
Clarence Ip4c1d9772016-06-26 09:35:38 -04001833 if (psde->pipe_hw)
1834 sde_hw_sspp_destroy(psde->pipe_hw);
1835
Clarence Ip4ce59322016-06-26 22:27:51 -04001836 kfree(psde);
1837 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001838}
1839
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001840static void sde_plane_destroy_state(struct drm_plane *plane,
1841 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001842{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001843 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04001844 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001845
Clarence Ipae4e60c2016-06-26 22:44:04 -04001846 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001847 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1848 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001849 return;
1850 }
1851
Clarence Ipaa0faf42016-05-30 12:07:48 -04001852 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04001853 pstate = to_sde_plane_state(state);
1854
Clarence Ip13a8cf42016-09-29 17:27:47 -04001855 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001856
Clarence Ipe78efb72016-06-24 18:35:21 -04001857 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001858 if (state->fb)
1859 drm_framebuffer_unreference(state->fb);
1860
Clarence Ipae4e60c2016-06-26 22:44:04 -04001861 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001862 if (pstate->input_fence)
1863 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001864
Clarence Ipaa0faf42016-05-30 12:07:48 -04001865 /* destroy value helper */
1866 msm_property_destroy_state(&psde->property_info, pstate,
1867 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001868}
1869
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001870static struct drm_plane_state *
1871sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001872{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001873 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001874 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04001875 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04001876 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001877
Clarence Ip13a8cf42016-09-29 17:27:47 -04001878 if (!plane) {
1879 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001880 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001881 } else if (!plane->state) {
1882 SDE_ERROR("invalid plane state\n");
1883 return NULL;
1884 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001885
Clarence Ip730e7192016-06-26 22:45:09 -04001886 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001887 psde = to_sde_plane(plane);
1888 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001889 if (!pstate) {
1890 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001891 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001892 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001893
Clarence Ip13a8cf42016-09-29 17:27:47 -04001894 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001895
1896 /* duplicate value helper */
1897 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
1898 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001899
Clarence Ip730e7192016-06-26 22:45:09 -04001900 /* add ref count for frame buffer */
1901 if (pstate->base.fb)
1902 drm_framebuffer_reference(pstate->base.fb);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001903
Clarence Ip17e908b2016-09-29 15:58:00 -04001904 /* clear out any input fence */
1905 pstate->input_fence = 0;
1906 input_fence_default = msm_property_get_default(
1907 &psde->property_info, PLANE_PROP_INPUT_FENCE);
1908 msm_property_set_property(&psde->property_info, pstate->property_values,
1909 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001910
Clarence Ip282dad62016-09-27 17:07:35 -04001911 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04001912 pstate->pending = false;
1913
1914 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001915}
1916
1917static void sde_plane_reset(struct drm_plane *plane)
1918{
Clarence Ipae4e60c2016-06-26 22:44:04 -04001919 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001920 struct sde_plane_state *pstate;
1921
Clarence Ipae4e60c2016-06-26 22:44:04 -04001922 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001923 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001924 return;
1925 }
1926
Clarence Ip730e7192016-06-26 22:45:09 -04001927 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001928 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001929
Clarence Ipae4e60c2016-06-26 22:44:04 -04001930 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001931 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04001932 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001933 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04001934 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001935
Clarence Ipaa0faf42016-05-30 12:07:48 -04001936 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001937 if (!pstate) {
1938 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001939 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001940 }
Clarence Ip730e7192016-06-26 22:45:09 -04001941
Clarence Ipaa0faf42016-05-30 12:07:48 -04001942 /* reset value helper */
1943 msm_property_reset_state(&psde->property_info, pstate,
1944 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001945
1946 pstate->base.plane = plane;
1947
1948 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001949}
1950
1951static const struct drm_plane_funcs sde_plane_funcs = {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001952 .update_plane = drm_atomic_helper_update_plane,
1953 .disable_plane = drm_atomic_helper_disable_plane,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001954 .destroy = sde_plane_destroy,
1955 .set_property = sde_plane_set_property,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001956 .atomic_set_property = sde_plane_atomic_set_property,
1957 .atomic_get_property = sde_plane_atomic_get_property,
1958 .reset = sde_plane_reset,
1959 .atomic_duplicate_state = sde_plane_duplicate_state,
1960 .atomic_destroy_state = sde_plane_destroy_state,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001961};
1962
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001963static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
1964 .prepare_fb = sde_plane_prepare_fb,
1965 .cleanup_fb = sde_plane_cleanup_fb,
1966 .atomic_check = sde_plane_atomic_check,
1967 .atomic_update = sde_plane_atomic_update,
1968};
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001969
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001970enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001971{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001972 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001973}
1974
Clarence Ip4ce59322016-06-26 22:27:51 -04001975static void _sde_plane_init_debugfs(struct sde_plane *psde, struct sde_kms *kms)
1976{
1977 const struct sde_sspp_sub_blks *sblk = 0;
1978 const struct sde_sspp_cfg *cfg = 0;
1979
1980 if (psde && psde->pipe_hw)
1981 cfg = psde->pipe_hw->cap;
1982 if (cfg)
1983 sblk = cfg->sblk;
1984
1985 if (kms && sblk) {
1986 /* create overall sub-directory for the pipe */
1987 psde->debugfs_root =
1988 debugfs_create_dir(psde->pipe_name,
1989 sde_debugfs_get_root(kms));
1990 if (psde->debugfs_root) {
1991 /* don't error check these */
Clarence Ip4c1d9772016-06-26 09:35:38 -04001992 debugfs_create_x32("features", 0644,
Clarence Ip4ce59322016-06-26 22:27:51 -04001993 psde->debugfs_root, &psde->features);
1994
1995 /* add register dump support */
1996 sde_debugfs_setup_regset32(&psde->debugfs_src,
1997 sblk->src_blk.base + cfg->base,
1998 sblk->src_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04001999 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002000 sde_debugfs_create_regset32("src_blk", 0444,
2001 psde->debugfs_root, &psde->debugfs_src);
2002
2003 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
2004 sblk->scaler_blk.base + cfg->base,
2005 sblk->scaler_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002006 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002007 sde_debugfs_create_regset32("scaler_blk", 0444,
2008 psde->debugfs_root,
2009 &psde->debugfs_scaler);
2010
2011 sde_debugfs_setup_regset32(&psde->debugfs_csc,
2012 sblk->csc_blk.base + cfg->base,
2013 sblk->csc_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002014 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002015 sde_debugfs_create_regset32("csc_blk", 0444,
2016 psde->debugfs_root, &psde->debugfs_csc);
2017 }
2018 }
2019}
2020
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002021/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04002022struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002023 uint32_t pipe, bool primary_plane,
2024 unsigned long possible_crtcs)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002025{
2026 struct drm_plane *plane = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002027 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002028 struct msm_drm_private *priv;
2029 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002030 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04002031 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002032
2033 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002034 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002035 goto exit;
2036 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002037
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002038 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04002039 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002040 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002041 goto exit;
2042 }
2043
2044 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002045 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002046 goto exit;
2047 }
2048 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002049
Clarence Ip4c1d9772016-06-26 09:35:38 -04002050 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002051 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002052 goto exit;
2053 }
2054
Clarence Ip4ce59322016-06-26 22:27:51 -04002055 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002056 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
2057 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002058 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002059 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002060 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002061 }
2062
Clarence Ip4c1d9772016-06-26 09:35:38 -04002063 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002064 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002065 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04002066 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002067
Clarence Ip4c1d9772016-06-26 09:35:38 -04002068 /* initialize underlying h/w driver */
2069 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
2070 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002071 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002072 ret = PTR_ERR(psde->pipe_hw);
2073 goto clean_plane;
2074 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002075 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002076 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002077 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002078
2079 /* cache features mask for later */
2080 psde->features = psde->pipe_hw->cap->features;
2081 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04002082 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002083 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04002084 goto clean_sspp;
2085 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002086
abeykun48f407a2016-08-25 12:06:44 -04002087 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
2088 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
2089 GFP_KERNEL);
2090 if (!psde->scaler3_cfg) {
2091 SDE_ERROR("[%u]failed to allocate scale struct\n",
2092 pipe);
2093 ret = -ENOMEM;
2094 goto clean_sspp;
2095 }
2096 }
2097
Clarence Ip4c1d9772016-06-26 09:35:38 -04002098 /* add plane to DRM framework */
Clarence Ipea3d6262016-07-15 16:20:11 -04002099 psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
2100 psde->formats,
2101 0,
2102 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002103
Clarence Ip4c1d9772016-06-26 09:35:38 -04002104 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002105 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002106 goto clean_sspp;
2107 }
2108
2109 if (psde->features & BIT(SDE_SSPP_CURSOR))
2110 type = DRM_PLANE_TYPE_CURSOR;
2111 else if (primary_plane)
2112 type = DRM_PLANE_TYPE_PRIMARY;
2113 else
2114 type = DRM_PLANE_TYPE_OVERLAY;
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002115 ret = drm_universal_plane_init(dev, plane, possible_crtcs,
2116 &sde_plane_funcs, psde->formats, psde->nformats, type);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002117 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04002118 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002119
Clarence Ip4c1d9772016-06-26 09:35:38 -04002120 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002121 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002122
Clarence Ipaa0faf42016-05-30 12:07:48 -04002123 msm_property_init(&psde->property_info, &plane->base, dev,
2124 priv->plane_property, psde->property_data,
2125 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
2126 sizeof(struct sde_plane_state));
2127
Clarence Ipc47a0692016-10-11 10:54:17 -04002128 _sde_plane_install_properties(plane, kms->catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002129
Clarence Ip4ce59322016-06-26 22:27:51 -04002130 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04002131 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04002132
Clarence Ip730e7192016-06-26 22:45:09 -04002133 mutex_init(&psde->lock);
2134
Clarence Ip4ce59322016-06-26 22:27:51 -04002135 _sde_plane_init_debugfs(psde, kms);
2136
Clarence Ip13a8cf42016-09-29 17:27:47 -04002137 DRM_INFO("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002138 return plane;
2139
Clarence Ip4c1d9772016-06-26 09:35:38 -04002140clean_sspp:
2141 if (psde && psde->pipe_hw)
2142 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04002143
2144 if (psde && psde->scaler3_cfg)
2145 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002146clean_plane:
2147 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04002148exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002149 return ERR_PTR(ret);
2150}