blob: f2ea15f83563a049449362c6dc75677ed4378c06 [file] [log] [blame]
Dhaval Patel14d46ce2017-01-17 16:28:12 -08001/*
2 * Copyright (C) 2014-2017 The Linux Foundation. All rights reserved.
3 * Copyright (C) 2013 Red Hat
4 * Author: Rob Clark <robdclark@gmail.com>
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005 *
Dhaval Patel14d46ce2017-01-17 16:28:12 -08006 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07009 *
Dhaval Patel14d46ce2017-01-17 16:28:12 -080010 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070017 */
Alan Kwong1a00e4d2016-07-18 09:42:30 -040018
19#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
20
Clarence Ip4ce59322016-06-26 22:27:51 -040021#include <linux/debugfs.h>
Alan Kwong4dd64c82017-02-04 18:41:51 -080022#include <linux/dma-buf.h>
Clarence Ip5e2a9222016-06-26 22:38:24 -040023#include <uapi/drm/sde_drm.h>
Benet Clarkd009b1d2016-06-27 14:45:59 -070024#include <uapi/drm/msm_drm_pp.h>
Clarence Ipaa0faf42016-05-30 12:07:48 -040025
26#include "msm_prop.h"
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080027#include "msm_drv.h"
Clarence Ipaa0faf42016-05-30 12:07:48 -040028
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070029#include "sde_kms.h"
Clarence Ipae4e60c2016-06-26 22:44:04 -040030#include "sde_fence.h"
Clarence Ipc475b082016-06-26 09:27:23 -040031#include "sde_formats.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040032#include "sde_hw_sspp.h"
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080033#include "sde_hw_catalog_format.h"
Alan Kwong1a00e4d2016-07-18 09:42:30 -040034#include "sde_trace.h"
Dhaval Patel48c76022016-09-01 17:51:23 -070035#include "sde_crtc.h"
Lloyd Atkinson8772e202016-09-26 17:52:16 -040036#include "sde_vbif.h"
Alan Kwong83285fb2016-10-21 20:51:17 -040037#include "sde_plane.h"
Benet Clarkd009b1d2016-06-27 14:45:59 -070038#include "sde_color_processing.h"
Alan Kwong4dd64c82017-02-04 18:41:51 -080039#include "sde_hw_rot.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040040
Clarence Ip56902792017-03-17 15:22:07 -040041static bool suspend_blank = true;
42module_param(suspend_blank, bool, 0400);
43MODULE_PARM_DESC(suspend_blank,
44 "If set, active planes will force their outputs to black,\n"
45 "by temporarily enabling the color fill, when recovering\n"
46 "from a system resume instead of attempting to display the\n"
47 "last provided frame buffer.");
48
Clarence Ip13a8cf42016-09-29 17:27:47 -040049#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
50 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
51
52#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
53 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
54
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040055#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
56#define PHASE_STEP_SHIFT 21
57#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
58#define PHASE_RESIDUAL 15
59
Clarence Ipe78efb72016-06-24 18:35:21 -040060#define SHARP_STRENGTH_DEFAULT 32
61#define SHARP_EDGE_THR_DEFAULT 112
62#define SHARP_SMOOTH_THR_DEFAULT 8
63#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040064
Clarence Ip5e2a9222016-06-26 22:38:24 -040065#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070066
Clarence Ipcae1bb62016-07-07 12:07:13 -040067#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
68
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080069/* multirect rect index */
70enum {
71 R0,
72 R1,
73 R_MAX
74};
75
76#define TX_MODE_BUFFER_LINE_THRES 2
77
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -070078#define SDE_QSEED3_DEFAULT_PRELOAD_H 0x4
79#define SDE_QSEED3_DEFAULT_PRELOAD_V 0x3
80
Alan Kwong4dd64c82017-02-04 18:41:51 -080081#define DEFAULT_REFRESH_RATE 60
82
Alan Kwong1a00e4d2016-07-18 09:42:30 -040083/**
84 * enum sde_plane_qos - Different qos configurations for each pipe
85 *
86 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
87 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
88 * this configuration is mutually exclusive from VBLANK_CTRL.
89 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
90 */
91enum sde_plane_qos {
92 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
93 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
94 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
95};
96
Clarence Ip5fc00c52016-09-23 15:03:34 -040097/*
98 * struct sde_plane - local sde plane structure
99 * @csc_cfg: Decoded user configuration for csc
100 * @csc_usr_ptr: Points to csc_cfg if valid user config available
101 * @csc_ptr: Points to sde_csc_cfg structure to use for current
Alan Kwong4dd64c82017-02-04 18:41:51 -0800102 * @catalog: Points to sde catalog structure
103 * @sbuf_mode: force stream buffer mode if set
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700104 * @sbuf_writeback: force stream buffer writeback if set
105 * @revalidate: force revalidation of all the plane properties
Alan Kwong4dd64c82017-02-04 18:41:51 -0800106 * @blob_rot_caps: Pointer to rotator capability blob
Clarence Ip5fc00c52016-09-23 15:03:34 -0400107 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700108struct sde_plane {
109 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400110
111 int mmu_id;
112
Clarence Ip730e7192016-06-26 22:45:09 -0400113 struct mutex lock;
114
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400115 enum sde_sspp pipe;
116 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700117 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400118 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400119
120 struct sde_hw_pipe *pipe_hw;
121 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -0400122 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -0400123 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400124 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400125 uint32_t color_fill;
126 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400127 bool is_rt_pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800128 bool is_virtual;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800129 struct sde_mdss_cfg *catalog;
130 u32 sbuf_mode;
131 u32 sbuf_writeback;
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700132 bool revalidate;
Clarence Ip4ce59322016-06-26 22:27:51 -0400133
Clarence Ipb43d4592016-09-08 14:21:35 -0400134 struct sde_hw_pixel_ext pixel_ext;
135 bool pixel_ext_usr;
136
Clarence Ip373f8592016-05-26 00:58:42 -0400137 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400138 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400139 struct sde_csc_cfg *csc_ptr;
140
Clarence Ip4c1d9772016-06-26 09:35:38 -0400141 const struct sde_sspp_sub_blks *pipe_sblk;
142
Clarence Ip5e2a9222016-06-26 22:38:24 -0400143 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400144
Clarence Ipaa0faf42016-05-30 12:07:48 -0400145 struct msm_property_info property_info;
146 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700147 struct drm_property_blob *blob_info;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800148 struct drm_property_blob *blob_rot_caps;
Clarence Ip730e7192016-06-26 22:45:09 -0400149
Clarence Ip4ce59322016-06-26 22:27:51 -0400150 /* debugfs related stuff */
151 struct dentry *debugfs_root;
152 struct sde_debugfs_regset32 debugfs_src;
153 struct sde_debugfs_regset32 debugfs_scaler;
154 struct sde_debugfs_regset32 debugfs_csc;
Clarence Ip716ab662017-03-20 06:51:24 -0700155 bool debugfs_default_scale;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700156};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700157
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700158#define to_sde_plane(x) container_of(x, struct sde_plane, base)
159
Alan Kwong4dd64c82017-02-04 18:41:51 -0800160static struct sde_kms *_sde_plane_get_kms(struct drm_plane *plane)
161{
162 struct msm_drm_private *priv;
163
164 if (!plane || !plane->dev)
165 return NULL;
166 priv = plane->dev->dev_private;
167 if (!priv)
168 return NULL;
169 return to_sde_kms(priv->kms);
170}
171
Alan Kwong4aacd532017-02-04 18:51:33 -0800172/**
173 * _sde_plane_get_crtc_state - obtain crtc state attached to given plane state
174 * @pstate: Pointer to drm plane state
175 * return: Pointer to crtc state if success; pointer error, otherwise
176 */
177static struct drm_crtc_state *_sde_plane_get_crtc_state(
178 struct drm_plane_state *pstate)
179{
180 struct drm_crtc_state *cstate;
181
182 if (!pstate || !pstate->crtc)
183 return NULL;
184
185 if (pstate->state)
186 cstate = drm_atomic_get_crtc_state(pstate->state, pstate->crtc);
187 else
188 cstate = pstate->crtc->state;
189
190 return cstate;
191}
192
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400193static bool sde_plane_enabled(struct drm_plane_state *state)
194{
Clarence Ipdbde9832016-06-26 09:48:36 -0400195 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400196}
197
Alan Kwong4dd64c82017-02-04 18:41:51 -0800198static bool sde_plane_sspp_enabled(struct drm_plane_state *state)
199{
200 return state && to_sde_plane_state(state)->rot.out_fb && state->crtc;
201}
202
203/**
204 * sde_plane_crtc_enabled - determine if crtc of given plane state is enabled
205 * @state: Pointer to drm plane state
206 * return: true if plane and the associated crtc are both enabled
207 */
208static bool sde_plane_crtc_enabled(struct drm_plane_state *state)
209{
210 return sde_plane_enabled(state) && state->crtc->state &&
211 state->crtc->state->active &&
212 state->crtc->state->enable;
213}
214
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400215/**
216 * _sde_plane_calc_fill_level - calculate fill level of the given source format
217 * @plane: Pointer to drm plane
218 * @fmt: Pointer to source buffer format
219 * @src_wdith: width of source buffer
220 * Return: fill level corresponding to the source buffer/format or 0 if error
221 */
222static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
223 const struct sde_format *fmt, u32 src_width)
224{
225 struct sde_plane *psde;
226 u32 fixed_buff_size;
227 u32 total_fl;
228
229 if (!plane || !fmt) {
230 SDE_ERROR("invalid arguments\n");
231 return 0;
232 }
233
234 psde = to_sde_plane(plane);
235 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
236
237 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
238 if (fmt->chroma_sample == SDE_CHROMA_420) {
239 /* NV12 */
240 total_fl = (fixed_buff_size / 2) /
241 ((src_width + 32) * fmt->bpp);
242 } else {
243 /* non NV12 */
244 total_fl = (fixed_buff_size) /
245 ((src_width + 32) * fmt->bpp);
246 }
247 } else {
248 total_fl = (fixed_buff_size * 2) /
249 ((src_width + 32) * fmt->bpp);
250 }
251
Dhaval Patel6c666622017-03-21 23:02:59 -0700252 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u fl:%u\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400253 plane->base.id, psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700254 (char *)&fmt->base.pixel_format,
255 src_width, total_fl);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400256
257 return total_fl;
258}
259
260/**
261 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
262 * @total_fl: fill level
263 * Return: LUT setting corresponding to the fill level
264 */
265static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
266{
267 u32 qos_lut;
268
269 if (total_fl <= 4)
270 qos_lut = 0x1B;
271 else if (total_fl <= 5)
272 qos_lut = 0x5B;
273 else if (total_fl <= 6)
274 qos_lut = 0x15B;
275 else if (total_fl <= 7)
276 qos_lut = 0x55B;
277 else if (total_fl <= 8)
278 qos_lut = 0x155B;
279 else if (total_fl <= 9)
280 qos_lut = 0x555B;
281 else if (total_fl <= 10)
282 qos_lut = 0x1555B;
283 else if (total_fl <= 11)
284 qos_lut = 0x5555B;
285 else if (total_fl <= 12)
286 qos_lut = 0x15555B;
287 else
288 qos_lut = 0x55555B;
289
290 return qos_lut;
291}
292
293/**
294 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
295 * @total_fl: fill level
296 * Return: LUT setting corresponding to the fill level
297 */
298static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
299{
300 u32 qos_lut;
301
302 if (total_fl <= 10)
303 qos_lut = 0x1AAff;
304 else if (total_fl <= 11)
305 qos_lut = 0x5AAFF;
306 else if (total_fl <= 12)
307 qos_lut = 0x15AAFF;
308 else
309 qos_lut = 0x55AAFF;
310
311 return qos_lut;
312}
313
314/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400315 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
316 * @plane: Pointer to drm plane
317 * @fb: Pointer to framebuffer associated with the given plane
318 */
319static void _sde_plane_set_qos_lut(struct drm_plane *plane,
320 struct drm_framebuffer *fb)
321{
322 struct sde_plane *psde;
323 const struct sde_format *fmt = NULL;
324 u32 qos_lut;
325 u32 total_fl = 0;
326
327 if (!plane || !fb) {
328 SDE_ERROR("invalid arguments plane %d fb %d\n",
329 plane != 0, fb != 0);
330 return;
331 }
332
333 psde = to_sde_plane(plane);
334
335 if (!psde->pipe_hw || !psde->pipe_sblk) {
336 SDE_ERROR("invalid arguments\n");
337 return;
338 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
339 return;
340 }
341
342 if (!psde->is_rt_pipe) {
343 qos_lut = psde->pipe_sblk->creq_lut_nrt;
344 } else {
345 fmt = sde_get_sde_format_ext(
346 fb->pixel_format,
347 fb->modifier,
348 drm_format_num_planes(fb->pixel_format));
349 total_fl = _sde_plane_calc_fill_level(plane, fmt,
350 psde->pipe_cfg.src_rect.w);
351
352 if (SDE_FORMAT_IS_LINEAR(fmt))
353 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
354 else
355 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
356 }
357
358 psde->pipe_qos_cfg.creq_lut = qos_lut;
359
360 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
361 (fmt) ? fmt->base.pixel_format : 0,
362 psde->is_rt_pipe, total_fl, qos_lut,
363 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
364
Dhaval Patel6c666622017-03-21 23:02:59 -0700365 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%x\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400366 plane->base.id,
367 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700368 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400369 psde->is_rt_pipe, total_fl, qos_lut);
370
371 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
372}
373
374/**
375 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
376 * @plane: Pointer to drm plane
377 * @fb: Pointer to framebuffer associated with the given plane
378 */
379static void _sde_plane_set_danger_lut(struct drm_plane *plane,
380 struct drm_framebuffer *fb)
381{
382 struct sde_plane *psde;
383 const struct sde_format *fmt = NULL;
384 u32 danger_lut, safe_lut;
385
386 if (!plane || !fb) {
387 SDE_ERROR("invalid arguments\n");
388 return;
389 }
390
391 psde = to_sde_plane(plane);
392
393 if (!psde->pipe_hw || !psde->pipe_sblk) {
394 SDE_ERROR("invalid arguments\n");
395 return;
396 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
397 return;
398 }
399
400 if (!psde->is_rt_pipe) {
401 danger_lut = psde->pipe_sblk->danger_lut_nrt;
402 safe_lut = psde->pipe_sblk->safe_lut_nrt;
403 } else {
404 fmt = sde_get_sde_format_ext(
405 fb->pixel_format,
406 fb->modifier,
407 drm_format_num_planes(fb->pixel_format));
408
409 if (SDE_FORMAT_IS_LINEAR(fmt)) {
410 danger_lut = psde->pipe_sblk->danger_lut_linear;
411 safe_lut = psde->pipe_sblk->safe_lut_linear;
412 } else {
413 danger_lut = psde->pipe_sblk->danger_lut_tile;
414 safe_lut = psde->pipe_sblk->safe_lut_tile;
415 }
416 }
417
418 psde->pipe_qos_cfg.danger_lut = danger_lut;
419 psde->pipe_qos_cfg.safe_lut = safe_lut;
420
421 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
422 (fmt) ? fmt->base.pixel_format : 0,
423 (fmt) ? fmt->fetch_mode : 0,
424 psde->pipe_qos_cfg.danger_lut,
425 psde->pipe_qos_cfg.safe_lut);
426
Dhaval Patel6c666622017-03-21 23:02:59 -0700427 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400428 plane->base.id,
429 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700430 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400431 fmt ? fmt->fetch_mode : -1,
432 psde->pipe_qos_cfg.danger_lut,
433 psde->pipe_qos_cfg.safe_lut);
434
435 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
436 &psde->pipe_qos_cfg);
437}
438
439/**
440 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
441 * @plane: Pointer to drm plane
442 * @enable: true to enable QoS control
443 * @flags: QoS control mode (enum sde_plane_qos)
444 */
445static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
446 bool enable, u32 flags)
447{
448 struct sde_plane *psde;
449
450 if (!plane) {
451 SDE_ERROR("invalid arguments\n");
452 return;
453 }
454
455 psde = to_sde_plane(plane);
456
457 if (!psde->pipe_hw || !psde->pipe_sblk) {
458 SDE_ERROR("invalid arguments\n");
459 return;
460 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
461 return;
462 }
463
464 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
465 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
466 psde->pipe_qos_cfg.danger_vblank =
467 psde->pipe_sblk->danger_vblank;
468 psde->pipe_qos_cfg.vblank_en = enable;
469 }
470
471 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
472 /* this feature overrules previous VBLANK_CTRL */
473 psde->pipe_qos_cfg.vblank_en = false;
474 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
475 }
476
477 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
478 psde->pipe_qos_cfg.danger_safe_en = enable;
479
480 if (!psde->is_rt_pipe) {
481 psde->pipe_qos_cfg.vblank_en = false;
482 psde->pipe_qos_cfg.danger_safe_en = false;
483 }
484
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400485 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 -0400486 plane->base.id,
487 psde->pipe - SSPP_VIG0,
488 psde->pipe_qos_cfg.danger_safe_en,
489 psde->pipe_qos_cfg.vblank_en,
490 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400491 psde->pipe_qos_cfg.danger_vblank,
492 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400493
494 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
495 &psde->pipe_qos_cfg);
496}
497
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700498void sde_plane_set_revalidate(struct drm_plane *plane, bool enable)
499{
500 struct sde_plane *psde;
501
502 if (!plane)
503 return;
504
505 psde = to_sde_plane(plane);
506 psde->revalidate = enable;
507}
508
Alan Kwongf0fd8512016-10-24 21:39:26 -0400509int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
510{
511 struct sde_plane *psde;
512 struct msm_drm_private *priv;
513 struct sde_kms *sde_kms;
514
515 if (!plane || !plane->dev) {
516 SDE_ERROR("invalid arguments\n");
517 return -EINVAL;
518 }
519
520 priv = plane->dev->dev_private;
521 if (!priv || !priv->kms) {
522 SDE_ERROR("invalid KMS reference\n");
523 return -EINVAL;
524 }
525
526 sde_kms = to_sde_kms(priv->kms);
527 psde = to_sde_plane(plane);
528
529 if (!psde->is_rt_pipe)
530 goto end;
531
532 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
533
534 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
535
536 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
537
538end:
539 return 0;
540}
541
Alan Kwong5d324e42016-07-28 22:56:18 -0400542/**
543 * _sde_plane_set_ot_limit - set OT limit for the given plane
544 * @plane: Pointer to drm plane
545 * @crtc: Pointer to drm crtc
546 */
547static void _sde_plane_set_ot_limit(struct drm_plane *plane,
548 struct drm_crtc *crtc)
549{
550 struct sde_plane *psde;
551 struct sde_vbif_set_ot_params ot_params;
552 struct msm_drm_private *priv;
553 struct sde_kms *sde_kms;
554
555 if (!plane || !plane->dev || !crtc) {
556 SDE_ERROR("invalid arguments plane %d crtc %d\n",
557 plane != 0, crtc != 0);
558 return;
559 }
560
561 priv = plane->dev->dev_private;
562 if (!priv || !priv->kms) {
563 SDE_ERROR("invalid KMS reference\n");
564 return;
565 }
566
567 sde_kms = to_sde_kms(priv->kms);
568 psde = to_sde_plane(plane);
569 if (!psde->pipe_hw) {
570 SDE_ERROR("invalid pipe reference\n");
571 return;
572 }
573
574 memset(&ot_params, 0, sizeof(ot_params));
575 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
576 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
577 ot_params.width = psde->pipe_cfg.src_rect.w;
578 ot_params.height = psde->pipe_cfg.src_rect.h;
579 ot_params.is_wfd = !psde->is_rt_pipe;
580 ot_params.frame_rate = crtc->mode.vrefresh;
581 ot_params.vbif_idx = VBIF_RT;
582 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
583 ot_params.rd = true;
584
585 sde_vbif_set_ot_limit(sde_kms, &ot_params);
586}
587
Alan Kwonga62eeb82017-04-19 08:57:55 -0700588/**
589 * _sde_plane_set_vbif_qos - set vbif QoS for the given plane
590 * @plane: Pointer to drm plane
591 */
592static void _sde_plane_set_qos_remap(struct drm_plane *plane)
593{
594 struct sde_plane *psde;
595 struct sde_vbif_set_qos_params qos_params;
596 struct msm_drm_private *priv;
597 struct sde_kms *sde_kms;
598
599 if (!plane || !plane->dev) {
600 SDE_ERROR("invalid arguments\n");
601 return;
602 }
603
604 priv = plane->dev->dev_private;
605 if (!priv || !priv->kms) {
606 SDE_ERROR("invalid KMS reference\n");
607 return;
608 }
609
610 sde_kms = to_sde_kms(priv->kms);
611 psde = to_sde_plane(plane);
612 if (!psde->pipe_hw) {
613 SDE_ERROR("invalid pipe reference\n");
614 return;
615 }
616
617 memset(&qos_params, 0, sizeof(qos_params));
618 qos_params.vbif_idx = VBIF_RT;
619 qos_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
620 qos_params.xin_id = psde->pipe_hw->cap->xin_id;
621 qos_params.num = psde->pipe_hw->idx - SSPP_VIG0;
622 qos_params.is_rt = psde->is_rt_pipe;
623
624 SDE_DEBUG("plane%d pipe:%d vbif:%d xin:%d rt:%d\n",
625 plane->base.id, qos_params.num,
626 qos_params.vbif_idx,
627 qos_params.xin_id, qos_params.is_rt);
628
629 sde_vbif_set_qos_remap(sde_kms, &qos_params);
630}
631
Clarence Ipcae1bb62016-07-07 12:07:13 -0400632/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400633static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400634 struct sde_plane_state *pstate, uint64_t fd)
635{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400636 if (!psde || !pstate) {
637 SDE_ERROR("invalid arg(s), plane %d state %d\n",
638 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400639 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400640 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400641
642 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400643 if (pstate->input_fence)
644 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400645
646 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400647 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400648
Clarence Ip13a8cf42016-09-29 17:27:47 -0400649 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400650}
651
Clarence Ipcae1bb62016-07-07 12:07:13 -0400652int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400653{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400654 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400655 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400656 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400657 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400658 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800659 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400660
661 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700662 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400663 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400664 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400665 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400666 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400667 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400668 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400669
Clarence Ipcae1bb62016-07-07 12:07:13 -0400670 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800671 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400672 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800673 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400674
Dhaval Patel39323d42017-03-01 23:48:24 -0800675 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400676 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400677 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
678 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400679 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800680 ret = -ETIMEDOUT;
681 break;
682 case -ERESTARTSYS:
683 SDE_ERROR_PLANE(psde,
684 "%ums wait interrupted on %08X\n",
685 wait_ms, prefix);
686 psde->is_error = true;
687 ret = -ERESTARTSYS;
688 break;
689 case -EINVAL:
690 SDE_ERROR_PLANE(psde,
691 "invalid fence param for %08X\n",
692 prefix);
693 psde->is_error = true;
694 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400695 break;
696 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800697 SDE_DEBUG_PLANE(psde, "signaled\n");
698 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400699 break;
700 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700701
702 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400703 } else {
704 ret = 0;
705 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400706 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400707 return ret;
708}
709
Clarence Ip282dad62016-09-27 17:07:35 -0400710static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400711 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400712 struct sde_hw_pipe_cfg *pipe_cfg,
713 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400714{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400715 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400716 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400717
Clarence Ip13a8cf42016-09-29 17:27:47 -0400718 if (!plane || !pstate || !pipe_cfg || !fb) {
719 SDE_ERROR(
720 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
721 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400722 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400723 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400724
725 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400726 if (!psde->pipe_hw) {
727 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400728 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400729 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400730
Clarence Ipb6eb2362016-09-08 16:18:13 -0400731 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
732 if (ret == -EAGAIN)
733 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
734 else if (ret)
735 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
736 else if (psde->pipe_hw->ops.setup_sourceaddress)
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800737 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
738 pstate->multirect_index);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400739}
740
abeykun48f407a2016-08-25 12:06:44 -0400741static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
742 struct sde_plane_state *pstate)
743{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500744 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400745 int ret = 0;
746
Clarence Ip3bf8d872017-02-16 15:25:38 -0500747 if (!psde || !psde->scaler3_cfg) {
748 SDE_ERROR("invalid args\n");
749 return -EINVAL;
750 } else if (!pstate) {
751 /* pstate is expected to be null on forced color fill */
752 SDE_DEBUG("null pstate\n");
753 return -EINVAL;
754 }
755
756 cfg = psde->scaler3_cfg;
757
abeykun48f407a2016-08-25 12:06:44 -0400758 cfg->dir_lut = msm_property_get_blob(
759 &psde->property_info,
760 pstate->property_blobs, &cfg->dir_len,
761 PLANE_PROP_SCALER_LUT_ED);
762 cfg->cir_lut = msm_property_get_blob(
763 &psde->property_info,
764 pstate->property_blobs, &cfg->cir_len,
765 PLANE_PROP_SCALER_LUT_CIR);
766 cfg->sep_lut = msm_property_get_blob(
767 &psde->property_info,
768 pstate->property_blobs, &cfg->sep_len,
769 PLANE_PROP_SCALER_LUT_SEP);
770 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
771 ret = -ENODATA;
772 return ret;
773}
774
Clarence Ipcb410d42016-06-26 22:52:33 -0400775static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400776 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
777 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400778 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400779 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
780{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700781 uint32_t decimated, i;
782
783 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
784 !chroma_subsmpl_v) {
785 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
786 , psde, scale_cfg, fmt, chroma_subsmpl_h,
787 chroma_subsmpl_v);
788 return;
789 }
790
791 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip716ab662017-03-20 06:51:24 -0700792 memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700793
794 decimated = DECIMATED_DIMENSION(src_w,
795 psde->pipe_cfg.horz_decimation);
796 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
797 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
798 decimated = DECIMATED_DIMENSION(src_h,
799 psde->pipe_cfg.vert_decimation);
800 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
801 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
802
803
804 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
805 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
806 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
807 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
808
809 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
810 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
811 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
812 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
813
814 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
815 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
816 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
817 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
818
819 for (i = 0; i < SDE_MAX_PLANES; i++) {
820 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
821 psde->pipe_cfg.horz_decimation);
822 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
823 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700824 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
825 scale_cfg->src_width[i] /= chroma_subsmpl_h;
826 scale_cfg->src_height[i] /= chroma_subsmpl_v;
827 }
828 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
829 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
830 psde->pixel_ext.num_ext_pxls_top[i] =
831 scale_cfg->src_height[i];
832 psde->pixel_ext.num_ext_pxls_left[i] =
833 scale_cfg->src_width[i];
834 }
835 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
836 && (src_w == dst_w))
837 return;
838
839 scale_cfg->dst_width = dst_w;
840 scale_cfg->dst_height = dst_h;
841 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
842 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
843 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
844 scale_cfg->lut_flag = 0;
845 scale_cfg->blend_cfg = 1;
846 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -0400847}
848
Clarence Ipcb410d42016-06-26 22:52:33 -0400849/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400850 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400851 * @psde: Pointer to SDE plane object
852 * @src: Source size
853 * @dst: Destination size
854 * @phase_steps: Pointer to output array for phase steps
855 * @filter: Pointer to output array for filter type
856 * @fmt: Pointer to format definition
857 * @chroma_subsampling: Subsampling amount for chroma channel
858 *
859 * Returns: 0 on success
860 */
861static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400862 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400863 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400864 uint32_t chroma_subsampling)
865{
Clarence Ipcb410d42016-06-26 22:52:33 -0400866 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400867 SDE_ERROR(
868 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
869 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400870 return -EINVAL;
871 }
872
Clarence Ip4c1d9772016-06-26 09:35:38 -0400873 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400874 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400875 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400876 phase_steps[SDE_SSPP_COMP_1_2] =
877 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
878 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
879 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400880
881 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400882 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400883 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400884 (src <= dst) ? SDE_SCALE_FILTER_BIL :
885 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400886
Clarence Ipdbde9832016-06-26 09:48:36 -0400887 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400888 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400889 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
890 } else {
891 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
892 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400893 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400894 }
895 } else {
896 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400897 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
898 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
899 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400900 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400901 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400902}
903
Clarence Ipcb410d42016-06-26 22:52:33 -0400904/**
905 * _sde_plane_setup_pixel_ext - determine default pixel extension values
906 * @psde: Pointer to SDE plane object
907 * @src: Source size
908 * @dst: Destination size
909 * @decimated_src: Source size after decimation, if any
910 * @phase_steps: Pointer to output array for phase steps
911 * @out_src: Output array for pixel extension values
912 * @out_edge1: Output array for pixel extension first edge
913 * @out_edge2: Output array for pixel extension second edge
914 * @filter: Pointer to array for filter type
915 * @fmt: Pointer to format definition
916 * @chroma_subsampling: Subsampling amount for chroma channel
917 * @post_compare: Whether to chroma subsampled source size for comparisions
918 */
919static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400920 uint32_t src, uint32_t dst, uint32_t decimated_src,
921 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400922 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400923 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400924 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400925{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400926 int64_t edge1, edge2, caf;
927 uint32_t src_work;
928 int i, tmp;
929
Clarence Ipcb410d42016-06-26 22:52:33 -0400930 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400931 out_edge2 && filter && fmt) {
932 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400933 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400934 caf = PHASE_STEP_UNIT_SCALE;
935 else
936 caf = 0;
937
938 for (i = 0; i < SDE_MAX_PLANES; i++) {
939 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400940 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400941 src_work /= chroma_subsampling;
942 if (post_compare)
943 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400944 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400945 /* unity */
946 edge1 = 0;
947 edge2 = 0;
948 } else if (dst >= src) {
949 /* upscale */
950 edge1 = (1 << PHASE_RESIDUAL);
951 edge1 -= caf;
952 edge2 = (1 << PHASE_RESIDUAL);
953 edge2 += (dst - 1) * *(phase_steps + i);
954 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
955 edge2 += caf;
956 edge2 = -(edge2);
957 } else {
958 /* downscale */
959 edge1 = 0;
960 edge2 = (dst - 1) * *(phase_steps + i);
961 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
962 edge2 += *(phase_steps + i);
963 edge2 = -(edge2);
964 }
965
966 /* only enable CAF for luma plane */
967 caf = 0;
968
969 /* populate output arrays */
970 *(out_src + i) = src_work;
971
972 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400973 if (edge1 >= 0) {
974 tmp = (uint32_t)edge1;
975 tmp >>= PHASE_STEP_SHIFT;
976 *(out_edge1 + i) = -tmp;
977 } else {
978 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400979 *(out_edge1 + i) =
980 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
981 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400982 }
983 if (edge2 >= 0) {
984 tmp = (uint32_t)edge2;
985 tmp >>= PHASE_STEP_SHIFT;
986 *(out_edge2 + i) = -tmp;
987 } else {
988 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400989 *(out_edge2 + i) =
990 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
991 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400992 }
993 }
994 }
995}
996
Clarence Ip5fc00c52016-09-23 15:03:34 -0400997static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400998{
999 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
1000 {
Clarence Ip373f8592016-05-26 00:58:42 -04001001 /* S15.16 format */
1002 0x00012A00, 0x00000000, 0x00019880,
1003 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1004 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -04001005 },
Clarence Ip373f8592016-05-26 00:58:42 -04001006 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -04001007 { 0xfff0, 0xff80, 0xff80,},
1008 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001009 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -04001010 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001011 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -04001012 };
abeykun1c312f62016-08-26 09:47:12 -04001013 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
1014 {
1015 /* S15.16 format */
1016 0x00012A00, 0x00000000, 0x00019880,
1017 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1018 0x00012A00, 0x00020480, 0x00000000,
1019 },
1020 /* signed bias */
1021 { 0xffc0, 0xfe00, 0xfe00,},
1022 { 0x0, 0x0, 0x0,},
1023 /* unsigned clamp */
1024 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
1025 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
1026 };
Clarence Ipe78efb72016-06-24 18:35:21 -04001027
Clarence Ip5fc00c52016-09-23 15:03:34 -04001028 if (!psde) {
1029 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001030 return;
1031 }
Clarence Ip5e2a9222016-06-26 22:38:24 -04001032
Clarence Ipcae1bb62016-07-07 12:07:13 -04001033 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001034 if (psde->csc_usr_ptr)
1035 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -04001036 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
1037 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001038 else
Clarence Ip373f8592016-05-26 00:58:42 -04001039 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001040
Clarence Ip13a8cf42016-09-29 17:27:47 -04001041 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -04001042 psde->csc_ptr->csc_mv[0],
1043 psde->csc_ptr->csc_mv[1],
1044 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -04001045}
1046
Benet Clarkeb1b4462016-06-27 14:43:06 -07001047static void sde_color_process_plane_setup(struct drm_plane *plane)
1048{
1049 struct sde_plane *psde;
1050 struct sde_plane_state *pstate;
1051 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001052 struct drm_msm_memcol *memcol = NULL;
1053 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001054
1055 psde = to_sde_plane(plane);
1056 pstate = to_sde_plane_state(plane->state);
1057
1058 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1059 if (psde->pipe_hw->ops.setup_pa_hue)
1060 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1061 saturation = (uint32_t) sde_plane_get_property(pstate,
1062 PLANE_PROP_SATURATION_ADJUST);
1063 if (psde->pipe_hw->ops.setup_pa_sat)
1064 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1065 value = (uint32_t) sde_plane_get_property(pstate,
1066 PLANE_PROP_VALUE_ADJUST);
1067 if (psde->pipe_hw->ops.setup_pa_val)
1068 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1069 contrast = (uint32_t) sde_plane_get_property(pstate,
1070 PLANE_PROP_CONTRAST_ADJUST);
1071 if (psde->pipe_hw->ops.setup_pa_cont)
1072 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001073
Benet Clarkd009b1d2016-06-27 14:45:59 -07001074 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1075 /* Skin memory color setup */
1076 memcol = msm_property_get_blob(&psde->property_info,
1077 pstate->property_blobs,
1078 &memcol_sz,
1079 PLANE_PROP_SKIN_COLOR);
1080 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1081 MEMCOLOR_SKIN, memcol);
1082
1083 /* Sky memory color setup */
1084 memcol = msm_property_get_blob(&psde->property_info,
1085 pstate->property_blobs,
1086 &memcol_sz,
1087 PLANE_PROP_SKY_COLOR);
1088 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1089 MEMCOLOR_SKY, memcol);
1090
1091 /* Foliage memory color setup */
1092 memcol = msm_property_get_blob(&psde->property_info,
1093 pstate->property_blobs,
1094 &memcol_sz,
1095 PLANE_PROP_FOLIAGE_COLOR);
1096 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1097 MEMCOLOR_FOLIAGE, memcol);
1098 }
1099}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001100
Clarence Ipcb410d42016-06-26 22:52:33 -04001101static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001102 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -04001103 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001104{
Clarence Ipb43d4592016-09-08 14:21:35 -04001105 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001106 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001107
Clarence Ipb43d4592016-09-08 14:21:35 -04001108 if (!psde || !fmt) {
1109 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1110 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001111 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001112 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001113
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001114 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001115
Clarence Ipdedbba92016-09-27 17:43:10 -04001116 psde->pipe_cfg.horz_decimation =
1117 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1118 psde->pipe_cfg.vert_decimation =
1119 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001120
1121 /* don't chroma subsample if decimating */
1122 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001123 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001124 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001125 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001126
Clarence Ip5e2a9222016-06-26 22:38:24 -04001127 /* update scaler */
1128 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001129 int error;
1130
1131 error = _sde_plane_setup_scaler3_lut(psde, pstate);
Clarence Ip716ab662017-03-20 06:51:24 -07001132 if (error || !psde->pixel_ext_usr ||
1133 psde->debugfs_default_scale) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001134 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001135 _sde_plane_setup_scaler3(psde,
1136 psde->pipe_cfg.src_rect.w,
1137 psde->pipe_cfg.src_rect.h,
1138 psde->pipe_cfg.dst_rect.w,
1139 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001140 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001141 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001142 }
Clarence Ip716ab662017-03-20 06:51:24 -07001143 } else if (!psde->pixel_ext_usr || !pstate ||
1144 psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001145 uint32_t deci_dim, i;
1146
Clarence Ipb43d4592016-09-08 14:21:35 -04001147 /* calculate default configuration for QSEED2 */
1148 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001149
Clarence Ip13a8cf42016-09-29 17:27:47 -04001150 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001151 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1152 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001153 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001154 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001155 psde->pipe_cfg.dst_rect.w,
1156 pe->phase_step_x,
1157 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001158
Clarence Ipdbde9832016-06-26 09:48:36 -04001159 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001160 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001161 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001162 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001163 pe->phase_step_x,
1164 pe->roi_w,
1165 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001166 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001167 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001168
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001169 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001170 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001171 _sde_plane_setup_scaler2(psde,
1172 deci_dim,
1173 psde->pipe_cfg.dst_rect.h,
1174 pe->phase_step_y,
1175 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001176 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001177 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001178 pe->phase_step_y,
1179 pe->roi_h,
1180 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001181 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001182 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001183
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001184 for (i = 0; i < SDE_MAX_PLANES; i++) {
1185 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001186 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001187 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001188 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001189
1190 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001191 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001192 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001193 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001194
1195 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001196 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001197 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001198 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001199
1200 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001201 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001202 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001203 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001204 }
1205 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001206}
1207
Clarence Ipcae1bb62016-07-07 12:07:13 -04001208/**
1209 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001210 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001211 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1212 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1213 * Returns: 0 on success
1214 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001215static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001216 uint32_t color, uint32_t alpha)
1217{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001218 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001219 const struct drm_plane *plane;
1220 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001221
Clarence Ip13a8cf42016-09-29 17:27:47 -04001222 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001223 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001224 return -EINVAL;
1225 }
1226
Clarence Ipcb410d42016-06-26 22:52:33 -04001227 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001228 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001229 return -EINVAL;
1230 }
1231
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001232 plane = &psde->base;
1233 pstate = to_sde_plane_state(plane->state);
1234
Clarence Ip13a8cf42016-09-29 17:27:47 -04001235 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001236
Clarence Ipcb410d42016-06-26 22:52:33 -04001237 /*
1238 * select fill format to match user property expectation,
1239 * h/w only supports RGB variants
1240 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001241 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001242
1243 /* update sspp */
1244 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1245 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001246 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1247 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001248
1249 /* override scaler/decimation if solid fill */
1250 psde->pipe_cfg.src_rect.x = 0;
1251 psde->pipe_cfg.src_rect.y = 0;
1252 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1253 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Dhaval Patele4b6bb22017-03-27 17:22:21 -07001254 _sde_plane_setup_scaler(psde, fmt, 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001255
Clarence Ipcb410d42016-06-26 22:52:33 -04001256 if (psde->pipe_hw->ops.setup_format)
1257 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001258 fmt, SDE_SSPP_SOLID_FILL,
1259 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001260
1261 if (psde->pipe_hw->ops.setup_rects)
1262 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001263 &psde->pipe_cfg,
1264 pstate->multirect_index);
1265
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001266 if (psde->pipe_hw->ops.setup_pe)
1267 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1268 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001269 }
1270
1271 return 0;
1272}
1273
Alan Kwong4dd64c82017-02-04 18:41:51 -08001274/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001275 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1276 */
1277static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1278{
1279 drm_framebuffer_reference(fb);
1280 return fb;
1281}
1282static void _sde_plane_fb_put(void *fb)
1283{
1284 drm_framebuffer_unreference(fb);
1285}
1286static struct sde_crtc_res_ops fb_res_ops = {
1287 .put = _sde_plane_fb_put,
1288 .get = _sde_plane_fb_get,
1289};
1290
1291/**
1292 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1293 */
1294static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1295{
1296 sde_kms_fbo_reference(fbo);
1297 return fbo;
1298}
1299static void _sde_plane_fbo_put(void *fbo)
1300{
1301 sde_kms_fbo_unreference(fbo);
1302}
1303static struct sde_crtc_res_ops fbo_res_ops = {
1304 .put = _sde_plane_fbo_put,
1305 .get = _sde_plane_fbo_get,
1306};
1307
1308/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001309 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001310 * @plane: Pointer to drm plane
1311 * return: prefill time in line
1312 */
1313static u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
1314{
1315 struct drm_plane_state *state;
1316 struct drm_crtc_state *cstate;
1317 struct sde_plane_state *pstate;
1318 struct sde_plane_rot_state *rstate;
1319 struct sde_kms *sde_kms;
1320 u32 blocksize = 128;
1321 u32 prefill_line = 0;
1322
1323 if (!plane || !plane->state || !plane->state->fb ||
1324 !plane->state->crtc || !plane->state->crtc->state) {
1325 SDE_ERROR("invalid parameters\n");
1326 return 0;
1327 }
1328
1329 sde_kms = _sde_plane_get_kms(plane);
1330 state = plane->state;
1331 cstate = state->crtc->state;
1332 pstate = to_sde_plane_state(state);
1333 rstate = &pstate->rot;
1334
1335 if (!rstate->rot_hw || !rstate->rot_hw->caps || !rstate->out_src_h ||
1336 !sde_kms || !sde_kms->catalog) {
1337 SDE_ERROR("invalid parameters\n");
1338 return 0;
1339 }
1340
Alan Kwong4aacd532017-02-04 18:51:33 -08001341 sde_format_get_block_size(rstate->out_fb_format, &blocksize,
1342 &blocksize);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001343 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
1344
1345 SDE_DEBUG("plane%d prefill:%u\n", plane->base.id, prefill_line);
1346
1347 return prefill_line;
1348}
1349
1350/**
1351 * sde_plane_is_sbuf_mode - check if sspp of given plane is in streaming
1352 * buffer mode
1353 * @plane: Pointer to drm plane
1354 * @prefill: Pointer to prefill line count
1355 * return: true if sspp is in stream buffer mode
1356 */
1357bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill)
1358{
1359 struct sde_plane_state *pstate = plane && plane->state ?
1360 to_sde_plane_state(plane->state) : NULL;
1361 struct sde_plane_rot_state *rstate = pstate ? &pstate->rot : NULL;
1362 bool sbuf_mode = rstate ? rstate->out_sbuf : false;
1363
1364 if (prefill && sbuf_mode)
1365 *prefill = sde_plane_rot_calc_prefill(plane);
1366
1367 return sbuf_mode;
1368}
1369
1370/**
1371 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1372 * enumerating over all planes attached to the same rotator
1373 * @plane: Pointer to drm plane
1374 * @state: Pointer to drm state to be updated
1375 * return: none
1376 */
1377static void sde_plane_rot_calc_cfg(struct drm_plane *plane,
1378 struct drm_plane_state *state)
1379{
1380 struct sde_plane_state *pstate;
1381 struct sde_plane_rot_state *rstate;
1382 struct sde_hw_blk *hw_blk;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001383 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001384 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001385 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001386 u32 dst_x, dst_y, dst_w, dst_h;
1387 int found = 0;
1388 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001389 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001390
1391 if (!plane || !state || !state->state) {
1392 SDE_ERROR("invalid parameters\n");
1393 return;
1394 }
1395
Alan Kwongcdb2f282017-03-18 13:42:06 -07001396 cstate = _sde_plane_get_crtc_state(state);
1397 if (IS_ERR_OR_NULL(cstate)) {
1398 ret = PTR_ERR(cstate);
1399 SDE_ERROR("invalid crtc state %d\n", ret);
1400 return;
1401 }
1402
Alan Kwong4dd64c82017-02-04 18:41:51 -08001403 pstate = to_sde_plane_state(state);
1404 rstate = &pstate->rot;
1405
1406 if (!rstate->rot_hw) {
1407 SDE_ERROR("invalid rotator hw\n");
1408 return;
1409 }
1410
1411 in_rot = &rstate->in_rot_rect;
1412 in_rot->x1 = state->src_x;
1413 in_rot->y1 = state->src_y;
1414 in_rot->x2 = state->src_x + state->src_w;
1415 in_rot->y2 = state->src_y + state->src_h;
1416
1417 out_rot = &rstate->out_rot_rect;
1418 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1419 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1420 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1421 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1422
1423 if (!dst_w && !dst_h) {
1424 rstate->out_rot_rect = rstate->in_rot_rect;
1425 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1426 state->fb->height << 16, rstate->in_rotation);
1427 } else {
1428 out_rot->x1 = dst_x;
1429 out_rot->y1 = dst_y;
1430 out_rot->x2 = dst_x + dst_w;
1431 out_rot->y2 = dst_y + dst_h;
1432 }
1433
1434 rstate->out_src_rect = rstate->out_rot_rect;
1435
1436 hw_blk = &rstate->rot_hw->base;
1437
1438 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001439 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001440 struct drm_plane_state *attached_state;
1441 struct sde_plane_state *attached_pstate;
1442 struct sde_plane_rot_state *attached_rstate;
1443 struct drm_rect attached_out_rect;
1444
Alan Kwong4dd64c82017-02-04 18:41:51 -08001445 attached_state = drm_atomic_get_existing_plane_state(
1446 state->state, attached_plane);
1447
1448 if (!attached_state)
1449 continue;
1450
1451 attached_pstate = to_sde_plane_state(attached_state);
1452 attached_rstate = &attached_pstate->rot;
1453
Alan Kwongcdb2f282017-03-18 13:42:06 -07001454 if (attached_rstate->rot_hw != rstate->rot_hw)
1455 continue;
1456
1457 found++;
1458
1459 /* skip itself */
1460 if (attached_plane == plane)
1461 continue;
1462
Alan Kwong4dd64c82017-02-04 18:41:51 -08001463 /* find bounding rotator source roi */
1464 if (attached_state->src_x < in_rot->x1)
1465 in_rot->x1 = attached_state->src_x;
1466
1467 if (attached_state->src_y < in_rot->y1)
1468 in_rot->y1 = attached_state->src_y;
1469
1470 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1471 in_rot->x2 = attached_state->src_x +
1472 attached_state->src_w;
1473
1474 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1475 in_rot->y2 = attached_state->src_y +
1476 attached_state->src_h;
1477
1478 /* find bounding rotator destination roi */
1479 dst_x = sde_plane_get_property(attached_pstate,
1480 PLANE_PROP_ROT_DST_X);
1481 dst_y = sde_plane_get_property(attached_pstate,
1482 PLANE_PROP_ROT_DST_Y);
1483 dst_w = sde_plane_get_property(attached_pstate,
1484 PLANE_PROP_ROT_DST_W);
1485 dst_h = sde_plane_get_property(attached_pstate,
1486 PLANE_PROP_ROT_DST_H);
1487 if (!dst_w && !dst_h) {
1488 attached_out_rect.x1 = attached_state->src_x;
1489 attached_out_rect.y1 = attached_state->src_y;
1490 attached_out_rect.x2 = attached_out_rect.x1 +
1491 attached_state->src_w;
1492 attached_out_rect.y2 = attached_out_rect.y1 +
1493 attached_state->src_h;
1494 drm_rect_rotate(&attached_out_rect,
1495 state->fb->width << 16,
1496 state->fb->height << 16,
1497 rstate->in_rotation);
1498 } else {
1499 attached_out_rect.x1 = dst_x;
1500 attached_out_rect.y1 = dst_y;
1501 attached_out_rect.x2 = dst_x + dst_w;
1502 attached_out_rect.y2 = dst_y + dst_h;
1503 }
1504
1505 /* find relative sspp position */
1506 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1507 xpos++;
1508
1509 if (attached_out_rect.x1 < out_rot->x1)
1510 out_rot->x1 = attached_out_rect.x1;
1511
1512 if (attached_out_rect.y1 < out_rot->y1)
1513 out_rot->y1 = attached_out_rect.y1;
1514
1515 if (attached_out_rect.x2 > out_rot->x2)
1516 out_rot->x2 = attached_out_rect.x2;
1517
1518 if (attached_out_rect.y2 > out_rot->y2)
1519 out_rot->y2 = attached_out_rect.y2;
1520
1521 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1522 attached_plane->base.id,
1523 attached_rstate->sequence_id,
1524 attached_rstate->out_src_rect.x1 >> 16,
1525 attached_state->src_w >> 16,
1526 attached_state->src_h >> 16,
1527 attached_state->src_x >> 16,
1528 attached_state->src_y >> 16,
1529 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1530 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1531 attached_rstate->out_src_rect.x1 >> 16,
1532 attached_rstate->out_src_rect.y1 >> 16);
1533 }
1534
1535 rstate->out_xpos = xpos;
1536 rstate->nplane = found;
1537
1538 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1539 plane->base.id, rstate->sequence_id,
1540 rstate->out_xpos, rstate->nplane,
1541 drm_rect_width(in_rot) >> 16,
1542 drm_rect_height(in_rot) >> 16,
1543 in_rot->x1 >> 16, in_rot->y1 >> 16,
1544 drm_rect_width(&rstate->out_rot_rect) >> 16,
1545 drm_rect_height(&rstate->out_rot_rect) >> 16,
1546 rstate->out_rot_rect.x1 >> 16,
1547 rstate->out_rot_rect.y1 >> 16);
1548}
1549
1550/**
1551 * sde_plane_rot_submit_command - commit given state for the rotator stage
1552 * @plane: Pointer to drm plane
1553 * @state: Pointer to the state to be committed
1554 * @hw_cmd: rotator command type
1555 * return: 0 if success; error code otherwise
1556 */
1557static int sde_plane_rot_submit_command(struct drm_plane *plane,
1558 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1559{
1560 struct sde_plane *psde = to_sde_plane(plane);
1561 struct sde_plane_state *pstate = to_sde_plane_state(state);
1562 struct sde_plane_rot_state *rstate = &pstate->rot;
1563 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001564 struct drm_crtc_state *cstate;
1565 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001566 int ret, i;
1567
1568 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1569 SDE_ERROR("invalid parameters\n");
1570 return -EINVAL;
1571 }
1572
Alan Kwong4aacd532017-02-04 18:51:33 -08001573 cstate = _sde_plane_get_crtc_state(state);
1574 if (IS_ERR_OR_NULL(cstate)) {
1575 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1576 return -EINVAL;
1577 }
1578 sde_cstate = to_sde_crtc_state(cstate);
1579
Alan Kwong4dd64c82017-02-04 18:41:51 -08001580 rot_cmd = &rstate->rot_cmd;
1581
1582 rot_cmd->master = (rstate->out_xpos == 0);
1583 rot_cmd->sequence_id = rstate->sequence_id;
1584 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1585 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1586 DEFAULT_REFRESH_RATE;
1587 rot_cmd->rot90 = rstate->rot90;
1588 rot_cmd->hflip = rstate->hflip;
1589 rot_cmd->vflip = rstate->vflip;
1590 rot_cmd->secure = state->fb->flags & DRM_MODE_FB_SECURE ? true : false;
Alan Kwong4aacd532017-02-04 18:51:33 -08001591 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1592 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001593 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1594 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001595 rot_cmd->dst_writeback = psde->sbuf_writeback;
1596
1597 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1598 rot_cmd->video_mode = true;
1599 else
1600 rot_cmd->video_mode = false;
1601
1602 rot_cmd->src_pixel_format = state->fb->pixel_format;
1603 rot_cmd->src_modifier = state->fb->modifier[0];
1604 rot_cmd->src_stride = state->fb->pitches[0];
1605
1606 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1607 if (!rot_cmd->src_format) {
1608 SDE_ERROR("failed to get src format\n");
1609 return -EINVAL;
1610 }
1611
1612 rot_cmd->src_width = state->fb->width;
1613 rot_cmd->src_height = state->fb->height;
1614 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1615 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1616 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1617 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
1618 rot_cmd->dst_rect_x = rstate->out_rot_rect.x1 >> 16;
1619 rot_cmd->dst_rect_y = rstate->out_rot_rect.y1 >> 16;
1620 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1621 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1622
1623 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1624 struct sde_hw_fmt_layout layout;
1625
1626 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1627 sde_format_populate_layout(rstate->mmu_id, state->fb,
1628 &layout);
1629 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1630 rot_cmd->src_iova[i] = layout.plane_addr[i];
1631 rot_cmd->src_len[i] = layout.plane_size[i];
1632 }
1633 rot_cmd->src_planes = layout.num_planes;
1634
1635 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1636 sde_format_populate_layout(rstate->mmu_id, rstate->out_fb,
1637 &layout);
1638 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1639 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1640 rot_cmd->dst_len[i] = layout.plane_size[i];
1641 }
1642 rot_cmd->dst_planes = layout.num_planes;
1643 }
1644
1645 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
1646 if (ret) {
1647 SDE_ERROR("failed to commit rotator %d\n", ret);
1648 return ret;
1649 }
1650
1651 rstate->out_rotation = rstate->in_rotation;
1652 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1653 DRM_MODE_FB_MODIFIERS : 0;
1654 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1655 rstate->out_fb_format = rot_cmd->dst_format;
1656 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1657
1658 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1659 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1660
1661 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1662 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1663 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1664 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1665 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1666 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1667
1668 if (rot_cmd->rot90)
1669 rstate->out_rotation &= ~DRM_ROTATE_90;
1670
1671 if (rot_cmd->hflip)
1672 rstate->out_rotation &= ~DRM_REFLECT_X;
1673
1674 if (rot_cmd->vflip)
1675 rstate->out_rotation &= ~DRM_REFLECT_Y;
1676
1677 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07001678 "plane%d.%d rot:%d/%c%c%c%c/%dx%d/%4.4s/%llx/%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001679 plane->base.id, rstate->sequence_id, hw_cmd,
1680 rot_cmd->rot90 ? 'r' : '_',
1681 rot_cmd->hflip ? 'h' : '_',
1682 rot_cmd->vflip ? 'v' : '_',
1683 rot_cmd->video_mode ? 'V' : 'C',
1684 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001685 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001686 state->fb->modifier[0],
1687 drm_rect_width(&rstate->in_rot_rect) >> 16,
1688 drm_rect_height(&rstate->in_rot_rect) >> 16,
1689 rstate->in_rot_rect.x1 >> 16,
1690 rstate->in_rot_rect.y1 >> 16);
1691
Dhaval Patel6c666622017-03-21 23:02:59 -07001692 SDE_DEBUG("plane%d.%d sspp:%d/%x/%dx%d/%4.4s/%llx/%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001693 plane->base.id, rstate->sequence_id, hw_cmd,
1694 rstate->out_rotation,
1695 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001696 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001697 rstate->out_fb_modifier[0],
1698 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
1699 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
1700
1701 return ret;
1702}
1703
1704/**
1705 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
1706 * for rotator (pre-sspp) stage
1707 * @plane: Pointer to drm plane
1708 * @new_state: Pointer to new drm plane state
1709 * return: 0 if success; error code otherwise
1710 */
1711static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
1712 struct drm_plane_state *new_state)
1713{
1714 struct drm_framebuffer *fb = new_state->fb;
1715 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
1716 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001717 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001718 int ret;
1719
1720 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
1721 plane->base.id,
1722 new_rstate->sequence_id, fb ? fb->base.id : 0,
1723 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
1724 sde_plane_crtc_enabled(new_state));
1725
1726 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
1727 return 0;
1728
Alan Kwongcdb2f282017-03-18 13:42:06 -07001729 cstate = _sde_plane_get_crtc_state(new_state);
1730 if (IS_ERR(cstate)) {
1731 ret = PTR_ERR(cstate);
1732 SDE_ERROR("invalid crtc state %d\n", ret);
1733 return ret;
1734 }
1735
Alan Kwong4dd64c82017-02-04 18:41:51 -08001736 /* need to re-calc based on all newly validated plane states */
1737 sde_plane_rot_calc_cfg(plane, new_state);
1738
1739 /* check if stream buffer is already attached to rotator */
1740 if (sde_plane_enabled(new_state)) {
1741 struct sde_kms_fbo *fbo;
1742 struct drm_framebuffer *fb;
1743
Alan Kwongcdb2f282017-03-18 13:42:06 -07001744 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1745 (u64) &new_rstate->rot_hw->base);
1746 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1747 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001748 if (fb && fbo) {
1749 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
1750 new_rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001751 } else if (fbo) {
1752 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1753 (u64) &new_rstate->rot_hw->base);
1754 fbo = NULL;
1755 } else if (fb) {
1756 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1757 (u64) &new_rstate->rot_hw->base);
1758 fb = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001759 }
Alan Kwongcdb2f282017-03-18 13:42:06 -07001760
1761 new_rstate->out_fbo = fbo;
1762 new_rstate->out_fb = fb;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001763 }
1764
1765 /* release buffer if output format configuration changes */
1766 if (new_rstate->out_fb &&
1767 ((new_rstate->out_fb_height != new_rstate->out_fb->height) ||
1768 (new_rstate->out_fb_width != new_rstate->out_fb->width) ||
1769 (new_rstate->out_fb_pixel_format !=
1770 new_rstate->out_fb->pixel_format) ||
1771 (new_rstate->out_fb_modifier[0] !=
1772 new_rstate->out_fb->modifier[0]) ||
1773 (new_rstate->out_fb_flags != new_rstate->out_fb->flags))) {
1774
1775 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
1776 new_rstate->sequence_id);
1777
Alan Kwongcdb2f282017-03-18 13:42:06 -07001778 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1779 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001780 new_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001781 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1782 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001783 new_rstate->out_fbo = NULL;
1784 }
1785
1786 /* create new stream buffer if it is not available */
1787 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
1788 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
1789 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
1790
1791 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
1792 new_rstate->sequence_id);
1793
1794 if (new_state->fb->flags & DRM_MODE_FB_SECURE)
1795 new_rstate->mmu_id = MSM_SMMU_DOMAIN_SECURE;
1796 else
1797 new_rstate->mmu_id = MSM_SMMU_DOMAIN_UNSECURE;
1798
1799 /* check if out_fb is already attached to rotator */
1800 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
1801 new_rstate->out_fb_pixel_format,
1802 new_rstate->out_fb_modifier,
1803 new_rstate->out_fb_flags);
1804 if (!new_rstate->out_fbo) {
1805 SDE_ERROR("failed to allocate inline buffer object\n");
1806 ret = -EINVAL;
1807 goto error_create_fbo;
1808 }
1809
Alan Kwongcdb2f282017-03-18 13:42:06 -07001810 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1811 (u64) &new_rstate->rot_hw->base,
1812 new_rstate->out_fbo, &fbo_res_ops);
1813 if (ret) {
1814 SDE_ERROR("failed to add crtc resource\n");
1815 goto error_create_fbo_res;
1816 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001817
1818 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
1819 new_rstate->out_fbo);
1820 if (!new_rstate->out_fb) {
1821 SDE_ERROR("failed to create inline framebuffer\n");
1822 ret = -EINVAL;
1823 goto error_create_fb;
1824 }
1825
Alan Kwongcdb2f282017-03-18 13:42:06 -07001826 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1827 (u64) &new_rstate->rot_hw->base,
1828 new_rstate->out_fb, &fb_res_ops);
1829 if (ret) {
1830 SDE_ERROR("failed to add crtc resource %d\n", ret);
1831 goto error_create_fb_res;
1832 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001833 }
1834
1835 /* prepare rotator input buffer */
1836 ret = msm_framebuffer_prepare(new_state->fb, new_rstate->mmu_id);
1837 if (ret) {
1838 SDE_ERROR("failed to prepare input framebuffer\n");
1839 goto error_prepare_input_buffer;
1840 }
1841
1842 /* prepare rotator output buffer */
1843 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
1844 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
1845 new_rstate->sequence_id);
1846
1847 ret = msm_framebuffer_prepare(new_rstate->out_fb,
1848 new_rstate->mmu_id);
1849 if (ret) {
1850 SDE_ERROR("failed to prepare inline framebuffer\n");
1851 goto error_prepare_output_buffer;
1852 }
1853 }
1854
1855 return 0;
1856
1857error_prepare_output_buffer:
1858 msm_framebuffer_cleanup(new_state->fb, new_rstate->mmu_id);
1859error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001860 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1861 (u64) &new_rstate->rot_hw->base);
1862error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001863 new_rstate->out_fb = NULL;
1864error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001865 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1866 (u64) &new_rstate->rot_hw->base);
1867error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001868 new_rstate->out_fbo = NULL;
1869error_create_fbo:
1870 return ret;
1871}
1872
1873/**
1874 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
1875 * rotator (pre-sspp) stage
1876 * @plane: Pointer to drm plane
1877 * @old_state: Pointer to previous drm plane state
1878 * return: none
1879 */
1880static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
1881 struct drm_plane_state *old_state)
1882{
1883 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
1884 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
1885 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001886 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001887 int ret;
1888
1889 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1890 old_rstate->sequence_id, old_state->fb->base.id,
1891 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
1892 sde_plane_crtc_enabled(old_state));
1893
1894 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
1895 return;
1896
Alan Kwongcdb2f282017-03-18 13:42:06 -07001897 cstate = _sde_plane_get_crtc_state(old_state);
1898 if (IS_ERR(cstate)) {
1899 ret = PTR_ERR(cstate);
1900 SDE_ERROR("invalid crtc state %d\n", ret);
1901 return;
1902 }
1903
Alan Kwong4dd64c82017-02-04 18:41:51 -08001904 if (sde_plane_crtc_enabled(old_state)) {
1905 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
1906 SDE_HW_ROT_CMD_CLEANUP);
1907 if (ret)
1908 SDE_ERROR("failed to cleanup rotator buffers\n");
1909 }
1910
1911 if (sde_plane_enabled(old_state)) {
1912 if (old_rstate->out_fb) {
1913 msm_framebuffer_cleanup(old_rstate->out_fb,
1914 old_rstate->mmu_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001915 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1916 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001917 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001918 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1919 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001920 old_rstate->out_fbo = NULL;
1921 }
1922
1923 msm_framebuffer_cleanup(old_state->fb, old_rstate->mmu_id);
1924 }
1925}
1926
1927/**
1928 * sde_plane_rot_atomic_check - verify rotator update of the given state
1929 * @plane: Pointer to drm plane
1930 * @state: Pointer to drm plane state to be validated
1931 * return: 0 if success; error code otherwise
1932 */
1933static int sde_plane_rot_atomic_check(struct drm_plane *plane,
1934 struct drm_plane_state *state)
1935{
1936 struct sde_plane *psde;
1937 struct sde_plane_state *pstate, *old_pstate;
1938 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001939 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001940 struct sde_hw_blk *hw_blk;
1941 int i, ret = 0;
1942
1943 if (!plane || !state) {
1944 SDE_ERROR("invalid plane/state\n");
1945 return -EINVAL;
1946 }
1947
1948 psde = to_sde_plane(plane);
1949 pstate = to_sde_plane_state(state);
1950 old_pstate = to_sde_plane_state(plane->state);
1951 rstate = &pstate->rot;
1952 old_rstate = &old_pstate->rot;
1953
Alan Kwongcdb2f282017-03-18 13:42:06 -07001954 /* cstate will be null if crtc is disconnected from plane */
1955 cstate = _sde_plane_get_crtc_state(state);
1956 if (IS_ERR(cstate)) {
1957 ret = PTR_ERR(cstate);
1958 SDE_ERROR("invalid crtc state %d\n", ret);
1959 return ret;
1960 }
1961
Alan Kwong4dd64c82017-02-04 18:41:51 -08001962 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1963 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
1964 !!rstate->out_sbuf, !!rstate->rot_hw,
1965 sde_plane_crtc_enabled(state));
1966
1967 rstate->in_rotation = drm_rotation_simplify(
1968 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07001969 DRM_ROTATE_0 | DRM_ROTATE_90 |
1970 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001971 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
1972 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
1973 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
1974 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
1975
Alan Kwongcdb2f282017-03-18 13:42:06 -07001976 if (sde_plane_enabled(state) && rstate->out_sbuf) {
1977 SDE_DEBUG("plane%d.%d acquire rotator\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001978 plane->base.id, rstate->sequence_id);
1979
Alan Kwongcdb2f282017-03-18 13:42:06 -07001980 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
1981 (u64) state->fb);
1982 if (!hw_blk) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001983 SDE_ERROR("plane%d no available rotator\n",
1984 plane->base.id);
1985 return -EINVAL;
1986 }
1987
Alan Kwongcdb2f282017-03-18 13:42:06 -07001988 rstate->rot_hw = to_sde_hw_rot(hw_blk);
1989
Alan Kwong4dd64c82017-02-04 18:41:51 -08001990 if (!rstate->rot_hw->ops.commit) {
1991 SDE_ERROR("plane%d invalid rotator ops\n",
1992 plane->base.id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001993 sde_crtc_res_put(cstate,
1994 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001995 rstate->rot_hw = NULL;
1996 return -EINVAL;
1997 }
1998
1999 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002000 } else {
2001 rstate->in_fb = NULL;
2002 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002003 }
2004
2005 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
2006
2007 SDE_DEBUG("plane%d.%d use rotator\n",
2008 plane->base.id, rstate->sequence_id);
2009
2010 sde_plane_rot_calc_cfg(plane, state);
2011
2012 ret = sde_plane_rot_submit_command(plane, state,
2013 SDE_HW_ROT_CMD_VALIDATE);
2014
Clarence Ip4475d582017-04-18 11:36:00 -04002015 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002016
2017 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
2018 rstate->sequence_id);
2019
2020 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04002021 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
2022 rstate->out_fb_modifier[i] = state->fb ?
2023 state->fb->modifier[i] : 0x0;
2024
2025 if (state->fb) {
2026 rstate->out_fb_pixel_format = state->fb->pixel_format;
2027 rstate->out_fb_flags = state->fb->flags;
2028 rstate->out_fb_width = state->fb->width;
2029 rstate->out_fb_height = state->fb->height;
2030 } else {
2031 rstate->out_fb_pixel_format = 0x0;
2032 rstate->out_fb_flags = 0x0;
2033 rstate->out_fb_width = 0;
2034 rstate->out_fb_height = 0;
2035 }
2036
Alan Kwong4dd64c82017-02-04 18:41:51 -08002037 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002038 rstate->out_src_x = state->src_x;
2039 rstate->out_src_y = state->src_y;
2040 rstate->out_src_w = state->src_w;
2041 rstate->out_src_h = state->src_h;
2042
2043 rstate->out_fb_format = NULL;
2044 rstate->out_sbuf = false;
2045 rstate->out_fb = state->fb;
2046 }
2047
2048 return ret;
2049}
2050
2051/**
2052 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2053 * @plane: Pointer to drm plane
2054 * @old_state: Pointer to previous state
2055 * return: none
2056 */
2057static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2058 struct drm_plane_state *old_state)
2059{
2060 struct drm_plane_state *state;
2061 struct sde_plane_state *pstate;
2062 struct sde_plane_rot_state *rstate;
2063
2064 if (!plane || !plane->state) {
2065 SDE_ERROR("invalid plane/state\n");
2066 return;
2067 }
2068
2069 state = plane->state;
2070 pstate = to_sde_plane_state(state);
2071 rstate = &pstate->rot;
2072
2073 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2074 rstate->sequence_id,
2075 !!rstate->out_sbuf, !!rstate->rot_hw,
2076 sde_plane_crtc_enabled(plane->state));
2077
2078 if (!sde_plane_crtc_enabled(state))
2079 return;
2080
2081 if (!rstate->out_sbuf || !rstate->rot_hw)
2082 return;
2083
2084 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
2085}
2086
2087/**
Clarence Ipddbf7752017-05-21 18:07:30 -04002088 * sde_plane_rot_flush - perform final flush related rotator options
2089 * @plane: Pointer to drm plane
2090 * @pstate: Pointer to sde plane state
2091 */
2092static void sde_plane_rot_flush(struct drm_plane *plane,
2093 struct sde_plane_state *pstate)
2094{
2095 if (!plane || !pstate || !pstate->rot.rot_hw ||
2096 !pstate->rot.rot_hw->ops.commit)
2097 return;
2098
2099 pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
2100 &pstate->rot.rot_cmd,
2101 SDE_HW_ROT_CMD_START);
2102}
2103
2104/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002105 * sde_plane_rot_destroy_state - destroy state for rotator stage
2106 * @plane: Pointer to drm plane
2107 * @state: Pointer to state to be destroyed
2108 * return: none
2109 */
2110static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2111 struct drm_plane_state *state)
2112{
2113 struct sde_plane_state *pstate = to_sde_plane_state(state);
2114 struct sde_plane_rot_state *rstate = &pstate->rot;
2115
2116 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2117 rstate->sequence_id,
2118 !!rstate->out_sbuf, !!rstate->rot_hw,
2119 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002120}
2121
2122/**
2123 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2124 * @plane: Pointer to drm plane
2125 * @new_state: Pointer to duplicated state
2126 * return: 0 if success; error code otherwise
2127 */
2128static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2129 struct drm_plane_state *new_state)
2130{
2131 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2132 struct sde_plane_rot_state *rstate = &pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002133 struct drm_crtc_state *cstate;
2134 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002135
2136 rstate->sequence_id++;
2137
2138 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2139 rstate->sequence_id,
2140 !!rstate->out_sbuf, !!rstate->rot_hw);
2141
Alan Kwongcdb2f282017-03-18 13:42:06 -07002142 cstate = _sde_plane_get_crtc_state(new_state);
2143 if (IS_ERR(cstate)) {
2144 ret = PTR_ERR(cstate);
2145 SDE_ERROR("invalid crtc state %d\n", ret);
2146 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002147 }
2148
Alan Kwongcdb2f282017-03-18 13:42:06 -07002149 if (rstate->rot_hw && cstate)
2150 sde_crtc_res_get(cstate, SDE_HW_BLK_ROT, (u64) rstate->in_fb);
2151 else if (rstate->rot_hw && !cstate)
2152 SDE_ERROR("plane%d.%d zombie rotator hw\n",
2153 plane->base.id, rstate->sequence_id);
2154
Alan Kwong4dd64c82017-02-04 18:41:51 -08002155 rstate->out_fb = NULL;
2156 rstate->out_fbo = NULL;
2157
2158 return 0;
2159}
2160
2161/**
2162 * sde_plane_rot_install_caps - install plane rotator capabilities
2163 * @plane: Pointer to drm plane
2164 * return: none
2165 */
2166static void sde_plane_rot_install_caps(struct drm_plane *plane)
2167{
2168 struct sde_plane *psde = to_sde_plane(plane);
2169 const struct sde_format_extended *format_list;
2170 struct sde_kms_info *info;
2171 struct sde_hw_rot *rot_hw;
2172 const char *downscale_caps;
2173
2174 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2175 !psde->catalog->rot_count)
2176 return;
2177
2178 if (psde->blob_rot_caps)
2179 return;
2180
2181 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2182 if (!info)
2183 return;
2184
2185 rot_hw = sde_hw_rot_get(NULL);
2186 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2187 !rot_hw->ops.get_downscale_caps) {
2188 SDE_ERROR("invalid rotator hw\n");
2189 goto error_rot;
2190 }
2191
2192 sde_kms_info_reset(info);
2193
2194 format_list = rot_hw->ops.get_format_caps(rot_hw);
2195 if (format_list) {
2196 sde_kms_info_start(info, "pixel_formats");
2197 while (format_list->fourcc_format) {
2198 sde_kms_info_append_format(info,
2199 format_list->fourcc_format,
2200 format_list->modifier);
2201 ++format_list;
2202 }
2203 sde_kms_info_stop(info);
2204 }
2205
2206 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2207 if (downscale_caps) {
2208 sde_kms_info_start(info, "downscale_ratios");
2209 sde_kms_info_append(info, downscale_caps);
2210 sde_kms_info_stop(info);
2211 }
2212
2213 if (rot_hw->ops.get_cache_size)
2214 sde_kms_info_add_keyint(info, "cache_size",
2215 rot_hw->ops.get_cache_size(rot_hw));
2216
Alan Kwong1a915802017-03-31 12:55:46 -07002217 if (rot_hw->ops.get_maxlinewidth)
2218 sde_kms_info_add_keyint(info, "max_linewidth",
2219 rot_hw->ops.get_maxlinewidth(rot_hw));
2220
Alan Kwong4dd64c82017-02-04 18:41:51 -08002221 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
2222 info->data, info->len, PLANE_PROP_ROT_CAPS_V1);
2223
2224 sde_hw_rot_put(rot_hw);
2225error_rot:
2226 kfree(info);
2227}
2228
2229/**
2230 * sde_plane_rot_install_properties - install plane rotator properties
2231 * @plane: Pointer to drm plane
2232 * @catalog: Pointer to mdss configuration
2233 * return: none
2234 */
2235static void sde_plane_rot_install_properties(struct drm_plane *plane,
2236 struct sde_mdss_cfg *catalog)
2237{
2238 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002239 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2240 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002241
2242 if (!plane || !psde) {
2243 SDE_ERROR("invalid plane\n");
2244 return;
2245 } else if (!catalog) {
2246 SDE_ERROR("invalid catalog\n");
2247 return;
2248 }
2249
2250 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2251 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2252 DRM_ROTATE_180 | DRM_ROTATE_270;
2253
2254 msm_property_install_rotation(&psde->property_info,
2255 supported_rotations, PLANE_PROP_ROTATION);
2256
2257 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2258 return;
2259
2260 msm_property_install_range(&psde->property_info, "rot_dst_x",
2261 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2262 msm_property_install_range(&psde->property_info, "rot_dst_y",
2263 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2264 msm_property_install_range(&psde->property_info, "rot_dst_w",
2265 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2266 msm_property_install_range(&psde->property_info, "rot_dst_h",
2267 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2268 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2269 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2270}
2271
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002272void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002273{
Clarence Ipcb410d42016-06-26 22:52:33 -04002274 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002275
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002276 if (!drm_state)
2277 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002278
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002279 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002280
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002281 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2282 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002283}
2284
2285int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2286{
2287 struct sde_plane_state *pstate[R_MAX];
2288 const struct drm_plane_state *drm_state[R_MAX];
2289 struct sde_rect src[R_MAX], dst[R_MAX];
2290 struct sde_plane *sde_plane[R_MAX];
2291 const struct sde_format *fmt[R_MAX];
2292 bool q16_data = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002293 int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
2294 bool parallel_fetch_qualified = true;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002295
2296 for (i = 0; i < R_MAX; i++) {
2297 const struct msm_format *msm_fmt;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002298 int width_threshold;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002299
2300 drm_state[i] = i ? plane->r1 : plane->r0;
2301 pstate[i] = to_sde_plane_state(drm_state[i]);
2302 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2303
2304 if (pstate[i] == NULL) {
2305 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2306 drm_state[i]->plane->base.id);
2307 return -EINVAL;
2308 }
2309
2310 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2311 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2312 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2313 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2314 drm_state[i]->crtc_h, !q16_data);
2315
2316 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2317 SDE_ERROR_PLANE(sde_plane[i],
2318 "scaling is not supported in multirect mode\n");
2319 return -EINVAL;
2320 }
2321
2322 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2323 fmt[i] = to_sde_format(msm_fmt);
2324 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2325 SDE_ERROR_PLANE(sde_plane[i],
2326 "Unsupported format for multirect mode\n");
2327 return -EINVAL;
2328 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002329
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002330 /**
2331 * SSPP PD_MEM is split half - one for each RECT.
2332 * Tiled formats need 5 lines of buffering while fetching
2333 * whereas linear formats need only 2 lines.
2334 * So we cannot support more than half of the supported SSPP
2335 * width for tiled formats.
2336 */
2337 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
2338 if (SDE_FORMAT_IS_UBWC(fmt[i]))
2339 width_threshold /= 2;
2340
2341 if (parallel_fetch_qualified && src[i].w > width_threshold)
2342 parallel_fetch_qualified = false;
2343
2344 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002345
2346 /* Validate RECT's and set the mode */
2347
2348 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002349 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002350 if (dst[R0].x <= dst[R1].x) {
2351 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2352 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2353 } else {
2354 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2355 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2356 }
2357
2358 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2359 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2360 goto done;
2361 }
2362
2363 /* TIME_MX Mode */
2364 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
2365 buffer_lines = 2 * fmt[R0]->tile_height;
2366
2367 if (dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) {
2368 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2369 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2370 } else if (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines) {
2371 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2372 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2373 } else {
2374 SDE_ERROR(
2375 "No multirect mode possible for the planes (%d - %d)\n",
2376 drm_state[R0]->plane->base.id,
2377 drm_state[R1]->plane->base.id);
2378 return -EINVAL;
2379 }
2380
2381 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2382 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2383done:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002384 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2385 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2386 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2387 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002388 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002389}
2390
Alan Kwong4dd64c82017-02-04 18:41:51 -08002391/**
2392 * sde_plane_get_ctl_flush - get control flush for the given plane
2393 * @plane: Pointer to drm plane structure
2394 * @ctl: Pointer to hardware control driver
2395 * @flush: Pointer to flush control word
2396 */
2397void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
2398 u32 *flush)
2399{
2400 struct sde_plane_state *pstate;
2401 struct sde_plane_rot_state *rstate;
2402 u32 bitmask;
2403
2404 if (!plane || !flush) {
2405 SDE_ERROR("invalid parameters\n");
2406 return;
2407 }
2408
2409 pstate = to_sde_plane_state(plane->state);
2410 rstate = &pstate->rot;
2411
2412 bitmask = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
2413
2414 if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
2415 ctl->ops.get_bitmask_rot)
2416 ctl->ops.get_bitmask_rot(ctl, &bitmask, rstate->rot_hw->idx);
2417
2418 *flush = bitmask;
2419}
2420
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002421static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002422 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002423{
2424 struct drm_framebuffer *fb = new_state->fb;
2425 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002426 struct sde_plane_rot_state *new_rstate;
2427 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002428
2429 if (!new_state->fb)
2430 return 0;
2431
Clarence Ip13a8cf42016-09-29 17:27:47 -04002432 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002433
2434 ret = sde_plane_rot_prepare_fb(plane, new_state);
2435 if (ret) {
2436 SDE_ERROR("failed to prepare rot framebuffer\n");
2437 return ret;
2438 }
2439
2440 new_rstate = &to_sde_plane_state(new_state)->rot;
2441
2442 ret = msm_framebuffer_prepare(new_rstate->out_fb, new_rstate->mmu_id);
2443 if (ret) {
2444 SDE_ERROR("failed to prepare framebuffer\n");
2445 return ret;
2446 }
2447
2448 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002449}
2450
2451static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002452 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002453{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002454 struct sde_plane *psde = to_sde_plane(plane);
2455 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002456
Alan Kwong4dd64c82017-02-04 18:41:51 -08002457 if (!old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002458 return;
2459
Alan Kwong4dd64c82017-02-04 18:41:51 -08002460 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2461
2462 old_rstate = &to_sde_plane_state(old_state)->rot;
2463
2464 msm_framebuffer_cleanup(old_rstate->out_fb, old_rstate->mmu_id);
2465
2466 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002467}
2468
Alan Kwong4dd64c82017-02-04 18:41:51 -08002469static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002470 struct drm_plane_state *state,
2471 struct drm_plane_state *old_state)
2472{
2473 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002474 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002475 struct sde_plane_rot_state *rstate = &pstate->rot;
2476 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2477 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002478
Dhaval Patel47302cf2016-08-18 15:04:28 -07002479 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002480 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002481 return;
2482
Clarence Ip282dad62016-09-27 17:07:35 -04002483 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2484 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002485 SDE_DEBUG_PLANE(psde,
2486 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002487 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002488 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002489 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002490 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002491 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2492 pstate->multirect_mode != old_pstate->multirect_mode) {
2493 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2494 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002495 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2496 rstate->out_src_h != old_rstate->out_src_h ||
2497 rstate->out_src_x != old_rstate->out_src_x ||
2498 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002499 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002500 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002501 } else if (state->crtc_w != old_state->crtc_w ||
2502 state->crtc_h != old_state->crtc_h ||
2503 state->crtc_x != old_state->crtc_x ||
2504 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002505 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002506 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002507 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2508 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2509 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2510 pstate->excl_rect.y != old_pstate->excl_rect.y) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07002511 SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002512 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002513 }
2514
Alan Kwong4dd64c82017-02-04 18:41:51 -08002515 fb = rstate->out_fb;
2516 old_fb = old_rstate->out_fb;
2517
2518 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002519 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002520 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002521 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002522 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002523 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002524 uint64_t *new_mods = fb->modifier;
2525 uint64_t *old_mods = old_fb->modifier;
2526 uint32_t *new_pitches = fb->pitches;
2527 uint32_t *old_pitches = old_fb->pitches;
2528 uint32_t *new_offset = fb->offsets;
2529 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002530 int i;
2531
Alan Kwong4dd64c82017-02-04 18:41:51 -08002532 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002533 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002534 SDE_DEBUG_PLANE(psde,
2535 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002536 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002537 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002538 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2539 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002540 break;
2541 }
2542 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002543 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002544 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002545 SDE_DEBUG_PLANE(psde,
2546 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002547 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002548 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002549 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002550 break;
2551 }
2552 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002553 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002554 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002555 SDE_DEBUG_PLANE(psde,
2556 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002557 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002558 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002559 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2560 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002561 break;
2562 }
2563 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002564 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002565}
2566
Alan Kwong4dd64c82017-02-04 18:41:51 -08002567static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002568 struct drm_plane_state *state)
2569{
Clarence Ipdedbba92016-09-27 17:43:10 -04002570 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04002571 struct sde_plane *psde;
2572 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002573 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002574 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002575 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04002576 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002577 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
2578 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04002579
2580 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002581 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2582 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04002583 ret = -EINVAL;
2584 goto exit;
2585 }
2586
2587 psde = to_sde_plane(plane);
2588 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002589 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04002590
2591 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002592 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002593 ret = -EINVAL;
2594 goto exit;
2595 }
2596
Clarence Ipdedbba92016-09-27 17:43:10 -04002597 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
2598 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04002599
2600 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002601 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2602 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002603 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
2604 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04002605
Dhaval Patel47302cf2016-08-18 15:04:28 -07002606 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
2607 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04002608
Dhaval Patel47302cf2016-08-18 15:04:28 -07002609 max_upscale = psde->pipe_sblk->maxupscale;
2610 max_downscale = psde->pipe_sblk->maxdwnscale;
2611 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04002612
Clarence Ip13a8cf42016-09-29 17:27:47 -04002613 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002614 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002615
Dhaval Patel47302cf2016-08-18 15:04:28 -07002616 if (!sde_plane_enabled(state))
2617 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04002618
Alan Kwong4dd64c82017-02-04 18:41:51 -08002619 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002620 "plane%d.%u sspp:%x/%dx%d/%4.4s/%llx/%dx%d+%d+%d crtc:%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08002621 plane->base.id, rstate->sequence_id,
2622 rstate->out_rotation,
2623 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002624 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002625 rstate->out_fb_modifier[0],
2626 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2627 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2628 state->crtc_w, state->crtc_h,
2629 state->crtc_x, state->crtc_y);
2630
Dhaval Patel47302cf2016-08-18 15:04:28 -07002631 fmt = to_sde_format(msm_framebuffer_format(state->fb));
2632
2633 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
2634
2635 if (SDE_FORMAT_IS_YUV(fmt) &&
2636 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04002637 !(psde->features & (BIT(SDE_SSPP_CSC)
2638 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002639 SDE_ERROR_PLANE(psde,
2640 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07002641 ret = -EINVAL;
2642
2643 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002644 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
2645 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07002646 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08002647 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
2648 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002649 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002650 src.x, src.y, src.w, src.h);
2651 ret = -E2BIG;
2652
2653 /* valid yuv image */
2654 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
2655 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002656 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002657 src.x, src.y, src.w, src.h);
2658 ret = -EINVAL;
2659
2660 /* min dst support */
2661 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002662 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002663 dst.x, dst.y, dst.w, dst.h);
2664 ret = -EINVAL;
2665
2666 /* decimation validation */
2667 } else if (deci_w || deci_h) {
2668 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
2669 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002670 SDE_ERROR_PLANE(psde,
2671 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002672 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002673 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002674 SDE_ERROR_PLANE(psde,
2675 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002676 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002677 }
2678
Dhaval Patel47302cf2016-08-18 15:04:28 -07002679 } else if (!(psde->features & SDE_SSPP_SCALER) &&
2680 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002681 SDE_ERROR_PLANE(psde,
2682 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002683 src.w, src.h, dst.w, dst.h);
2684 ret = -EINVAL;
2685
2686 /* check decimated source width */
2687 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002688 SDE_ERROR_PLANE(psde,
2689 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002690 src.w, src_deci_w, max_linewidth);
2691 ret = -E2BIG;
2692
2693 /* check max scaler capability */
2694 } else if (((src_deci_w * max_upscale) < dst.w) ||
2695 ((src_deci_h * max_upscale) < dst.h) ||
2696 ((dst.w * max_downscale) < src_deci_w) ||
2697 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002698 SDE_ERROR_PLANE(psde,
2699 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002700 src_deci_w, src_deci_h, dst.w, dst.h);
2701 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002702 }
2703
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002704 /* check excl rect configs */
2705 if (pstate->excl_rect.w && pstate->excl_rect.h) {
2706 struct sde_rect intersect;
2707
2708 /*
2709 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002710 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002711 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05002712 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002713 if (intersect.w != pstate->excl_rect.w ||
2714 intersect.h != pstate->excl_rect.h ||
2715 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002716 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07002717 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002718 pstate->excl_rect.x, pstate->excl_rect.y,
2719 pstate->excl_rect.w, pstate->excl_rect.h,
2720 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07002721 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002722 ret = -EINVAL;
2723 }
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07002724 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
2725 pstate->excl_rect.x, pstate->excl_rect.y,
2726 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002727 }
2728
Dhaval Patel47302cf2016-08-18 15:04:28 -07002729modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002730 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002731 _sde_plane_sspp_atomic_check_mode_changed(psde,
2732 state, plane->state);
2733exit:
2734 return ret;
2735}
2736
2737static int sde_plane_atomic_check(struct drm_plane *plane,
2738 struct drm_plane_state *state)
2739{
2740 int ret = 0;
2741 struct sde_plane *psde;
2742 struct sde_plane_state *pstate;
2743
2744 if (!plane || !state) {
2745 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2746 plane != 0, state != 0);
2747 ret = -EINVAL;
2748 goto exit;
2749 }
2750
2751 psde = to_sde_plane(plane);
2752 pstate = to_sde_plane_state(state);
2753
2754 SDE_DEBUG_PLANE(psde, "\n");
2755
2756 ret = sde_plane_rot_atomic_check(plane, state);
2757 if (ret)
2758 goto exit;
2759
2760 ret = sde_plane_sspp_atomic_check(plane, state);
2761
Clarence Ipdbde9832016-06-26 09:48:36 -04002762exit:
2763 return ret;
2764}
2765
Clarence Ipcae1bb62016-07-07 12:07:13 -04002766/**
2767 * sde_plane_flush - final plane operations before commit flush
2768 * @plane: Pointer to drm plane structure
2769 */
2770void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04002771{
Clarence Ipcae1bb62016-07-07 12:07:13 -04002772 struct sde_plane *psde;
Clarence Ipddbf7752017-05-21 18:07:30 -04002773 struct sde_plane_state *pstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -04002774
Clarence Ipddbf7752017-05-21 18:07:30 -04002775 if (!plane || !plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002776 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04002777 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002778 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04002779
2780 psde = to_sde_plane(plane);
Clarence Ipddbf7752017-05-21 18:07:30 -04002781 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002782
2783 /*
2784 * These updates have to be done immediately before the plane flush
2785 * timing, and may not be moved to the atomic_update/mode_set functions.
2786 */
2787 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05002788 /* force white frame with 100% alpha pipe output on error */
2789 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002790 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
2791 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04002792 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002793 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
2794 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
2795
Clarence Ip56902792017-03-17 15:22:07 -04002796 /* force black color fill during suspend */
2797 if (msm_is_suspend_state(plane->dev) && suspend_blank)
2798 _sde_plane_color_fill(psde, 0x0, 0x0);
2799
Clarence Ipcae1bb62016-07-07 12:07:13 -04002800 /* flag h/w flush complete */
2801 if (plane->state)
Clarence Ipddbf7752017-05-21 18:07:30 -04002802 pstate->pending = false;
2803
2804 /* signal inline rotator start */
2805 sde_plane_rot_flush(plane, pstate);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002806}
2807
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002808static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
2809 struct drm_plane_state *old_state)
2810{
2811 uint32_t nplanes, src_flags;
2812 struct sde_plane *psde;
2813 struct drm_plane_state *state;
2814 struct sde_plane_state *pstate;
2815 struct sde_plane_state *old_pstate;
2816 struct sde_plane_rot_state *rstate;
2817 const struct sde_format *fmt;
2818 struct drm_crtc *crtc;
2819 struct drm_framebuffer *fb;
2820 struct sde_rect src, dst;
2821 const struct sde_rect *crtc_roi;
2822 bool q16_data = true;
2823 int idx;
2824
2825 if (!plane) {
2826 SDE_ERROR("invalid plane\n");
2827 return -EINVAL;
2828 } else if (!plane->state) {
2829 SDE_ERROR("invalid plane state\n");
2830 return -EINVAL;
2831 } else if (!old_state) {
2832 SDE_ERROR("invalid old state\n");
2833 return -EINVAL;
2834 }
2835
2836 psde = to_sde_plane(plane);
2837 state = plane->state;
2838
2839 pstate = to_sde_plane_state(state);
2840 rstate = &pstate->rot;
2841
2842 old_pstate = to_sde_plane_state(old_state);
2843
2844 crtc = state->crtc;
2845 fb = rstate->out_fb;
2846 if (!crtc || !fb) {
2847 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
2848 crtc != 0, fb != 0);
2849 return -EINVAL;
2850 }
2851 fmt = to_sde_format(msm_framebuffer_format(fb));
2852 nplanes = fmt->num_planes;
2853
2854 SDE_DEBUG(
2855 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
2856 plane->base.id, rstate->sequence_id,
2857 rstate->out_fb_width, rstate->out_fb_height,
2858 (char *) &rstate->out_fb_pixel_format,
2859 rstate->out_fb_modifier[0],
2860 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2861 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2862 rstate->out_rotation,
2863 state->crtc_w, state->crtc_h,
2864 state->crtc_x, state->crtc_y);
2865
2866 /* force reprogramming of all the parameters, if the flag is set */
2867 if (psde->revalidate) {
2868 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
2869 plane->base.id);
2870 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2871 psde->revalidate = false;
2872 }
2873
2874 /* determine what needs to be refreshed */
2875 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
2876 switch (idx) {
2877 case PLANE_PROP_SCALER_V1:
2878 case PLANE_PROP_SCALER_V2:
2879 case PLANE_PROP_H_DECIMATE:
2880 case PLANE_PROP_V_DECIMATE:
2881 case PLANE_PROP_SRC_CONFIG:
2882 case PLANE_PROP_ZPOS:
2883 case PLANE_PROP_EXCL_RECT_V1:
2884 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2885 break;
2886 case PLANE_PROP_CSC_V1:
2887 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2888 break;
2889 case PLANE_PROP_COLOR_FILL:
2890 /* potentially need to refresh everything */
2891 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2892 break;
2893 case PLANE_PROP_ROTATION:
2894 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2895 break;
2896 case PLANE_PROP_INFO:
2897 case PLANE_PROP_ALPHA:
2898 case PLANE_PROP_INPUT_FENCE:
2899 case PLANE_PROP_BLEND_OP:
2900 /* no special action required */
2901 break;
2902 case PLANE_PROP_ROT_DST_X:
2903 case PLANE_PROP_ROT_DST_Y:
2904 case PLANE_PROP_ROT_DST_W:
2905 case PLANE_PROP_ROT_DST_H:
2906 /* handled by rotator atomic update */
2907 break;
2908 default:
2909 /* unknown property, refresh everything */
2910 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
2911 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
2912 break;
2913 }
2914 }
2915
2916 /**
2917 * since plane_atomic_check is invoked before crtc_atomic_check
2918 * in the commit sequence, all the parameters for updating the
2919 * plane dirty flag will not be available during
2920 * plane_atomic_check as some features params are updated
2921 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
2922 * before sspp update.
2923 */
2924 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
2925 old_state);
2926
2927 /* re-program the output rects always in the case of partial update */
2928 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
2929 if (!sde_kms_rect_is_null(crtc_roi))
2930 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2931
2932 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
2933 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
2934
2935 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
2936
2937 /* early out if nothing dirty */
2938 if (!pstate->dirty)
2939 return 0;
2940 pstate->pending = true;
2941
2942 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
2943 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
2944
2945 /* update roi config */
2946 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
2947 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2948 rstate->out_src_w, rstate->out_src_h, q16_data);
2949 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
2950 state->crtc_w, state->crtc_h, !q16_data);
2951
2952 SDE_DEBUG_PLANE(psde,
2953 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
2954 fb->base.id, src.x, src.y, src.w, src.h,
2955 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
2956 (char *)&fmt->base.pixel_format,
2957 SDE_FORMAT_IS_UBWC(fmt));
2958
2959 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
2960 BIT(SDE_DRM_DEINTERLACE)) {
2961 SDE_DEBUG_PLANE(psde, "deinterlace\n");
2962 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
2963 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
2964 src.h /= 2;
2965 src.y = DIV_ROUND_UP(src.y, 2);
2966 src.y &= ~0x1;
2967 }
2968
2969 /*
2970 * adjust layer mixer position of the sspp in the presence
2971 * of a partial update to the active lm origin
2972 */
2973 dst.x -= crtc_roi->x;
2974 dst.y -= crtc_roi->y;
2975
2976 psde->pipe_cfg.src_rect = src;
2977 psde->pipe_cfg.dst_rect = dst;
2978
2979 _sde_plane_setup_scaler(psde, fmt, pstate);
2980
2981 /* check for color fill */
2982 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
2983 PLANE_PROP_COLOR_FILL);
2984 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
2985 /* skip remaining processing on color fill */
2986 pstate->dirty = 0x0;
2987 } else if (psde->pipe_hw->ops.setup_rects) {
2988 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
2989 &psde->pipe_cfg,
2990 pstate->multirect_index);
2991 }
2992
2993 if (psde->pipe_hw->ops.setup_pe)
2994 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
2995 &psde->pixel_ext);
2996
2997 /**
2998 * when programmed in multirect mode, scalar block will be
2999 * bypassed. Still we need to update alpha and bitwidth
3000 * ONLY for RECT0
3001 */
3002 if (psde->pipe_hw->ops.setup_scaler &&
3003 pstate->multirect_index != SDE_SSPP_RECT_1)
3004 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
3005 &psde->pipe_cfg, &psde->pixel_ext,
3006 psde->scaler3_cfg);
3007
3008 /* update excl rect */
3009 if (psde->pipe_hw->ops.setup_excl_rect)
3010 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
3011 &pstate->excl_rect,
3012 pstate->multirect_index);
3013
3014 if (psde->pipe_hw->ops.setup_multirect)
3015 psde->pipe_hw->ops.setup_multirect(
3016 psde->pipe_hw,
3017 pstate->multirect_index,
3018 pstate->multirect_mode);
3019 }
3020
3021 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
3022 psde->pipe_hw->ops.setup_format) {
3023 src_flags = 0x0;
3024 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
3025 if (rstate->out_rotation & DRM_REFLECT_X)
3026 src_flags |= SDE_SSPP_FLIP_LR;
3027 if (rstate->out_rotation & DRM_REFLECT_Y)
3028 src_flags |= SDE_SSPP_FLIP_UD;
3029
3030 /* update format */
3031 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
3032 pstate->multirect_index);
3033
3034 if (psde->pipe_hw->ops.setup_sys_cache) {
3035 if (rstate->out_sbuf) {
3036 if (rstate->nplane < 2)
3037 pstate->sc_cfg.op_mode =
3038 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
3039 else if (rstate->out_xpos == 0)
3040 pstate->sc_cfg.op_mode =
3041 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
3042 else
3043 pstate->sc_cfg.op_mode =
3044 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
3045
3046 pstate->sc_cfg.rd_en = true;
3047 pstate->sc_cfg.rd_scid =
3048 rstate->rot_hw->caps->scid;
3049 pstate->sc_cfg.rd_noallocate = true;
3050 pstate->sc_cfg.rd_op_type =
3051 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3052 } else {
3053 pstate->sc_cfg.op_mode =
3054 SDE_PIPE_SC_OP_MODE_OFFLINE;
3055 pstate->sc_cfg.rd_en = false;
3056 pstate->sc_cfg.rd_scid = 0;
3057 pstate->sc_cfg.rd_noallocate = false;
3058 pstate->sc_cfg.rd_op_type =
3059 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3060 }
3061
3062 psde->pipe_hw->ops.setup_sys_cache(
3063 psde->pipe_hw, &pstate->sc_cfg);
3064 }
3065
3066 /* update csc */
3067 if (SDE_FORMAT_IS_YUV(fmt))
3068 _sde_plane_setup_csc(psde);
3069 else
3070 psde->csc_ptr = 0;
3071 }
3072
3073 sde_color_process_plane_setup(plane);
3074
3075 /* update sharpening */
3076 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3077 psde->pipe_hw->ops.setup_sharpening) {
3078 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3079 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3080 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3081 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3082
3083 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3084 &psde->sharp_cfg);
3085 }
3086
3087 _sde_plane_set_qos_lut(plane, fb);
3088 _sde_plane_set_danger_lut(plane, fb);
3089
3090 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3091 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3092 _sde_plane_set_ot_limit(plane, crtc);
3093 }
3094
Alan Kwonga62eeb82017-04-19 08:57:55 -07003095 _sde_plane_set_qos_remap(plane);
3096
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003097 /* clear dirty */
3098 pstate->dirty = 0x0;
3099
3100 return 0;
3101}
3102
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003103static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003104 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003105{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003106 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003107 struct drm_plane_state *state;
3108 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003109 struct sde_plane_state *old_pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003110
Clarence Ip13a8cf42016-09-29 17:27:47 -04003111 if (!plane) {
3112 SDE_ERROR("invalid plane\n");
3113 return;
3114 } else if (!plane->state) {
3115 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003116 return;
3117 }
3118
Clarence Ip13a8cf42016-09-29 17:27:47 -04003119 psde = to_sde_plane(plane);
3120 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003121 state = plane->state;
3122 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003123 old_pstate = to_sde_plane_state(old_state);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003124
Clarence Ip13a8cf42016-09-29 17:27:47 -04003125 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003126
Alan Kwong4dd64c82017-02-04 18:41:51 -08003127 sde_plane_rot_atomic_update(plane, old_state);
3128
3129 if (!sde_plane_sspp_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04003130 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04003131 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003132 int ret;
3133
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003134 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003135 /* atomic_check should have ensured that this doesn't fail */
3136 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003137 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003138}
3139
Dhaval Patel47302cf2016-08-18 15:04:28 -07003140
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003141/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003142static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003143 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003144{
Clarence Ip5e2a9222016-06-26 22:38:24 -04003145 static const struct drm_prop_enum_list e_blend_op[] = {
3146 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3147 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3148 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3149 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3150 };
3151 static const struct drm_prop_enum_list e_src_config[] = {
3152 {SDE_DRM_DEINTERLACE, "deinterlace"}
3153 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003154 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003155 struct sde_format_extended *virt_format_list = NULL;
Dhaval Patel4e574842016-08-23 15:11:37 -07003156 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003157 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003158 int zpos_max = 255;
3159 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003160 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003161
Clarence Ip13a8cf42016-09-29 17:27:47 -04003162 if (!plane || !psde) {
3163 SDE_ERROR("invalid plane\n");
3164 return;
3165 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3166 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3167 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003168 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003169 } else if (!catalog) {
3170 SDE_ERROR("invalid catalog\n");
3171 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003172 }
3173
Alan Kwong4dd64c82017-02-04 18:41:51 -08003174 psde->catalog = catalog;
3175
Clarence Ipc47a0692016-10-11 10:54:17 -04003176 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003177 if (catalog->mixer_count && catalog->mixer &&
3178 catalog->mixer[0].sblk->maxblendstages) {
3179 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3180 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3181 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3182 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003183 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3184 /* reserve zpos == 0 for primary planes */
3185 zpos_def = drm_plane_index(plane) + 1;
3186 }
3187
3188 msm_property_install_range(&psde->property_info, "zpos",
3189 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003190
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003191 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003192 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003193
Dhaval Patel47302cf2016-08-18 15:04:28 -07003194 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003195 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003196 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003197
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003198 if (!master_plane_id) {
3199 if (psde->pipe_sblk->maxhdeciexp) {
3200 msm_property_install_range(&psde->property_info,
3201 "h_decimate", 0x0, 0,
3202 psde->pipe_sblk->maxhdeciexp, 0,
3203 PLANE_PROP_H_DECIMATE);
3204 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003205
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003206 if (psde->pipe_sblk->maxvdeciexp) {
3207 msm_property_install_range(&psde->property_info,
3208 "v_decimate", 0x0, 0,
3209 psde->pipe_sblk->maxvdeciexp, 0,
3210 PLANE_PROP_V_DECIMATE);
3211 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003212
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003213 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
3214 msm_property_install_volatile_range(
3215 &psde->property_info, "scaler_v2",
3216 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3217 msm_property_install_blob(&psde->property_info,
3218 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3219 msm_property_install_blob(&psde->property_info,
3220 "lut_cir", 0,
3221 PLANE_PROP_SCALER_LUT_CIR);
3222 msm_property_install_blob(&psde->property_info,
3223 "lut_sep", 0,
3224 PLANE_PROP_SCALER_LUT_SEP);
3225 } else if (psde->features & SDE_SSPP_SCALER) {
3226 msm_property_install_volatile_range(
3227 &psde->property_info, "scaler_v1", 0x0,
3228 0, ~0, 0, PLANE_PROP_SCALER_V1);
3229 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003230
Dhaval Patel0aee0972017-02-08 19:00:58 -08003231 if (psde->features & BIT(SDE_SSPP_CSC) ||
3232 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003233 msm_property_install_volatile_range(
3234 &psde->property_info, "csc_v1", 0x0,
3235 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003236
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003237 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3238 snprintf(feature_name, sizeof(feature_name), "%s%d",
3239 "SDE_SSPP_HUE_V",
3240 psde->pipe_sblk->hsic_blk.version >> 16);
3241 msm_property_install_range(&psde->property_info,
3242 feature_name, 0, 0, 0xFFFFFFFF, 0,
3243 PLANE_PROP_HUE_ADJUST);
3244 snprintf(feature_name, sizeof(feature_name), "%s%d",
3245 "SDE_SSPP_SATURATION_V",
3246 psde->pipe_sblk->hsic_blk.version >> 16);
3247 msm_property_install_range(&psde->property_info,
3248 feature_name, 0, 0, 0xFFFFFFFF, 0,
3249 PLANE_PROP_SATURATION_ADJUST);
3250 snprintf(feature_name, sizeof(feature_name), "%s%d",
3251 "SDE_SSPP_VALUE_V",
3252 psde->pipe_sblk->hsic_blk.version >> 16);
3253 msm_property_install_range(&psde->property_info,
3254 feature_name, 0, 0, 0xFFFFFFFF, 0,
3255 PLANE_PROP_VALUE_ADJUST);
3256 snprintf(feature_name, sizeof(feature_name), "%s%d",
3257 "SDE_SSPP_CONTRAST_V",
3258 psde->pipe_sblk->hsic_blk.version >> 16);
3259 msm_property_install_range(&psde->property_info,
3260 feature_name, 0, 0, 0xFFFFFFFF, 0,
3261 PLANE_PROP_CONTRAST_ADJUST);
3262 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003263 }
3264
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003265 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3266 msm_property_install_volatile_range(&psde->property_info,
3267 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3268
Alan Kwong4dd64c82017-02-04 18:41:51 -08003269 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003270
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003271 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003272 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003273
Dhaval Patel47302cf2016-08-18 15:04:28 -07003274 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3275 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3276
3277 if (psde->pipe_hw->ops.setup_solidfill)
3278 msm_property_install_range(&psde->property_info, "color_fill",
3279 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3280
Dhaval Patel4e574842016-08-23 15:11:37 -07003281 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003282 if (!info) {
3283 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003284 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003285 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003286
3287 msm_property_install_blob(&psde->property_info, "capabilities",
3288 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3289 sde_kms_info_reset(info);
3290
Clarence Ipea3d6262016-07-15 16:20:11 -04003291 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003292
3293 if (master_plane_id) {
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003294 int index, array_size;
3295
3296 array_size = ARRAY_SIZE(plane_formats)
3297 + ARRAY_SIZE(rgb_10bit_formats);
3298 virt_format_list = kcalloc(array_size,
3299 sizeof(struct sde_format_extended), GFP_KERNEL);
3300 if (!virt_format_list) {
3301 SDE_ERROR(
3302 "failed to allocate virtual pipe format list\n");
3303 return;
3304 }
3305
3306 index = sde_copy_formats(virt_format_list, array_size,
3307 0, plane_formats, ARRAY_SIZE(plane_formats));
3308 sde_copy_formats(virt_format_list, array_size,
3309 index, rgb_10bit_formats,
3310 ARRAY_SIZE(rgb_10bit_formats));
3311
3312 format_list = virt_format_list;
3313
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003314 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003315 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003316 }
3317
Clarence Ipea3d6262016-07-15 16:20:11 -04003318 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003319 sde_kms_info_start(info, "pixel_formats");
3320 while (format_list->fourcc_format) {
3321 sde_kms_info_append_format(info,
3322 format_list->fourcc_format,
3323 format_list->modifier);
3324 ++format_list;
3325 }
3326 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003327 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003328
3329 sde_kms_info_add_keyint(info, "max_linewidth",
3330 psde->pipe_sblk->maxlinewidth);
3331 sde_kms_info_add_keyint(info, "max_upscale",
3332 psde->pipe_sblk->maxupscale);
3333 sde_kms_info_add_keyint(info, "max_downscale",
3334 psde->pipe_sblk->maxdwnscale);
3335 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3336 psde->pipe_sblk->maxhdeciexp);
3337 sde_kms_info_add_keyint(info, "max_vertical_deci",
3338 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07003339 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
3340 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07003341 msm_property_set_blob(&psde->property_info, &psde->blob_info,
3342 info->data, info->len, PLANE_PROP_INFO);
3343
3344 kfree(info);
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003345 kfree(virt_format_list);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003346
3347 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3348 snprintf(feature_name, sizeof(feature_name), "%s%d",
3349 "SDE_SSPP_SKIN_COLOR_V",
3350 psde->pipe_sblk->memcolor_blk.version >> 16);
3351 msm_property_install_blob(&psde->property_info, feature_name, 0,
3352 PLANE_PROP_SKIN_COLOR);
3353 snprintf(feature_name, sizeof(feature_name), "%s%d",
3354 "SDE_SSPP_SKY_COLOR_V",
3355 psde->pipe_sblk->memcolor_blk.version >> 16);
3356 msm_property_install_blob(&psde->property_info, feature_name, 0,
3357 PLANE_PROP_SKY_COLOR);
3358 snprintf(feature_name, sizeof(feature_name), "%s%d",
3359 "SDE_SSPP_FOLIAGE_COLOR_V",
3360 psde->pipe_sblk->memcolor_blk.version >> 16);
3361 msm_property_install_blob(&psde->property_info, feature_name, 0,
3362 PLANE_PROP_FOLIAGE_COLOR);
3363 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003364}
3365
Clarence Ip5fc00c52016-09-23 15:03:34 -04003366static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
3367{
3368 struct sde_drm_csc_v1 csc_v1;
3369 int i;
3370
3371 if (!psde) {
3372 SDE_ERROR("invalid plane\n");
3373 return;
3374 }
3375
3376 psde->csc_usr_ptr = NULL;
3377 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003378 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003379 return;
3380 }
3381
3382 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003383 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003384 return;
3385 }
3386
Clarence Ipb43d4592016-09-08 14:21:35 -04003387 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04003388 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
3389 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
3390 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
3391 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
3392 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
3393 }
3394 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
3395 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
3396 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
3397 }
3398 psde->csc_usr_ptr = &psde->csc_cfg;
3399}
3400
Clarence Ipb43d4592016-09-08 14:21:35 -04003401static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
3402{
3403 struct sde_drm_scaler_v1 scale_v1;
3404 struct sde_hw_pixel_ext *pe;
3405 int i;
3406
3407 if (!psde) {
3408 SDE_ERROR("invalid plane\n");
3409 return;
3410 }
3411
3412 psde->pixel_ext_usr = false;
3413 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003414 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003415 return;
3416 }
3417
3418 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003419 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003420 return;
3421 }
3422
3423 /* populate from user space */
3424 pe = &(psde->pixel_ext);
3425 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3426 for (i = 0; i < SDE_MAX_PLANES; i++) {
3427 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
3428 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
3429 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
3430 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
3431
3432 pe->horz_filter[i] = scale_v1.horz_filter[i];
3433 pe->vert_filter[i] = scale_v1.vert_filter[i];
3434 }
3435 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003436 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
3437 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
3438 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
3439 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
3440 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003441
abeykun41060122016-11-28 13:02:01 -05003442 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
3443 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
3444 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
3445 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
3446 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003447 }
abeykun41060122016-11-28 13:02:01 -05003448
Clarence Ipb43d4592016-09-08 14:21:35 -04003449 psde->pixel_ext_usr = true;
3450
Clarence Ip13a8cf42016-09-29 17:27:47 -04003451 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003452}
3453
abeykun48f407a2016-08-25 12:06:44 -04003454static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
3455 struct sde_plane_state *pstate, void *usr)
3456{
3457 struct sde_drm_scaler_v2 scale_v2;
3458 struct sde_hw_pixel_ext *pe;
3459 int i;
3460 struct sde_hw_scaler3_cfg *cfg;
3461
3462 if (!psde) {
3463 SDE_ERROR("invalid plane\n");
3464 return;
3465 }
3466
3467 cfg = psde->scaler3_cfg;
3468 psde->pixel_ext_usr = false;
3469 if (!usr) {
3470 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3471 return;
3472 }
3473
3474 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
3475 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
3476 return;
3477 }
3478
3479 /* populate from user space */
3480 pe = &(psde->pixel_ext);
3481 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3482 cfg->enable = scale_v2.enable;
3483 cfg->dir_en = scale_v2.dir_en;
3484 for (i = 0; i < SDE_MAX_PLANES; i++) {
3485 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
3486 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
3487 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
3488 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
3489
3490 cfg->preload_x[i] = scale_v2.preload_x[i];
3491 cfg->preload_y[i] = scale_v2.preload_y[i];
3492 cfg->src_width[i] = scale_v2.src_width[i];
3493 cfg->src_height[i] = scale_v2.src_height[i];
3494 }
3495 cfg->dst_width = scale_v2.dst_width;
3496 cfg->dst_height = scale_v2.dst_height;
3497
3498 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
3499 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
3500 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
3501 cfg->blend_cfg = scale_v2.blend_cfg;
3502
3503 cfg->lut_flag = scale_v2.lut_flag;
3504 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
3505 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
3506 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
3507 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
3508 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
3509
3510 cfg->de.enable = scale_v2.de.enable;
3511 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
3512 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
3513 cfg->de.clip = scale_v2.de.clip;
3514 cfg->de.limit = scale_v2.de.limit;
3515 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
3516 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
3517 cfg->de.thr_low = scale_v2.de.thr_low;
3518 cfg->de.thr_high = scale_v2.de.thr_high;
3519 cfg->de.prec_shift = scale_v2.de.prec_shift;
3520 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
3521 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
3522 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
3523 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
3524 }
3525 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003526 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
3527 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
3528 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
3529 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
3530 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04003531
abeykun41060122016-11-28 13:02:01 -05003532 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
3533 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
3534 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
3535 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
3536 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04003537 }
3538 psde->pixel_ext_usr = true;
3539
3540 SDE_DEBUG_PLANE(psde, "user property data copied\n");
3541}
3542
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003543static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
3544 struct sde_plane_state *pstate, void *usr_ptr)
3545{
3546 struct drm_clip_rect excl_rect_v1;
3547
3548 if (!psde) {
3549 SDE_ERROR("invalid plane\n");
3550 return;
3551 }
3552
3553 if (!usr_ptr) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003554 SDE_DEBUG_PLANE(psde, "invalid excl_rect user data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003555 return;
3556 }
3557
3558 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003559 SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003560 return;
3561 }
3562
3563 /* populate from user space */
3564 pstate->excl_rect.x = excl_rect_v1.x1;
3565 pstate->excl_rect.y = excl_rect_v1.y1;
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003566 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
3567 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
3568
3569 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3570 pstate->excl_rect.x, pstate->excl_rect.y,
3571 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003572}
3573
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003574static int sde_plane_atomic_set_property(struct drm_plane *plane,
3575 struct drm_plane_state *state, struct drm_property *property,
3576 uint64_t val)
3577{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003578 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003579 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003580 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003581
Clarence Ip13a8cf42016-09-29 17:27:47 -04003582 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003583
3584 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003585 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003586 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003587 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003588 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04003589 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003590 ret = msm_property_atomic_set(&psde->property_info,
3591 pstate->property_values, pstate->property_blobs,
3592 property, val);
3593 if (!ret) {
3594 idx = msm_property_index(&psde->property_info,
3595 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003596 switch (idx) {
3597 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04003598 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003599 break;
3600 case PLANE_PROP_CSC_V1:
3601 _sde_plane_set_csc_v1(psde, (void *)val);
3602 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04003603 case PLANE_PROP_SCALER_V1:
3604 _sde_plane_set_scaler_v1(psde, (void *)val);
3605 break;
abeykun48f407a2016-08-25 12:06:44 -04003606 case PLANE_PROP_SCALER_V2:
3607 _sde_plane_set_scaler_v2(psde, pstate,
3608 (void *)val);
3609 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003610 case PLANE_PROP_EXCL_RECT_V1:
3611 _sde_plane_set_excl_rect_v1(psde, pstate,
3612 (void *)val);
3613 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04003614 default:
3615 /* nothing to do */
3616 break;
3617 }
Clarence Ipe78efb72016-06-24 18:35:21 -04003618 }
3619 }
3620
Alan Kwong4dd64c82017-02-04 18:41:51 -08003621 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
3622 property->name, property->base.id, val, ret);
3623
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003624 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003625}
3626
3627static int sde_plane_set_property(struct drm_plane *plane,
3628 struct drm_property *property, uint64_t val)
3629{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003630 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003631
Clarence Ipae4e60c2016-06-26 22:44:04 -04003632 return sde_plane_atomic_set_property(plane,
3633 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003634}
3635
3636static int sde_plane_atomic_get_property(struct drm_plane *plane,
3637 const struct drm_plane_state *state,
3638 struct drm_property *property, uint64_t *val)
3639{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003640 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003641 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04003642 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003643
Clarence Ipaa0faf42016-05-30 12:07:48 -04003644 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003645 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003646 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003647 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003648 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003649 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003650 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003651 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003652 ret = msm_property_atomic_get(&psde->property_info,
3653 pstate->property_values, pstate->property_blobs,
3654 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04003655 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003656
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003657 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003658}
3659
3660static void sde_plane_destroy(struct drm_plane *plane)
3661{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003662 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003663
Clarence Ip13a8cf42016-09-29 17:27:47 -04003664 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003665
Clarence Ip13a8cf42016-09-29 17:27:47 -04003666 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04003667 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3668
Dhaval Patel4e574842016-08-23 15:11:37 -07003669 if (psde->blob_info)
3670 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003671 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04003672 mutex_destroy(&psde->lock);
3673
Clarence Ip4ce59322016-06-26 22:27:51 -04003674 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003675
Clarence Ip4ce59322016-06-26 22:27:51 -04003676 /* this will destroy the states as well */
3677 drm_plane_cleanup(plane);
3678
Clarence Ip4c1d9772016-06-26 09:35:38 -04003679 if (psde->pipe_hw)
3680 sde_hw_sspp_destroy(psde->pipe_hw);
3681
Clarence Ip4ce59322016-06-26 22:27:51 -04003682 kfree(psde);
3683 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003684}
3685
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003686static void sde_plane_destroy_state(struct drm_plane *plane,
3687 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003688{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003689 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04003690 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003691
Clarence Ipae4e60c2016-06-26 22:44:04 -04003692 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003693 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3694 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003695 return;
3696 }
3697
Clarence Ipaa0faf42016-05-30 12:07:48 -04003698 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04003699 pstate = to_sde_plane_state(state);
3700
Clarence Ip13a8cf42016-09-29 17:27:47 -04003701 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003702
Alan Kwong4dd64c82017-02-04 18:41:51 -08003703 sde_plane_rot_destroy_state(plane, &pstate->base);
3704
Clarence Ipe78efb72016-06-24 18:35:21 -04003705 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003706 if (state->fb)
3707 drm_framebuffer_unreference(state->fb);
3708
Clarence Ipae4e60c2016-06-26 22:44:04 -04003709 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003710 if (pstate->input_fence)
3711 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003712
Clarence Ipaa0faf42016-05-30 12:07:48 -04003713 /* destroy value helper */
3714 msm_property_destroy_state(&psde->property_info, pstate,
3715 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003716}
3717
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003718static struct drm_plane_state *
3719sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003720{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003721 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003722 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04003723 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04003724 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003725
Clarence Ip13a8cf42016-09-29 17:27:47 -04003726 if (!plane) {
3727 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003728 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003729 } else if (!plane->state) {
3730 SDE_ERROR("invalid plane state\n");
3731 return NULL;
3732 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003733
Clarence Ip730e7192016-06-26 22:45:09 -04003734 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003735 psde = to_sde_plane(plane);
3736 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003737 if (!pstate) {
3738 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003739 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003740 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003741
Clarence Ip13a8cf42016-09-29 17:27:47 -04003742 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003743
3744 /* duplicate value helper */
3745 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
3746 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003747
Clarence Ip17e908b2016-09-29 15:58:00 -04003748 /* clear out any input fence */
3749 pstate->input_fence = 0;
3750 input_fence_default = msm_property_get_default(
3751 &psde->property_info, PLANE_PROP_INPUT_FENCE);
3752 msm_property_set_property(&psde->property_info, pstate->property_values,
3753 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003754
Clarence Ip282dad62016-09-27 17:07:35 -04003755 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04003756 pstate->pending = false;
3757
Alan Kwongcdb2f282017-03-18 13:42:06 -07003758 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
3759
Alan Kwong4dd64c82017-02-04 18:41:51 -08003760 sde_plane_rot_duplicate_state(plane, &pstate->base);
3761
Clarence Ip730e7192016-06-26 22:45:09 -04003762 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003763}
3764
3765static void sde_plane_reset(struct drm_plane *plane)
3766{
Clarence Ipae4e60c2016-06-26 22:44:04 -04003767 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003768 struct sde_plane_state *pstate;
3769
Clarence Ipae4e60c2016-06-26 22:44:04 -04003770 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003771 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003772 return;
3773 }
3774
Clarence Ip730e7192016-06-26 22:45:09 -04003775 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003776 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003777
Clarence Ipae4e60c2016-06-26 22:44:04 -04003778 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04003779 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04003780 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003781 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04003782 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003783
Clarence Ipaa0faf42016-05-30 12:07:48 -04003784 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003785 if (!pstate) {
3786 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003787 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003788 }
Clarence Ip730e7192016-06-26 22:45:09 -04003789
Clarence Ipaa0faf42016-05-30 12:07:48 -04003790 /* reset value helper */
3791 msm_property_reset_state(&psde->property_info, pstate,
3792 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003793
3794 pstate->base.plane = plane;
3795
3796 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003797}
3798
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003799#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04003800static ssize_t _sde_plane_danger_read(struct file *file,
3801 char __user *buff, size_t count, loff_t *ppos)
3802{
3803 struct sde_kms *kms = file->private_data;
3804 struct sde_mdss_cfg *cfg = kms->catalog;
3805 int len = 0;
3806 char buf[40] = {'\0'};
3807
3808 if (!cfg)
3809 return -ENODEV;
3810
3811 if (*ppos)
3812 return 0; /* the end */
3813
3814 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
3815 if (len < 0 || len >= sizeof(buf))
3816 return 0;
3817
3818 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
3819 return -EFAULT;
3820
3821 *ppos += len; /* increase offset */
3822
3823 return len;
3824}
3825
3826static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
3827{
3828 struct drm_plane *plane;
3829
3830 drm_for_each_plane(plane, kms->dev) {
3831 if (plane->fb && plane->state) {
3832 sde_plane_danger_signal_ctrl(plane, enable);
3833 SDE_DEBUG("plane:%d img:%dx%d ",
3834 plane->base.id, plane->fb->width,
3835 plane->fb->height);
3836 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
3837 plane->state->src_x >> 16,
3838 plane->state->src_y >> 16,
3839 plane->state->src_w >> 16,
3840 plane->state->src_h >> 16,
3841 plane->state->crtc_x, plane->state->crtc_y,
3842 plane->state->crtc_w, plane->state->crtc_h);
3843 } else {
3844 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
3845 }
3846 }
3847}
3848
3849static ssize_t _sde_plane_danger_write(struct file *file,
3850 const char __user *user_buf, size_t count, loff_t *ppos)
3851{
3852 struct sde_kms *kms = file->private_data;
3853 struct sde_mdss_cfg *cfg = kms->catalog;
3854 int disable_panic;
3855 char buf[10];
3856
3857 if (!cfg)
3858 return -EFAULT;
3859
3860 if (count >= sizeof(buf))
3861 return -EFAULT;
3862
3863 if (copy_from_user(buf, user_buf, count))
3864 return -EFAULT;
3865
3866 buf[count] = 0; /* end of string */
3867
3868 if (kstrtoint(buf, 0, &disable_panic))
3869 return -EFAULT;
3870
3871 if (disable_panic) {
3872 /* Disable panic signal for all active pipes */
3873 SDE_DEBUG("Disabling danger:\n");
3874 _sde_plane_set_danger_state(kms, false);
3875 kms->has_danger_ctrl = false;
3876 } else {
3877 /* Enable panic signal for all active pipes */
3878 SDE_DEBUG("Enabling danger:\n");
3879 kms->has_danger_ctrl = true;
3880 _sde_plane_set_danger_state(kms, true);
3881 }
3882
3883 return count;
3884}
3885
3886static const struct file_operations sde_plane_danger_enable = {
3887 .open = simple_open,
3888 .read = _sde_plane_danger_read,
3889 .write = _sde_plane_danger_write,
3890};
3891
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003892static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04003893{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003894 struct sde_plane *psde;
3895 struct sde_kms *kms;
3896 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04003897 const struct sde_sspp_sub_blks *sblk = 0;
3898 const struct sde_sspp_cfg *cfg = 0;
3899
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003900 if (!plane || !plane->dev) {
3901 SDE_ERROR("invalid arguments\n");
3902 return -EINVAL;
3903 }
3904
3905 priv = plane->dev->dev_private;
3906 if (!priv || !priv->kms) {
3907 SDE_ERROR("invalid KMS reference\n");
3908 return -EINVAL;
3909 }
3910
3911 kms = to_sde_kms(priv->kms);
3912 psde = to_sde_plane(plane);
3913
Clarence Ip4ce59322016-06-26 22:27:51 -04003914 if (psde && psde->pipe_hw)
3915 cfg = psde->pipe_hw->cap;
3916 if (cfg)
3917 sblk = cfg->sblk;
3918
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003919 if (!sblk)
3920 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04003921
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003922 /* create overall sub-directory for the pipe */
3923 psde->debugfs_root =
3924 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07003925 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04003926
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003927 if (!psde->debugfs_root)
3928 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04003929
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003930 /* don't error check these */
3931 debugfs_create_x32("features", 0644,
3932 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003933
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003934 /* add register dump support */
3935 sde_debugfs_setup_regset32(&psde->debugfs_src,
3936 sblk->src_blk.base + cfg->base,
3937 sblk->src_blk.len,
3938 kms);
3939 sde_debugfs_create_regset32("src_blk", 0444,
3940 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003941
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003942 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
3943 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
3944 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
3945 sblk->scaler_blk.base + cfg->base,
3946 sblk->scaler_blk.len,
3947 kms);
3948 sde_debugfs_create_regset32("scaler_blk", 0444,
3949 psde->debugfs_root,
3950 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07003951 debugfs_create_bool("default_scaling",
3952 0644,
3953 psde->debugfs_root,
3954 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04003955 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003956
3957 if (cfg->features & BIT(SDE_SSPP_CSC) ||
3958 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
3959 sde_debugfs_setup_regset32(&psde->debugfs_csc,
3960 sblk->csc_blk.base + cfg->base,
3961 sblk->csc_blk.len,
3962 kms);
3963 sde_debugfs_create_regset32("csc_blk", 0444,
3964 psde->debugfs_root, &psde->debugfs_csc);
3965 }
3966
3967 debugfs_create_u32("xin_id",
3968 0444,
3969 psde->debugfs_root,
3970 (u32 *) &cfg->xin_id);
3971 debugfs_create_u32("clk_ctrl",
3972 0444,
3973 psde->debugfs_root,
3974 (u32 *) &cfg->clk_ctrl);
3975 debugfs_create_x32("creq_vblank",
3976 0644,
3977 psde->debugfs_root,
3978 (u32 *) &sblk->creq_vblank);
3979 debugfs_create_x32("danger_vblank",
3980 0644,
3981 psde->debugfs_root,
3982 (u32 *) &sblk->danger_vblank);
3983
3984 debugfs_create_file("disable_danger",
3985 0644,
3986 psde->debugfs_root,
3987 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003988 debugfs_create_u32("sbuf_mode",
3989 0644,
3990 psde->debugfs_root, &psde->sbuf_mode);
3991 debugfs_create_u32("sbuf_writeback",
3992 0644,
3993 psde->debugfs_root,
3994 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003995
3996 return 0;
3997}
3998
3999static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4000{
4001 struct sde_plane *psde;
4002
4003 if (!plane)
4004 return;
4005 psde = to_sde_plane(plane);
4006
4007 debugfs_remove_recursive(psde->debugfs_root);
4008}
4009#else
4010static int _sde_plane_init_debugfs(struct drm_plane *plane)
4011{
4012 return 0;
4013}
4014static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4015{
4016}
4017#endif
4018
4019static int sde_plane_late_register(struct drm_plane *plane)
4020{
4021 return _sde_plane_init_debugfs(plane);
4022}
4023
4024static void sde_plane_early_unregister(struct drm_plane *plane)
4025{
4026 _sde_plane_destroy_debugfs(plane);
4027}
4028
4029static const struct drm_plane_funcs sde_plane_funcs = {
4030 .update_plane = drm_atomic_helper_update_plane,
4031 .disable_plane = drm_atomic_helper_disable_plane,
4032 .destroy = sde_plane_destroy,
4033 .set_property = sde_plane_set_property,
4034 .atomic_set_property = sde_plane_atomic_set_property,
4035 .atomic_get_property = sde_plane_atomic_get_property,
4036 .reset = sde_plane_reset,
4037 .atomic_duplicate_state = sde_plane_duplicate_state,
4038 .atomic_destroy_state = sde_plane_destroy_state,
4039 .late_register = sde_plane_late_register,
4040 .early_unregister = sde_plane_early_unregister,
4041};
4042
4043static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
4044 .prepare_fb = sde_plane_prepare_fb,
4045 .cleanup_fb = sde_plane_cleanup_fb,
4046 .atomic_check = sde_plane_atomic_check,
4047 .atomic_update = sde_plane_atomic_update,
4048};
4049
4050enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
4051{
4052 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
4053}
4054
4055bool is_sde_plane_virtual(struct drm_plane *plane)
4056{
4057 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04004058}
4059
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004060/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04004061struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04004062 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004063 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004064{
4065 struct drm_plane *plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004066 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004067 struct sde_format_extended *virt_format_list = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004068 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004069 struct msm_drm_private *priv;
4070 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004071 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04004072 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004073
4074 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004075 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004076 goto exit;
4077 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004078
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004079 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004080 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004081 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004082 goto exit;
4083 }
4084
4085 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004086 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004087 goto exit;
4088 }
4089 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004090
Clarence Ip4c1d9772016-06-26 09:35:38 -04004091 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004092 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004093 goto exit;
4094 }
4095
Clarence Ip4ce59322016-06-26 22:27:51 -04004096 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004097 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4098 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004099 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004100 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004101 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004102 }
4103
Clarence Ip4c1d9772016-06-26 09:35:38 -04004104 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004105 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004106 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04004107 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004108 psde->is_virtual = (master_plane_id != 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004109
Clarence Ip4c1d9772016-06-26 09:35:38 -04004110 /* initialize underlying h/w driver */
4111 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
4112 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004113 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004114 ret = PTR_ERR(psde->pipe_hw);
4115 goto clean_plane;
4116 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004117 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004118 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004119 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004120
4121 /* cache features mask for later */
4122 psde->features = psde->pipe_hw->cap->features;
4123 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004124 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004125 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004126 goto clean_sspp;
4127 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004128
abeykun48f407a2016-08-25 12:06:44 -04004129 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
4130 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
4131 GFP_KERNEL);
4132 if (!psde->scaler3_cfg) {
4133 SDE_ERROR("[%u]failed to allocate scale struct\n",
4134 pipe);
4135 ret = -ENOMEM;
4136 goto clean_sspp;
4137 }
4138 }
4139
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004140 format_list = psde->pipe_sblk->format_list;
4141
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004142 if (master_plane_id) {
4143 int index, array_size;
4144
4145 array_size = ARRAY_SIZE(plane_formats)
4146 + ARRAY_SIZE(rgb_10bit_formats);
4147 virt_format_list = kcalloc(array_size,
4148 sizeof(struct sde_format_extended),
4149 GFP_KERNEL);
4150 if (!virt_format_list) {
4151 SDE_ERROR(
4152 "failed to allocate virtual pipe format list\n");
4153 goto clean_sspp;
4154 }
4155
4156 index = sde_copy_formats(virt_format_list, array_size,
4157 0, plane_formats, ARRAY_SIZE(plane_formats));
4158 sde_copy_formats(virt_format_list, array_size,
4159 index, rgb_10bit_formats,
4160 ARRAY_SIZE(rgb_10bit_formats));
4161
4162 format_list = virt_format_list;
4163 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004164
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004165 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004166 psde->formats,
4167 0,
4168 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004169
Clarence Ip4c1d9772016-06-26 09:35:38 -04004170 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004171 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004172 goto clean_sspp;
4173 }
4174
4175 if (psde->features & BIT(SDE_SSPP_CURSOR))
4176 type = DRM_PLANE_TYPE_CURSOR;
4177 else if (primary_plane)
4178 type = DRM_PLANE_TYPE_PRIMARY;
4179 else
4180 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07004181 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
4182 psde->formats, psde->nformats,
4183 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004184 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04004185 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004186
Clarence Ip4c1d9772016-06-26 09:35:38 -04004187 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004188 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004189
Clarence Ipaa0faf42016-05-30 12:07:48 -04004190 msm_property_init(&psde->property_info, &plane->base, dev,
4191 priv->plane_property, psde->property_data,
4192 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
4193 sizeof(struct sde_plane_state));
4194
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004195 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004196
Clarence Ip4ce59322016-06-26 22:27:51 -04004197 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004198 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004199
Clarence Ip730e7192016-06-26 22:45:09 -04004200 mutex_init(&psde->lock);
4201
Dhaval Patel82c8dbc2017-02-18 23:15:10 -08004202 SDE_DEBUG("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004203 return plane;
4204
Clarence Ip4c1d9772016-06-26 09:35:38 -04004205clean_sspp:
4206 if (psde && psde->pipe_hw)
4207 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04004208
4209 if (psde && psde->scaler3_cfg)
4210 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004211clean_plane:
4212 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004213exit:
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004214 kfree(virt_format_list);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004215 return ERR_PTR(ret);
4216}