blob: e11a797ca099ede7f36ef60b6978f2fc73d4fb99 [file] [log] [blame]
Clarence Ipaac9f332016-08-31 15:46:35 -04001/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
Alan Kwong1a00e4d2016-07-18 09:42:30 -040012
13#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
14
Clarence Ip4ce59322016-06-26 22:27:51 -040015#include <linux/debugfs.h>
Clarence Ip5e2a9222016-06-26 22:38:24 -040016#include <uapi/drm/sde_drm.h>
Clarence Ipaa0faf42016-05-30 12:07:48 -040017
18#include "msm_prop.h"
19
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070020#include "sde_kms.h"
Clarence Ipae4e60c2016-06-26 22:44:04 -040021#include "sde_fence.h"
Clarence Ipc475b082016-06-26 09:27:23 -040022#include "sde_formats.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040023#include "sde_hw_sspp.h"
Alan Kwong1a00e4d2016-07-18 09:42:30 -040024#include "sde_trace.h"
Dhaval Patel48c76022016-09-01 17:51:23 -070025#include "sde_crtc.h"
Lloyd Atkinson8772e202016-09-26 17:52:16 -040026#include "sde_vbif.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040027
Clarence Ip13a8cf42016-09-29 17:27:47 -040028#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
29 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
30
31#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
32 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
33
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040034#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
35#define PHASE_STEP_SHIFT 21
36#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
37#define PHASE_RESIDUAL 15
38
Clarence Ipe78efb72016-06-24 18:35:21 -040039#define SHARP_STRENGTH_DEFAULT 32
40#define SHARP_EDGE_THR_DEFAULT 112
41#define SHARP_SMOOTH_THR_DEFAULT 8
42#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040043
Clarence Ip5e2a9222016-06-26 22:38:24 -040044#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070045
Clarence Ipcae1bb62016-07-07 12:07:13 -040046#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
47
Clarence Ip282dad62016-09-27 17:07:35 -040048/* dirty bits for update function */
49#define SDE_PLANE_DIRTY_RECTS 0x1
50#define SDE_PLANE_DIRTY_FORMAT 0x2
51#define SDE_PLANE_DIRTY_SHARPEN 0x4
52#define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF
53
Alan Kwong1a00e4d2016-07-18 09:42:30 -040054/**
55 * enum sde_plane_qos - Different qos configurations for each pipe
56 *
57 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
58 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
59 * this configuration is mutually exclusive from VBLANK_CTRL.
60 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
61 */
62enum sde_plane_qos {
63 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
64 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
65 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
66};
67
Clarence Ip5fc00c52016-09-23 15:03:34 -040068/*
69 * struct sde_plane - local sde plane structure
70 * @csc_cfg: Decoded user configuration for csc
71 * @csc_usr_ptr: Points to csc_cfg if valid user config available
72 * @csc_ptr: Points to sde_csc_cfg structure to use for current
73 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070074struct sde_plane {
75 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040076
77 int mmu_id;
78
Clarence Ip730e7192016-06-26 22:45:09 -040079 struct mutex lock;
80
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040081 enum sde_sspp pipe;
82 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070083 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -040084 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040085
86 struct sde_hw_pipe *pipe_hw;
87 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -040088 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -040089 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040090 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -040091 uint32_t color_fill;
92 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -040093 bool is_rt_pipe;
Clarence Ip4ce59322016-06-26 22:27:51 -040094
Clarence Ipb43d4592016-09-08 14:21:35 -040095 struct sde_hw_pixel_ext pixel_ext;
96 bool pixel_ext_usr;
97
Clarence Ip373f8592016-05-26 00:58:42 -040098 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -040099 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400100 struct sde_csc_cfg *csc_ptr;
101
Clarence Ip4c1d9772016-06-26 09:35:38 -0400102 const struct sde_sspp_sub_blks *pipe_sblk;
103
Clarence Ip5e2a9222016-06-26 22:38:24 -0400104 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400105
Clarence Ipaa0faf42016-05-30 12:07:48 -0400106 struct msm_property_info property_info;
107 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700108 struct drm_property_blob *blob_info;
Clarence Ip730e7192016-06-26 22:45:09 -0400109
Clarence Ip4ce59322016-06-26 22:27:51 -0400110 /* debugfs related stuff */
111 struct dentry *debugfs_root;
112 struct sde_debugfs_regset32 debugfs_src;
113 struct sde_debugfs_regset32 debugfs_scaler;
114 struct sde_debugfs_regset32 debugfs_csc;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700115};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700116
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700117#define to_sde_plane(x) container_of(x, struct sde_plane, base)
118
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400119static bool sde_plane_enabled(struct drm_plane_state *state)
120{
Clarence Ipdbde9832016-06-26 09:48:36 -0400121 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400122}
123
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400124/**
125 * _sde_plane_calc_fill_level - calculate fill level of the given source format
126 * @plane: Pointer to drm plane
127 * @fmt: Pointer to source buffer format
128 * @src_wdith: width of source buffer
129 * Return: fill level corresponding to the source buffer/format or 0 if error
130 */
131static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
132 const struct sde_format *fmt, u32 src_width)
133{
134 struct sde_plane *psde;
135 u32 fixed_buff_size;
136 u32 total_fl;
137
138 if (!plane || !fmt) {
139 SDE_ERROR("invalid arguments\n");
140 return 0;
141 }
142
143 psde = to_sde_plane(plane);
144 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
145
146 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
147 if (fmt->chroma_sample == SDE_CHROMA_420) {
148 /* NV12 */
149 total_fl = (fixed_buff_size / 2) /
150 ((src_width + 32) * fmt->bpp);
151 } else {
152 /* non NV12 */
153 total_fl = (fixed_buff_size) /
154 ((src_width + 32) * fmt->bpp);
155 }
156 } else {
157 total_fl = (fixed_buff_size * 2) /
158 ((src_width + 32) * fmt->bpp);
159 }
160
161 SDE_DEBUG("plane%u: pnum:%d fmt:%x w:%u fl:%u\n",
162 plane->base.id, psde->pipe - SSPP_VIG0,
163 fmt->base.pixel_format, src_width, total_fl);
164
165 return total_fl;
166}
167
168/**
169 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
170 * @total_fl: fill level
171 * Return: LUT setting corresponding to the fill level
172 */
173static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
174{
175 u32 qos_lut;
176
177 if (total_fl <= 4)
178 qos_lut = 0x1B;
179 else if (total_fl <= 5)
180 qos_lut = 0x5B;
181 else if (total_fl <= 6)
182 qos_lut = 0x15B;
183 else if (total_fl <= 7)
184 qos_lut = 0x55B;
185 else if (total_fl <= 8)
186 qos_lut = 0x155B;
187 else if (total_fl <= 9)
188 qos_lut = 0x555B;
189 else if (total_fl <= 10)
190 qos_lut = 0x1555B;
191 else if (total_fl <= 11)
192 qos_lut = 0x5555B;
193 else if (total_fl <= 12)
194 qos_lut = 0x15555B;
195 else
196 qos_lut = 0x55555B;
197
198 return qos_lut;
199}
200
201/**
202 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
203 * @total_fl: fill level
204 * Return: LUT setting corresponding to the fill level
205 */
206static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
207{
208 u32 qos_lut;
209
210 if (total_fl <= 10)
211 qos_lut = 0x1AAff;
212 else if (total_fl <= 11)
213 qos_lut = 0x5AAFF;
214 else if (total_fl <= 12)
215 qos_lut = 0x15AAFF;
216 else
217 qos_lut = 0x55AAFF;
218
219 return qos_lut;
220}
221
222/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400223 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
224 * @plane: Pointer to drm plane
225 * @fb: Pointer to framebuffer associated with the given plane
226 */
227static void _sde_plane_set_qos_lut(struct drm_plane *plane,
228 struct drm_framebuffer *fb)
229{
230 struct sde_plane *psde;
231 const struct sde_format *fmt = NULL;
232 u32 qos_lut;
233 u32 total_fl = 0;
234
235 if (!plane || !fb) {
236 SDE_ERROR("invalid arguments plane %d fb %d\n",
237 plane != 0, fb != 0);
238 return;
239 }
240
241 psde = to_sde_plane(plane);
242
243 if (!psde->pipe_hw || !psde->pipe_sblk) {
244 SDE_ERROR("invalid arguments\n");
245 return;
246 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
247 return;
248 }
249
250 if (!psde->is_rt_pipe) {
251 qos_lut = psde->pipe_sblk->creq_lut_nrt;
252 } else {
253 fmt = sde_get_sde_format_ext(
254 fb->pixel_format,
255 fb->modifier,
256 drm_format_num_planes(fb->pixel_format));
257 total_fl = _sde_plane_calc_fill_level(plane, fmt,
258 psde->pipe_cfg.src_rect.w);
259
260 if (SDE_FORMAT_IS_LINEAR(fmt))
261 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
262 else
263 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
264 }
265
266 psde->pipe_qos_cfg.creq_lut = qos_lut;
267
268 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
269 (fmt) ? fmt->base.pixel_format : 0,
270 psde->is_rt_pipe, total_fl, qos_lut,
271 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
272
273 SDE_DEBUG("plane%u: pnum:%d fmt:%x rt:%d fl:%u lut:0x%x\n",
274 plane->base.id,
275 psde->pipe - SSPP_VIG0,
276 (fmt) ? fmt->base.pixel_format : 0,
277 psde->is_rt_pipe, total_fl, qos_lut);
278
279 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
280}
281
282/**
283 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
284 * @plane: Pointer to drm plane
285 * @fb: Pointer to framebuffer associated with the given plane
286 */
287static void _sde_plane_set_danger_lut(struct drm_plane *plane,
288 struct drm_framebuffer *fb)
289{
290 struct sde_plane *psde;
291 const struct sde_format *fmt = NULL;
292 u32 danger_lut, safe_lut;
293
294 if (!plane || !fb) {
295 SDE_ERROR("invalid arguments\n");
296 return;
297 }
298
299 psde = to_sde_plane(plane);
300
301 if (!psde->pipe_hw || !psde->pipe_sblk) {
302 SDE_ERROR("invalid arguments\n");
303 return;
304 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
305 return;
306 }
307
308 if (!psde->is_rt_pipe) {
309 danger_lut = psde->pipe_sblk->danger_lut_nrt;
310 safe_lut = psde->pipe_sblk->safe_lut_nrt;
311 } else {
312 fmt = sde_get_sde_format_ext(
313 fb->pixel_format,
314 fb->modifier,
315 drm_format_num_planes(fb->pixel_format));
316
317 if (SDE_FORMAT_IS_LINEAR(fmt)) {
318 danger_lut = psde->pipe_sblk->danger_lut_linear;
319 safe_lut = psde->pipe_sblk->safe_lut_linear;
320 } else {
321 danger_lut = psde->pipe_sblk->danger_lut_tile;
322 safe_lut = psde->pipe_sblk->safe_lut_tile;
323 }
324 }
325
326 psde->pipe_qos_cfg.danger_lut = danger_lut;
327 psde->pipe_qos_cfg.safe_lut = safe_lut;
328
329 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
330 (fmt) ? fmt->base.pixel_format : 0,
331 (fmt) ? fmt->fetch_mode : 0,
332 psde->pipe_qos_cfg.danger_lut,
333 psde->pipe_qos_cfg.safe_lut);
334
335 SDE_DEBUG("plane%u: pnum:%d fmt:%x mode:%d luts[0x%x, 0x%x]\n",
336 plane->base.id,
337 psde->pipe - SSPP_VIG0,
338 fmt ? fmt->base.pixel_format : 0,
339 fmt ? fmt->fetch_mode : -1,
340 psde->pipe_qos_cfg.danger_lut,
341 psde->pipe_qos_cfg.safe_lut);
342
343 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
344 &psde->pipe_qos_cfg);
345}
346
347/**
348 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
349 * @plane: Pointer to drm plane
350 * @enable: true to enable QoS control
351 * @flags: QoS control mode (enum sde_plane_qos)
352 */
353static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
354 bool enable, u32 flags)
355{
356 struct sde_plane *psde;
357
358 if (!plane) {
359 SDE_ERROR("invalid arguments\n");
360 return;
361 }
362
363 psde = to_sde_plane(plane);
364
365 if (!psde->pipe_hw || !psde->pipe_sblk) {
366 SDE_ERROR("invalid arguments\n");
367 return;
368 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
369 return;
370 }
371
372 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
373 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
374 psde->pipe_qos_cfg.danger_vblank =
375 psde->pipe_sblk->danger_vblank;
376 psde->pipe_qos_cfg.vblank_en = enable;
377 }
378
379 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
380 /* this feature overrules previous VBLANK_CTRL */
381 psde->pipe_qos_cfg.vblank_en = false;
382 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
383 }
384
385 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
386 psde->pipe_qos_cfg.danger_safe_en = enable;
387
388 if (!psde->is_rt_pipe) {
389 psde->pipe_qos_cfg.vblank_en = false;
390 psde->pipe_qos_cfg.danger_safe_en = false;
391 }
392
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400393 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 -0400394 plane->base.id,
395 psde->pipe - SSPP_VIG0,
396 psde->pipe_qos_cfg.danger_safe_en,
397 psde->pipe_qos_cfg.vblank_en,
398 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400399 psde->pipe_qos_cfg.danger_vblank,
400 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400401
402 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
403 &psde->pipe_qos_cfg);
404}
405
Alan Kwong5d324e42016-07-28 22:56:18 -0400406/**
407 * _sde_plane_set_ot_limit - set OT limit for the given plane
408 * @plane: Pointer to drm plane
409 * @crtc: Pointer to drm crtc
410 */
411static void _sde_plane_set_ot_limit(struct drm_plane *plane,
412 struct drm_crtc *crtc)
413{
414 struct sde_plane *psde;
415 struct sde_vbif_set_ot_params ot_params;
416 struct msm_drm_private *priv;
417 struct sde_kms *sde_kms;
418
419 if (!plane || !plane->dev || !crtc) {
420 SDE_ERROR("invalid arguments plane %d crtc %d\n",
421 plane != 0, crtc != 0);
422 return;
423 }
424
425 priv = plane->dev->dev_private;
426 if (!priv || !priv->kms) {
427 SDE_ERROR("invalid KMS reference\n");
428 return;
429 }
430
431 sde_kms = to_sde_kms(priv->kms);
432 psde = to_sde_plane(plane);
433 if (!psde->pipe_hw) {
434 SDE_ERROR("invalid pipe reference\n");
435 return;
436 }
437
438 memset(&ot_params, 0, sizeof(ot_params));
439 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
440 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
441 ot_params.width = psde->pipe_cfg.src_rect.w;
442 ot_params.height = psde->pipe_cfg.src_rect.h;
443 ot_params.is_wfd = !psde->is_rt_pipe;
444 ot_params.frame_rate = crtc->mode.vrefresh;
445 ot_params.vbif_idx = VBIF_RT;
446 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
447 ot_params.rd = true;
448
449 sde_vbif_set_ot_limit(sde_kms, &ot_params);
450}
451
Clarence Ipcae1bb62016-07-07 12:07:13 -0400452/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400453static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400454 struct sde_plane_state *pstate, uint64_t fd)
455{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400456 if (!psde || !pstate) {
457 SDE_ERROR("invalid arg(s), plane %d state %d\n",
458 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400459 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400460 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400461
462 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400463 if (pstate->input_fence)
464 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400465
466 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400467 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400468
Clarence Ip13a8cf42016-09-29 17:27:47 -0400469 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400470}
471
Clarence Ipcae1bb62016-07-07 12:07:13 -0400472int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400473{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400474 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400475 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400476 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400477 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400478 int ret = -EINVAL;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400479
480 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700481 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400482 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400483 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400484 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400485 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400486 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400487 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400488
Clarence Ipcae1bb62016-07-07 12:07:13 -0400489 if (input_fence) {
Clarence Ip78a04ed2016-10-04 15:57:45 -0400490 prefix = sde_sync_get_name_prefix(input_fence);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400491 ret = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400492
493 MSM_EVT(plane->dev,
494 plane->base.id,
495 (uint64_t)-ret << (sizeof(uint32_t) * CHAR_BIT)
496 | prefix);
497
Clarence Ipcae1bb62016-07-07 12:07:13 -0400498 switch (ret) {
499 case 0:
Clarence Ip13a8cf42016-09-29 17:27:47 -0400500 SDE_DEBUG_PLANE(psde, "signaled\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400501 break;
502 case -ETIME:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400503 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
504 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400505 psde->is_error = true;
506 break;
507 default:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400508 SDE_ERROR_PLANE(psde, "error %d on %08X\n",
509 ret, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400510 psde->is_error = true;
511 break;
512 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400513 } else {
514 ret = 0;
515 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400516 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400517 return ret;
518}
519
Clarence Ip282dad62016-09-27 17:07:35 -0400520static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400521 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400522 struct sde_hw_pipe_cfg *pipe_cfg,
523 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400524{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400525 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400526 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400527
Clarence Ip13a8cf42016-09-29 17:27:47 -0400528 if (!plane || !pstate || !pipe_cfg || !fb) {
529 SDE_ERROR(
530 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
531 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400532 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400533 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400534
535 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400536 if (!psde->pipe_hw) {
537 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400538 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400539 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400540
Clarence Ipb6eb2362016-09-08 16:18:13 -0400541 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
542 if (ret == -EAGAIN)
543 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
544 else if (ret)
545 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
546 else if (psde->pipe_hw->ops.setup_sourceaddress)
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400547 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400548}
549
abeykun48f407a2016-08-25 12:06:44 -0400550static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
551 struct sde_plane_state *pstate)
552{
553 struct sde_hw_scaler3_cfg *cfg = psde->scaler3_cfg;
554 int ret = 0;
555
556 cfg->dir_lut = msm_property_get_blob(
557 &psde->property_info,
558 pstate->property_blobs, &cfg->dir_len,
559 PLANE_PROP_SCALER_LUT_ED);
560 cfg->cir_lut = msm_property_get_blob(
561 &psde->property_info,
562 pstate->property_blobs, &cfg->cir_len,
563 PLANE_PROP_SCALER_LUT_CIR);
564 cfg->sep_lut = msm_property_get_blob(
565 &psde->property_info,
566 pstate->property_blobs, &cfg->sep_len,
567 PLANE_PROP_SCALER_LUT_SEP);
568 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
569 ret = -ENODATA;
570 return ret;
571}
572
Clarence Ipcb410d42016-06-26 22:52:33 -0400573static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400574 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
575 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400576 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400577 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
578{
579}
580
Clarence Ipcb410d42016-06-26 22:52:33 -0400581/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400582 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400583 * @psde: Pointer to SDE plane object
584 * @src: Source size
585 * @dst: Destination size
586 * @phase_steps: Pointer to output array for phase steps
587 * @filter: Pointer to output array for filter type
588 * @fmt: Pointer to format definition
589 * @chroma_subsampling: Subsampling amount for chroma channel
590 *
591 * Returns: 0 on success
592 */
593static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400594 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400595 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400596 uint32_t chroma_subsampling)
597{
Clarence Ipcb410d42016-06-26 22:52:33 -0400598 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400599 SDE_ERROR(
600 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
601 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400602 return -EINVAL;
603 }
604
Clarence Ip4c1d9772016-06-26 09:35:38 -0400605 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400606 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400607 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400608 phase_steps[SDE_SSPP_COMP_1_2] =
609 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
610 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
611 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400612
613 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400614 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400615 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400616 (src <= dst) ? SDE_SCALE_FILTER_BIL :
617 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400618
Clarence Ipdbde9832016-06-26 09:48:36 -0400619 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400620 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400621 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
622 } else {
623 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
624 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400625 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400626 }
627 } else {
628 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400629 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
630 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
631 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400632 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400633 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400634}
635
Clarence Ipcb410d42016-06-26 22:52:33 -0400636/**
637 * _sde_plane_setup_pixel_ext - determine default pixel extension values
638 * @psde: Pointer to SDE plane object
639 * @src: Source size
640 * @dst: Destination size
641 * @decimated_src: Source size after decimation, if any
642 * @phase_steps: Pointer to output array for phase steps
643 * @out_src: Output array for pixel extension values
644 * @out_edge1: Output array for pixel extension first edge
645 * @out_edge2: Output array for pixel extension second edge
646 * @filter: Pointer to array for filter type
647 * @fmt: Pointer to format definition
648 * @chroma_subsampling: Subsampling amount for chroma channel
649 * @post_compare: Whether to chroma subsampled source size for comparisions
650 */
651static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400652 uint32_t src, uint32_t dst, uint32_t decimated_src,
653 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400654 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400655 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400656 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400657{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400658 int64_t edge1, edge2, caf;
659 uint32_t src_work;
660 int i, tmp;
661
Clarence Ipcb410d42016-06-26 22:52:33 -0400662 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400663 out_edge2 && filter && fmt) {
664 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400665 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400666 caf = PHASE_STEP_UNIT_SCALE;
667 else
668 caf = 0;
669
670 for (i = 0; i < SDE_MAX_PLANES; i++) {
671 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400672 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400673 src_work /= chroma_subsampling;
674 if (post_compare)
675 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400676 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400677 /* unity */
678 edge1 = 0;
679 edge2 = 0;
680 } else if (dst >= src) {
681 /* upscale */
682 edge1 = (1 << PHASE_RESIDUAL);
683 edge1 -= caf;
684 edge2 = (1 << PHASE_RESIDUAL);
685 edge2 += (dst - 1) * *(phase_steps + i);
686 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
687 edge2 += caf;
688 edge2 = -(edge2);
689 } else {
690 /* downscale */
691 edge1 = 0;
692 edge2 = (dst - 1) * *(phase_steps + i);
693 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
694 edge2 += *(phase_steps + i);
695 edge2 = -(edge2);
696 }
697
698 /* only enable CAF for luma plane */
699 caf = 0;
700
701 /* populate output arrays */
702 *(out_src + i) = src_work;
703
704 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400705 if (edge1 >= 0) {
706 tmp = (uint32_t)edge1;
707 tmp >>= PHASE_STEP_SHIFT;
708 *(out_edge1 + i) = -tmp;
709 } else {
710 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400711 *(out_edge1 + i) =
712 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
713 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400714 }
715 if (edge2 >= 0) {
716 tmp = (uint32_t)edge2;
717 tmp >>= PHASE_STEP_SHIFT;
718 *(out_edge2 + i) = -tmp;
719 } else {
720 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400721 *(out_edge2 + i) =
722 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
723 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400724 }
725 }
726 }
727}
728
Clarence Ip5fc00c52016-09-23 15:03:34 -0400729static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400730{
731 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
732 {
Clarence Ip373f8592016-05-26 00:58:42 -0400733 /* S15.16 format */
734 0x00012A00, 0x00000000, 0x00019880,
735 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
736 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400737 },
Clarence Ip373f8592016-05-26 00:58:42 -0400738 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400739 { 0xfff0, 0xff80, 0xff80,},
740 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400741 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400742 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400743 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400744 };
abeykun1c312f62016-08-26 09:47:12 -0400745 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
746 {
747 /* S15.16 format */
748 0x00012A00, 0x00000000, 0x00019880,
749 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
750 0x00012A00, 0x00020480, 0x00000000,
751 },
752 /* signed bias */
753 { 0xffc0, 0xfe00, 0xfe00,},
754 { 0x0, 0x0, 0x0,},
755 /* unsigned clamp */
756 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
757 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
758 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400759
Clarence Ip5fc00c52016-09-23 15:03:34 -0400760 if (!psde) {
761 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400762 return;
763 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400764
Clarence Ipcae1bb62016-07-07 12:07:13 -0400765 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400766 if (psde->csc_usr_ptr)
767 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400768 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
769 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400770 else
Clarence Ip373f8592016-05-26 00:58:42 -0400771 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400772
Clarence Ip13a8cf42016-09-29 17:27:47 -0400773 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400774 psde->csc_ptr->csc_mv[0],
775 psde->csc_ptr->csc_mv[1],
776 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -0400777}
778
Clarence Ipcb410d42016-06-26 22:52:33 -0400779static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400780 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -0400781 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700782{
Clarence Ipb43d4592016-09-08 14:21:35 -0400783 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -0400784 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Clarence Ipb43d4592016-09-08 14:21:35 -0400785 uint32_t tmp, i;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400786
Clarence Ipb43d4592016-09-08 14:21:35 -0400787 if (!psde || !fmt) {
788 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
789 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400790 return;
Clarence Ipb43d4592016-09-08 14:21:35 -0400791 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400792
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400793 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400794
Clarence Ipdedbba92016-09-27 17:43:10 -0400795 psde->pipe_cfg.horz_decimation =
796 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
797 psde->pipe_cfg.vert_decimation =
798 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400799
800 /* don't chroma subsample if decimating */
801 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400802 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400803 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400804 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -0400805
Clarence Ip5e2a9222016-06-26 22:38:24 -0400806 /* update scaler */
807 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -0400808 int error;
809
810 error = _sde_plane_setup_scaler3_lut(psde, pstate);
811 if (error || !psde->pixel_ext_usr) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400812 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -0400813 _sde_plane_setup_scaler3(psde,
814 psde->pipe_cfg.src_rect.w,
815 psde->pipe_cfg.src_rect.h,
816 psde->pipe_cfg.dst_rect.w,
817 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -0400818 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400819 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400820 }
Clarence Ipb43d4592016-09-08 14:21:35 -0400821 } else if (!psde->pixel_ext_usr) {
822 /* calculate default configuration for QSEED2 */
823 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400824
Clarence Ip13a8cf42016-09-29 17:27:47 -0400825 SDE_DEBUG_PLANE(psde, "default config\n");
Clarence Ipb43d4592016-09-08 14:21:35 -0400826 _sde_plane_setup_scaler2(psde,
827 psde->pipe_cfg.src_rect.w,
828 psde->pipe_cfg.dst_rect.w,
829 pe->phase_step_x,
830 pe->horz_filter, fmt, chroma_subsmpl_h);
831 _sde_plane_setup_scaler2(psde,
832 psde->pipe_cfg.src_rect.h,
833 psde->pipe_cfg.dst_rect.h,
834 pe->phase_step_y,
835 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -0400836
Clarence Ip5e2a9222016-06-26 22:38:24 -0400837 /* calculate left/right/top/bottom pixel extensions */
Clarence Ipcb410d42016-06-26 22:52:33 -0400838 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400839 psde->pipe_cfg.horz_decimation);
Clarence Ipdbde9832016-06-26 09:48:36 -0400840 if (SDE_FORMAT_IS_YUV(fmt))
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400841 tmp &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -0400842 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
843 psde->pipe_cfg.dst_rect.w, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400844 pe->phase_step_x,
845 pe->roi_w,
846 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -0400847 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400848 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400849
Clarence Ipcb410d42016-06-26 22:52:33 -0400850 tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400851 psde->pipe_cfg.vert_decimation);
Clarence Ipcb410d42016-06-26 22:52:33 -0400852 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
853 psde->pipe_cfg.dst_rect.h, tmp,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400854 pe->phase_step_y,
855 pe->roi_h,
856 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -0400857 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400858 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400859
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400860 for (i = 0; i < SDE_MAX_PLANES; i++) {
861 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400862 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400863 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400864 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400865
866 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400867 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400868 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400869 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400870
871 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400872 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400873 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400874 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400875
876 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -0400877 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400878 else
Clarence Ipb43d4592016-09-08 14:21:35 -0400879 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400880 }
881 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400882}
883
Clarence Ipcae1bb62016-07-07 12:07:13 -0400884/**
885 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -0400886 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -0400887 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
888 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
889 * Returns: 0 on success
890 */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400891static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -0400892 uint32_t color, uint32_t alpha)
893{
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400894 const struct sde_format *fmt;
Clarence Ipcb410d42016-06-26 22:52:33 -0400895
Clarence Ip13a8cf42016-09-29 17:27:47 -0400896 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700897 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400898 return -EINVAL;
899 }
900
Clarence Ipcb410d42016-06-26 22:52:33 -0400901 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400902 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400903 return -EINVAL;
904 }
905
Clarence Ip13a8cf42016-09-29 17:27:47 -0400906 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400907
Clarence Ipcb410d42016-06-26 22:52:33 -0400908 /*
909 * select fill format to match user property expectation,
910 * h/w only supports RGB variants
911 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400912 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -0400913
914 /* update sspp */
915 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
916 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
917 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
918
919 /* override scaler/decimation if solid fill */
920 psde->pipe_cfg.src_rect.x = 0;
921 psde->pipe_cfg.src_rect.y = 0;
922 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
923 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
924
925 _sde_plane_setup_scaler(psde, fmt, 0);
926
927 if (psde->pipe_hw->ops.setup_format)
928 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
929 fmt, SDE_SSPP_SOLID_FILL);
930
931 if (psde->pipe_hw->ops.setup_rects)
932 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -0400933 &psde->pipe_cfg, &psde->pixel_ext,
934 psde->scaler3_cfg);
Clarence Ipcb410d42016-06-26 22:52:33 -0400935 }
936
937 return 0;
938}
939
940static int _sde_plane_mode_set(struct drm_plane *plane,
Dhaval Patel47302cf2016-08-18 15:04:28 -0700941 struct drm_plane_state *state)
Clarence Ipcb410d42016-06-26 22:52:33 -0400942{
Clarence Ipc47a0692016-10-11 10:54:17 -0400943 uint32_t nplanes, src_flags;
Clarence Ipcb410d42016-06-26 22:52:33 -0400944 struct sde_plane *psde;
945 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400946 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -0700947 struct drm_crtc *crtc;
948 struct drm_framebuffer *fb;
949 struct sde_rect src, dst;
950 bool q16_data = true;
Clarence Ip282dad62016-09-27 17:07:35 -0400951 int idx;
Clarence Ipcb410d42016-06-26 22:52:33 -0400952
Clarence Ip13a8cf42016-09-29 17:27:47 -0400953 if (!plane) {
Clarence Ip282dad62016-09-27 17:07:35 -0400954 SDE_ERROR("invalid plane\n");
955 return -EINVAL;
956 } else if (!plane->state) {
957 SDE_ERROR("invalid plane state\n");
Clarence Ipcb410d42016-06-26 22:52:33 -0400958 return -EINVAL;
959 }
960
961 psde = to_sde_plane(plane);
962 pstate = to_sde_plane_state(plane->state);
Clarence Ipcb410d42016-06-26 22:52:33 -0400963
Dhaval Patel47302cf2016-08-18 15:04:28 -0700964 crtc = state->crtc;
965 fb = state->fb;
966 if (!crtc || !fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400967 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
968 crtc != 0, fb != 0);
Dhaval Patel47302cf2016-08-18 15:04:28 -0700969 return -EINVAL;
970 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400971 fmt = to_sde_format(msm_framebuffer_format(fb));
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400972 nplanes = fmt->num_planes;
Clarence Ipcb410d42016-06-26 22:52:33 -0400973
Clarence Ip282dad62016-09-27 17:07:35 -0400974 /* determine what needs to be refreshed */
975 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
976 switch (idx) {
Clarence Ipb43d4592016-09-08 14:21:35 -0400977 case PLANE_PROP_SCALER_V1:
abeykun48f407a2016-08-25 12:06:44 -0400978 case PLANE_PROP_SCALER_V2:
Clarence Ipdedbba92016-09-27 17:43:10 -0400979 case PLANE_PROP_H_DECIMATE:
980 case PLANE_PROP_V_DECIMATE:
981 case PLANE_PROP_SRC_CONFIG:
982 case PLANE_PROP_ZPOS:
Clarence Ip282dad62016-09-27 17:07:35 -0400983 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
984 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400985 case PLANE_PROP_CSC_V1:
Clarence Ip282dad62016-09-27 17:07:35 -0400986 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
987 break;
988 case PLANE_PROP_COLOR_FILL:
989 /* potentially need to refresh everything */
990 pstate->dirty = SDE_PLANE_DIRTY_ALL;
991 break;
992 case PLANE_PROP_ROTATION:
993 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
994 break;
Clarence Ip282dad62016-09-27 17:07:35 -0400995 case PLANE_PROP_INFO:
996 case PLANE_PROP_ALPHA:
997 case PLANE_PROP_INPUT_FENCE:
998 case PLANE_PROP_BLEND_OP:
999 /* no special action required */
1000 break;
1001 default:
1002 /* unknown property, refresh everything */
1003 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
1004 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
1005 break;
1006 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001007 }
1008
Clarence Ip282dad62016-09-27 17:07:35 -04001009 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
1010 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
Clarence Ipcb410d42016-06-26 22:52:33 -04001011
1012 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
1013
Clarence Ip282dad62016-09-27 17:07:35 -04001014 /* early out if nothing dirty */
1015 if (!pstate->dirty)
1016 return 0;
1017 pstate->pending = true;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001018
Clarence Ip0d0e96d2016-10-24 18:13:13 -04001019 psde->is_rt_pipe = sde_crtc_is_rt(crtc);
Clarence Ip282dad62016-09-27 17:07:35 -04001020 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1021
1022 /* update roi config */
1023 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
1024 POPULATE_RECT(&src, state->src_x, state->src_y,
1025 state->src_w, state->src_h, q16_data);
1026 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
1027 state->crtc_w, state->crtc_h, !q16_data);
1028
Clarence Ip13a8cf42016-09-29 17:27:47 -04001029 SDE_DEBUG_PLANE(psde,
1030 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %s ubwc %d\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001031 fb->base.id, src.x, src.y, src.w, src.h,
1032 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
1033 drm_get_format_name(fmt->base.pixel_format),
1034 SDE_FORMAT_IS_UBWC(fmt));
1035
1036 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
1037 BIT(SDE_DRM_DEINTERLACE)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001038 SDE_DEBUG_PLANE(psde, "deinterlace\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001039 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
1040 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
1041 src.h /= 2;
1042 src.y = DIV_ROUND_UP(src.y, 2);
1043 src.y &= ~0x1;
1044 }
1045
1046 psde->pipe_cfg.src_rect = src;
1047 psde->pipe_cfg.dst_rect = dst;
1048
1049 /* check for color fill */
1050 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
1051 PLANE_PROP_COLOR_FILL);
1052 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
1053 /* skip remaining processing on color fill */
1054 pstate->dirty = 0x0;
1055 } else if (psde->pipe_hw->ops.setup_rects) {
1056 _sde_plane_setup_scaler(psde, fmt, pstate);
1057
Clarence Ip282dad62016-09-27 17:07:35 -04001058 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
abeykun48f407a2016-08-25 12:06:44 -04001059 &psde->pipe_cfg, &psde->pixel_ext,
1060 psde->scaler3_cfg);
Clarence Ip282dad62016-09-27 17:07:35 -04001061 }
Dhaval Patel48c76022016-09-01 17:51:23 -07001062 }
1063
Clarence Ip282dad62016-09-27 17:07:35 -04001064 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
1065 psde->pipe_hw->ops.setup_format) {
1066 src_flags = 0x0;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001067 SDE_DEBUG_PLANE(psde, "rotation 0x%llX\n",
Clarence Ip282dad62016-09-27 17:07:35 -04001068 sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
1069 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1070 BIT(DRM_REFLECT_X))
1071 src_flags |= SDE_SSPP_FLIP_LR;
1072 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
1073 BIT(DRM_REFLECT_Y))
1074 src_flags |= SDE_SSPP_FLIP_UD;
1075
1076 /* update format */
1077 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags);
1078
1079 /* update csc */
1080 if (SDE_FORMAT_IS_YUV(fmt))
Clarence Ip5fc00c52016-09-23 15:03:34 -04001081 _sde_plane_setup_csc(psde);
Clarence Ip282dad62016-09-27 17:07:35 -04001082 else
1083 psde->csc_ptr = 0;
1084 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001085
Clarence Ipe78efb72016-06-24 18:35:21 -04001086 /* update sharpening */
Clarence Ip282dad62016-09-27 17:07:35 -04001087 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
1088 psde->pipe_hw->ops.setup_sharpening) {
1089 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
1090 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
1091 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
1092 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
Clarence Ipe78efb72016-06-24 18:35:21 -04001093
Clarence Ipe78efb72016-06-24 18:35:21 -04001094 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
Clarence Ip282dad62016-09-27 17:07:35 -04001095 &psde->sharp_cfg);
1096 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001097
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001098 _sde_plane_set_qos_lut(plane, fb);
1099 _sde_plane_set_danger_lut(plane, fb);
1100
Alan Kwong5d324e42016-07-28 22:56:18 -04001101 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001102 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
Alan Kwong5d324e42016-07-28 22:56:18 -04001103 _sde_plane_set_ot_limit(plane, crtc);
1104 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001105
Clarence Ip282dad62016-09-27 17:07:35 -04001106 /* clear dirty */
1107 pstate->dirty = 0x0;
1108
Clarence Ip5e2a9222016-06-26 22:38:24 -04001109 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001110}
1111
1112static int sde_plane_prepare_fb(struct drm_plane *plane,
1113 const struct drm_plane_state *new_state)
1114{
1115 struct drm_framebuffer *fb = new_state->fb;
1116 struct sde_plane *psde = to_sde_plane(plane);
1117
1118 if (!new_state->fb)
1119 return 0;
1120
Clarence Ip13a8cf42016-09-29 17:27:47 -04001121 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001122 return msm_framebuffer_prepare(fb, psde->mmu_id);
1123}
1124
1125static void sde_plane_cleanup_fb(struct drm_plane *plane,
1126 const struct drm_plane_state *old_state)
1127{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001128 struct drm_framebuffer *fb = old_state ? old_state->fb : NULL;
1129 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001130
1131 if (!fb)
1132 return;
1133
Clarence Ip13a8cf42016-09-29 17:27:47 -04001134 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001135 msm_framebuffer_cleanup(fb, psde->mmu_id);
1136}
1137
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001138static void _sde_plane_atomic_check_mode_changed(struct sde_plane *psde,
1139 struct drm_plane_state *state,
1140 struct drm_plane_state *old_state)
1141{
1142 struct sde_plane_state *pstate = to_sde_plane_state(state);
1143
Dhaval Patel47302cf2016-08-18 15:04:28 -07001144 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04001145 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001146 return;
1147
Clarence Ip282dad62016-09-27 17:07:35 -04001148 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
1149 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001150 SDE_DEBUG_PLANE(psde,
1151 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001152 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001153 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001154 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001155 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001156 } else if (state->src_w != old_state->src_w ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07001157 state->src_h != old_state->src_h ||
1158 state->src_x != old_state->src_x ||
1159 state->src_y != old_state->src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001160 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001161 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001162 } else if (state->crtc_w != old_state->crtc_w ||
1163 state->crtc_h != old_state->crtc_h ||
1164 state->crtc_x != old_state->crtc_x ||
1165 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001166 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001167 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
1168 }
1169
1170 if (!state->fb || !old_state->fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001171 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001172 } else if (state->fb->pixel_format != old_state->fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001173 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04001174 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001175 } else {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001176 uint64_t *new_mods = state->fb->modifier;
1177 uint64_t *old_mods = old_state->fb->modifier;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001178 uint32_t *new_pitches = state->fb->pitches;
1179 uint32_t *old_pitches = old_state->fb->pitches;
1180 uint32_t *new_offset = state->fb->offsets;
1181 uint32_t *old_offset = old_state->fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001182 int i;
1183
1184 for (i = 0; i < ARRAY_SIZE(state->fb->modifier); i++) {
1185 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001186 SDE_DEBUG_PLANE(psde,
1187 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001188 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001189 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001190 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1191 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001192 break;
1193 }
1194 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001195 for (i = 0; i < ARRAY_SIZE(state->fb->pitches); i++) {
1196 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001197 SDE_DEBUG_PLANE(psde,
1198 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001199 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001200 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001201 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001202 break;
1203 }
1204 }
Dhaval Patel47302cf2016-08-18 15:04:28 -07001205 for (i = 0; i < ARRAY_SIZE(state->fb->offsets); i++) {
1206 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001207 SDE_DEBUG_PLANE(psde,
1208 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07001209 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04001210 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04001211 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
1212 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001213 break;
1214 }
1215 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04001216 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001217}
1218
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001219static int sde_plane_atomic_check(struct drm_plane *plane,
1220 struct drm_plane_state *state)
1221{
Clarence Ipdedbba92016-09-27 17:43:10 -04001222 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04001223 struct sde_plane *psde;
1224 struct sde_plane_state *pstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001225 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001226 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04001227 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001228 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
1229 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04001230
1231 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001232 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1233 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04001234 ret = -EINVAL;
1235 goto exit;
1236 }
1237
1238 psde = to_sde_plane(plane);
1239 pstate = to_sde_plane_state(state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001240
1241 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001242 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001243 ret = -EINVAL;
1244 goto exit;
1245 }
1246
Clarence Ipdedbba92016-09-27 17:43:10 -04001247 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1248 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04001249
1250 /* src values are in Q16 fixed point, convert to integer */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001251 POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w,
1252 state->src_h, q16_data);
1253 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
1254 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04001255
Dhaval Patel47302cf2016-08-18 15:04:28 -07001256 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
1257 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04001258
Dhaval Patel47302cf2016-08-18 15:04:28 -07001259 max_upscale = psde->pipe_sblk->maxupscale;
1260 max_downscale = psde->pipe_sblk->maxdwnscale;
1261 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04001262
Clarence Ip13a8cf42016-09-29 17:27:47 -04001263 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001264 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001265
Dhaval Patel47302cf2016-08-18 15:04:28 -07001266 if (!sde_plane_enabled(state))
1267 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04001268
Dhaval Patel47302cf2016-08-18 15:04:28 -07001269 fmt = to_sde_format(msm_framebuffer_format(state->fb));
1270
1271 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
1272
1273 if (SDE_FORMAT_IS_YUV(fmt) &&
1274 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04001275 !(psde->features & (BIT(SDE_SSPP_CSC)
1276 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001277 SDE_ERROR_PLANE(psde,
1278 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07001279 ret = -EINVAL;
1280
1281 /* check src bounds */
1282 } else if (state->fb->width > MAX_IMG_WIDTH ||
1283 state->fb->height > MAX_IMG_HEIGHT ||
1284 src.w < min_src_size || src.h < min_src_size ||
1285 CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) ||
1286 CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001287 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001288 src.x, src.y, src.w, src.h);
1289 ret = -E2BIG;
1290
1291 /* valid yuv image */
1292 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
1293 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001294 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001295 src.x, src.y, src.w, src.h);
1296 ret = -EINVAL;
1297
1298 /* min dst support */
1299 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001300 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001301 dst.x, dst.y, dst.w, dst.h);
1302 ret = -EINVAL;
1303
1304 /* decimation validation */
1305 } else if (deci_w || deci_h) {
1306 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
1307 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001308 SDE_ERROR_PLANE(psde,
1309 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001310 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07001311 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001312 SDE_ERROR_PLANE(psde,
1313 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04001314 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001315 }
1316
Dhaval Patel47302cf2016-08-18 15:04:28 -07001317 } else if (!(psde->features & SDE_SSPP_SCALER) &&
1318 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001319 SDE_ERROR_PLANE(psde,
1320 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001321 src.w, src.h, dst.w, dst.h);
1322 ret = -EINVAL;
1323
1324 /* check decimated source width */
1325 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001326 SDE_ERROR_PLANE(psde,
1327 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001328 src.w, src_deci_w, max_linewidth);
1329 ret = -E2BIG;
1330
1331 /* check max scaler capability */
1332 } else if (((src_deci_w * max_upscale) < dst.w) ||
1333 ((src_deci_h * max_upscale) < dst.h) ||
1334 ((dst.w * max_downscale) < src_deci_w) ||
1335 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001336 SDE_ERROR_PLANE(psde,
1337 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001338 src_deci_w, src_deci_h, dst.w, dst.h);
1339 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001340 }
1341
Dhaval Patel47302cf2016-08-18 15:04:28 -07001342modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001343 if (!ret)
Dhaval Patel47302cf2016-08-18 15:04:28 -07001344 _sde_plane_atomic_check_mode_changed(psde, state, plane->state);
Clarence Ipdbde9832016-06-26 09:48:36 -04001345exit:
1346 return ret;
1347}
1348
Clarence Ipcae1bb62016-07-07 12:07:13 -04001349/**
1350 * sde_plane_flush - final plane operations before commit flush
1351 * @plane: Pointer to drm plane structure
1352 */
1353void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04001354{
Clarence Ipcae1bb62016-07-07 12:07:13 -04001355 struct sde_plane *psde;
1356
Clarence Ip13a8cf42016-09-29 17:27:47 -04001357 if (!plane) {
1358 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001359 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001360 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04001361
1362 psde = to_sde_plane(plane);
1363
1364 /*
1365 * These updates have to be done immediately before the plane flush
1366 * timing, and may not be moved to the atomic_update/mode_set functions.
1367 */
1368 if (psde->is_error)
1369 /* force white frame with 0% alpha pipe output on error */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001370 _sde_plane_color_fill(psde, 0xFFFFFF, 0x0);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001371 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
1372 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001373 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04001374 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
1375 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
1376
1377 /* flag h/w flush complete */
1378 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04001379 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001380}
1381
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001382static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04001383 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001384{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001385 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001386 struct drm_plane_state *state;
1387 struct sde_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001388
Clarence Ip13a8cf42016-09-29 17:27:47 -04001389 if (!plane) {
1390 SDE_ERROR("invalid plane\n");
1391 return;
1392 } else if (!plane->state) {
1393 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04001394 return;
1395 }
1396
Clarence Ip13a8cf42016-09-29 17:27:47 -04001397 psde = to_sde_plane(plane);
1398 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001399 state = plane->state;
1400 pstate = to_sde_plane_state(state);
1401
Clarence Ip13a8cf42016-09-29 17:27:47 -04001402 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001403
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001404 if (!sde_plane_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04001405 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04001406 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001407 int ret;
1408
Dhaval Patel47302cf2016-08-18 15:04:28 -07001409 ret = _sde_plane_mode_set(plane, state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001410 /* atomic_check should have ensured that this doesn't fail */
1411 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001412 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001413}
1414
Dhaval Patel47302cf2016-08-18 15:04:28 -07001415
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001416/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07001417static void _sde_plane_install_properties(struct drm_plane *plane,
Clarence Ipc47a0692016-10-11 10:54:17 -04001418 struct sde_mdss_cfg *catalog)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001419{
Clarence Ip5e2a9222016-06-26 22:38:24 -04001420 static const struct drm_prop_enum_list e_blend_op[] = {
1421 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
1422 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
1423 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
1424 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
1425 };
1426 static const struct drm_prop_enum_list e_src_config[] = {
1427 {SDE_DRM_DEINTERLACE, "deinterlace"}
1428 };
Clarence Ipea3d6262016-07-15 16:20:11 -04001429 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07001430 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001431 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04001432 int zpos_max = 255;
1433 int zpos_def = 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001434
Clarence Ip13a8cf42016-09-29 17:27:47 -04001435 if (!plane || !psde) {
1436 SDE_ERROR("invalid plane\n");
1437 return;
1438 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
1439 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
1440 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001441 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04001442 } else if (!catalog) {
1443 SDE_ERROR("invalid catalog\n");
1444 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001445 }
1446
Clarence Ipc47a0692016-10-11 10:54:17 -04001447 if (sde_is_custom_client()) {
1448 if (catalog->mixer_count && catalog->mixer)
1449 zpos_max = catalog->mixer[0].sblk->maxblendstages;
1450 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
1451 /* reserve zpos == 0 for primary planes */
1452 zpos_def = drm_plane_index(plane) + 1;
1453 }
1454
1455 msm_property_install_range(&psde->property_info, "zpos",
1456 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001457
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001458 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07001459 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001460
Dhaval Patel47302cf2016-08-18 15:04:28 -07001461 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001462 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07001463 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001464
Clarence Ipdedbba92016-09-27 17:43:10 -04001465 if (psde->pipe_sblk->maxhdeciexp) {
1466 msm_property_install_range(&psde->property_info, "h_decimate",
1467 0x0, 0, psde->pipe_sblk->maxhdeciexp, 0,
1468 PLANE_PROP_H_DECIMATE);
1469 }
1470
1471 if (psde->pipe_sblk->maxvdeciexp) {
1472 msm_property_install_range(&psde->property_info, "v_decimate",
1473 0x0, 0, psde->pipe_sblk->maxvdeciexp, 0,
1474 PLANE_PROP_V_DECIMATE);
1475 }
1476
abeykun48f407a2016-08-25 12:06:44 -04001477 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
1478 msm_property_install_volatile_range(&psde->property_info,
1479 "scaler_v2", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
1480 msm_property_install_blob(&psde->property_info, "lut_ed", 0,
1481 PLANE_PROP_SCALER_LUT_ED);
1482 msm_property_install_blob(&psde->property_info, "lut_cir", 0,
1483 PLANE_PROP_SCALER_LUT_CIR);
1484 msm_property_install_blob(&psde->property_info, "lut_sep", 0,
1485 PLANE_PROP_SCALER_LUT_SEP);
1486 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001487 msm_property_install_volatile_range(&psde->property_info,
1488 "scaler_v1", 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V1);
1489 }
1490
Clarence Ip5fc00c52016-09-23 15:03:34 -04001491 if (psde->features & BIT(SDE_SSPP_CSC)) {
1492 msm_property_install_volatile_range(&psde->property_info,
1493 "csc_v1", 0x0, 0, ~0, 0, PLANE_PROP_CSC_V1);
1494 }
1495
Clarence Ip5e2a9222016-06-26 22:38:24 -04001496 /* standard properties */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001497 msm_property_install_rotation(&psde->property_info,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001498 BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y), PLANE_PROP_ROTATION);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001499
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04001500 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07001501 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001502
Dhaval Patel47302cf2016-08-18 15:04:28 -07001503 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
1504 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
1505
1506 if (psde->pipe_hw->ops.setup_solidfill)
1507 msm_property_install_range(&psde->property_info, "color_fill",
1508 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
1509
Dhaval Patel4e574842016-08-23 15:11:37 -07001510 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001511 if (!info) {
1512 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07001513 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001514 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001515
1516 msm_property_install_blob(&psde->property_info, "capabilities",
1517 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
1518 sde_kms_info_reset(info);
1519
Clarence Ipea3d6262016-07-15 16:20:11 -04001520 format_list = psde->pipe_sblk->format_list;
1521 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04001522 sde_kms_info_start(info, "pixel_formats");
1523 while (format_list->fourcc_format) {
1524 sde_kms_info_append_format(info,
1525 format_list->fourcc_format,
1526 format_list->modifier);
1527 ++format_list;
1528 }
1529 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04001530 }
Dhaval Patel4e574842016-08-23 15:11:37 -07001531
1532 sde_kms_info_add_keyint(info, "max_linewidth",
1533 psde->pipe_sblk->maxlinewidth);
1534 sde_kms_info_add_keyint(info, "max_upscale",
1535 psde->pipe_sblk->maxupscale);
1536 sde_kms_info_add_keyint(info, "max_downscale",
1537 psde->pipe_sblk->maxdwnscale);
1538 sde_kms_info_add_keyint(info, "max_horizontal_deci",
1539 psde->pipe_sblk->maxhdeciexp);
1540 sde_kms_info_add_keyint(info, "max_vertical_deci",
1541 psde->pipe_sblk->maxvdeciexp);
1542 msm_property_set_blob(&psde->property_info, &psde->blob_info,
1543 info->data, info->len, PLANE_PROP_INFO);
1544
1545 kfree(info);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001546}
1547
Clarence Ip5fc00c52016-09-23 15:03:34 -04001548static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
1549{
1550 struct sde_drm_csc_v1 csc_v1;
1551 int i;
1552
1553 if (!psde) {
1554 SDE_ERROR("invalid plane\n");
1555 return;
1556 }
1557
1558 psde->csc_usr_ptr = NULL;
1559 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001560 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001561 return;
1562 }
1563
1564 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001565 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04001566 return;
1567 }
1568
Clarence Ipb43d4592016-09-08 14:21:35 -04001569 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001570 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
1571 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
1572 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
1573 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
1574 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
1575 }
1576 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
1577 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
1578 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
1579 }
1580 psde->csc_usr_ptr = &psde->csc_cfg;
1581}
1582
Clarence Ipb43d4592016-09-08 14:21:35 -04001583static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
1584{
1585 struct sde_drm_scaler_v1 scale_v1;
1586 struct sde_hw_pixel_ext *pe;
1587 int i;
1588
1589 if (!psde) {
1590 SDE_ERROR("invalid plane\n");
1591 return;
1592 }
1593
1594 psde->pixel_ext_usr = false;
1595 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001596 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001597 return;
1598 }
1599
1600 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001601 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001602 return;
1603 }
1604
1605 /* populate from user space */
1606 pe = &(psde->pixel_ext);
1607 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1608 for (i = 0; i < SDE_MAX_PLANES; i++) {
1609 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
1610 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
1611 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
1612 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
1613
1614 pe->horz_filter[i] = scale_v1.horz_filter[i];
1615 pe->vert_filter[i] = scale_v1.vert_filter[i];
1616 }
1617 for (i = 0; i < SDE_MAX_PLANES; i++) {
1618 pe->num_ext_pxls_left[i] = scale_v1.lr.num_pxls_start[i];
1619 pe->num_ext_pxls_right[i] = scale_v1.lr.num_pxls_end[i];
1620 pe->left_ftch[i] = scale_v1.lr.ftch_start[i];
1621 pe->right_ftch[i] = scale_v1.lr.ftch_end[i];
1622 pe->left_rpt[i] = scale_v1.lr.rpt_start[i];
1623 pe->right_rpt[i] = scale_v1.lr.rpt_end[i];
1624 pe->roi_w[i] = scale_v1.lr.roi[i];
1625
1626 pe->num_ext_pxls_top[i] = scale_v1.tb.num_pxls_start[i];
1627 pe->num_ext_pxls_btm[i] = scale_v1.tb.num_pxls_end[i];
1628 pe->top_ftch[i] = scale_v1.tb.ftch_start[i];
1629 pe->btm_ftch[i] = scale_v1.tb.ftch_end[i];
1630 pe->top_rpt[i] = scale_v1.tb.rpt_start[i];
1631 pe->btm_rpt[i] = scale_v1.tb.rpt_end[i];
1632 pe->roi_h[i] = scale_v1.tb.roi[i];
1633 }
1634 psde->pixel_ext_usr = true;
1635
Clarence Ip13a8cf42016-09-29 17:27:47 -04001636 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04001637}
1638
abeykun48f407a2016-08-25 12:06:44 -04001639static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
1640 struct sde_plane_state *pstate, void *usr)
1641{
1642 struct sde_drm_scaler_v2 scale_v2;
1643 struct sde_hw_pixel_ext *pe;
1644 int i;
1645 struct sde_hw_scaler3_cfg *cfg;
1646
1647 if (!psde) {
1648 SDE_ERROR("invalid plane\n");
1649 return;
1650 }
1651
1652 cfg = psde->scaler3_cfg;
1653 psde->pixel_ext_usr = false;
1654 if (!usr) {
1655 SDE_DEBUG_PLANE(psde, "scale data removed\n");
1656 return;
1657 }
1658
1659 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
1660 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
1661 return;
1662 }
1663
1664 /* populate from user space */
1665 pe = &(psde->pixel_ext);
1666 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
1667 cfg->enable = scale_v2.enable;
1668 cfg->dir_en = scale_v2.dir_en;
1669 for (i = 0; i < SDE_MAX_PLANES; i++) {
1670 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
1671 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
1672 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
1673 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
1674
1675 cfg->preload_x[i] = scale_v2.preload_x[i];
1676 cfg->preload_y[i] = scale_v2.preload_y[i];
1677 cfg->src_width[i] = scale_v2.src_width[i];
1678 cfg->src_height[i] = scale_v2.src_height[i];
1679 }
1680 cfg->dst_width = scale_v2.dst_width;
1681 cfg->dst_height = scale_v2.dst_height;
1682
1683 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
1684 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
1685 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
1686 cfg->blend_cfg = scale_v2.blend_cfg;
1687
1688 cfg->lut_flag = scale_v2.lut_flag;
1689 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
1690 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
1691 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
1692 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
1693 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
1694
1695 cfg->de.enable = scale_v2.de.enable;
1696 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
1697 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
1698 cfg->de.clip = scale_v2.de.clip;
1699 cfg->de.limit = scale_v2.de.limit;
1700 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
1701 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
1702 cfg->de.thr_low = scale_v2.de.thr_low;
1703 cfg->de.thr_high = scale_v2.de.thr_high;
1704 cfg->de.prec_shift = scale_v2.de.prec_shift;
1705 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
1706 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
1707 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
1708 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
1709 }
1710 for (i = 0; i < SDE_MAX_PLANES; i++) {
1711 pe->num_ext_pxls_left[i] = scale_v2.lr.num_pxls_start[i];
1712 pe->num_ext_pxls_right[i] = scale_v2.lr.num_pxls_end[i];
1713 pe->left_ftch[i] = scale_v2.lr.ftch_start[i];
1714 pe->right_ftch[i] = scale_v2.lr.ftch_end[i];
1715 pe->left_rpt[i] = scale_v2.lr.rpt_start[i];
1716 pe->right_rpt[i] = scale_v2.lr.rpt_end[i];
1717 pe->roi_w[i] = scale_v2.lr.roi[i];
1718
1719 pe->num_ext_pxls_top[i] = scale_v2.tb.num_pxls_start[i];
1720 pe->num_ext_pxls_btm[i] = scale_v2.tb.num_pxls_end[i];
1721 pe->top_ftch[i] = scale_v2.tb.ftch_start[i];
1722 pe->btm_ftch[i] = scale_v2.tb.ftch_end[i];
1723 pe->top_rpt[i] = scale_v2.tb.rpt_start[i];
1724 pe->btm_rpt[i] = scale_v2.tb.rpt_end[i];
1725 pe->roi_h[i] = scale_v2.tb.roi[i];
1726 }
1727 psde->pixel_ext_usr = true;
1728
1729 SDE_DEBUG_PLANE(psde, "user property data copied\n");
1730}
1731
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001732static int sde_plane_atomic_set_property(struct drm_plane *plane,
1733 struct drm_plane_state *state, struct drm_property *property,
1734 uint64_t val)
1735{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001736 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001737 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001738 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001739
Clarence Ip13a8cf42016-09-29 17:27:47 -04001740 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001741
1742 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001743 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001744 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001745 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001746 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04001747 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001748 ret = msm_property_atomic_set(&psde->property_info,
1749 pstate->property_values, pstate->property_blobs,
1750 property, val);
1751 if (!ret) {
1752 idx = msm_property_index(&psde->property_info,
1753 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001754 switch (idx) {
1755 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04001756 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04001757 break;
1758 case PLANE_PROP_CSC_V1:
1759 _sde_plane_set_csc_v1(psde, (void *)val);
1760 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04001761 case PLANE_PROP_SCALER_V1:
1762 _sde_plane_set_scaler_v1(psde, (void *)val);
1763 break;
abeykun48f407a2016-08-25 12:06:44 -04001764 case PLANE_PROP_SCALER_V2:
1765 _sde_plane_set_scaler_v2(psde, pstate,
1766 (void *)val);
1767 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001768 default:
1769 /* nothing to do */
1770 break;
1771 }
Clarence Ipe78efb72016-06-24 18:35:21 -04001772 }
1773 }
1774
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001775 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001776}
1777
1778static int sde_plane_set_property(struct drm_plane *plane,
1779 struct drm_property *property, uint64_t val)
1780{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001781 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001782
Clarence Ipae4e60c2016-06-26 22:44:04 -04001783 return sde_plane_atomic_set_property(plane,
1784 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001785}
1786
1787static int sde_plane_atomic_get_property(struct drm_plane *plane,
1788 const struct drm_plane_state *state,
1789 struct drm_property *property, uint64_t *val)
1790{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001791 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001792 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04001793 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001794
Clarence Ipaa0faf42016-05-30 12:07:48 -04001795 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001796 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001797 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001798 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001799 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001800 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04001801 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001802 ret = msm_property_atomic_get(&psde->property_info,
1803 pstate->property_values, pstate->property_blobs,
1804 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04001805 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001806
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001807 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001808}
1809
1810static void sde_plane_destroy(struct drm_plane *plane)
1811{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001812 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001813
Clarence Ip13a8cf42016-09-29 17:27:47 -04001814 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001815
Clarence Ip13a8cf42016-09-29 17:27:47 -04001816 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04001817 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
1818
Clarence Ip4ce59322016-06-26 22:27:51 -04001819 debugfs_remove_recursive(psde->debugfs_root);
Clarence Ipe78efb72016-06-24 18:35:21 -04001820
Dhaval Patel4e574842016-08-23 15:11:37 -07001821 if (psde->blob_info)
1822 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001823 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04001824 mutex_destroy(&psde->lock);
1825
Clarence Ip4ce59322016-06-26 22:27:51 -04001826 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001827
Clarence Ip4ce59322016-06-26 22:27:51 -04001828 /* this will destroy the states as well */
1829 drm_plane_cleanup(plane);
1830
Clarence Ip4c1d9772016-06-26 09:35:38 -04001831 if (psde->pipe_hw)
1832 sde_hw_sspp_destroy(psde->pipe_hw);
1833
Clarence Ip4ce59322016-06-26 22:27:51 -04001834 kfree(psde);
1835 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001836}
1837
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001838static void sde_plane_destroy_state(struct drm_plane *plane,
1839 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001840{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001841 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04001842 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04001843
Clarence Ipae4e60c2016-06-26 22:44:04 -04001844 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001845 SDE_ERROR("invalid arg(s), plane %d state %d\n",
1846 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001847 return;
1848 }
1849
Clarence Ipaa0faf42016-05-30 12:07:48 -04001850 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04001851 pstate = to_sde_plane_state(state);
1852
Clarence Ip13a8cf42016-09-29 17:27:47 -04001853 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001854
Clarence Ipe78efb72016-06-24 18:35:21 -04001855 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001856 if (state->fb)
1857 drm_framebuffer_unreference(state->fb);
1858
Clarence Ipae4e60c2016-06-26 22:44:04 -04001859 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04001860 if (pstate->input_fence)
1861 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001862
Clarence Ipaa0faf42016-05-30 12:07:48 -04001863 /* destroy value helper */
1864 msm_property_destroy_state(&psde->property_info, pstate,
1865 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001866}
1867
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001868static struct drm_plane_state *
1869sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001870{
Clarence Ipaa0faf42016-05-30 12:07:48 -04001871 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001872 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04001873 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04001874 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001875
Clarence Ip13a8cf42016-09-29 17:27:47 -04001876 if (!plane) {
1877 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001878 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001879 } else if (!plane->state) {
1880 SDE_ERROR("invalid plane state\n");
1881 return NULL;
1882 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001883
Clarence Ip730e7192016-06-26 22:45:09 -04001884 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001885 psde = to_sde_plane(plane);
1886 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001887 if (!pstate) {
1888 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001889 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001890 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001891
Clarence Ip13a8cf42016-09-29 17:27:47 -04001892 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001893
1894 /* duplicate value helper */
1895 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
1896 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04001897
Clarence Ip730e7192016-06-26 22:45:09 -04001898 /* add ref count for frame buffer */
1899 if (pstate->base.fb)
1900 drm_framebuffer_reference(pstate->base.fb);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001901
Clarence Ip17e908b2016-09-29 15:58:00 -04001902 /* clear out any input fence */
1903 pstate->input_fence = 0;
1904 input_fence_default = msm_property_get_default(
1905 &psde->property_info, PLANE_PROP_INPUT_FENCE);
1906 msm_property_set_property(&psde->property_info, pstate->property_values,
1907 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001908
Clarence Ip282dad62016-09-27 17:07:35 -04001909 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04001910 pstate->pending = false;
1911
1912 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001913}
1914
1915static void sde_plane_reset(struct drm_plane *plane)
1916{
Clarence Ipae4e60c2016-06-26 22:44:04 -04001917 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001918 struct sde_plane_state *pstate;
1919
Clarence Ipae4e60c2016-06-26 22:44:04 -04001920 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001921 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04001922 return;
1923 }
1924
Clarence Ip730e7192016-06-26 22:45:09 -04001925 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001926 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04001927
Clarence Ipae4e60c2016-06-26 22:44:04 -04001928 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04001929 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04001930 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04001931 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04001932 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001933
Clarence Ipaa0faf42016-05-30 12:07:48 -04001934 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04001935 if (!pstate) {
1936 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001937 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04001938 }
Clarence Ip730e7192016-06-26 22:45:09 -04001939
Clarence Ipaa0faf42016-05-30 12:07:48 -04001940 /* reset value helper */
1941 msm_property_reset_state(&psde->property_info, pstate,
1942 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001943
1944 pstate->base.plane = plane;
1945
1946 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001947}
1948
1949static const struct drm_plane_funcs sde_plane_funcs = {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001950 .update_plane = drm_atomic_helper_update_plane,
1951 .disable_plane = drm_atomic_helper_disable_plane,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001952 .destroy = sde_plane_destroy,
1953 .set_property = sde_plane_set_property,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001954 .atomic_set_property = sde_plane_atomic_set_property,
1955 .atomic_get_property = sde_plane_atomic_get_property,
1956 .reset = sde_plane_reset,
1957 .atomic_duplicate_state = sde_plane_duplicate_state,
1958 .atomic_destroy_state = sde_plane_destroy_state,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001959};
1960
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001961static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
1962 .prepare_fb = sde_plane_prepare_fb,
1963 .cleanup_fb = sde_plane_cleanup_fb,
1964 .atomic_check = sde_plane_atomic_check,
1965 .atomic_update = sde_plane_atomic_update,
1966};
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001967
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001968enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001969{
Clarence Ip13a8cf42016-09-29 17:27:47 -04001970 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001971}
1972
Clarence Ip4ce59322016-06-26 22:27:51 -04001973static void _sde_plane_init_debugfs(struct sde_plane *psde, struct sde_kms *kms)
1974{
1975 const struct sde_sspp_sub_blks *sblk = 0;
1976 const struct sde_sspp_cfg *cfg = 0;
1977
1978 if (psde && psde->pipe_hw)
1979 cfg = psde->pipe_hw->cap;
1980 if (cfg)
1981 sblk = cfg->sblk;
1982
1983 if (kms && sblk) {
1984 /* create overall sub-directory for the pipe */
1985 psde->debugfs_root =
1986 debugfs_create_dir(psde->pipe_name,
1987 sde_debugfs_get_root(kms));
1988 if (psde->debugfs_root) {
1989 /* don't error check these */
Clarence Ip4c1d9772016-06-26 09:35:38 -04001990 debugfs_create_x32("features", 0644,
Clarence Ip4ce59322016-06-26 22:27:51 -04001991 psde->debugfs_root, &psde->features);
1992
1993 /* add register dump support */
1994 sde_debugfs_setup_regset32(&psde->debugfs_src,
1995 sblk->src_blk.base + cfg->base,
1996 sblk->src_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04001997 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04001998 sde_debugfs_create_regset32("src_blk", 0444,
1999 psde->debugfs_root, &psde->debugfs_src);
2000
2001 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
2002 sblk->scaler_blk.base + cfg->base,
2003 sblk->scaler_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002004 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002005 sde_debugfs_create_regset32("scaler_blk", 0444,
2006 psde->debugfs_root,
2007 &psde->debugfs_scaler);
2008
2009 sde_debugfs_setup_regset32(&psde->debugfs_csc,
2010 sblk->csc_blk.base + cfg->base,
2011 sblk->csc_blk.len,
Clarence Ipaac9f332016-08-31 15:46:35 -04002012 kms);
Clarence Ip4ce59322016-06-26 22:27:51 -04002013 sde_debugfs_create_regset32("csc_blk", 0444,
2014 psde->debugfs_root, &psde->debugfs_csc);
2015 }
2016 }
2017}
2018
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002019/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04002020struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002021 uint32_t pipe, bool primary_plane,
2022 unsigned long possible_crtcs)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002023{
2024 struct drm_plane *plane = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002025 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002026 struct msm_drm_private *priv;
2027 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002028 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04002029 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002030
2031 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002032 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002033 goto exit;
2034 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002035
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002036 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04002037 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002038 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002039 goto exit;
2040 }
2041
2042 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002043 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04002044 goto exit;
2045 }
2046 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002047
Clarence Ip4c1d9772016-06-26 09:35:38 -04002048 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002049 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002050 goto exit;
2051 }
2052
Clarence Ip4ce59322016-06-26 22:27:51 -04002053 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002054 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
2055 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002056 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002057 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04002058 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002059 }
2060
Clarence Ip4c1d9772016-06-26 09:35:38 -04002061 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002062 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002063 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04002064 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002065
Clarence Ip4c1d9772016-06-26 09:35:38 -04002066 /* initialize underlying h/w driver */
2067 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
2068 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002069 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002070 ret = PTR_ERR(psde->pipe_hw);
2071 goto clean_plane;
2072 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002073 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002074 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002075 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002076
2077 /* cache features mask for later */
2078 psde->features = psde->pipe_hw->cap->features;
2079 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04002080 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002081 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04002082 goto clean_sspp;
2083 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04002084
abeykun48f407a2016-08-25 12:06:44 -04002085 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
2086 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
2087 GFP_KERNEL);
2088 if (!psde->scaler3_cfg) {
2089 SDE_ERROR("[%u]failed to allocate scale struct\n",
2090 pipe);
2091 ret = -ENOMEM;
2092 goto clean_sspp;
2093 }
2094 }
2095
Clarence Ip4c1d9772016-06-26 09:35:38 -04002096 /* add plane to DRM framework */
Clarence Ipea3d6262016-07-15 16:20:11 -04002097 psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
2098 psde->formats,
2099 0,
2100 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002101
Clarence Ip4c1d9772016-06-26 09:35:38 -04002102 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002103 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002104 goto clean_sspp;
2105 }
2106
2107 if (psde->features & BIT(SDE_SSPP_CURSOR))
2108 type = DRM_PLANE_TYPE_CURSOR;
2109 else if (primary_plane)
2110 type = DRM_PLANE_TYPE_PRIMARY;
2111 else
2112 type = DRM_PLANE_TYPE_OVERLAY;
Clarence Ip2bbf7b32016-09-23 15:07:16 -04002113 ret = drm_universal_plane_init(dev, plane, possible_crtcs,
2114 &sde_plane_funcs, psde->formats, psde->nformats, type);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002115 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04002116 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002117
Clarence Ip4c1d9772016-06-26 09:35:38 -04002118 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002119 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002120
Clarence Ipaa0faf42016-05-30 12:07:48 -04002121 msm_property_init(&psde->property_info, &plane->base, dev,
2122 priv->plane_property, psde->property_data,
2123 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
2124 sizeof(struct sde_plane_state));
2125
Clarence Ipc47a0692016-10-11 10:54:17 -04002126 _sde_plane_install_properties(plane, kms->catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002127
Clarence Ip4ce59322016-06-26 22:27:51 -04002128 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04002129 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04002130
Clarence Ip730e7192016-06-26 22:45:09 -04002131 mutex_init(&psde->lock);
2132
Clarence Ip4ce59322016-06-26 22:27:51 -04002133 _sde_plane_init_debugfs(psde, kms);
2134
Clarence Ip13a8cf42016-09-29 17:27:47 -04002135 DRM_INFO("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002136 return plane;
2137
Clarence Ip4c1d9772016-06-26 09:35:38 -04002138clean_sspp:
2139 if (psde && psde->pipe_hw)
2140 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04002141
2142 if (psde && psde->scaler3_cfg)
2143 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04002144clean_plane:
2145 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04002146exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002147 return ERR_PTR(ret);
2148}