blob: ad207d6a314f521ce22d1ea7155e22495fe1c5c6 [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
Clarence Ipcae1bb62016-07-07 12:07:13 -0400588/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400589static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400590 struct sde_plane_state *pstate, uint64_t fd)
591{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400592 if (!psde || !pstate) {
593 SDE_ERROR("invalid arg(s), plane %d state %d\n",
594 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400595 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400596 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400597
598 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400599 if (pstate->input_fence)
600 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400601
602 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400603 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400604
Clarence Ip13a8cf42016-09-29 17:27:47 -0400605 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400606}
607
Clarence Ipcae1bb62016-07-07 12:07:13 -0400608int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400609{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400610 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400611 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400612 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400613 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400614 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800615 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400616
617 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700618 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400619 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400620 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400621 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400622 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400623 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400624 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400625
Clarence Ipcae1bb62016-07-07 12:07:13 -0400626 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800627 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400628 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800629 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400630
Dhaval Patel39323d42017-03-01 23:48:24 -0800631 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400632 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400633 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
634 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400635 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800636 ret = -ETIMEDOUT;
637 break;
638 case -ERESTARTSYS:
639 SDE_ERROR_PLANE(psde,
640 "%ums wait interrupted on %08X\n",
641 wait_ms, prefix);
642 psde->is_error = true;
643 ret = -ERESTARTSYS;
644 break;
645 case -EINVAL:
646 SDE_ERROR_PLANE(psde,
647 "invalid fence param for %08X\n",
648 prefix);
649 psde->is_error = true;
650 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400651 break;
652 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800653 SDE_DEBUG_PLANE(psde, "signaled\n");
654 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400655 break;
656 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700657
658 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400659 } else {
660 ret = 0;
661 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400662 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400663 return ret;
664}
665
Clarence Ip282dad62016-09-27 17:07:35 -0400666static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400667 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400668 struct sde_hw_pipe_cfg *pipe_cfg,
669 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400670{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400671 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400672 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400673
Clarence Ip13a8cf42016-09-29 17:27:47 -0400674 if (!plane || !pstate || !pipe_cfg || !fb) {
675 SDE_ERROR(
676 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
677 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400678 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400679 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400680
681 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400682 if (!psde->pipe_hw) {
683 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400684 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400685 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400686
Clarence Ipb6eb2362016-09-08 16:18:13 -0400687 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
688 if (ret == -EAGAIN)
689 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
690 else if (ret)
691 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
692 else if (psde->pipe_hw->ops.setup_sourceaddress)
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800693 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
694 pstate->multirect_index);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400695}
696
abeykun48f407a2016-08-25 12:06:44 -0400697static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
698 struct sde_plane_state *pstate)
699{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500700 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400701 int ret = 0;
702
Clarence Ip3bf8d872017-02-16 15:25:38 -0500703 if (!psde || !psde->scaler3_cfg) {
704 SDE_ERROR("invalid args\n");
705 return -EINVAL;
706 } else if (!pstate) {
707 /* pstate is expected to be null on forced color fill */
708 SDE_DEBUG("null pstate\n");
709 return -EINVAL;
710 }
711
712 cfg = psde->scaler3_cfg;
713
abeykun48f407a2016-08-25 12:06:44 -0400714 cfg->dir_lut = msm_property_get_blob(
715 &psde->property_info,
716 pstate->property_blobs, &cfg->dir_len,
717 PLANE_PROP_SCALER_LUT_ED);
718 cfg->cir_lut = msm_property_get_blob(
719 &psde->property_info,
720 pstate->property_blobs, &cfg->cir_len,
721 PLANE_PROP_SCALER_LUT_CIR);
722 cfg->sep_lut = msm_property_get_blob(
723 &psde->property_info,
724 pstate->property_blobs, &cfg->sep_len,
725 PLANE_PROP_SCALER_LUT_SEP);
726 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
727 ret = -ENODATA;
728 return ret;
729}
730
Clarence Ipcb410d42016-06-26 22:52:33 -0400731static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400732 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
733 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400734 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400735 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
736{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700737 uint32_t decimated, i;
738
739 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
740 !chroma_subsmpl_v) {
741 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
742 , psde, scale_cfg, fmt, chroma_subsmpl_h,
743 chroma_subsmpl_v);
744 return;
745 }
746
747 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip716ab662017-03-20 06:51:24 -0700748 memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700749
750 decimated = DECIMATED_DIMENSION(src_w,
751 psde->pipe_cfg.horz_decimation);
752 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
753 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
754 decimated = DECIMATED_DIMENSION(src_h,
755 psde->pipe_cfg.vert_decimation);
756 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
757 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
758
759
760 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
761 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
762 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
763 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
764
765 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
766 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
767 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
768 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
769
770 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
771 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
772 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
773 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
774
775 for (i = 0; i < SDE_MAX_PLANES; i++) {
776 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
777 psde->pipe_cfg.horz_decimation);
778 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
779 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700780 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
781 scale_cfg->src_width[i] /= chroma_subsmpl_h;
782 scale_cfg->src_height[i] /= chroma_subsmpl_v;
783 }
784 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
785 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
786 psde->pixel_ext.num_ext_pxls_top[i] =
787 scale_cfg->src_height[i];
788 psde->pixel_ext.num_ext_pxls_left[i] =
789 scale_cfg->src_width[i];
790 }
791 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
792 && (src_w == dst_w))
793 return;
794
795 scale_cfg->dst_width = dst_w;
796 scale_cfg->dst_height = dst_h;
797 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
798 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
799 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
800 scale_cfg->lut_flag = 0;
801 scale_cfg->blend_cfg = 1;
802 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -0400803}
804
Clarence Ipcb410d42016-06-26 22:52:33 -0400805/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400806 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400807 * @psde: Pointer to SDE plane object
808 * @src: Source size
809 * @dst: Destination size
810 * @phase_steps: Pointer to output array for phase steps
811 * @filter: Pointer to output array for filter type
812 * @fmt: Pointer to format definition
813 * @chroma_subsampling: Subsampling amount for chroma channel
814 *
815 * Returns: 0 on success
816 */
817static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400818 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400819 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400820 uint32_t chroma_subsampling)
821{
Clarence Ipcb410d42016-06-26 22:52:33 -0400822 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400823 SDE_ERROR(
824 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
825 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400826 return -EINVAL;
827 }
828
Clarence Ip4c1d9772016-06-26 09:35:38 -0400829 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400830 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400831 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400832 phase_steps[SDE_SSPP_COMP_1_2] =
833 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
834 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
835 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400836
837 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400838 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400839 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400840 (src <= dst) ? SDE_SCALE_FILTER_BIL :
841 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400842
Clarence Ipdbde9832016-06-26 09:48:36 -0400843 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400844 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400845 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
846 } else {
847 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
848 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400849 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400850 }
851 } else {
852 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400853 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
854 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
855 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400856 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400857 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400858}
859
Clarence Ipcb410d42016-06-26 22:52:33 -0400860/**
861 * _sde_plane_setup_pixel_ext - determine default pixel extension values
862 * @psde: Pointer to SDE plane object
863 * @src: Source size
864 * @dst: Destination size
865 * @decimated_src: Source size after decimation, if any
866 * @phase_steps: Pointer to output array for phase steps
867 * @out_src: Output array for pixel extension values
868 * @out_edge1: Output array for pixel extension first edge
869 * @out_edge2: Output array for pixel extension second edge
870 * @filter: Pointer to array for filter type
871 * @fmt: Pointer to format definition
872 * @chroma_subsampling: Subsampling amount for chroma channel
873 * @post_compare: Whether to chroma subsampled source size for comparisions
874 */
875static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400876 uint32_t src, uint32_t dst, uint32_t decimated_src,
877 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400878 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400879 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400880 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400881{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400882 int64_t edge1, edge2, caf;
883 uint32_t src_work;
884 int i, tmp;
885
Clarence Ipcb410d42016-06-26 22:52:33 -0400886 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400887 out_edge2 && filter && fmt) {
888 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400889 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400890 caf = PHASE_STEP_UNIT_SCALE;
891 else
892 caf = 0;
893
894 for (i = 0; i < SDE_MAX_PLANES; i++) {
895 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400896 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400897 src_work /= chroma_subsampling;
898 if (post_compare)
899 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400900 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400901 /* unity */
902 edge1 = 0;
903 edge2 = 0;
904 } else if (dst >= src) {
905 /* upscale */
906 edge1 = (1 << PHASE_RESIDUAL);
907 edge1 -= caf;
908 edge2 = (1 << PHASE_RESIDUAL);
909 edge2 += (dst - 1) * *(phase_steps + i);
910 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
911 edge2 += caf;
912 edge2 = -(edge2);
913 } else {
914 /* downscale */
915 edge1 = 0;
916 edge2 = (dst - 1) * *(phase_steps + i);
917 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
918 edge2 += *(phase_steps + i);
919 edge2 = -(edge2);
920 }
921
922 /* only enable CAF for luma plane */
923 caf = 0;
924
925 /* populate output arrays */
926 *(out_src + i) = src_work;
927
928 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400929 if (edge1 >= 0) {
930 tmp = (uint32_t)edge1;
931 tmp >>= PHASE_STEP_SHIFT;
932 *(out_edge1 + i) = -tmp;
933 } else {
934 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400935 *(out_edge1 + i) =
936 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
937 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400938 }
939 if (edge2 >= 0) {
940 tmp = (uint32_t)edge2;
941 tmp >>= PHASE_STEP_SHIFT;
942 *(out_edge2 + i) = -tmp;
943 } else {
944 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400945 *(out_edge2 + i) =
946 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
947 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400948 }
949 }
950 }
951}
952
Clarence Ip5fc00c52016-09-23 15:03:34 -0400953static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400954{
955 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
956 {
Clarence Ip373f8592016-05-26 00:58:42 -0400957 /* S15.16 format */
958 0x00012A00, 0x00000000, 0x00019880,
959 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
960 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400961 },
Clarence Ip373f8592016-05-26 00:58:42 -0400962 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400963 { 0xfff0, 0xff80, 0xff80,},
964 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400965 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400966 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400967 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400968 };
abeykun1c312f62016-08-26 09:47:12 -0400969 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
970 {
971 /* S15.16 format */
972 0x00012A00, 0x00000000, 0x00019880,
973 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
974 0x00012A00, 0x00020480, 0x00000000,
975 },
976 /* signed bias */
977 { 0xffc0, 0xfe00, 0xfe00,},
978 { 0x0, 0x0, 0x0,},
979 /* unsigned clamp */
980 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
981 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
982 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400983
Clarence Ip5fc00c52016-09-23 15:03:34 -0400984 if (!psde) {
985 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400986 return;
987 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400988
Clarence Ipcae1bb62016-07-07 12:07:13 -0400989 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400990 if (psde->csc_usr_ptr)
991 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400992 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
993 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400994 else
Clarence Ip373f8592016-05-26 00:58:42 -0400995 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400996
Clarence Ip13a8cf42016-09-29 17:27:47 -0400997 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400998 psde->csc_ptr->csc_mv[0],
999 psde->csc_ptr->csc_mv[1],
1000 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -04001001}
1002
Benet Clarkeb1b4462016-06-27 14:43:06 -07001003static void sde_color_process_plane_setup(struct drm_plane *plane)
1004{
1005 struct sde_plane *psde;
1006 struct sde_plane_state *pstate;
1007 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001008 struct drm_msm_memcol *memcol = NULL;
1009 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001010
1011 psde = to_sde_plane(plane);
1012 pstate = to_sde_plane_state(plane->state);
1013
1014 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1015 if (psde->pipe_hw->ops.setup_pa_hue)
1016 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1017 saturation = (uint32_t) sde_plane_get_property(pstate,
1018 PLANE_PROP_SATURATION_ADJUST);
1019 if (psde->pipe_hw->ops.setup_pa_sat)
1020 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1021 value = (uint32_t) sde_plane_get_property(pstate,
1022 PLANE_PROP_VALUE_ADJUST);
1023 if (psde->pipe_hw->ops.setup_pa_val)
1024 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1025 contrast = (uint32_t) sde_plane_get_property(pstate,
1026 PLANE_PROP_CONTRAST_ADJUST);
1027 if (psde->pipe_hw->ops.setup_pa_cont)
1028 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001029
Benet Clarkd009b1d2016-06-27 14:45:59 -07001030 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1031 /* Skin memory color setup */
1032 memcol = msm_property_get_blob(&psde->property_info,
1033 pstate->property_blobs,
1034 &memcol_sz,
1035 PLANE_PROP_SKIN_COLOR);
1036 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1037 MEMCOLOR_SKIN, memcol);
1038
1039 /* Sky memory color setup */
1040 memcol = msm_property_get_blob(&psde->property_info,
1041 pstate->property_blobs,
1042 &memcol_sz,
1043 PLANE_PROP_SKY_COLOR);
1044 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1045 MEMCOLOR_SKY, memcol);
1046
1047 /* Foliage memory color setup */
1048 memcol = msm_property_get_blob(&psde->property_info,
1049 pstate->property_blobs,
1050 &memcol_sz,
1051 PLANE_PROP_FOLIAGE_COLOR);
1052 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1053 MEMCOLOR_FOLIAGE, memcol);
1054 }
1055}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001056
Clarence Ipcb410d42016-06-26 22:52:33 -04001057static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001058 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -04001059 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001060{
Clarence Ipb43d4592016-09-08 14:21:35 -04001061 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001062 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001063
Clarence Ipb43d4592016-09-08 14:21:35 -04001064 if (!psde || !fmt) {
1065 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1066 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001067 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001068 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001069
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001070 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001071
Clarence Ipdedbba92016-09-27 17:43:10 -04001072 psde->pipe_cfg.horz_decimation =
1073 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1074 psde->pipe_cfg.vert_decimation =
1075 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001076
1077 /* don't chroma subsample if decimating */
1078 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001079 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001080 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001081 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001082
Clarence Ip5e2a9222016-06-26 22:38:24 -04001083 /* update scaler */
1084 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001085 int error;
1086
1087 error = _sde_plane_setup_scaler3_lut(psde, pstate);
Clarence Ip716ab662017-03-20 06:51:24 -07001088 if (error || !psde->pixel_ext_usr ||
1089 psde->debugfs_default_scale) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001090 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001091 _sde_plane_setup_scaler3(psde,
1092 psde->pipe_cfg.src_rect.w,
1093 psde->pipe_cfg.src_rect.h,
1094 psde->pipe_cfg.dst_rect.w,
1095 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001096 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001097 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001098 }
Clarence Ip716ab662017-03-20 06:51:24 -07001099 } else if (!psde->pixel_ext_usr || !pstate ||
1100 psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001101 uint32_t deci_dim, i;
1102
Clarence Ipb43d4592016-09-08 14:21:35 -04001103 /* calculate default configuration for QSEED2 */
1104 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001105
Clarence Ip13a8cf42016-09-29 17:27:47 -04001106 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001107 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1108 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001109 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001110 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001111 psde->pipe_cfg.dst_rect.w,
1112 pe->phase_step_x,
1113 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001114
Clarence Ipdbde9832016-06-26 09:48:36 -04001115 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001116 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001117 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001118 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001119 pe->phase_step_x,
1120 pe->roi_w,
1121 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001122 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001123 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001124
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001125 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001126 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001127 _sde_plane_setup_scaler2(psde,
1128 deci_dim,
1129 psde->pipe_cfg.dst_rect.h,
1130 pe->phase_step_y,
1131 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001132 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001133 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001134 pe->phase_step_y,
1135 pe->roi_h,
1136 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001137 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001138 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001139
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001140 for (i = 0; i < SDE_MAX_PLANES; i++) {
1141 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001142 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001143 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001144 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001145
1146 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001147 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001148 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001149 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001150
1151 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001152 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001153 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001154 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001155
1156 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001157 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001158 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001159 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001160 }
1161 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001162}
1163
Clarence Ipcae1bb62016-07-07 12:07:13 -04001164/**
1165 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001166 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001167 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1168 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1169 * Returns: 0 on success
1170 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001171static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001172 uint32_t color, uint32_t alpha)
1173{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001174 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001175 const struct drm_plane *plane;
1176 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001177
Clarence Ip13a8cf42016-09-29 17:27:47 -04001178 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001179 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001180 return -EINVAL;
1181 }
1182
Clarence Ipcb410d42016-06-26 22:52:33 -04001183 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001184 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001185 return -EINVAL;
1186 }
1187
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001188 plane = &psde->base;
1189 pstate = to_sde_plane_state(plane->state);
1190
Clarence Ip13a8cf42016-09-29 17:27:47 -04001191 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001192
Clarence Ipcb410d42016-06-26 22:52:33 -04001193 /*
1194 * select fill format to match user property expectation,
1195 * h/w only supports RGB variants
1196 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001197 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001198
1199 /* update sspp */
1200 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1201 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001202 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1203 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001204
1205 /* override scaler/decimation if solid fill */
1206 psde->pipe_cfg.src_rect.x = 0;
1207 psde->pipe_cfg.src_rect.y = 0;
1208 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1209 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Dhaval Patele4b6bb22017-03-27 17:22:21 -07001210 _sde_plane_setup_scaler(psde, fmt, 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001211
Clarence Ipcb410d42016-06-26 22:52:33 -04001212 if (psde->pipe_hw->ops.setup_format)
1213 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001214 fmt, SDE_SSPP_SOLID_FILL,
1215 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001216
1217 if (psde->pipe_hw->ops.setup_rects)
1218 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001219 &psde->pipe_cfg,
1220 pstate->multirect_index);
1221
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001222 if (psde->pipe_hw->ops.setup_pe)
1223 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1224 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001225 }
1226
1227 return 0;
1228}
1229
Alan Kwong4dd64c82017-02-04 18:41:51 -08001230/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001231 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1232 */
1233static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1234{
1235 drm_framebuffer_reference(fb);
1236 return fb;
1237}
1238static void _sde_plane_fb_put(void *fb)
1239{
1240 drm_framebuffer_unreference(fb);
1241}
1242static struct sde_crtc_res_ops fb_res_ops = {
1243 .put = _sde_plane_fb_put,
1244 .get = _sde_plane_fb_get,
1245};
1246
1247/**
1248 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1249 */
1250static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1251{
1252 sde_kms_fbo_reference(fbo);
1253 return fbo;
1254}
1255static void _sde_plane_fbo_put(void *fbo)
1256{
1257 sde_kms_fbo_unreference(fbo);
1258}
1259static struct sde_crtc_res_ops fbo_res_ops = {
1260 .put = _sde_plane_fbo_put,
1261 .get = _sde_plane_fbo_get,
1262};
1263
1264/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001265 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001266 * @plane: Pointer to drm plane
1267 * return: prefill time in line
1268 */
1269static u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
1270{
1271 struct drm_plane_state *state;
1272 struct drm_crtc_state *cstate;
1273 struct sde_plane_state *pstate;
1274 struct sde_plane_rot_state *rstate;
1275 struct sde_kms *sde_kms;
1276 u32 blocksize = 128;
1277 u32 prefill_line = 0;
1278
1279 if (!plane || !plane->state || !plane->state->fb ||
1280 !plane->state->crtc || !plane->state->crtc->state) {
1281 SDE_ERROR("invalid parameters\n");
1282 return 0;
1283 }
1284
1285 sde_kms = _sde_plane_get_kms(plane);
1286 state = plane->state;
1287 cstate = state->crtc->state;
1288 pstate = to_sde_plane_state(state);
1289 rstate = &pstate->rot;
1290
1291 if (!rstate->rot_hw || !rstate->rot_hw->caps || !rstate->out_src_h ||
1292 !sde_kms || !sde_kms->catalog) {
1293 SDE_ERROR("invalid parameters\n");
1294 return 0;
1295 }
1296
Alan Kwong4aacd532017-02-04 18:51:33 -08001297 sde_format_get_block_size(rstate->out_fb_format, &blocksize,
1298 &blocksize);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001299 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
1300
1301 SDE_DEBUG("plane%d prefill:%u\n", plane->base.id, prefill_line);
1302
1303 return prefill_line;
1304}
1305
1306/**
1307 * sde_plane_is_sbuf_mode - check if sspp of given plane is in streaming
1308 * buffer mode
1309 * @plane: Pointer to drm plane
1310 * @prefill: Pointer to prefill line count
1311 * return: true if sspp is in stream buffer mode
1312 */
1313bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill)
1314{
1315 struct sde_plane_state *pstate = plane && plane->state ?
1316 to_sde_plane_state(plane->state) : NULL;
1317 struct sde_plane_rot_state *rstate = pstate ? &pstate->rot : NULL;
1318 bool sbuf_mode = rstate ? rstate->out_sbuf : false;
1319
1320 if (prefill && sbuf_mode)
1321 *prefill = sde_plane_rot_calc_prefill(plane);
1322
1323 return sbuf_mode;
1324}
1325
1326/**
1327 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1328 * enumerating over all planes attached to the same rotator
1329 * @plane: Pointer to drm plane
1330 * @state: Pointer to drm state to be updated
1331 * return: none
1332 */
1333static void sde_plane_rot_calc_cfg(struct drm_plane *plane,
1334 struct drm_plane_state *state)
1335{
1336 struct sde_plane_state *pstate;
1337 struct sde_plane_rot_state *rstate;
1338 struct sde_hw_blk *hw_blk;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001339 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001340 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001341 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001342 u32 dst_x, dst_y, dst_w, dst_h;
1343 int found = 0;
1344 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001345 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001346
1347 if (!plane || !state || !state->state) {
1348 SDE_ERROR("invalid parameters\n");
1349 return;
1350 }
1351
Alan Kwongcdb2f282017-03-18 13:42:06 -07001352 cstate = _sde_plane_get_crtc_state(state);
1353 if (IS_ERR_OR_NULL(cstate)) {
1354 ret = PTR_ERR(cstate);
1355 SDE_ERROR("invalid crtc state %d\n", ret);
1356 return;
1357 }
1358
Alan Kwong4dd64c82017-02-04 18:41:51 -08001359 pstate = to_sde_plane_state(state);
1360 rstate = &pstate->rot;
1361
1362 if (!rstate->rot_hw) {
1363 SDE_ERROR("invalid rotator hw\n");
1364 return;
1365 }
1366
1367 in_rot = &rstate->in_rot_rect;
1368 in_rot->x1 = state->src_x;
1369 in_rot->y1 = state->src_y;
1370 in_rot->x2 = state->src_x + state->src_w;
1371 in_rot->y2 = state->src_y + state->src_h;
1372
1373 out_rot = &rstate->out_rot_rect;
1374 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1375 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1376 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1377 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1378
1379 if (!dst_w && !dst_h) {
1380 rstate->out_rot_rect = rstate->in_rot_rect;
1381 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1382 state->fb->height << 16, rstate->in_rotation);
1383 } else {
1384 out_rot->x1 = dst_x;
1385 out_rot->y1 = dst_y;
1386 out_rot->x2 = dst_x + dst_w;
1387 out_rot->y2 = dst_y + dst_h;
1388 }
1389
1390 rstate->out_src_rect = rstate->out_rot_rect;
1391
1392 hw_blk = &rstate->rot_hw->base;
1393
1394 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001395 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001396 struct drm_plane_state *attached_state;
1397 struct sde_plane_state *attached_pstate;
1398 struct sde_plane_rot_state *attached_rstate;
1399 struct drm_rect attached_out_rect;
1400
Alan Kwong4dd64c82017-02-04 18:41:51 -08001401 attached_state = drm_atomic_get_existing_plane_state(
1402 state->state, attached_plane);
1403
1404 if (!attached_state)
1405 continue;
1406
1407 attached_pstate = to_sde_plane_state(attached_state);
1408 attached_rstate = &attached_pstate->rot;
1409
Alan Kwongcdb2f282017-03-18 13:42:06 -07001410 if (attached_rstate->rot_hw != rstate->rot_hw)
1411 continue;
1412
1413 found++;
1414
1415 /* skip itself */
1416 if (attached_plane == plane)
1417 continue;
1418
Alan Kwong4dd64c82017-02-04 18:41:51 -08001419 /* find bounding rotator source roi */
1420 if (attached_state->src_x < in_rot->x1)
1421 in_rot->x1 = attached_state->src_x;
1422
1423 if (attached_state->src_y < in_rot->y1)
1424 in_rot->y1 = attached_state->src_y;
1425
1426 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1427 in_rot->x2 = attached_state->src_x +
1428 attached_state->src_w;
1429
1430 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1431 in_rot->y2 = attached_state->src_y +
1432 attached_state->src_h;
1433
1434 /* find bounding rotator destination roi */
1435 dst_x = sde_plane_get_property(attached_pstate,
1436 PLANE_PROP_ROT_DST_X);
1437 dst_y = sde_plane_get_property(attached_pstate,
1438 PLANE_PROP_ROT_DST_Y);
1439 dst_w = sde_plane_get_property(attached_pstate,
1440 PLANE_PROP_ROT_DST_W);
1441 dst_h = sde_plane_get_property(attached_pstate,
1442 PLANE_PROP_ROT_DST_H);
1443 if (!dst_w && !dst_h) {
1444 attached_out_rect.x1 = attached_state->src_x;
1445 attached_out_rect.y1 = attached_state->src_y;
1446 attached_out_rect.x2 = attached_out_rect.x1 +
1447 attached_state->src_w;
1448 attached_out_rect.y2 = attached_out_rect.y1 +
1449 attached_state->src_h;
1450 drm_rect_rotate(&attached_out_rect,
1451 state->fb->width << 16,
1452 state->fb->height << 16,
1453 rstate->in_rotation);
1454 } else {
1455 attached_out_rect.x1 = dst_x;
1456 attached_out_rect.y1 = dst_y;
1457 attached_out_rect.x2 = dst_x + dst_w;
1458 attached_out_rect.y2 = dst_y + dst_h;
1459 }
1460
1461 /* find relative sspp position */
1462 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1463 xpos++;
1464
1465 if (attached_out_rect.x1 < out_rot->x1)
1466 out_rot->x1 = attached_out_rect.x1;
1467
1468 if (attached_out_rect.y1 < out_rot->y1)
1469 out_rot->y1 = attached_out_rect.y1;
1470
1471 if (attached_out_rect.x2 > out_rot->x2)
1472 out_rot->x2 = attached_out_rect.x2;
1473
1474 if (attached_out_rect.y2 > out_rot->y2)
1475 out_rot->y2 = attached_out_rect.y2;
1476
1477 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1478 attached_plane->base.id,
1479 attached_rstate->sequence_id,
1480 attached_rstate->out_src_rect.x1 >> 16,
1481 attached_state->src_w >> 16,
1482 attached_state->src_h >> 16,
1483 attached_state->src_x >> 16,
1484 attached_state->src_y >> 16,
1485 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1486 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1487 attached_rstate->out_src_rect.x1 >> 16,
1488 attached_rstate->out_src_rect.y1 >> 16);
1489 }
1490
1491 rstate->out_xpos = xpos;
1492 rstate->nplane = found;
1493
1494 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1495 plane->base.id, rstate->sequence_id,
1496 rstate->out_xpos, rstate->nplane,
1497 drm_rect_width(in_rot) >> 16,
1498 drm_rect_height(in_rot) >> 16,
1499 in_rot->x1 >> 16, in_rot->y1 >> 16,
1500 drm_rect_width(&rstate->out_rot_rect) >> 16,
1501 drm_rect_height(&rstate->out_rot_rect) >> 16,
1502 rstate->out_rot_rect.x1 >> 16,
1503 rstate->out_rot_rect.y1 >> 16);
1504}
1505
1506/**
1507 * sde_plane_rot_submit_command - commit given state for the rotator stage
1508 * @plane: Pointer to drm plane
1509 * @state: Pointer to the state to be committed
1510 * @hw_cmd: rotator command type
1511 * return: 0 if success; error code otherwise
1512 */
1513static int sde_plane_rot_submit_command(struct drm_plane *plane,
1514 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1515{
1516 struct sde_plane *psde = to_sde_plane(plane);
1517 struct sde_plane_state *pstate = to_sde_plane_state(state);
1518 struct sde_plane_rot_state *rstate = &pstate->rot;
1519 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001520 struct drm_crtc_state *cstate;
1521 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001522 int ret, i;
1523
1524 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1525 SDE_ERROR("invalid parameters\n");
1526 return -EINVAL;
1527 }
1528
Alan Kwong4aacd532017-02-04 18:51:33 -08001529 cstate = _sde_plane_get_crtc_state(state);
1530 if (IS_ERR_OR_NULL(cstate)) {
1531 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1532 return -EINVAL;
1533 }
1534 sde_cstate = to_sde_crtc_state(cstate);
1535
Alan Kwong4dd64c82017-02-04 18:41:51 -08001536 rot_cmd = &rstate->rot_cmd;
1537
1538 rot_cmd->master = (rstate->out_xpos == 0);
1539 rot_cmd->sequence_id = rstate->sequence_id;
1540 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1541 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1542 DEFAULT_REFRESH_RATE;
1543 rot_cmd->rot90 = rstate->rot90;
1544 rot_cmd->hflip = rstate->hflip;
1545 rot_cmd->vflip = rstate->vflip;
1546 rot_cmd->secure = state->fb->flags & DRM_MODE_FB_SECURE ? true : false;
Alan Kwong4aacd532017-02-04 18:51:33 -08001547 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1548 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001549 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1550 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001551 rot_cmd->dst_writeback = psde->sbuf_writeback;
1552
1553 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1554 rot_cmd->video_mode = true;
1555 else
1556 rot_cmd->video_mode = false;
1557
1558 rot_cmd->src_pixel_format = state->fb->pixel_format;
1559 rot_cmd->src_modifier = state->fb->modifier[0];
1560 rot_cmd->src_stride = state->fb->pitches[0];
1561
1562 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1563 if (!rot_cmd->src_format) {
1564 SDE_ERROR("failed to get src format\n");
1565 return -EINVAL;
1566 }
1567
1568 rot_cmd->src_width = state->fb->width;
1569 rot_cmd->src_height = state->fb->height;
1570 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1571 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1572 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1573 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
1574 rot_cmd->dst_rect_x = rstate->out_rot_rect.x1 >> 16;
1575 rot_cmd->dst_rect_y = rstate->out_rot_rect.y1 >> 16;
1576 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1577 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1578
1579 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1580 struct sde_hw_fmt_layout layout;
1581
1582 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1583 sde_format_populate_layout(rstate->mmu_id, state->fb,
1584 &layout);
1585 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1586 rot_cmd->src_iova[i] = layout.plane_addr[i];
1587 rot_cmd->src_len[i] = layout.plane_size[i];
1588 }
1589 rot_cmd->src_planes = layout.num_planes;
1590
1591 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1592 sde_format_populate_layout(rstate->mmu_id, rstate->out_fb,
1593 &layout);
1594 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1595 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1596 rot_cmd->dst_len[i] = layout.plane_size[i];
1597 }
1598 rot_cmd->dst_planes = layout.num_planes;
1599 }
1600
1601 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
1602 if (ret) {
1603 SDE_ERROR("failed to commit rotator %d\n", ret);
1604 return ret;
1605 }
1606
1607 rstate->out_rotation = rstate->in_rotation;
1608 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1609 DRM_MODE_FB_MODIFIERS : 0;
1610 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1611 rstate->out_fb_format = rot_cmd->dst_format;
1612 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1613
1614 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1615 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1616
1617 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1618 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1619 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1620 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1621 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1622 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1623
1624 if (rot_cmd->rot90)
1625 rstate->out_rotation &= ~DRM_ROTATE_90;
1626
1627 if (rot_cmd->hflip)
1628 rstate->out_rotation &= ~DRM_REFLECT_X;
1629
1630 if (rot_cmd->vflip)
1631 rstate->out_rotation &= ~DRM_REFLECT_Y;
1632
1633 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07001634 "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 -08001635 plane->base.id, rstate->sequence_id, hw_cmd,
1636 rot_cmd->rot90 ? 'r' : '_',
1637 rot_cmd->hflip ? 'h' : '_',
1638 rot_cmd->vflip ? 'v' : '_',
1639 rot_cmd->video_mode ? 'V' : 'C',
1640 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001641 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001642 state->fb->modifier[0],
1643 drm_rect_width(&rstate->in_rot_rect) >> 16,
1644 drm_rect_height(&rstate->in_rot_rect) >> 16,
1645 rstate->in_rot_rect.x1 >> 16,
1646 rstate->in_rot_rect.y1 >> 16);
1647
Dhaval Patel6c666622017-03-21 23:02:59 -07001648 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 -08001649 plane->base.id, rstate->sequence_id, hw_cmd,
1650 rstate->out_rotation,
1651 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001652 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001653 rstate->out_fb_modifier[0],
1654 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
1655 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
1656
1657 return ret;
1658}
1659
1660/**
1661 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
1662 * for rotator (pre-sspp) stage
1663 * @plane: Pointer to drm plane
1664 * @new_state: Pointer to new drm plane state
1665 * return: 0 if success; error code otherwise
1666 */
1667static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
1668 struct drm_plane_state *new_state)
1669{
1670 struct drm_framebuffer *fb = new_state->fb;
1671 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
1672 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001673 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001674 int ret;
1675
1676 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
1677 plane->base.id,
1678 new_rstate->sequence_id, fb ? fb->base.id : 0,
1679 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
1680 sde_plane_crtc_enabled(new_state));
1681
1682 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
1683 return 0;
1684
Alan Kwongcdb2f282017-03-18 13:42:06 -07001685 cstate = _sde_plane_get_crtc_state(new_state);
1686 if (IS_ERR(cstate)) {
1687 ret = PTR_ERR(cstate);
1688 SDE_ERROR("invalid crtc state %d\n", ret);
1689 return ret;
1690 }
1691
Alan Kwong4dd64c82017-02-04 18:41:51 -08001692 /* need to re-calc based on all newly validated plane states */
1693 sde_plane_rot_calc_cfg(plane, new_state);
1694
1695 /* check if stream buffer is already attached to rotator */
1696 if (sde_plane_enabled(new_state)) {
1697 struct sde_kms_fbo *fbo;
1698 struct drm_framebuffer *fb;
1699
Alan Kwongcdb2f282017-03-18 13:42:06 -07001700 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1701 (u64) &new_rstate->rot_hw->base);
1702 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1703 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001704 if (fb && fbo) {
1705 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
1706 new_rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001707 } else if (fbo) {
1708 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1709 (u64) &new_rstate->rot_hw->base);
1710 fbo = NULL;
1711 } else if (fb) {
1712 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1713 (u64) &new_rstate->rot_hw->base);
1714 fb = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001715 }
Alan Kwongcdb2f282017-03-18 13:42:06 -07001716
1717 new_rstate->out_fbo = fbo;
1718 new_rstate->out_fb = fb;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001719 }
1720
1721 /* release buffer if output format configuration changes */
1722 if (new_rstate->out_fb &&
1723 ((new_rstate->out_fb_height != new_rstate->out_fb->height) ||
1724 (new_rstate->out_fb_width != new_rstate->out_fb->width) ||
1725 (new_rstate->out_fb_pixel_format !=
1726 new_rstate->out_fb->pixel_format) ||
1727 (new_rstate->out_fb_modifier[0] !=
1728 new_rstate->out_fb->modifier[0]) ||
1729 (new_rstate->out_fb_flags != new_rstate->out_fb->flags))) {
1730
1731 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
1732 new_rstate->sequence_id);
1733
Alan Kwongcdb2f282017-03-18 13:42:06 -07001734 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1735 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001736 new_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001737 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1738 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001739 new_rstate->out_fbo = NULL;
1740 }
1741
1742 /* create new stream buffer if it is not available */
1743 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
1744 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
1745 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
1746
1747 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
1748 new_rstate->sequence_id);
1749
1750 if (new_state->fb->flags & DRM_MODE_FB_SECURE)
1751 new_rstate->mmu_id = MSM_SMMU_DOMAIN_SECURE;
1752 else
1753 new_rstate->mmu_id = MSM_SMMU_DOMAIN_UNSECURE;
1754
1755 /* check if out_fb is already attached to rotator */
1756 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
1757 new_rstate->out_fb_pixel_format,
1758 new_rstate->out_fb_modifier,
1759 new_rstate->out_fb_flags);
1760 if (!new_rstate->out_fbo) {
1761 SDE_ERROR("failed to allocate inline buffer object\n");
1762 ret = -EINVAL;
1763 goto error_create_fbo;
1764 }
1765
Alan Kwongcdb2f282017-03-18 13:42:06 -07001766 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1767 (u64) &new_rstate->rot_hw->base,
1768 new_rstate->out_fbo, &fbo_res_ops);
1769 if (ret) {
1770 SDE_ERROR("failed to add crtc resource\n");
1771 goto error_create_fbo_res;
1772 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001773
1774 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
1775 new_rstate->out_fbo);
1776 if (!new_rstate->out_fb) {
1777 SDE_ERROR("failed to create inline framebuffer\n");
1778 ret = -EINVAL;
1779 goto error_create_fb;
1780 }
1781
Alan Kwongcdb2f282017-03-18 13:42:06 -07001782 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1783 (u64) &new_rstate->rot_hw->base,
1784 new_rstate->out_fb, &fb_res_ops);
1785 if (ret) {
1786 SDE_ERROR("failed to add crtc resource %d\n", ret);
1787 goto error_create_fb_res;
1788 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001789 }
1790
1791 /* prepare rotator input buffer */
1792 ret = msm_framebuffer_prepare(new_state->fb, new_rstate->mmu_id);
1793 if (ret) {
1794 SDE_ERROR("failed to prepare input framebuffer\n");
1795 goto error_prepare_input_buffer;
1796 }
1797
1798 /* prepare rotator output buffer */
1799 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
1800 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
1801 new_rstate->sequence_id);
1802
1803 ret = msm_framebuffer_prepare(new_rstate->out_fb,
1804 new_rstate->mmu_id);
1805 if (ret) {
1806 SDE_ERROR("failed to prepare inline framebuffer\n");
1807 goto error_prepare_output_buffer;
1808 }
1809 }
1810
1811 return 0;
1812
1813error_prepare_output_buffer:
1814 msm_framebuffer_cleanup(new_state->fb, new_rstate->mmu_id);
1815error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001816 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1817 (u64) &new_rstate->rot_hw->base);
1818error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001819 new_rstate->out_fb = NULL;
1820error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001821 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1822 (u64) &new_rstate->rot_hw->base);
1823error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001824 new_rstate->out_fbo = NULL;
1825error_create_fbo:
1826 return ret;
1827}
1828
1829/**
1830 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
1831 * rotator (pre-sspp) stage
1832 * @plane: Pointer to drm plane
1833 * @old_state: Pointer to previous drm plane state
1834 * return: none
1835 */
1836static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
1837 struct drm_plane_state *old_state)
1838{
1839 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
1840 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
1841 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001842 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001843 int ret;
1844
1845 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1846 old_rstate->sequence_id, old_state->fb->base.id,
1847 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
1848 sde_plane_crtc_enabled(old_state));
1849
1850 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
1851 return;
1852
Alan Kwongcdb2f282017-03-18 13:42:06 -07001853 cstate = _sde_plane_get_crtc_state(old_state);
1854 if (IS_ERR(cstate)) {
1855 ret = PTR_ERR(cstate);
1856 SDE_ERROR("invalid crtc state %d\n", ret);
1857 return;
1858 }
1859
Alan Kwong4dd64c82017-02-04 18:41:51 -08001860 if (sde_plane_crtc_enabled(old_state)) {
1861 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
1862 SDE_HW_ROT_CMD_CLEANUP);
1863 if (ret)
1864 SDE_ERROR("failed to cleanup rotator buffers\n");
1865 }
1866
1867 if (sde_plane_enabled(old_state)) {
1868 if (old_rstate->out_fb) {
1869 msm_framebuffer_cleanup(old_rstate->out_fb,
1870 old_rstate->mmu_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001871 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1872 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001873 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001874 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1875 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001876 old_rstate->out_fbo = NULL;
1877 }
1878
1879 msm_framebuffer_cleanup(old_state->fb, old_rstate->mmu_id);
1880 }
1881}
1882
1883/**
1884 * sde_plane_rot_atomic_check - verify rotator update of the given state
1885 * @plane: Pointer to drm plane
1886 * @state: Pointer to drm plane state to be validated
1887 * return: 0 if success; error code otherwise
1888 */
1889static int sde_plane_rot_atomic_check(struct drm_plane *plane,
1890 struct drm_plane_state *state)
1891{
1892 struct sde_plane *psde;
1893 struct sde_plane_state *pstate, *old_pstate;
1894 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001895 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001896 struct sde_hw_blk *hw_blk;
1897 int i, ret = 0;
1898
1899 if (!plane || !state) {
1900 SDE_ERROR("invalid plane/state\n");
1901 return -EINVAL;
1902 }
1903
1904 psde = to_sde_plane(plane);
1905 pstate = to_sde_plane_state(state);
1906 old_pstate = to_sde_plane_state(plane->state);
1907 rstate = &pstate->rot;
1908 old_rstate = &old_pstate->rot;
1909
Alan Kwongcdb2f282017-03-18 13:42:06 -07001910 /* cstate will be null if crtc is disconnected from plane */
1911 cstate = _sde_plane_get_crtc_state(state);
1912 if (IS_ERR(cstate)) {
1913 ret = PTR_ERR(cstate);
1914 SDE_ERROR("invalid crtc state %d\n", ret);
1915 return ret;
1916 }
1917
Alan Kwong4dd64c82017-02-04 18:41:51 -08001918 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1919 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
1920 !!rstate->out_sbuf, !!rstate->rot_hw,
1921 sde_plane_crtc_enabled(state));
1922
1923 rstate->in_rotation = drm_rotation_simplify(
1924 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07001925 DRM_ROTATE_0 | DRM_ROTATE_90 |
1926 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001927 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
1928 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
1929 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
1930 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
1931
Alan Kwongcdb2f282017-03-18 13:42:06 -07001932 if (sde_plane_enabled(state) && rstate->out_sbuf) {
1933 SDE_DEBUG("plane%d.%d acquire rotator\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001934 plane->base.id, rstate->sequence_id);
1935
Alan Kwongcdb2f282017-03-18 13:42:06 -07001936 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
1937 (u64) state->fb);
1938 if (!hw_blk) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001939 SDE_ERROR("plane%d no available rotator\n",
1940 plane->base.id);
1941 return -EINVAL;
1942 }
1943
Alan Kwongcdb2f282017-03-18 13:42:06 -07001944 rstate->rot_hw = to_sde_hw_rot(hw_blk);
1945
Alan Kwong4dd64c82017-02-04 18:41:51 -08001946 if (!rstate->rot_hw->ops.commit) {
1947 SDE_ERROR("plane%d invalid rotator ops\n",
1948 plane->base.id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001949 sde_crtc_res_put(cstate,
1950 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001951 rstate->rot_hw = NULL;
1952 return -EINVAL;
1953 }
1954
1955 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001956 } else {
1957 rstate->in_fb = NULL;
1958 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001959 }
1960
1961 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
1962
1963 SDE_DEBUG("plane%d.%d use rotator\n",
1964 plane->base.id, rstate->sequence_id);
1965
1966 sde_plane_rot_calc_cfg(plane, state);
1967
1968 ret = sde_plane_rot_submit_command(plane, state,
1969 SDE_HW_ROT_CMD_VALIDATE);
1970
Clarence Ip4475d582017-04-18 11:36:00 -04001971 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001972
1973 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
1974 rstate->sequence_id);
1975
1976 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04001977 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1978 rstate->out_fb_modifier[i] = state->fb ?
1979 state->fb->modifier[i] : 0x0;
1980
1981 if (state->fb) {
1982 rstate->out_fb_pixel_format = state->fb->pixel_format;
1983 rstate->out_fb_flags = state->fb->flags;
1984 rstate->out_fb_width = state->fb->width;
1985 rstate->out_fb_height = state->fb->height;
1986 } else {
1987 rstate->out_fb_pixel_format = 0x0;
1988 rstate->out_fb_flags = 0x0;
1989 rstate->out_fb_width = 0;
1990 rstate->out_fb_height = 0;
1991 }
1992
Alan Kwong4dd64c82017-02-04 18:41:51 -08001993 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001994 rstate->out_src_x = state->src_x;
1995 rstate->out_src_y = state->src_y;
1996 rstate->out_src_w = state->src_w;
1997 rstate->out_src_h = state->src_h;
1998
1999 rstate->out_fb_format = NULL;
2000 rstate->out_sbuf = false;
2001 rstate->out_fb = state->fb;
2002 }
2003
2004 return ret;
2005}
2006
2007/**
2008 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2009 * @plane: Pointer to drm plane
2010 * @old_state: Pointer to previous state
2011 * return: none
2012 */
2013static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2014 struct drm_plane_state *old_state)
2015{
2016 struct drm_plane_state *state;
2017 struct sde_plane_state *pstate;
2018 struct sde_plane_rot_state *rstate;
2019
2020 if (!plane || !plane->state) {
2021 SDE_ERROR("invalid plane/state\n");
2022 return;
2023 }
2024
2025 state = plane->state;
2026 pstate = to_sde_plane_state(state);
2027 rstate = &pstate->rot;
2028
2029 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2030 rstate->sequence_id,
2031 !!rstate->out_sbuf, !!rstate->rot_hw,
2032 sde_plane_crtc_enabled(plane->state));
2033
2034 if (!sde_plane_crtc_enabled(state))
2035 return;
2036
2037 if (!rstate->out_sbuf || !rstate->rot_hw)
2038 return;
2039
2040 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
2041}
2042
2043/**
2044 * sde_plane_rot_destroy_state - destroy state for rotator stage
2045 * @plane: Pointer to drm plane
2046 * @state: Pointer to state to be destroyed
2047 * return: none
2048 */
2049static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2050 struct drm_plane_state *state)
2051{
2052 struct sde_plane_state *pstate = to_sde_plane_state(state);
2053 struct sde_plane_rot_state *rstate = &pstate->rot;
2054
2055 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2056 rstate->sequence_id,
2057 !!rstate->out_sbuf, !!rstate->rot_hw,
2058 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002059}
2060
2061/**
2062 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2063 * @plane: Pointer to drm plane
2064 * @new_state: Pointer to duplicated state
2065 * return: 0 if success; error code otherwise
2066 */
2067static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2068 struct drm_plane_state *new_state)
2069{
2070 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2071 struct sde_plane_rot_state *rstate = &pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002072 struct drm_crtc_state *cstate;
2073 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002074
2075 rstate->sequence_id++;
2076
2077 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2078 rstate->sequence_id,
2079 !!rstate->out_sbuf, !!rstate->rot_hw);
2080
Alan Kwongcdb2f282017-03-18 13:42:06 -07002081 cstate = _sde_plane_get_crtc_state(new_state);
2082 if (IS_ERR(cstate)) {
2083 ret = PTR_ERR(cstate);
2084 SDE_ERROR("invalid crtc state %d\n", ret);
2085 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002086 }
2087
Alan Kwongcdb2f282017-03-18 13:42:06 -07002088 if (rstate->rot_hw && cstate)
2089 sde_crtc_res_get(cstate, SDE_HW_BLK_ROT, (u64) rstate->in_fb);
2090 else if (rstate->rot_hw && !cstate)
2091 SDE_ERROR("plane%d.%d zombie rotator hw\n",
2092 plane->base.id, rstate->sequence_id);
2093
Alan Kwong4dd64c82017-02-04 18:41:51 -08002094 rstate->out_fb = NULL;
2095 rstate->out_fbo = NULL;
2096
2097 return 0;
2098}
2099
2100/**
2101 * sde_plane_rot_install_caps - install plane rotator capabilities
2102 * @plane: Pointer to drm plane
2103 * return: none
2104 */
2105static void sde_plane_rot_install_caps(struct drm_plane *plane)
2106{
2107 struct sde_plane *psde = to_sde_plane(plane);
2108 const struct sde_format_extended *format_list;
2109 struct sde_kms_info *info;
2110 struct sde_hw_rot *rot_hw;
2111 const char *downscale_caps;
2112
2113 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2114 !psde->catalog->rot_count)
2115 return;
2116
2117 if (psde->blob_rot_caps)
2118 return;
2119
2120 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2121 if (!info)
2122 return;
2123
2124 rot_hw = sde_hw_rot_get(NULL);
2125 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2126 !rot_hw->ops.get_downscale_caps) {
2127 SDE_ERROR("invalid rotator hw\n");
2128 goto error_rot;
2129 }
2130
2131 sde_kms_info_reset(info);
2132
2133 format_list = rot_hw->ops.get_format_caps(rot_hw);
2134 if (format_list) {
2135 sde_kms_info_start(info, "pixel_formats");
2136 while (format_list->fourcc_format) {
2137 sde_kms_info_append_format(info,
2138 format_list->fourcc_format,
2139 format_list->modifier);
2140 ++format_list;
2141 }
2142 sde_kms_info_stop(info);
2143 }
2144
2145 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2146 if (downscale_caps) {
2147 sde_kms_info_start(info, "downscale_ratios");
2148 sde_kms_info_append(info, downscale_caps);
2149 sde_kms_info_stop(info);
2150 }
2151
2152 if (rot_hw->ops.get_cache_size)
2153 sde_kms_info_add_keyint(info, "cache_size",
2154 rot_hw->ops.get_cache_size(rot_hw));
2155
Alan Kwong1a915802017-03-31 12:55:46 -07002156 if (rot_hw->ops.get_maxlinewidth)
2157 sde_kms_info_add_keyint(info, "max_linewidth",
2158 rot_hw->ops.get_maxlinewidth(rot_hw));
2159
Alan Kwong4dd64c82017-02-04 18:41:51 -08002160 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
2161 info->data, info->len, PLANE_PROP_ROT_CAPS_V1);
2162
2163 sde_hw_rot_put(rot_hw);
2164error_rot:
2165 kfree(info);
2166}
2167
2168/**
2169 * sde_plane_rot_install_properties - install plane rotator properties
2170 * @plane: Pointer to drm plane
2171 * @catalog: Pointer to mdss configuration
2172 * return: none
2173 */
2174static void sde_plane_rot_install_properties(struct drm_plane *plane,
2175 struct sde_mdss_cfg *catalog)
2176{
2177 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002178 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2179 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002180
2181 if (!plane || !psde) {
2182 SDE_ERROR("invalid plane\n");
2183 return;
2184 } else if (!catalog) {
2185 SDE_ERROR("invalid catalog\n");
2186 return;
2187 }
2188
2189 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2190 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2191 DRM_ROTATE_180 | DRM_ROTATE_270;
2192
2193 msm_property_install_rotation(&psde->property_info,
2194 supported_rotations, PLANE_PROP_ROTATION);
2195
2196 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2197 return;
2198
2199 msm_property_install_range(&psde->property_info, "rot_dst_x",
2200 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2201 msm_property_install_range(&psde->property_info, "rot_dst_y",
2202 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2203 msm_property_install_range(&psde->property_info, "rot_dst_w",
2204 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2205 msm_property_install_range(&psde->property_info, "rot_dst_h",
2206 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2207 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2208 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2209}
2210
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002211void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002212{
Clarence Ipcb410d42016-06-26 22:52:33 -04002213 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002214
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002215 if (!drm_state)
2216 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002217
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002218 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002219
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002220 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2221 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002222}
2223
2224int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2225{
2226 struct sde_plane_state *pstate[R_MAX];
2227 const struct drm_plane_state *drm_state[R_MAX];
2228 struct sde_rect src[R_MAX], dst[R_MAX];
2229 struct sde_plane *sde_plane[R_MAX];
2230 const struct sde_format *fmt[R_MAX];
2231 bool q16_data = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002232 int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
2233 bool parallel_fetch_qualified = true;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002234
2235 for (i = 0; i < R_MAX; i++) {
2236 const struct msm_format *msm_fmt;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002237 int width_threshold;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002238
2239 drm_state[i] = i ? plane->r1 : plane->r0;
2240 pstate[i] = to_sde_plane_state(drm_state[i]);
2241 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2242
2243 if (pstate[i] == NULL) {
2244 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2245 drm_state[i]->plane->base.id);
2246 return -EINVAL;
2247 }
2248
2249 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2250 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2251 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2252 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2253 drm_state[i]->crtc_h, !q16_data);
2254
2255 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2256 SDE_ERROR_PLANE(sde_plane[i],
2257 "scaling is not supported in multirect mode\n");
2258 return -EINVAL;
2259 }
2260
2261 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2262 fmt[i] = to_sde_format(msm_fmt);
2263 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2264 SDE_ERROR_PLANE(sde_plane[i],
2265 "Unsupported format for multirect mode\n");
2266 return -EINVAL;
2267 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002268
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002269 /**
2270 * SSPP PD_MEM is split half - one for each RECT.
2271 * Tiled formats need 5 lines of buffering while fetching
2272 * whereas linear formats need only 2 lines.
2273 * So we cannot support more than half of the supported SSPP
2274 * width for tiled formats.
2275 */
2276 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
2277 if (SDE_FORMAT_IS_UBWC(fmt[i]))
2278 width_threshold /= 2;
2279
2280 if (parallel_fetch_qualified && src[i].w > width_threshold)
2281 parallel_fetch_qualified = false;
2282
2283 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002284
2285 /* Validate RECT's and set the mode */
2286
2287 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002288 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002289 if (dst[R0].x <= dst[R1].x) {
2290 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2291 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2292 } else {
2293 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2294 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2295 }
2296
2297 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2298 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2299 goto done;
2300 }
2301
2302 /* TIME_MX Mode */
2303 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
2304 buffer_lines = 2 * fmt[R0]->tile_height;
2305
2306 if (dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) {
2307 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2308 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2309 } else if (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines) {
2310 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2311 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2312 } else {
2313 SDE_ERROR(
2314 "No multirect mode possible for the planes (%d - %d)\n",
2315 drm_state[R0]->plane->base.id,
2316 drm_state[R1]->plane->base.id);
2317 return -EINVAL;
2318 }
2319
2320 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2321 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2322done:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002323 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2324 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2325 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2326 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002327 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002328}
2329
Alan Kwong4dd64c82017-02-04 18:41:51 -08002330/**
2331 * sde_plane_get_ctl_flush - get control flush for the given plane
2332 * @plane: Pointer to drm plane structure
2333 * @ctl: Pointer to hardware control driver
2334 * @flush: Pointer to flush control word
2335 */
2336void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
2337 u32 *flush)
2338{
2339 struct sde_plane_state *pstate;
2340 struct sde_plane_rot_state *rstate;
2341 u32 bitmask;
2342
2343 if (!plane || !flush) {
2344 SDE_ERROR("invalid parameters\n");
2345 return;
2346 }
2347
2348 pstate = to_sde_plane_state(plane->state);
2349 rstate = &pstate->rot;
2350
2351 bitmask = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
2352
2353 if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
2354 ctl->ops.get_bitmask_rot)
2355 ctl->ops.get_bitmask_rot(ctl, &bitmask, rstate->rot_hw->idx);
2356
2357 *flush = bitmask;
2358}
2359
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002360static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002361 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002362{
2363 struct drm_framebuffer *fb = new_state->fb;
2364 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002365 struct sde_plane_rot_state *new_rstate;
2366 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002367
2368 if (!new_state->fb)
2369 return 0;
2370
Clarence Ip13a8cf42016-09-29 17:27:47 -04002371 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002372
2373 ret = sde_plane_rot_prepare_fb(plane, new_state);
2374 if (ret) {
2375 SDE_ERROR("failed to prepare rot framebuffer\n");
2376 return ret;
2377 }
2378
2379 new_rstate = &to_sde_plane_state(new_state)->rot;
2380
2381 ret = msm_framebuffer_prepare(new_rstate->out_fb, new_rstate->mmu_id);
2382 if (ret) {
2383 SDE_ERROR("failed to prepare framebuffer\n");
2384 return ret;
2385 }
2386
2387 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002388}
2389
2390static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002391 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002392{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002393 struct sde_plane *psde = to_sde_plane(plane);
2394 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002395
Alan Kwong4dd64c82017-02-04 18:41:51 -08002396 if (!old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002397 return;
2398
Alan Kwong4dd64c82017-02-04 18:41:51 -08002399 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2400
2401 old_rstate = &to_sde_plane_state(old_state)->rot;
2402
2403 msm_framebuffer_cleanup(old_rstate->out_fb, old_rstate->mmu_id);
2404
2405 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002406}
2407
Alan Kwong4dd64c82017-02-04 18:41:51 -08002408static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002409 struct drm_plane_state *state,
2410 struct drm_plane_state *old_state)
2411{
2412 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002413 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002414 struct sde_plane_rot_state *rstate = &pstate->rot;
2415 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2416 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002417
Dhaval Patel47302cf2016-08-18 15:04:28 -07002418 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002419 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002420 return;
2421
Clarence Ip282dad62016-09-27 17:07:35 -04002422 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2423 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002424 SDE_DEBUG_PLANE(psde,
2425 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002426 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002427 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002428 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002429 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002430 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2431 pstate->multirect_mode != old_pstate->multirect_mode) {
2432 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2433 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002434 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2435 rstate->out_src_h != old_rstate->out_src_h ||
2436 rstate->out_src_x != old_rstate->out_src_x ||
2437 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002438 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002439 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002440 } else if (state->crtc_w != old_state->crtc_w ||
2441 state->crtc_h != old_state->crtc_h ||
2442 state->crtc_x != old_state->crtc_x ||
2443 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002444 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002445 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002446 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2447 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2448 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2449 pstate->excl_rect.y != old_pstate->excl_rect.y) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07002450 SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002451 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002452 }
2453
Alan Kwong4dd64c82017-02-04 18:41:51 -08002454 fb = rstate->out_fb;
2455 old_fb = old_rstate->out_fb;
2456
2457 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002458 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002459 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002460 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002461 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002462 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002463 uint64_t *new_mods = fb->modifier;
2464 uint64_t *old_mods = old_fb->modifier;
2465 uint32_t *new_pitches = fb->pitches;
2466 uint32_t *old_pitches = old_fb->pitches;
2467 uint32_t *new_offset = fb->offsets;
2468 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002469 int i;
2470
Alan Kwong4dd64c82017-02-04 18:41:51 -08002471 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002472 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002473 SDE_DEBUG_PLANE(psde,
2474 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002475 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002476 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002477 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2478 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002479 break;
2480 }
2481 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002482 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002483 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002484 SDE_DEBUG_PLANE(psde,
2485 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002486 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002487 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002488 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002489 break;
2490 }
2491 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002492 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002493 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002494 SDE_DEBUG_PLANE(psde,
2495 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002496 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002497 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002498 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2499 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002500 break;
2501 }
2502 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002503 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002504}
2505
Alan Kwong4dd64c82017-02-04 18:41:51 -08002506static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002507 struct drm_plane_state *state)
2508{
Clarence Ipdedbba92016-09-27 17:43:10 -04002509 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04002510 struct sde_plane *psde;
2511 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002512 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002513 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002514 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04002515 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002516 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
2517 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04002518
2519 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002520 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2521 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04002522 ret = -EINVAL;
2523 goto exit;
2524 }
2525
2526 psde = to_sde_plane(plane);
2527 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002528 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04002529
2530 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002531 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002532 ret = -EINVAL;
2533 goto exit;
2534 }
2535
Clarence Ipdedbba92016-09-27 17:43:10 -04002536 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
2537 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04002538
2539 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002540 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2541 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002542 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
2543 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04002544
Dhaval Patel47302cf2016-08-18 15:04:28 -07002545 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
2546 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04002547
Dhaval Patel47302cf2016-08-18 15:04:28 -07002548 max_upscale = psde->pipe_sblk->maxupscale;
2549 max_downscale = psde->pipe_sblk->maxdwnscale;
2550 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04002551
Clarence Ip13a8cf42016-09-29 17:27:47 -04002552 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002553 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002554
Dhaval Patel47302cf2016-08-18 15:04:28 -07002555 if (!sde_plane_enabled(state))
2556 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04002557
Alan Kwong4dd64c82017-02-04 18:41:51 -08002558 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002559 "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 -08002560 plane->base.id, rstate->sequence_id,
2561 rstate->out_rotation,
2562 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002563 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002564 rstate->out_fb_modifier[0],
2565 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2566 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2567 state->crtc_w, state->crtc_h,
2568 state->crtc_x, state->crtc_y);
2569
Dhaval Patel47302cf2016-08-18 15:04:28 -07002570 fmt = to_sde_format(msm_framebuffer_format(state->fb));
2571
2572 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
2573
2574 if (SDE_FORMAT_IS_YUV(fmt) &&
2575 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04002576 !(psde->features & (BIT(SDE_SSPP_CSC)
2577 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002578 SDE_ERROR_PLANE(psde,
2579 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07002580 ret = -EINVAL;
2581
2582 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002583 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
2584 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07002585 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08002586 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
2587 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002588 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002589 src.x, src.y, src.w, src.h);
2590 ret = -E2BIG;
2591
2592 /* valid yuv image */
2593 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
2594 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002595 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002596 src.x, src.y, src.w, src.h);
2597 ret = -EINVAL;
2598
2599 /* min dst support */
2600 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002601 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002602 dst.x, dst.y, dst.w, dst.h);
2603 ret = -EINVAL;
2604
2605 /* decimation validation */
2606 } else if (deci_w || deci_h) {
2607 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
2608 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002609 SDE_ERROR_PLANE(psde,
2610 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002611 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002612 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002613 SDE_ERROR_PLANE(psde,
2614 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002615 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002616 }
2617
Dhaval Patel47302cf2016-08-18 15:04:28 -07002618 } else if (!(psde->features & SDE_SSPP_SCALER) &&
2619 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002620 SDE_ERROR_PLANE(psde,
2621 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002622 src.w, src.h, dst.w, dst.h);
2623 ret = -EINVAL;
2624
2625 /* check decimated source width */
2626 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002627 SDE_ERROR_PLANE(psde,
2628 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002629 src.w, src_deci_w, max_linewidth);
2630 ret = -E2BIG;
2631
2632 /* check max scaler capability */
2633 } else if (((src_deci_w * max_upscale) < dst.w) ||
2634 ((src_deci_h * max_upscale) < dst.h) ||
2635 ((dst.w * max_downscale) < src_deci_w) ||
2636 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002637 SDE_ERROR_PLANE(psde,
2638 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002639 src_deci_w, src_deci_h, dst.w, dst.h);
2640 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002641 }
2642
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002643 /* check excl rect configs */
2644 if (pstate->excl_rect.w && pstate->excl_rect.h) {
2645 struct sde_rect intersect;
2646
2647 /*
2648 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002649 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002650 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05002651 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002652 if (intersect.w != pstate->excl_rect.w ||
2653 intersect.h != pstate->excl_rect.h ||
2654 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002655 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07002656 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002657 pstate->excl_rect.x, pstate->excl_rect.y,
2658 pstate->excl_rect.w, pstate->excl_rect.h,
2659 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07002660 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002661 ret = -EINVAL;
2662 }
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07002663 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
2664 pstate->excl_rect.x, pstate->excl_rect.y,
2665 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002666 }
2667
Dhaval Patel47302cf2016-08-18 15:04:28 -07002668modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002669 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002670 _sde_plane_sspp_atomic_check_mode_changed(psde,
2671 state, plane->state);
2672exit:
2673 return ret;
2674}
2675
2676static int sde_plane_atomic_check(struct drm_plane *plane,
2677 struct drm_plane_state *state)
2678{
2679 int ret = 0;
2680 struct sde_plane *psde;
2681 struct sde_plane_state *pstate;
2682
2683 if (!plane || !state) {
2684 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2685 plane != 0, state != 0);
2686 ret = -EINVAL;
2687 goto exit;
2688 }
2689
2690 psde = to_sde_plane(plane);
2691 pstate = to_sde_plane_state(state);
2692
2693 SDE_DEBUG_PLANE(psde, "\n");
2694
2695 ret = sde_plane_rot_atomic_check(plane, state);
2696 if (ret)
2697 goto exit;
2698
2699 ret = sde_plane_sspp_atomic_check(plane, state);
2700
Clarence Ipdbde9832016-06-26 09:48:36 -04002701exit:
2702 return ret;
2703}
2704
Clarence Ipcae1bb62016-07-07 12:07:13 -04002705/**
2706 * sde_plane_flush - final plane operations before commit flush
2707 * @plane: Pointer to drm plane structure
2708 */
2709void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04002710{
Clarence Ipcae1bb62016-07-07 12:07:13 -04002711 struct sde_plane *psde;
2712
Clarence Ip13a8cf42016-09-29 17:27:47 -04002713 if (!plane) {
2714 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04002715 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002716 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04002717
2718 psde = to_sde_plane(plane);
2719
2720 /*
2721 * These updates have to be done immediately before the plane flush
2722 * timing, and may not be moved to the atomic_update/mode_set functions.
2723 */
2724 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05002725 /* force white frame with 100% alpha pipe output on error */
2726 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002727 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
2728 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04002729 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002730 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
2731 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
2732
Clarence Ip56902792017-03-17 15:22:07 -04002733 /* force black color fill during suspend */
2734 if (msm_is_suspend_state(plane->dev) && suspend_blank)
2735 _sde_plane_color_fill(psde, 0x0, 0x0);
2736
Clarence Ipcae1bb62016-07-07 12:07:13 -04002737 /* flag h/w flush complete */
2738 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04002739 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002740}
2741
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002742static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
2743 struct drm_plane_state *old_state)
2744{
2745 uint32_t nplanes, src_flags;
2746 struct sde_plane *psde;
2747 struct drm_plane_state *state;
2748 struct sde_plane_state *pstate;
2749 struct sde_plane_state *old_pstate;
2750 struct sde_plane_rot_state *rstate;
2751 const struct sde_format *fmt;
2752 struct drm_crtc *crtc;
2753 struct drm_framebuffer *fb;
2754 struct sde_rect src, dst;
2755 const struct sde_rect *crtc_roi;
2756 bool q16_data = true;
2757 int idx;
2758
2759 if (!plane) {
2760 SDE_ERROR("invalid plane\n");
2761 return -EINVAL;
2762 } else if (!plane->state) {
2763 SDE_ERROR("invalid plane state\n");
2764 return -EINVAL;
2765 } else if (!old_state) {
2766 SDE_ERROR("invalid old state\n");
2767 return -EINVAL;
2768 }
2769
2770 psde = to_sde_plane(plane);
2771 state = plane->state;
2772
2773 pstate = to_sde_plane_state(state);
2774 rstate = &pstate->rot;
2775
2776 old_pstate = to_sde_plane_state(old_state);
2777
2778 crtc = state->crtc;
2779 fb = rstate->out_fb;
2780 if (!crtc || !fb) {
2781 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
2782 crtc != 0, fb != 0);
2783 return -EINVAL;
2784 }
2785 fmt = to_sde_format(msm_framebuffer_format(fb));
2786 nplanes = fmt->num_planes;
2787
2788 SDE_DEBUG(
2789 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
2790 plane->base.id, rstate->sequence_id,
2791 rstate->out_fb_width, rstate->out_fb_height,
2792 (char *) &rstate->out_fb_pixel_format,
2793 rstate->out_fb_modifier[0],
2794 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2795 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2796 rstate->out_rotation,
2797 state->crtc_w, state->crtc_h,
2798 state->crtc_x, state->crtc_y);
2799
2800 /* force reprogramming of all the parameters, if the flag is set */
2801 if (psde->revalidate) {
2802 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
2803 plane->base.id);
2804 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2805 psde->revalidate = false;
2806 }
2807
2808 /* determine what needs to be refreshed */
2809 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
2810 switch (idx) {
2811 case PLANE_PROP_SCALER_V1:
2812 case PLANE_PROP_SCALER_V2:
2813 case PLANE_PROP_H_DECIMATE:
2814 case PLANE_PROP_V_DECIMATE:
2815 case PLANE_PROP_SRC_CONFIG:
2816 case PLANE_PROP_ZPOS:
2817 case PLANE_PROP_EXCL_RECT_V1:
2818 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2819 break;
2820 case PLANE_PROP_CSC_V1:
2821 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2822 break;
2823 case PLANE_PROP_COLOR_FILL:
2824 /* potentially need to refresh everything */
2825 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2826 break;
2827 case PLANE_PROP_ROTATION:
2828 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2829 break;
2830 case PLANE_PROP_INFO:
2831 case PLANE_PROP_ALPHA:
2832 case PLANE_PROP_INPUT_FENCE:
2833 case PLANE_PROP_BLEND_OP:
2834 /* no special action required */
2835 break;
2836 case PLANE_PROP_ROT_DST_X:
2837 case PLANE_PROP_ROT_DST_Y:
2838 case PLANE_PROP_ROT_DST_W:
2839 case PLANE_PROP_ROT_DST_H:
2840 /* handled by rotator atomic update */
2841 break;
2842 default:
2843 /* unknown property, refresh everything */
2844 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
2845 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
2846 break;
2847 }
2848 }
2849
2850 /**
2851 * since plane_atomic_check is invoked before crtc_atomic_check
2852 * in the commit sequence, all the parameters for updating the
2853 * plane dirty flag will not be available during
2854 * plane_atomic_check as some features params are updated
2855 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
2856 * before sspp update.
2857 */
2858 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
2859 old_state);
2860
2861 /* re-program the output rects always in the case of partial update */
2862 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
2863 if (!sde_kms_rect_is_null(crtc_roi))
2864 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2865
2866 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
2867 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
2868
2869 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
2870
2871 /* early out if nothing dirty */
2872 if (!pstate->dirty)
2873 return 0;
2874 pstate->pending = true;
2875
2876 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
2877 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
2878
2879 /* update roi config */
2880 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
2881 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2882 rstate->out_src_w, rstate->out_src_h, q16_data);
2883 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
2884 state->crtc_w, state->crtc_h, !q16_data);
2885
2886 SDE_DEBUG_PLANE(psde,
2887 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
2888 fb->base.id, src.x, src.y, src.w, src.h,
2889 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
2890 (char *)&fmt->base.pixel_format,
2891 SDE_FORMAT_IS_UBWC(fmt));
2892
2893 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
2894 BIT(SDE_DRM_DEINTERLACE)) {
2895 SDE_DEBUG_PLANE(psde, "deinterlace\n");
2896 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
2897 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
2898 src.h /= 2;
2899 src.y = DIV_ROUND_UP(src.y, 2);
2900 src.y &= ~0x1;
2901 }
2902
2903 /*
2904 * adjust layer mixer position of the sspp in the presence
2905 * of a partial update to the active lm origin
2906 */
2907 dst.x -= crtc_roi->x;
2908 dst.y -= crtc_roi->y;
2909
2910 psde->pipe_cfg.src_rect = src;
2911 psde->pipe_cfg.dst_rect = dst;
2912
2913 _sde_plane_setup_scaler(psde, fmt, pstate);
2914
2915 /* check for color fill */
2916 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
2917 PLANE_PROP_COLOR_FILL);
2918 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
2919 /* skip remaining processing on color fill */
2920 pstate->dirty = 0x0;
2921 } else if (psde->pipe_hw->ops.setup_rects) {
2922 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
2923 &psde->pipe_cfg,
2924 pstate->multirect_index);
2925 }
2926
2927 if (psde->pipe_hw->ops.setup_pe)
2928 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
2929 &psde->pixel_ext);
2930
2931 /**
2932 * when programmed in multirect mode, scalar block will be
2933 * bypassed. Still we need to update alpha and bitwidth
2934 * ONLY for RECT0
2935 */
2936 if (psde->pipe_hw->ops.setup_scaler &&
2937 pstate->multirect_index != SDE_SSPP_RECT_1)
2938 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
2939 &psde->pipe_cfg, &psde->pixel_ext,
2940 psde->scaler3_cfg);
2941
2942 /* update excl rect */
2943 if (psde->pipe_hw->ops.setup_excl_rect)
2944 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
2945 &pstate->excl_rect,
2946 pstate->multirect_index);
2947
2948 if (psde->pipe_hw->ops.setup_multirect)
2949 psde->pipe_hw->ops.setup_multirect(
2950 psde->pipe_hw,
2951 pstate->multirect_index,
2952 pstate->multirect_mode);
2953 }
2954
2955 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
2956 psde->pipe_hw->ops.setup_format) {
2957 src_flags = 0x0;
2958 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
2959 if (rstate->out_rotation & DRM_REFLECT_X)
2960 src_flags |= SDE_SSPP_FLIP_LR;
2961 if (rstate->out_rotation & DRM_REFLECT_Y)
2962 src_flags |= SDE_SSPP_FLIP_UD;
2963
2964 /* update format */
2965 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
2966 pstate->multirect_index);
2967
2968 if (psde->pipe_hw->ops.setup_sys_cache) {
2969 if (rstate->out_sbuf) {
2970 if (rstate->nplane < 2)
2971 pstate->sc_cfg.op_mode =
2972 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
2973 else if (rstate->out_xpos == 0)
2974 pstate->sc_cfg.op_mode =
2975 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
2976 else
2977 pstate->sc_cfg.op_mode =
2978 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
2979
2980 pstate->sc_cfg.rd_en = true;
2981 pstate->sc_cfg.rd_scid =
2982 rstate->rot_hw->caps->scid;
2983 pstate->sc_cfg.rd_noallocate = true;
2984 pstate->sc_cfg.rd_op_type =
2985 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
2986 } else {
2987 pstate->sc_cfg.op_mode =
2988 SDE_PIPE_SC_OP_MODE_OFFLINE;
2989 pstate->sc_cfg.rd_en = false;
2990 pstate->sc_cfg.rd_scid = 0;
2991 pstate->sc_cfg.rd_noallocate = false;
2992 pstate->sc_cfg.rd_op_type =
2993 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
2994 }
2995
2996 psde->pipe_hw->ops.setup_sys_cache(
2997 psde->pipe_hw, &pstate->sc_cfg);
2998 }
2999
3000 /* update csc */
3001 if (SDE_FORMAT_IS_YUV(fmt))
3002 _sde_plane_setup_csc(psde);
3003 else
3004 psde->csc_ptr = 0;
3005 }
3006
3007 sde_color_process_plane_setup(plane);
3008
3009 /* update sharpening */
3010 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3011 psde->pipe_hw->ops.setup_sharpening) {
3012 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3013 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3014 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3015 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3016
3017 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3018 &psde->sharp_cfg);
3019 }
3020
3021 _sde_plane_set_qos_lut(plane, fb);
3022 _sde_plane_set_danger_lut(plane, fb);
3023
3024 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3025 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3026 _sde_plane_set_ot_limit(plane, crtc);
3027 }
3028
3029 /* clear dirty */
3030 pstate->dirty = 0x0;
3031
3032 return 0;
3033}
3034
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003035static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003036 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003037{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003038 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003039 struct drm_plane_state *state;
3040 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003041 struct sde_plane_state *old_pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003042
Clarence Ip13a8cf42016-09-29 17:27:47 -04003043 if (!plane) {
3044 SDE_ERROR("invalid plane\n");
3045 return;
3046 } else if (!plane->state) {
3047 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003048 return;
3049 }
3050
Clarence Ip13a8cf42016-09-29 17:27:47 -04003051 psde = to_sde_plane(plane);
3052 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003053 state = plane->state;
3054 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003055 old_pstate = to_sde_plane_state(old_state);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003056
Clarence Ip13a8cf42016-09-29 17:27:47 -04003057 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003058
Alan Kwong4dd64c82017-02-04 18:41:51 -08003059 sde_plane_rot_atomic_update(plane, old_state);
3060
3061 if (!sde_plane_sspp_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04003062 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04003063 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003064 int ret;
3065
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003066 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003067 /* atomic_check should have ensured that this doesn't fail */
3068 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003069 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003070}
3071
Dhaval Patel47302cf2016-08-18 15:04:28 -07003072
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003073/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003074static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003075 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003076{
Clarence Ip5e2a9222016-06-26 22:38:24 -04003077 static const struct drm_prop_enum_list e_blend_op[] = {
3078 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3079 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3080 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3081 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3082 };
3083 static const struct drm_prop_enum_list e_src_config[] = {
3084 {SDE_DRM_DEINTERLACE, "deinterlace"}
3085 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003086 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003087 struct sde_format_extended *virt_format_list = NULL;
Dhaval Patel4e574842016-08-23 15:11:37 -07003088 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003089 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003090 int zpos_max = 255;
3091 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003092 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003093
Clarence Ip13a8cf42016-09-29 17:27:47 -04003094 if (!plane || !psde) {
3095 SDE_ERROR("invalid plane\n");
3096 return;
3097 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3098 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3099 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003100 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003101 } else if (!catalog) {
3102 SDE_ERROR("invalid catalog\n");
3103 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003104 }
3105
Alan Kwong4dd64c82017-02-04 18:41:51 -08003106 psde->catalog = catalog;
3107
Clarence Ipc47a0692016-10-11 10:54:17 -04003108 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003109 if (catalog->mixer_count && catalog->mixer &&
3110 catalog->mixer[0].sblk->maxblendstages) {
3111 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3112 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3113 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3114 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003115 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3116 /* reserve zpos == 0 for primary planes */
3117 zpos_def = drm_plane_index(plane) + 1;
3118 }
3119
3120 msm_property_install_range(&psde->property_info, "zpos",
3121 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003122
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003123 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003124 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003125
Dhaval Patel47302cf2016-08-18 15:04:28 -07003126 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003127 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003128 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003129
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003130 if (!master_plane_id) {
3131 if (psde->pipe_sblk->maxhdeciexp) {
3132 msm_property_install_range(&psde->property_info,
3133 "h_decimate", 0x0, 0,
3134 psde->pipe_sblk->maxhdeciexp, 0,
3135 PLANE_PROP_H_DECIMATE);
3136 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003137
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003138 if (psde->pipe_sblk->maxvdeciexp) {
3139 msm_property_install_range(&psde->property_info,
3140 "v_decimate", 0x0, 0,
3141 psde->pipe_sblk->maxvdeciexp, 0,
3142 PLANE_PROP_V_DECIMATE);
3143 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003144
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003145 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
3146 msm_property_install_volatile_range(
3147 &psde->property_info, "scaler_v2",
3148 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3149 msm_property_install_blob(&psde->property_info,
3150 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3151 msm_property_install_blob(&psde->property_info,
3152 "lut_cir", 0,
3153 PLANE_PROP_SCALER_LUT_CIR);
3154 msm_property_install_blob(&psde->property_info,
3155 "lut_sep", 0,
3156 PLANE_PROP_SCALER_LUT_SEP);
3157 } else if (psde->features & SDE_SSPP_SCALER) {
3158 msm_property_install_volatile_range(
3159 &psde->property_info, "scaler_v1", 0x0,
3160 0, ~0, 0, PLANE_PROP_SCALER_V1);
3161 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003162
Dhaval Patel0aee0972017-02-08 19:00:58 -08003163 if (psde->features & BIT(SDE_SSPP_CSC) ||
3164 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003165 msm_property_install_volatile_range(
3166 &psde->property_info, "csc_v1", 0x0,
3167 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003168
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003169 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3170 snprintf(feature_name, sizeof(feature_name), "%s%d",
3171 "SDE_SSPP_HUE_V",
3172 psde->pipe_sblk->hsic_blk.version >> 16);
3173 msm_property_install_range(&psde->property_info,
3174 feature_name, 0, 0, 0xFFFFFFFF, 0,
3175 PLANE_PROP_HUE_ADJUST);
3176 snprintf(feature_name, sizeof(feature_name), "%s%d",
3177 "SDE_SSPP_SATURATION_V",
3178 psde->pipe_sblk->hsic_blk.version >> 16);
3179 msm_property_install_range(&psde->property_info,
3180 feature_name, 0, 0, 0xFFFFFFFF, 0,
3181 PLANE_PROP_SATURATION_ADJUST);
3182 snprintf(feature_name, sizeof(feature_name), "%s%d",
3183 "SDE_SSPP_VALUE_V",
3184 psde->pipe_sblk->hsic_blk.version >> 16);
3185 msm_property_install_range(&psde->property_info,
3186 feature_name, 0, 0, 0xFFFFFFFF, 0,
3187 PLANE_PROP_VALUE_ADJUST);
3188 snprintf(feature_name, sizeof(feature_name), "%s%d",
3189 "SDE_SSPP_CONTRAST_V",
3190 psde->pipe_sblk->hsic_blk.version >> 16);
3191 msm_property_install_range(&psde->property_info,
3192 feature_name, 0, 0, 0xFFFFFFFF, 0,
3193 PLANE_PROP_CONTRAST_ADJUST);
3194 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003195 }
3196
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003197 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3198 msm_property_install_volatile_range(&psde->property_info,
3199 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3200
Alan Kwong4dd64c82017-02-04 18:41:51 -08003201 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003202
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003203 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003204 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003205
Dhaval Patel47302cf2016-08-18 15:04:28 -07003206 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3207 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3208
3209 if (psde->pipe_hw->ops.setup_solidfill)
3210 msm_property_install_range(&psde->property_info, "color_fill",
3211 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3212
Dhaval Patel4e574842016-08-23 15:11:37 -07003213 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003214 if (!info) {
3215 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003216 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003217 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003218
3219 msm_property_install_blob(&psde->property_info, "capabilities",
3220 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3221 sde_kms_info_reset(info);
3222
Clarence Ipea3d6262016-07-15 16:20:11 -04003223 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003224
3225 if (master_plane_id) {
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003226 int index, array_size;
3227
3228 array_size = ARRAY_SIZE(plane_formats)
3229 + ARRAY_SIZE(rgb_10bit_formats);
3230 virt_format_list = kcalloc(array_size,
3231 sizeof(struct sde_format_extended), GFP_KERNEL);
3232 if (!virt_format_list) {
3233 SDE_ERROR(
3234 "failed to allocate virtual pipe format list\n");
3235 return;
3236 }
3237
3238 index = sde_copy_formats(virt_format_list, array_size,
3239 0, plane_formats, ARRAY_SIZE(plane_formats));
3240 sde_copy_formats(virt_format_list, array_size,
3241 index, rgb_10bit_formats,
3242 ARRAY_SIZE(rgb_10bit_formats));
3243
3244 format_list = virt_format_list;
3245
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003246 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003247 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003248 }
3249
Clarence Ipea3d6262016-07-15 16:20:11 -04003250 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003251 sde_kms_info_start(info, "pixel_formats");
3252 while (format_list->fourcc_format) {
3253 sde_kms_info_append_format(info,
3254 format_list->fourcc_format,
3255 format_list->modifier);
3256 ++format_list;
3257 }
3258 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003259 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003260
3261 sde_kms_info_add_keyint(info, "max_linewidth",
3262 psde->pipe_sblk->maxlinewidth);
3263 sde_kms_info_add_keyint(info, "max_upscale",
3264 psde->pipe_sblk->maxupscale);
3265 sde_kms_info_add_keyint(info, "max_downscale",
3266 psde->pipe_sblk->maxdwnscale);
3267 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3268 psde->pipe_sblk->maxhdeciexp);
3269 sde_kms_info_add_keyint(info, "max_vertical_deci",
3270 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07003271 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
3272 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07003273 msm_property_set_blob(&psde->property_info, &psde->blob_info,
3274 info->data, info->len, PLANE_PROP_INFO);
3275
3276 kfree(info);
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003277 kfree(virt_format_list);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003278
3279 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3280 snprintf(feature_name, sizeof(feature_name), "%s%d",
3281 "SDE_SSPP_SKIN_COLOR_V",
3282 psde->pipe_sblk->memcolor_blk.version >> 16);
3283 msm_property_install_blob(&psde->property_info, feature_name, 0,
3284 PLANE_PROP_SKIN_COLOR);
3285 snprintf(feature_name, sizeof(feature_name), "%s%d",
3286 "SDE_SSPP_SKY_COLOR_V",
3287 psde->pipe_sblk->memcolor_blk.version >> 16);
3288 msm_property_install_blob(&psde->property_info, feature_name, 0,
3289 PLANE_PROP_SKY_COLOR);
3290 snprintf(feature_name, sizeof(feature_name), "%s%d",
3291 "SDE_SSPP_FOLIAGE_COLOR_V",
3292 psde->pipe_sblk->memcolor_blk.version >> 16);
3293 msm_property_install_blob(&psde->property_info, feature_name, 0,
3294 PLANE_PROP_FOLIAGE_COLOR);
3295 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003296}
3297
Clarence Ip5fc00c52016-09-23 15:03:34 -04003298static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
3299{
3300 struct sde_drm_csc_v1 csc_v1;
3301 int i;
3302
3303 if (!psde) {
3304 SDE_ERROR("invalid plane\n");
3305 return;
3306 }
3307
3308 psde->csc_usr_ptr = NULL;
3309 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003310 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003311 return;
3312 }
3313
3314 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003315 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003316 return;
3317 }
3318
Clarence Ipb43d4592016-09-08 14:21:35 -04003319 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04003320 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
3321 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
3322 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
3323 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
3324 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
3325 }
3326 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
3327 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
3328 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
3329 }
3330 psde->csc_usr_ptr = &psde->csc_cfg;
3331}
3332
Clarence Ipb43d4592016-09-08 14:21:35 -04003333static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
3334{
3335 struct sde_drm_scaler_v1 scale_v1;
3336 struct sde_hw_pixel_ext *pe;
3337 int i;
3338
3339 if (!psde) {
3340 SDE_ERROR("invalid plane\n");
3341 return;
3342 }
3343
3344 psde->pixel_ext_usr = false;
3345 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003346 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003347 return;
3348 }
3349
3350 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003351 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003352 return;
3353 }
3354
3355 /* populate from user space */
3356 pe = &(psde->pixel_ext);
3357 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3358 for (i = 0; i < SDE_MAX_PLANES; i++) {
3359 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
3360 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
3361 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
3362 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
3363
3364 pe->horz_filter[i] = scale_v1.horz_filter[i];
3365 pe->vert_filter[i] = scale_v1.vert_filter[i];
3366 }
3367 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003368 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
3369 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
3370 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
3371 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
3372 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003373
abeykun41060122016-11-28 13:02:01 -05003374 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
3375 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
3376 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
3377 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
3378 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003379 }
abeykun41060122016-11-28 13:02:01 -05003380
Clarence Ipb43d4592016-09-08 14:21:35 -04003381 psde->pixel_ext_usr = true;
3382
Clarence Ip13a8cf42016-09-29 17:27:47 -04003383 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003384}
3385
abeykun48f407a2016-08-25 12:06:44 -04003386static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
3387 struct sde_plane_state *pstate, void *usr)
3388{
3389 struct sde_drm_scaler_v2 scale_v2;
3390 struct sde_hw_pixel_ext *pe;
3391 int i;
3392 struct sde_hw_scaler3_cfg *cfg;
3393
3394 if (!psde) {
3395 SDE_ERROR("invalid plane\n");
3396 return;
3397 }
3398
3399 cfg = psde->scaler3_cfg;
3400 psde->pixel_ext_usr = false;
3401 if (!usr) {
3402 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3403 return;
3404 }
3405
3406 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
3407 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
3408 return;
3409 }
3410
3411 /* populate from user space */
3412 pe = &(psde->pixel_ext);
3413 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3414 cfg->enable = scale_v2.enable;
3415 cfg->dir_en = scale_v2.dir_en;
3416 for (i = 0; i < SDE_MAX_PLANES; i++) {
3417 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
3418 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
3419 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
3420 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
3421
3422 cfg->preload_x[i] = scale_v2.preload_x[i];
3423 cfg->preload_y[i] = scale_v2.preload_y[i];
3424 cfg->src_width[i] = scale_v2.src_width[i];
3425 cfg->src_height[i] = scale_v2.src_height[i];
3426 }
3427 cfg->dst_width = scale_v2.dst_width;
3428 cfg->dst_height = scale_v2.dst_height;
3429
3430 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
3431 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
3432 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
3433 cfg->blend_cfg = scale_v2.blend_cfg;
3434
3435 cfg->lut_flag = scale_v2.lut_flag;
3436 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
3437 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
3438 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
3439 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
3440 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
3441
3442 cfg->de.enable = scale_v2.de.enable;
3443 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
3444 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
3445 cfg->de.clip = scale_v2.de.clip;
3446 cfg->de.limit = scale_v2.de.limit;
3447 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
3448 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
3449 cfg->de.thr_low = scale_v2.de.thr_low;
3450 cfg->de.thr_high = scale_v2.de.thr_high;
3451 cfg->de.prec_shift = scale_v2.de.prec_shift;
3452 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
3453 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
3454 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
3455 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
3456 }
3457 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003458 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
3459 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
3460 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
3461 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
3462 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04003463
abeykun41060122016-11-28 13:02:01 -05003464 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
3465 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
3466 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
3467 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
3468 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04003469 }
3470 psde->pixel_ext_usr = true;
3471
3472 SDE_DEBUG_PLANE(psde, "user property data copied\n");
3473}
3474
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003475static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
3476 struct sde_plane_state *pstate, void *usr_ptr)
3477{
3478 struct drm_clip_rect excl_rect_v1;
3479
3480 if (!psde) {
3481 SDE_ERROR("invalid plane\n");
3482 return;
3483 }
3484
3485 if (!usr_ptr) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003486 SDE_DEBUG_PLANE(psde, "invalid excl_rect user data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003487 return;
3488 }
3489
3490 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003491 SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003492 return;
3493 }
3494
3495 /* populate from user space */
3496 pstate->excl_rect.x = excl_rect_v1.x1;
3497 pstate->excl_rect.y = excl_rect_v1.y1;
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003498 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
3499 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
3500
3501 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3502 pstate->excl_rect.x, pstate->excl_rect.y,
3503 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003504}
3505
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003506static int sde_plane_atomic_set_property(struct drm_plane *plane,
3507 struct drm_plane_state *state, struct drm_property *property,
3508 uint64_t val)
3509{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003510 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003511 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003512 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003513
Clarence Ip13a8cf42016-09-29 17:27:47 -04003514 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003515
3516 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003517 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003518 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003519 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003520 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04003521 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003522 ret = msm_property_atomic_set(&psde->property_info,
3523 pstate->property_values, pstate->property_blobs,
3524 property, val);
3525 if (!ret) {
3526 idx = msm_property_index(&psde->property_info,
3527 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003528 switch (idx) {
3529 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04003530 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003531 break;
3532 case PLANE_PROP_CSC_V1:
3533 _sde_plane_set_csc_v1(psde, (void *)val);
3534 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04003535 case PLANE_PROP_SCALER_V1:
3536 _sde_plane_set_scaler_v1(psde, (void *)val);
3537 break;
abeykun48f407a2016-08-25 12:06:44 -04003538 case PLANE_PROP_SCALER_V2:
3539 _sde_plane_set_scaler_v2(psde, pstate,
3540 (void *)val);
3541 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003542 case PLANE_PROP_EXCL_RECT_V1:
3543 _sde_plane_set_excl_rect_v1(psde, pstate,
3544 (void *)val);
3545 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04003546 default:
3547 /* nothing to do */
3548 break;
3549 }
Clarence Ipe78efb72016-06-24 18:35:21 -04003550 }
3551 }
3552
Alan Kwong4dd64c82017-02-04 18:41:51 -08003553 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
3554 property->name, property->base.id, val, ret);
3555
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003556 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003557}
3558
3559static int sde_plane_set_property(struct drm_plane *plane,
3560 struct drm_property *property, uint64_t val)
3561{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003562 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003563
Clarence Ipae4e60c2016-06-26 22:44:04 -04003564 return sde_plane_atomic_set_property(plane,
3565 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003566}
3567
3568static int sde_plane_atomic_get_property(struct drm_plane *plane,
3569 const struct drm_plane_state *state,
3570 struct drm_property *property, uint64_t *val)
3571{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003572 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003573 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04003574 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003575
Clarence Ipaa0faf42016-05-30 12:07:48 -04003576 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003577 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003578 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003579 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003580 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003581 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003582 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003583 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003584 ret = msm_property_atomic_get(&psde->property_info,
3585 pstate->property_values, pstate->property_blobs,
3586 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04003587 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003588
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003589 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003590}
3591
3592static void sde_plane_destroy(struct drm_plane *plane)
3593{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003594 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003595
Clarence Ip13a8cf42016-09-29 17:27:47 -04003596 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003597
Clarence Ip13a8cf42016-09-29 17:27:47 -04003598 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04003599 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3600
Dhaval Patel4e574842016-08-23 15:11:37 -07003601 if (psde->blob_info)
3602 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003603 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04003604 mutex_destroy(&psde->lock);
3605
Clarence Ip4ce59322016-06-26 22:27:51 -04003606 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003607
Clarence Ip4ce59322016-06-26 22:27:51 -04003608 /* this will destroy the states as well */
3609 drm_plane_cleanup(plane);
3610
Clarence Ip4c1d9772016-06-26 09:35:38 -04003611 if (psde->pipe_hw)
3612 sde_hw_sspp_destroy(psde->pipe_hw);
3613
Clarence Ip4ce59322016-06-26 22:27:51 -04003614 kfree(psde);
3615 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003616}
3617
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003618static void sde_plane_destroy_state(struct drm_plane *plane,
3619 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003620{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003621 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04003622 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003623
Clarence Ipae4e60c2016-06-26 22:44:04 -04003624 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003625 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3626 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003627 return;
3628 }
3629
Clarence Ipaa0faf42016-05-30 12:07:48 -04003630 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04003631 pstate = to_sde_plane_state(state);
3632
Clarence Ip13a8cf42016-09-29 17:27:47 -04003633 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003634
Alan Kwong4dd64c82017-02-04 18:41:51 -08003635 sde_plane_rot_destroy_state(plane, &pstate->base);
3636
Clarence Ipe78efb72016-06-24 18:35:21 -04003637 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003638 if (state->fb)
3639 drm_framebuffer_unreference(state->fb);
3640
Clarence Ipae4e60c2016-06-26 22:44:04 -04003641 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003642 if (pstate->input_fence)
3643 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003644
Clarence Ipaa0faf42016-05-30 12:07:48 -04003645 /* destroy value helper */
3646 msm_property_destroy_state(&psde->property_info, pstate,
3647 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003648}
3649
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003650static struct drm_plane_state *
3651sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003652{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003653 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003654 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04003655 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04003656 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003657
Clarence Ip13a8cf42016-09-29 17:27:47 -04003658 if (!plane) {
3659 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003660 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003661 } else if (!plane->state) {
3662 SDE_ERROR("invalid plane state\n");
3663 return NULL;
3664 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003665
Clarence Ip730e7192016-06-26 22:45:09 -04003666 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003667 psde = to_sde_plane(plane);
3668 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003669 if (!pstate) {
3670 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003671 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003672 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003673
Clarence Ip13a8cf42016-09-29 17:27:47 -04003674 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003675
3676 /* duplicate value helper */
3677 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
3678 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003679
Clarence Ip17e908b2016-09-29 15:58:00 -04003680 /* clear out any input fence */
3681 pstate->input_fence = 0;
3682 input_fence_default = msm_property_get_default(
3683 &psde->property_info, PLANE_PROP_INPUT_FENCE);
3684 msm_property_set_property(&psde->property_info, pstate->property_values,
3685 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003686
Clarence Ip282dad62016-09-27 17:07:35 -04003687 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04003688 pstate->pending = false;
3689
Alan Kwongcdb2f282017-03-18 13:42:06 -07003690 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
3691
Alan Kwong4dd64c82017-02-04 18:41:51 -08003692 sde_plane_rot_duplicate_state(plane, &pstate->base);
3693
Clarence Ip730e7192016-06-26 22:45:09 -04003694 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003695}
3696
3697static void sde_plane_reset(struct drm_plane *plane)
3698{
Clarence Ipae4e60c2016-06-26 22:44:04 -04003699 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003700 struct sde_plane_state *pstate;
3701
Clarence Ipae4e60c2016-06-26 22:44:04 -04003702 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003703 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003704 return;
3705 }
3706
Clarence Ip730e7192016-06-26 22:45:09 -04003707 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003708 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003709
Clarence Ipae4e60c2016-06-26 22:44:04 -04003710 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04003711 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04003712 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003713 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04003714 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003715
Clarence Ipaa0faf42016-05-30 12:07:48 -04003716 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003717 if (!pstate) {
3718 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003719 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003720 }
Clarence Ip730e7192016-06-26 22:45:09 -04003721
Clarence Ipaa0faf42016-05-30 12:07:48 -04003722 /* reset value helper */
3723 msm_property_reset_state(&psde->property_info, pstate,
3724 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003725
3726 pstate->base.plane = plane;
3727
3728 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003729}
3730
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003731#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04003732static ssize_t _sde_plane_danger_read(struct file *file,
3733 char __user *buff, size_t count, loff_t *ppos)
3734{
3735 struct sde_kms *kms = file->private_data;
3736 struct sde_mdss_cfg *cfg = kms->catalog;
3737 int len = 0;
3738 char buf[40] = {'\0'};
3739
3740 if (!cfg)
3741 return -ENODEV;
3742
3743 if (*ppos)
3744 return 0; /* the end */
3745
3746 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
3747 if (len < 0 || len >= sizeof(buf))
3748 return 0;
3749
3750 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
3751 return -EFAULT;
3752
3753 *ppos += len; /* increase offset */
3754
3755 return len;
3756}
3757
3758static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
3759{
3760 struct drm_plane *plane;
3761
3762 drm_for_each_plane(plane, kms->dev) {
3763 if (plane->fb && plane->state) {
3764 sde_plane_danger_signal_ctrl(plane, enable);
3765 SDE_DEBUG("plane:%d img:%dx%d ",
3766 plane->base.id, plane->fb->width,
3767 plane->fb->height);
3768 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
3769 plane->state->src_x >> 16,
3770 plane->state->src_y >> 16,
3771 plane->state->src_w >> 16,
3772 plane->state->src_h >> 16,
3773 plane->state->crtc_x, plane->state->crtc_y,
3774 plane->state->crtc_w, plane->state->crtc_h);
3775 } else {
3776 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
3777 }
3778 }
3779}
3780
3781static ssize_t _sde_plane_danger_write(struct file *file,
3782 const char __user *user_buf, size_t count, loff_t *ppos)
3783{
3784 struct sde_kms *kms = file->private_data;
3785 struct sde_mdss_cfg *cfg = kms->catalog;
3786 int disable_panic;
3787 char buf[10];
3788
3789 if (!cfg)
3790 return -EFAULT;
3791
3792 if (count >= sizeof(buf))
3793 return -EFAULT;
3794
3795 if (copy_from_user(buf, user_buf, count))
3796 return -EFAULT;
3797
3798 buf[count] = 0; /* end of string */
3799
3800 if (kstrtoint(buf, 0, &disable_panic))
3801 return -EFAULT;
3802
3803 if (disable_panic) {
3804 /* Disable panic signal for all active pipes */
3805 SDE_DEBUG("Disabling danger:\n");
3806 _sde_plane_set_danger_state(kms, false);
3807 kms->has_danger_ctrl = false;
3808 } else {
3809 /* Enable panic signal for all active pipes */
3810 SDE_DEBUG("Enabling danger:\n");
3811 kms->has_danger_ctrl = true;
3812 _sde_plane_set_danger_state(kms, true);
3813 }
3814
3815 return count;
3816}
3817
3818static const struct file_operations sde_plane_danger_enable = {
3819 .open = simple_open,
3820 .read = _sde_plane_danger_read,
3821 .write = _sde_plane_danger_write,
3822};
3823
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003824static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04003825{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003826 struct sde_plane *psde;
3827 struct sde_kms *kms;
3828 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04003829 const struct sde_sspp_sub_blks *sblk = 0;
3830 const struct sde_sspp_cfg *cfg = 0;
3831
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003832 if (!plane || !plane->dev) {
3833 SDE_ERROR("invalid arguments\n");
3834 return -EINVAL;
3835 }
3836
3837 priv = plane->dev->dev_private;
3838 if (!priv || !priv->kms) {
3839 SDE_ERROR("invalid KMS reference\n");
3840 return -EINVAL;
3841 }
3842
3843 kms = to_sde_kms(priv->kms);
3844 psde = to_sde_plane(plane);
3845
Clarence Ip4ce59322016-06-26 22:27:51 -04003846 if (psde && psde->pipe_hw)
3847 cfg = psde->pipe_hw->cap;
3848 if (cfg)
3849 sblk = cfg->sblk;
3850
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003851 if (!sblk)
3852 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04003853
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003854 /* create overall sub-directory for the pipe */
3855 psde->debugfs_root =
3856 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07003857 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04003858
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003859 if (!psde->debugfs_root)
3860 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04003861
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003862 /* don't error check these */
3863 debugfs_create_x32("features", 0644,
3864 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003865
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003866 /* add register dump support */
3867 sde_debugfs_setup_regset32(&psde->debugfs_src,
3868 sblk->src_blk.base + cfg->base,
3869 sblk->src_blk.len,
3870 kms);
3871 sde_debugfs_create_regset32("src_blk", 0444,
3872 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003873
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003874 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
3875 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
3876 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
3877 sblk->scaler_blk.base + cfg->base,
3878 sblk->scaler_blk.len,
3879 kms);
3880 sde_debugfs_create_regset32("scaler_blk", 0444,
3881 psde->debugfs_root,
3882 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07003883 debugfs_create_bool("default_scaling",
3884 0644,
3885 psde->debugfs_root,
3886 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04003887 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003888
3889 if (cfg->features & BIT(SDE_SSPP_CSC) ||
3890 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
3891 sde_debugfs_setup_regset32(&psde->debugfs_csc,
3892 sblk->csc_blk.base + cfg->base,
3893 sblk->csc_blk.len,
3894 kms);
3895 sde_debugfs_create_regset32("csc_blk", 0444,
3896 psde->debugfs_root, &psde->debugfs_csc);
3897 }
3898
3899 debugfs_create_u32("xin_id",
3900 0444,
3901 psde->debugfs_root,
3902 (u32 *) &cfg->xin_id);
3903 debugfs_create_u32("clk_ctrl",
3904 0444,
3905 psde->debugfs_root,
3906 (u32 *) &cfg->clk_ctrl);
3907 debugfs_create_x32("creq_vblank",
3908 0644,
3909 psde->debugfs_root,
3910 (u32 *) &sblk->creq_vblank);
3911 debugfs_create_x32("danger_vblank",
3912 0644,
3913 psde->debugfs_root,
3914 (u32 *) &sblk->danger_vblank);
3915
3916 debugfs_create_file("disable_danger",
3917 0644,
3918 psde->debugfs_root,
3919 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003920 debugfs_create_u32("sbuf_mode",
3921 0644,
3922 psde->debugfs_root, &psde->sbuf_mode);
3923 debugfs_create_u32("sbuf_writeback",
3924 0644,
3925 psde->debugfs_root,
3926 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003927
3928 return 0;
3929}
3930
3931static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3932{
3933 struct sde_plane *psde;
3934
3935 if (!plane)
3936 return;
3937 psde = to_sde_plane(plane);
3938
3939 debugfs_remove_recursive(psde->debugfs_root);
3940}
3941#else
3942static int _sde_plane_init_debugfs(struct drm_plane *plane)
3943{
3944 return 0;
3945}
3946static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3947{
3948}
3949#endif
3950
3951static int sde_plane_late_register(struct drm_plane *plane)
3952{
3953 return _sde_plane_init_debugfs(plane);
3954}
3955
3956static void sde_plane_early_unregister(struct drm_plane *plane)
3957{
3958 _sde_plane_destroy_debugfs(plane);
3959}
3960
3961static const struct drm_plane_funcs sde_plane_funcs = {
3962 .update_plane = drm_atomic_helper_update_plane,
3963 .disable_plane = drm_atomic_helper_disable_plane,
3964 .destroy = sde_plane_destroy,
3965 .set_property = sde_plane_set_property,
3966 .atomic_set_property = sde_plane_atomic_set_property,
3967 .atomic_get_property = sde_plane_atomic_get_property,
3968 .reset = sde_plane_reset,
3969 .atomic_duplicate_state = sde_plane_duplicate_state,
3970 .atomic_destroy_state = sde_plane_destroy_state,
3971 .late_register = sde_plane_late_register,
3972 .early_unregister = sde_plane_early_unregister,
3973};
3974
3975static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
3976 .prepare_fb = sde_plane_prepare_fb,
3977 .cleanup_fb = sde_plane_cleanup_fb,
3978 .atomic_check = sde_plane_atomic_check,
3979 .atomic_update = sde_plane_atomic_update,
3980};
3981
3982enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
3983{
3984 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
3985}
3986
3987bool is_sde_plane_virtual(struct drm_plane *plane)
3988{
3989 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04003990}
3991
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003992/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04003993struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04003994 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003995 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003996{
3997 struct drm_plane *plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003998 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003999 struct sde_format_extended *virt_format_list = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004000 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004001 struct msm_drm_private *priv;
4002 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004003 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04004004 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004005
4006 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004007 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004008 goto exit;
4009 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004010
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004011 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004012 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004013 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004014 goto exit;
4015 }
4016
4017 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004018 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004019 goto exit;
4020 }
4021 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004022
Clarence Ip4c1d9772016-06-26 09:35:38 -04004023 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004024 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004025 goto exit;
4026 }
4027
Clarence Ip4ce59322016-06-26 22:27:51 -04004028 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004029 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4030 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004031 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004032 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004033 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004034 }
4035
Clarence Ip4c1d9772016-06-26 09:35:38 -04004036 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004037 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004038 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04004039 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004040 psde->is_virtual = (master_plane_id != 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004041
Clarence Ip4c1d9772016-06-26 09:35:38 -04004042 /* initialize underlying h/w driver */
4043 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
4044 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004045 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004046 ret = PTR_ERR(psde->pipe_hw);
4047 goto clean_plane;
4048 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004049 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004050 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004051 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004052
4053 /* cache features mask for later */
4054 psde->features = psde->pipe_hw->cap->features;
4055 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004056 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004057 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004058 goto clean_sspp;
4059 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004060
abeykun48f407a2016-08-25 12:06:44 -04004061 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
4062 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
4063 GFP_KERNEL);
4064 if (!psde->scaler3_cfg) {
4065 SDE_ERROR("[%u]failed to allocate scale struct\n",
4066 pipe);
4067 ret = -ENOMEM;
4068 goto clean_sspp;
4069 }
4070 }
4071
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004072 format_list = psde->pipe_sblk->format_list;
4073
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004074 if (master_plane_id) {
4075 int index, array_size;
4076
4077 array_size = ARRAY_SIZE(plane_formats)
4078 + ARRAY_SIZE(rgb_10bit_formats);
4079 virt_format_list = kcalloc(array_size,
4080 sizeof(struct sde_format_extended),
4081 GFP_KERNEL);
4082 if (!virt_format_list) {
4083 SDE_ERROR(
4084 "failed to allocate virtual pipe format list\n");
4085 goto clean_sspp;
4086 }
4087
4088 index = sde_copy_formats(virt_format_list, array_size,
4089 0, plane_formats, ARRAY_SIZE(plane_formats));
4090 sde_copy_formats(virt_format_list, array_size,
4091 index, rgb_10bit_formats,
4092 ARRAY_SIZE(rgb_10bit_formats));
4093
4094 format_list = virt_format_list;
4095 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004096
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004097 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004098 psde->formats,
4099 0,
4100 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004101
Clarence Ip4c1d9772016-06-26 09:35:38 -04004102 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004103 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004104 goto clean_sspp;
4105 }
4106
4107 if (psde->features & BIT(SDE_SSPP_CURSOR))
4108 type = DRM_PLANE_TYPE_CURSOR;
4109 else if (primary_plane)
4110 type = DRM_PLANE_TYPE_PRIMARY;
4111 else
4112 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07004113 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
4114 psde->formats, psde->nformats,
4115 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004116 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04004117 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004118
Clarence Ip4c1d9772016-06-26 09:35:38 -04004119 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004120 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004121
Clarence Ipaa0faf42016-05-30 12:07:48 -04004122 msm_property_init(&psde->property_info, &plane->base, dev,
4123 priv->plane_property, psde->property_data,
4124 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
4125 sizeof(struct sde_plane_state));
4126
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004127 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004128
Clarence Ip4ce59322016-06-26 22:27:51 -04004129 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004130 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004131
Clarence Ip730e7192016-06-26 22:45:09 -04004132 mutex_init(&psde->lock);
4133
Dhaval Patel82c8dbc2017-02-18 23:15:10 -08004134 SDE_DEBUG("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004135 return plane;
4136
Clarence Ip4c1d9772016-06-26 09:35:38 -04004137clean_sspp:
4138 if (psde && psde->pipe_hw)
4139 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04004140
4141 if (psde && psde->scaler3_cfg)
4142 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004143clean_plane:
4144 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004145exit:
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004146 kfree(virt_format_list);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004147 return ERR_PTR(ret);
4148}