blob: ed16a0da2e50720d69b1e93349ccabc2931dcfcb [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/**
Clarence Ipddbf7752017-05-21 18:07:30 -04002044 * sde_plane_rot_flush - perform final flush related rotator options
2045 * @plane: Pointer to drm plane
2046 * @pstate: Pointer to sde plane state
2047 */
2048static void sde_plane_rot_flush(struct drm_plane *plane,
2049 struct sde_plane_state *pstate)
2050{
2051 if (!plane || !pstate || !pstate->rot.rot_hw ||
2052 !pstate->rot.rot_hw->ops.commit)
2053 return;
2054
2055 pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
2056 &pstate->rot.rot_cmd,
2057 SDE_HW_ROT_CMD_START);
2058}
2059
2060/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002061 * sde_plane_rot_destroy_state - destroy state for rotator stage
2062 * @plane: Pointer to drm plane
2063 * @state: Pointer to state to be destroyed
2064 * return: none
2065 */
2066static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2067 struct drm_plane_state *state)
2068{
2069 struct sde_plane_state *pstate = to_sde_plane_state(state);
2070 struct sde_plane_rot_state *rstate = &pstate->rot;
2071
2072 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2073 rstate->sequence_id,
2074 !!rstate->out_sbuf, !!rstate->rot_hw,
2075 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002076}
2077
2078/**
2079 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2080 * @plane: Pointer to drm plane
2081 * @new_state: Pointer to duplicated state
2082 * return: 0 if success; error code otherwise
2083 */
2084static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2085 struct drm_plane_state *new_state)
2086{
2087 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2088 struct sde_plane_rot_state *rstate = &pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002089 struct drm_crtc_state *cstate;
2090 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002091
2092 rstate->sequence_id++;
2093
2094 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2095 rstate->sequence_id,
2096 !!rstate->out_sbuf, !!rstate->rot_hw);
2097
Alan Kwongcdb2f282017-03-18 13:42:06 -07002098 cstate = _sde_plane_get_crtc_state(new_state);
2099 if (IS_ERR(cstate)) {
2100 ret = PTR_ERR(cstate);
2101 SDE_ERROR("invalid crtc state %d\n", ret);
2102 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002103 }
2104
Alan Kwongcdb2f282017-03-18 13:42:06 -07002105 if (rstate->rot_hw && cstate)
2106 sde_crtc_res_get(cstate, SDE_HW_BLK_ROT, (u64) rstate->in_fb);
2107 else if (rstate->rot_hw && !cstate)
2108 SDE_ERROR("plane%d.%d zombie rotator hw\n",
2109 plane->base.id, rstate->sequence_id);
2110
Alan Kwong4dd64c82017-02-04 18:41:51 -08002111 rstate->out_fb = NULL;
2112 rstate->out_fbo = NULL;
2113
2114 return 0;
2115}
2116
2117/**
2118 * sde_plane_rot_install_caps - install plane rotator capabilities
2119 * @plane: Pointer to drm plane
2120 * return: none
2121 */
2122static void sde_plane_rot_install_caps(struct drm_plane *plane)
2123{
2124 struct sde_plane *psde = to_sde_plane(plane);
2125 const struct sde_format_extended *format_list;
2126 struct sde_kms_info *info;
2127 struct sde_hw_rot *rot_hw;
2128 const char *downscale_caps;
2129
2130 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2131 !psde->catalog->rot_count)
2132 return;
2133
2134 if (psde->blob_rot_caps)
2135 return;
2136
2137 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2138 if (!info)
2139 return;
2140
2141 rot_hw = sde_hw_rot_get(NULL);
2142 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2143 !rot_hw->ops.get_downscale_caps) {
2144 SDE_ERROR("invalid rotator hw\n");
2145 goto error_rot;
2146 }
2147
2148 sde_kms_info_reset(info);
2149
2150 format_list = rot_hw->ops.get_format_caps(rot_hw);
2151 if (format_list) {
2152 sde_kms_info_start(info, "pixel_formats");
2153 while (format_list->fourcc_format) {
2154 sde_kms_info_append_format(info,
2155 format_list->fourcc_format,
2156 format_list->modifier);
2157 ++format_list;
2158 }
2159 sde_kms_info_stop(info);
2160 }
2161
2162 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2163 if (downscale_caps) {
2164 sde_kms_info_start(info, "downscale_ratios");
2165 sde_kms_info_append(info, downscale_caps);
2166 sde_kms_info_stop(info);
2167 }
2168
2169 if (rot_hw->ops.get_cache_size)
2170 sde_kms_info_add_keyint(info, "cache_size",
2171 rot_hw->ops.get_cache_size(rot_hw));
2172
Alan Kwong1a915802017-03-31 12:55:46 -07002173 if (rot_hw->ops.get_maxlinewidth)
2174 sde_kms_info_add_keyint(info, "max_linewidth",
2175 rot_hw->ops.get_maxlinewidth(rot_hw));
2176
Alan Kwong4dd64c82017-02-04 18:41:51 -08002177 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
2178 info->data, info->len, PLANE_PROP_ROT_CAPS_V1);
2179
2180 sde_hw_rot_put(rot_hw);
2181error_rot:
2182 kfree(info);
2183}
2184
2185/**
2186 * sde_plane_rot_install_properties - install plane rotator properties
2187 * @plane: Pointer to drm plane
2188 * @catalog: Pointer to mdss configuration
2189 * return: none
2190 */
2191static void sde_plane_rot_install_properties(struct drm_plane *plane,
2192 struct sde_mdss_cfg *catalog)
2193{
2194 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002195 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2196 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002197
2198 if (!plane || !psde) {
2199 SDE_ERROR("invalid plane\n");
2200 return;
2201 } else if (!catalog) {
2202 SDE_ERROR("invalid catalog\n");
2203 return;
2204 }
2205
2206 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2207 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2208 DRM_ROTATE_180 | DRM_ROTATE_270;
2209
2210 msm_property_install_rotation(&psde->property_info,
2211 supported_rotations, PLANE_PROP_ROTATION);
2212
2213 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2214 return;
2215
2216 msm_property_install_range(&psde->property_info, "rot_dst_x",
2217 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2218 msm_property_install_range(&psde->property_info, "rot_dst_y",
2219 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2220 msm_property_install_range(&psde->property_info, "rot_dst_w",
2221 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2222 msm_property_install_range(&psde->property_info, "rot_dst_h",
2223 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2224 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2225 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2226}
2227
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002228void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002229{
Clarence Ipcb410d42016-06-26 22:52:33 -04002230 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002231
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002232 if (!drm_state)
2233 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002234
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002235 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002236
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002237 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2238 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002239}
2240
2241int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2242{
2243 struct sde_plane_state *pstate[R_MAX];
2244 const struct drm_plane_state *drm_state[R_MAX];
2245 struct sde_rect src[R_MAX], dst[R_MAX];
2246 struct sde_plane *sde_plane[R_MAX];
2247 const struct sde_format *fmt[R_MAX];
2248 bool q16_data = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002249 int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
2250 bool parallel_fetch_qualified = true;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002251
2252 for (i = 0; i < R_MAX; i++) {
2253 const struct msm_format *msm_fmt;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002254 int width_threshold;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002255
2256 drm_state[i] = i ? plane->r1 : plane->r0;
2257 pstate[i] = to_sde_plane_state(drm_state[i]);
2258 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2259
2260 if (pstate[i] == NULL) {
2261 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2262 drm_state[i]->plane->base.id);
2263 return -EINVAL;
2264 }
2265
2266 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2267 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2268 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2269 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2270 drm_state[i]->crtc_h, !q16_data);
2271
2272 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2273 SDE_ERROR_PLANE(sde_plane[i],
2274 "scaling is not supported in multirect mode\n");
2275 return -EINVAL;
2276 }
2277
2278 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2279 fmt[i] = to_sde_format(msm_fmt);
2280 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2281 SDE_ERROR_PLANE(sde_plane[i],
2282 "Unsupported format for multirect mode\n");
2283 return -EINVAL;
2284 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002285
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002286 /**
2287 * SSPP PD_MEM is split half - one for each RECT.
2288 * Tiled formats need 5 lines of buffering while fetching
2289 * whereas linear formats need only 2 lines.
2290 * So we cannot support more than half of the supported SSPP
2291 * width for tiled formats.
2292 */
2293 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
2294 if (SDE_FORMAT_IS_UBWC(fmt[i]))
2295 width_threshold /= 2;
2296
2297 if (parallel_fetch_qualified && src[i].w > width_threshold)
2298 parallel_fetch_qualified = false;
2299
2300 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002301
2302 /* Validate RECT's and set the mode */
2303
2304 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002305 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002306 if (dst[R0].x <= dst[R1].x) {
2307 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2308 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2309 } else {
2310 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2311 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2312 }
2313
2314 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2315 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2316 goto done;
2317 }
2318
2319 /* TIME_MX Mode */
2320 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
2321 buffer_lines = 2 * fmt[R0]->tile_height;
2322
2323 if (dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) {
2324 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2325 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2326 } else if (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines) {
2327 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2328 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2329 } else {
2330 SDE_ERROR(
2331 "No multirect mode possible for the planes (%d - %d)\n",
2332 drm_state[R0]->plane->base.id,
2333 drm_state[R1]->plane->base.id);
2334 return -EINVAL;
2335 }
2336
2337 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2338 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2339done:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002340 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2341 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2342 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2343 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002344 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002345}
2346
Alan Kwong4dd64c82017-02-04 18:41:51 -08002347/**
2348 * sde_plane_get_ctl_flush - get control flush for the given plane
2349 * @plane: Pointer to drm plane structure
2350 * @ctl: Pointer to hardware control driver
2351 * @flush: Pointer to flush control word
2352 */
2353void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
2354 u32 *flush)
2355{
2356 struct sde_plane_state *pstate;
2357 struct sde_plane_rot_state *rstate;
2358 u32 bitmask;
2359
2360 if (!plane || !flush) {
2361 SDE_ERROR("invalid parameters\n");
2362 return;
2363 }
2364
2365 pstate = to_sde_plane_state(plane->state);
2366 rstate = &pstate->rot;
2367
2368 bitmask = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
2369
2370 if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
2371 ctl->ops.get_bitmask_rot)
2372 ctl->ops.get_bitmask_rot(ctl, &bitmask, rstate->rot_hw->idx);
2373
2374 *flush = bitmask;
2375}
2376
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002377static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002378 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002379{
2380 struct drm_framebuffer *fb = new_state->fb;
2381 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002382 struct sde_plane_rot_state *new_rstate;
2383 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002384
2385 if (!new_state->fb)
2386 return 0;
2387
Clarence Ip13a8cf42016-09-29 17:27:47 -04002388 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002389
2390 ret = sde_plane_rot_prepare_fb(plane, new_state);
2391 if (ret) {
2392 SDE_ERROR("failed to prepare rot framebuffer\n");
2393 return ret;
2394 }
2395
2396 new_rstate = &to_sde_plane_state(new_state)->rot;
2397
2398 ret = msm_framebuffer_prepare(new_rstate->out_fb, new_rstate->mmu_id);
2399 if (ret) {
2400 SDE_ERROR("failed to prepare framebuffer\n");
2401 return ret;
2402 }
2403
2404 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002405}
2406
2407static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002408 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002409{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002410 struct sde_plane *psde = to_sde_plane(plane);
2411 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002412
Alan Kwong4dd64c82017-02-04 18:41:51 -08002413 if (!old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002414 return;
2415
Alan Kwong4dd64c82017-02-04 18:41:51 -08002416 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2417
2418 old_rstate = &to_sde_plane_state(old_state)->rot;
2419
2420 msm_framebuffer_cleanup(old_rstate->out_fb, old_rstate->mmu_id);
2421
2422 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002423}
2424
Alan Kwong4dd64c82017-02-04 18:41:51 -08002425static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002426 struct drm_plane_state *state,
2427 struct drm_plane_state *old_state)
2428{
2429 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002430 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002431 struct sde_plane_rot_state *rstate = &pstate->rot;
2432 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2433 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002434
Dhaval Patel47302cf2016-08-18 15:04:28 -07002435 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002436 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002437 return;
2438
Clarence Ip282dad62016-09-27 17:07:35 -04002439 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2440 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002441 SDE_DEBUG_PLANE(psde,
2442 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002443 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002444 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002445 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002446 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002447 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2448 pstate->multirect_mode != old_pstate->multirect_mode) {
2449 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2450 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002451 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2452 rstate->out_src_h != old_rstate->out_src_h ||
2453 rstate->out_src_x != old_rstate->out_src_x ||
2454 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002455 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002456 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002457 } else if (state->crtc_w != old_state->crtc_w ||
2458 state->crtc_h != old_state->crtc_h ||
2459 state->crtc_x != old_state->crtc_x ||
2460 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002461 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002462 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002463 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2464 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2465 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2466 pstate->excl_rect.y != old_pstate->excl_rect.y) {
2467 SDE_DEBUG_PLANE(psde, "excl rect updated\n");
2468 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002469 }
2470
Alan Kwong4dd64c82017-02-04 18:41:51 -08002471 fb = rstate->out_fb;
2472 old_fb = old_rstate->out_fb;
2473
2474 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002475 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002476 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002477 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002478 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002479 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002480 uint64_t *new_mods = fb->modifier;
2481 uint64_t *old_mods = old_fb->modifier;
2482 uint32_t *new_pitches = fb->pitches;
2483 uint32_t *old_pitches = old_fb->pitches;
2484 uint32_t *new_offset = fb->offsets;
2485 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002486 int i;
2487
Alan Kwong4dd64c82017-02-04 18:41:51 -08002488 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002489 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002490 SDE_DEBUG_PLANE(psde,
2491 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002492 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002493 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002494 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2495 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002496 break;
2497 }
2498 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002499 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002500 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002501 SDE_DEBUG_PLANE(psde,
2502 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002503 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002504 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002505 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002506 break;
2507 }
2508 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002509 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002510 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002511 SDE_DEBUG_PLANE(psde,
2512 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002513 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002514 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002515 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2516 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002517 break;
2518 }
2519 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002520 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002521}
2522
Alan Kwong4dd64c82017-02-04 18:41:51 -08002523static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002524 struct drm_plane_state *state)
2525{
Clarence Ipdedbba92016-09-27 17:43:10 -04002526 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04002527 struct sde_plane *psde;
2528 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002529 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002530 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002531 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04002532 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002533 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
2534 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04002535
2536 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002537 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2538 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04002539 ret = -EINVAL;
2540 goto exit;
2541 }
2542
2543 psde = to_sde_plane(plane);
2544 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002545 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04002546
2547 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002548 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002549 ret = -EINVAL;
2550 goto exit;
2551 }
2552
Clarence Ipdedbba92016-09-27 17:43:10 -04002553 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
2554 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04002555
2556 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002557 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2558 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002559 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
2560 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04002561
Dhaval Patel47302cf2016-08-18 15:04:28 -07002562 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
2563 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04002564
Dhaval Patel47302cf2016-08-18 15:04:28 -07002565 max_upscale = psde->pipe_sblk->maxupscale;
2566 max_downscale = psde->pipe_sblk->maxdwnscale;
2567 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04002568
Clarence Ip13a8cf42016-09-29 17:27:47 -04002569 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002570 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002571
Dhaval Patel47302cf2016-08-18 15:04:28 -07002572 if (!sde_plane_enabled(state))
2573 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04002574
Alan Kwong4dd64c82017-02-04 18:41:51 -08002575 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002576 "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 -08002577 plane->base.id, rstate->sequence_id,
2578 rstate->out_rotation,
2579 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002580 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002581 rstate->out_fb_modifier[0],
2582 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2583 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2584 state->crtc_w, state->crtc_h,
2585 state->crtc_x, state->crtc_y);
2586
Dhaval Patel47302cf2016-08-18 15:04:28 -07002587 fmt = to_sde_format(msm_framebuffer_format(state->fb));
2588
2589 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
2590
2591 if (SDE_FORMAT_IS_YUV(fmt) &&
2592 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04002593 !(psde->features & (BIT(SDE_SSPP_CSC)
2594 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002595 SDE_ERROR_PLANE(psde,
2596 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07002597 ret = -EINVAL;
2598
2599 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002600 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
2601 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07002602 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08002603 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
2604 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002605 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002606 src.x, src.y, src.w, src.h);
2607 ret = -E2BIG;
2608
2609 /* valid yuv image */
2610 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
2611 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002612 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002613 src.x, src.y, src.w, src.h);
2614 ret = -EINVAL;
2615
2616 /* min dst support */
2617 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002618 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002619 dst.x, dst.y, dst.w, dst.h);
2620 ret = -EINVAL;
2621
2622 /* decimation validation */
2623 } else if (deci_w || deci_h) {
2624 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
2625 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002626 SDE_ERROR_PLANE(psde,
2627 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002628 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002629 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002630 SDE_ERROR_PLANE(psde,
2631 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002632 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002633 }
2634
Dhaval Patel47302cf2016-08-18 15:04:28 -07002635 } else if (!(psde->features & SDE_SSPP_SCALER) &&
2636 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002637 SDE_ERROR_PLANE(psde,
2638 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002639 src.w, src.h, dst.w, dst.h);
2640 ret = -EINVAL;
2641
2642 /* check decimated source width */
2643 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002644 SDE_ERROR_PLANE(psde,
2645 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002646 src.w, src_deci_w, max_linewidth);
2647 ret = -E2BIG;
2648
2649 /* check max scaler capability */
2650 } else if (((src_deci_w * max_upscale) < dst.w) ||
2651 ((src_deci_h * max_upscale) < dst.h) ||
2652 ((dst.w * max_downscale) < src_deci_w) ||
2653 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002654 SDE_ERROR_PLANE(psde,
2655 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002656 src_deci_w, src_deci_h, dst.w, dst.h);
2657 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002658 }
2659
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002660 /* check excl rect configs */
2661 if (pstate->excl_rect.w && pstate->excl_rect.h) {
2662 struct sde_rect intersect;
2663
2664 /*
2665 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002666 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002667 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05002668 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002669 if (intersect.w != pstate->excl_rect.w ||
2670 intersect.h != pstate->excl_rect.h ||
2671 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002672 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07002673 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002674 pstate->excl_rect.x, pstate->excl_rect.y,
2675 pstate->excl_rect.w, pstate->excl_rect.h,
2676 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07002677 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002678 ret = -EINVAL;
2679 }
2680 }
2681
Dhaval Patel47302cf2016-08-18 15:04:28 -07002682modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002683 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002684 _sde_plane_sspp_atomic_check_mode_changed(psde,
2685 state, plane->state);
2686exit:
2687 return ret;
2688}
2689
2690static int sde_plane_atomic_check(struct drm_plane *plane,
2691 struct drm_plane_state *state)
2692{
2693 int ret = 0;
2694 struct sde_plane *psde;
2695 struct sde_plane_state *pstate;
2696
2697 if (!plane || !state) {
2698 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2699 plane != 0, state != 0);
2700 ret = -EINVAL;
2701 goto exit;
2702 }
2703
2704 psde = to_sde_plane(plane);
2705 pstate = to_sde_plane_state(state);
2706
2707 SDE_DEBUG_PLANE(psde, "\n");
2708
2709 ret = sde_plane_rot_atomic_check(plane, state);
2710 if (ret)
2711 goto exit;
2712
2713 ret = sde_plane_sspp_atomic_check(plane, state);
2714
Clarence Ipdbde9832016-06-26 09:48:36 -04002715exit:
2716 return ret;
2717}
2718
Clarence Ipcae1bb62016-07-07 12:07:13 -04002719/**
2720 * sde_plane_flush - final plane operations before commit flush
2721 * @plane: Pointer to drm plane structure
2722 */
2723void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04002724{
Clarence Ipcae1bb62016-07-07 12:07:13 -04002725 struct sde_plane *psde;
Clarence Ipddbf7752017-05-21 18:07:30 -04002726 struct sde_plane_state *pstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -04002727
Clarence Ipddbf7752017-05-21 18:07:30 -04002728 if (!plane || !plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002729 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04002730 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002731 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04002732
2733 psde = to_sde_plane(plane);
Clarence Ipddbf7752017-05-21 18:07:30 -04002734 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002735
2736 /*
2737 * These updates have to be done immediately before the plane flush
2738 * timing, and may not be moved to the atomic_update/mode_set functions.
2739 */
2740 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05002741 /* force white frame with 100% alpha pipe output on error */
2742 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002743 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
2744 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04002745 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002746 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
2747 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
2748
Clarence Ip56902792017-03-17 15:22:07 -04002749 /* force black color fill during suspend */
2750 if (msm_is_suspend_state(plane->dev) && suspend_blank)
2751 _sde_plane_color_fill(psde, 0x0, 0x0);
2752
Clarence Ipcae1bb62016-07-07 12:07:13 -04002753 /* flag h/w flush complete */
2754 if (plane->state)
Clarence Ipddbf7752017-05-21 18:07:30 -04002755 pstate->pending = false;
2756
2757 /* signal inline rotator start */
2758 sde_plane_rot_flush(plane, pstate);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002759}
2760
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002761static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
2762 struct drm_plane_state *old_state)
2763{
2764 uint32_t nplanes, src_flags;
2765 struct sde_plane *psde;
2766 struct drm_plane_state *state;
2767 struct sde_plane_state *pstate;
2768 struct sde_plane_state *old_pstate;
2769 struct sde_plane_rot_state *rstate;
2770 const struct sde_format *fmt;
2771 struct drm_crtc *crtc;
2772 struct drm_framebuffer *fb;
2773 struct sde_rect src, dst;
2774 const struct sde_rect *crtc_roi;
2775 bool q16_data = true;
2776 int idx;
2777
2778 if (!plane) {
2779 SDE_ERROR("invalid plane\n");
2780 return -EINVAL;
2781 } else if (!plane->state) {
2782 SDE_ERROR("invalid plane state\n");
2783 return -EINVAL;
2784 } else if (!old_state) {
2785 SDE_ERROR("invalid old state\n");
2786 return -EINVAL;
2787 }
2788
2789 psde = to_sde_plane(plane);
2790 state = plane->state;
2791
2792 pstate = to_sde_plane_state(state);
2793 rstate = &pstate->rot;
2794
2795 old_pstate = to_sde_plane_state(old_state);
2796
2797 crtc = state->crtc;
2798 fb = rstate->out_fb;
2799 if (!crtc || !fb) {
2800 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
2801 crtc != 0, fb != 0);
2802 return -EINVAL;
2803 }
2804 fmt = to_sde_format(msm_framebuffer_format(fb));
2805 nplanes = fmt->num_planes;
2806
2807 SDE_DEBUG(
2808 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
2809 plane->base.id, rstate->sequence_id,
2810 rstate->out_fb_width, rstate->out_fb_height,
2811 (char *) &rstate->out_fb_pixel_format,
2812 rstate->out_fb_modifier[0],
2813 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2814 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2815 rstate->out_rotation,
2816 state->crtc_w, state->crtc_h,
2817 state->crtc_x, state->crtc_y);
2818
2819 /* force reprogramming of all the parameters, if the flag is set */
2820 if (psde->revalidate) {
2821 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
2822 plane->base.id);
2823 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2824 psde->revalidate = false;
2825 }
2826
2827 /* determine what needs to be refreshed */
2828 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
2829 switch (idx) {
2830 case PLANE_PROP_SCALER_V1:
2831 case PLANE_PROP_SCALER_V2:
2832 case PLANE_PROP_H_DECIMATE:
2833 case PLANE_PROP_V_DECIMATE:
2834 case PLANE_PROP_SRC_CONFIG:
2835 case PLANE_PROP_ZPOS:
2836 case PLANE_PROP_EXCL_RECT_V1:
2837 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2838 break;
2839 case PLANE_PROP_CSC_V1:
2840 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2841 break;
2842 case PLANE_PROP_COLOR_FILL:
2843 /* potentially need to refresh everything */
2844 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2845 break;
2846 case PLANE_PROP_ROTATION:
2847 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2848 break;
2849 case PLANE_PROP_INFO:
2850 case PLANE_PROP_ALPHA:
2851 case PLANE_PROP_INPUT_FENCE:
2852 case PLANE_PROP_BLEND_OP:
2853 /* no special action required */
2854 break;
2855 case PLANE_PROP_ROT_DST_X:
2856 case PLANE_PROP_ROT_DST_Y:
2857 case PLANE_PROP_ROT_DST_W:
2858 case PLANE_PROP_ROT_DST_H:
2859 /* handled by rotator atomic update */
2860 break;
2861 default:
2862 /* unknown property, refresh everything */
2863 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
2864 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
2865 break;
2866 }
2867 }
2868
2869 /**
2870 * since plane_atomic_check is invoked before crtc_atomic_check
2871 * in the commit sequence, all the parameters for updating the
2872 * plane dirty flag will not be available during
2873 * plane_atomic_check as some features params are updated
2874 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
2875 * before sspp update.
2876 */
2877 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
2878 old_state);
2879
2880 /* re-program the output rects always in the case of partial update */
2881 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
2882 if (!sde_kms_rect_is_null(crtc_roi))
2883 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2884
2885 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
2886 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
2887
2888 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
2889
2890 /* early out if nothing dirty */
2891 if (!pstate->dirty)
2892 return 0;
2893 pstate->pending = true;
2894
2895 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
2896 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
2897
2898 /* update roi config */
2899 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
2900 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2901 rstate->out_src_w, rstate->out_src_h, q16_data);
2902 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
2903 state->crtc_w, state->crtc_h, !q16_data);
2904
2905 SDE_DEBUG_PLANE(psde,
2906 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
2907 fb->base.id, src.x, src.y, src.w, src.h,
2908 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
2909 (char *)&fmt->base.pixel_format,
2910 SDE_FORMAT_IS_UBWC(fmt));
2911
2912 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
2913 BIT(SDE_DRM_DEINTERLACE)) {
2914 SDE_DEBUG_PLANE(psde, "deinterlace\n");
2915 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
2916 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
2917 src.h /= 2;
2918 src.y = DIV_ROUND_UP(src.y, 2);
2919 src.y &= ~0x1;
2920 }
2921
2922 /*
2923 * adjust layer mixer position of the sspp in the presence
2924 * of a partial update to the active lm origin
2925 */
2926 dst.x -= crtc_roi->x;
2927 dst.y -= crtc_roi->y;
2928
2929 psde->pipe_cfg.src_rect = src;
2930 psde->pipe_cfg.dst_rect = dst;
2931
2932 _sde_plane_setup_scaler(psde, fmt, pstate);
2933
2934 /* check for color fill */
2935 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
2936 PLANE_PROP_COLOR_FILL);
2937 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
2938 /* skip remaining processing on color fill */
2939 pstate->dirty = 0x0;
2940 } else if (psde->pipe_hw->ops.setup_rects) {
2941 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
2942 &psde->pipe_cfg,
2943 pstate->multirect_index);
2944 }
2945
2946 if (psde->pipe_hw->ops.setup_pe)
2947 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
2948 &psde->pixel_ext);
2949
2950 /**
2951 * when programmed in multirect mode, scalar block will be
2952 * bypassed. Still we need to update alpha and bitwidth
2953 * ONLY for RECT0
2954 */
2955 if (psde->pipe_hw->ops.setup_scaler &&
2956 pstate->multirect_index != SDE_SSPP_RECT_1)
2957 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
2958 &psde->pipe_cfg, &psde->pixel_ext,
2959 psde->scaler3_cfg);
2960
2961 /* update excl rect */
2962 if (psde->pipe_hw->ops.setup_excl_rect)
2963 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
2964 &pstate->excl_rect,
2965 pstate->multirect_index);
2966
2967 if (psde->pipe_hw->ops.setup_multirect)
2968 psde->pipe_hw->ops.setup_multirect(
2969 psde->pipe_hw,
2970 pstate->multirect_index,
2971 pstate->multirect_mode);
2972 }
2973
2974 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
2975 psde->pipe_hw->ops.setup_format) {
2976 src_flags = 0x0;
2977 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
2978 if (rstate->out_rotation & DRM_REFLECT_X)
2979 src_flags |= SDE_SSPP_FLIP_LR;
2980 if (rstate->out_rotation & DRM_REFLECT_Y)
2981 src_flags |= SDE_SSPP_FLIP_UD;
2982
2983 /* update format */
2984 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
2985 pstate->multirect_index);
2986
2987 if (psde->pipe_hw->ops.setup_sys_cache) {
2988 if (rstate->out_sbuf) {
2989 if (rstate->nplane < 2)
2990 pstate->sc_cfg.op_mode =
2991 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
2992 else if (rstate->out_xpos == 0)
2993 pstate->sc_cfg.op_mode =
2994 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
2995 else
2996 pstate->sc_cfg.op_mode =
2997 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
2998
2999 pstate->sc_cfg.rd_en = true;
3000 pstate->sc_cfg.rd_scid =
3001 rstate->rot_hw->caps->scid;
3002 pstate->sc_cfg.rd_noallocate = true;
3003 pstate->sc_cfg.rd_op_type =
3004 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3005 } else {
3006 pstate->sc_cfg.op_mode =
3007 SDE_PIPE_SC_OP_MODE_OFFLINE;
3008 pstate->sc_cfg.rd_en = false;
3009 pstate->sc_cfg.rd_scid = 0;
3010 pstate->sc_cfg.rd_noallocate = false;
3011 pstate->sc_cfg.rd_op_type =
3012 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3013 }
3014
3015 psde->pipe_hw->ops.setup_sys_cache(
3016 psde->pipe_hw, &pstate->sc_cfg);
3017 }
3018
3019 /* update csc */
3020 if (SDE_FORMAT_IS_YUV(fmt))
3021 _sde_plane_setup_csc(psde);
3022 else
3023 psde->csc_ptr = 0;
3024 }
3025
3026 sde_color_process_plane_setup(plane);
3027
3028 /* update sharpening */
3029 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3030 psde->pipe_hw->ops.setup_sharpening) {
3031 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3032 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3033 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3034 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3035
3036 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3037 &psde->sharp_cfg);
3038 }
3039
3040 _sde_plane_set_qos_lut(plane, fb);
3041 _sde_plane_set_danger_lut(plane, fb);
3042
3043 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3044 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3045 _sde_plane_set_ot_limit(plane, crtc);
3046 }
3047
3048 /* clear dirty */
3049 pstate->dirty = 0x0;
3050
3051 return 0;
3052}
3053
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003054static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003055 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003056{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003057 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003058 struct drm_plane_state *state;
3059 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003060 struct sde_plane_state *old_pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003061
Clarence Ip13a8cf42016-09-29 17:27:47 -04003062 if (!plane) {
3063 SDE_ERROR("invalid plane\n");
3064 return;
3065 } else if (!plane->state) {
3066 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003067 return;
3068 }
3069
Clarence Ip13a8cf42016-09-29 17:27:47 -04003070 psde = to_sde_plane(plane);
3071 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003072 state = plane->state;
3073 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003074 old_pstate = to_sde_plane_state(old_state);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003075
Clarence Ip13a8cf42016-09-29 17:27:47 -04003076 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003077
Alan Kwong4dd64c82017-02-04 18:41:51 -08003078 sde_plane_rot_atomic_update(plane, old_state);
3079
3080 if (!sde_plane_sspp_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04003081 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04003082 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003083 int ret;
3084
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003085 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003086 /* atomic_check should have ensured that this doesn't fail */
3087 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003088 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003089}
3090
Dhaval Patel47302cf2016-08-18 15:04:28 -07003091
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003092/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003093static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003094 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003095{
Clarence Ip5e2a9222016-06-26 22:38:24 -04003096 static const struct drm_prop_enum_list e_blend_op[] = {
3097 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3098 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3099 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3100 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3101 };
3102 static const struct drm_prop_enum_list e_src_config[] = {
3103 {SDE_DRM_DEINTERLACE, "deinterlace"}
3104 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003105 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003106 struct sde_format_extended *virt_format_list = NULL;
Dhaval Patel4e574842016-08-23 15:11:37 -07003107 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003108 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003109 int zpos_max = 255;
3110 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003111 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003112
Clarence Ip13a8cf42016-09-29 17:27:47 -04003113 if (!plane || !psde) {
3114 SDE_ERROR("invalid plane\n");
3115 return;
3116 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3117 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3118 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003119 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003120 } else if (!catalog) {
3121 SDE_ERROR("invalid catalog\n");
3122 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003123 }
3124
Alan Kwong4dd64c82017-02-04 18:41:51 -08003125 psde->catalog = catalog;
3126
Clarence Ipc47a0692016-10-11 10:54:17 -04003127 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003128 if (catalog->mixer_count && catalog->mixer &&
3129 catalog->mixer[0].sblk->maxblendstages) {
3130 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3131 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3132 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3133 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003134 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3135 /* reserve zpos == 0 for primary planes */
3136 zpos_def = drm_plane_index(plane) + 1;
3137 }
3138
3139 msm_property_install_range(&psde->property_info, "zpos",
3140 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003141
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003142 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003143 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003144
Dhaval Patel47302cf2016-08-18 15:04:28 -07003145 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003146 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003147 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003148
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003149 if (!master_plane_id) {
3150 if (psde->pipe_sblk->maxhdeciexp) {
3151 msm_property_install_range(&psde->property_info,
3152 "h_decimate", 0x0, 0,
3153 psde->pipe_sblk->maxhdeciexp, 0,
3154 PLANE_PROP_H_DECIMATE);
3155 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003156
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003157 if (psde->pipe_sblk->maxvdeciexp) {
3158 msm_property_install_range(&psde->property_info,
3159 "v_decimate", 0x0, 0,
3160 psde->pipe_sblk->maxvdeciexp, 0,
3161 PLANE_PROP_V_DECIMATE);
3162 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003163
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003164 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
3165 msm_property_install_volatile_range(
3166 &psde->property_info, "scaler_v2",
3167 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3168 msm_property_install_blob(&psde->property_info,
3169 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3170 msm_property_install_blob(&psde->property_info,
3171 "lut_cir", 0,
3172 PLANE_PROP_SCALER_LUT_CIR);
3173 msm_property_install_blob(&psde->property_info,
3174 "lut_sep", 0,
3175 PLANE_PROP_SCALER_LUT_SEP);
3176 } else if (psde->features & SDE_SSPP_SCALER) {
3177 msm_property_install_volatile_range(
3178 &psde->property_info, "scaler_v1", 0x0,
3179 0, ~0, 0, PLANE_PROP_SCALER_V1);
3180 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003181
Dhaval Patel0aee0972017-02-08 19:00:58 -08003182 if (psde->features & BIT(SDE_SSPP_CSC) ||
3183 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003184 msm_property_install_volatile_range(
3185 &psde->property_info, "csc_v1", 0x0,
3186 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003187
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003188 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3189 snprintf(feature_name, sizeof(feature_name), "%s%d",
3190 "SDE_SSPP_HUE_V",
3191 psde->pipe_sblk->hsic_blk.version >> 16);
3192 msm_property_install_range(&psde->property_info,
3193 feature_name, 0, 0, 0xFFFFFFFF, 0,
3194 PLANE_PROP_HUE_ADJUST);
3195 snprintf(feature_name, sizeof(feature_name), "%s%d",
3196 "SDE_SSPP_SATURATION_V",
3197 psde->pipe_sblk->hsic_blk.version >> 16);
3198 msm_property_install_range(&psde->property_info,
3199 feature_name, 0, 0, 0xFFFFFFFF, 0,
3200 PLANE_PROP_SATURATION_ADJUST);
3201 snprintf(feature_name, sizeof(feature_name), "%s%d",
3202 "SDE_SSPP_VALUE_V",
3203 psde->pipe_sblk->hsic_blk.version >> 16);
3204 msm_property_install_range(&psde->property_info,
3205 feature_name, 0, 0, 0xFFFFFFFF, 0,
3206 PLANE_PROP_VALUE_ADJUST);
3207 snprintf(feature_name, sizeof(feature_name), "%s%d",
3208 "SDE_SSPP_CONTRAST_V",
3209 psde->pipe_sblk->hsic_blk.version >> 16);
3210 msm_property_install_range(&psde->property_info,
3211 feature_name, 0, 0, 0xFFFFFFFF, 0,
3212 PLANE_PROP_CONTRAST_ADJUST);
3213 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003214 }
3215
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003216 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3217 msm_property_install_volatile_range(&psde->property_info,
3218 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3219
Alan Kwong4dd64c82017-02-04 18:41:51 -08003220 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003221
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003222 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003223 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003224
Dhaval Patel47302cf2016-08-18 15:04:28 -07003225 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3226 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3227
3228 if (psde->pipe_hw->ops.setup_solidfill)
3229 msm_property_install_range(&psde->property_info, "color_fill",
3230 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3231
Dhaval Patel4e574842016-08-23 15:11:37 -07003232 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003233 if (!info) {
3234 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003235 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003236 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003237
3238 msm_property_install_blob(&psde->property_info, "capabilities",
3239 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3240 sde_kms_info_reset(info);
3241
Clarence Ipea3d6262016-07-15 16:20:11 -04003242 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003243
3244 if (master_plane_id) {
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003245 int index, array_size;
3246
3247 array_size = ARRAY_SIZE(plane_formats)
3248 + ARRAY_SIZE(rgb_10bit_formats);
3249 virt_format_list = kcalloc(array_size,
3250 sizeof(struct sde_format_extended), GFP_KERNEL);
3251 if (!virt_format_list) {
3252 SDE_ERROR(
3253 "failed to allocate virtual pipe format list\n");
3254 return;
3255 }
3256
3257 index = sde_copy_formats(virt_format_list, array_size,
3258 0, plane_formats, ARRAY_SIZE(plane_formats));
3259 sde_copy_formats(virt_format_list, array_size,
3260 index, rgb_10bit_formats,
3261 ARRAY_SIZE(rgb_10bit_formats));
3262
3263 format_list = virt_format_list;
3264
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003265 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003266 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003267 }
3268
Clarence Ipea3d6262016-07-15 16:20:11 -04003269 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003270 sde_kms_info_start(info, "pixel_formats");
3271 while (format_list->fourcc_format) {
3272 sde_kms_info_append_format(info,
3273 format_list->fourcc_format,
3274 format_list->modifier);
3275 ++format_list;
3276 }
3277 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003278 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003279
3280 sde_kms_info_add_keyint(info, "max_linewidth",
3281 psde->pipe_sblk->maxlinewidth);
3282 sde_kms_info_add_keyint(info, "max_upscale",
3283 psde->pipe_sblk->maxupscale);
3284 sde_kms_info_add_keyint(info, "max_downscale",
3285 psde->pipe_sblk->maxdwnscale);
3286 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3287 psde->pipe_sblk->maxhdeciexp);
3288 sde_kms_info_add_keyint(info, "max_vertical_deci",
3289 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07003290 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
3291 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07003292 msm_property_set_blob(&psde->property_info, &psde->blob_info,
3293 info->data, info->len, PLANE_PROP_INFO);
3294
3295 kfree(info);
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003296 kfree(virt_format_list);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003297
3298 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3299 snprintf(feature_name, sizeof(feature_name), "%s%d",
3300 "SDE_SSPP_SKIN_COLOR_V",
3301 psde->pipe_sblk->memcolor_blk.version >> 16);
3302 msm_property_install_blob(&psde->property_info, feature_name, 0,
3303 PLANE_PROP_SKIN_COLOR);
3304 snprintf(feature_name, sizeof(feature_name), "%s%d",
3305 "SDE_SSPP_SKY_COLOR_V",
3306 psde->pipe_sblk->memcolor_blk.version >> 16);
3307 msm_property_install_blob(&psde->property_info, feature_name, 0,
3308 PLANE_PROP_SKY_COLOR);
3309 snprintf(feature_name, sizeof(feature_name), "%s%d",
3310 "SDE_SSPP_FOLIAGE_COLOR_V",
3311 psde->pipe_sblk->memcolor_blk.version >> 16);
3312 msm_property_install_blob(&psde->property_info, feature_name, 0,
3313 PLANE_PROP_FOLIAGE_COLOR);
3314 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003315}
3316
Clarence Ip5fc00c52016-09-23 15:03:34 -04003317static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
3318{
3319 struct sde_drm_csc_v1 csc_v1;
3320 int i;
3321
3322 if (!psde) {
3323 SDE_ERROR("invalid plane\n");
3324 return;
3325 }
3326
3327 psde->csc_usr_ptr = NULL;
3328 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003329 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003330 return;
3331 }
3332
3333 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003334 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003335 return;
3336 }
3337
Clarence Ipb43d4592016-09-08 14:21:35 -04003338 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04003339 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
3340 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
3341 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
3342 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
3343 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
3344 }
3345 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
3346 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
3347 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
3348 }
3349 psde->csc_usr_ptr = &psde->csc_cfg;
3350}
3351
Clarence Ipb43d4592016-09-08 14:21:35 -04003352static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
3353{
3354 struct sde_drm_scaler_v1 scale_v1;
3355 struct sde_hw_pixel_ext *pe;
3356 int i;
3357
3358 if (!psde) {
3359 SDE_ERROR("invalid plane\n");
3360 return;
3361 }
3362
3363 psde->pixel_ext_usr = false;
3364 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003365 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003366 return;
3367 }
3368
3369 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003370 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003371 return;
3372 }
3373
3374 /* populate from user space */
3375 pe = &(psde->pixel_ext);
3376 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3377 for (i = 0; i < SDE_MAX_PLANES; i++) {
3378 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
3379 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
3380 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
3381 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
3382
3383 pe->horz_filter[i] = scale_v1.horz_filter[i];
3384 pe->vert_filter[i] = scale_v1.vert_filter[i];
3385 }
3386 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003387 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
3388 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
3389 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
3390 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
3391 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003392
abeykun41060122016-11-28 13:02:01 -05003393 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
3394 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
3395 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
3396 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
3397 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003398 }
abeykun41060122016-11-28 13:02:01 -05003399
Clarence Ipb43d4592016-09-08 14:21:35 -04003400 psde->pixel_ext_usr = true;
3401
Clarence Ip13a8cf42016-09-29 17:27:47 -04003402 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003403}
3404
abeykun48f407a2016-08-25 12:06:44 -04003405static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
3406 struct sde_plane_state *pstate, void *usr)
3407{
3408 struct sde_drm_scaler_v2 scale_v2;
3409 struct sde_hw_pixel_ext *pe;
3410 int i;
3411 struct sde_hw_scaler3_cfg *cfg;
3412
3413 if (!psde) {
3414 SDE_ERROR("invalid plane\n");
3415 return;
3416 }
3417
3418 cfg = psde->scaler3_cfg;
3419 psde->pixel_ext_usr = false;
3420 if (!usr) {
3421 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3422 return;
3423 }
3424
3425 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
3426 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
3427 return;
3428 }
3429
3430 /* populate from user space */
3431 pe = &(psde->pixel_ext);
3432 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3433 cfg->enable = scale_v2.enable;
3434 cfg->dir_en = scale_v2.dir_en;
3435 for (i = 0; i < SDE_MAX_PLANES; i++) {
3436 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
3437 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
3438 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
3439 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
3440
3441 cfg->preload_x[i] = scale_v2.preload_x[i];
3442 cfg->preload_y[i] = scale_v2.preload_y[i];
3443 cfg->src_width[i] = scale_v2.src_width[i];
3444 cfg->src_height[i] = scale_v2.src_height[i];
3445 }
3446 cfg->dst_width = scale_v2.dst_width;
3447 cfg->dst_height = scale_v2.dst_height;
3448
3449 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
3450 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
3451 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
3452 cfg->blend_cfg = scale_v2.blend_cfg;
3453
3454 cfg->lut_flag = scale_v2.lut_flag;
3455 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
3456 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
3457 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
3458 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
3459 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
3460
3461 cfg->de.enable = scale_v2.de.enable;
3462 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
3463 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
3464 cfg->de.clip = scale_v2.de.clip;
3465 cfg->de.limit = scale_v2.de.limit;
3466 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
3467 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
3468 cfg->de.thr_low = scale_v2.de.thr_low;
3469 cfg->de.thr_high = scale_v2.de.thr_high;
3470 cfg->de.prec_shift = scale_v2.de.prec_shift;
3471 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
3472 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
3473 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
3474 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
3475 }
3476 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003477 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
3478 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
3479 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
3480 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
3481 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04003482
abeykun41060122016-11-28 13:02:01 -05003483 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
3484 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
3485 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
3486 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
3487 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04003488 }
3489 psde->pixel_ext_usr = true;
3490
3491 SDE_DEBUG_PLANE(psde, "user property data copied\n");
3492}
3493
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003494static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
3495 struct sde_plane_state *pstate, void *usr_ptr)
3496{
3497 struct drm_clip_rect excl_rect_v1;
3498
3499 if (!psde) {
3500 SDE_ERROR("invalid plane\n");
3501 return;
3502 }
3503
3504 if (!usr_ptr) {
3505 SDE_DEBUG_PLANE(psde, "excl rect data removed\n");
3506 return;
3507 }
3508
3509 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
3510 SDE_ERROR_PLANE(psde, "failed to copy excl rect data\n");
3511 return;
3512 }
3513
3514 /* populate from user space */
3515 pstate->excl_rect.x = excl_rect_v1.x1;
3516 pstate->excl_rect.y = excl_rect_v1.y1;
3517 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1 + 1;
3518 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1 + 1;
3519}
3520
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003521static int sde_plane_atomic_set_property(struct drm_plane *plane,
3522 struct drm_plane_state *state, struct drm_property *property,
3523 uint64_t val)
3524{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003525 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003526 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003527 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003528
Clarence Ip13a8cf42016-09-29 17:27:47 -04003529 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003530
3531 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003532 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003533 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003534 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003535 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04003536 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003537 ret = msm_property_atomic_set(&psde->property_info,
3538 pstate->property_values, pstate->property_blobs,
3539 property, val);
3540 if (!ret) {
3541 idx = msm_property_index(&psde->property_info,
3542 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003543 switch (idx) {
3544 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04003545 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003546 break;
3547 case PLANE_PROP_CSC_V1:
3548 _sde_plane_set_csc_v1(psde, (void *)val);
3549 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04003550 case PLANE_PROP_SCALER_V1:
3551 _sde_plane_set_scaler_v1(psde, (void *)val);
3552 break;
abeykun48f407a2016-08-25 12:06:44 -04003553 case PLANE_PROP_SCALER_V2:
3554 _sde_plane_set_scaler_v2(psde, pstate,
3555 (void *)val);
3556 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003557 case PLANE_PROP_EXCL_RECT_V1:
3558 _sde_plane_set_excl_rect_v1(psde, pstate,
3559 (void *)val);
3560 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04003561 default:
3562 /* nothing to do */
3563 break;
3564 }
Clarence Ipe78efb72016-06-24 18:35:21 -04003565 }
3566 }
3567
Alan Kwong4dd64c82017-02-04 18:41:51 -08003568 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
3569 property->name, property->base.id, val, ret);
3570
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003571 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003572}
3573
3574static int sde_plane_set_property(struct drm_plane *plane,
3575 struct drm_property *property, uint64_t val)
3576{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003577 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003578
Clarence Ipae4e60c2016-06-26 22:44:04 -04003579 return sde_plane_atomic_set_property(plane,
3580 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003581}
3582
3583static int sde_plane_atomic_get_property(struct drm_plane *plane,
3584 const struct drm_plane_state *state,
3585 struct drm_property *property, uint64_t *val)
3586{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003587 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003588 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04003589 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003590
Clarence Ipaa0faf42016-05-30 12:07:48 -04003591 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003592 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003593 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003594 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003595 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003596 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003597 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003598 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003599 ret = msm_property_atomic_get(&psde->property_info,
3600 pstate->property_values, pstate->property_blobs,
3601 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04003602 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003603
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003604 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003605}
3606
3607static void sde_plane_destroy(struct drm_plane *plane)
3608{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003609 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003610
Clarence Ip13a8cf42016-09-29 17:27:47 -04003611 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003612
Clarence Ip13a8cf42016-09-29 17:27:47 -04003613 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04003614 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3615
Dhaval Patel4e574842016-08-23 15:11:37 -07003616 if (psde->blob_info)
3617 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003618 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04003619 mutex_destroy(&psde->lock);
3620
Clarence Ip4ce59322016-06-26 22:27:51 -04003621 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003622
Clarence Ip4ce59322016-06-26 22:27:51 -04003623 /* this will destroy the states as well */
3624 drm_plane_cleanup(plane);
3625
Clarence Ip4c1d9772016-06-26 09:35:38 -04003626 if (psde->pipe_hw)
3627 sde_hw_sspp_destroy(psde->pipe_hw);
3628
Clarence Ip4ce59322016-06-26 22:27:51 -04003629 kfree(psde);
3630 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003631}
3632
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003633static void sde_plane_destroy_state(struct drm_plane *plane,
3634 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003635{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003636 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04003637 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003638
Clarence Ipae4e60c2016-06-26 22:44:04 -04003639 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003640 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3641 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003642 return;
3643 }
3644
Clarence Ipaa0faf42016-05-30 12:07:48 -04003645 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04003646 pstate = to_sde_plane_state(state);
3647
Clarence Ip13a8cf42016-09-29 17:27:47 -04003648 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003649
Alan Kwong4dd64c82017-02-04 18:41:51 -08003650 sde_plane_rot_destroy_state(plane, &pstate->base);
3651
Clarence Ipe78efb72016-06-24 18:35:21 -04003652 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003653 if (state->fb)
3654 drm_framebuffer_unreference(state->fb);
3655
Clarence Ipae4e60c2016-06-26 22:44:04 -04003656 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003657 if (pstate->input_fence)
3658 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003659
Clarence Ipaa0faf42016-05-30 12:07:48 -04003660 /* destroy value helper */
3661 msm_property_destroy_state(&psde->property_info, pstate,
3662 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003663}
3664
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003665static struct drm_plane_state *
3666sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003667{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003668 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003669 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04003670 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04003671 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003672
Clarence Ip13a8cf42016-09-29 17:27:47 -04003673 if (!plane) {
3674 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003675 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003676 } else if (!plane->state) {
3677 SDE_ERROR("invalid plane state\n");
3678 return NULL;
3679 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003680
Clarence Ip730e7192016-06-26 22:45:09 -04003681 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003682 psde = to_sde_plane(plane);
3683 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003684 if (!pstate) {
3685 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003686 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003687 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003688
Clarence Ip13a8cf42016-09-29 17:27:47 -04003689 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003690
3691 /* duplicate value helper */
3692 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
3693 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003694
Clarence Ip17e908b2016-09-29 15:58:00 -04003695 /* clear out any input fence */
3696 pstate->input_fence = 0;
3697 input_fence_default = msm_property_get_default(
3698 &psde->property_info, PLANE_PROP_INPUT_FENCE);
3699 msm_property_set_property(&psde->property_info, pstate->property_values,
3700 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003701
Clarence Ip282dad62016-09-27 17:07:35 -04003702 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04003703 pstate->pending = false;
3704
Alan Kwongcdb2f282017-03-18 13:42:06 -07003705 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
3706
Alan Kwong4dd64c82017-02-04 18:41:51 -08003707 sde_plane_rot_duplicate_state(plane, &pstate->base);
3708
Clarence Ip730e7192016-06-26 22:45:09 -04003709 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003710}
3711
3712static void sde_plane_reset(struct drm_plane *plane)
3713{
Clarence Ipae4e60c2016-06-26 22:44:04 -04003714 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003715 struct sde_plane_state *pstate;
3716
Clarence Ipae4e60c2016-06-26 22:44:04 -04003717 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003718 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003719 return;
3720 }
3721
Clarence Ip730e7192016-06-26 22:45:09 -04003722 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003723 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003724
Clarence Ipae4e60c2016-06-26 22:44:04 -04003725 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04003726 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04003727 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003728 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04003729 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003730
Clarence Ipaa0faf42016-05-30 12:07:48 -04003731 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003732 if (!pstate) {
3733 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003734 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003735 }
Clarence Ip730e7192016-06-26 22:45:09 -04003736
Clarence Ipaa0faf42016-05-30 12:07:48 -04003737 /* reset value helper */
3738 msm_property_reset_state(&psde->property_info, pstate,
3739 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003740
3741 pstate->base.plane = plane;
3742
3743 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003744}
3745
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003746#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04003747static ssize_t _sde_plane_danger_read(struct file *file,
3748 char __user *buff, size_t count, loff_t *ppos)
3749{
3750 struct sde_kms *kms = file->private_data;
3751 struct sde_mdss_cfg *cfg = kms->catalog;
3752 int len = 0;
3753 char buf[40] = {'\0'};
3754
3755 if (!cfg)
3756 return -ENODEV;
3757
3758 if (*ppos)
3759 return 0; /* the end */
3760
3761 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
3762 if (len < 0 || len >= sizeof(buf))
3763 return 0;
3764
3765 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
3766 return -EFAULT;
3767
3768 *ppos += len; /* increase offset */
3769
3770 return len;
3771}
3772
3773static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
3774{
3775 struct drm_plane *plane;
3776
3777 drm_for_each_plane(plane, kms->dev) {
3778 if (plane->fb && plane->state) {
3779 sde_plane_danger_signal_ctrl(plane, enable);
3780 SDE_DEBUG("plane:%d img:%dx%d ",
3781 plane->base.id, plane->fb->width,
3782 plane->fb->height);
3783 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
3784 plane->state->src_x >> 16,
3785 plane->state->src_y >> 16,
3786 plane->state->src_w >> 16,
3787 plane->state->src_h >> 16,
3788 plane->state->crtc_x, plane->state->crtc_y,
3789 plane->state->crtc_w, plane->state->crtc_h);
3790 } else {
3791 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
3792 }
3793 }
3794}
3795
3796static ssize_t _sde_plane_danger_write(struct file *file,
3797 const char __user *user_buf, size_t count, loff_t *ppos)
3798{
3799 struct sde_kms *kms = file->private_data;
3800 struct sde_mdss_cfg *cfg = kms->catalog;
3801 int disable_panic;
3802 char buf[10];
3803
3804 if (!cfg)
3805 return -EFAULT;
3806
3807 if (count >= sizeof(buf))
3808 return -EFAULT;
3809
3810 if (copy_from_user(buf, user_buf, count))
3811 return -EFAULT;
3812
3813 buf[count] = 0; /* end of string */
3814
3815 if (kstrtoint(buf, 0, &disable_panic))
3816 return -EFAULT;
3817
3818 if (disable_panic) {
3819 /* Disable panic signal for all active pipes */
3820 SDE_DEBUG("Disabling danger:\n");
3821 _sde_plane_set_danger_state(kms, false);
3822 kms->has_danger_ctrl = false;
3823 } else {
3824 /* Enable panic signal for all active pipes */
3825 SDE_DEBUG("Enabling danger:\n");
3826 kms->has_danger_ctrl = true;
3827 _sde_plane_set_danger_state(kms, true);
3828 }
3829
3830 return count;
3831}
3832
3833static const struct file_operations sde_plane_danger_enable = {
3834 .open = simple_open,
3835 .read = _sde_plane_danger_read,
3836 .write = _sde_plane_danger_write,
3837};
3838
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003839static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04003840{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003841 struct sde_plane *psde;
3842 struct sde_kms *kms;
3843 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04003844 const struct sde_sspp_sub_blks *sblk = 0;
3845 const struct sde_sspp_cfg *cfg = 0;
3846
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003847 if (!plane || !plane->dev) {
3848 SDE_ERROR("invalid arguments\n");
3849 return -EINVAL;
3850 }
3851
3852 priv = plane->dev->dev_private;
3853 if (!priv || !priv->kms) {
3854 SDE_ERROR("invalid KMS reference\n");
3855 return -EINVAL;
3856 }
3857
3858 kms = to_sde_kms(priv->kms);
3859 psde = to_sde_plane(plane);
3860
Clarence Ip4ce59322016-06-26 22:27:51 -04003861 if (psde && psde->pipe_hw)
3862 cfg = psde->pipe_hw->cap;
3863 if (cfg)
3864 sblk = cfg->sblk;
3865
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003866 if (!sblk)
3867 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04003868
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003869 /* create overall sub-directory for the pipe */
3870 psde->debugfs_root =
3871 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07003872 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04003873
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003874 if (!psde->debugfs_root)
3875 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04003876
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003877 /* don't error check these */
3878 debugfs_create_x32("features", 0644,
3879 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003880
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003881 /* add register dump support */
3882 sde_debugfs_setup_regset32(&psde->debugfs_src,
3883 sblk->src_blk.base + cfg->base,
3884 sblk->src_blk.len,
3885 kms);
3886 sde_debugfs_create_regset32("src_blk", 0444,
3887 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003888
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003889 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
3890 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
3891 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
3892 sblk->scaler_blk.base + cfg->base,
3893 sblk->scaler_blk.len,
3894 kms);
3895 sde_debugfs_create_regset32("scaler_blk", 0444,
3896 psde->debugfs_root,
3897 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07003898 debugfs_create_bool("default_scaling",
3899 0644,
3900 psde->debugfs_root,
3901 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04003902 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003903
3904 if (cfg->features & BIT(SDE_SSPP_CSC) ||
3905 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
3906 sde_debugfs_setup_regset32(&psde->debugfs_csc,
3907 sblk->csc_blk.base + cfg->base,
3908 sblk->csc_blk.len,
3909 kms);
3910 sde_debugfs_create_regset32("csc_blk", 0444,
3911 psde->debugfs_root, &psde->debugfs_csc);
3912 }
3913
3914 debugfs_create_u32("xin_id",
3915 0444,
3916 psde->debugfs_root,
3917 (u32 *) &cfg->xin_id);
3918 debugfs_create_u32("clk_ctrl",
3919 0444,
3920 psde->debugfs_root,
3921 (u32 *) &cfg->clk_ctrl);
3922 debugfs_create_x32("creq_vblank",
3923 0644,
3924 psde->debugfs_root,
3925 (u32 *) &sblk->creq_vblank);
3926 debugfs_create_x32("danger_vblank",
3927 0644,
3928 psde->debugfs_root,
3929 (u32 *) &sblk->danger_vblank);
3930
3931 debugfs_create_file("disable_danger",
3932 0644,
3933 psde->debugfs_root,
3934 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003935 debugfs_create_u32("sbuf_mode",
3936 0644,
3937 psde->debugfs_root, &psde->sbuf_mode);
3938 debugfs_create_u32("sbuf_writeback",
3939 0644,
3940 psde->debugfs_root,
3941 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003942
3943 return 0;
3944}
3945
3946static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3947{
3948 struct sde_plane *psde;
3949
3950 if (!plane)
3951 return;
3952 psde = to_sde_plane(plane);
3953
3954 debugfs_remove_recursive(psde->debugfs_root);
3955}
3956#else
3957static int _sde_plane_init_debugfs(struct drm_plane *plane)
3958{
3959 return 0;
3960}
3961static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3962{
3963}
3964#endif
3965
3966static int sde_plane_late_register(struct drm_plane *plane)
3967{
3968 return _sde_plane_init_debugfs(plane);
3969}
3970
3971static void sde_plane_early_unregister(struct drm_plane *plane)
3972{
3973 _sde_plane_destroy_debugfs(plane);
3974}
3975
3976static const struct drm_plane_funcs sde_plane_funcs = {
3977 .update_plane = drm_atomic_helper_update_plane,
3978 .disable_plane = drm_atomic_helper_disable_plane,
3979 .destroy = sde_plane_destroy,
3980 .set_property = sde_plane_set_property,
3981 .atomic_set_property = sde_plane_atomic_set_property,
3982 .atomic_get_property = sde_plane_atomic_get_property,
3983 .reset = sde_plane_reset,
3984 .atomic_duplicate_state = sde_plane_duplicate_state,
3985 .atomic_destroy_state = sde_plane_destroy_state,
3986 .late_register = sde_plane_late_register,
3987 .early_unregister = sde_plane_early_unregister,
3988};
3989
3990static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
3991 .prepare_fb = sde_plane_prepare_fb,
3992 .cleanup_fb = sde_plane_cleanup_fb,
3993 .atomic_check = sde_plane_atomic_check,
3994 .atomic_update = sde_plane_atomic_update,
3995};
3996
3997enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
3998{
3999 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
4000}
4001
4002bool is_sde_plane_virtual(struct drm_plane *plane)
4003{
4004 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04004005}
4006
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004007/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04004008struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04004009 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004010 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004011{
4012 struct drm_plane *plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004013 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004014 struct sde_format_extended *virt_format_list = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004015 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004016 struct msm_drm_private *priv;
4017 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004018 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04004019 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004020
4021 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004022 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004023 goto exit;
4024 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004025
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004026 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004027 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004028 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004029 goto exit;
4030 }
4031
4032 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004033 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004034 goto exit;
4035 }
4036 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004037
Clarence Ip4c1d9772016-06-26 09:35:38 -04004038 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004039 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004040 goto exit;
4041 }
4042
Clarence Ip4ce59322016-06-26 22:27:51 -04004043 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004044 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4045 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004046 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004047 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004048 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004049 }
4050
Clarence Ip4c1d9772016-06-26 09:35:38 -04004051 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004052 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004053 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04004054 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004055 psde->is_virtual = (master_plane_id != 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004056
Clarence Ip4c1d9772016-06-26 09:35:38 -04004057 /* initialize underlying h/w driver */
4058 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
4059 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004060 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004061 ret = PTR_ERR(psde->pipe_hw);
4062 goto clean_plane;
4063 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004064 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004065 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004066 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004067
4068 /* cache features mask for later */
4069 psde->features = psde->pipe_hw->cap->features;
4070 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004071 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004072 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004073 goto clean_sspp;
4074 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004075
abeykun48f407a2016-08-25 12:06:44 -04004076 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
4077 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
4078 GFP_KERNEL);
4079 if (!psde->scaler3_cfg) {
4080 SDE_ERROR("[%u]failed to allocate scale struct\n",
4081 pipe);
4082 ret = -ENOMEM;
4083 goto clean_sspp;
4084 }
4085 }
4086
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004087 format_list = psde->pipe_sblk->format_list;
4088
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004089 if (master_plane_id) {
4090 int index, array_size;
4091
4092 array_size = ARRAY_SIZE(plane_formats)
4093 + ARRAY_SIZE(rgb_10bit_formats);
4094 virt_format_list = kcalloc(array_size,
4095 sizeof(struct sde_format_extended),
4096 GFP_KERNEL);
4097 if (!virt_format_list) {
4098 SDE_ERROR(
4099 "failed to allocate virtual pipe format list\n");
4100 goto clean_sspp;
4101 }
4102
4103 index = sde_copy_formats(virt_format_list, array_size,
4104 0, plane_formats, ARRAY_SIZE(plane_formats));
4105 sde_copy_formats(virt_format_list, array_size,
4106 index, rgb_10bit_formats,
4107 ARRAY_SIZE(rgb_10bit_formats));
4108
4109 format_list = virt_format_list;
4110 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004111
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004112 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004113 psde->formats,
4114 0,
4115 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004116
Clarence Ip4c1d9772016-06-26 09:35:38 -04004117 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004118 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004119 goto clean_sspp;
4120 }
4121
4122 if (psde->features & BIT(SDE_SSPP_CURSOR))
4123 type = DRM_PLANE_TYPE_CURSOR;
4124 else if (primary_plane)
4125 type = DRM_PLANE_TYPE_PRIMARY;
4126 else
4127 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07004128 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
4129 psde->formats, psde->nformats,
4130 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004131 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04004132 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004133
Clarence Ip4c1d9772016-06-26 09:35:38 -04004134 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004135 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004136
Clarence Ipaa0faf42016-05-30 12:07:48 -04004137 msm_property_init(&psde->property_info, &plane->base, dev,
4138 priv->plane_property, psde->property_data,
4139 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
4140 sizeof(struct sde_plane_state));
4141
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004142 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004143
Clarence Ip4ce59322016-06-26 22:27:51 -04004144 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004145 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004146
Clarence Ip730e7192016-06-26 22:45:09 -04004147 mutex_init(&psde->lock);
4148
Dhaval Patel82c8dbc2017-02-18 23:15:10 -08004149 SDE_DEBUG("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004150 return plane;
4151
Clarence Ip4c1d9772016-06-26 09:35:38 -04004152clean_sspp:
4153 if (psde && psde->pipe_hw)
4154 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04004155
4156 if (psde && psde->scaler3_cfg)
4157 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004158clean_plane:
4159 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004160exit:
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004161 kfree(virt_format_list);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004162 return ERR_PTR(ret);
4163}