blob: 3a6de758204b706dbfde9576102648d2628857da [file] [log] [blame]
Dhaval Patel14d46ce2017-01-17 16:28:12 -08001/*
2 * Copyright (C) 2014-2017 The Linux Foundation. All rights reserved.
3 * Copyright (C) 2013 Red Hat
4 * Author: Rob Clark <robdclark@gmail.com>
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005 *
Dhaval Patel14d46ce2017-01-17 16:28:12 -08006 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07009 *
Dhaval Patel14d46ce2017-01-17 16:28:12 -080010 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070017 */
Alan Kwong1a00e4d2016-07-18 09:42:30 -040018
19#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
20
Clarence Ip4ce59322016-06-26 22:27:51 -040021#include <linux/debugfs.h>
Alan Kwong4dd64c82017-02-04 18:41:51 -080022#include <linux/dma-buf.h>
Clarence Ip5e2a9222016-06-26 22:38:24 -040023#include <uapi/drm/sde_drm.h>
Benet Clarkd009b1d2016-06-27 14:45:59 -070024#include <uapi/drm/msm_drm_pp.h>
Clarence Ipaa0faf42016-05-30 12:07:48 -040025
26#include "msm_prop.h"
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080027#include "msm_drv.h"
Clarence Ipaa0faf42016-05-30 12:07:48 -040028
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070029#include "sde_kms.h"
Clarence Ipae4e60c2016-06-26 22:44:04 -040030#include "sde_fence.h"
Clarence Ipc475b082016-06-26 09:27:23 -040031#include "sde_formats.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040032#include "sde_hw_sspp.h"
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080033#include "sde_hw_catalog_format.h"
Alan Kwong1a00e4d2016-07-18 09:42:30 -040034#include "sde_trace.h"
Dhaval Patel48c76022016-09-01 17:51:23 -070035#include "sde_crtc.h"
Lloyd Atkinson8772e202016-09-26 17:52:16 -040036#include "sde_vbif.h"
Alan Kwong83285fb2016-10-21 20:51:17 -040037#include "sde_plane.h"
Benet Clarkd009b1d2016-06-27 14:45:59 -070038#include "sde_color_processing.h"
Alan Kwong4dd64c82017-02-04 18:41:51 -080039#include "sde_hw_rot.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040040
Clarence Ip56902792017-03-17 15:22:07 -040041static bool suspend_blank = true;
42module_param(suspend_blank, bool, 0400);
43MODULE_PARM_DESC(suspend_blank,
44 "If set, active planes will force their outputs to black,\n"
45 "by temporarily enabling the color fill, when recovering\n"
46 "from a system resume instead of attempting to display the\n"
47 "last provided frame buffer.");
48
Clarence Ip13a8cf42016-09-29 17:27:47 -040049#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
50 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
51
52#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
53 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
54
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040055#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
56#define PHASE_STEP_SHIFT 21
57#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
58#define PHASE_RESIDUAL 15
59
Clarence Ipe78efb72016-06-24 18:35:21 -040060#define SHARP_STRENGTH_DEFAULT 32
61#define SHARP_EDGE_THR_DEFAULT 112
62#define SHARP_SMOOTH_THR_DEFAULT 8
63#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040064
Clarence Ip5e2a9222016-06-26 22:38:24 -040065#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070066
Clarence Ipcae1bb62016-07-07 12:07:13 -040067#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
68
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080069/* multirect rect index */
70enum {
71 R0,
72 R1,
73 R_MAX
74};
75
76#define TX_MODE_BUFFER_LINE_THRES 2
77
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -070078#define SDE_QSEED3_DEFAULT_PRELOAD_H 0x4
79#define SDE_QSEED3_DEFAULT_PRELOAD_V 0x3
80
Alan Kwong4dd64c82017-02-04 18:41:51 -080081#define DEFAULT_REFRESH_RATE 60
82
Alan Kwong1a00e4d2016-07-18 09:42:30 -040083/**
84 * enum sde_plane_qos - Different qos configurations for each pipe
85 *
86 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
87 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
88 * this configuration is mutually exclusive from VBLANK_CTRL.
89 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
90 */
91enum sde_plane_qos {
92 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
93 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
94 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
95};
96
Clarence Ip5fc00c52016-09-23 15:03:34 -040097/*
98 * struct sde_plane - local sde plane structure
99 * @csc_cfg: Decoded user configuration for csc
100 * @csc_usr_ptr: Points to csc_cfg if valid user config available
101 * @csc_ptr: Points to sde_csc_cfg structure to use for current
Alan Kwong4dd64c82017-02-04 18:41:51 -0800102 * @catalog: Points to sde catalog structure
103 * @sbuf_mode: force stream buffer mode if set
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700104 * @sbuf_writeback: force stream buffer writeback if set
105 * @revalidate: force revalidation of all the plane properties
Alan Kwong4dd64c82017-02-04 18:41:51 -0800106 * @blob_rot_caps: Pointer to rotator capability blob
Clarence Ip5fc00c52016-09-23 15:03:34 -0400107 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700108struct sde_plane {
109 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400110
111 int mmu_id;
112
Clarence Ip730e7192016-06-26 22:45:09 -0400113 struct mutex lock;
114
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400115 enum sde_sspp pipe;
116 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700117 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400118 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400119
120 struct sde_hw_pipe *pipe_hw;
121 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -0400122 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -0400123 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400124 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400125 uint32_t color_fill;
126 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400127 bool is_rt_pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800128 bool is_virtual;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800129 struct sde_mdss_cfg *catalog;
130 u32 sbuf_mode;
131 u32 sbuf_writeback;
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700132 bool revalidate;
Clarence Ip4ce59322016-06-26 22:27:51 -0400133
Clarence Ipb43d4592016-09-08 14:21:35 -0400134 struct sde_hw_pixel_ext pixel_ext;
135 bool pixel_ext_usr;
136
Clarence Ip373f8592016-05-26 00:58:42 -0400137 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400138 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400139 struct sde_csc_cfg *csc_ptr;
140
Clarence Ip4c1d9772016-06-26 09:35:38 -0400141 const struct sde_sspp_sub_blks *pipe_sblk;
142
Clarence Ip5e2a9222016-06-26 22:38:24 -0400143 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400144
Clarence Ipaa0faf42016-05-30 12:07:48 -0400145 struct msm_property_info property_info;
146 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700147 struct drm_property_blob *blob_info;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800148 struct drm_property_blob *blob_rot_caps;
Clarence Ip730e7192016-06-26 22:45:09 -0400149
Clarence Ip4ce59322016-06-26 22:27:51 -0400150 /* debugfs related stuff */
151 struct dentry *debugfs_root;
152 struct sde_debugfs_regset32 debugfs_src;
153 struct sde_debugfs_regset32 debugfs_scaler;
154 struct sde_debugfs_regset32 debugfs_csc;
Clarence Ip716ab662017-03-20 06:51:24 -0700155 bool debugfs_default_scale;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700156};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700157
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700158#define to_sde_plane(x) container_of(x, struct sde_plane, base)
159
Alan Kwong4dd64c82017-02-04 18:41:51 -0800160static struct sde_kms *_sde_plane_get_kms(struct drm_plane *plane)
161{
162 struct msm_drm_private *priv;
163
164 if (!plane || !plane->dev)
165 return NULL;
166 priv = plane->dev->dev_private;
167 if (!priv)
168 return NULL;
169 return to_sde_kms(priv->kms);
170}
171
Alan Kwong4aacd532017-02-04 18:51:33 -0800172/**
173 * _sde_plane_get_crtc_state - obtain crtc state attached to given plane state
174 * @pstate: Pointer to drm plane state
175 * return: Pointer to crtc state if success; pointer error, otherwise
176 */
177static struct drm_crtc_state *_sde_plane_get_crtc_state(
178 struct drm_plane_state *pstate)
179{
180 struct drm_crtc_state *cstate;
181
182 if (!pstate || !pstate->crtc)
183 return NULL;
184
185 if (pstate->state)
186 cstate = drm_atomic_get_crtc_state(pstate->state, pstate->crtc);
187 else
188 cstate = pstate->crtc->state;
189
190 return cstate;
191}
192
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400193static bool sde_plane_enabled(struct drm_plane_state *state)
194{
Clarence Ipdbde9832016-06-26 09:48:36 -0400195 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400196}
197
Alan Kwong4dd64c82017-02-04 18:41:51 -0800198static bool sde_plane_sspp_enabled(struct drm_plane_state *state)
199{
200 return state && to_sde_plane_state(state)->rot.out_fb && state->crtc;
201}
202
203/**
204 * sde_plane_crtc_enabled - determine if crtc of given plane state is enabled
205 * @state: Pointer to drm plane state
206 * return: true if plane and the associated crtc are both enabled
207 */
208static bool sde_plane_crtc_enabled(struct drm_plane_state *state)
209{
210 return sde_plane_enabled(state) && state->crtc->state &&
211 state->crtc->state->active &&
212 state->crtc->state->enable;
213}
214
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400215/**
216 * _sde_plane_calc_fill_level - calculate fill level of the given source format
217 * @plane: Pointer to drm plane
218 * @fmt: Pointer to source buffer format
219 * @src_wdith: width of source buffer
220 * Return: fill level corresponding to the source buffer/format or 0 if error
221 */
222static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
223 const struct sde_format *fmt, u32 src_width)
224{
225 struct sde_plane *psde;
226 u32 fixed_buff_size;
227 u32 total_fl;
228
229 if (!plane || !fmt) {
230 SDE_ERROR("invalid arguments\n");
231 return 0;
232 }
233
234 psde = to_sde_plane(plane);
235 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
236
237 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
238 if (fmt->chroma_sample == SDE_CHROMA_420) {
239 /* NV12 */
240 total_fl = (fixed_buff_size / 2) /
241 ((src_width + 32) * fmt->bpp);
242 } else {
243 /* non NV12 */
244 total_fl = (fixed_buff_size) /
245 ((src_width + 32) * fmt->bpp);
246 }
247 } else {
248 total_fl = (fixed_buff_size * 2) /
249 ((src_width + 32) * fmt->bpp);
250 }
251
Dhaval Patel6c666622017-03-21 23:02:59 -0700252 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u fl:%u\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400253 plane->base.id, psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700254 (char *)&fmt->base.pixel_format,
255 src_width, total_fl);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400256
257 return total_fl;
258}
259
260/**
261 * _sde_plane_get_qos_lut_linear - get linear LUT mapping
262 * @total_fl: fill level
263 * Return: LUT setting corresponding to the fill level
264 */
265static inline u32 _sde_plane_get_qos_lut_linear(u32 total_fl)
266{
267 u32 qos_lut;
268
269 if (total_fl <= 4)
270 qos_lut = 0x1B;
271 else if (total_fl <= 5)
272 qos_lut = 0x5B;
273 else if (total_fl <= 6)
274 qos_lut = 0x15B;
275 else if (total_fl <= 7)
276 qos_lut = 0x55B;
277 else if (total_fl <= 8)
278 qos_lut = 0x155B;
279 else if (total_fl <= 9)
280 qos_lut = 0x555B;
281 else if (total_fl <= 10)
282 qos_lut = 0x1555B;
283 else if (total_fl <= 11)
284 qos_lut = 0x5555B;
285 else if (total_fl <= 12)
286 qos_lut = 0x15555B;
287 else
288 qos_lut = 0x55555B;
289
290 return qos_lut;
291}
292
293/**
294 * _sde_plane_get_qos_lut_macrotile - get macrotile LUT mapping
295 * @total_fl: fill level
296 * Return: LUT setting corresponding to the fill level
297 */
298static inline u32 _sde_plane_get_qos_lut_macrotile(u32 total_fl)
299{
300 u32 qos_lut;
301
302 if (total_fl <= 10)
303 qos_lut = 0x1AAff;
304 else if (total_fl <= 11)
305 qos_lut = 0x5AAFF;
306 else if (total_fl <= 12)
307 qos_lut = 0x15AAFF;
308 else
309 qos_lut = 0x55AAFF;
310
311 return qos_lut;
312}
313
314/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400315 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
316 * @plane: Pointer to drm plane
317 * @fb: Pointer to framebuffer associated with the given plane
318 */
319static void _sde_plane_set_qos_lut(struct drm_plane *plane,
320 struct drm_framebuffer *fb)
321{
322 struct sde_plane *psde;
323 const struct sde_format *fmt = NULL;
324 u32 qos_lut;
325 u32 total_fl = 0;
326
327 if (!plane || !fb) {
328 SDE_ERROR("invalid arguments plane %d fb %d\n",
329 plane != 0, fb != 0);
330 return;
331 }
332
333 psde = to_sde_plane(plane);
334
335 if (!psde->pipe_hw || !psde->pipe_sblk) {
336 SDE_ERROR("invalid arguments\n");
337 return;
338 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
339 return;
340 }
341
342 if (!psde->is_rt_pipe) {
343 qos_lut = psde->pipe_sblk->creq_lut_nrt;
344 } else {
345 fmt = sde_get_sde_format_ext(
346 fb->pixel_format,
347 fb->modifier,
348 drm_format_num_planes(fb->pixel_format));
349 total_fl = _sde_plane_calc_fill_level(plane, fmt,
350 psde->pipe_cfg.src_rect.w);
351
352 if (SDE_FORMAT_IS_LINEAR(fmt))
353 qos_lut = _sde_plane_get_qos_lut_linear(total_fl);
354 else
355 qos_lut = _sde_plane_get_qos_lut_macrotile(total_fl);
356 }
357
358 psde->pipe_qos_cfg.creq_lut = qos_lut;
359
360 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
361 (fmt) ? fmt->base.pixel_format : 0,
362 psde->is_rt_pipe, total_fl, qos_lut,
363 (fmt) ? SDE_FORMAT_IS_LINEAR(fmt) : 0);
364
Dhaval Patel6c666622017-03-21 23:02:59 -0700365 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%x\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400366 plane->base.id,
367 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700368 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400369 psde->is_rt_pipe, total_fl, qos_lut);
370
371 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
372}
373
374/**
375 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
376 * @plane: Pointer to drm plane
377 * @fb: Pointer to framebuffer associated with the given plane
378 */
379static void _sde_plane_set_danger_lut(struct drm_plane *plane,
380 struct drm_framebuffer *fb)
381{
382 struct sde_plane *psde;
383 const struct sde_format *fmt = NULL;
384 u32 danger_lut, safe_lut;
385
386 if (!plane || !fb) {
387 SDE_ERROR("invalid arguments\n");
388 return;
389 }
390
391 psde = to_sde_plane(plane);
392
393 if (!psde->pipe_hw || !psde->pipe_sblk) {
394 SDE_ERROR("invalid arguments\n");
395 return;
396 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
397 return;
398 }
399
400 if (!psde->is_rt_pipe) {
401 danger_lut = psde->pipe_sblk->danger_lut_nrt;
402 safe_lut = psde->pipe_sblk->safe_lut_nrt;
403 } else {
404 fmt = sde_get_sde_format_ext(
405 fb->pixel_format,
406 fb->modifier,
407 drm_format_num_planes(fb->pixel_format));
408
409 if (SDE_FORMAT_IS_LINEAR(fmt)) {
410 danger_lut = psde->pipe_sblk->danger_lut_linear;
411 safe_lut = psde->pipe_sblk->safe_lut_linear;
412 } else {
413 danger_lut = psde->pipe_sblk->danger_lut_tile;
414 safe_lut = psde->pipe_sblk->safe_lut_tile;
415 }
416 }
417
418 psde->pipe_qos_cfg.danger_lut = danger_lut;
419 psde->pipe_qos_cfg.safe_lut = safe_lut;
420
421 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
422 (fmt) ? fmt->base.pixel_format : 0,
423 (fmt) ? fmt->fetch_mode : 0,
424 psde->pipe_qos_cfg.danger_lut,
425 psde->pipe_qos_cfg.safe_lut);
426
Dhaval Patel6c666622017-03-21 23:02:59 -0700427 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400428 plane->base.id,
429 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700430 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400431 fmt ? fmt->fetch_mode : -1,
432 psde->pipe_qos_cfg.danger_lut,
433 psde->pipe_qos_cfg.safe_lut);
434
435 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
436 &psde->pipe_qos_cfg);
437}
438
439/**
440 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
441 * @plane: Pointer to drm plane
442 * @enable: true to enable QoS control
443 * @flags: QoS control mode (enum sde_plane_qos)
444 */
445static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
446 bool enable, u32 flags)
447{
448 struct sde_plane *psde;
449
450 if (!plane) {
451 SDE_ERROR("invalid arguments\n");
452 return;
453 }
454
455 psde = to_sde_plane(plane);
456
457 if (!psde->pipe_hw || !psde->pipe_sblk) {
458 SDE_ERROR("invalid arguments\n");
459 return;
460 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
461 return;
462 }
463
464 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
465 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
466 psde->pipe_qos_cfg.danger_vblank =
467 psde->pipe_sblk->danger_vblank;
468 psde->pipe_qos_cfg.vblank_en = enable;
469 }
470
471 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
472 /* this feature overrules previous VBLANK_CTRL */
473 psde->pipe_qos_cfg.vblank_en = false;
474 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
475 }
476
477 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
478 psde->pipe_qos_cfg.danger_safe_en = enable;
479
480 if (!psde->is_rt_pipe) {
481 psde->pipe_qos_cfg.vblank_en = false;
482 psde->pipe_qos_cfg.danger_safe_en = false;
483 }
484
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400485 SDE_DEBUG("plane%u: pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400486 plane->base.id,
487 psde->pipe - SSPP_VIG0,
488 psde->pipe_qos_cfg.danger_safe_en,
489 psde->pipe_qos_cfg.vblank_en,
490 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400491 psde->pipe_qos_cfg.danger_vblank,
492 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400493
494 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
495 &psde->pipe_qos_cfg);
496}
497
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700498void sde_plane_set_revalidate(struct drm_plane *plane, bool enable)
499{
500 struct sde_plane *psde;
501
502 if (!plane)
503 return;
504
505 psde = to_sde_plane(plane);
506 psde->revalidate = enable;
507}
508
Alan Kwongf0fd8512016-10-24 21:39:26 -0400509int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
510{
511 struct sde_plane *psde;
512 struct msm_drm_private *priv;
513 struct sde_kms *sde_kms;
514
515 if (!plane || !plane->dev) {
516 SDE_ERROR("invalid arguments\n");
517 return -EINVAL;
518 }
519
520 priv = plane->dev->dev_private;
521 if (!priv || !priv->kms) {
522 SDE_ERROR("invalid KMS reference\n");
523 return -EINVAL;
524 }
525
526 sde_kms = to_sde_kms(priv->kms);
527 psde = to_sde_plane(plane);
528
529 if (!psde->is_rt_pipe)
530 goto end;
531
532 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
533
534 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
535
536 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
537
538end:
539 return 0;
540}
541
Alan Kwong5d324e42016-07-28 22:56:18 -0400542/**
543 * _sde_plane_set_ot_limit - set OT limit for the given plane
544 * @plane: Pointer to drm plane
545 * @crtc: Pointer to drm crtc
546 */
547static void _sde_plane_set_ot_limit(struct drm_plane *plane,
548 struct drm_crtc *crtc)
549{
550 struct sde_plane *psde;
551 struct sde_vbif_set_ot_params ot_params;
552 struct msm_drm_private *priv;
553 struct sde_kms *sde_kms;
554
555 if (!plane || !plane->dev || !crtc) {
556 SDE_ERROR("invalid arguments plane %d crtc %d\n",
557 plane != 0, crtc != 0);
558 return;
559 }
560
561 priv = plane->dev->dev_private;
562 if (!priv || !priv->kms) {
563 SDE_ERROR("invalid KMS reference\n");
564 return;
565 }
566
567 sde_kms = to_sde_kms(priv->kms);
568 psde = to_sde_plane(plane);
569 if (!psde->pipe_hw) {
570 SDE_ERROR("invalid pipe reference\n");
571 return;
572 }
573
574 memset(&ot_params, 0, sizeof(ot_params));
575 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
576 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
577 ot_params.width = psde->pipe_cfg.src_rect.w;
578 ot_params.height = psde->pipe_cfg.src_rect.h;
579 ot_params.is_wfd = !psde->is_rt_pipe;
580 ot_params.frame_rate = crtc->mode.vrefresh;
581 ot_params.vbif_idx = VBIF_RT;
582 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
583 ot_params.rd = true;
584
585 sde_vbif_set_ot_limit(sde_kms, &ot_params);
586}
587
Clarence Ipcae1bb62016-07-07 12:07:13 -0400588/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400589static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400590 struct sde_plane_state *pstate, uint64_t fd)
591{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400592 if (!psde || !pstate) {
593 SDE_ERROR("invalid arg(s), plane %d state %d\n",
594 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400595 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400596 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400597
598 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400599 if (pstate->input_fence)
600 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400601
602 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400603 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400604
Clarence Ip13a8cf42016-09-29 17:27:47 -0400605 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400606}
607
Clarence Ipcae1bb62016-07-07 12:07:13 -0400608int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400609{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400610 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400611 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400612 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400613 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400614 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800615 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400616
617 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700618 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400619 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400620 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400621 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400622 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400623 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400624 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400625
Clarence Ipcae1bb62016-07-07 12:07:13 -0400626 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800627 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400628 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800629 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400630
Dhaval Patel39323d42017-03-01 23:48:24 -0800631 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400632 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400633 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
634 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400635 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800636 ret = -ETIMEDOUT;
637 break;
638 case -ERESTARTSYS:
639 SDE_ERROR_PLANE(psde,
640 "%ums wait interrupted on %08X\n",
641 wait_ms, prefix);
642 psde->is_error = true;
643 ret = -ERESTARTSYS;
644 break;
645 case -EINVAL:
646 SDE_ERROR_PLANE(psde,
647 "invalid fence param for %08X\n",
648 prefix);
649 psde->is_error = true;
650 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400651 break;
652 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800653 SDE_DEBUG_PLANE(psde, "signaled\n");
654 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400655 break;
656 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700657
658 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400659 } else {
660 ret = 0;
661 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400662 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400663 return ret;
664}
665
Clarence Ip282dad62016-09-27 17:07:35 -0400666static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400667 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400668 struct sde_hw_pipe_cfg *pipe_cfg,
669 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400670{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400671 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400672 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400673
Clarence Ip13a8cf42016-09-29 17:27:47 -0400674 if (!plane || !pstate || !pipe_cfg || !fb) {
675 SDE_ERROR(
676 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
677 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400678 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400679 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400680
681 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400682 if (!psde->pipe_hw) {
683 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400684 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400685 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400686
Clarence Ipb6eb2362016-09-08 16:18:13 -0400687 ret = sde_format_populate_layout(psde->mmu_id, fb, &pipe_cfg->layout);
688 if (ret == -EAGAIN)
689 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
690 else if (ret)
691 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
692 else if (psde->pipe_hw->ops.setup_sourceaddress)
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800693 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
694 pstate->multirect_index);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400695}
696
abeykun48f407a2016-08-25 12:06:44 -0400697static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
698 struct sde_plane_state *pstate)
699{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500700 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400701 int ret = 0;
702
Clarence Ip3bf8d872017-02-16 15:25:38 -0500703 if (!psde || !psde->scaler3_cfg) {
704 SDE_ERROR("invalid args\n");
705 return -EINVAL;
706 } else if (!pstate) {
707 /* pstate is expected to be null on forced color fill */
708 SDE_DEBUG("null pstate\n");
709 return -EINVAL;
710 }
711
712 cfg = psde->scaler3_cfg;
713
abeykun48f407a2016-08-25 12:06:44 -0400714 cfg->dir_lut = msm_property_get_blob(
715 &psde->property_info,
716 pstate->property_blobs, &cfg->dir_len,
717 PLANE_PROP_SCALER_LUT_ED);
718 cfg->cir_lut = msm_property_get_blob(
719 &psde->property_info,
720 pstate->property_blobs, &cfg->cir_len,
721 PLANE_PROP_SCALER_LUT_CIR);
722 cfg->sep_lut = msm_property_get_blob(
723 &psde->property_info,
724 pstate->property_blobs, &cfg->sep_len,
725 PLANE_PROP_SCALER_LUT_SEP);
726 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
727 ret = -ENODATA;
728 return ret;
729}
730
Clarence Ipcb410d42016-06-26 22:52:33 -0400731static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400732 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
733 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400734 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400735 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
736{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700737 uint32_t decimated, i;
738
739 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
740 !chroma_subsmpl_v) {
741 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
742 , psde, scale_cfg, fmt, chroma_subsmpl_h,
743 chroma_subsmpl_v);
744 return;
745 }
746
747 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip716ab662017-03-20 06:51:24 -0700748 memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700749
750 decimated = DECIMATED_DIMENSION(src_w,
751 psde->pipe_cfg.horz_decimation);
752 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
753 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
754 decimated = DECIMATED_DIMENSION(src_h,
755 psde->pipe_cfg.vert_decimation);
756 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
757 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
758
759
760 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
761 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
762 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
763 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
764
765 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
766 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
767 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
768 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
769
770 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
771 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
772 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
773 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
774
775 for (i = 0; i < SDE_MAX_PLANES; i++) {
776 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
777 psde->pipe_cfg.horz_decimation);
778 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
779 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700780 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
781 scale_cfg->src_width[i] /= chroma_subsmpl_h;
782 scale_cfg->src_height[i] /= chroma_subsmpl_v;
783 }
784 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
785 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
786 psde->pixel_ext.num_ext_pxls_top[i] =
787 scale_cfg->src_height[i];
788 psde->pixel_ext.num_ext_pxls_left[i] =
789 scale_cfg->src_width[i];
790 }
791 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
792 && (src_w == dst_w))
793 return;
794
795 scale_cfg->dst_width = dst_w;
796 scale_cfg->dst_height = dst_h;
797 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
798 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
799 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
800 scale_cfg->lut_flag = 0;
801 scale_cfg->blend_cfg = 1;
802 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -0400803}
804
Clarence Ipcb410d42016-06-26 22:52:33 -0400805/**
Clarence Ip13a8cf42016-09-29 17:27:47 -0400806 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -0400807 * @psde: Pointer to SDE plane object
808 * @src: Source size
809 * @dst: Destination size
810 * @phase_steps: Pointer to output array for phase steps
811 * @filter: Pointer to output array for filter type
812 * @fmt: Pointer to format definition
813 * @chroma_subsampling: Subsampling amount for chroma channel
814 *
815 * Returns: 0 on success
816 */
817static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400818 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400819 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400820 uint32_t chroma_subsampling)
821{
Clarence Ipcb410d42016-06-26 22:52:33 -0400822 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400823 SDE_ERROR(
824 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
825 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -0400826 return -EINVAL;
827 }
828
Clarence Ip4c1d9772016-06-26 09:35:38 -0400829 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -0400830 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400831 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -0400832 phase_steps[SDE_SSPP_COMP_1_2] =
833 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
834 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
835 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400836
837 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -0400838 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -0400839 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400840 (src <= dst) ? SDE_SCALE_FILTER_BIL :
841 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400842
Clarence Ipdbde9832016-06-26 09:48:36 -0400843 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400844 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -0400845 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
846 } else {
847 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
848 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400849 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -0400850 }
851 } else {
852 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400853 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
854 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
855 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400856 }
Clarence Ipcb410d42016-06-26 22:52:33 -0400857 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400858}
859
Clarence Ipcb410d42016-06-26 22:52:33 -0400860/**
861 * _sde_plane_setup_pixel_ext - determine default pixel extension values
862 * @psde: Pointer to SDE plane object
863 * @src: Source size
864 * @dst: Destination size
865 * @decimated_src: Source size after decimation, if any
866 * @phase_steps: Pointer to output array for phase steps
867 * @out_src: Output array for pixel extension values
868 * @out_edge1: Output array for pixel extension first edge
869 * @out_edge2: Output array for pixel extension second edge
870 * @filter: Pointer to array for filter type
871 * @fmt: Pointer to format definition
872 * @chroma_subsampling: Subsampling amount for chroma channel
873 * @post_compare: Whether to chroma subsampled source size for comparisions
874 */
875static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400876 uint32_t src, uint32_t dst, uint32_t decimated_src,
877 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -0400878 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400879 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -0400880 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400881{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400882 int64_t edge1, edge2, caf;
883 uint32_t src_work;
884 int i, tmp;
885
Clarence Ipcb410d42016-06-26 22:52:33 -0400886 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -0400887 out_edge2 && filter && fmt) {
888 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400889 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400890 caf = PHASE_STEP_UNIT_SCALE;
891 else
892 caf = 0;
893
894 for (i = 0; i < SDE_MAX_PLANES; i++) {
895 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -0400896 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400897 src_work /= chroma_subsampling;
898 if (post_compare)
899 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -0400900 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400901 /* unity */
902 edge1 = 0;
903 edge2 = 0;
904 } else if (dst >= src) {
905 /* upscale */
906 edge1 = (1 << PHASE_RESIDUAL);
907 edge1 -= caf;
908 edge2 = (1 << PHASE_RESIDUAL);
909 edge2 += (dst - 1) * *(phase_steps + i);
910 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
911 edge2 += caf;
912 edge2 = -(edge2);
913 } else {
914 /* downscale */
915 edge1 = 0;
916 edge2 = (dst - 1) * *(phase_steps + i);
917 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
918 edge2 += *(phase_steps + i);
919 edge2 = -(edge2);
920 }
921
922 /* only enable CAF for luma plane */
923 caf = 0;
924
925 /* populate output arrays */
926 *(out_src + i) = src_work;
927
928 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400929 if (edge1 >= 0) {
930 tmp = (uint32_t)edge1;
931 tmp >>= PHASE_STEP_SHIFT;
932 *(out_edge1 + i) = -tmp;
933 } else {
934 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -0400935 *(out_edge1 + i) =
936 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
937 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400938 }
939 if (edge2 >= 0) {
940 tmp = (uint32_t)edge2;
941 tmp >>= PHASE_STEP_SHIFT;
942 *(out_edge2 + i) = -tmp;
943 } else {
944 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -0400945 *(out_edge2 + i) =
946 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
947 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400948 }
949 }
950 }
951}
952
Clarence Ip5fc00c52016-09-23 15:03:34 -0400953static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -0400954{
955 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
956 {
Clarence Ip373f8592016-05-26 00:58:42 -0400957 /* S15.16 format */
958 0x00012A00, 0x00000000, 0x00019880,
959 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
960 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -0400961 },
Clarence Ip373f8592016-05-26 00:58:42 -0400962 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -0400963 { 0xfff0, 0xff80, 0xff80,},
964 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400965 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -0400966 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -0400967 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -0400968 };
abeykun1c312f62016-08-26 09:47:12 -0400969 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
970 {
971 /* S15.16 format */
972 0x00012A00, 0x00000000, 0x00019880,
973 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
974 0x00012A00, 0x00020480, 0x00000000,
975 },
976 /* signed bias */
977 { 0xffc0, 0xfe00, 0xfe00,},
978 { 0x0, 0x0, 0x0,},
979 /* unsigned clamp */
980 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
981 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
982 };
Clarence Ipe78efb72016-06-24 18:35:21 -0400983
Clarence Ip5fc00c52016-09-23 15:03:34 -0400984 if (!psde) {
985 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -0400986 return;
987 }
Clarence Ip5e2a9222016-06-26 22:38:24 -0400988
Clarence Ipcae1bb62016-07-07 12:07:13 -0400989 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -0400990 if (psde->csc_usr_ptr)
991 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -0400992 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
993 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400994 else
Clarence Ip373f8592016-05-26 00:58:42 -0400995 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400996
Clarence Ip13a8cf42016-09-29 17:27:47 -0400997 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -0400998 psde->csc_ptr->csc_mv[0],
999 psde->csc_ptr->csc_mv[1],
1000 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -04001001}
1002
Benet Clarkeb1b4462016-06-27 14:43:06 -07001003static void sde_color_process_plane_setup(struct drm_plane *plane)
1004{
1005 struct sde_plane *psde;
1006 struct sde_plane_state *pstate;
1007 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001008 struct drm_msm_memcol *memcol = NULL;
1009 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001010
1011 psde = to_sde_plane(plane);
1012 pstate = to_sde_plane_state(plane->state);
1013
1014 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1015 if (psde->pipe_hw->ops.setup_pa_hue)
1016 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1017 saturation = (uint32_t) sde_plane_get_property(pstate,
1018 PLANE_PROP_SATURATION_ADJUST);
1019 if (psde->pipe_hw->ops.setup_pa_sat)
1020 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1021 value = (uint32_t) sde_plane_get_property(pstate,
1022 PLANE_PROP_VALUE_ADJUST);
1023 if (psde->pipe_hw->ops.setup_pa_val)
1024 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1025 contrast = (uint32_t) sde_plane_get_property(pstate,
1026 PLANE_PROP_CONTRAST_ADJUST);
1027 if (psde->pipe_hw->ops.setup_pa_cont)
1028 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001029
Benet Clarkd009b1d2016-06-27 14:45:59 -07001030 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1031 /* Skin memory color setup */
1032 memcol = msm_property_get_blob(&psde->property_info,
1033 pstate->property_blobs,
1034 &memcol_sz,
1035 PLANE_PROP_SKIN_COLOR);
1036 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1037 MEMCOLOR_SKIN, memcol);
1038
1039 /* Sky memory color setup */
1040 memcol = msm_property_get_blob(&psde->property_info,
1041 pstate->property_blobs,
1042 &memcol_sz,
1043 PLANE_PROP_SKY_COLOR);
1044 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1045 MEMCOLOR_SKY, memcol);
1046
1047 /* Foliage memory color setup */
1048 memcol = msm_property_get_blob(&psde->property_info,
1049 pstate->property_blobs,
1050 &memcol_sz,
1051 PLANE_PROP_FOLIAGE_COLOR);
1052 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1053 MEMCOLOR_FOLIAGE, memcol);
1054 }
1055}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001056
Clarence Ipcb410d42016-06-26 22:52:33 -04001057static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001058 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -04001059 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001060{
Clarence Ipb43d4592016-09-08 14:21:35 -04001061 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001062 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001063
Clarence Ipb43d4592016-09-08 14:21:35 -04001064 if (!psde || !fmt) {
1065 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1066 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001067 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001068 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001069
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001070 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001071
Clarence Ipdedbba92016-09-27 17:43:10 -04001072 psde->pipe_cfg.horz_decimation =
1073 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1074 psde->pipe_cfg.vert_decimation =
1075 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001076
1077 /* don't chroma subsample if decimating */
1078 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001079 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001080 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001081 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001082
Clarence Ip5e2a9222016-06-26 22:38:24 -04001083 /* update scaler */
1084 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001085 int error;
1086
1087 error = _sde_plane_setup_scaler3_lut(psde, pstate);
Clarence Ip716ab662017-03-20 06:51:24 -07001088 if (error || !psde->pixel_ext_usr ||
1089 psde->debugfs_default_scale) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001090 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001091 _sde_plane_setup_scaler3(psde,
1092 psde->pipe_cfg.src_rect.w,
1093 psde->pipe_cfg.src_rect.h,
1094 psde->pipe_cfg.dst_rect.w,
1095 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001096 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001097 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001098 }
Clarence Ip716ab662017-03-20 06:51:24 -07001099 } else if (!psde->pixel_ext_usr || !pstate ||
1100 psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001101 uint32_t deci_dim, i;
1102
Clarence Ipb43d4592016-09-08 14:21:35 -04001103 /* calculate default configuration for QSEED2 */
1104 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001105
Clarence Ip13a8cf42016-09-29 17:27:47 -04001106 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001107 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1108 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001109 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001110 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001111 psde->pipe_cfg.dst_rect.w,
1112 pe->phase_step_x,
1113 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001114
Clarence Ipdbde9832016-06-26 09:48:36 -04001115 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001116 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001117 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001118 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001119 pe->phase_step_x,
1120 pe->roi_w,
1121 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001122 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001123 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001124
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001125 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001126 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001127 _sde_plane_setup_scaler2(psde,
1128 deci_dim,
1129 psde->pipe_cfg.dst_rect.h,
1130 pe->phase_step_y,
1131 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001132 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001133 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001134 pe->phase_step_y,
1135 pe->roi_h,
1136 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001137 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001138 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001139
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001140 for (i = 0; i < SDE_MAX_PLANES; i++) {
1141 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001142 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001143 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001144 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001145
1146 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001147 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001148 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001149 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001150
1151 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001152 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001153 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001154 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001155
1156 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001157 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001158 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001159 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001160 }
1161 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001162}
1163
Clarence Ipcae1bb62016-07-07 12:07:13 -04001164/**
1165 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001166 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001167 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1168 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1169 * Returns: 0 on success
1170 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001171static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001172 uint32_t color, uint32_t alpha)
1173{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001174 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001175 const struct drm_plane *plane;
1176 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001177
Clarence Ip13a8cf42016-09-29 17:27:47 -04001178 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001179 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001180 return -EINVAL;
1181 }
1182
Clarence Ipcb410d42016-06-26 22:52:33 -04001183 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001184 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001185 return -EINVAL;
1186 }
1187
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001188 plane = &psde->base;
1189 pstate = to_sde_plane_state(plane->state);
1190
Clarence Ip13a8cf42016-09-29 17:27:47 -04001191 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001192
Clarence Ipcb410d42016-06-26 22:52:33 -04001193 /*
1194 * select fill format to match user property expectation,
1195 * h/w only supports RGB variants
1196 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001197 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001198
1199 /* update sspp */
1200 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1201 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001202 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1203 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001204
1205 /* override scaler/decimation if solid fill */
1206 psde->pipe_cfg.src_rect.x = 0;
1207 psde->pipe_cfg.src_rect.y = 0;
1208 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1209 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Dhaval Patele4b6bb22017-03-27 17:22:21 -07001210 _sde_plane_setup_scaler(psde, fmt, 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001211
Clarence Ipcb410d42016-06-26 22:52:33 -04001212 if (psde->pipe_hw->ops.setup_format)
1213 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001214 fmt, SDE_SSPP_SOLID_FILL,
1215 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001216
1217 if (psde->pipe_hw->ops.setup_rects)
1218 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001219 &psde->pipe_cfg,
1220 pstate->multirect_index);
1221
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001222 if (psde->pipe_hw->ops.setup_pe)
1223 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1224 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001225 }
1226
1227 return 0;
1228}
1229
Alan Kwong4dd64c82017-02-04 18:41:51 -08001230/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001231 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1232 */
1233static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1234{
1235 drm_framebuffer_reference(fb);
1236 return fb;
1237}
1238static void _sde_plane_fb_put(void *fb)
1239{
1240 drm_framebuffer_unreference(fb);
1241}
1242static struct sde_crtc_res_ops fb_res_ops = {
1243 .put = _sde_plane_fb_put,
1244 .get = _sde_plane_fb_get,
1245};
1246
1247/**
1248 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1249 */
1250static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1251{
1252 sde_kms_fbo_reference(fbo);
1253 return fbo;
1254}
1255static void _sde_plane_fbo_put(void *fbo)
1256{
1257 sde_kms_fbo_unreference(fbo);
1258}
1259static struct sde_crtc_res_ops fbo_res_ops = {
1260 .put = _sde_plane_fbo_put,
1261 .get = _sde_plane_fbo_get,
1262};
1263
1264/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001265 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001266 * @plane: Pointer to drm plane
1267 * return: prefill time in line
1268 */
1269static u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
1270{
1271 struct drm_plane_state *state;
1272 struct drm_crtc_state *cstate;
1273 struct sde_plane_state *pstate;
1274 struct sde_plane_rot_state *rstate;
1275 struct sde_kms *sde_kms;
1276 u32 blocksize = 128;
1277 u32 prefill_line = 0;
1278
1279 if (!plane || !plane->state || !plane->state->fb ||
1280 !plane->state->crtc || !plane->state->crtc->state) {
1281 SDE_ERROR("invalid parameters\n");
1282 return 0;
1283 }
1284
1285 sde_kms = _sde_plane_get_kms(plane);
1286 state = plane->state;
1287 cstate = state->crtc->state;
1288 pstate = to_sde_plane_state(state);
1289 rstate = &pstate->rot;
1290
1291 if (!rstate->rot_hw || !rstate->rot_hw->caps || !rstate->out_src_h ||
1292 !sde_kms || !sde_kms->catalog) {
1293 SDE_ERROR("invalid parameters\n");
1294 return 0;
1295 }
1296
Alan Kwong4aacd532017-02-04 18:51:33 -08001297 sde_format_get_block_size(rstate->out_fb_format, &blocksize,
1298 &blocksize);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001299 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
1300
1301 SDE_DEBUG("plane%d prefill:%u\n", plane->base.id, prefill_line);
1302
1303 return prefill_line;
1304}
1305
1306/**
1307 * sde_plane_is_sbuf_mode - check if sspp of given plane is in streaming
1308 * buffer mode
1309 * @plane: Pointer to drm plane
1310 * @prefill: Pointer to prefill line count
1311 * return: true if sspp is in stream buffer mode
1312 */
1313bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill)
1314{
1315 struct sde_plane_state *pstate = plane && plane->state ?
1316 to_sde_plane_state(plane->state) : NULL;
1317 struct sde_plane_rot_state *rstate = pstate ? &pstate->rot : NULL;
1318 bool sbuf_mode = rstate ? rstate->out_sbuf : false;
1319
1320 if (prefill && sbuf_mode)
1321 *prefill = sde_plane_rot_calc_prefill(plane);
1322
1323 return sbuf_mode;
1324}
1325
1326/**
1327 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1328 * enumerating over all planes attached to the same rotator
1329 * @plane: Pointer to drm plane
1330 * @state: Pointer to drm state to be updated
1331 * return: none
1332 */
1333static void sde_plane_rot_calc_cfg(struct drm_plane *plane,
1334 struct drm_plane_state *state)
1335{
1336 struct sde_plane_state *pstate;
1337 struct sde_plane_rot_state *rstate;
1338 struct sde_hw_blk *hw_blk;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001339 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001340 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001341 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001342 u32 dst_x, dst_y, dst_w, dst_h;
1343 int found = 0;
1344 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001345 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001346
1347 if (!plane || !state || !state->state) {
1348 SDE_ERROR("invalid parameters\n");
1349 return;
1350 }
1351
Alan Kwongcdb2f282017-03-18 13:42:06 -07001352 cstate = _sde_plane_get_crtc_state(state);
1353 if (IS_ERR_OR_NULL(cstate)) {
1354 ret = PTR_ERR(cstate);
1355 SDE_ERROR("invalid crtc state %d\n", ret);
1356 return;
1357 }
1358
Alan Kwong4dd64c82017-02-04 18:41:51 -08001359 pstate = to_sde_plane_state(state);
1360 rstate = &pstate->rot;
1361
1362 if (!rstate->rot_hw) {
1363 SDE_ERROR("invalid rotator hw\n");
1364 return;
1365 }
1366
1367 in_rot = &rstate->in_rot_rect;
1368 in_rot->x1 = state->src_x;
1369 in_rot->y1 = state->src_y;
1370 in_rot->x2 = state->src_x + state->src_w;
1371 in_rot->y2 = state->src_y + state->src_h;
1372
1373 out_rot = &rstate->out_rot_rect;
1374 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1375 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1376 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1377 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1378
1379 if (!dst_w && !dst_h) {
1380 rstate->out_rot_rect = rstate->in_rot_rect;
1381 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1382 state->fb->height << 16, rstate->in_rotation);
1383 } else {
1384 out_rot->x1 = dst_x;
1385 out_rot->y1 = dst_y;
1386 out_rot->x2 = dst_x + dst_w;
1387 out_rot->y2 = dst_y + dst_h;
1388 }
1389
1390 rstate->out_src_rect = rstate->out_rot_rect;
1391
1392 hw_blk = &rstate->rot_hw->base;
1393
1394 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001395 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001396 struct drm_plane_state *attached_state;
1397 struct sde_plane_state *attached_pstate;
1398 struct sde_plane_rot_state *attached_rstate;
1399 struct drm_rect attached_out_rect;
1400
Alan Kwong4dd64c82017-02-04 18:41:51 -08001401 attached_state = drm_atomic_get_existing_plane_state(
1402 state->state, attached_plane);
1403
1404 if (!attached_state)
1405 continue;
1406
1407 attached_pstate = to_sde_plane_state(attached_state);
1408 attached_rstate = &attached_pstate->rot;
1409
Alan Kwongcdb2f282017-03-18 13:42:06 -07001410 if (attached_rstate->rot_hw != rstate->rot_hw)
1411 continue;
1412
1413 found++;
1414
1415 /* skip itself */
1416 if (attached_plane == plane)
1417 continue;
1418
Alan Kwong4dd64c82017-02-04 18:41:51 -08001419 /* find bounding rotator source roi */
1420 if (attached_state->src_x < in_rot->x1)
1421 in_rot->x1 = attached_state->src_x;
1422
1423 if (attached_state->src_y < in_rot->y1)
1424 in_rot->y1 = attached_state->src_y;
1425
1426 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1427 in_rot->x2 = attached_state->src_x +
1428 attached_state->src_w;
1429
1430 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1431 in_rot->y2 = attached_state->src_y +
1432 attached_state->src_h;
1433
1434 /* find bounding rotator destination roi */
1435 dst_x = sde_plane_get_property(attached_pstate,
1436 PLANE_PROP_ROT_DST_X);
1437 dst_y = sde_plane_get_property(attached_pstate,
1438 PLANE_PROP_ROT_DST_Y);
1439 dst_w = sde_plane_get_property(attached_pstate,
1440 PLANE_PROP_ROT_DST_W);
1441 dst_h = sde_plane_get_property(attached_pstate,
1442 PLANE_PROP_ROT_DST_H);
1443 if (!dst_w && !dst_h) {
1444 attached_out_rect.x1 = attached_state->src_x;
1445 attached_out_rect.y1 = attached_state->src_y;
1446 attached_out_rect.x2 = attached_out_rect.x1 +
1447 attached_state->src_w;
1448 attached_out_rect.y2 = attached_out_rect.y1 +
1449 attached_state->src_h;
1450 drm_rect_rotate(&attached_out_rect,
1451 state->fb->width << 16,
1452 state->fb->height << 16,
1453 rstate->in_rotation);
1454 } else {
1455 attached_out_rect.x1 = dst_x;
1456 attached_out_rect.y1 = dst_y;
1457 attached_out_rect.x2 = dst_x + dst_w;
1458 attached_out_rect.y2 = dst_y + dst_h;
1459 }
1460
1461 /* find relative sspp position */
1462 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1463 xpos++;
1464
1465 if (attached_out_rect.x1 < out_rot->x1)
1466 out_rot->x1 = attached_out_rect.x1;
1467
1468 if (attached_out_rect.y1 < out_rot->y1)
1469 out_rot->y1 = attached_out_rect.y1;
1470
1471 if (attached_out_rect.x2 > out_rot->x2)
1472 out_rot->x2 = attached_out_rect.x2;
1473
1474 if (attached_out_rect.y2 > out_rot->y2)
1475 out_rot->y2 = attached_out_rect.y2;
1476
1477 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1478 attached_plane->base.id,
1479 attached_rstate->sequence_id,
1480 attached_rstate->out_src_rect.x1 >> 16,
1481 attached_state->src_w >> 16,
1482 attached_state->src_h >> 16,
1483 attached_state->src_x >> 16,
1484 attached_state->src_y >> 16,
1485 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1486 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1487 attached_rstate->out_src_rect.x1 >> 16,
1488 attached_rstate->out_src_rect.y1 >> 16);
1489 }
1490
1491 rstate->out_xpos = xpos;
1492 rstate->nplane = found;
1493
1494 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1495 plane->base.id, rstate->sequence_id,
1496 rstate->out_xpos, rstate->nplane,
1497 drm_rect_width(in_rot) >> 16,
1498 drm_rect_height(in_rot) >> 16,
1499 in_rot->x1 >> 16, in_rot->y1 >> 16,
1500 drm_rect_width(&rstate->out_rot_rect) >> 16,
1501 drm_rect_height(&rstate->out_rot_rect) >> 16,
1502 rstate->out_rot_rect.x1 >> 16,
1503 rstate->out_rot_rect.y1 >> 16);
1504}
1505
1506/**
1507 * sde_plane_rot_submit_command - commit given state for the rotator stage
1508 * @plane: Pointer to drm plane
1509 * @state: Pointer to the state to be committed
1510 * @hw_cmd: rotator command type
1511 * return: 0 if success; error code otherwise
1512 */
1513static int sde_plane_rot_submit_command(struct drm_plane *plane,
1514 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1515{
1516 struct sde_plane *psde = to_sde_plane(plane);
1517 struct sde_plane_state *pstate = to_sde_plane_state(state);
1518 struct sde_plane_rot_state *rstate = &pstate->rot;
1519 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001520 struct drm_crtc_state *cstate;
1521 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001522 int ret, i;
1523
1524 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1525 SDE_ERROR("invalid parameters\n");
1526 return -EINVAL;
1527 }
1528
Alan Kwong4aacd532017-02-04 18:51:33 -08001529 cstate = _sde_plane_get_crtc_state(state);
1530 if (IS_ERR_OR_NULL(cstate)) {
1531 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1532 return -EINVAL;
1533 }
1534 sde_cstate = to_sde_crtc_state(cstate);
1535
Alan Kwong4dd64c82017-02-04 18:41:51 -08001536 rot_cmd = &rstate->rot_cmd;
1537
1538 rot_cmd->master = (rstate->out_xpos == 0);
1539 rot_cmd->sequence_id = rstate->sequence_id;
1540 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1541 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1542 DEFAULT_REFRESH_RATE;
1543 rot_cmd->rot90 = rstate->rot90;
1544 rot_cmd->hflip = rstate->hflip;
1545 rot_cmd->vflip = rstate->vflip;
1546 rot_cmd->secure = state->fb->flags & DRM_MODE_FB_SECURE ? true : false;
Alan Kwong4aacd532017-02-04 18:51:33 -08001547 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1548 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001549 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1550 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001551 rot_cmd->dst_writeback = psde->sbuf_writeback;
1552
1553 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1554 rot_cmd->video_mode = true;
1555 else
1556 rot_cmd->video_mode = false;
1557
1558 rot_cmd->src_pixel_format = state->fb->pixel_format;
1559 rot_cmd->src_modifier = state->fb->modifier[0];
1560 rot_cmd->src_stride = state->fb->pitches[0];
1561
1562 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1563 if (!rot_cmd->src_format) {
1564 SDE_ERROR("failed to get src format\n");
1565 return -EINVAL;
1566 }
1567
1568 rot_cmd->src_width = state->fb->width;
1569 rot_cmd->src_height = state->fb->height;
1570 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1571 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1572 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1573 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
1574 rot_cmd->dst_rect_x = rstate->out_rot_rect.x1 >> 16;
1575 rot_cmd->dst_rect_y = rstate->out_rot_rect.y1 >> 16;
1576 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1577 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1578
1579 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1580 struct sde_hw_fmt_layout layout;
1581
1582 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1583 sde_format_populate_layout(rstate->mmu_id, state->fb,
1584 &layout);
1585 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1586 rot_cmd->src_iova[i] = layout.plane_addr[i];
1587 rot_cmd->src_len[i] = layout.plane_size[i];
1588 }
1589 rot_cmd->src_planes = layout.num_planes;
1590
1591 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
1592 sde_format_populate_layout(rstate->mmu_id, rstate->out_fb,
1593 &layout);
1594 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1595 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1596 rot_cmd->dst_len[i] = layout.plane_size[i];
1597 }
1598 rot_cmd->dst_planes = layout.num_planes;
1599 }
1600
1601 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
1602 if (ret) {
1603 SDE_ERROR("failed to commit rotator %d\n", ret);
1604 return ret;
1605 }
1606
1607 rstate->out_rotation = rstate->in_rotation;
1608 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1609 DRM_MODE_FB_MODIFIERS : 0;
1610 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1611 rstate->out_fb_format = rot_cmd->dst_format;
1612 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1613
1614 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1615 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1616
1617 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1618 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1619 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1620 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1621 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1622 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1623
1624 if (rot_cmd->rot90)
1625 rstate->out_rotation &= ~DRM_ROTATE_90;
1626
1627 if (rot_cmd->hflip)
1628 rstate->out_rotation &= ~DRM_REFLECT_X;
1629
1630 if (rot_cmd->vflip)
1631 rstate->out_rotation &= ~DRM_REFLECT_Y;
1632
1633 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07001634 "plane%d.%d rot:%d/%c%c%c%c/%dx%d/%4.4s/%llx/%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001635 plane->base.id, rstate->sequence_id, hw_cmd,
1636 rot_cmd->rot90 ? 'r' : '_',
1637 rot_cmd->hflip ? 'h' : '_',
1638 rot_cmd->vflip ? 'v' : '_',
1639 rot_cmd->video_mode ? 'V' : 'C',
1640 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001641 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001642 state->fb->modifier[0],
1643 drm_rect_width(&rstate->in_rot_rect) >> 16,
1644 drm_rect_height(&rstate->in_rot_rect) >> 16,
1645 rstate->in_rot_rect.x1 >> 16,
1646 rstate->in_rot_rect.y1 >> 16);
1647
Dhaval Patel6c666622017-03-21 23:02:59 -07001648 SDE_DEBUG("plane%d.%d sspp:%d/%x/%dx%d/%4.4s/%llx/%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001649 plane->base.id, rstate->sequence_id, hw_cmd,
1650 rstate->out_rotation,
1651 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001652 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001653 rstate->out_fb_modifier[0],
1654 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
1655 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
1656
1657 return ret;
1658}
1659
1660/**
1661 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
1662 * for rotator (pre-sspp) stage
1663 * @plane: Pointer to drm plane
1664 * @new_state: Pointer to new drm plane state
1665 * return: 0 if success; error code otherwise
1666 */
1667static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
1668 struct drm_plane_state *new_state)
1669{
1670 struct drm_framebuffer *fb = new_state->fb;
1671 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
1672 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001673 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001674 int ret;
1675
1676 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
1677 plane->base.id,
1678 new_rstate->sequence_id, fb ? fb->base.id : 0,
1679 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
1680 sde_plane_crtc_enabled(new_state));
1681
1682 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
1683 return 0;
1684
Alan Kwongcdb2f282017-03-18 13:42:06 -07001685 cstate = _sde_plane_get_crtc_state(new_state);
1686 if (IS_ERR(cstate)) {
1687 ret = PTR_ERR(cstate);
1688 SDE_ERROR("invalid crtc state %d\n", ret);
1689 return ret;
1690 }
1691
Alan Kwong4dd64c82017-02-04 18:41:51 -08001692 /* need to re-calc based on all newly validated plane states */
1693 sde_plane_rot_calc_cfg(plane, new_state);
1694
1695 /* check if stream buffer is already attached to rotator */
1696 if (sde_plane_enabled(new_state)) {
1697 struct sde_kms_fbo *fbo;
1698 struct drm_framebuffer *fb;
1699
Alan Kwongcdb2f282017-03-18 13:42:06 -07001700 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1701 (u64) &new_rstate->rot_hw->base);
1702 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1703 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001704 if (fb && fbo) {
1705 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
1706 new_rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001707 } else if (fbo) {
1708 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1709 (u64) &new_rstate->rot_hw->base);
1710 fbo = NULL;
1711 } else if (fb) {
1712 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1713 (u64) &new_rstate->rot_hw->base);
1714 fb = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001715 }
Alan Kwongcdb2f282017-03-18 13:42:06 -07001716
1717 new_rstate->out_fbo = fbo;
1718 new_rstate->out_fb = fb;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001719 }
1720
1721 /* release buffer if output format configuration changes */
1722 if (new_rstate->out_fb &&
1723 ((new_rstate->out_fb_height != new_rstate->out_fb->height) ||
1724 (new_rstate->out_fb_width != new_rstate->out_fb->width) ||
1725 (new_rstate->out_fb_pixel_format !=
1726 new_rstate->out_fb->pixel_format) ||
1727 (new_rstate->out_fb_modifier[0] !=
1728 new_rstate->out_fb->modifier[0]) ||
1729 (new_rstate->out_fb_flags != new_rstate->out_fb->flags))) {
1730
1731 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
1732 new_rstate->sequence_id);
1733
Alan Kwongcdb2f282017-03-18 13:42:06 -07001734 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1735 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001736 new_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001737 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1738 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001739 new_rstate->out_fbo = NULL;
1740 }
1741
1742 /* create new stream buffer if it is not available */
1743 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
1744 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
1745 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
1746
1747 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
1748 new_rstate->sequence_id);
1749
1750 if (new_state->fb->flags & DRM_MODE_FB_SECURE)
1751 new_rstate->mmu_id = MSM_SMMU_DOMAIN_SECURE;
1752 else
1753 new_rstate->mmu_id = MSM_SMMU_DOMAIN_UNSECURE;
1754
1755 /* check if out_fb is already attached to rotator */
1756 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
1757 new_rstate->out_fb_pixel_format,
1758 new_rstate->out_fb_modifier,
1759 new_rstate->out_fb_flags);
1760 if (!new_rstate->out_fbo) {
1761 SDE_ERROR("failed to allocate inline buffer object\n");
1762 ret = -EINVAL;
1763 goto error_create_fbo;
1764 }
1765
Alan Kwongcdb2f282017-03-18 13:42:06 -07001766 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1767 (u64) &new_rstate->rot_hw->base,
1768 new_rstate->out_fbo, &fbo_res_ops);
1769 if (ret) {
1770 SDE_ERROR("failed to add crtc resource\n");
1771 goto error_create_fbo_res;
1772 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001773
1774 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
1775 new_rstate->out_fbo);
1776 if (!new_rstate->out_fb) {
1777 SDE_ERROR("failed to create inline framebuffer\n");
1778 ret = -EINVAL;
1779 goto error_create_fb;
1780 }
1781
Alan Kwongcdb2f282017-03-18 13:42:06 -07001782 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1783 (u64) &new_rstate->rot_hw->base,
1784 new_rstate->out_fb, &fb_res_ops);
1785 if (ret) {
1786 SDE_ERROR("failed to add crtc resource %d\n", ret);
1787 goto error_create_fb_res;
1788 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001789 }
1790
1791 /* prepare rotator input buffer */
1792 ret = msm_framebuffer_prepare(new_state->fb, new_rstate->mmu_id);
1793 if (ret) {
1794 SDE_ERROR("failed to prepare input framebuffer\n");
1795 goto error_prepare_input_buffer;
1796 }
1797
1798 /* prepare rotator output buffer */
1799 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
1800 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
1801 new_rstate->sequence_id);
1802
1803 ret = msm_framebuffer_prepare(new_rstate->out_fb,
1804 new_rstate->mmu_id);
1805 if (ret) {
1806 SDE_ERROR("failed to prepare inline framebuffer\n");
1807 goto error_prepare_output_buffer;
1808 }
1809 }
1810
1811 return 0;
1812
1813error_prepare_output_buffer:
1814 msm_framebuffer_cleanup(new_state->fb, new_rstate->mmu_id);
1815error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001816 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1817 (u64) &new_rstate->rot_hw->base);
1818error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001819 new_rstate->out_fb = NULL;
1820error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07001821 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1822 (u64) &new_rstate->rot_hw->base);
1823error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08001824 new_rstate->out_fbo = NULL;
1825error_create_fbo:
1826 return ret;
1827}
1828
1829/**
1830 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
1831 * rotator (pre-sspp) stage
1832 * @plane: Pointer to drm plane
1833 * @old_state: Pointer to previous drm plane state
1834 * return: none
1835 */
1836static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
1837 struct drm_plane_state *old_state)
1838{
1839 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
1840 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
1841 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001842 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001843 int ret;
1844
1845 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1846 old_rstate->sequence_id, old_state->fb->base.id,
1847 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
1848 sde_plane_crtc_enabled(old_state));
1849
1850 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
1851 return;
1852
Alan Kwongcdb2f282017-03-18 13:42:06 -07001853 cstate = _sde_plane_get_crtc_state(old_state);
1854 if (IS_ERR(cstate)) {
1855 ret = PTR_ERR(cstate);
1856 SDE_ERROR("invalid crtc state %d\n", ret);
1857 return;
1858 }
1859
Alan Kwong4dd64c82017-02-04 18:41:51 -08001860 if (sde_plane_crtc_enabled(old_state)) {
1861 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
1862 SDE_HW_ROT_CMD_CLEANUP);
1863 if (ret)
1864 SDE_ERROR("failed to cleanup rotator buffers\n");
1865 }
1866
1867 if (sde_plane_enabled(old_state)) {
1868 if (old_rstate->out_fb) {
1869 msm_framebuffer_cleanup(old_rstate->out_fb,
1870 old_rstate->mmu_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001871 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1872 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001873 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001874 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1875 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001876 old_rstate->out_fbo = NULL;
1877 }
1878
1879 msm_framebuffer_cleanup(old_state->fb, old_rstate->mmu_id);
1880 }
1881}
1882
1883/**
1884 * sde_plane_rot_atomic_check - verify rotator update of the given state
1885 * @plane: Pointer to drm plane
1886 * @state: Pointer to drm plane state to be validated
1887 * return: 0 if success; error code otherwise
1888 */
1889static int sde_plane_rot_atomic_check(struct drm_plane *plane,
1890 struct drm_plane_state *state)
1891{
1892 struct sde_plane *psde;
1893 struct sde_plane_state *pstate, *old_pstate;
1894 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001895 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001896 struct sde_hw_blk *hw_blk;
1897 int i, ret = 0;
1898
1899 if (!plane || !state) {
1900 SDE_ERROR("invalid plane/state\n");
1901 return -EINVAL;
1902 }
1903
1904 psde = to_sde_plane(plane);
1905 pstate = to_sde_plane_state(state);
1906 old_pstate = to_sde_plane_state(plane->state);
1907 rstate = &pstate->rot;
1908 old_rstate = &old_pstate->rot;
1909
Alan Kwongcdb2f282017-03-18 13:42:06 -07001910 /* cstate will be null if crtc is disconnected from plane */
1911 cstate = _sde_plane_get_crtc_state(state);
1912 if (IS_ERR(cstate)) {
1913 ret = PTR_ERR(cstate);
1914 SDE_ERROR("invalid crtc state %d\n", ret);
1915 return ret;
1916 }
1917
Alan Kwong4dd64c82017-02-04 18:41:51 -08001918 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
1919 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
1920 !!rstate->out_sbuf, !!rstate->rot_hw,
1921 sde_plane_crtc_enabled(state));
1922
1923 rstate->in_rotation = drm_rotation_simplify(
1924 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07001925 DRM_ROTATE_0 | DRM_ROTATE_90 |
1926 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001927 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
1928 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
1929 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
1930 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
1931
Alan Kwongcdb2f282017-03-18 13:42:06 -07001932 if (sde_plane_enabled(state) && rstate->out_sbuf) {
1933 SDE_DEBUG("plane%d.%d acquire rotator\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08001934 plane->base.id, rstate->sequence_id);
1935
Alan Kwongcdb2f282017-03-18 13:42:06 -07001936 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
1937 (u64) state->fb);
1938 if (!hw_blk) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001939 SDE_ERROR("plane%d no available rotator\n",
1940 plane->base.id);
1941 return -EINVAL;
1942 }
1943
Alan Kwongcdb2f282017-03-18 13:42:06 -07001944 rstate->rot_hw = to_sde_hw_rot(hw_blk);
1945
Alan Kwong4dd64c82017-02-04 18:41:51 -08001946 if (!rstate->rot_hw->ops.commit) {
1947 SDE_ERROR("plane%d invalid rotator ops\n",
1948 plane->base.id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07001949 sde_crtc_res_put(cstate,
1950 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001951 rstate->rot_hw = NULL;
1952 return -EINVAL;
1953 }
1954
1955 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001956 } else {
1957 rstate->in_fb = NULL;
1958 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001959 }
1960
1961 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
1962
1963 SDE_DEBUG("plane%d.%d use rotator\n",
1964 plane->base.id, rstate->sequence_id);
1965
1966 sde_plane_rot_calc_cfg(plane, state);
1967
1968 ret = sde_plane_rot_submit_command(plane, state,
1969 SDE_HW_ROT_CMD_VALIDATE);
1970
Clarence Ip4475d582017-04-18 11:36:00 -04001971 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001972
1973 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
1974 rstate->sequence_id);
1975
1976 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04001977 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1978 rstate->out_fb_modifier[i] = state->fb ?
1979 state->fb->modifier[i] : 0x0;
1980
1981 if (state->fb) {
1982 rstate->out_fb_pixel_format = state->fb->pixel_format;
1983 rstate->out_fb_flags = state->fb->flags;
1984 rstate->out_fb_width = state->fb->width;
1985 rstate->out_fb_height = state->fb->height;
1986 } else {
1987 rstate->out_fb_pixel_format = 0x0;
1988 rstate->out_fb_flags = 0x0;
1989 rstate->out_fb_width = 0;
1990 rstate->out_fb_height = 0;
1991 }
1992
Alan Kwong4dd64c82017-02-04 18:41:51 -08001993 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001994 rstate->out_src_x = state->src_x;
1995 rstate->out_src_y = state->src_y;
1996 rstate->out_src_w = state->src_w;
1997 rstate->out_src_h = state->src_h;
1998
1999 rstate->out_fb_format = NULL;
2000 rstate->out_sbuf = false;
2001 rstate->out_fb = state->fb;
2002 }
2003
2004 return ret;
2005}
2006
2007/**
2008 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2009 * @plane: Pointer to drm plane
2010 * @old_state: Pointer to previous state
2011 * return: none
2012 */
2013static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2014 struct drm_plane_state *old_state)
2015{
2016 struct drm_plane_state *state;
2017 struct sde_plane_state *pstate;
2018 struct sde_plane_rot_state *rstate;
2019
2020 if (!plane || !plane->state) {
2021 SDE_ERROR("invalid plane/state\n");
2022 return;
2023 }
2024
2025 state = plane->state;
2026 pstate = to_sde_plane_state(state);
2027 rstate = &pstate->rot;
2028
2029 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2030 rstate->sequence_id,
2031 !!rstate->out_sbuf, !!rstate->rot_hw,
2032 sde_plane_crtc_enabled(plane->state));
2033
2034 if (!sde_plane_crtc_enabled(state))
2035 return;
2036
2037 if (!rstate->out_sbuf || !rstate->rot_hw)
2038 return;
2039
2040 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
2041}
2042
2043/**
2044 * sde_plane_rot_destroy_state - destroy state for rotator stage
2045 * @plane: Pointer to drm plane
2046 * @state: Pointer to state to be destroyed
2047 * return: none
2048 */
2049static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2050 struct drm_plane_state *state)
2051{
2052 struct sde_plane_state *pstate = to_sde_plane_state(state);
2053 struct sde_plane_rot_state *rstate = &pstate->rot;
2054
2055 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2056 rstate->sequence_id,
2057 !!rstate->out_sbuf, !!rstate->rot_hw,
2058 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002059}
2060
2061/**
2062 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2063 * @plane: Pointer to drm plane
2064 * @new_state: Pointer to duplicated state
2065 * return: 0 if success; error code otherwise
2066 */
2067static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2068 struct drm_plane_state *new_state)
2069{
2070 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2071 struct sde_plane_rot_state *rstate = &pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002072 struct drm_crtc_state *cstate;
2073 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002074
2075 rstate->sequence_id++;
2076
2077 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2078 rstate->sequence_id,
2079 !!rstate->out_sbuf, !!rstate->rot_hw);
2080
Alan Kwongcdb2f282017-03-18 13:42:06 -07002081 cstate = _sde_plane_get_crtc_state(new_state);
2082 if (IS_ERR(cstate)) {
2083 ret = PTR_ERR(cstate);
2084 SDE_ERROR("invalid crtc state %d\n", ret);
2085 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002086 }
2087
Alan Kwongcdb2f282017-03-18 13:42:06 -07002088 if (rstate->rot_hw && cstate)
2089 sde_crtc_res_get(cstate, SDE_HW_BLK_ROT, (u64) rstate->in_fb);
2090 else if (rstate->rot_hw && !cstate)
2091 SDE_ERROR("plane%d.%d zombie rotator hw\n",
2092 plane->base.id, rstate->sequence_id);
2093
Alan Kwong4dd64c82017-02-04 18:41:51 -08002094 rstate->out_fb = NULL;
2095 rstate->out_fbo = NULL;
2096
2097 return 0;
2098}
2099
2100/**
2101 * sde_plane_rot_install_caps - install plane rotator capabilities
2102 * @plane: Pointer to drm plane
2103 * return: none
2104 */
2105static void sde_plane_rot_install_caps(struct drm_plane *plane)
2106{
2107 struct sde_plane *psde = to_sde_plane(plane);
2108 const struct sde_format_extended *format_list;
2109 struct sde_kms_info *info;
2110 struct sde_hw_rot *rot_hw;
2111 const char *downscale_caps;
2112
2113 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2114 !psde->catalog->rot_count)
2115 return;
2116
2117 if (psde->blob_rot_caps)
2118 return;
2119
2120 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2121 if (!info)
2122 return;
2123
2124 rot_hw = sde_hw_rot_get(NULL);
2125 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2126 !rot_hw->ops.get_downscale_caps) {
2127 SDE_ERROR("invalid rotator hw\n");
2128 goto error_rot;
2129 }
2130
2131 sde_kms_info_reset(info);
2132
2133 format_list = rot_hw->ops.get_format_caps(rot_hw);
2134 if (format_list) {
2135 sde_kms_info_start(info, "pixel_formats");
2136 while (format_list->fourcc_format) {
2137 sde_kms_info_append_format(info,
2138 format_list->fourcc_format,
2139 format_list->modifier);
2140 ++format_list;
2141 }
2142 sde_kms_info_stop(info);
2143 }
2144
2145 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2146 if (downscale_caps) {
2147 sde_kms_info_start(info, "downscale_ratios");
2148 sde_kms_info_append(info, downscale_caps);
2149 sde_kms_info_stop(info);
2150 }
2151
2152 if (rot_hw->ops.get_cache_size)
2153 sde_kms_info_add_keyint(info, "cache_size",
2154 rot_hw->ops.get_cache_size(rot_hw));
2155
Alan Kwong1a915802017-03-31 12:55:46 -07002156 if (rot_hw->ops.get_maxlinewidth)
2157 sde_kms_info_add_keyint(info, "max_linewidth",
2158 rot_hw->ops.get_maxlinewidth(rot_hw));
2159
Alan Kwong4dd64c82017-02-04 18:41:51 -08002160 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
2161 info->data, info->len, PLANE_PROP_ROT_CAPS_V1);
2162
2163 sde_hw_rot_put(rot_hw);
2164error_rot:
2165 kfree(info);
2166}
2167
2168/**
2169 * sde_plane_rot_install_properties - install plane rotator properties
2170 * @plane: Pointer to drm plane
2171 * @catalog: Pointer to mdss configuration
2172 * return: none
2173 */
2174static void sde_plane_rot_install_properties(struct drm_plane *plane,
2175 struct sde_mdss_cfg *catalog)
2176{
2177 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002178 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2179 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002180
2181 if (!plane || !psde) {
2182 SDE_ERROR("invalid plane\n");
2183 return;
2184 } else if (!catalog) {
2185 SDE_ERROR("invalid catalog\n");
2186 return;
2187 }
2188
2189 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2190 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2191 DRM_ROTATE_180 | DRM_ROTATE_270;
2192
2193 msm_property_install_rotation(&psde->property_info,
2194 supported_rotations, PLANE_PROP_ROTATION);
2195
2196 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2197 return;
2198
2199 msm_property_install_range(&psde->property_info, "rot_dst_x",
2200 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2201 msm_property_install_range(&psde->property_info, "rot_dst_y",
2202 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2203 msm_property_install_range(&psde->property_info, "rot_dst_w",
2204 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2205 msm_property_install_range(&psde->property_info, "rot_dst_h",
2206 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2207 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2208 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2209}
2210
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002211void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002212{
Clarence Ipcb410d42016-06-26 22:52:33 -04002213 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002214
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002215 if (!drm_state)
2216 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002217
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002218 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002219
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002220 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2221 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002222}
2223
2224int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2225{
2226 struct sde_plane_state *pstate[R_MAX];
2227 const struct drm_plane_state *drm_state[R_MAX];
2228 struct sde_rect src[R_MAX], dst[R_MAX];
2229 struct sde_plane *sde_plane[R_MAX];
2230 const struct sde_format *fmt[R_MAX];
2231 bool q16_data = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002232 int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
2233 bool parallel_fetch_qualified = true;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002234
2235 for (i = 0; i < R_MAX; i++) {
2236 const struct msm_format *msm_fmt;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002237 int width_threshold;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002238
2239 drm_state[i] = i ? plane->r1 : plane->r0;
2240 pstate[i] = to_sde_plane_state(drm_state[i]);
2241 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2242
2243 if (pstate[i] == NULL) {
2244 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2245 drm_state[i]->plane->base.id);
2246 return -EINVAL;
2247 }
2248
2249 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2250 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2251 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2252 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2253 drm_state[i]->crtc_h, !q16_data);
2254
2255 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2256 SDE_ERROR_PLANE(sde_plane[i],
2257 "scaling is not supported in multirect mode\n");
2258 return -EINVAL;
2259 }
2260
2261 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2262 fmt[i] = to_sde_format(msm_fmt);
2263 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2264 SDE_ERROR_PLANE(sde_plane[i],
2265 "Unsupported format for multirect mode\n");
2266 return -EINVAL;
2267 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002268
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002269 /**
2270 * SSPP PD_MEM is split half - one for each RECT.
2271 * Tiled formats need 5 lines of buffering while fetching
2272 * whereas linear formats need only 2 lines.
2273 * So we cannot support more than half of the supported SSPP
2274 * width for tiled formats.
2275 */
2276 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
2277 if (SDE_FORMAT_IS_UBWC(fmt[i]))
2278 width_threshold /= 2;
2279
2280 if (parallel_fetch_qualified && src[i].w > width_threshold)
2281 parallel_fetch_qualified = false;
2282
2283 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002284
2285 /* Validate RECT's and set the mode */
2286
2287 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002288 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002289 if (dst[R0].x <= dst[R1].x) {
2290 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2291 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2292 } else {
2293 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2294 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2295 }
2296
2297 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2298 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2299 goto done;
2300 }
2301
2302 /* TIME_MX Mode */
2303 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
2304 buffer_lines = 2 * fmt[R0]->tile_height;
2305
2306 if (dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) {
2307 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2308 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2309 } else if (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines) {
2310 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2311 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2312 } else {
2313 SDE_ERROR(
2314 "No multirect mode possible for the planes (%d - %d)\n",
2315 drm_state[R0]->plane->base.id,
2316 drm_state[R1]->plane->base.id);
2317 return -EINVAL;
2318 }
2319
2320 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2321 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2322done:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002323 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2324 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2325 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2326 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002327 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002328}
2329
Alan Kwong4dd64c82017-02-04 18:41:51 -08002330/**
2331 * sde_plane_get_ctl_flush - get control flush for the given plane
2332 * @plane: Pointer to drm plane structure
2333 * @ctl: Pointer to hardware control driver
2334 * @flush: Pointer to flush control word
2335 */
2336void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
2337 u32 *flush)
2338{
2339 struct sde_plane_state *pstate;
2340 struct sde_plane_rot_state *rstate;
2341 u32 bitmask;
2342
2343 if (!plane || !flush) {
2344 SDE_ERROR("invalid parameters\n");
2345 return;
2346 }
2347
2348 pstate = to_sde_plane_state(plane->state);
2349 rstate = &pstate->rot;
2350
2351 bitmask = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
2352
2353 if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
2354 ctl->ops.get_bitmask_rot)
2355 ctl->ops.get_bitmask_rot(ctl, &bitmask, rstate->rot_hw->idx);
2356
2357 *flush = bitmask;
2358}
2359
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002360static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002361 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002362{
2363 struct drm_framebuffer *fb = new_state->fb;
2364 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002365 struct sde_plane_rot_state *new_rstate;
2366 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002367
2368 if (!new_state->fb)
2369 return 0;
2370
Clarence Ip13a8cf42016-09-29 17:27:47 -04002371 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002372
2373 ret = sde_plane_rot_prepare_fb(plane, new_state);
2374 if (ret) {
2375 SDE_ERROR("failed to prepare rot framebuffer\n");
2376 return ret;
2377 }
2378
2379 new_rstate = &to_sde_plane_state(new_state)->rot;
2380
2381 ret = msm_framebuffer_prepare(new_rstate->out_fb, new_rstate->mmu_id);
2382 if (ret) {
2383 SDE_ERROR("failed to prepare framebuffer\n");
2384 return ret;
2385 }
2386
2387 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002388}
2389
2390static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002391 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002392{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002393 struct sde_plane *psde = to_sde_plane(plane);
2394 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002395
Alan Kwong4dd64c82017-02-04 18:41:51 -08002396 if (!old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002397 return;
2398
Alan Kwong4dd64c82017-02-04 18:41:51 -08002399 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2400
2401 old_rstate = &to_sde_plane_state(old_state)->rot;
2402
2403 msm_framebuffer_cleanup(old_rstate->out_fb, old_rstate->mmu_id);
2404
2405 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002406}
2407
Alan Kwong4dd64c82017-02-04 18:41:51 -08002408static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002409 struct drm_plane_state *state,
2410 struct drm_plane_state *old_state)
2411{
2412 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002413 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002414 struct sde_plane_rot_state *rstate = &pstate->rot;
2415 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2416 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002417
Dhaval Patel47302cf2016-08-18 15:04:28 -07002418 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002419 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002420 return;
2421
Clarence Ip282dad62016-09-27 17:07:35 -04002422 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2423 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002424 SDE_DEBUG_PLANE(psde,
2425 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002426 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002427 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002428 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002429 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002430 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2431 pstate->multirect_mode != old_pstate->multirect_mode) {
2432 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2433 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002434 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2435 rstate->out_src_h != old_rstate->out_src_h ||
2436 rstate->out_src_x != old_rstate->out_src_x ||
2437 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002438 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002439 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002440 } else if (state->crtc_w != old_state->crtc_w ||
2441 state->crtc_h != old_state->crtc_h ||
2442 state->crtc_x != old_state->crtc_x ||
2443 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002444 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002445 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002446 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2447 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2448 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2449 pstate->excl_rect.y != old_pstate->excl_rect.y) {
2450 SDE_DEBUG_PLANE(psde, "excl rect updated\n");
2451 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002452 }
2453
Alan Kwong4dd64c82017-02-04 18:41:51 -08002454 fb = rstate->out_fb;
2455 old_fb = old_rstate->out_fb;
2456
2457 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002458 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002459 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002460 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002461 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002462 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002463 uint64_t *new_mods = fb->modifier;
2464 uint64_t *old_mods = old_fb->modifier;
2465 uint32_t *new_pitches = fb->pitches;
2466 uint32_t *old_pitches = old_fb->pitches;
2467 uint32_t *new_offset = fb->offsets;
2468 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002469 int i;
2470
Alan Kwong4dd64c82017-02-04 18:41:51 -08002471 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002472 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002473 SDE_DEBUG_PLANE(psde,
2474 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002475 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002476 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002477 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2478 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002479 break;
2480 }
2481 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002482 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002483 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002484 SDE_DEBUG_PLANE(psde,
2485 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002486 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002487 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002488 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002489 break;
2490 }
2491 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002492 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002493 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002494 SDE_DEBUG_PLANE(psde,
2495 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002496 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002497 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002498 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2499 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002500 break;
2501 }
2502 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002503 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002504}
2505
Alan Kwong4dd64c82017-02-04 18:41:51 -08002506static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002507 struct drm_plane_state *state)
2508{
Clarence Ipdedbba92016-09-27 17:43:10 -04002509 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04002510 struct sde_plane *psde;
2511 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002512 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002513 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002514 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04002515 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002516 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
2517 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04002518
2519 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002520 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2521 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04002522 ret = -EINVAL;
2523 goto exit;
2524 }
2525
2526 psde = to_sde_plane(plane);
2527 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002528 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04002529
2530 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002531 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002532 ret = -EINVAL;
2533 goto exit;
2534 }
2535
Clarence Ipdedbba92016-09-27 17:43:10 -04002536 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
2537 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04002538
2539 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002540 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2541 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002542 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
2543 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04002544
Dhaval Patel47302cf2016-08-18 15:04:28 -07002545 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
2546 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04002547
Dhaval Patel47302cf2016-08-18 15:04:28 -07002548 max_upscale = psde->pipe_sblk->maxupscale;
2549 max_downscale = psde->pipe_sblk->maxdwnscale;
2550 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04002551
Clarence Ip13a8cf42016-09-29 17:27:47 -04002552 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002553 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002554
Dhaval Patel47302cf2016-08-18 15:04:28 -07002555 if (!sde_plane_enabled(state))
2556 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04002557
Alan Kwong4dd64c82017-02-04 18:41:51 -08002558 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002559 "plane%d.%u sspp:%x/%dx%d/%4.4s/%llx/%dx%d+%d+%d crtc:%dx%d+%d+%d\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08002560 plane->base.id, rstate->sequence_id,
2561 rstate->out_rotation,
2562 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002563 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002564 rstate->out_fb_modifier[0],
2565 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2566 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2567 state->crtc_w, state->crtc_h,
2568 state->crtc_x, state->crtc_y);
2569
Dhaval Patel47302cf2016-08-18 15:04:28 -07002570 fmt = to_sde_format(msm_framebuffer_format(state->fb));
2571
2572 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
2573
2574 if (SDE_FORMAT_IS_YUV(fmt) &&
2575 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04002576 !(psde->features & (BIT(SDE_SSPP_CSC)
2577 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002578 SDE_ERROR_PLANE(psde,
2579 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07002580 ret = -EINVAL;
2581
2582 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002583 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
2584 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07002585 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08002586 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
2587 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002588 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002589 src.x, src.y, src.w, src.h);
2590 ret = -E2BIG;
2591
2592 /* valid yuv image */
2593 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
2594 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002595 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002596 src.x, src.y, src.w, src.h);
2597 ret = -EINVAL;
2598
2599 /* min dst support */
2600 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002601 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002602 dst.x, dst.y, dst.w, dst.h);
2603 ret = -EINVAL;
2604
2605 /* decimation validation */
2606 } else if (deci_w || deci_h) {
2607 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
2608 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002609 SDE_ERROR_PLANE(psde,
2610 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002611 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002612 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002613 SDE_ERROR_PLANE(psde,
2614 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002615 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002616 }
2617
Dhaval Patel47302cf2016-08-18 15:04:28 -07002618 } else if (!(psde->features & SDE_SSPP_SCALER) &&
2619 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002620 SDE_ERROR_PLANE(psde,
2621 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002622 src.w, src.h, dst.w, dst.h);
2623 ret = -EINVAL;
2624
2625 /* check decimated source width */
2626 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002627 SDE_ERROR_PLANE(psde,
2628 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002629 src.w, src_deci_w, max_linewidth);
2630 ret = -E2BIG;
2631
2632 /* check max scaler capability */
2633 } else if (((src_deci_w * max_upscale) < dst.w) ||
2634 ((src_deci_h * max_upscale) < dst.h) ||
2635 ((dst.w * max_downscale) < src_deci_w) ||
2636 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002637 SDE_ERROR_PLANE(psde,
2638 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002639 src_deci_w, src_deci_h, dst.w, dst.h);
2640 ret = -E2BIG;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002641 }
2642
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002643 /* check excl rect configs */
2644 if (pstate->excl_rect.w && pstate->excl_rect.h) {
2645 struct sde_rect intersect;
2646
2647 /*
2648 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002649 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002650 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05002651 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07002652 if (intersect.w != pstate->excl_rect.w ||
2653 intersect.h != pstate->excl_rect.h ||
2654 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002655 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07002656 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002657 pstate->excl_rect.x, pstate->excl_rect.y,
2658 pstate->excl_rect.w, pstate->excl_rect.h,
2659 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07002660 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002661 ret = -EINVAL;
2662 }
2663 }
2664
Dhaval Patel47302cf2016-08-18 15:04:28 -07002665modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002666 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002667 _sde_plane_sspp_atomic_check_mode_changed(psde,
2668 state, plane->state);
2669exit:
2670 return ret;
2671}
2672
2673static int sde_plane_atomic_check(struct drm_plane *plane,
2674 struct drm_plane_state *state)
2675{
2676 int ret = 0;
2677 struct sde_plane *psde;
2678 struct sde_plane_state *pstate;
2679
2680 if (!plane || !state) {
2681 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2682 plane != 0, state != 0);
2683 ret = -EINVAL;
2684 goto exit;
2685 }
2686
2687 psde = to_sde_plane(plane);
2688 pstate = to_sde_plane_state(state);
2689
2690 SDE_DEBUG_PLANE(psde, "\n");
2691
2692 ret = sde_plane_rot_atomic_check(plane, state);
2693 if (ret)
2694 goto exit;
2695
2696 ret = sde_plane_sspp_atomic_check(plane, state);
2697
Clarence Ipdbde9832016-06-26 09:48:36 -04002698exit:
2699 return ret;
2700}
2701
Clarence Ipcae1bb62016-07-07 12:07:13 -04002702/**
2703 * sde_plane_flush - final plane operations before commit flush
2704 * @plane: Pointer to drm plane structure
2705 */
2706void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04002707{
Clarence Ipcae1bb62016-07-07 12:07:13 -04002708 struct sde_plane *psde;
2709
Clarence Ip13a8cf42016-09-29 17:27:47 -04002710 if (!plane) {
2711 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04002712 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04002713 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04002714
2715 psde = to_sde_plane(plane);
2716
2717 /*
2718 * These updates have to be done immediately before the plane flush
2719 * timing, and may not be moved to the atomic_update/mode_set functions.
2720 */
2721 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05002722 /* force white frame with 100% alpha pipe output on error */
2723 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002724 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
2725 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04002726 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04002727 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
2728 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
2729
Clarence Ip56902792017-03-17 15:22:07 -04002730 /* force black color fill during suspend */
2731 if (msm_is_suspend_state(plane->dev) && suspend_blank)
2732 _sde_plane_color_fill(psde, 0x0, 0x0);
2733
Clarence Ipcae1bb62016-07-07 12:07:13 -04002734 /* flag h/w flush complete */
2735 if (plane->state)
Clarence Ipdbde9832016-06-26 09:48:36 -04002736 to_sde_plane_state(plane->state)->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002737}
2738
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002739static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
2740 struct drm_plane_state *old_state)
2741{
2742 uint32_t nplanes, src_flags;
2743 struct sde_plane *psde;
2744 struct drm_plane_state *state;
2745 struct sde_plane_state *pstate;
2746 struct sde_plane_state *old_pstate;
2747 struct sde_plane_rot_state *rstate;
2748 const struct sde_format *fmt;
2749 struct drm_crtc *crtc;
2750 struct drm_framebuffer *fb;
2751 struct sde_rect src, dst;
2752 const struct sde_rect *crtc_roi;
2753 bool q16_data = true;
2754 int idx;
2755
2756 if (!plane) {
2757 SDE_ERROR("invalid plane\n");
2758 return -EINVAL;
2759 } else if (!plane->state) {
2760 SDE_ERROR("invalid plane state\n");
2761 return -EINVAL;
2762 } else if (!old_state) {
2763 SDE_ERROR("invalid old state\n");
2764 return -EINVAL;
2765 }
2766
2767 psde = to_sde_plane(plane);
2768 state = plane->state;
2769
2770 pstate = to_sde_plane_state(state);
2771 rstate = &pstate->rot;
2772
2773 old_pstate = to_sde_plane_state(old_state);
2774
2775 crtc = state->crtc;
2776 fb = rstate->out_fb;
2777 if (!crtc || !fb) {
2778 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
2779 crtc != 0, fb != 0);
2780 return -EINVAL;
2781 }
2782 fmt = to_sde_format(msm_framebuffer_format(fb));
2783 nplanes = fmt->num_planes;
2784
2785 SDE_DEBUG(
2786 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
2787 plane->base.id, rstate->sequence_id,
2788 rstate->out_fb_width, rstate->out_fb_height,
2789 (char *) &rstate->out_fb_pixel_format,
2790 rstate->out_fb_modifier[0],
2791 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2792 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2793 rstate->out_rotation,
2794 state->crtc_w, state->crtc_h,
2795 state->crtc_x, state->crtc_y);
2796
2797 /* force reprogramming of all the parameters, if the flag is set */
2798 if (psde->revalidate) {
2799 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
2800 plane->base.id);
2801 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2802 psde->revalidate = false;
2803 }
2804
2805 /* determine what needs to be refreshed */
2806 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
2807 switch (idx) {
2808 case PLANE_PROP_SCALER_V1:
2809 case PLANE_PROP_SCALER_V2:
2810 case PLANE_PROP_H_DECIMATE:
2811 case PLANE_PROP_V_DECIMATE:
2812 case PLANE_PROP_SRC_CONFIG:
2813 case PLANE_PROP_ZPOS:
2814 case PLANE_PROP_EXCL_RECT_V1:
2815 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2816 break;
2817 case PLANE_PROP_CSC_V1:
2818 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2819 break;
2820 case PLANE_PROP_COLOR_FILL:
2821 /* potentially need to refresh everything */
2822 pstate->dirty = SDE_PLANE_DIRTY_ALL;
2823 break;
2824 case PLANE_PROP_ROTATION:
2825 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
2826 break;
2827 case PLANE_PROP_INFO:
2828 case PLANE_PROP_ALPHA:
2829 case PLANE_PROP_INPUT_FENCE:
2830 case PLANE_PROP_BLEND_OP:
2831 /* no special action required */
2832 break;
2833 case PLANE_PROP_ROT_DST_X:
2834 case PLANE_PROP_ROT_DST_Y:
2835 case PLANE_PROP_ROT_DST_W:
2836 case PLANE_PROP_ROT_DST_H:
2837 /* handled by rotator atomic update */
2838 break;
2839 default:
2840 /* unknown property, refresh everything */
2841 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
2842 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
2843 break;
2844 }
2845 }
2846
2847 /**
2848 * since plane_atomic_check is invoked before crtc_atomic_check
2849 * in the commit sequence, all the parameters for updating the
2850 * plane dirty flag will not be available during
2851 * plane_atomic_check as some features params are updated
2852 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
2853 * before sspp update.
2854 */
2855 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
2856 old_state);
2857
2858 /* re-program the output rects always in the case of partial update */
2859 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
2860 if (!sde_kms_rect_is_null(crtc_roi))
2861 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
2862
2863 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
2864 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
2865
2866 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
2867
2868 /* early out if nothing dirty */
2869 if (!pstate->dirty)
2870 return 0;
2871 pstate->pending = true;
2872
2873 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
2874 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
2875
2876 /* update roi config */
2877 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
2878 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2879 rstate->out_src_w, rstate->out_src_h, q16_data);
2880 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
2881 state->crtc_w, state->crtc_h, !q16_data);
2882
2883 SDE_DEBUG_PLANE(psde,
2884 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
2885 fb->base.id, src.x, src.y, src.w, src.h,
2886 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
2887 (char *)&fmt->base.pixel_format,
2888 SDE_FORMAT_IS_UBWC(fmt));
2889
2890 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
2891 BIT(SDE_DRM_DEINTERLACE)) {
2892 SDE_DEBUG_PLANE(psde, "deinterlace\n");
2893 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
2894 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
2895 src.h /= 2;
2896 src.y = DIV_ROUND_UP(src.y, 2);
2897 src.y &= ~0x1;
2898 }
2899
2900 /*
2901 * adjust layer mixer position of the sspp in the presence
2902 * of a partial update to the active lm origin
2903 */
2904 dst.x -= crtc_roi->x;
2905 dst.y -= crtc_roi->y;
2906
2907 psde->pipe_cfg.src_rect = src;
2908 psde->pipe_cfg.dst_rect = dst;
2909
2910 _sde_plane_setup_scaler(psde, fmt, pstate);
2911
2912 /* check for color fill */
2913 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
2914 PLANE_PROP_COLOR_FILL);
2915 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
2916 /* skip remaining processing on color fill */
2917 pstate->dirty = 0x0;
2918 } else if (psde->pipe_hw->ops.setup_rects) {
2919 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
2920 &psde->pipe_cfg,
2921 pstate->multirect_index);
2922 }
2923
2924 if (psde->pipe_hw->ops.setup_pe)
2925 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
2926 &psde->pixel_ext);
2927
2928 /**
2929 * when programmed in multirect mode, scalar block will be
2930 * bypassed. Still we need to update alpha and bitwidth
2931 * ONLY for RECT0
2932 */
2933 if (psde->pipe_hw->ops.setup_scaler &&
2934 pstate->multirect_index != SDE_SSPP_RECT_1)
2935 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
2936 &psde->pipe_cfg, &psde->pixel_ext,
2937 psde->scaler3_cfg);
2938
2939 /* update excl rect */
2940 if (psde->pipe_hw->ops.setup_excl_rect)
2941 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
2942 &pstate->excl_rect,
2943 pstate->multirect_index);
2944
2945 if (psde->pipe_hw->ops.setup_multirect)
2946 psde->pipe_hw->ops.setup_multirect(
2947 psde->pipe_hw,
2948 pstate->multirect_index,
2949 pstate->multirect_mode);
2950 }
2951
2952 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
2953 psde->pipe_hw->ops.setup_format) {
2954 src_flags = 0x0;
2955 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
2956 if (rstate->out_rotation & DRM_REFLECT_X)
2957 src_flags |= SDE_SSPP_FLIP_LR;
2958 if (rstate->out_rotation & DRM_REFLECT_Y)
2959 src_flags |= SDE_SSPP_FLIP_UD;
2960
2961 /* update format */
2962 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
2963 pstate->multirect_index);
2964
2965 if (psde->pipe_hw->ops.setup_sys_cache) {
2966 if (rstate->out_sbuf) {
2967 if (rstate->nplane < 2)
2968 pstate->sc_cfg.op_mode =
2969 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
2970 else if (rstate->out_xpos == 0)
2971 pstate->sc_cfg.op_mode =
2972 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
2973 else
2974 pstate->sc_cfg.op_mode =
2975 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
2976
2977 pstate->sc_cfg.rd_en = true;
2978 pstate->sc_cfg.rd_scid =
2979 rstate->rot_hw->caps->scid;
2980 pstate->sc_cfg.rd_noallocate = true;
2981 pstate->sc_cfg.rd_op_type =
2982 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
2983 } else {
2984 pstate->sc_cfg.op_mode =
2985 SDE_PIPE_SC_OP_MODE_OFFLINE;
2986 pstate->sc_cfg.rd_en = false;
2987 pstate->sc_cfg.rd_scid = 0;
2988 pstate->sc_cfg.rd_noallocate = false;
2989 pstate->sc_cfg.rd_op_type =
2990 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
2991 }
2992
2993 psde->pipe_hw->ops.setup_sys_cache(
2994 psde->pipe_hw, &pstate->sc_cfg);
2995 }
2996
2997 /* update csc */
2998 if (SDE_FORMAT_IS_YUV(fmt))
2999 _sde_plane_setup_csc(psde);
3000 else
3001 psde->csc_ptr = 0;
3002 }
3003
3004 sde_color_process_plane_setup(plane);
3005
3006 /* update sharpening */
3007 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3008 psde->pipe_hw->ops.setup_sharpening) {
3009 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3010 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3011 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3012 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3013
3014 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3015 &psde->sharp_cfg);
3016 }
3017
3018 _sde_plane_set_qos_lut(plane, fb);
3019 _sde_plane_set_danger_lut(plane, fb);
3020
3021 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3022 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3023 _sde_plane_set_ot_limit(plane, crtc);
3024 }
3025
3026 /* clear dirty */
3027 pstate->dirty = 0x0;
3028
3029 return 0;
3030}
3031
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003032static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003033 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003034{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003035 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003036 struct drm_plane_state *state;
3037 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003038 struct sde_plane_state *old_pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003039
Clarence Ip13a8cf42016-09-29 17:27:47 -04003040 if (!plane) {
3041 SDE_ERROR("invalid plane\n");
3042 return;
3043 } else if (!plane->state) {
3044 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003045 return;
3046 }
3047
Clarence Ip13a8cf42016-09-29 17:27:47 -04003048 psde = to_sde_plane(plane);
3049 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003050 state = plane->state;
3051 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003052 old_pstate = to_sde_plane_state(old_state);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003053
Clarence Ip13a8cf42016-09-29 17:27:47 -04003054 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003055
Alan Kwong4dd64c82017-02-04 18:41:51 -08003056 sde_plane_rot_atomic_update(plane, old_state);
3057
3058 if (!sde_plane_sspp_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04003059 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04003060 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003061 int ret;
3062
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003063 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003064 /* atomic_check should have ensured that this doesn't fail */
3065 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003066 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003067}
3068
Dhaval Patel47302cf2016-08-18 15:04:28 -07003069
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003070/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003071static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003072 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003073{
Clarence Ip5e2a9222016-06-26 22:38:24 -04003074 static const struct drm_prop_enum_list e_blend_op[] = {
3075 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3076 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3077 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3078 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3079 };
3080 static const struct drm_prop_enum_list e_src_config[] = {
3081 {SDE_DRM_DEINTERLACE, "deinterlace"}
3082 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003083 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003084 struct sde_format_extended *virt_format_list = NULL;
Dhaval Patel4e574842016-08-23 15:11:37 -07003085 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003086 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003087 int zpos_max = 255;
3088 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003089 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003090
Clarence Ip13a8cf42016-09-29 17:27:47 -04003091 if (!plane || !psde) {
3092 SDE_ERROR("invalid plane\n");
3093 return;
3094 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3095 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3096 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003097 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003098 } else if (!catalog) {
3099 SDE_ERROR("invalid catalog\n");
3100 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003101 }
3102
Alan Kwong4dd64c82017-02-04 18:41:51 -08003103 psde->catalog = catalog;
3104
Clarence Ipc47a0692016-10-11 10:54:17 -04003105 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003106 if (catalog->mixer_count && catalog->mixer &&
3107 catalog->mixer[0].sblk->maxblendstages) {
3108 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3109 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3110 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3111 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003112 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3113 /* reserve zpos == 0 for primary planes */
3114 zpos_def = drm_plane_index(plane) + 1;
3115 }
3116
3117 msm_property_install_range(&psde->property_info, "zpos",
3118 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003119
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003120 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003121 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003122
Dhaval Patel47302cf2016-08-18 15:04:28 -07003123 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003124 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003125 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003126
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003127 if (!master_plane_id) {
3128 if (psde->pipe_sblk->maxhdeciexp) {
3129 msm_property_install_range(&psde->property_info,
3130 "h_decimate", 0x0, 0,
3131 psde->pipe_sblk->maxhdeciexp, 0,
3132 PLANE_PROP_H_DECIMATE);
3133 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003134
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003135 if (psde->pipe_sblk->maxvdeciexp) {
3136 msm_property_install_range(&psde->property_info,
3137 "v_decimate", 0x0, 0,
3138 psde->pipe_sblk->maxvdeciexp, 0,
3139 PLANE_PROP_V_DECIMATE);
3140 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003141
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003142 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
3143 msm_property_install_volatile_range(
3144 &psde->property_info, "scaler_v2",
3145 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3146 msm_property_install_blob(&psde->property_info,
3147 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3148 msm_property_install_blob(&psde->property_info,
3149 "lut_cir", 0,
3150 PLANE_PROP_SCALER_LUT_CIR);
3151 msm_property_install_blob(&psde->property_info,
3152 "lut_sep", 0,
3153 PLANE_PROP_SCALER_LUT_SEP);
3154 } else if (psde->features & SDE_SSPP_SCALER) {
3155 msm_property_install_volatile_range(
3156 &psde->property_info, "scaler_v1", 0x0,
3157 0, ~0, 0, PLANE_PROP_SCALER_V1);
3158 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003159
Dhaval Patel0aee0972017-02-08 19:00:58 -08003160 if (psde->features & BIT(SDE_SSPP_CSC) ||
3161 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003162 msm_property_install_volatile_range(
3163 &psde->property_info, "csc_v1", 0x0,
3164 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003165
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003166 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3167 snprintf(feature_name, sizeof(feature_name), "%s%d",
3168 "SDE_SSPP_HUE_V",
3169 psde->pipe_sblk->hsic_blk.version >> 16);
3170 msm_property_install_range(&psde->property_info,
3171 feature_name, 0, 0, 0xFFFFFFFF, 0,
3172 PLANE_PROP_HUE_ADJUST);
3173 snprintf(feature_name, sizeof(feature_name), "%s%d",
3174 "SDE_SSPP_SATURATION_V",
3175 psde->pipe_sblk->hsic_blk.version >> 16);
3176 msm_property_install_range(&psde->property_info,
3177 feature_name, 0, 0, 0xFFFFFFFF, 0,
3178 PLANE_PROP_SATURATION_ADJUST);
3179 snprintf(feature_name, sizeof(feature_name), "%s%d",
3180 "SDE_SSPP_VALUE_V",
3181 psde->pipe_sblk->hsic_blk.version >> 16);
3182 msm_property_install_range(&psde->property_info,
3183 feature_name, 0, 0, 0xFFFFFFFF, 0,
3184 PLANE_PROP_VALUE_ADJUST);
3185 snprintf(feature_name, sizeof(feature_name), "%s%d",
3186 "SDE_SSPP_CONTRAST_V",
3187 psde->pipe_sblk->hsic_blk.version >> 16);
3188 msm_property_install_range(&psde->property_info,
3189 feature_name, 0, 0, 0xFFFFFFFF, 0,
3190 PLANE_PROP_CONTRAST_ADJUST);
3191 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003192 }
3193
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003194 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3195 msm_property_install_volatile_range(&psde->property_info,
3196 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3197
Alan Kwong4dd64c82017-02-04 18:41:51 -08003198 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003199
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003200 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003201 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003202
Dhaval Patel47302cf2016-08-18 15:04:28 -07003203 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3204 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3205
3206 if (psde->pipe_hw->ops.setup_solidfill)
3207 msm_property_install_range(&psde->property_info, "color_fill",
3208 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3209
Dhaval Patel4e574842016-08-23 15:11:37 -07003210 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003211 if (!info) {
3212 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003213 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003214 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003215
3216 msm_property_install_blob(&psde->property_info, "capabilities",
3217 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3218 sde_kms_info_reset(info);
3219
Clarence Ipea3d6262016-07-15 16:20:11 -04003220 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003221
3222 if (master_plane_id) {
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003223 int index, array_size;
3224
3225 array_size = ARRAY_SIZE(plane_formats)
3226 + ARRAY_SIZE(rgb_10bit_formats);
3227 virt_format_list = kcalloc(array_size,
3228 sizeof(struct sde_format_extended), GFP_KERNEL);
3229 if (!virt_format_list) {
3230 SDE_ERROR(
3231 "failed to allocate virtual pipe format list\n");
3232 return;
3233 }
3234
3235 index = sde_copy_formats(virt_format_list, array_size,
3236 0, plane_formats, ARRAY_SIZE(plane_formats));
3237 sde_copy_formats(virt_format_list, array_size,
3238 index, rgb_10bit_formats,
3239 ARRAY_SIZE(rgb_10bit_formats));
3240
3241 format_list = virt_format_list;
3242
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003243 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003244 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003245 }
3246
Clarence Ipea3d6262016-07-15 16:20:11 -04003247 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003248 sde_kms_info_start(info, "pixel_formats");
3249 while (format_list->fourcc_format) {
3250 sde_kms_info_append_format(info,
3251 format_list->fourcc_format,
3252 format_list->modifier);
3253 ++format_list;
3254 }
3255 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003256 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003257
3258 sde_kms_info_add_keyint(info, "max_linewidth",
3259 psde->pipe_sblk->maxlinewidth);
3260 sde_kms_info_add_keyint(info, "max_upscale",
3261 psde->pipe_sblk->maxupscale);
3262 sde_kms_info_add_keyint(info, "max_downscale",
3263 psde->pipe_sblk->maxdwnscale);
3264 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3265 psde->pipe_sblk->maxhdeciexp);
3266 sde_kms_info_add_keyint(info, "max_vertical_deci",
3267 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07003268 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
3269 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07003270 msm_property_set_blob(&psde->property_info, &psde->blob_info,
3271 info->data, info->len, PLANE_PROP_INFO);
3272
3273 kfree(info);
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003274 kfree(virt_format_list);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003275
3276 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3277 snprintf(feature_name, sizeof(feature_name), "%s%d",
3278 "SDE_SSPP_SKIN_COLOR_V",
3279 psde->pipe_sblk->memcolor_blk.version >> 16);
3280 msm_property_install_blob(&psde->property_info, feature_name, 0,
3281 PLANE_PROP_SKIN_COLOR);
3282 snprintf(feature_name, sizeof(feature_name), "%s%d",
3283 "SDE_SSPP_SKY_COLOR_V",
3284 psde->pipe_sblk->memcolor_blk.version >> 16);
3285 msm_property_install_blob(&psde->property_info, feature_name, 0,
3286 PLANE_PROP_SKY_COLOR);
3287 snprintf(feature_name, sizeof(feature_name), "%s%d",
3288 "SDE_SSPP_FOLIAGE_COLOR_V",
3289 psde->pipe_sblk->memcolor_blk.version >> 16);
3290 msm_property_install_blob(&psde->property_info, feature_name, 0,
3291 PLANE_PROP_FOLIAGE_COLOR);
3292 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003293}
3294
Clarence Ip5fc00c52016-09-23 15:03:34 -04003295static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
3296{
3297 struct sde_drm_csc_v1 csc_v1;
3298 int i;
3299
3300 if (!psde) {
3301 SDE_ERROR("invalid plane\n");
3302 return;
3303 }
3304
3305 psde->csc_usr_ptr = NULL;
3306 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003307 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003308 return;
3309 }
3310
3311 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003312 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003313 return;
3314 }
3315
Clarence Ipb43d4592016-09-08 14:21:35 -04003316 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04003317 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
3318 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
3319 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
3320 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
3321 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
3322 }
3323 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
3324 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
3325 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
3326 }
3327 psde->csc_usr_ptr = &psde->csc_cfg;
3328}
3329
Clarence Ipb43d4592016-09-08 14:21:35 -04003330static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
3331{
3332 struct sde_drm_scaler_v1 scale_v1;
3333 struct sde_hw_pixel_ext *pe;
3334 int i;
3335
3336 if (!psde) {
3337 SDE_ERROR("invalid plane\n");
3338 return;
3339 }
3340
3341 psde->pixel_ext_usr = false;
3342 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003343 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003344 return;
3345 }
3346
3347 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003348 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003349 return;
3350 }
3351
3352 /* populate from user space */
3353 pe = &(psde->pixel_ext);
3354 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3355 for (i = 0; i < SDE_MAX_PLANES; i++) {
3356 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
3357 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
3358 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
3359 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
3360
3361 pe->horz_filter[i] = scale_v1.horz_filter[i];
3362 pe->vert_filter[i] = scale_v1.vert_filter[i];
3363 }
3364 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003365 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
3366 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
3367 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
3368 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
3369 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003370
abeykun41060122016-11-28 13:02:01 -05003371 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
3372 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
3373 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
3374 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
3375 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003376 }
abeykun41060122016-11-28 13:02:01 -05003377
Clarence Ipb43d4592016-09-08 14:21:35 -04003378 psde->pixel_ext_usr = true;
3379
Clarence Ip13a8cf42016-09-29 17:27:47 -04003380 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003381}
3382
abeykun48f407a2016-08-25 12:06:44 -04003383static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
3384 struct sde_plane_state *pstate, void *usr)
3385{
3386 struct sde_drm_scaler_v2 scale_v2;
3387 struct sde_hw_pixel_ext *pe;
3388 int i;
3389 struct sde_hw_scaler3_cfg *cfg;
3390
3391 if (!psde) {
3392 SDE_ERROR("invalid plane\n");
3393 return;
3394 }
3395
3396 cfg = psde->scaler3_cfg;
3397 psde->pixel_ext_usr = false;
3398 if (!usr) {
3399 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3400 return;
3401 }
3402
3403 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
3404 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
3405 return;
3406 }
3407
3408 /* populate from user space */
3409 pe = &(psde->pixel_ext);
3410 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3411 cfg->enable = scale_v2.enable;
3412 cfg->dir_en = scale_v2.dir_en;
3413 for (i = 0; i < SDE_MAX_PLANES; i++) {
3414 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
3415 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
3416 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
3417 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
3418
3419 cfg->preload_x[i] = scale_v2.preload_x[i];
3420 cfg->preload_y[i] = scale_v2.preload_y[i];
3421 cfg->src_width[i] = scale_v2.src_width[i];
3422 cfg->src_height[i] = scale_v2.src_height[i];
3423 }
3424 cfg->dst_width = scale_v2.dst_width;
3425 cfg->dst_height = scale_v2.dst_height;
3426
3427 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
3428 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
3429 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
3430 cfg->blend_cfg = scale_v2.blend_cfg;
3431
3432 cfg->lut_flag = scale_v2.lut_flag;
3433 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
3434 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
3435 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
3436 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
3437 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
3438
3439 cfg->de.enable = scale_v2.de.enable;
3440 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
3441 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
3442 cfg->de.clip = scale_v2.de.clip;
3443 cfg->de.limit = scale_v2.de.limit;
3444 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
3445 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
3446 cfg->de.thr_low = scale_v2.de.thr_low;
3447 cfg->de.thr_high = scale_v2.de.thr_high;
3448 cfg->de.prec_shift = scale_v2.de.prec_shift;
3449 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
3450 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
3451 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
3452 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
3453 }
3454 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003455 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
3456 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
3457 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
3458 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
3459 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04003460
abeykun41060122016-11-28 13:02:01 -05003461 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
3462 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
3463 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
3464 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
3465 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04003466 }
3467 psde->pixel_ext_usr = true;
3468
3469 SDE_DEBUG_PLANE(psde, "user property data copied\n");
3470}
3471
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003472static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
3473 struct sde_plane_state *pstate, void *usr_ptr)
3474{
3475 struct drm_clip_rect excl_rect_v1;
3476
3477 if (!psde) {
3478 SDE_ERROR("invalid plane\n");
3479 return;
3480 }
3481
3482 if (!usr_ptr) {
3483 SDE_DEBUG_PLANE(psde, "excl rect data removed\n");
3484 return;
3485 }
3486
3487 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
3488 SDE_ERROR_PLANE(psde, "failed to copy excl rect data\n");
3489 return;
3490 }
3491
3492 /* populate from user space */
3493 pstate->excl_rect.x = excl_rect_v1.x1;
3494 pstate->excl_rect.y = excl_rect_v1.y1;
3495 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1 + 1;
3496 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1 + 1;
3497}
3498
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003499static int sde_plane_atomic_set_property(struct drm_plane *plane,
3500 struct drm_plane_state *state, struct drm_property *property,
3501 uint64_t val)
3502{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003503 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003504 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003505 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003506
Clarence Ip13a8cf42016-09-29 17:27:47 -04003507 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003508
3509 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003510 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003511 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003512 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003513 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04003514 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003515 ret = msm_property_atomic_set(&psde->property_info,
3516 pstate->property_values, pstate->property_blobs,
3517 property, val);
3518 if (!ret) {
3519 idx = msm_property_index(&psde->property_info,
3520 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003521 switch (idx) {
3522 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04003523 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003524 break;
3525 case PLANE_PROP_CSC_V1:
3526 _sde_plane_set_csc_v1(psde, (void *)val);
3527 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04003528 case PLANE_PROP_SCALER_V1:
3529 _sde_plane_set_scaler_v1(psde, (void *)val);
3530 break;
abeykun48f407a2016-08-25 12:06:44 -04003531 case PLANE_PROP_SCALER_V2:
3532 _sde_plane_set_scaler_v2(psde, pstate,
3533 (void *)val);
3534 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003535 case PLANE_PROP_EXCL_RECT_V1:
3536 _sde_plane_set_excl_rect_v1(psde, pstate,
3537 (void *)val);
3538 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04003539 default:
3540 /* nothing to do */
3541 break;
3542 }
Clarence Ipe78efb72016-06-24 18:35:21 -04003543 }
3544 }
3545
Alan Kwong4dd64c82017-02-04 18:41:51 -08003546 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
3547 property->name, property->base.id, val, ret);
3548
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003549 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003550}
3551
3552static int sde_plane_set_property(struct drm_plane *plane,
3553 struct drm_property *property, uint64_t val)
3554{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003555 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003556
Clarence Ipae4e60c2016-06-26 22:44:04 -04003557 return sde_plane_atomic_set_property(plane,
3558 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003559}
3560
3561static int sde_plane_atomic_get_property(struct drm_plane *plane,
3562 const struct drm_plane_state *state,
3563 struct drm_property *property, uint64_t *val)
3564{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003565 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003566 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04003567 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003568
Clarence Ipaa0faf42016-05-30 12:07:48 -04003569 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003570 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003571 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003572 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003573 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003574 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04003575 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003576 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003577 ret = msm_property_atomic_get(&psde->property_info,
3578 pstate->property_values, pstate->property_blobs,
3579 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04003580 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003581
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003582 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003583}
3584
3585static void sde_plane_destroy(struct drm_plane *plane)
3586{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003587 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003588
Clarence Ip13a8cf42016-09-29 17:27:47 -04003589 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003590
Clarence Ip13a8cf42016-09-29 17:27:47 -04003591 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04003592 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3593
Dhaval Patel4e574842016-08-23 15:11:37 -07003594 if (psde->blob_info)
3595 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003596 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04003597 mutex_destroy(&psde->lock);
3598
Clarence Ip4ce59322016-06-26 22:27:51 -04003599 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003600
Clarence Ip4ce59322016-06-26 22:27:51 -04003601 /* this will destroy the states as well */
3602 drm_plane_cleanup(plane);
3603
Clarence Ip4c1d9772016-06-26 09:35:38 -04003604 if (psde->pipe_hw)
3605 sde_hw_sspp_destroy(psde->pipe_hw);
3606
Clarence Ip4ce59322016-06-26 22:27:51 -04003607 kfree(psde);
3608 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003609}
3610
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003611static void sde_plane_destroy_state(struct drm_plane *plane,
3612 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003613{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003614 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04003615 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003616
Clarence Ipae4e60c2016-06-26 22:44:04 -04003617 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003618 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3619 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003620 return;
3621 }
3622
Clarence Ipaa0faf42016-05-30 12:07:48 -04003623 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04003624 pstate = to_sde_plane_state(state);
3625
Clarence Ip13a8cf42016-09-29 17:27:47 -04003626 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003627
Alan Kwong4dd64c82017-02-04 18:41:51 -08003628 sde_plane_rot_destroy_state(plane, &pstate->base);
3629
Clarence Ipe78efb72016-06-24 18:35:21 -04003630 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003631 if (state->fb)
3632 drm_framebuffer_unreference(state->fb);
3633
Clarence Ipae4e60c2016-06-26 22:44:04 -04003634 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003635 if (pstate->input_fence)
3636 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003637
Clarence Ipaa0faf42016-05-30 12:07:48 -04003638 /* destroy value helper */
3639 msm_property_destroy_state(&psde->property_info, pstate,
3640 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003641}
3642
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003643static struct drm_plane_state *
3644sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003645{
Clarence Ipaa0faf42016-05-30 12:07:48 -04003646 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003647 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04003648 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04003649 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003650
Clarence Ip13a8cf42016-09-29 17:27:47 -04003651 if (!plane) {
3652 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003653 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003654 } else if (!plane->state) {
3655 SDE_ERROR("invalid plane state\n");
3656 return NULL;
3657 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003658
Clarence Ip730e7192016-06-26 22:45:09 -04003659 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003660 psde = to_sde_plane(plane);
3661 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003662 if (!pstate) {
3663 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003664 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003665 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003666
Clarence Ip13a8cf42016-09-29 17:27:47 -04003667 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003668
3669 /* duplicate value helper */
3670 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
3671 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04003672
Clarence Ip17e908b2016-09-29 15:58:00 -04003673 /* clear out any input fence */
3674 pstate->input_fence = 0;
3675 input_fence_default = msm_property_get_default(
3676 &psde->property_info, PLANE_PROP_INPUT_FENCE);
3677 msm_property_set_property(&psde->property_info, pstate->property_values,
3678 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003679
Clarence Ip282dad62016-09-27 17:07:35 -04003680 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04003681 pstate->pending = false;
3682
Alan Kwongcdb2f282017-03-18 13:42:06 -07003683 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
3684
Alan Kwong4dd64c82017-02-04 18:41:51 -08003685 sde_plane_rot_duplicate_state(plane, &pstate->base);
3686
Clarence Ip730e7192016-06-26 22:45:09 -04003687 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003688}
3689
3690static void sde_plane_reset(struct drm_plane *plane)
3691{
Clarence Ipae4e60c2016-06-26 22:44:04 -04003692 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003693 struct sde_plane_state *pstate;
3694
Clarence Ipae4e60c2016-06-26 22:44:04 -04003695 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003696 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003697 return;
3698 }
3699
Clarence Ip730e7192016-06-26 22:45:09 -04003700 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003701 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003702
Clarence Ipae4e60c2016-06-26 22:44:04 -04003703 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04003704 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04003705 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003706 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04003707 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003708
Clarence Ipaa0faf42016-05-30 12:07:48 -04003709 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003710 if (!pstate) {
3711 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003712 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003713 }
Clarence Ip730e7192016-06-26 22:45:09 -04003714
Clarence Ipaa0faf42016-05-30 12:07:48 -04003715 /* reset value helper */
3716 msm_property_reset_state(&psde->property_info, pstate,
3717 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003718
3719 pstate->base.plane = plane;
3720
3721 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003722}
3723
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003724#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04003725static ssize_t _sde_plane_danger_read(struct file *file,
3726 char __user *buff, size_t count, loff_t *ppos)
3727{
3728 struct sde_kms *kms = file->private_data;
3729 struct sde_mdss_cfg *cfg = kms->catalog;
3730 int len = 0;
3731 char buf[40] = {'\0'};
3732
3733 if (!cfg)
3734 return -ENODEV;
3735
3736 if (*ppos)
3737 return 0; /* the end */
3738
3739 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
3740 if (len < 0 || len >= sizeof(buf))
3741 return 0;
3742
3743 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
3744 return -EFAULT;
3745
3746 *ppos += len; /* increase offset */
3747
3748 return len;
3749}
3750
3751static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
3752{
3753 struct drm_plane *plane;
3754
3755 drm_for_each_plane(plane, kms->dev) {
3756 if (plane->fb && plane->state) {
3757 sde_plane_danger_signal_ctrl(plane, enable);
3758 SDE_DEBUG("plane:%d img:%dx%d ",
3759 plane->base.id, plane->fb->width,
3760 plane->fb->height);
3761 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
3762 plane->state->src_x >> 16,
3763 plane->state->src_y >> 16,
3764 plane->state->src_w >> 16,
3765 plane->state->src_h >> 16,
3766 plane->state->crtc_x, plane->state->crtc_y,
3767 plane->state->crtc_w, plane->state->crtc_h);
3768 } else {
3769 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
3770 }
3771 }
3772}
3773
3774static ssize_t _sde_plane_danger_write(struct file *file,
3775 const char __user *user_buf, size_t count, loff_t *ppos)
3776{
3777 struct sde_kms *kms = file->private_data;
3778 struct sde_mdss_cfg *cfg = kms->catalog;
3779 int disable_panic;
3780 char buf[10];
3781
3782 if (!cfg)
3783 return -EFAULT;
3784
3785 if (count >= sizeof(buf))
3786 return -EFAULT;
3787
3788 if (copy_from_user(buf, user_buf, count))
3789 return -EFAULT;
3790
3791 buf[count] = 0; /* end of string */
3792
3793 if (kstrtoint(buf, 0, &disable_panic))
3794 return -EFAULT;
3795
3796 if (disable_panic) {
3797 /* Disable panic signal for all active pipes */
3798 SDE_DEBUG("Disabling danger:\n");
3799 _sde_plane_set_danger_state(kms, false);
3800 kms->has_danger_ctrl = false;
3801 } else {
3802 /* Enable panic signal for all active pipes */
3803 SDE_DEBUG("Enabling danger:\n");
3804 kms->has_danger_ctrl = true;
3805 _sde_plane_set_danger_state(kms, true);
3806 }
3807
3808 return count;
3809}
3810
3811static const struct file_operations sde_plane_danger_enable = {
3812 .open = simple_open,
3813 .read = _sde_plane_danger_read,
3814 .write = _sde_plane_danger_write,
3815};
3816
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003817static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04003818{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003819 struct sde_plane *psde;
3820 struct sde_kms *kms;
3821 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04003822 const struct sde_sspp_sub_blks *sblk = 0;
3823 const struct sde_sspp_cfg *cfg = 0;
3824
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003825 if (!plane || !plane->dev) {
3826 SDE_ERROR("invalid arguments\n");
3827 return -EINVAL;
3828 }
3829
3830 priv = plane->dev->dev_private;
3831 if (!priv || !priv->kms) {
3832 SDE_ERROR("invalid KMS reference\n");
3833 return -EINVAL;
3834 }
3835
3836 kms = to_sde_kms(priv->kms);
3837 psde = to_sde_plane(plane);
3838
Clarence Ip4ce59322016-06-26 22:27:51 -04003839 if (psde && psde->pipe_hw)
3840 cfg = psde->pipe_hw->cap;
3841 if (cfg)
3842 sblk = cfg->sblk;
3843
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003844 if (!sblk)
3845 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04003846
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003847 /* create overall sub-directory for the pipe */
3848 psde->debugfs_root =
3849 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07003850 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04003851
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003852 if (!psde->debugfs_root)
3853 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04003854
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003855 /* don't error check these */
3856 debugfs_create_x32("features", 0644,
3857 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003858
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003859 /* add register dump support */
3860 sde_debugfs_setup_regset32(&psde->debugfs_src,
3861 sblk->src_blk.base + cfg->base,
3862 sblk->src_blk.len,
3863 kms);
3864 sde_debugfs_create_regset32("src_blk", 0444,
3865 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04003866
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003867 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
3868 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
3869 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
3870 sblk->scaler_blk.base + cfg->base,
3871 sblk->scaler_blk.len,
3872 kms);
3873 sde_debugfs_create_regset32("scaler_blk", 0444,
3874 psde->debugfs_root,
3875 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07003876 debugfs_create_bool("default_scaling",
3877 0644,
3878 psde->debugfs_root,
3879 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04003880 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003881
3882 if (cfg->features & BIT(SDE_SSPP_CSC) ||
3883 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
3884 sde_debugfs_setup_regset32(&psde->debugfs_csc,
3885 sblk->csc_blk.base + cfg->base,
3886 sblk->csc_blk.len,
3887 kms);
3888 sde_debugfs_create_regset32("csc_blk", 0444,
3889 psde->debugfs_root, &psde->debugfs_csc);
3890 }
3891
3892 debugfs_create_u32("xin_id",
3893 0444,
3894 psde->debugfs_root,
3895 (u32 *) &cfg->xin_id);
3896 debugfs_create_u32("clk_ctrl",
3897 0444,
3898 psde->debugfs_root,
3899 (u32 *) &cfg->clk_ctrl);
3900 debugfs_create_x32("creq_vblank",
3901 0644,
3902 psde->debugfs_root,
3903 (u32 *) &sblk->creq_vblank);
3904 debugfs_create_x32("danger_vblank",
3905 0644,
3906 psde->debugfs_root,
3907 (u32 *) &sblk->danger_vblank);
3908
3909 debugfs_create_file("disable_danger",
3910 0644,
3911 psde->debugfs_root,
3912 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003913 debugfs_create_u32("sbuf_mode",
3914 0644,
3915 psde->debugfs_root, &psde->sbuf_mode);
3916 debugfs_create_u32("sbuf_writeback",
3917 0644,
3918 psde->debugfs_root,
3919 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07003920
3921 return 0;
3922}
3923
3924static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3925{
3926 struct sde_plane *psde;
3927
3928 if (!plane)
3929 return;
3930 psde = to_sde_plane(plane);
3931
3932 debugfs_remove_recursive(psde->debugfs_root);
3933}
3934#else
3935static int _sde_plane_init_debugfs(struct drm_plane *plane)
3936{
3937 return 0;
3938}
3939static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
3940{
3941}
3942#endif
3943
3944static int sde_plane_late_register(struct drm_plane *plane)
3945{
3946 return _sde_plane_init_debugfs(plane);
3947}
3948
3949static void sde_plane_early_unregister(struct drm_plane *plane)
3950{
3951 _sde_plane_destroy_debugfs(plane);
3952}
3953
3954static const struct drm_plane_funcs sde_plane_funcs = {
3955 .update_plane = drm_atomic_helper_update_plane,
3956 .disable_plane = drm_atomic_helper_disable_plane,
3957 .destroy = sde_plane_destroy,
3958 .set_property = sde_plane_set_property,
3959 .atomic_set_property = sde_plane_atomic_set_property,
3960 .atomic_get_property = sde_plane_atomic_get_property,
3961 .reset = sde_plane_reset,
3962 .atomic_duplicate_state = sde_plane_duplicate_state,
3963 .atomic_destroy_state = sde_plane_destroy_state,
3964 .late_register = sde_plane_late_register,
3965 .early_unregister = sde_plane_early_unregister,
3966};
3967
3968static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
3969 .prepare_fb = sde_plane_prepare_fb,
3970 .cleanup_fb = sde_plane_cleanup_fb,
3971 .atomic_check = sde_plane_atomic_check,
3972 .atomic_update = sde_plane_atomic_update,
3973};
3974
3975enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
3976{
3977 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
3978}
3979
3980bool is_sde_plane_virtual(struct drm_plane *plane)
3981{
3982 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04003983}
3984
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003985/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04003986struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04003987 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003988 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003989{
3990 struct drm_plane *plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003991 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003992 struct sde_format_extended *virt_format_list = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003993 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003994 struct msm_drm_private *priv;
3995 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003996 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04003997 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04003998
3999 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004000 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004001 goto exit;
4002 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004003
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004004 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004005 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004006 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004007 goto exit;
4008 }
4009
4010 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004011 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004012 goto exit;
4013 }
4014 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004015
Clarence Ip4c1d9772016-06-26 09:35:38 -04004016 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004017 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004018 goto exit;
4019 }
4020
Clarence Ip4ce59322016-06-26 22:27:51 -04004021 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004022 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4023 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004024 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004025 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004026 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004027 }
4028
Clarence Ip4c1d9772016-06-26 09:35:38 -04004029 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004030 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004031 psde->pipe = pipe;
Alan Kwong112a84f2016-05-24 20:49:21 -04004032 psde->mmu_id = kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004033 psde->is_virtual = (master_plane_id != 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004034
Clarence Ip4c1d9772016-06-26 09:35:38 -04004035 /* initialize underlying h/w driver */
4036 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
4037 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004038 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004039 ret = PTR_ERR(psde->pipe_hw);
4040 goto clean_plane;
4041 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004042 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004043 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004044 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004045
4046 /* cache features mask for later */
4047 psde->features = psde->pipe_hw->cap->features;
4048 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004049 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004050 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004051 goto clean_sspp;
4052 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004053
abeykun48f407a2016-08-25 12:06:44 -04004054 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
4055 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
4056 GFP_KERNEL);
4057 if (!psde->scaler3_cfg) {
4058 SDE_ERROR("[%u]failed to allocate scale struct\n",
4059 pipe);
4060 ret = -ENOMEM;
4061 goto clean_sspp;
4062 }
4063 }
4064
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004065 format_list = psde->pipe_sblk->format_list;
4066
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004067 if (master_plane_id) {
4068 int index, array_size;
4069
4070 array_size = ARRAY_SIZE(plane_formats)
4071 + ARRAY_SIZE(rgb_10bit_formats);
4072 virt_format_list = kcalloc(array_size,
4073 sizeof(struct sde_format_extended),
4074 GFP_KERNEL);
4075 if (!virt_format_list) {
4076 SDE_ERROR(
4077 "failed to allocate virtual pipe format list\n");
4078 goto clean_sspp;
4079 }
4080
4081 index = sde_copy_formats(virt_format_list, array_size,
4082 0, plane_formats, ARRAY_SIZE(plane_formats));
4083 sde_copy_formats(virt_format_list, array_size,
4084 index, rgb_10bit_formats,
4085 ARRAY_SIZE(rgb_10bit_formats));
4086
4087 format_list = virt_format_list;
4088 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004089
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004090 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004091 psde->formats,
4092 0,
4093 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004094
Clarence Ip4c1d9772016-06-26 09:35:38 -04004095 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004096 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004097 goto clean_sspp;
4098 }
4099
4100 if (psde->features & BIT(SDE_SSPP_CURSOR))
4101 type = DRM_PLANE_TYPE_CURSOR;
4102 else if (primary_plane)
4103 type = DRM_PLANE_TYPE_PRIMARY;
4104 else
4105 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07004106 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
4107 psde->formats, psde->nformats,
4108 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004109 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04004110 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004111
Clarence Ip4c1d9772016-06-26 09:35:38 -04004112 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004113 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004114
Clarence Ipaa0faf42016-05-30 12:07:48 -04004115 msm_property_init(&psde->property_info, &plane->base, dev,
4116 priv->plane_property, psde->property_data,
4117 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
4118 sizeof(struct sde_plane_state));
4119
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004120 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004121
Clarence Ip4ce59322016-06-26 22:27:51 -04004122 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004123 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004124
Clarence Ip730e7192016-06-26 22:45:09 -04004125 mutex_init(&psde->lock);
4126
Dhaval Patel82c8dbc2017-02-18 23:15:10 -08004127 SDE_DEBUG("%s created for pipe %u\n", psde->pipe_name, pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004128 return plane;
4129
Clarence Ip4c1d9772016-06-26 09:35:38 -04004130clean_sspp:
4131 if (psde && psde->pipe_hw)
4132 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04004133
4134 if (psde && psde->scaler3_cfg)
4135 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004136clean_plane:
4137 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004138exit:
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004139 kfree(virt_format_list);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004140 return ERR_PTR(ret);
4141}