blob: 36764bab92186cb8a25b1ba5748c2e098ea94f2f [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
Alan Kwong2349d742017-04-20 08:27:30 -0700632/**
633 * _sde_plane_set_ts_prefill - set prefill with traffic shaper
634 * @plane: Pointer to drm plane
635 * @pstate: Pointer to sde plane state
636 */
637static void _sde_plane_set_ts_prefill(struct drm_plane *plane,
638 struct sde_plane_state *pstate)
639{
640 struct sde_plane *psde;
641 struct sde_hw_pipe_ts_cfg cfg;
642 struct msm_drm_private *priv;
643 struct sde_kms *sde_kms;
644
645 if (!plane || !plane->dev) {
646 SDE_ERROR("invalid arguments");
647 return;
648 }
649
650 priv = plane->dev->dev_private;
651 if (!priv || !priv->kms) {
652 SDE_ERROR("invalid KMS reference\n");
653 return;
654 }
655
656 sde_kms = to_sde_kms(priv->kms);
657 psde = to_sde_plane(plane);
658 if (!psde->pipe_hw) {
659 SDE_ERROR("invalid pipe reference\n");
660 return;
661 }
662
663 if (!psde->pipe_hw || !psde->pipe_hw->ops.setup_ts_prefill)
664 return;
665
666 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_VBLANK_AMORTIZE);
667
668 memset(&cfg, 0, sizeof(cfg));
669 cfg.size = sde_plane_get_property(pstate,
670 PLANE_PROP_PREFILL_SIZE);
671 cfg.time = sde_plane_get_property(pstate,
672 PLANE_PROP_PREFILL_TIME);
673
674 SDE_DEBUG("plane%d size:%llu time:%llu\n",
675 plane->base.id, cfg.size, cfg.time);
676 SDE_EVT32(DRMID(plane), cfg.size, cfg.time);
677 psde->pipe_hw->ops.setup_ts_prefill(psde->pipe_hw, &cfg,
678 pstate->multirect_index);
679}
680
Clarence Ipcae1bb62016-07-07 12:07:13 -0400681/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400682static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400683 struct sde_plane_state *pstate, uint64_t fd)
684{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400685 if (!psde || !pstate) {
686 SDE_ERROR("invalid arg(s), plane %d state %d\n",
687 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400688 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400689 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400690
691 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400692 if (pstate->input_fence)
693 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400694
695 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400696 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400697
Clarence Ip13a8cf42016-09-29 17:27:47 -0400698 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400699}
700
Clarence Ipcae1bb62016-07-07 12:07:13 -0400701int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400702{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400703 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400704 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400705 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400706 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400707 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800708 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400709
710 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700711 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400712 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400713 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400714 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400715 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400716 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400717 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400718
Clarence Ipcae1bb62016-07-07 12:07:13 -0400719 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800720 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400721 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800722 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400723
Dhaval Patel39323d42017-03-01 23:48:24 -0800724 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400725 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400726 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
727 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400728 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800729 ret = -ETIMEDOUT;
730 break;
731 case -ERESTARTSYS:
732 SDE_ERROR_PLANE(psde,
733 "%ums wait interrupted on %08X\n",
734 wait_ms, prefix);
735 psde->is_error = true;
736 ret = -ERESTARTSYS;
737 break;
738 case -EINVAL:
739 SDE_ERROR_PLANE(psde,
740 "invalid fence param for %08X\n",
741 prefix);
742 psde->is_error = true;
743 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400744 break;
745 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800746 SDE_DEBUG_PLANE(psde, "signaled\n");
747 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400748 break;
749 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700750
751 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400752 } else {
753 ret = 0;
754 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400755 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400756 return ret;
757}
758
Clarence Ip282dad62016-09-27 17:07:35 -0400759static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400760 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400761 struct sde_hw_pipe_cfg *pipe_cfg,
762 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400763{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400764 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400765 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400766
Clarence Ip13a8cf42016-09-29 17:27:47 -0400767 if (!plane || !pstate || !pipe_cfg || !fb) {
768 SDE_ERROR(
769 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
770 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400771 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400772 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400773
774 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400775 if (!psde->pipe_hw) {
776 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400777 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400778 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400779
Clarence Ipb6eb2362016-09-08 16:18:13 -0400780 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
781 if (ret == -EAGAIN)
782 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
783 else if (ret)
784 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
785 else if (psde->pipe_hw->ops.setup_sourceaddress)
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800786 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
787 pstate->multirect_index);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400788}
789
abeykun48f407a2016-08-25 12:06:44 -0400790static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
791 struct sde_plane_state *pstate)
792{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500793 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400794 int ret = 0;
795
Clarence Ip3bf8d872017-02-16 15:25:38 -0500796 if (!psde || !psde->scaler3_cfg) {
797 SDE_ERROR("invalid args\n");
798 return -EINVAL;
799 } else if (!pstate) {
800 /* pstate is expected to be null on forced color fill */
801 SDE_DEBUG("null pstate\n");
802 return -EINVAL;
803 }
804
805 cfg = psde->scaler3_cfg;
806
abeykun48f407a2016-08-25 12:06:44 -0400807 cfg->dir_lut = msm_property_get_blob(
808 &psde->property_info,
809 pstate->property_blobs, &cfg->dir_len,
810 PLANE_PROP_SCALER_LUT_ED);
811 cfg->cir_lut = msm_property_get_blob(
812 &psde->property_info,
813 pstate->property_blobs, &cfg->cir_len,
814 PLANE_PROP_SCALER_LUT_CIR);
815 cfg->sep_lut = msm_property_get_blob(
816 &psde->property_info,
817 pstate->property_blobs, &cfg->sep_len,
818 PLANE_PROP_SCALER_LUT_SEP);
819 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
820 ret = -ENODATA;
821 return ret;
822}
823
Clarence Ipcb410d42016-06-26 22:52:33 -0400824static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400825 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
826 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400827 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400828 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
829{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700830 uint32_t decimated, i;
831
832 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
833 !chroma_subsmpl_v) {
834 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
835 , psde, scale_cfg, fmt, chroma_subsmpl_h,
836 chroma_subsmpl_v);
837 return;
838 }
839
840 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip716ab662017-03-20 06:51:24 -0700841 memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700842
843 decimated = DECIMATED_DIMENSION(src_w,
844 psde->pipe_cfg.horz_decimation);
845 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
846 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
847 decimated = DECIMATED_DIMENSION(src_h,
848 psde->pipe_cfg.vert_decimation);
849 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
850 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
851
852
853 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
854 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
855 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
856 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
857
858 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
859 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
860 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
861 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
862
863 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
864 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
865 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
866 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
867
868 for (i = 0; i < SDE_MAX_PLANES; i++) {
869 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
870 psde->pipe_cfg.horz_decimation);
871 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
872 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700873 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
874 scale_cfg->src_width[i] /= chroma_subsmpl_h;
875 scale_cfg->src_height[i] /= chroma_subsmpl_v;
876 }
877 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
878 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
879 psde->pixel_ext.num_ext_pxls_top[i] =
880 scale_cfg->src_height[i];
881 psde->pixel_ext.num_ext_pxls_left[i] =
882 scale_cfg->src_width[i];
883 }
884 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
885 && (src_w == dst_w))
886 return;
887
888 scale_cfg->dst_width = dst_w;
889 scale_cfg->dst_height = dst_h;
890 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
891 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
892 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
893 scale_cfg->lut_flag = 0;
894 scale_cfg->blend_cfg = 1;
895 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -0400896}
897
Clarence Ipcb410d42016-06-26 22:52:33 -0400898/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400899 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400900 * @psde: Pointer to SDE plane object
901 * @src: Source size
902 * @dst: Destination size
903 * @phase_steps: Pointer to output array for phase steps
904 * @filter: Pointer to output array for filter type
905 * @fmt: Pointer to format definition
906 * @chroma_subsampling: Subsampling amount for chroma channel
907 *
908 * Returns: 0 on success
909 */
910static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400911 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400912 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400913 uint32_t chroma_subsampling)
914{
Clarence Ipcb410d42016-06-26 22:52:33 -0400915 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400916 SDE_ERROR(
917 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
918 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400919 return -EINVAL;
920 }
921
Clarence Ip4c1d9772016-06-26 09:35:38 -0400922 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400923 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400924 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400925 phase_steps[SDE_SSPP_COMP_1_2] =
926 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
927 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
928 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400929
930 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400931 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400932 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400933 (src <= dst) ? SDE_SCALE_FILTER_BIL :
934 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400935
Clarence Ipdbde9832016-06-26 09:48:36 -0400936 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400937 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400938 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
939 } else {
940 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
941 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400942 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400943 }
944 } else {
945 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400946 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
947 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
948 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400949 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400950 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400951}
952
Clarence Ipcb410d42016-06-26 22:52:33 -0400953/**
954 * _sde_plane_setup_pixel_ext - determine default pixel extension values
955 * @psde: Pointer to SDE plane object
956 * @src: Source size
957 * @dst: Destination size
958 * @decimated_src: Source size after decimation, if any
959 * @phase_steps: Pointer to output array for phase steps
960 * @out_src: Output array for pixel extension values
961 * @out_edge1: Output array for pixel extension first edge
962 * @out_edge2: Output array for pixel extension second edge
963 * @filter: Pointer to array for filter type
964 * @fmt: Pointer to format definition
965 * @chroma_subsampling: Subsampling amount for chroma channel
966 * @post_compare: Whether to chroma subsampled source size for comparisions
967 */
968static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400969 uint32_t src, uint32_t dst, uint32_t decimated_src,
970 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400971 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400972 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400973 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400974{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400975 int64_t edge1, edge2, caf;
976 uint32_t src_work;
977 int i, tmp;
978
Clarence Ipcb410d42016-06-26 22:52:33 -0400979 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400980 out_edge2 && filter && fmt) {
981 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400982 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400983 caf = PHASE_STEP_UNIT_SCALE;
984 else
985 caf = 0;
986
987 for (i = 0; i < SDE_MAX_PLANES; i++) {
988 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400989 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400990 src_work /= chroma_subsampling;
991 if (post_compare)
992 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400993 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400994 /* unity */
995 edge1 = 0;
996 edge2 = 0;
997 } else if (dst >= src) {
998 /* upscale */
999 edge1 = (1 << PHASE_RESIDUAL);
1000 edge1 -= caf;
1001 edge2 = (1 << PHASE_RESIDUAL);
1002 edge2 += (dst - 1) * *(phase_steps + i);
1003 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1004 edge2 += caf;
1005 edge2 = -(edge2);
1006 } else {
1007 /* downscale */
1008 edge1 = 0;
1009 edge2 = (dst - 1) * *(phase_steps + i);
1010 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1011 edge2 += *(phase_steps + i);
1012 edge2 = -(edge2);
1013 }
1014
1015 /* only enable CAF for luma plane */
1016 caf = 0;
1017
1018 /* populate output arrays */
1019 *(out_src + i) = src_work;
1020
1021 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001022 if (edge1 >= 0) {
1023 tmp = (uint32_t)edge1;
1024 tmp >>= PHASE_STEP_SHIFT;
1025 *(out_edge1 + i) = -tmp;
1026 } else {
1027 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -04001028 *(out_edge1 + i) =
1029 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1030 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001031 }
1032 if (edge2 >= 0) {
1033 tmp = (uint32_t)edge2;
1034 tmp >>= PHASE_STEP_SHIFT;
1035 *(out_edge2 + i) = -tmp;
1036 } else {
1037 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -04001038 *(out_edge2 + i) =
1039 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1040 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001041 }
1042 }
1043 }
1044}
1045
Clarence Ip5fc00c52016-09-23 15:03:34 -04001046static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -04001047{
1048 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
1049 {
Clarence Ip373f8592016-05-26 00:58:42 -04001050 /* S15.16 format */
1051 0x00012A00, 0x00000000, 0x00019880,
1052 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1053 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -04001054 },
Clarence Ip373f8592016-05-26 00:58:42 -04001055 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -04001056 { 0xfff0, 0xff80, 0xff80,},
1057 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001058 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -04001059 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001060 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -04001061 };
abeykun1c312f62016-08-26 09:47:12 -04001062 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
1063 {
1064 /* S15.16 format */
1065 0x00012A00, 0x00000000, 0x00019880,
1066 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1067 0x00012A00, 0x00020480, 0x00000000,
1068 },
1069 /* signed bias */
1070 { 0xffc0, 0xfe00, 0xfe00,},
1071 { 0x0, 0x0, 0x0,},
1072 /* unsigned clamp */
1073 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
1074 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
1075 };
Clarence Ipe78efb72016-06-24 18:35:21 -04001076
Clarence Ip5fc00c52016-09-23 15:03:34 -04001077 if (!psde) {
1078 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001079 return;
1080 }
Clarence Ip5e2a9222016-06-26 22:38:24 -04001081
Clarence Ipcae1bb62016-07-07 12:07:13 -04001082 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001083 if (psde->csc_usr_ptr)
1084 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -04001085 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
1086 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001087 else
Clarence Ip373f8592016-05-26 00:58:42 -04001088 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001089
Clarence Ip13a8cf42016-09-29 17:27:47 -04001090 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -04001091 psde->csc_ptr->csc_mv[0],
1092 psde->csc_ptr->csc_mv[1],
1093 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -04001094}
1095
Benet Clarkeb1b4462016-06-27 14:43:06 -07001096static void sde_color_process_plane_setup(struct drm_plane *plane)
1097{
1098 struct sde_plane *psde;
1099 struct sde_plane_state *pstate;
1100 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001101 struct drm_msm_memcol *memcol = NULL;
1102 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001103
1104 psde = to_sde_plane(plane);
1105 pstate = to_sde_plane_state(plane->state);
1106
1107 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1108 if (psde->pipe_hw->ops.setup_pa_hue)
1109 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1110 saturation = (uint32_t) sde_plane_get_property(pstate,
1111 PLANE_PROP_SATURATION_ADJUST);
1112 if (psde->pipe_hw->ops.setup_pa_sat)
1113 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1114 value = (uint32_t) sde_plane_get_property(pstate,
1115 PLANE_PROP_VALUE_ADJUST);
1116 if (psde->pipe_hw->ops.setup_pa_val)
1117 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1118 contrast = (uint32_t) sde_plane_get_property(pstate,
1119 PLANE_PROP_CONTRAST_ADJUST);
1120 if (psde->pipe_hw->ops.setup_pa_cont)
1121 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001122
Benet Clarkd009b1d2016-06-27 14:45:59 -07001123 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1124 /* Skin memory color setup */
1125 memcol = msm_property_get_blob(&psde->property_info,
1126 pstate->property_blobs,
1127 &memcol_sz,
1128 PLANE_PROP_SKIN_COLOR);
1129 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1130 MEMCOLOR_SKIN, memcol);
1131
1132 /* Sky memory color setup */
1133 memcol = msm_property_get_blob(&psde->property_info,
1134 pstate->property_blobs,
1135 &memcol_sz,
1136 PLANE_PROP_SKY_COLOR);
1137 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1138 MEMCOLOR_SKY, memcol);
1139
1140 /* Foliage memory color setup */
1141 memcol = msm_property_get_blob(&psde->property_info,
1142 pstate->property_blobs,
1143 &memcol_sz,
1144 PLANE_PROP_FOLIAGE_COLOR);
1145 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1146 MEMCOLOR_FOLIAGE, memcol);
1147 }
1148}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001149
Clarence Ipcb410d42016-06-26 22:52:33 -04001150static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001151 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -04001152 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001153{
Clarence Ipb43d4592016-09-08 14:21:35 -04001154 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001155 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001156
Clarence Ipb43d4592016-09-08 14:21:35 -04001157 if (!psde || !fmt) {
1158 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1159 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001160 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001161 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001162
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001163 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001164
Clarence Ipdedbba92016-09-27 17:43:10 -04001165 psde->pipe_cfg.horz_decimation =
1166 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1167 psde->pipe_cfg.vert_decimation =
1168 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001169
1170 /* don't chroma subsample if decimating */
1171 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001172 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001173 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001174 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001175
Clarence Ip5e2a9222016-06-26 22:38:24 -04001176 /* update scaler */
1177 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001178 int error;
1179
1180 error = _sde_plane_setup_scaler3_lut(psde, pstate);
Clarence Ip716ab662017-03-20 06:51:24 -07001181 if (error || !psde->pixel_ext_usr ||
1182 psde->debugfs_default_scale) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001183 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001184 _sde_plane_setup_scaler3(psde,
1185 psde->pipe_cfg.src_rect.w,
1186 psde->pipe_cfg.src_rect.h,
1187 psde->pipe_cfg.dst_rect.w,
1188 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001189 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001190 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001191 }
Clarence Ip716ab662017-03-20 06:51:24 -07001192 } else if (!psde->pixel_ext_usr || !pstate ||
1193 psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001194 uint32_t deci_dim, i;
1195
Clarence Ipb43d4592016-09-08 14:21:35 -04001196 /* calculate default configuration for QSEED2 */
1197 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001198
Clarence Ip13a8cf42016-09-29 17:27:47 -04001199 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001200 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1201 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001202 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001203 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001204 psde->pipe_cfg.dst_rect.w,
1205 pe->phase_step_x,
1206 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001207
Clarence Ipdbde9832016-06-26 09:48:36 -04001208 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001209 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001210 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001211 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001212 pe->phase_step_x,
1213 pe->roi_w,
1214 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001215 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001216 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001217
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001218 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001219 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001220 _sde_plane_setup_scaler2(psde,
1221 deci_dim,
1222 psde->pipe_cfg.dst_rect.h,
1223 pe->phase_step_y,
1224 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001225 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001226 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001227 pe->phase_step_y,
1228 pe->roi_h,
1229 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001230 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001231 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001232
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001233 for (i = 0; i < SDE_MAX_PLANES; i++) {
1234 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001235 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001236 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001237 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001238
1239 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001240 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001241 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001242 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001243
1244 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001245 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001246 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001247 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001248
1249 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001250 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001251 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001252 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001253 }
1254 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001255}
1256
Clarence Ipcae1bb62016-07-07 12:07:13 -04001257/**
1258 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001259 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001260 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1261 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1262 * Returns: 0 on success
1263 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001264static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001265 uint32_t color, uint32_t alpha)
1266{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001267 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001268 const struct drm_plane *plane;
1269 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001270
Clarence Ip13a8cf42016-09-29 17:27:47 -04001271 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001272 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001273 return -EINVAL;
1274 }
1275
Clarence Ipcb410d42016-06-26 22:52:33 -04001276 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001277 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001278 return -EINVAL;
1279 }
1280
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001281 plane = &psde->base;
1282 pstate = to_sde_plane_state(plane->state);
1283
Clarence Ip13a8cf42016-09-29 17:27:47 -04001284 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001285
Clarence Ipcb410d42016-06-26 22:52:33 -04001286 /*
1287 * select fill format to match user property expectation,
1288 * h/w only supports RGB variants
1289 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001290 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001291
1292 /* update sspp */
1293 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1294 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001295 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1296 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001297
1298 /* override scaler/decimation if solid fill */
1299 psde->pipe_cfg.src_rect.x = 0;
1300 psde->pipe_cfg.src_rect.y = 0;
1301 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1302 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Dhaval Patele4b6bb22017-03-27 17:22:21 -07001303 _sde_plane_setup_scaler(psde, fmt, 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001304
Clarence Ipcb410d42016-06-26 22:52:33 -04001305 if (psde->pipe_hw->ops.setup_format)
1306 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001307 fmt, SDE_SSPP_SOLID_FILL,
1308 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001309
1310 if (psde->pipe_hw->ops.setup_rects)
1311 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001312 &psde->pipe_cfg,
1313 pstate->multirect_index);
1314
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001315 if (psde->pipe_hw->ops.setup_pe)
1316 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1317 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001318 }
1319
1320 return 0;
1321}
1322
Alan Kwong4dd64c82017-02-04 18:41:51 -08001323/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001324 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1325 */
1326static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1327{
1328 drm_framebuffer_reference(fb);
1329 return fb;
1330}
1331static void _sde_plane_fb_put(void *fb)
1332{
1333 drm_framebuffer_unreference(fb);
1334}
1335static struct sde_crtc_res_ops fb_res_ops = {
1336 .put = _sde_plane_fb_put,
1337 .get = _sde_plane_fb_get,
1338};
1339
1340/**
1341 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1342 */
1343static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1344{
1345 sde_kms_fbo_reference(fbo);
1346 return fbo;
1347}
1348static void _sde_plane_fbo_put(void *fbo)
1349{
1350 sde_kms_fbo_unreference(fbo);
1351}
1352static struct sde_crtc_res_ops fbo_res_ops = {
1353 .put = _sde_plane_fbo_put,
1354 .get = _sde_plane_fbo_get,
1355};
1356
1357/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001358 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001359 * @plane: Pointer to drm plane
1360 * return: prefill time in line
1361 */
1362static u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
1363{
1364 struct drm_plane_state *state;
1365 struct drm_crtc_state *cstate;
1366 struct sde_plane_state *pstate;
1367 struct sde_plane_rot_state *rstate;
1368 struct sde_kms *sde_kms;
1369 u32 blocksize = 128;
1370 u32 prefill_line = 0;
1371
1372 if (!plane || !plane->state || !plane->state->fb ||
1373 !plane->state->crtc || !plane->state->crtc->state) {
1374 SDE_ERROR("invalid parameters\n");
1375 return 0;
1376 }
1377
1378 sde_kms = _sde_plane_get_kms(plane);
1379 state = plane->state;
1380 cstate = state->crtc->state;
1381 pstate = to_sde_plane_state(state);
1382 rstate = &pstate->rot;
1383
1384 if (!rstate->rot_hw || !rstate->rot_hw->caps || !rstate->out_src_h ||
1385 !sde_kms || !sde_kms->catalog) {
1386 SDE_ERROR("invalid parameters\n");
1387 return 0;
1388 }
1389
Alan Kwong4aacd532017-02-04 18:51:33 -08001390 sde_format_get_block_size(rstate->out_fb_format, &blocksize,
1391 &blocksize);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001392 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
1393
1394 SDE_DEBUG("plane%d prefill:%u\n", plane->base.id, prefill_line);
1395
1396 return prefill_line;
1397}
1398
1399/**
1400 * sde_plane_is_sbuf_mode - check if sspp of given plane is in streaming
1401 * buffer mode
1402 * @plane: Pointer to drm plane
1403 * @prefill: Pointer to prefill line count
1404 * return: true if sspp is in stream buffer mode
1405 */
1406bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill)
1407{
1408 struct sde_plane_state *pstate = plane && plane->state ?
1409 to_sde_plane_state(plane->state) : NULL;
1410 struct sde_plane_rot_state *rstate = pstate ? &pstate->rot : NULL;
1411 bool sbuf_mode = rstate ? rstate->out_sbuf : false;
1412
1413 if (prefill && sbuf_mode)
1414 *prefill = sde_plane_rot_calc_prefill(plane);
1415
1416 return sbuf_mode;
1417}
1418
1419/**
1420 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1421 * enumerating over all planes attached to the same rotator
1422 * @plane: Pointer to drm plane
1423 * @state: Pointer to drm state to be updated
1424 * return: none
1425 */
1426static void sde_plane_rot_calc_cfg(struct drm_plane *plane,
1427 struct drm_plane_state *state)
1428{
1429 struct sde_plane_state *pstate;
1430 struct sde_plane_rot_state *rstate;
1431 struct sde_hw_blk *hw_blk;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001432 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001433 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001434 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001435 u32 dst_x, dst_y, dst_w, dst_h;
1436 int found = 0;
1437 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001438 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001439
1440 if (!plane || !state || !state->state) {
1441 SDE_ERROR("invalid parameters\n");
1442 return;
1443 }
1444
Alan Kwongcdb2f282017-03-18 13:42:06 -07001445 cstate = _sde_plane_get_crtc_state(state);
1446 if (IS_ERR_OR_NULL(cstate)) {
1447 ret = PTR_ERR(cstate);
1448 SDE_ERROR("invalid crtc state %d\n", ret);
1449 return;
1450 }
1451
Alan Kwong4dd64c82017-02-04 18:41:51 -08001452 pstate = to_sde_plane_state(state);
1453 rstate = &pstate->rot;
1454
1455 if (!rstate->rot_hw) {
1456 SDE_ERROR("invalid rotator hw\n");
1457 return;
1458 }
1459
1460 in_rot = &rstate->in_rot_rect;
1461 in_rot->x1 = state->src_x;
1462 in_rot->y1 = state->src_y;
1463 in_rot->x2 = state->src_x + state->src_w;
1464 in_rot->y2 = state->src_y + state->src_h;
1465
1466 out_rot = &rstate->out_rot_rect;
1467 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1468 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1469 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1470 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1471
1472 if (!dst_w && !dst_h) {
1473 rstate->out_rot_rect = rstate->in_rot_rect;
1474 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1475 state->fb->height << 16, rstate->in_rotation);
1476 } else {
1477 out_rot->x1 = dst_x;
1478 out_rot->y1 = dst_y;
1479 out_rot->x2 = dst_x + dst_w;
1480 out_rot->y2 = dst_y + dst_h;
1481 }
1482
1483 rstate->out_src_rect = rstate->out_rot_rect;
1484
1485 hw_blk = &rstate->rot_hw->base;
1486
1487 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001488 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001489 struct drm_plane_state *attached_state;
1490 struct sde_plane_state *attached_pstate;
1491 struct sde_plane_rot_state *attached_rstate;
1492 struct drm_rect attached_out_rect;
1493
Alan Kwong4dd64c82017-02-04 18:41:51 -08001494 attached_state = drm_atomic_get_existing_plane_state(
1495 state->state, attached_plane);
1496
1497 if (!attached_state)
1498 continue;
1499
1500 attached_pstate = to_sde_plane_state(attached_state);
1501 attached_rstate = &attached_pstate->rot;
1502
Alan Kwongcdb2f282017-03-18 13:42:06 -07001503 if (attached_rstate->rot_hw != rstate->rot_hw)
1504 continue;
1505
1506 found++;
1507
1508 /* skip itself */
1509 if (attached_plane == plane)
1510 continue;
1511
Alan Kwong4dd64c82017-02-04 18:41:51 -08001512 /* find bounding rotator source roi */
1513 if (attached_state->src_x < in_rot->x1)
1514 in_rot->x1 = attached_state->src_x;
1515
1516 if (attached_state->src_y < in_rot->y1)
1517 in_rot->y1 = attached_state->src_y;
1518
1519 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1520 in_rot->x2 = attached_state->src_x +
1521 attached_state->src_w;
1522
1523 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1524 in_rot->y2 = attached_state->src_y +
1525 attached_state->src_h;
1526
1527 /* find bounding rotator destination roi */
1528 dst_x = sde_plane_get_property(attached_pstate,
1529 PLANE_PROP_ROT_DST_X);
1530 dst_y = sde_plane_get_property(attached_pstate,
1531 PLANE_PROP_ROT_DST_Y);
1532 dst_w = sde_plane_get_property(attached_pstate,
1533 PLANE_PROP_ROT_DST_W);
1534 dst_h = sde_plane_get_property(attached_pstate,
1535 PLANE_PROP_ROT_DST_H);
1536 if (!dst_w && !dst_h) {
1537 attached_out_rect.x1 = attached_state->src_x;
1538 attached_out_rect.y1 = attached_state->src_y;
1539 attached_out_rect.x2 = attached_out_rect.x1 +
1540 attached_state->src_w;
1541 attached_out_rect.y2 = attached_out_rect.y1 +
1542 attached_state->src_h;
1543 drm_rect_rotate(&attached_out_rect,
1544 state->fb->width << 16,
1545 state->fb->height << 16,
1546 rstate->in_rotation);
1547 } else {
1548 attached_out_rect.x1 = dst_x;
1549 attached_out_rect.y1 = dst_y;
1550 attached_out_rect.x2 = dst_x + dst_w;
1551 attached_out_rect.y2 = dst_y + dst_h;
1552 }
1553
1554 /* find relative sspp position */
1555 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1556 xpos++;
1557
1558 if (attached_out_rect.x1 < out_rot->x1)
1559 out_rot->x1 = attached_out_rect.x1;
1560
1561 if (attached_out_rect.y1 < out_rot->y1)
1562 out_rot->y1 = attached_out_rect.y1;
1563
1564 if (attached_out_rect.x2 > out_rot->x2)
1565 out_rot->x2 = attached_out_rect.x2;
1566
1567 if (attached_out_rect.y2 > out_rot->y2)
1568 out_rot->y2 = attached_out_rect.y2;
1569
1570 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1571 attached_plane->base.id,
1572 attached_rstate->sequence_id,
1573 attached_rstate->out_src_rect.x1 >> 16,
1574 attached_state->src_w >> 16,
1575 attached_state->src_h >> 16,
1576 attached_state->src_x >> 16,
1577 attached_state->src_y >> 16,
1578 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1579 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1580 attached_rstate->out_src_rect.x1 >> 16,
1581 attached_rstate->out_src_rect.y1 >> 16);
1582 }
1583
1584 rstate->out_xpos = xpos;
1585 rstate->nplane = found;
1586
1587 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1588 plane->base.id, rstate->sequence_id,
1589 rstate->out_xpos, rstate->nplane,
1590 drm_rect_width(in_rot) >> 16,
1591 drm_rect_height(in_rot) >> 16,
1592 in_rot->x1 >> 16, in_rot->y1 >> 16,
1593 drm_rect_width(&rstate->out_rot_rect) >> 16,
1594 drm_rect_height(&rstate->out_rot_rect) >> 16,
1595 rstate->out_rot_rect.x1 >> 16,
1596 rstate->out_rot_rect.y1 >> 16);
1597}
1598
1599/**
1600 * sde_plane_rot_submit_command - commit given state for the rotator stage
1601 * @plane: Pointer to drm plane
1602 * @state: Pointer to the state to be committed
1603 * @hw_cmd: rotator command type
1604 * return: 0 if success; error code otherwise
1605 */
1606static int sde_plane_rot_submit_command(struct drm_plane *plane,
1607 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1608{
1609 struct sde_plane *psde = to_sde_plane(plane);
1610 struct sde_plane_state *pstate = to_sde_plane_state(state);
1611 struct sde_plane_rot_state *rstate = &pstate->rot;
1612 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001613 struct drm_crtc_state *cstate;
1614 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001615 int ret, i;
1616
1617 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1618 SDE_ERROR("invalid parameters\n");
1619 return -EINVAL;
1620 }
1621
Alan Kwong4aacd532017-02-04 18:51:33 -08001622 cstate = _sde_plane_get_crtc_state(state);
1623 if (IS_ERR_OR_NULL(cstate)) {
1624 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1625 return -EINVAL;
1626 }
1627 sde_cstate = to_sde_crtc_state(cstate);
1628
Alan Kwong4dd64c82017-02-04 18:41:51 -08001629 rot_cmd = &rstate->rot_cmd;
1630
1631 rot_cmd->master = (rstate->out_xpos == 0);
1632 rot_cmd->sequence_id = rstate->sequence_id;
1633 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1634 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1635 DEFAULT_REFRESH_RATE;
1636 rot_cmd->rot90 = rstate->rot90;
1637 rot_cmd->hflip = rstate->hflip;
1638 rot_cmd->vflip = rstate->vflip;
1639 rot_cmd->secure = state->fb->flags & DRM_MODE_FB_SECURE ? true : false;
Alan Kwong4aacd532017-02-04 18:51:33 -08001640 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1641 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001642 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1643 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001644 rot_cmd->dst_writeback = psde->sbuf_writeback;
1645
1646 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1647 rot_cmd->video_mode = true;
1648 else
1649 rot_cmd->video_mode = false;
1650
1651 rot_cmd->src_pixel_format = state->fb->pixel_format;
1652 rot_cmd->src_modifier = state->fb->modifier[0];
1653 rot_cmd->src_stride = state->fb->pitches[0];
1654
1655 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1656 if (!rot_cmd->src_format) {
1657 SDE_ERROR("failed to get src format\n");
1658 return -EINVAL;
1659 }
1660
1661 rot_cmd->src_width = state->fb->width;
1662 rot_cmd->src_height = state->fb->height;
1663 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1664 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1665 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1666 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
1667 rot_cmd->dst_rect_x = rstate->out_rot_rect.x1 >> 16;
1668 rot_cmd->dst_rect_y = rstate->out_rot_rect.y1 >> 16;
1669 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1670 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1671
1672 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1673 struct sde_hw_fmt_layout layout;
1674
1675 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1676 sde_format_populate_layout(rstate->mmu_id, state->fb,
1677 &layout);
1678 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1679 rot_cmd->src_iova[i] = layout.plane_addr[i];
1680 rot_cmd->src_len[i] = layout.plane_size[i];
1681 }
1682 rot_cmd->src_planes = layout.num_planes;
1683
1684 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1685 sde_format_populate_layout(rstate->mmu_id, rstate->out_fb,
1686 &layout);
1687 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1688 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1689 rot_cmd->dst_len[i] = layout.plane_size[i];
1690 }
1691 rot_cmd->dst_planes = layout.num_planes;
1692 }
1693
1694 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
1695 if (ret) {
1696 SDE_ERROR("failed to commit rotator %d\n", ret);
1697 return ret;
1698 }
1699
1700 rstate->out_rotation = rstate->in_rotation;
1701 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1702 DRM_MODE_FB_MODIFIERS : 0;
1703 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1704 rstate->out_fb_format = rot_cmd->dst_format;
1705 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1706
1707 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1708 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1709
1710 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1711 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1712 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1713 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1714 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1715 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1716
1717 if (rot_cmd->rot90)
1718 rstate->out_rotation &= ~DRM_ROTATE_90;
1719
1720 if (rot_cmd->hflip)
1721 rstate->out_rotation &= ~DRM_REFLECT_X;
1722
1723 if (rot_cmd->vflip)
1724 rstate->out_rotation &= ~DRM_REFLECT_Y;
1725
1726 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07001727 "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 -08001728 plane->base.id, rstate->sequence_id, hw_cmd,
1729 rot_cmd->rot90 ? 'r' : '_',
1730 rot_cmd->hflip ? 'h' : '_',
1731 rot_cmd->vflip ? 'v' : '_',
1732 rot_cmd->video_mode ? 'V' : 'C',
1733 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001734 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001735 state->fb->modifier[0],
1736 drm_rect_width(&rstate->in_rot_rect) >> 16,
1737 drm_rect_height(&rstate->in_rot_rect) >> 16,
1738 rstate->in_rot_rect.x1 >> 16,
1739 rstate->in_rot_rect.y1 >> 16);
1740
Dhaval Patel6c666622017-03-21 23:02:59 -07001741 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 -08001742 plane->base.id, rstate->sequence_id, hw_cmd,
1743 rstate->out_rotation,
1744 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001745 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001746 rstate->out_fb_modifier[0],
1747 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
1748 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
1749
1750 return ret;
1751}
1752
1753/**
1754 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
1755 * for rotator (pre-sspp) stage
1756 * @plane: Pointer to drm plane
1757 * @new_state: Pointer to new drm plane state
1758 * return: 0 if success; error code otherwise
1759 */
1760static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
1761 struct drm_plane_state *new_state)
1762{
1763 struct drm_framebuffer *fb = new_state->fb;
1764 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
1765 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001766 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001767 int ret;
1768
1769 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
1770 plane->base.id,
1771 new_rstate->sequence_id, fb ? fb->base.id : 0,
1772 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
1773 sde_plane_crtc_enabled(new_state));
1774
1775 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
1776 return 0;
1777
Alan Kwongcdb2f282017-03-18 13:42:06 -07001778 cstate = _sde_plane_get_crtc_state(new_state);
1779 if (IS_ERR(cstate)) {
1780 ret = PTR_ERR(cstate);
1781 SDE_ERROR("invalid crtc state %d\n", ret);
1782 return ret;
1783 }
1784
Alan Kwong4dd64c82017-02-04 18:41:51 -08001785 /* need to re-calc based on all newly validated plane states */
1786 sde_plane_rot_calc_cfg(plane, new_state);
1787
1788 /* check if stream buffer is already attached to rotator */
1789 if (sde_plane_enabled(new_state)) {
1790 struct sde_kms_fbo *fbo;
1791 struct drm_framebuffer *fb;
1792
Alan Kwongcdb2f282017-03-18 13:42:06 -07001793 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1794 (u64) &new_rstate->rot_hw->base);
1795 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1796 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001797 if (fb && fbo) {
1798 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
1799 new_rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001800 } else if (fbo) {
1801 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1802 (u64) &new_rstate->rot_hw->base);
1803 fbo = NULL;
1804 } else if (fb) {
1805 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1806 (u64) &new_rstate->rot_hw->base);
1807 fb = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001808 }
Alan Kwongcdb2f282017-03-18 13:42:06 -07001809
1810 new_rstate->out_fbo = fbo;
1811 new_rstate->out_fb = fb;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001812 }
1813
1814 /* release buffer if output format configuration changes */
1815 if (new_rstate->out_fb &&
1816 ((new_rstate->out_fb_height != new_rstate->out_fb->height) ||
1817 (new_rstate->out_fb_width != new_rstate->out_fb->width) ||
1818 (new_rstate->out_fb_pixel_format !=
1819 new_rstate->out_fb->pixel_format) ||
1820 (new_rstate->out_fb_modifier[0] !=
1821 new_rstate->out_fb->modifier[0]) ||
1822 (new_rstate->out_fb_flags != new_rstate->out_fb->flags))) {
1823
1824 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
1825 new_rstate->sequence_id);
1826
Alan Kwongcdb2f282017-03-18 13:42:06 -07001827 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1828 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001829 new_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001830 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1831 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001832 new_rstate->out_fbo = NULL;
1833 }
1834
1835 /* create new stream buffer if it is not available */
1836 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
1837 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
1838 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
1839
1840 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
1841 new_rstate->sequence_id);
1842
1843 if (new_state->fb->flags & DRM_MODE_FB_SECURE)
1844 new_rstate->mmu_id = MSM_SMMU_DOMAIN_SECURE;
1845 else
1846 new_rstate->mmu_id = MSM_SMMU_DOMAIN_UNSECURE;
1847
1848 /* check if out_fb is already attached to rotator */
1849 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
1850 new_rstate->out_fb_pixel_format,
1851 new_rstate->out_fb_modifier,
1852 new_rstate->out_fb_flags);
1853 if (!new_rstate->out_fbo) {
1854 SDE_ERROR("failed to allocate inline buffer object\n");
1855 ret = -EINVAL;
1856 goto error_create_fbo;
1857 }
1858
Alan Kwongcdb2f282017-03-18 13:42:06 -07001859 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1860 (u64) &new_rstate->rot_hw->base,
1861 new_rstate->out_fbo, &fbo_res_ops);
1862 if (ret) {
1863 SDE_ERROR("failed to add crtc resource\n");
1864 goto error_create_fbo_res;
1865 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001866
1867 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
1868 new_rstate->out_fbo);
1869 if (!new_rstate->out_fb) {
1870 SDE_ERROR("failed to create inline framebuffer\n");
1871 ret = -EINVAL;
1872 goto error_create_fb;
1873 }
1874
Alan Kwongcdb2f282017-03-18 13:42:06 -07001875 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1876 (u64) &new_rstate->rot_hw->base,
1877 new_rstate->out_fb, &fb_res_ops);
1878 if (ret) {
1879 SDE_ERROR("failed to add crtc resource %d\n", ret);
1880 goto error_create_fb_res;
1881 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001882 }
1883
1884 /* prepare rotator input buffer */
1885 ret = msm_framebuffer_prepare(new_state->fb, new_rstate->mmu_id);
1886 if (ret) {
1887 SDE_ERROR("failed to prepare input framebuffer\n");
1888 goto error_prepare_input_buffer;
1889 }
1890
1891 /* prepare rotator output buffer */
1892 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
1893 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
1894 new_rstate->sequence_id);
1895
1896 ret = msm_framebuffer_prepare(new_rstate->out_fb,
1897 new_rstate->mmu_id);
1898 if (ret) {
1899 SDE_ERROR("failed to prepare inline framebuffer\n");
1900 goto error_prepare_output_buffer;
1901 }
1902 }
1903
1904 return 0;
1905
1906error_prepare_output_buffer:
1907 msm_framebuffer_cleanup(new_state->fb, new_rstate->mmu_id);
1908error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001909 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1910 (u64) &new_rstate->rot_hw->base);
1911error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001912 new_rstate->out_fb = NULL;
1913error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001914 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1915 (u64) &new_rstate->rot_hw->base);
1916error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001917 new_rstate->out_fbo = NULL;
1918error_create_fbo:
1919 return ret;
1920}
1921
1922/**
1923 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
1924 * rotator (pre-sspp) stage
1925 * @plane: Pointer to drm plane
1926 * @old_state: Pointer to previous drm plane state
1927 * return: none
1928 */
1929static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
1930 struct drm_plane_state *old_state)
1931{
1932 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
1933 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
1934 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001935 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001936 int ret;
1937
1938 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1939 old_rstate->sequence_id, old_state->fb->base.id,
1940 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
1941 sde_plane_crtc_enabled(old_state));
1942
1943 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
1944 return;
1945
Alan Kwongcdb2f282017-03-18 13:42:06 -07001946 cstate = _sde_plane_get_crtc_state(old_state);
1947 if (IS_ERR(cstate)) {
1948 ret = PTR_ERR(cstate);
1949 SDE_ERROR("invalid crtc state %d\n", ret);
1950 return;
1951 }
1952
Alan Kwong4dd64c82017-02-04 18:41:51 -08001953 if (sde_plane_crtc_enabled(old_state)) {
1954 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
1955 SDE_HW_ROT_CMD_CLEANUP);
1956 if (ret)
1957 SDE_ERROR("failed to cleanup rotator buffers\n");
1958 }
1959
1960 if (sde_plane_enabled(old_state)) {
1961 if (old_rstate->out_fb) {
1962 msm_framebuffer_cleanup(old_rstate->out_fb,
1963 old_rstate->mmu_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001964 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1965 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001966 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001967 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1968 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001969 old_rstate->out_fbo = NULL;
1970 }
1971
1972 msm_framebuffer_cleanup(old_state->fb, old_rstate->mmu_id);
1973 }
1974}
1975
1976/**
1977 * sde_plane_rot_atomic_check - verify rotator update of the given state
1978 * @plane: Pointer to drm plane
1979 * @state: Pointer to drm plane state to be validated
1980 * return: 0 if success; error code otherwise
1981 */
1982static int sde_plane_rot_atomic_check(struct drm_plane *plane,
1983 struct drm_plane_state *state)
1984{
1985 struct sde_plane *psde;
1986 struct sde_plane_state *pstate, *old_pstate;
1987 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001988 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001989 struct sde_hw_blk *hw_blk;
1990 int i, ret = 0;
1991
1992 if (!plane || !state) {
1993 SDE_ERROR("invalid plane/state\n");
1994 return -EINVAL;
1995 }
1996
1997 psde = to_sde_plane(plane);
1998 pstate = to_sde_plane_state(state);
1999 old_pstate = to_sde_plane_state(plane->state);
2000 rstate = &pstate->rot;
2001 old_rstate = &old_pstate->rot;
2002
Alan Kwongcdb2f282017-03-18 13:42:06 -07002003 /* cstate will be null if crtc is disconnected from plane */
2004 cstate = _sde_plane_get_crtc_state(state);
2005 if (IS_ERR(cstate)) {
2006 ret = PTR_ERR(cstate);
2007 SDE_ERROR("invalid crtc state %d\n", ret);
2008 return ret;
2009 }
2010
Alan Kwong4dd64c82017-02-04 18:41:51 -08002011 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2012 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
2013 !!rstate->out_sbuf, !!rstate->rot_hw,
2014 sde_plane_crtc_enabled(state));
2015
2016 rstate->in_rotation = drm_rotation_simplify(
2017 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07002018 DRM_ROTATE_0 | DRM_ROTATE_90 |
2019 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002020 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
2021 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
2022 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
2023 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
2024
Alan Kwongcdb2f282017-03-18 13:42:06 -07002025 if (sde_plane_enabled(state) && rstate->out_sbuf) {
2026 SDE_DEBUG("plane%d.%d acquire rotator\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08002027 plane->base.id, rstate->sequence_id);
2028
Alan Kwongcdb2f282017-03-18 13:42:06 -07002029 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
2030 (u64) state->fb);
2031 if (!hw_blk) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002032 SDE_ERROR("plane%d no available rotator\n",
2033 plane->base.id);
2034 return -EINVAL;
2035 }
2036
Alan Kwongcdb2f282017-03-18 13:42:06 -07002037 rstate->rot_hw = to_sde_hw_rot(hw_blk);
2038
Alan Kwong4dd64c82017-02-04 18:41:51 -08002039 if (!rstate->rot_hw->ops.commit) {
2040 SDE_ERROR("plane%d invalid rotator ops\n",
2041 plane->base.id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002042 sde_crtc_res_put(cstate,
2043 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002044 rstate->rot_hw = NULL;
2045 return -EINVAL;
2046 }
2047
2048 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002049 } else {
2050 rstate->in_fb = NULL;
2051 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002052 }
2053
2054 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
2055
2056 SDE_DEBUG("plane%d.%d use rotator\n",
2057 plane->base.id, rstate->sequence_id);
2058
2059 sde_plane_rot_calc_cfg(plane, state);
2060
2061 ret = sde_plane_rot_submit_command(plane, state,
2062 SDE_HW_ROT_CMD_VALIDATE);
2063
Clarence Ip4475d582017-04-18 11:36:00 -04002064 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002065
2066 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
2067 rstate->sequence_id);
2068
2069 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04002070 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
2071 rstate->out_fb_modifier[i] = state->fb ?
2072 state->fb->modifier[i] : 0x0;
2073
2074 if (state->fb) {
2075 rstate->out_fb_pixel_format = state->fb->pixel_format;
2076 rstate->out_fb_flags = state->fb->flags;
2077 rstate->out_fb_width = state->fb->width;
2078 rstate->out_fb_height = state->fb->height;
2079 } else {
2080 rstate->out_fb_pixel_format = 0x0;
2081 rstate->out_fb_flags = 0x0;
2082 rstate->out_fb_width = 0;
2083 rstate->out_fb_height = 0;
2084 }
2085
Alan Kwong4dd64c82017-02-04 18:41:51 -08002086 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002087 rstate->out_src_x = state->src_x;
2088 rstate->out_src_y = state->src_y;
2089 rstate->out_src_w = state->src_w;
2090 rstate->out_src_h = state->src_h;
2091
2092 rstate->out_fb_format = NULL;
2093 rstate->out_sbuf = false;
2094 rstate->out_fb = state->fb;
2095 }
2096
2097 return ret;
2098}
2099
2100/**
2101 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2102 * @plane: Pointer to drm plane
2103 * @old_state: Pointer to previous state
2104 * return: none
2105 */
2106static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2107 struct drm_plane_state *old_state)
2108{
2109 struct drm_plane_state *state;
2110 struct sde_plane_state *pstate;
2111 struct sde_plane_rot_state *rstate;
2112
2113 if (!plane || !plane->state) {
2114 SDE_ERROR("invalid plane/state\n");
2115 return;
2116 }
2117
2118 state = plane->state;
2119 pstate = to_sde_plane_state(state);
2120 rstate = &pstate->rot;
2121
2122 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2123 rstate->sequence_id,
2124 !!rstate->out_sbuf, !!rstate->rot_hw,
2125 sde_plane_crtc_enabled(plane->state));
2126
2127 if (!sde_plane_crtc_enabled(state))
2128 return;
2129
2130 if (!rstate->out_sbuf || !rstate->rot_hw)
2131 return;
2132
2133 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
2134}
2135
2136/**
Clarence Ipddbf7752017-05-21 18:07:30 -04002137 * sde_plane_rot_flush - perform final flush related rotator options
2138 * @plane: Pointer to drm plane
2139 * @pstate: Pointer to sde plane state
2140 */
2141static void sde_plane_rot_flush(struct drm_plane *plane,
2142 struct sde_plane_state *pstate)
2143{
2144 if (!plane || !pstate || !pstate->rot.rot_hw ||
2145 !pstate->rot.rot_hw->ops.commit)
2146 return;
2147
2148 pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
2149 &pstate->rot.rot_cmd,
2150 SDE_HW_ROT_CMD_START);
2151}
2152
2153/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002154 * sde_plane_rot_destroy_state - destroy state for rotator stage
2155 * @plane: Pointer to drm plane
2156 * @state: Pointer to state to be destroyed
2157 * return: none
2158 */
2159static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2160 struct drm_plane_state *state)
2161{
2162 struct sde_plane_state *pstate = to_sde_plane_state(state);
2163 struct sde_plane_rot_state *rstate = &pstate->rot;
2164
2165 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2166 rstate->sequence_id,
2167 !!rstate->out_sbuf, !!rstate->rot_hw,
2168 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002169}
2170
2171/**
2172 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2173 * @plane: Pointer to drm plane
2174 * @new_state: Pointer to duplicated state
2175 * return: 0 if success; error code otherwise
2176 */
2177static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2178 struct drm_plane_state *new_state)
2179{
2180 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2181 struct sde_plane_rot_state *rstate = &pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002182 struct drm_crtc_state *cstate;
2183 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002184
2185 rstate->sequence_id++;
2186
2187 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2188 rstate->sequence_id,
2189 !!rstate->out_sbuf, !!rstate->rot_hw);
2190
Alan Kwongcdb2f282017-03-18 13:42:06 -07002191 cstate = _sde_plane_get_crtc_state(new_state);
2192 if (IS_ERR(cstate)) {
2193 ret = PTR_ERR(cstate);
2194 SDE_ERROR("invalid crtc state %d\n", ret);
2195 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002196 }
2197
Alan Kwongcdb2f282017-03-18 13:42:06 -07002198 if (rstate->rot_hw && cstate)
2199 sde_crtc_res_get(cstate, SDE_HW_BLK_ROT, (u64) rstate->in_fb);
2200 else if (rstate->rot_hw && !cstate)
2201 SDE_ERROR("plane%d.%d zombie rotator hw\n",
2202 plane->base.id, rstate->sequence_id);
2203
Alan Kwong4dd64c82017-02-04 18:41:51 -08002204 rstate->out_fb = NULL;
2205 rstate->out_fbo = NULL;
2206
2207 return 0;
2208}
2209
2210/**
2211 * sde_plane_rot_install_caps - install plane rotator capabilities
2212 * @plane: Pointer to drm plane
2213 * return: none
2214 */
2215static void sde_plane_rot_install_caps(struct drm_plane *plane)
2216{
2217 struct sde_plane *psde = to_sde_plane(plane);
2218 const struct sde_format_extended *format_list;
2219 struct sde_kms_info *info;
2220 struct sde_hw_rot *rot_hw;
2221 const char *downscale_caps;
2222
2223 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2224 !psde->catalog->rot_count)
2225 return;
2226
2227 if (psde->blob_rot_caps)
2228 return;
2229
2230 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2231 if (!info)
2232 return;
2233
2234 rot_hw = sde_hw_rot_get(NULL);
2235 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2236 !rot_hw->ops.get_downscale_caps) {
2237 SDE_ERROR("invalid rotator hw\n");
2238 goto error_rot;
2239 }
2240
2241 sde_kms_info_reset(info);
2242
2243 format_list = rot_hw->ops.get_format_caps(rot_hw);
2244 if (format_list) {
2245 sde_kms_info_start(info, "pixel_formats");
2246 while (format_list->fourcc_format) {
2247 sde_kms_info_append_format(info,
2248 format_list->fourcc_format,
2249 format_list->modifier);
2250 ++format_list;
2251 }
2252 sde_kms_info_stop(info);
2253 }
2254
2255 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2256 if (downscale_caps) {
2257 sde_kms_info_start(info, "downscale_ratios");
2258 sde_kms_info_append(info, downscale_caps);
2259 sde_kms_info_stop(info);
2260 }
2261
2262 if (rot_hw->ops.get_cache_size)
2263 sde_kms_info_add_keyint(info, "cache_size",
2264 rot_hw->ops.get_cache_size(rot_hw));
2265
Alan Kwong1a915802017-03-31 12:55:46 -07002266 if (rot_hw->ops.get_maxlinewidth)
2267 sde_kms_info_add_keyint(info, "max_linewidth",
2268 rot_hw->ops.get_maxlinewidth(rot_hw));
2269
Alan Kwong4dd64c82017-02-04 18:41:51 -08002270 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
2271 info->data, info->len, PLANE_PROP_ROT_CAPS_V1);
2272
2273 sde_hw_rot_put(rot_hw);
2274error_rot:
2275 kfree(info);
2276}
2277
2278/**
2279 * sde_plane_rot_install_properties - install plane rotator properties
2280 * @plane: Pointer to drm plane
2281 * @catalog: Pointer to mdss configuration
2282 * return: none
2283 */
2284static void sde_plane_rot_install_properties(struct drm_plane *plane,
2285 struct sde_mdss_cfg *catalog)
2286{
2287 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002288 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2289 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002290
2291 if (!plane || !psde) {
2292 SDE_ERROR("invalid plane\n");
2293 return;
2294 } else if (!catalog) {
2295 SDE_ERROR("invalid catalog\n");
2296 return;
2297 }
2298
2299 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2300 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2301 DRM_ROTATE_180 | DRM_ROTATE_270;
2302
2303 msm_property_install_rotation(&psde->property_info,
2304 supported_rotations, PLANE_PROP_ROTATION);
2305
2306 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2307 return;
2308
2309 msm_property_install_range(&psde->property_info, "rot_dst_x",
2310 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2311 msm_property_install_range(&psde->property_info, "rot_dst_y",
2312 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2313 msm_property_install_range(&psde->property_info, "rot_dst_w",
2314 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2315 msm_property_install_range(&psde->property_info, "rot_dst_h",
2316 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2317 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2318 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2319}
2320
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002321void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002322{
Clarence Ipcb410d42016-06-26 22:52:33 -04002323 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002324
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002325 if (!drm_state)
2326 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002327
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002328 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002329
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002330 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2331 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002332}
2333
2334int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2335{
2336 struct sde_plane_state *pstate[R_MAX];
2337 const struct drm_plane_state *drm_state[R_MAX];
2338 struct sde_rect src[R_MAX], dst[R_MAX];
2339 struct sde_plane *sde_plane[R_MAX];
2340 const struct sde_format *fmt[R_MAX];
2341 bool q16_data = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002342 int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
2343 bool parallel_fetch_qualified = true;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002344
2345 for (i = 0; i < R_MAX; i++) {
2346 const struct msm_format *msm_fmt;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002347 int width_threshold;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002348
2349 drm_state[i] = i ? plane->r1 : plane->r0;
2350 pstate[i] = to_sde_plane_state(drm_state[i]);
2351 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2352
2353 if (pstate[i] == NULL) {
2354 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2355 drm_state[i]->plane->base.id);
2356 return -EINVAL;
2357 }
2358
2359 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2360 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2361 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2362 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2363 drm_state[i]->crtc_h, !q16_data);
2364
2365 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2366 SDE_ERROR_PLANE(sde_plane[i],
2367 "scaling is not supported in multirect mode\n");
2368 return -EINVAL;
2369 }
2370
2371 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2372 fmt[i] = to_sde_format(msm_fmt);
2373 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2374 SDE_ERROR_PLANE(sde_plane[i],
2375 "Unsupported format for multirect mode\n");
2376 return -EINVAL;
2377 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002378
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002379 /**
2380 * SSPP PD_MEM is split half - one for each RECT.
2381 * Tiled formats need 5 lines of buffering while fetching
2382 * whereas linear formats need only 2 lines.
2383 * So we cannot support more than half of the supported SSPP
2384 * width for tiled formats.
2385 */
2386 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
2387 if (SDE_FORMAT_IS_UBWC(fmt[i]))
2388 width_threshold /= 2;
2389
2390 if (parallel_fetch_qualified && src[i].w > width_threshold)
2391 parallel_fetch_qualified = false;
2392
2393 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002394
2395 /* Validate RECT's and set the mode */
2396
2397 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002398 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002399 if (dst[R0].x <= dst[R1].x) {
2400 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2401 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2402 } else {
2403 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2404 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2405 }
2406
2407 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2408 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2409 goto done;
2410 }
2411
2412 /* TIME_MX Mode */
2413 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
2414 buffer_lines = 2 * fmt[R0]->tile_height;
2415
2416 if (dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) {
2417 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2418 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2419 } else if (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines) {
2420 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2421 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2422 } else {
2423 SDE_ERROR(
2424 "No multirect mode possible for the planes (%d - %d)\n",
2425 drm_state[R0]->plane->base.id,
2426 drm_state[R1]->plane->base.id);
2427 return -EINVAL;
2428 }
2429
2430 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2431 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2432done:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002433 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2434 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2435 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2436 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002437 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002438}
2439
Alan Kwong4dd64c82017-02-04 18:41:51 -08002440/**
2441 * sde_plane_get_ctl_flush - get control flush for the given plane
2442 * @plane: Pointer to drm plane structure
2443 * @ctl: Pointer to hardware control driver
2444 * @flush: Pointer to flush control word
2445 */
2446void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
2447 u32 *flush)
2448{
2449 struct sde_plane_state *pstate;
2450 struct sde_plane_rot_state *rstate;
2451 u32 bitmask;
2452
2453 if (!plane || !flush) {
2454 SDE_ERROR("invalid parameters\n");
2455 return;
2456 }
2457
2458 pstate = to_sde_plane_state(plane->state);
2459 rstate = &pstate->rot;
2460
2461 bitmask = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
2462
2463 if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
2464 ctl->ops.get_bitmask_rot)
2465 ctl->ops.get_bitmask_rot(ctl, &bitmask, rstate->rot_hw->idx);
2466
2467 *flush = bitmask;
2468}
2469
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002470static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002471 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002472{
2473 struct drm_framebuffer *fb = new_state->fb;
2474 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002475 struct sde_plane_rot_state *new_rstate;
2476 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002477
2478 if (!new_state->fb)
2479 return 0;
2480
Clarence Ip13a8cf42016-09-29 17:27:47 -04002481 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002482
2483 ret = sde_plane_rot_prepare_fb(plane, new_state);
2484 if (ret) {
2485 SDE_ERROR("failed to prepare rot framebuffer\n");
2486 return ret;
2487 }
2488
2489 new_rstate = &to_sde_plane_state(new_state)->rot;
2490
2491 ret = msm_framebuffer_prepare(new_rstate->out_fb, new_rstate->mmu_id);
2492 if (ret) {
2493 SDE_ERROR("failed to prepare framebuffer\n");
2494 return ret;
2495 }
2496
2497 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002498}
2499
2500static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002501 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002502{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002503 struct sde_plane *psde = to_sde_plane(plane);
2504 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002505
Alan Kwong4dd64c82017-02-04 18:41:51 -08002506 if (!old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002507 return;
2508
Alan Kwong4dd64c82017-02-04 18:41:51 -08002509 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2510
2511 old_rstate = &to_sde_plane_state(old_state)->rot;
2512
2513 msm_framebuffer_cleanup(old_rstate->out_fb, old_rstate->mmu_id);
2514
2515 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002516}
2517
Alan Kwong4dd64c82017-02-04 18:41:51 -08002518static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002519 struct drm_plane_state *state,
2520 struct drm_plane_state *old_state)
2521{
2522 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002523 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002524 struct sde_plane_rot_state *rstate = &pstate->rot;
2525 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2526 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002527
Dhaval Patel47302cf2016-08-18 15:04:28 -07002528 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002529 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002530 return;
2531
Clarence Ip282dad62016-09-27 17:07:35 -04002532 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2533 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002534 SDE_DEBUG_PLANE(psde,
2535 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002536 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002537 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002538 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002539 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002540 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2541 pstate->multirect_mode != old_pstate->multirect_mode) {
2542 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2543 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002544 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2545 rstate->out_src_h != old_rstate->out_src_h ||
2546 rstate->out_src_x != old_rstate->out_src_x ||
2547 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002548 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002549 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002550 } else if (state->crtc_w != old_state->crtc_w ||
2551 state->crtc_h != old_state->crtc_h ||
2552 state->crtc_x != old_state->crtc_x ||
2553 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002554 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002555 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002556 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2557 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2558 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2559 pstate->excl_rect.y != old_pstate->excl_rect.y) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07002560 SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002561 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002562 }
2563
Alan Kwong4dd64c82017-02-04 18:41:51 -08002564 fb = rstate->out_fb;
2565 old_fb = old_rstate->out_fb;
2566
2567 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002568 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002569 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002570 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002571 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002572 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002573 uint64_t *new_mods = fb->modifier;
2574 uint64_t *old_mods = old_fb->modifier;
2575 uint32_t *new_pitches = fb->pitches;
2576 uint32_t *old_pitches = old_fb->pitches;
2577 uint32_t *new_offset = fb->offsets;
2578 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002579 int i;
2580
Alan Kwong4dd64c82017-02-04 18:41:51 -08002581 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002582 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002583 SDE_DEBUG_PLANE(psde,
2584 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002585 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002586 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002587 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2588 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002589 break;
2590 }
2591 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002592 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002593 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002594 SDE_DEBUG_PLANE(psde,
2595 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002596 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002597 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002598 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002599 break;
2600 }
2601 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002602 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002603 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002604 SDE_DEBUG_PLANE(psde,
2605 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002606 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002607 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002608 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2609 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002610 break;
2611 }
2612 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002613 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002614}
2615
Alan Kwong4dd64c82017-02-04 18:41:51 -08002616static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002617 struct drm_plane_state *state)
2618{
Clarence Ipdedbba92016-09-27 17:43:10 -04002619 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04002620 struct sde_plane *psde;
2621 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002622 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002623 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002624 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04002625 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002626 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
2627 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04002628
2629 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002630 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2631 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04002632 ret = -EINVAL;
2633 goto exit;
2634 }
2635
2636 psde = to_sde_plane(plane);
2637 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002638 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04002639
2640 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002641 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002642 ret = -EINVAL;
2643 goto exit;
2644 }
2645
Clarence Ipdedbba92016-09-27 17:43:10 -04002646 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
2647 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04002648
2649 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002650 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2651 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002652 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
2653 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04002654
Dhaval Patel47302cf2016-08-18 15:04:28 -07002655 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
2656 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04002657
Dhaval Patel47302cf2016-08-18 15:04:28 -07002658 max_upscale = psde->pipe_sblk->maxupscale;
2659 max_downscale = psde->pipe_sblk->maxdwnscale;
2660 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04002661
Clarence Ip13a8cf42016-09-29 17:27:47 -04002662 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002663 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002664
Dhaval Patel47302cf2016-08-18 15:04:28 -07002665 if (!sde_plane_enabled(state))
2666 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04002667
Alan Kwong4dd64c82017-02-04 18:41:51 -08002668 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002669 "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 -08002670 plane->base.id, rstate->sequence_id,
2671 rstate->out_rotation,
2672 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002673 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002674 rstate->out_fb_modifier[0],
2675 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2676 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2677 state->crtc_w, state->crtc_h,
2678 state->crtc_x, state->crtc_y);
2679
Dhaval Patel47302cf2016-08-18 15:04:28 -07002680 fmt = to_sde_format(msm_framebuffer_format(state->fb));
2681
2682 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
2683
2684 if (SDE_FORMAT_IS_YUV(fmt) &&
2685 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04002686 !(psde->features & (BIT(SDE_SSPP_CSC)
2687 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002688 SDE_ERROR_PLANE(psde,
2689 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07002690 ret = -EINVAL;
2691
2692 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002693 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
2694 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07002695 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08002696 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
2697 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002698 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002699 src.x, src.y, src.w, src.h);
2700 ret = -E2BIG;
2701
2702 /* valid yuv image */
2703 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
2704 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002705 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002706 src.x, src.y, src.w, src.h);
2707 ret = -EINVAL;
2708
2709 /* min dst support */
2710 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002711 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002712 dst.x, dst.y, dst.w, dst.h);
2713 ret = -EINVAL;
2714
2715 /* decimation validation */
2716 } else if (deci_w || deci_h) {
2717 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
2718 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002719 SDE_ERROR_PLANE(psde,
2720 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002721 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002722 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002723 SDE_ERROR_PLANE(psde,
2724 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002725 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002726 }
2727
Dhaval Patel47302cf2016-08-18 15:04:28 -07002728 } else if (!(psde->features & SDE_SSPP_SCALER) &&
2729 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002730 SDE_ERROR_PLANE(psde,
2731 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002732 src.w, src.h, dst.w, dst.h);
2733 ret = -EINVAL;
2734
2735 /* check decimated source width */
2736 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002737 SDE_ERROR_PLANE(psde,
2738 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002739 src.w, src_deci_w, max_linewidth);
2740 ret = -E2BIG;
2741
2742 /* check max scaler capability */
2743 } else if (((src_deci_w * max_upscale) < dst.w) ||
2744 ((src_deci_h * max_upscale) < dst.h) ||
2745 ((dst.w * max_downscale) < src_deci_w) ||
2746 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002747 SDE_ERROR_PLANE(psde,
2748 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002749 src_deci_w, src_deci_h, dst.w, dst.h);
2750 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002751 }
2752
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002753 /* check excl rect configs */
2754 if (pstate->excl_rect.w && pstate->excl_rect.h) {
2755 struct sde_rect intersect;
2756
2757 /*
2758 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002759 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002760 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05002761 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002762 if (intersect.w != pstate->excl_rect.w ||
2763 intersect.h != pstate->excl_rect.h ||
2764 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002765 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07002766 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002767 pstate->excl_rect.x, pstate->excl_rect.y,
2768 pstate->excl_rect.w, pstate->excl_rect.h,
2769 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07002770 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002771 ret = -EINVAL;
2772 }
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07002773 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
2774 pstate->excl_rect.x, pstate->excl_rect.y,
2775 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002776 }
2777
Dhaval Patel47302cf2016-08-18 15:04:28 -07002778modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002779 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002780 _sde_plane_sspp_atomic_check_mode_changed(psde,
2781 state, plane->state);
2782exit:
2783 return ret;
2784}
2785
2786static int sde_plane_atomic_check(struct drm_plane *plane,
2787 struct drm_plane_state *state)
2788{
2789 int ret = 0;
2790 struct sde_plane *psde;
2791 struct sde_plane_state *pstate;
2792
2793 if (!plane || !state) {
2794 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2795 plane != 0, state != 0);
2796 ret = -EINVAL;
2797 goto exit;
2798 }
2799
2800 psde = to_sde_plane(plane);
2801 pstate = to_sde_plane_state(state);
2802
2803 SDE_DEBUG_PLANE(psde, "\n");
2804
2805 ret = sde_plane_rot_atomic_check(plane, state);
2806 if (ret)
2807 goto exit;
2808
2809 ret = sde_plane_sspp_atomic_check(plane, state);
2810
Clarence Ipdbde9832016-06-26 09:48:36 -04002811exit:
2812 return ret;
2813}
2814
Clarence Ipcae1bb62016-07-07 12:07:13 -04002815/**
2816 * sde_plane_flush - final plane operations before commit flush
2817 * @plane: Pointer to drm plane structure
2818 */
2819void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04002820{
Clarence Ipcae1bb62016-07-07 12:07:13 -04002821 struct sde_plane *psde;
Clarence Ipddbf7752017-05-21 18:07:30 -04002822 struct sde_plane_state *pstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -04002823
Clarence Ipddbf7752017-05-21 18:07:30 -04002824 if (!plane || !plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002825 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04002826 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002827 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04002828
2829 psde = to_sde_plane(plane);
Clarence Ipddbf7752017-05-21 18:07:30 -04002830 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002831
2832 /*
2833 * These updates have to be done immediately before the plane flush
2834 * timing, and may not be moved to the atomic_update/mode_set functions.
2835 */
2836 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05002837 /* force white frame with 100% alpha pipe output on error */
2838 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002839 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
2840 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04002841 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002842 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
2843 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
2844
Clarence Ip56902792017-03-17 15:22:07 -04002845 /* force black color fill during suspend */
2846 if (msm_is_suspend_state(plane->dev) && suspend_blank)
2847 _sde_plane_color_fill(psde, 0x0, 0x0);
2848
Clarence Ipcae1bb62016-07-07 12:07:13 -04002849 /* flag h/w flush complete */
2850 if (plane->state)
Clarence Ipddbf7752017-05-21 18:07:30 -04002851 pstate->pending = false;
2852
2853 /* signal inline rotator start */
2854 sde_plane_rot_flush(plane, pstate);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002855}
2856
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002857static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
2858 struct drm_plane_state *old_state)
2859{
2860 uint32_t nplanes, src_flags;
2861 struct sde_plane *psde;
2862 struct drm_plane_state *state;
2863 struct sde_plane_state *pstate;
2864 struct sde_plane_state *old_pstate;
2865 struct sde_plane_rot_state *rstate;
2866 const struct sde_format *fmt;
2867 struct drm_crtc *crtc;
2868 struct drm_framebuffer *fb;
2869 struct sde_rect src, dst;
2870 const struct sde_rect *crtc_roi;
2871 bool q16_data = true;
2872 int idx;
2873
2874 if (!plane) {
2875 SDE_ERROR("invalid plane\n");
2876 return -EINVAL;
2877 } else if (!plane->state) {
2878 SDE_ERROR("invalid plane state\n");
2879 return -EINVAL;
2880 } else if (!old_state) {
2881 SDE_ERROR("invalid old state\n");
2882 return -EINVAL;
2883 }
2884
2885 psde = to_sde_plane(plane);
2886 state = plane->state;
2887
2888 pstate = to_sde_plane_state(state);
2889 rstate = &pstate->rot;
2890
2891 old_pstate = to_sde_plane_state(old_state);
2892
2893 crtc = state->crtc;
2894 fb = rstate->out_fb;
2895 if (!crtc || !fb) {
2896 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
2897 crtc != 0, fb != 0);
2898 return -EINVAL;
2899 }
2900 fmt = to_sde_format(msm_framebuffer_format(fb));
2901 nplanes = fmt->num_planes;
2902
2903 SDE_DEBUG(
2904 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
2905 plane->base.id, rstate->sequence_id,
2906 rstate->out_fb_width, rstate->out_fb_height,
2907 (char *) &rstate->out_fb_pixel_format,
2908 rstate->out_fb_modifier[0],
2909 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2910 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2911 rstate->out_rotation,
2912 state->crtc_w, state->crtc_h,
2913 state->crtc_x, state->crtc_y);
2914
2915 /* force reprogramming of all the parameters, if the flag is set */
2916 if (psde->revalidate) {
2917 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
2918 plane->base.id);
2919 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2920 psde->revalidate = false;
2921 }
2922
2923 /* determine what needs to be refreshed */
2924 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
2925 switch (idx) {
2926 case PLANE_PROP_SCALER_V1:
2927 case PLANE_PROP_SCALER_V2:
2928 case PLANE_PROP_H_DECIMATE:
2929 case PLANE_PROP_V_DECIMATE:
2930 case PLANE_PROP_SRC_CONFIG:
2931 case PLANE_PROP_ZPOS:
2932 case PLANE_PROP_EXCL_RECT_V1:
2933 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2934 break;
2935 case PLANE_PROP_CSC_V1:
2936 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2937 break;
2938 case PLANE_PROP_COLOR_FILL:
2939 /* potentially need to refresh everything */
2940 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2941 break;
2942 case PLANE_PROP_ROTATION:
2943 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2944 break;
2945 case PLANE_PROP_INFO:
2946 case PLANE_PROP_ALPHA:
2947 case PLANE_PROP_INPUT_FENCE:
2948 case PLANE_PROP_BLEND_OP:
2949 /* no special action required */
2950 break;
Alan Kwong2349d742017-04-20 08:27:30 -07002951 case PLANE_PROP_PREFILL_SIZE:
2952 case PLANE_PROP_PREFILL_TIME:
2953 pstate->dirty |= SDE_PLANE_DIRTY_PERF;
2954 break;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002955 case PLANE_PROP_ROT_DST_X:
2956 case PLANE_PROP_ROT_DST_Y:
2957 case PLANE_PROP_ROT_DST_W:
2958 case PLANE_PROP_ROT_DST_H:
2959 /* handled by rotator atomic update */
2960 break;
2961 default:
2962 /* unknown property, refresh everything */
2963 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
2964 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
2965 break;
2966 }
2967 }
2968
2969 /**
2970 * since plane_atomic_check is invoked before crtc_atomic_check
2971 * in the commit sequence, all the parameters for updating the
2972 * plane dirty flag will not be available during
2973 * plane_atomic_check as some features params are updated
2974 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
2975 * before sspp update.
2976 */
2977 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
2978 old_state);
2979
2980 /* re-program the output rects always in the case of partial update */
2981 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
2982 if (!sde_kms_rect_is_null(crtc_roi))
2983 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2984
2985 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
2986 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
2987
2988 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
2989
2990 /* early out if nothing dirty */
2991 if (!pstate->dirty)
2992 return 0;
2993 pstate->pending = true;
2994
2995 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
2996 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
2997
2998 /* update roi config */
2999 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
3000 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3001 rstate->out_src_w, rstate->out_src_h, q16_data);
3002 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
3003 state->crtc_w, state->crtc_h, !q16_data);
3004
3005 SDE_DEBUG_PLANE(psde,
3006 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
3007 fb->base.id, src.x, src.y, src.w, src.h,
3008 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
3009 (char *)&fmt->base.pixel_format,
3010 SDE_FORMAT_IS_UBWC(fmt));
3011
3012 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
3013 BIT(SDE_DRM_DEINTERLACE)) {
3014 SDE_DEBUG_PLANE(psde, "deinterlace\n");
3015 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
3016 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
3017 src.h /= 2;
3018 src.y = DIV_ROUND_UP(src.y, 2);
3019 src.y &= ~0x1;
3020 }
3021
3022 /*
3023 * adjust layer mixer position of the sspp in the presence
3024 * of a partial update to the active lm origin
3025 */
3026 dst.x -= crtc_roi->x;
3027 dst.y -= crtc_roi->y;
3028
3029 psde->pipe_cfg.src_rect = src;
3030 psde->pipe_cfg.dst_rect = dst;
3031
3032 _sde_plane_setup_scaler(psde, fmt, pstate);
3033
3034 /* check for color fill */
3035 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
3036 PLANE_PROP_COLOR_FILL);
3037 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
3038 /* skip remaining processing on color fill */
3039 pstate->dirty = 0x0;
3040 } else if (psde->pipe_hw->ops.setup_rects) {
3041 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
3042 &psde->pipe_cfg,
3043 pstate->multirect_index);
3044 }
3045
3046 if (psde->pipe_hw->ops.setup_pe)
3047 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
3048 &psde->pixel_ext);
3049
3050 /**
3051 * when programmed in multirect mode, scalar block will be
3052 * bypassed. Still we need to update alpha and bitwidth
3053 * ONLY for RECT0
3054 */
3055 if (psde->pipe_hw->ops.setup_scaler &&
3056 pstate->multirect_index != SDE_SSPP_RECT_1)
3057 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
3058 &psde->pipe_cfg, &psde->pixel_ext,
3059 psde->scaler3_cfg);
3060
3061 /* update excl rect */
3062 if (psde->pipe_hw->ops.setup_excl_rect)
3063 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
3064 &pstate->excl_rect,
3065 pstate->multirect_index);
3066
3067 if (psde->pipe_hw->ops.setup_multirect)
3068 psde->pipe_hw->ops.setup_multirect(
3069 psde->pipe_hw,
3070 pstate->multirect_index,
3071 pstate->multirect_mode);
3072 }
3073
3074 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
3075 psde->pipe_hw->ops.setup_format) {
3076 src_flags = 0x0;
3077 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
3078 if (rstate->out_rotation & DRM_REFLECT_X)
3079 src_flags |= SDE_SSPP_FLIP_LR;
3080 if (rstate->out_rotation & DRM_REFLECT_Y)
3081 src_flags |= SDE_SSPP_FLIP_UD;
3082
3083 /* update format */
3084 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
3085 pstate->multirect_index);
3086
3087 if (psde->pipe_hw->ops.setup_sys_cache) {
3088 if (rstate->out_sbuf) {
3089 if (rstate->nplane < 2)
3090 pstate->sc_cfg.op_mode =
3091 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
3092 else if (rstate->out_xpos == 0)
3093 pstate->sc_cfg.op_mode =
3094 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
3095 else
3096 pstate->sc_cfg.op_mode =
3097 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
3098
3099 pstate->sc_cfg.rd_en = true;
3100 pstate->sc_cfg.rd_scid =
3101 rstate->rot_hw->caps->scid;
3102 pstate->sc_cfg.rd_noallocate = true;
3103 pstate->sc_cfg.rd_op_type =
3104 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3105 } else {
3106 pstate->sc_cfg.op_mode =
3107 SDE_PIPE_SC_OP_MODE_OFFLINE;
3108 pstate->sc_cfg.rd_en = false;
3109 pstate->sc_cfg.rd_scid = 0;
3110 pstate->sc_cfg.rd_noallocate = false;
3111 pstate->sc_cfg.rd_op_type =
3112 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3113 }
3114
3115 psde->pipe_hw->ops.setup_sys_cache(
3116 psde->pipe_hw, &pstate->sc_cfg);
3117 }
3118
3119 /* update csc */
3120 if (SDE_FORMAT_IS_YUV(fmt))
3121 _sde_plane_setup_csc(psde);
3122 else
3123 psde->csc_ptr = 0;
3124 }
3125
3126 sde_color_process_plane_setup(plane);
3127
3128 /* update sharpening */
3129 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3130 psde->pipe_hw->ops.setup_sharpening) {
3131 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3132 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3133 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3134 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3135
3136 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3137 &psde->sharp_cfg);
3138 }
3139
3140 _sde_plane_set_qos_lut(plane, fb);
3141 _sde_plane_set_danger_lut(plane, fb);
3142
3143 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3144 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3145 _sde_plane_set_ot_limit(plane, crtc);
Alan Kwong2349d742017-04-20 08:27:30 -07003146 if (pstate->dirty & SDE_PLANE_DIRTY_PERF)
3147 _sde_plane_set_ts_prefill(plane, pstate);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003148 }
3149
Alan Kwonga62eeb82017-04-19 08:57:55 -07003150 _sde_plane_set_qos_remap(plane);
3151
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003152 /* clear dirty */
3153 pstate->dirty = 0x0;
3154
3155 return 0;
3156}
3157
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003158static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003159 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003160{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003161 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003162 struct drm_plane_state *state;
3163 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003164 struct sde_plane_state *old_pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003165
Clarence Ip13a8cf42016-09-29 17:27:47 -04003166 if (!plane) {
3167 SDE_ERROR("invalid plane\n");
3168 return;
3169 } else if (!plane->state) {
3170 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003171 return;
3172 }
3173
Clarence Ip13a8cf42016-09-29 17:27:47 -04003174 psde = to_sde_plane(plane);
3175 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003176 state = plane->state;
3177 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003178 old_pstate = to_sde_plane_state(old_state);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003179
Clarence Ip13a8cf42016-09-29 17:27:47 -04003180 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003181
Alan Kwong4dd64c82017-02-04 18:41:51 -08003182 sde_plane_rot_atomic_update(plane, old_state);
3183
3184 if (!sde_plane_sspp_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04003185 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04003186 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003187 int ret;
3188
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003189 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003190 /* atomic_check should have ensured that this doesn't fail */
3191 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003192 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003193}
3194
Dhaval Patel47302cf2016-08-18 15:04:28 -07003195
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003196/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003197static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003198 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003199{
Clarence Ip5e2a9222016-06-26 22:38:24 -04003200 static const struct drm_prop_enum_list e_blend_op[] = {
3201 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3202 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3203 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3204 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3205 };
3206 static const struct drm_prop_enum_list e_src_config[] = {
3207 {SDE_DRM_DEINTERLACE, "deinterlace"}
3208 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003209 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003210 struct sde_format_extended *virt_format_list = NULL;
Dhaval Patel4e574842016-08-23 15:11:37 -07003211 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003212 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003213 int zpos_max = 255;
3214 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003215 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003216
Clarence Ip13a8cf42016-09-29 17:27:47 -04003217 if (!plane || !psde) {
3218 SDE_ERROR("invalid plane\n");
3219 return;
3220 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3221 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3222 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003223 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003224 } else if (!catalog) {
3225 SDE_ERROR("invalid catalog\n");
3226 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003227 }
3228
Alan Kwong4dd64c82017-02-04 18:41:51 -08003229 psde->catalog = catalog;
3230
Clarence Ipc47a0692016-10-11 10:54:17 -04003231 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003232 if (catalog->mixer_count && catalog->mixer &&
3233 catalog->mixer[0].sblk->maxblendstages) {
3234 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3235 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3236 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3237 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003238 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3239 /* reserve zpos == 0 for primary planes */
3240 zpos_def = drm_plane_index(plane) + 1;
3241 }
3242
3243 msm_property_install_range(&psde->property_info, "zpos",
3244 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003245
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003246 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003247 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003248
Dhaval Patel47302cf2016-08-18 15:04:28 -07003249 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003250 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003251 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003252
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003253 if (!master_plane_id) {
3254 if (psde->pipe_sblk->maxhdeciexp) {
3255 msm_property_install_range(&psde->property_info,
3256 "h_decimate", 0x0, 0,
3257 psde->pipe_sblk->maxhdeciexp, 0,
3258 PLANE_PROP_H_DECIMATE);
3259 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003260
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003261 if (psde->pipe_sblk->maxvdeciexp) {
3262 msm_property_install_range(&psde->property_info,
3263 "v_decimate", 0x0, 0,
3264 psde->pipe_sblk->maxvdeciexp, 0,
3265 PLANE_PROP_V_DECIMATE);
3266 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003267
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003268 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
3269 msm_property_install_volatile_range(
3270 &psde->property_info, "scaler_v2",
3271 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3272 msm_property_install_blob(&psde->property_info,
3273 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3274 msm_property_install_blob(&psde->property_info,
3275 "lut_cir", 0,
3276 PLANE_PROP_SCALER_LUT_CIR);
3277 msm_property_install_blob(&psde->property_info,
3278 "lut_sep", 0,
3279 PLANE_PROP_SCALER_LUT_SEP);
3280 } else if (psde->features & SDE_SSPP_SCALER) {
3281 msm_property_install_volatile_range(
3282 &psde->property_info, "scaler_v1", 0x0,
3283 0, ~0, 0, PLANE_PROP_SCALER_V1);
3284 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003285
Dhaval Patel0aee0972017-02-08 19:00:58 -08003286 if (psde->features & BIT(SDE_SSPP_CSC) ||
3287 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003288 msm_property_install_volatile_range(
3289 &psde->property_info, "csc_v1", 0x0,
3290 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003291
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003292 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3293 snprintf(feature_name, sizeof(feature_name), "%s%d",
3294 "SDE_SSPP_HUE_V",
3295 psde->pipe_sblk->hsic_blk.version >> 16);
3296 msm_property_install_range(&psde->property_info,
3297 feature_name, 0, 0, 0xFFFFFFFF, 0,
3298 PLANE_PROP_HUE_ADJUST);
3299 snprintf(feature_name, sizeof(feature_name), "%s%d",
3300 "SDE_SSPP_SATURATION_V",
3301 psde->pipe_sblk->hsic_blk.version >> 16);
3302 msm_property_install_range(&psde->property_info,
3303 feature_name, 0, 0, 0xFFFFFFFF, 0,
3304 PLANE_PROP_SATURATION_ADJUST);
3305 snprintf(feature_name, sizeof(feature_name), "%s%d",
3306 "SDE_SSPP_VALUE_V",
3307 psde->pipe_sblk->hsic_blk.version >> 16);
3308 msm_property_install_range(&psde->property_info,
3309 feature_name, 0, 0, 0xFFFFFFFF, 0,
3310 PLANE_PROP_VALUE_ADJUST);
3311 snprintf(feature_name, sizeof(feature_name), "%s%d",
3312 "SDE_SSPP_CONTRAST_V",
3313 psde->pipe_sblk->hsic_blk.version >> 16);
3314 msm_property_install_range(&psde->property_info,
3315 feature_name, 0, 0, 0xFFFFFFFF, 0,
3316 PLANE_PROP_CONTRAST_ADJUST);
3317 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003318 }
3319
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003320 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3321 msm_property_install_volatile_range(&psde->property_info,
3322 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3323
Alan Kwong4dd64c82017-02-04 18:41:51 -08003324 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003325
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003326 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003327 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003328
Dhaval Patel47302cf2016-08-18 15:04:28 -07003329 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3330 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3331
3332 if (psde->pipe_hw->ops.setup_solidfill)
3333 msm_property_install_range(&psde->property_info, "color_fill",
3334 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3335
Alan Kwong2349d742017-04-20 08:27:30 -07003336 msm_property_install_range(&psde->property_info,
3337 "prefill_size", 0x0, 0, ~0, 0,
3338 PLANE_PROP_PREFILL_SIZE);
3339 msm_property_install_range(&psde->property_info,
3340 "prefill_time", 0x0, 0, ~0, 0,
3341 PLANE_PROP_PREFILL_TIME);
3342
Dhaval Patel4e574842016-08-23 15:11:37 -07003343 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003344 if (!info) {
3345 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003346 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003347 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003348
3349 msm_property_install_blob(&psde->property_info, "capabilities",
3350 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3351 sde_kms_info_reset(info);
3352
Clarence Ipea3d6262016-07-15 16:20:11 -04003353 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003354
3355 if (master_plane_id) {
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003356 int index, array_size;
3357
3358 array_size = ARRAY_SIZE(plane_formats)
3359 + ARRAY_SIZE(rgb_10bit_formats);
3360 virt_format_list = kcalloc(array_size,
3361 sizeof(struct sde_format_extended), GFP_KERNEL);
3362 if (!virt_format_list) {
3363 SDE_ERROR(
3364 "failed to allocate virtual pipe format list\n");
3365 return;
3366 }
3367
3368 index = sde_copy_formats(virt_format_list, array_size,
3369 0, plane_formats, ARRAY_SIZE(plane_formats));
3370 sde_copy_formats(virt_format_list, array_size,
3371 index, rgb_10bit_formats,
3372 ARRAY_SIZE(rgb_10bit_formats));
3373
3374 format_list = virt_format_list;
3375
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003376 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003377 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003378 }
3379
Clarence Ipea3d6262016-07-15 16:20:11 -04003380 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003381 sde_kms_info_start(info, "pixel_formats");
3382 while (format_list->fourcc_format) {
3383 sde_kms_info_append_format(info,
3384 format_list->fourcc_format,
3385 format_list->modifier);
3386 ++format_list;
3387 }
3388 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003389 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003390
3391 sde_kms_info_add_keyint(info, "max_linewidth",
3392 psde->pipe_sblk->maxlinewidth);
3393 sde_kms_info_add_keyint(info, "max_upscale",
3394 psde->pipe_sblk->maxupscale);
3395 sde_kms_info_add_keyint(info, "max_downscale",
3396 psde->pipe_sblk->maxdwnscale);
3397 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3398 psde->pipe_sblk->maxhdeciexp);
3399 sde_kms_info_add_keyint(info, "max_vertical_deci",
3400 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07003401 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
3402 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07003403 msm_property_set_blob(&psde->property_info, &psde->blob_info,
3404 info->data, info->len, PLANE_PROP_INFO);
3405
3406 kfree(info);
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003407 kfree(virt_format_list);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003408
3409 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3410 snprintf(feature_name, sizeof(feature_name), "%s%d",
3411 "SDE_SSPP_SKIN_COLOR_V",
3412 psde->pipe_sblk->memcolor_blk.version >> 16);
3413 msm_property_install_blob(&psde->property_info, feature_name, 0,
3414 PLANE_PROP_SKIN_COLOR);
3415 snprintf(feature_name, sizeof(feature_name), "%s%d",
3416 "SDE_SSPP_SKY_COLOR_V",
3417 psde->pipe_sblk->memcolor_blk.version >> 16);
3418 msm_property_install_blob(&psde->property_info, feature_name, 0,
3419 PLANE_PROP_SKY_COLOR);
3420 snprintf(feature_name, sizeof(feature_name), "%s%d",
3421 "SDE_SSPP_FOLIAGE_COLOR_V",
3422 psde->pipe_sblk->memcolor_blk.version >> 16);
3423 msm_property_install_blob(&psde->property_info, feature_name, 0,
3424 PLANE_PROP_FOLIAGE_COLOR);
3425 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003426}
3427
Clarence Ip5fc00c52016-09-23 15:03:34 -04003428static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
3429{
3430 struct sde_drm_csc_v1 csc_v1;
3431 int i;
3432
3433 if (!psde) {
3434 SDE_ERROR("invalid plane\n");
3435 return;
3436 }
3437
3438 psde->csc_usr_ptr = NULL;
3439 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003440 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003441 return;
3442 }
3443
3444 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003445 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003446 return;
3447 }
3448
Clarence Ipb43d4592016-09-08 14:21:35 -04003449 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04003450 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
3451 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
3452 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
3453 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
3454 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
3455 }
3456 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
3457 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
3458 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
3459 }
3460 psde->csc_usr_ptr = &psde->csc_cfg;
3461}
3462
Clarence Ipb43d4592016-09-08 14:21:35 -04003463static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
3464{
3465 struct sde_drm_scaler_v1 scale_v1;
3466 struct sde_hw_pixel_ext *pe;
3467 int i;
3468
3469 if (!psde) {
3470 SDE_ERROR("invalid plane\n");
3471 return;
3472 }
3473
3474 psde->pixel_ext_usr = false;
3475 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003476 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003477 return;
3478 }
3479
3480 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003481 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003482 return;
3483 }
3484
3485 /* populate from user space */
3486 pe = &(psde->pixel_ext);
3487 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3488 for (i = 0; i < SDE_MAX_PLANES; i++) {
3489 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
3490 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
3491 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
3492 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
3493
3494 pe->horz_filter[i] = scale_v1.horz_filter[i];
3495 pe->vert_filter[i] = scale_v1.vert_filter[i];
3496 }
3497 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003498 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
3499 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
3500 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
3501 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
3502 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003503
abeykun41060122016-11-28 13:02:01 -05003504 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
3505 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
3506 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
3507 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
3508 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003509 }
abeykun41060122016-11-28 13:02:01 -05003510
Clarence Ipb43d4592016-09-08 14:21:35 -04003511 psde->pixel_ext_usr = true;
3512
Clarence Ip13a8cf42016-09-29 17:27:47 -04003513 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003514}
3515
abeykun48f407a2016-08-25 12:06:44 -04003516static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
3517 struct sde_plane_state *pstate, void *usr)
3518{
3519 struct sde_drm_scaler_v2 scale_v2;
3520 struct sde_hw_pixel_ext *pe;
3521 int i;
3522 struct sde_hw_scaler3_cfg *cfg;
3523
3524 if (!psde) {
3525 SDE_ERROR("invalid plane\n");
3526 return;
3527 }
3528
3529 cfg = psde->scaler3_cfg;
3530 psde->pixel_ext_usr = false;
3531 if (!usr) {
3532 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3533 return;
3534 }
3535
3536 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
3537 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
3538 return;
3539 }
3540
3541 /* populate from user space */
3542 pe = &(psde->pixel_ext);
3543 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3544 cfg->enable = scale_v2.enable;
3545 cfg->dir_en = scale_v2.dir_en;
3546 for (i = 0; i < SDE_MAX_PLANES; i++) {
3547 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
3548 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
3549 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
3550 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
3551
3552 cfg->preload_x[i] = scale_v2.preload_x[i];
3553 cfg->preload_y[i] = scale_v2.preload_y[i];
3554 cfg->src_width[i] = scale_v2.src_width[i];
3555 cfg->src_height[i] = scale_v2.src_height[i];
3556 }
3557 cfg->dst_width = scale_v2.dst_width;
3558 cfg->dst_height = scale_v2.dst_height;
3559
3560 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
3561 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
3562 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
3563 cfg->blend_cfg = scale_v2.blend_cfg;
3564
3565 cfg->lut_flag = scale_v2.lut_flag;
3566 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
3567 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
3568 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
3569 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
3570 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
3571
3572 cfg->de.enable = scale_v2.de.enable;
3573 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
3574 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
3575 cfg->de.clip = scale_v2.de.clip;
3576 cfg->de.limit = scale_v2.de.limit;
3577 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
3578 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
3579 cfg->de.thr_low = scale_v2.de.thr_low;
3580 cfg->de.thr_high = scale_v2.de.thr_high;
3581 cfg->de.prec_shift = scale_v2.de.prec_shift;
3582 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
3583 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
3584 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
3585 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
3586 }
3587 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003588 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
3589 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
3590 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
3591 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
3592 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04003593
abeykun41060122016-11-28 13:02:01 -05003594 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
3595 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
3596 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
3597 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
3598 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04003599 }
3600 psde->pixel_ext_usr = true;
3601
3602 SDE_DEBUG_PLANE(psde, "user property data copied\n");
3603}
3604
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003605static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
3606 struct sde_plane_state *pstate, void *usr_ptr)
3607{
3608 struct drm_clip_rect excl_rect_v1;
3609
3610 if (!psde) {
3611 SDE_ERROR("invalid plane\n");
3612 return;
3613 }
3614
3615 if (!usr_ptr) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003616 SDE_DEBUG_PLANE(psde, "invalid excl_rect user data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003617 return;
3618 }
3619
3620 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003621 SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003622 return;
3623 }
3624
3625 /* populate from user space */
3626 pstate->excl_rect.x = excl_rect_v1.x1;
3627 pstate->excl_rect.y = excl_rect_v1.y1;
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003628 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
3629 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
3630
3631 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3632 pstate->excl_rect.x, pstate->excl_rect.y,
3633 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003634}
3635
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003636static int sde_plane_atomic_set_property(struct drm_plane *plane,
3637 struct drm_plane_state *state, struct drm_property *property,
3638 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 Ipe78efb72016-06-24 18:35:21 -04003642 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003643
Clarence Ip13a8cf42016-09-29 17:27:47 -04003644 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003645
3646 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003647 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003648 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003649 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003650 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04003651 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003652 ret = msm_property_atomic_set(&psde->property_info,
3653 pstate->property_values, pstate->property_blobs,
3654 property, val);
3655 if (!ret) {
3656 idx = msm_property_index(&psde->property_info,
3657 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003658 switch (idx) {
3659 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04003660 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003661 break;
3662 case PLANE_PROP_CSC_V1:
3663 _sde_plane_set_csc_v1(psde, (void *)val);
3664 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04003665 case PLANE_PROP_SCALER_V1:
3666 _sde_plane_set_scaler_v1(psde, (void *)val);
3667 break;
abeykun48f407a2016-08-25 12:06:44 -04003668 case PLANE_PROP_SCALER_V2:
3669 _sde_plane_set_scaler_v2(psde, pstate,
3670 (void *)val);
3671 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003672 case PLANE_PROP_EXCL_RECT_V1:
3673 _sde_plane_set_excl_rect_v1(psde, pstate,
3674 (void *)val);
3675 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04003676 default:
3677 /* nothing to do */
3678 break;
3679 }
Clarence Ipe78efb72016-06-24 18:35:21 -04003680 }
3681 }
3682
Alan Kwong4dd64c82017-02-04 18:41:51 -08003683 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
3684 property->name, property->base.id, val, ret);
3685
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003686 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003687}
3688
3689static int sde_plane_set_property(struct drm_plane *plane,
3690 struct drm_property *property, uint64_t val)
3691{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003692 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003693
Clarence Ipae4e60c2016-06-26 22:44:04 -04003694 return sde_plane_atomic_set_property(plane,
3695 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003696}
3697
3698static int sde_plane_atomic_get_property(struct drm_plane *plane,
3699 const struct drm_plane_state *state,
3700 struct drm_property *property, uint64_t *val)
3701{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003702 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003703 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04003704 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003705
Clarence Ipaa0faf42016-05-30 12:07:48 -04003706 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003707 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003708 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003709 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003710 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003711 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003712 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003713 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003714 ret = msm_property_atomic_get(&psde->property_info,
3715 pstate->property_values, pstate->property_blobs,
3716 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04003717 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003718
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003719 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003720}
3721
3722static void sde_plane_destroy(struct drm_plane *plane)
3723{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003724 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003725
Clarence Ip13a8cf42016-09-29 17:27:47 -04003726 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003727
Clarence Ip13a8cf42016-09-29 17:27:47 -04003728 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04003729 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3730
Dhaval Patel4e574842016-08-23 15:11:37 -07003731 if (psde->blob_info)
3732 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003733 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04003734 mutex_destroy(&psde->lock);
3735
Clarence Ip4ce59322016-06-26 22:27:51 -04003736 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003737
Clarence Ip4ce59322016-06-26 22:27:51 -04003738 /* this will destroy the states as well */
3739 drm_plane_cleanup(plane);
3740
Clarence Ip4c1d9772016-06-26 09:35:38 -04003741 if (psde->pipe_hw)
3742 sde_hw_sspp_destroy(psde->pipe_hw);
3743
Clarence Ip4ce59322016-06-26 22:27:51 -04003744 kfree(psde);
3745 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003746}
3747
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003748static void sde_plane_destroy_state(struct drm_plane *plane,
3749 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003750{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003751 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04003752 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003753
Clarence Ipae4e60c2016-06-26 22:44:04 -04003754 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003755 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3756 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003757 return;
3758 }
3759
Clarence Ipaa0faf42016-05-30 12:07:48 -04003760 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04003761 pstate = to_sde_plane_state(state);
3762
Clarence Ip13a8cf42016-09-29 17:27:47 -04003763 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003764
Alan Kwong4dd64c82017-02-04 18:41:51 -08003765 sde_plane_rot_destroy_state(plane, &pstate->base);
3766
Clarence Ipe78efb72016-06-24 18:35:21 -04003767 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003768 if (state->fb)
3769 drm_framebuffer_unreference(state->fb);
3770
Clarence Ipae4e60c2016-06-26 22:44:04 -04003771 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003772 if (pstate->input_fence)
3773 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003774
Clarence Ipaa0faf42016-05-30 12:07:48 -04003775 /* destroy value helper */
3776 msm_property_destroy_state(&psde->property_info, pstate,
3777 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003778}
3779
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003780static struct drm_plane_state *
3781sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003782{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003783 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003784 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04003785 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04003786 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003787
Clarence Ip13a8cf42016-09-29 17:27:47 -04003788 if (!plane) {
3789 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003790 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003791 } else if (!plane->state) {
3792 SDE_ERROR("invalid plane state\n");
3793 return NULL;
3794 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003795
Clarence Ip730e7192016-06-26 22:45:09 -04003796 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003797 psde = to_sde_plane(plane);
3798 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003799 if (!pstate) {
3800 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003801 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003802 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003803
Clarence Ip13a8cf42016-09-29 17:27:47 -04003804 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003805
3806 /* duplicate value helper */
3807 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
3808 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003809
Clarence Ip17e908b2016-09-29 15:58:00 -04003810 /* clear out any input fence */
3811 pstate->input_fence = 0;
3812 input_fence_default = msm_property_get_default(
3813 &psde->property_info, PLANE_PROP_INPUT_FENCE);
3814 msm_property_set_property(&psde->property_info, pstate->property_values,
3815 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003816
Clarence Ip282dad62016-09-27 17:07:35 -04003817 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04003818 pstate->pending = false;
3819
Alan Kwongcdb2f282017-03-18 13:42:06 -07003820 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
3821
Alan Kwong4dd64c82017-02-04 18:41:51 -08003822 sde_plane_rot_duplicate_state(plane, &pstate->base);
3823
Clarence Ip730e7192016-06-26 22:45:09 -04003824 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003825}
3826
3827static void sde_plane_reset(struct drm_plane *plane)
3828{
Clarence Ipae4e60c2016-06-26 22:44:04 -04003829 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003830 struct sde_plane_state *pstate;
3831
Clarence Ipae4e60c2016-06-26 22:44:04 -04003832 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003833 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003834 return;
3835 }
3836
Clarence Ip730e7192016-06-26 22:45:09 -04003837 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003838 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003839
Clarence Ipae4e60c2016-06-26 22:44:04 -04003840 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04003841 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04003842 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003843 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04003844 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003845
Clarence Ipaa0faf42016-05-30 12:07:48 -04003846 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003847 if (!pstate) {
3848 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003849 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003850 }
Clarence Ip730e7192016-06-26 22:45:09 -04003851
Clarence Ipaa0faf42016-05-30 12:07:48 -04003852 /* reset value helper */
3853 msm_property_reset_state(&psde->property_info, pstate,
3854 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003855
3856 pstate->base.plane = plane;
3857
3858 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003859}
3860
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003861#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04003862static ssize_t _sde_plane_danger_read(struct file *file,
3863 char __user *buff, size_t count, loff_t *ppos)
3864{
3865 struct sde_kms *kms = file->private_data;
3866 struct sde_mdss_cfg *cfg = kms->catalog;
3867 int len = 0;
3868 char buf[40] = {'\0'};
3869
3870 if (!cfg)
3871 return -ENODEV;
3872
3873 if (*ppos)
3874 return 0; /* the end */
3875
3876 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
3877 if (len < 0 || len >= sizeof(buf))
3878 return 0;
3879
3880 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
3881 return -EFAULT;
3882
3883 *ppos += len; /* increase offset */
3884
3885 return len;
3886}
3887
3888static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
3889{
3890 struct drm_plane *plane;
3891
3892 drm_for_each_plane(plane, kms->dev) {
3893 if (plane->fb && plane->state) {
3894 sde_plane_danger_signal_ctrl(plane, enable);
3895 SDE_DEBUG("plane:%d img:%dx%d ",
3896 plane->base.id, plane->fb->width,
3897 plane->fb->height);
3898 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
3899 plane->state->src_x >> 16,
3900 plane->state->src_y >> 16,
3901 plane->state->src_w >> 16,
3902 plane->state->src_h >> 16,
3903 plane->state->crtc_x, plane->state->crtc_y,
3904 plane->state->crtc_w, plane->state->crtc_h);
3905 } else {
3906 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
3907 }
3908 }
3909}
3910
3911static ssize_t _sde_plane_danger_write(struct file *file,
3912 const char __user *user_buf, size_t count, loff_t *ppos)
3913{
3914 struct sde_kms *kms = file->private_data;
3915 struct sde_mdss_cfg *cfg = kms->catalog;
3916 int disable_panic;
3917 char buf[10];
3918
3919 if (!cfg)
3920 return -EFAULT;
3921
3922 if (count >= sizeof(buf))
3923 return -EFAULT;
3924
3925 if (copy_from_user(buf, user_buf, count))
3926 return -EFAULT;
3927
3928 buf[count] = 0; /* end of string */
3929
3930 if (kstrtoint(buf, 0, &disable_panic))
3931 return -EFAULT;
3932
3933 if (disable_panic) {
3934 /* Disable panic signal for all active pipes */
3935 SDE_DEBUG("Disabling danger:\n");
3936 _sde_plane_set_danger_state(kms, false);
3937 kms->has_danger_ctrl = false;
3938 } else {
3939 /* Enable panic signal for all active pipes */
3940 SDE_DEBUG("Enabling danger:\n");
3941 kms->has_danger_ctrl = true;
3942 _sde_plane_set_danger_state(kms, true);
3943 }
3944
3945 return count;
3946}
3947
3948static const struct file_operations sde_plane_danger_enable = {
3949 .open = simple_open,
3950 .read = _sde_plane_danger_read,
3951 .write = _sde_plane_danger_write,
3952};
3953
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003954static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04003955{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003956 struct sde_plane *psde;
3957 struct sde_kms *kms;
3958 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04003959 const struct sde_sspp_sub_blks *sblk = 0;
3960 const struct sde_sspp_cfg *cfg = 0;
3961
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003962 if (!plane || !plane->dev) {
3963 SDE_ERROR("invalid arguments\n");
3964 return -EINVAL;
3965 }
3966
3967 priv = plane->dev->dev_private;
3968 if (!priv || !priv->kms) {
3969 SDE_ERROR("invalid KMS reference\n");
3970 return -EINVAL;
3971 }
3972
3973 kms = to_sde_kms(priv->kms);
3974 psde = to_sde_plane(plane);
3975
Clarence Ip4ce59322016-06-26 22:27:51 -04003976 if (psde && psde->pipe_hw)
3977 cfg = psde->pipe_hw->cap;
3978 if (cfg)
3979 sblk = cfg->sblk;
3980
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003981 if (!sblk)
3982 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04003983
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003984 /* create overall sub-directory for the pipe */
3985 psde->debugfs_root =
3986 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07003987 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04003988
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003989 if (!psde->debugfs_root)
3990 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04003991
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003992 /* don't error check these */
3993 debugfs_create_x32("features", 0644,
3994 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003995
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003996 /* add register dump support */
3997 sde_debugfs_setup_regset32(&psde->debugfs_src,
3998 sblk->src_blk.base + cfg->base,
3999 sblk->src_blk.len,
4000 kms);
4001 sde_debugfs_create_regset32("src_blk", 0444,
4002 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004003
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004004 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
4005 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
4006 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
4007 sblk->scaler_blk.base + cfg->base,
4008 sblk->scaler_blk.len,
4009 kms);
4010 sde_debugfs_create_regset32("scaler_blk", 0444,
4011 psde->debugfs_root,
4012 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07004013 debugfs_create_bool("default_scaling",
4014 0644,
4015 psde->debugfs_root,
4016 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04004017 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004018
4019 if (cfg->features & BIT(SDE_SSPP_CSC) ||
4020 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
4021 sde_debugfs_setup_regset32(&psde->debugfs_csc,
4022 sblk->csc_blk.base + cfg->base,
4023 sblk->csc_blk.len,
4024 kms);
4025 sde_debugfs_create_regset32("csc_blk", 0444,
4026 psde->debugfs_root, &psde->debugfs_csc);
4027 }
4028
4029 debugfs_create_u32("xin_id",
4030 0444,
4031 psde->debugfs_root,
4032 (u32 *) &cfg->xin_id);
4033 debugfs_create_u32("clk_ctrl",
4034 0444,
4035 psde->debugfs_root,
4036 (u32 *) &cfg->clk_ctrl);
4037 debugfs_create_x32("creq_vblank",
4038 0644,
4039 psde->debugfs_root,
4040 (u32 *) &sblk->creq_vblank);
4041 debugfs_create_x32("danger_vblank",
4042 0644,
4043 psde->debugfs_root,
4044 (u32 *) &sblk->danger_vblank);
4045
4046 debugfs_create_file("disable_danger",
4047 0644,
4048 psde->debugfs_root,
4049 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004050 debugfs_create_u32("sbuf_mode",
4051 0644,
4052 psde->debugfs_root, &psde->sbuf_mode);
4053 debugfs_create_u32("sbuf_writeback",
4054 0644,
4055 psde->debugfs_root,
4056 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004057
4058 return 0;
4059}
4060
4061static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4062{
4063 struct sde_plane *psde;
4064
4065 if (!plane)
4066 return;
4067 psde = to_sde_plane(plane);
4068
4069 debugfs_remove_recursive(psde->debugfs_root);
4070}
4071#else
4072static int _sde_plane_init_debugfs(struct drm_plane *plane)
4073{
4074 return 0;
4075}
4076static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4077{
4078}
4079#endif
4080
4081static int sde_plane_late_register(struct drm_plane *plane)
4082{
4083 return _sde_plane_init_debugfs(plane);
4084}
4085
4086static void sde_plane_early_unregister(struct drm_plane *plane)
4087{
4088 _sde_plane_destroy_debugfs(plane);
4089}
4090
4091static const struct drm_plane_funcs sde_plane_funcs = {
4092 .update_plane = drm_atomic_helper_update_plane,
4093 .disable_plane = drm_atomic_helper_disable_plane,
4094 .destroy = sde_plane_destroy,
4095 .set_property = sde_plane_set_property,
4096 .atomic_set_property = sde_plane_atomic_set_property,
4097 .atomic_get_property = sde_plane_atomic_get_property,
4098 .reset = sde_plane_reset,
4099 .atomic_duplicate_state = sde_plane_duplicate_state,
4100 .atomic_destroy_state = sde_plane_destroy_state,
4101 .late_register = sde_plane_late_register,
4102 .early_unregister = sde_plane_early_unregister,
4103};
4104
4105static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
4106 .prepare_fb = sde_plane_prepare_fb,
4107 .cleanup_fb = sde_plane_cleanup_fb,
4108 .atomic_check = sde_plane_atomic_check,
4109 .atomic_update = sde_plane_atomic_update,
4110};
4111
4112enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
4113{
4114 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
4115}
4116
4117bool is_sde_plane_virtual(struct drm_plane *plane)
4118{
4119 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04004120}
4121
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004122/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04004123struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04004124 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004125 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004126{
4127 struct drm_plane *plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004128 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004129 struct sde_format_extended *virt_format_list = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004130 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004131 struct msm_drm_private *priv;
4132 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004133 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04004134 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004135
4136 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004137 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004138 goto exit;
4139 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004140
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004141 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004142 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004143 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004144 goto exit;
4145 }
4146
4147 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004148 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004149 goto exit;
4150 }
4151 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004152
Clarence Ip4c1d9772016-06-26 09:35:38 -04004153 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004154 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004155 goto exit;
4156 }
4157
Clarence Ip4ce59322016-06-26 22:27:51 -04004158 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004159 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4160 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004161 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004162 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004163 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004164 }
4165
Clarence Ip4c1d9772016-06-26 09:35:38 -04004166 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004167 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004168 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04004169 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004170 psde->is_virtual = (master_plane_id != 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004171
Clarence Ip4c1d9772016-06-26 09:35:38 -04004172 /* initialize underlying h/w driver */
4173 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
4174 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004175 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004176 ret = PTR_ERR(psde->pipe_hw);
4177 goto clean_plane;
4178 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004179 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004180 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004181 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004182
4183 /* cache features mask for later */
4184 psde->features = psde->pipe_hw->cap->features;
4185 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004186 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004187 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004188 goto clean_sspp;
4189 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004190
abeykun48f407a2016-08-25 12:06:44 -04004191 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
4192 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
4193 GFP_KERNEL);
4194 if (!psde->scaler3_cfg) {
4195 SDE_ERROR("[%u]failed to allocate scale struct\n",
4196 pipe);
4197 ret = -ENOMEM;
4198 goto clean_sspp;
4199 }
4200 }
4201
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004202 format_list = psde->pipe_sblk->format_list;
4203
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004204 if (master_plane_id) {
4205 int index, array_size;
4206
4207 array_size = ARRAY_SIZE(plane_formats)
4208 + ARRAY_SIZE(rgb_10bit_formats);
4209 virt_format_list = kcalloc(array_size,
4210 sizeof(struct sde_format_extended),
4211 GFP_KERNEL);
4212 if (!virt_format_list) {
4213 SDE_ERROR(
4214 "failed to allocate virtual pipe format list\n");
4215 goto clean_sspp;
4216 }
4217
4218 index = sde_copy_formats(virt_format_list, array_size,
4219 0, plane_formats, ARRAY_SIZE(plane_formats));
4220 sde_copy_formats(virt_format_list, array_size,
4221 index, rgb_10bit_formats,
4222 ARRAY_SIZE(rgb_10bit_formats));
4223
4224 format_list = virt_format_list;
4225 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004226
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004227 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004228 psde->formats,
4229 0,
4230 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004231
Clarence Ip4c1d9772016-06-26 09:35:38 -04004232 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004233 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004234 goto clean_sspp;
4235 }
4236
4237 if (psde->features & BIT(SDE_SSPP_CURSOR))
4238 type = DRM_PLANE_TYPE_CURSOR;
4239 else if (primary_plane)
4240 type = DRM_PLANE_TYPE_PRIMARY;
4241 else
4242 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07004243 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
4244 psde->formats, psde->nformats,
4245 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004246 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04004247 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004248
Clarence Ip4c1d9772016-06-26 09:35:38 -04004249 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004250 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004251
Clarence Ipaa0faf42016-05-30 12:07:48 -04004252 msm_property_init(&psde->property_info, &plane->base, dev,
4253 priv->plane_property, psde->property_data,
4254 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
4255 sizeof(struct sde_plane_state));
4256
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004257 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004258
Clarence Ip4ce59322016-06-26 22:27:51 -04004259 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004260 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004261
Clarence Ip730e7192016-06-26 22:45:09 -04004262 mutex_init(&psde->lock);
4263
Dhaval Patel82c8dbc2017-02-18 23:15:10 -08004264 SDE_DEBUG("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004265 return plane;
4266
Clarence Ip4c1d9772016-06-26 09:35:38 -04004267clean_sspp:
4268 if (psde && psde->pipe_hw)
4269 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04004270
4271 if (psde && psde->scaler3_cfg)
4272 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004273clean_plane:
4274 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004275exit:
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004276 kfree(virt_format_list);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004277 return ERR_PTR(ret);
4278}