blob: 7675c11d2e1a84b5a782768bc8831ed751d0a90e [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 Ip059c8c32017-06-06 17:15:54 -040097/**
98 * enum sde_plane_sclcheck_state - User scaler data status
99 *
100 * @SDE_PLANE_SCLCHECK_NONE: No user data provided
101 * @SDE_PLANE_SCLCHECK_INVALID: Invalid user data provided
102 * @SDE_PLANE_SCLCHECK_SCALER_V1: Valid scaler v1 data
103 * @SDE_PLANE_SCLCHECK_SCALER_V1_CHECK: Unchecked scaler v1 data
104 * @SDE_PLANE_SCLCHECK_SCALER_V2: Valid scaler v2 data
105 * @SDE_PLANE_SCLCHECK_SCALER_V2_CHECK: Unchecked scaler v2 data
106 */
107enum sde_plane_sclcheck_state {
108 SDE_PLANE_SCLCHECK_NONE,
109 SDE_PLANE_SCLCHECK_INVALID,
110 SDE_PLANE_SCLCHECK_SCALER_V1,
111 SDE_PLANE_SCLCHECK_SCALER_V1_CHECK,
112 SDE_PLANE_SCLCHECK_SCALER_V2,
113 SDE_PLANE_SCLCHECK_SCALER_V2_CHECK,
114};
115
Clarence Ip5fc00c52016-09-23 15:03:34 -0400116/*
117 * struct sde_plane - local sde plane structure
Jordan Croused8e96522017-02-13 10:14:16 -0700118 * @aspace: address space pointer
Clarence Ip5fc00c52016-09-23 15:03:34 -0400119 * @csc_cfg: Decoded user configuration for csc
120 * @csc_usr_ptr: Points to csc_cfg if valid user config available
121 * @csc_ptr: Points to sde_csc_cfg structure to use for current
Alan Kwongdce56da2017-04-27 15:50:34 -0700122 * @mplane_list: List of multirect planes of the same pipe
Alan Kwong4dd64c82017-02-04 18:41:51 -0800123 * @catalog: Points to sde catalog structure
124 * @sbuf_mode: force stream buffer mode if set
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700125 * @sbuf_writeback: force stream buffer writeback if set
126 * @revalidate: force revalidation of all the plane properties
Clarence Ip059c8c32017-06-06 17:15:54 -0400127 * @scaler_check_state: Indicates status of user provided pixle extension data
Alan Kwong4dd64c82017-02-04 18:41:51 -0800128 * @blob_rot_caps: Pointer to rotator capability blob
Clarence Ip5fc00c52016-09-23 15:03:34 -0400129 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700130struct sde_plane {
131 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400132
Clarence Ip730e7192016-06-26 22:45:09 -0400133 struct mutex lock;
134
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400135 enum sde_sspp pipe;
136 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700137 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400138 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400139
140 struct sde_hw_pipe *pipe_hw;
141 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -0400142 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -0400143 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400144 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400145 uint32_t color_fill;
146 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400147 bool is_rt_pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800148 bool is_virtual;
Alan Kwongdce56da2017-04-27 15:50:34 -0700149 struct list_head mplane_list;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800150 struct sde_mdss_cfg *catalog;
151 u32 sbuf_mode;
152 u32 sbuf_writeback;
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700153 bool revalidate;
Clarence Ip4ce59322016-06-26 22:27:51 -0400154
Clarence Ipb43d4592016-09-08 14:21:35 -0400155 struct sde_hw_pixel_ext pixel_ext;
Clarence Ip059c8c32017-06-06 17:15:54 -0400156 enum sde_plane_sclcheck_state scaler_check_state;
Clarence Ipb43d4592016-09-08 14:21:35 -0400157
Clarence Ip373f8592016-05-26 00:58:42 -0400158 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400159 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400160 struct sde_csc_cfg *csc_ptr;
161
Clarence Ip4c1d9772016-06-26 09:35:38 -0400162 const struct sde_sspp_sub_blks *pipe_sblk;
163
Clarence Ip5e2a9222016-06-26 22:38:24 -0400164 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400165
Clarence Ipaa0faf42016-05-30 12:07:48 -0400166 struct msm_property_info property_info;
167 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700168 struct drm_property_blob *blob_info;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800169 struct drm_property_blob *blob_rot_caps;
Clarence Ip730e7192016-06-26 22:45:09 -0400170
Clarence Ip4ce59322016-06-26 22:27:51 -0400171 /* debugfs related stuff */
172 struct dentry *debugfs_root;
173 struct sde_debugfs_regset32 debugfs_src;
174 struct sde_debugfs_regset32 debugfs_scaler;
175 struct sde_debugfs_regset32 debugfs_csc;
Clarence Ip716ab662017-03-20 06:51:24 -0700176 bool debugfs_default_scale;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700177};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700178
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700179#define to_sde_plane(x) container_of(x, struct sde_plane, base)
180
Alan Kwong4dd64c82017-02-04 18:41:51 -0800181static struct sde_kms *_sde_plane_get_kms(struct drm_plane *plane)
182{
183 struct msm_drm_private *priv;
184
185 if (!plane || !plane->dev)
186 return NULL;
187 priv = plane->dev->dev_private;
188 if (!priv)
189 return NULL;
190 return to_sde_kms(priv->kms);
191}
192
Alan Kwong4aacd532017-02-04 18:51:33 -0800193/**
194 * _sde_plane_get_crtc_state - obtain crtc state attached to given plane state
195 * @pstate: Pointer to drm plane state
196 * return: Pointer to crtc state if success; pointer error, otherwise
197 */
198static struct drm_crtc_state *_sde_plane_get_crtc_state(
199 struct drm_plane_state *pstate)
200{
201 struct drm_crtc_state *cstate;
202
203 if (!pstate || !pstate->crtc)
204 return NULL;
205
206 if (pstate->state)
207 cstate = drm_atomic_get_crtc_state(pstate->state, pstate->crtc);
208 else
209 cstate = pstate->crtc->state;
210
211 return cstate;
212}
213
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400214static bool sde_plane_enabled(struct drm_plane_state *state)
215{
Clarence Ipdbde9832016-06-26 09:48:36 -0400216 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400217}
218
Alan Kwong4dd64c82017-02-04 18:41:51 -0800219static bool sde_plane_sspp_enabled(struct drm_plane_state *state)
220{
221 return state && to_sde_plane_state(state)->rot.out_fb && state->crtc;
222}
223
224/**
225 * sde_plane_crtc_enabled - determine if crtc of given plane state is enabled
226 * @state: Pointer to drm plane state
227 * return: true if plane and the associated crtc are both enabled
228 */
229static bool sde_plane_crtc_enabled(struct drm_plane_state *state)
230{
231 return sde_plane_enabled(state) && state->crtc->state &&
232 state->crtc->state->active &&
233 state->crtc->state->enable;
234}
235
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400236/**
237 * _sde_plane_calc_fill_level - calculate fill level of the given source format
238 * @plane: Pointer to drm plane
239 * @fmt: Pointer to source buffer format
240 * @src_wdith: width of source buffer
241 * Return: fill level corresponding to the source buffer/format or 0 if error
242 */
243static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
244 const struct sde_format *fmt, u32 src_width)
245{
Alan Kwongdce56da2017-04-27 15:50:34 -0700246 struct sde_plane *psde, *tmp;
247 struct sde_plane_state *pstate;
248 struct sde_plane_rot_state *rstate;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400249 u32 fixed_buff_size;
250 u32 total_fl;
Alan Kwongdce56da2017-04-27 15:50:34 -0700251 u32 hflip_bytes;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400252
Alan Kwongdce56da2017-04-27 15:50:34 -0700253 if (!plane || !fmt || !plane->state || !src_width || !fmt->bpp) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400254 SDE_ERROR("invalid arguments\n");
255 return 0;
256 }
257
258 psde = to_sde_plane(plane);
Alan Kwongdce56da2017-04-27 15:50:34 -0700259 pstate = to_sde_plane_state(plane->state);
260 rstate = &pstate->rot;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400261 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
262
Alan Kwongdce56da2017-04-27 15:50:34 -0700263 list_for_each_entry(tmp, &psde->mplane_list, mplane_list) {
264 if (!sde_plane_enabled(tmp->base.state))
265 continue;
266 SDE_DEBUG("plane%d/%d src_width:%d/%d\n",
267 psde->base.base.id, tmp->base.base.id,
268 src_width, tmp->pipe_cfg.src_rect.w);
269 src_width = max_t(u32, src_width, tmp->pipe_cfg.src_rect.w);
270 }
271
272 if ((rstate->out_rotation & DRM_REFLECT_X) &&
273 SDE_FORMAT_IS_LINEAR(fmt))
274 hflip_bytes = (src_width + 32) * fmt->bpp;
275 else
276 hflip_bytes = 0;
277
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400278 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
279 if (fmt->chroma_sample == SDE_CHROMA_420) {
280 /* NV12 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700281 total_fl = (fixed_buff_size / 2 - hflip_bytes) /
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400282 ((src_width + 32) * fmt->bpp);
283 } else {
284 /* non NV12 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700285 total_fl = (fixed_buff_size / 2 - hflip_bytes) /
286 ((src_width + 32) * fmt->bpp * 2);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400287 }
288 } else {
Alan Kwongdce56da2017-04-27 15:50:34 -0700289 if (pstate->multirect_mode == SDE_SSPP_MULTIRECT_PARALLEL) {
290 total_fl = (fixed_buff_size / 2 - hflip_bytes) /
291 ((src_width + 32) * fmt->bpp * 2);
292 } else {
293 total_fl = (fixed_buff_size - hflip_bytes) /
294 ((src_width + 32) * fmt->bpp * 2);
295 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400296 }
297
Alan Kwongdce56da2017-04-27 15:50:34 -0700298 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u hf:%d fl:%u\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400299 plane->base.id, psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700300 (char *)&fmt->base.pixel_format,
Alan Kwongdce56da2017-04-27 15:50:34 -0700301 src_width, hflip_bytes, total_fl);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400302
303 return total_fl;
304}
305
306/**
Alan Kwongdce56da2017-04-27 15:50:34 -0700307 * _sde_plane_get_qos_lut - get LUT mapping based on fill level
308 * @tbl: Pointer to LUT table
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400309 * @total_fl: fill level
310 * Return: LUT setting corresponding to the fill level
311 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700312static u64 _sde_plane_get_qos_lut(const struct sde_qos_lut_tbl *tbl,
313 u32 total_fl)
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400314{
Alan Kwongdce56da2017-04-27 15:50:34 -0700315 int i;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400316
Alan Kwongdce56da2017-04-27 15:50:34 -0700317 if (!tbl || !tbl->nentry || !tbl->entries)
318 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400319
Alan Kwongdce56da2017-04-27 15:50:34 -0700320 for (i = 0; i < tbl->nentry; i++)
321 if (total_fl <= tbl->entries[i].fl)
322 return tbl->entries[i].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400323
Alan Kwongdce56da2017-04-27 15:50:34 -0700324 /* if last fl is zero, use as default */
325 if (!tbl->entries[i-1].fl)
326 return tbl->entries[i-1].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400327
Alan Kwongdce56da2017-04-27 15:50:34 -0700328 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400329}
330
331/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400332 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
333 * @plane: Pointer to drm plane
334 * @fb: Pointer to framebuffer associated with the given plane
335 */
336static void _sde_plane_set_qos_lut(struct drm_plane *plane,
337 struct drm_framebuffer *fb)
338{
339 struct sde_plane *psde;
340 const struct sde_format *fmt = NULL;
Alan Kwongdce56da2017-04-27 15:50:34 -0700341 u64 qos_lut;
342 u32 total_fl = 0, lut_usage;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400343
344 if (!plane || !fb) {
345 SDE_ERROR("invalid arguments plane %d fb %d\n",
346 plane != 0, fb != 0);
347 return;
348 }
349
350 psde = to_sde_plane(plane);
351
Alan Kwongdce56da2017-04-27 15:50:34 -0700352 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400353 SDE_ERROR("invalid arguments\n");
354 return;
355 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
356 return;
357 }
358
359 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700360 lut_usage = SDE_QOS_LUT_USAGE_NRT;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400361 } else {
362 fmt = sde_get_sde_format_ext(
363 fb->pixel_format,
364 fb->modifier,
365 drm_format_num_planes(fb->pixel_format));
366 total_fl = _sde_plane_calc_fill_level(plane, fmt,
367 psde->pipe_cfg.src_rect.w);
368
Narendra Muppallaec11a0a2017-06-15 15:35:17 -0700369 if (fmt && SDE_FORMAT_IS_LINEAR(fmt))
Alan Kwongdce56da2017-04-27 15:50:34 -0700370 lut_usage = SDE_QOS_LUT_USAGE_LINEAR;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400371 else
Alan Kwongdce56da2017-04-27 15:50:34 -0700372 lut_usage = SDE_QOS_LUT_USAGE_MACROTILE;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400373 }
374
Alan Kwongdce56da2017-04-27 15:50:34 -0700375 qos_lut = _sde_plane_get_qos_lut(
376 &psde->catalog->perf.qos_lut_tbl[lut_usage], total_fl);
377
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400378 psde->pipe_qos_cfg.creq_lut = qos_lut;
379
380 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
381 (fmt) ? fmt->base.pixel_format : 0,
Alan Kwongdce56da2017-04-27 15:50:34 -0700382 psde->is_rt_pipe, total_fl, qos_lut, lut_usage);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400383
Alan Kwongdce56da2017-04-27 15:50:34 -0700384 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400385 plane->base.id,
386 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700387 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400388 psde->is_rt_pipe, total_fl, qos_lut);
389
390 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
391}
392
393/**
394 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
395 * @plane: Pointer to drm plane
396 * @fb: Pointer to framebuffer associated with the given plane
397 */
398static void _sde_plane_set_danger_lut(struct drm_plane *plane,
399 struct drm_framebuffer *fb)
400{
401 struct sde_plane *psde;
402 const struct sde_format *fmt = NULL;
403 u32 danger_lut, safe_lut;
404
405 if (!plane || !fb) {
406 SDE_ERROR("invalid arguments\n");
407 return;
408 }
409
410 psde = to_sde_plane(plane);
411
Alan Kwongdce56da2017-04-27 15:50:34 -0700412 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400413 SDE_ERROR("invalid arguments\n");
414 return;
415 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
416 return;
417 }
418
419 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700420 danger_lut = psde->catalog->perf.danger_lut_tbl
421 [SDE_QOS_LUT_USAGE_NRT];
422 safe_lut = psde->catalog->perf.safe_lut_tbl
423 [SDE_QOS_LUT_USAGE_NRT];
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400424 } else {
425 fmt = sde_get_sde_format_ext(
426 fb->pixel_format,
427 fb->modifier,
428 drm_format_num_planes(fb->pixel_format));
429
Narendra Muppallaec11a0a2017-06-15 15:35:17 -0700430 if (fmt && SDE_FORMAT_IS_LINEAR(fmt)) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700431 danger_lut = psde->catalog->perf.danger_lut_tbl
432 [SDE_QOS_LUT_USAGE_LINEAR];
433 safe_lut = psde->catalog->perf.safe_lut_tbl
434 [SDE_QOS_LUT_USAGE_LINEAR];
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400435 } else {
Alan Kwongdce56da2017-04-27 15:50:34 -0700436 danger_lut = psde->catalog->perf.danger_lut_tbl
437 [SDE_QOS_LUT_USAGE_MACROTILE];
438 safe_lut = psde->catalog->perf.safe_lut_tbl
439 [SDE_QOS_LUT_USAGE_MACROTILE];
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400440 }
441 }
442
443 psde->pipe_qos_cfg.danger_lut = danger_lut;
444 psde->pipe_qos_cfg.safe_lut = safe_lut;
445
446 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
447 (fmt) ? fmt->base.pixel_format : 0,
448 (fmt) ? fmt->fetch_mode : 0,
449 psde->pipe_qos_cfg.danger_lut,
450 psde->pipe_qos_cfg.safe_lut);
451
Dhaval Patel6c666622017-03-21 23:02:59 -0700452 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400453 plane->base.id,
454 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700455 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400456 fmt ? fmt->fetch_mode : -1,
457 psde->pipe_qos_cfg.danger_lut,
458 psde->pipe_qos_cfg.safe_lut);
459
460 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
461 &psde->pipe_qos_cfg);
462}
463
464/**
465 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
466 * @plane: Pointer to drm plane
467 * @enable: true to enable QoS control
468 * @flags: QoS control mode (enum sde_plane_qos)
469 */
470static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
471 bool enable, u32 flags)
472{
473 struct sde_plane *psde;
474
475 if (!plane) {
476 SDE_ERROR("invalid arguments\n");
477 return;
478 }
479
480 psde = to_sde_plane(plane);
481
482 if (!psde->pipe_hw || !psde->pipe_sblk) {
483 SDE_ERROR("invalid arguments\n");
484 return;
485 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
486 return;
487 }
488
489 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
490 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
491 psde->pipe_qos_cfg.danger_vblank =
492 psde->pipe_sblk->danger_vblank;
493 psde->pipe_qos_cfg.vblank_en = enable;
494 }
495
496 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
497 /* this feature overrules previous VBLANK_CTRL */
498 psde->pipe_qos_cfg.vblank_en = false;
499 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
500 }
501
502 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
503 psde->pipe_qos_cfg.danger_safe_en = enable;
504
505 if (!psde->is_rt_pipe) {
506 psde->pipe_qos_cfg.vblank_en = false;
507 psde->pipe_qos_cfg.danger_safe_en = false;
508 }
509
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400510 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 -0400511 plane->base.id,
512 psde->pipe - SSPP_VIG0,
513 psde->pipe_qos_cfg.danger_safe_en,
514 psde->pipe_qos_cfg.vblank_en,
515 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400516 psde->pipe_qos_cfg.danger_vblank,
517 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400518
519 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
520 &psde->pipe_qos_cfg);
521}
522
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700523void sde_plane_set_revalidate(struct drm_plane *plane, bool enable)
524{
525 struct sde_plane *psde;
526
527 if (!plane)
528 return;
529
530 psde = to_sde_plane(plane);
531 psde->revalidate = enable;
532}
533
Alan Kwongf0fd8512016-10-24 21:39:26 -0400534int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
535{
536 struct sde_plane *psde;
537 struct msm_drm_private *priv;
538 struct sde_kms *sde_kms;
539
540 if (!plane || !plane->dev) {
541 SDE_ERROR("invalid arguments\n");
542 return -EINVAL;
543 }
544
545 priv = plane->dev->dev_private;
546 if (!priv || !priv->kms) {
547 SDE_ERROR("invalid KMS reference\n");
548 return -EINVAL;
549 }
550
551 sde_kms = to_sde_kms(priv->kms);
552 psde = to_sde_plane(plane);
553
554 if (!psde->is_rt_pipe)
555 goto end;
556
557 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
558
559 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
560
561 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
562
563end:
564 return 0;
565}
566
Alan Kwong5d324e42016-07-28 22:56:18 -0400567/**
568 * _sde_plane_set_ot_limit - set OT limit for the given plane
569 * @plane: Pointer to drm plane
570 * @crtc: Pointer to drm crtc
571 */
572static void _sde_plane_set_ot_limit(struct drm_plane *plane,
573 struct drm_crtc *crtc)
574{
575 struct sde_plane *psde;
576 struct sde_vbif_set_ot_params ot_params;
577 struct msm_drm_private *priv;
578 struct sde_kms *sde_kms;
579
580 if (!plane || !plane->dev || !crtc) {
581 SDE_ERROR("invalid arguments plane %d crtc %d\n",
582 plane != 0, crtc != 0);
583 return;
584 }
585
586 priv = plane->dev->dev_private;
587 if (!priv || !priv->kms) {
588 SDE_ERROR("invalid KMS reference\n");
589 return;
590 }
591
592 sde_kms = to_sde_kms(priv->kms);
593 psde = to_sde_plane(plane);
594 if (!psde->pipe_hw) {
595 SDE_ERROR("invalid pipe reference\n");
596 return;
597 }
598
599 memset(&ot_params, 0, sizeof(ot_params));
600 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
601 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
602 ot_params.width = psde->pipe_cfg.src_rect.w;
603 ot_params.height = psde->pipe_cfg.src_rect.h;
604 ot_params.is_wfd = !psde->is_rt_pipe;
605 ot_params.frame_rate = crtc->mode.vrefresh;
606 ot_params.vbif_idx = VBIF_RT;
607 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
608 ot_params.rd = true;
609
610 sde_vbif_set_ot_limit(sde_kms, &ot_params);
611}
612
Alan Kwonga62eeb82017-04-19 08:57:55 -0700613/**
614 * _sde_plane_set_vbif_qos - set vbif QoS for the given plane
615 * @plane: Pointer to drm plane
616 */
617static void _sde_plane_set_qos_remap(struct drm_plane *plane)
618{
619 struct sde_plane *psde;
620 struct sde_vbif_set_qos_params qos_params;
621 struct msm_drm_private *priv;
622 struct sde_kms *sde_kms;
623
624 if (!plane || !plane->dev) {
625 SDE_ERROR("invalid arguments\n");
626 return;
627 }
628
629 priv = plane->dev->dev_private;
630 if (!priv || !priv->kms) {
631 SDE_ERROR("invalid KMS reference\n");
632 return;
633 }
634
635 sde_kms = to_sde_kms(priv->kms);
636 psde = to_sde_plane(plane);
637 if (!psde->pipe_hw) {
638 SDE_ERROR("invalid pipe reference\n");
639 return;
640 }
641
642 memset(&qos_params, 0, sizeof(qos_params));
643 qos_params.vbif_idx = VBIF_RT;
644 qos_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
645 qos_params.xin_id = psde->pipe_hw->cap->xin_id;
646 qos_params.num = psde->pipe_hw->idx - SSPP_VIG0;
647 qos_params.is_rt = psde->is_rt_pipe;
648
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700649 SDE_DEBUG("plane%d pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n",
Alan Kwonga62eeb82017-04-19 08:57:55 -0700650 plane->base.id, qos_params.num,
651 qos_params.vbif_idx,
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700652 qos_params.xin_id, qos_params.is_rt,
653 qos_params.clk_ctrl);
Alan Kwonga62eeb82017-04-19 08:57:55 -0700654
655 sde_vbif_set_qos_remap(sde_kms, &qos_params);
656}
657
Alan Kwong2349d742017-04-20 08:27:30 -0700658/**
659 * _sde_plane_set_ts_prefill - set prefill with traffic shaper
660 * @plane: Pointer to drm plane
661 * @pstate: Pointer to sde plane state
662 */
663static void _sde_plane_set_ts_prefill(struct drm_plane *plane,
664 struct sde_plane_state *pstate)
665{
666 struct sde_plane *psde;
667 struct sde_hw_pipe_ts_cfg cfg;
668 struct msm_drm_private *priv;
669 struct sde_kms *sde_kms;
670
671 if (!plane || !plane->dev) {
672 SDE_ERROR("invalid arguments");
673 return;
674 }
675
676 priv = plane->dev->dev_private;
677 if (!priv || !priv->kms) {
678 SDE_ERROR("invalid KMS reference\n");
679 return;
680 }
681
682 sde_kms = to_sde_kms(priv->kms);
683 psde = to_sde_plane(plane);
684 if (!psde->pipe_hw) {
685 SDE_ERROR("invalid pipe reference\n");
686 return;
687 }
688
689 if (!psde->pipe_hw || !psde->pipe_hw->ops.setup_ts_prefill)
690 return;
691
692 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_VBLANK_AMORTIZE);
693
694 memset(&cfg, 0, sizeof(cfg));
695 cfg.size = sde_plane_get_property(pstate,
696 PLANE_PROP_PREFILL_SIZE);
697 cfg.time = sde_plane_get_property(pstate,
698 PLANE_PROP_PREFILL_TIME);
699
700 SDE_DEBUG("plane%d size:%llu time:%llu\n",
701 plane->base.id, cfg.size, cfg.time);
702 SDE_EVT32(DRMID(plane), cfg.size, cfg.time);
703 psde->pipe_hw->ops.setup_ts_prefill(psde->pipe_hw, &cfg,
704 pstate->multirect_index);
705}
706
Clarence Ipcae1bb62016-07-07 12:07:13 -0400707/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400708static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400709 struct sde_plane_state *pstate, uint64_t fd)
710{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400711 if (!psde || !pstate) {
712 SDE_ERROR("invalid arg(s), plane %d state %d\n",
713 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400714 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400715 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400716
717 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400718 if (pstate->input_fence)
719 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400720
721 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400722 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400723
Clarence Ip13a8cf42016-09-29 17:27:47 -0400724 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400725}
726
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700727/**
728 * _sde_plane_inline_rot_set_ot_limit - set OT limit for the given inline
729 * rotation xin client
730 * @plane: pointer to drm plane
731 * @crtc: pointer to drm crtc
732 * @cfg: pointer to rotator vbif config
733 * @rect_w: rotator frame width
734 * @rect_h: rotator frame height
735 */
736static void _sde_plane_inline_rot_set_ot_limit(struct drm_plane *plane,
737 struct drm_crtc *crtc, const struct sde_rot_vbif_cfg *cfg,
738 u32 rect_w, u32 rect_h)
739{
740 struct sde_vbif_set_ot_params ot_params;
741 struct msm_drm_private *priv;
742 struct sde_kms *sde_kms;
743
744 if (!plane || !plane->dev) {
745 SDE_ERROR("invalid arguments\n");
746 return;
747 }
748
749 priv = plane->dev->dev_private;
750 if (!priv || !priv->kms) {
751 SDE_ERROR("invalid KMS reference\n");
752 return;
753 }
754
755 sde_kms = to_sde_kms(priv->kms);
756
757 memset(&ot_params, 0, sizeof(ot_params));
758 ot_params.xin_id = cfg->xin_id;
759 ot_params.num = cfg->num;
760 ot_params.width = rect_w;
761 ot_params.height = rect_h;
762 ot_params.is_wfd = false;
763 ot_params.frame_rate = crtc->mode.vrefresh;
764 ot_params.vbif_idx = VBIF_RT;
765 ot_params.clk_ctrl = cfg->clk_ctrl;
766 ot_params.rd = cfg->is_read;
767
768 sde_vbif_set_ot_limit(sde_kms, &ot_params);
769}
770
771/**
772 * _sde_plane_inline_rot_set_qos_remap - set vbif QoS for the given inline
773 * rotation xin client
774 * @plane: Pointer to drm plane
775 * @cfg: Pointer to rotator vbif cfg
776 */
777static void _sde_plane_inline_rot_set_qos_remap(struct drm_plane *plane,
778 const struct sde_rot_vbif_cfg *cfg)
779{
780 struct sde_vbif_set_qos_params qos_params;
781 struct msm_drm_private *priv;
782 struct sde_kms *sde_kms;
783
784 if (!plane || !plane->dev) {
785 SDE_ERROR("invalid arguments\n");
786 return;
787 }
788
789 priv = plane->dev->dev_private;
790 if (!priv || !priv->kms) {
791 SDE_ERROR("invalid KMS reference\n");
792 return;
793 }
794
795 sde_kms = to_sde_kms(priv->kms);
796
797 memset(&qos_params, 0, sizeof(qos_params));
798 qos_params.vbif_idx = VBIF_RT;
799 qos_params.xin_id = cfg->xin_id;
800 qos_params.clk_ctrl = cfg->clk_ctrl;
801 qos_params.num = cfg->num;
802 qos_params.is_rt = true;
803
804 SDE_DEBUG("vbif:%d xin:%d num:%d rt:%d clk_ctrl:%d\n",
805 qos_params.vbif_idx, qos_params.xin_id,
806 qos_params.num, qos_params.is_rt, qos_params.clk_ctrl);
807
808 sde_vbif_set_qos_remap(sde_kms, &qos_params);
809}
810
Clarence Ipcae1bb62016-07-07 12:07:13 -0400811int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400812{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400813 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400814 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400815 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400816 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400817 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800818 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400819
820 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700821 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400822 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400823 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400824 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400825 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400826 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400827 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400828
Clarence Ipcae1bb62016-07-07 12:07:13 -0400829 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800830 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400831 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800832 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400833
Dhaval Patel39323d42017-03-01 23:48:24 -0800834 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400835 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400836 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
837 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400838 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800839 ret = -ETIMEDOUT;
840 break;
841 case -ERESTARTSYS:
842 SDE_ERROR_PLANE(psde,
843 "%ums wait interrupted on %08X\n",
844 wait_ms, prefix);
845 psde->is_error = true;
846 ret = -ERESTARTSYS;
847 break;
848 case -EINVAL:
849 SDE_ERROR_PLANE(psde,
850 "invalid fence param for %08X\n",
851 prefix);
852 psde->is_error = true;
853 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400854 break;
855 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800856 SDE_DEBUG_PLANE(psde, "signaled\n");
857 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400858 break;
859 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700860
861 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400862 } else {
863 ret = 0;
864 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400865 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400866 return ret;
867}
868
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700869/**
870 * _sde_plane_get_aspace: gets the address space based on the
871 * fb_translation mode property
872 */
873static int _sde_plane_get_aspace(
874 struct sde_plane *psde,
875 struct sde_plane_state *pstate,
876 struct msm_gem_address_space **aspace)
877{
878 struct sde_kms *kms;
879 int mode;
880
881 if (!psde || !pstate || !aspace) {
882 SDE_ERROR("invalid parameters\n");
883 return -EINVAL;
884 }
885
886 kms = _sde_plane_get_kms(&psde->base);
887 if (!kms) {
888 SDE_ERROR("invalid kms\n");
889 return -EINVAL;
890 }
891
892 mode = sde_plane_get_property(pstate,
893 PLANE_PROP_FB_TRANSLATION_MODE);
894
895 switch (mode) {
896 case SDE_DRM_FB_NON_SEC:
897 *aspace = kms->aspace[MSM_SMMU_DOMAIN_UNSECURE];
898 if (!aspace)
899 return -EINVAL;
900 break;
901 case SDE_DRM_FB_SEC:
902 *aspace = kms->aspace[MSM_SMMU_DOMAIN_SECURE];
903 if (!aspace)
904 return -EINVAL;
905 break;
906 case SDE_DRM_FB_SEC_DIR_TRANS:
907 case SDE_DRM_FB_NON_SEC_DIR_TRANS:
908 *aspace = NULL;
909 break;
910 default:
911 SDE_ERROR("invalid fb_translation mode:%d\n", mode);
912 return -EFAULT;
913 }
914
915 return 0;
916}
917
Clarence Ip282dad62016-09-27 17:07:35 -0400918static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400919 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400920 struct sde_hw_pipe_cfg *pipe_cfg,
921 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400922{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400923 struct sde_plane *psde;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700924 struct msm_gem_address_space *aspace = NULL;
Clarence Ip282dad62016-09-27 17:07:35 -0400925 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400926
Clarence Ip13a8cf42016-09-29 17:27:47 -0400927 if (!plane || !pstate || !pipe_cfg || !fb) {
928 SDE_ERROR(
929 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
930 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400931 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400932 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400933
934 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400935 if (!psde->pipe_hw) {
936 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400937 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400938 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400939
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700940 ret = _sde_plane_get_aspace(psde, pstate, &aspace);
941 if (ret) {
942 SDE_ERROR_PLANE(psde, "Failed to get aspace %d\n", ret);
943 return;
944 }
945
946 ret = sde_format_populate_layout(aspace, fb, &pipe_cfg->layout);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400947 if (ret == -EAGAIN)
948 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
949 else if (ret)
950 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
Alan Kwongc16e0922017-05-11 14:50:46 -0700951 else if (psde->pipe_hw->ops.setup_sourceaddress) {
952 SDE_EVT32(psde->pipe_hw->idx,
953 pipe_cfg->layout.width,
954 pipe_cfg->layout.height,
955 pipe_cfg->layout.plane_addr[0],
956 pipe_cfg->layout.plane_size[0],
957 pipe_cfg->layout.plane_addr[1],
958 pipe_cfg->layout.plane_size[1],
959 pipe_cfg->layout.plane_addr[2],
960 pipe_cfg->layout.plane_size[2],
961 pipe_cfg->layout.plane_addr[3],
962 pipe_cfg->layout.plane_size[3],
963 pstate->multirect_index);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800964 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
965 pstate->multirect_index);
Alan Kwongc16e0922017-05-11 14:50:46 -0700966 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400967}
968
abeykun48f407a2016-08-25 12:06:44 -0400969static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
970 struct sde_plane_state *pstate)
971{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500972 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400973 int ret = 0;
974
Clarence Ip3bf8d872017-02-16 15:25:38 -0500975 if (!psde || !psde->scaler3_cfg) {
976 SDE_ERROR("invalid args\n");
977 return -EINVAL;
978 } else if (!pstate) {
979 /* pstate is expected to be null on forced color fill */
980 SDE_DEBUG("null pstate\n");
981 return -EINVAL;
982 }
983
984 cfg = psde->scaler3_cfg;
985
abeykun48f407a2016-08-25 12:06:44 -0400986 cfg->dir_lut = msm_property_get_blob(
987 &psde->property_info,
988 pstate->property_blobs, &cfg->dir_len,
989 PLANE_PROP_SCALER_LUT_ED);
990 cfg->cir_lut = msm_property_get_blob(
991 &psde->property_info,
992 pstate->property_blobs, &cfg->cir_len,
993 PLANE_PROP_SCALER_LUT_CIR);
994 cfg->sep_lut = msm_property_get_blob(
995 &psde->property_info,
996 pstate->property_blobs, &cfg->sep_len,
997 PLANE_PROP_SCALER_LUT_SEP);
998 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
999 ret = -ENODATA;
1000 return ret;
1001}
1002
Clarence Ipcb410d42016-06-26 22:52:33 -04001003static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001004 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
1005 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001006 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001007 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
1008{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001009 uint32_t decimated, i;
1010
1011 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
1012 !chroma_subsmpl_v) {
1013 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
1014 , psde, scale_cfg, fmt, chroma_subsmpl_h,
1015 chroma_subsmpl_v);
1016 return;
1017 }
1018
1019 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip716ab662017-03-20 06:51:24 -07001020 memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001021
1022 decimated = DECIMATED_DIMENSION(src_w,
1023 psde->pipe_cfg.horz_decimation);
1024 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
1025 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
1026 decimated = DECIMATED_DIMENSION(src_h,
1027 psde->pipe_cfg.vert_decimation);
1028 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
1029 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
1030
1031
1032 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
1033 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
1034 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
1035 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
1036
1037 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
1038 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
1039 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
1040 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
1041
1042 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
1043 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
1044 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
1045 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
1046
1047 for (i = 0; i < SDE_MAX_PLANES; i++) {
1048 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
1049 psde->pipe_cfg.horz_decimation);
1050 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
1051 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001052 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
1053 scale_cfg->src_width[i] /= chroma_subsmpl_h;
1054 scale_cfg->src_height[i] /= chroma_subsmpl_v;
1055 }
1056 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
1057 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
1058 psde->pixel_ext.num_ext_pxls_top[i] =
1059 scale_cfg->src_height[i];
1060 psde->pixel_ext.num_ext_pxls_left[i] =
1061 scale_cfg->src_width[i];
1062 }
1063 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
1064 && (src_w == dst_w))
1065 return;
1066
1067 scale_cfg->dst_width = dst_w;
1068 scale_cfg->dst_height = dst_h;
1069 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
1070 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
1071 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
1072 scale_cfg->lut_flag = 0;
1073 scale_cfg->blend_cfg = 1;
1074 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001075}
1076
Clarence Ipcb410d42016-06-26 22:52:33 -04001077/**
Clarence Ip13a8cf42016-09-29 17:27:47 -04001078 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -04001079 * @psde: Pointer to SDE plane object
1080 * @src: Source size
1081 * @dst: Destination size
1082 * @phase_steps: Pointer to output array for phase steps
1083 * @filter: Pointer to output array for filter type
1084 * @fmt: Pointer to format definition
1085 * @chroma_subsampling: Subsampling amount for chroma channel
1086 *
1087 * Returns: 0 on success
1088 */
1089static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001090 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001091 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001092 uint32_t chroma_subsampling)
1093{
Clarence Ipcb410d42016-06-26 22:52:33 -04001094 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001095 SDE_ERROR(
1096 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
1097 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001098 return -EINVAL;
1099 }
1100
Clarence Ip4c1d9772016-06-26 09:35:38 -04001101 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -04001102 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001103 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -04001104 phase_steps[SDE_SSPP_COMP_1_2] =
1105 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
1106 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
1107 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001108
1109 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -04001110 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -04001111 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001112 (src <= dst) ? SDE_SCALE_FILTER_BIL :
1113 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001114
Clarence Ipdbde9832016-06-26 09:48:36 -04001115 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001116 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -04001117 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
1118 } else {
1119 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
1120 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001121 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -04001122 }
1123 } else {
1124 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001125 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
1126 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
1127 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001128 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001129 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001130}
1131
Clarence Ipcb410d42016-06-26 22:52:33 -04001132/**
1133 * _sde_plane_setup_pixel_ext - determine default pixel extension values
1134 * @psde: Pointer to SDE plane object
1135 * @src: Source size
1136 * @dst: Destination size
1137 * @decimated_src: Source size after decimation, if any
1138 * @phase_steps: Pointer to output array for phase steps
1139 * @out_src: Output array for pixel extension values
1140 * @out_edge1: Output array for pixel extension first edge
1141 * @out_edge2: Output array for pixel extension second edge
1142 * @filter: Pointer to array for filter type
1143 * @fmt: Pointer to format definition
1144 * @chroma_subsampling: Subsampling amount for chroma channel
1145 * @post_compare: Whether to chroma subsampled source size for comparisions
1146 */
1147static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001148 uint32_t src, uint32_t dst, uint32_t decimated_src,
1149 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -04001150 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001151 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -04001152 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001153{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001154 int64_t edge1, edge2, caf;
1155 uint32_t src_work;
1156 int i, tmp;
1157
Clarence Ipcb410d42016-06-26 22:52:33 -04001158 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -04001159 out_edge2 && filter && fmt) {
1160 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001161 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001162 caf = PHASE_STEP_UNIT_SCALE;
1163 else
1164 caf = 0;
1165
1166 for (i = 0; i < SDE_MAX_PLANES; i++) {
1167 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -04001168 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001169 src_work /= chroma_subsampling;
1170 if (post_compare)
1171 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -04001172 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001173 /* unity */
1174 edge1 = 0;
1175 edge2 = 0;
1176 } else if (dst >= src) {
1177 /* upscale */
1178 edge1 = (1 << PHASE_RESIDUAL);
1179 edge1 -= caf;
1180 edge2 = (1 << PHASE_RESIDUAL);
1181 edge2 += (dst - 1) * *(phase_steps + i);
1182 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1183 edge2 += caf;
1184 edge2 = -(edge2);
1185 } else {
1186 /* downscale */
1187 edge1 = 0;
1188 edge2 = (dst - 1) * *(phase_steps + i);
1189 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1190 edge2 += *(phase_steps + i);
1191 edge2 = -(edge2);
1192 }
1193
1194 /* only enable CAF for luma plane */
1195 caf = 0;
1196
1197 /* populate output arrays */
1198 *(out_src + i) = src_work;
1199
1200 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001201 if (edge1 >= 0) {
1202 tmp = (uint32_t)edge1;
1203 tmp >>= PHASE_STEP_SHIFT;
1204 *(out_edge1 + i) = -tmp;
1205 } else {
1206 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -04001207 *(out_edge1 + i) =
1208 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1209 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001210 }
1211 if (edge2 >= 0) {
1212 tmp = (uint32_t)edge2;
1213 tmp >>= PHASE_STEP_SHIFT;
1214 *(out_edge2 + i) = -tmp;
1215 } else {
1216 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -04001217 *(out_edge2 + i) =
1218 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1219 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001220 }
1221 }
1222 }
1223}
1224
Clarence Ip5fc00c52016-09-23 15:03:34 -04001225static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -04001226{
1227 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
1228 {
Clarence Ip373f8592016-05-26 00:58:42 -04001229 /* S15.16 format */
1230 0x00012A00, 0x00000000, 0x00019880,
1231 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1232 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -04001233 },
Clarence Ip373f8592016-05-26 00:58:42 -04001234 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -04001235 { 0xfff0, 0xff80, 0xff80,},
1236 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001237 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -04001238 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001239 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -04001240 };
abeykun1c312f62016-08-26 09:47:12 -04001241 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
1242 {
1243 /* S15.16 format */
1244 0x00012A00, 0x00000000, 0x00019880,
1245 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1246 0x00012A00, 0x00020480, 0x00000000,
1247 },
1248 /* signed bias */
1249 { 0xffc0, 0xfe00, 0xfe00,},
1250 { 0x0, 0x0, 0x0,},
1251 /* unsigned clamp */
1252 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
1253 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
1254 };
Clarence Ipe78efb72016-06-24 18:35:21 -04001255
Clarence Ip5fc00c52016-09-23 15:03:34 -04001256 if (!psde) {
1257 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001258 return;
1259 }
Clarence Ip5e2a9222016-06-26 22:38:24 -04001260
Clarence Ipcae1bb62016-07-07 12:07:13 -04001261 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001262 if (psde->csc_usr_ptr)
1263 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -04001264 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
1265 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001266 else
Clarence Ip373f8592016-05-26 00:58:42 -04001267 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001268
Clarence Ip13a8cf42016-09-29 17:27:47 -04001269 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -04001270 psde->csc_ptr->csc_mv[0],
1271 psde->csc_ptr->csc_mv[1],
1272 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -04001273}
1274
Benet Clarkeb1b4462016-06-27 14:43:06 -07001275static void sde_color_process_plane_setup(struct drm_plane *plane)
1276{
1277 struct sde_plane *psde;
1278 struct sde_plane_state *pstate;
1279 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001280 struct drm_msm_memcol *memcol = NULL;
1281 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001282
1283 psde = to_sde_plane(plane);
1284 pstate = to_sde_plane_state(plane->state);
1285
1286 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1287 if (psde->pipe_hw->ops.setup_pa_hue)
1288 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1289 saturation = (uint32_t) sde_plane_get_property(pstate,
1290 PLANE_PROP_SATURATION_ADJUST);
1291 if (psde->pipe_hw->ops.setup_pa_sat)
1292 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1293 value = (uint32_t) sde_plane_get_property(pstate,
1294 PLANE_PROP_VALUE_ADJUST);
1295 if (psde->pipe_hw->ops.setup_pa_val)
1296 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1297 contrast = (uint32_t) sde_plane_get_property(pstate,
1298 PLANE_PROP_CONTRAST_ADJUST);
1299 if (psde->pipe_hw->ops.setup_pa_cont)
1300 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001301
Benet Clarkd009b1d2016-06-27 14:45:59 -07001302 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1303 /* Skin memory color setup */
1304 memcol = msm_property_get_blob(&psde->property_info,
1305 pstate->property_blobs,
1306 &memcol_sz,
1307 PLANE_PROP_SKIN_COLOR);
1308 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1309 MEMCOLOR_SKIN, memcol);
1310
1311 /* Sky memory color setup */
1312 memcol = msm_property_get_blob(&psde->property_info,
1313 pstate->property_blobs,
1314 &memcol_sz,
1315 PLANE_PROP_SKY_COLOR);
1316 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1317 MEMCOLOR_SKY, memcol);
1318
1319 /* Foliage memory color setup */
1320 memcol = msm_property_get_blob(&psde->property_info,
1321 pstate->property_blobs,
1322 &memcol_sz,
1323 PLANE_PROP_FOLIAGE_COLOR);
1324 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1325 MEMCOLOR_FOLIAGE, memcol);
1326 }
1327}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001328
Clarence Ipcb410d42016-06-26 22:52:33 -04001329static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001330 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -04001331 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001332{
Clarence Ipb43d4592016-09-08 14:21:35 -04001333 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001334 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001335
Clarence Ipb43d4592016-09-08 14:21:35 -04001336 if (!psde || !fmt) {
1337 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1338 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001339 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001340 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001341
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001342 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001343
Clarence Ipdedbba92016-09-27 17:43:10 -04001344 psde->pipe_cfg.horz_decimation =
1345 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1346 psde->pipe_cfg.vert_decimation =
1347 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001348
1349 /* don't chroma subsample if decimating */
1350 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001351 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001352 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001353 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001354
Clarence Ip5e2a9222016-06-26 22:38:24 -04001355 /* update scaler */
1356 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001357 int error;
1358
1359 error = _sde_plane_setup_scaler3_lut(psde, pstate);
Clarence Ip059c8c32017-06-06 17:15:54 -04001360 if (error || psde->debugfs_default_scale ||
1361 psde->scaler_check_state !=
1362 SDE_PLANE_SCLCHECK_SCALER_V2) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001363 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001364 _sde_plane_setup_scaler3(psde,
1365 psde->pipe_cfg.src_rect.w,
1366 psde->pipe_cfg.src_rect.h,
1367 psde->pipe_cfg.dst_rect.w,
1368 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001369 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001370 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001371 }
Clarence Ip059c8c32017-06-06 17:15:54 -04001372 } else if (psde->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 ||
1373 !pstate || psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001374 uint32_t deci_dim, i;
1375
Clarence Ipb43d4592016-09-08 14:21:35 -04001376 /* calculate default configuration for QSEED2 */
1377 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001378
Clarence Ip13a8cf42016-09-29 17:27:47 -04001379 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001380 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1381 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001382 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001383 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001384 psde->pipe_cfg.dst_rect.w,
1385 pe->phase_step_x,
1386 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001387
Clarence Ipdbde9832016-06-26 09:48:36 -04001388 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001389 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001390 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001391 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001392 pe->phase_step_x,
1393 pe->roi_w,
1394 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001395 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001396 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001397
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001398 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001399 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001400 _sde_plane_setup_scaler2(psde,
1401 deci_dim,
1402 psde->pipe_cfg.dst_rect.h,
1403 pe->phase_step_y,
1404 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001405 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001406 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001407 pe->phase_step_y,
1408 pe->roi_h,
1409 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001410 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001411 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001412
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001413 for (i = 0; i < SDE_MAX_PLANES; i++) {
1414 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001415 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001416 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001417 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001418
1419 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001420 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001421 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001422 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001423
1424 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001425 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001426 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001427 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001428
1429 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001430 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001431 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001432 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001433 }
1434 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001435}
1436
Clarence Ipcae1bb62016-07-07 12:07:13 -04001437/**
1438 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001439 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001440 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1441 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1442 * Returns: 0 on success
1443 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001444static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001445 uint32_t color, uint32_t alpha)
1446{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001447 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001448 const struct drm_plane *plane;
1449 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001450
Clarence Ip13a8cf42016-09-29 17:27:47 -04001451 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001452 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001453 return -EINVAL;
1454 }
1455
Clarence Ipcb410d42016-06-26 22:52:33 -04001456 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001457 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001458 return -EINVAL;
1459 }
1460
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001461 plane = &psde->base;
1462 pstate = to_sde_plane_state(plane->state);
1463
Clarence Ip13a8cf42016-09-29 17:27:47 -04001464 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001465
Clarence Ipcb410d42016-06-26 22:52:33 -04001466 /*
1467 * select fill format to match user property expectation,
1468 * h/w only supports RGB variants
1469 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001470 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001471
1472 /* update sspp */
1473 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1474 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001475 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1476 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001477
1478 /* override scaler/decimation if solid fill */
1479 psde->pipe_cfg.src_rect.x = 0;
1480 psde->pipe_cfg.src_rect.y = 0;
1481 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1482 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Dhaval Patele4b6bb22017-03-27 17:22:21 -07001483 _sde_plane_setup_scaler(psde, fmt, 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001484
Clarence Ipcb410d42016-06-26 22:52:33 -04001485 if (psde->pipe_hw->ops.setup_format)
1486 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001487 fmt, SDE_SSPP_SOLID_FILL,
1488 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001489
1490 if (psde->pipe_hw->ops.setup_rects)
1491 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001492 &psde->pipe_cfg,
1493 pstate->multirect_index);
1494
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001495 if (psde->pipe_hw->ops.setup_pe)
1496 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1497 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001498 }
1499
1500 return 0;
1501}
1502
Alan Kwong4dd64c82017-02-04 18:41:51 -08001503/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001504 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1505 */
1506static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1507{
1508 drm_framebuffer_reference(fb);
1509 return fb;
1510}
1511static void _sde_plane_fb_put(void *fb)
1512{
1513 drm_framebuffer_unreference(fb);
1514}
1515static struct sde_crtc_res_ops fb_res_ops = {
1516 .put = _sde_plane_fb_put,
1517 .get = _sde_plane_fb_get,
1518};
1519
1520/**
1521 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1522 */
1523static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1524{
1525 sde_kms_fbo_reference(fbo);
1526 return fbo;
1527}
1528static void _sde_plane_fbo_put(void *fbo)
1529{
1530 sde_kms_fbo_unreference(fbo);
1531}
1532static struct sde_crtc_res_ops fbo_res_ops = {
1533 .put = _sde_plane_fbo_put,
1534 .get = _sde_plane_fbo_get,
1535};
1536
1537/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001538 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001539 * @plane: Pointer to drm plane
1540 * return: prefill time in line
1541 */
1542static u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
1543{
1544 struct drm_plane_state *state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001545 struct sde_plane_state *pstate;
1546 struct sde_plane_rot_state *rstate;
1547 struct sde_kms *sde_kms;
1548 u32 blocksize = 128;
1549 u32 prefill_line = 0;
1550
Clarence Ip7eb90452017-05-23 11:41:19 -04001551 if (!plane || !plane->state || !plane->state->fb) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001552 SDE_ERROR("invalid parameters\n");
1553 return 0;
1554 }
1555
1556 sde_kms = _sde_plane_get_kms(plane);
1557 state = plane->state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001558 pstate = to_sde_plane_state(state);
1559 rstate = &pstate->rot;
1560
Clarence Ip7eb90452017-05-23 11:41:19 -04001561 if (!sde_kms || !sde_kms->catalog) {
1562 SDE_ERROR("invalid kms\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08001563 return 0;
1564 }
1565
Clarence Ip7eb90452017-05-23 11:41:19 -04001566 if (rstate->out_fb_format)
1567 sde_format_get_block_size(rstate->out_fb_format,
1568 &blocksize, &blocksize);
1569
Alan Kwong4dd64c82017-02-04 18:41:51 -08001570 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
1571
1572 SDE_DEBUG("plane%d prefill:%u\n", plane->base.id, prefill_line);
1573
1574 return prefill_line;
1575}
1576
1577/**
1578 * sde_plane_is_sbuf_mode - check if sspp of given plane is in streaming
1579 * buffer mode
1580 * @plane: Pointer to drm plane
1581 * @prefill: Pointer to prefill line count
1582 * return: true if sspp is in stream buffer mode
1583 */
1584bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill)
1585{
1586 struct sde_plane_state *pstate = plane && plane->state ?
1587 to_sde_plane_state(plane->state) : NULL;
1588 struct sde_plane_rot_state *rstate = pstate ? &pstate->rot : NULL;
1589 bool sbuf_mode = rstate ? rstate->out_sbuf : false;
1590
Clarence Ip7eb90452017-05-23 11:41:19 -04001591 if (prefill)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001592 *prefill = sde_plane_rot_calc_prefill(plane);
1593
1594 return sbuf_mode;
1595}
1596
1597/**
1598 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1599 * enumerating over all planes attached to the same rotator
1600 * @plane: Pointer to drm plane
1601 * @state: Pointer to drm state to be updated
1602 * return: none
1603 */
1604static void sde_plane_rot_calc_cfg(struct drm_plane *plane,
1605 struct drm_plane_state *state)
1606{
1607 struct sde_plane_state *pstate;
1608 struct sde_plane_rot_state *rstate;
1609 struct sde_hw_blk *hw_blk;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001610 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001611 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001612 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001613 u32 dst_x, dst_y, dst_w, dst_h;
1614 int found = 0;
1615 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001616 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001617
1618 if (!plane || !state || !state->state) {
1619 SDE_ERROR("invalid parameters\n");
1620 return;
1621 }
1622
Alan Kwongcdb2f282017-03-18 13:42:06 -07001623 cstate = _sde_plane_get_crtc_state(state);
1624 if (IS_ERR_OR_NULL(cstate)) {
1625 ret = PTR_ERR(cstate);
1626 SDE_ERROR("invalid crtc state %d\n", ret);
1627 return;
1628 }
1629
Alan Kwong4dd64c82017-02-04 18:41:51 -08001630 pstate = to_sde_plane_state(state);
1631 rstate = &pstate->rot;
1632
1633 if (!rstate->rot_hw) {
1634 SDE_ERROR("invalid rotator hw\n");
1635 return;
1636 }
1637
1638 in_rot = &rstate->in_rot_rect;
1639 in_rot->x1 = state->src_x;
1640 in_rot->y1 = state->src_y;
1641 in_rot->x2 = state->src_x + state->src_w;
1642 in_rot->y2 = state->src_y + state->src_h;
1643
1644 out_rot = &rstate->out_rot_rect;
1645 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1646 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1647 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1648 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1649
1650 if (!dst_w && !dst_h) {
1651 rstate->out_rot_rect = rstate->in_rot_rect;
1652 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1653 state->fb->height << 16, rstate->in_rotation);
1654 } else {
1655 out_rot->x1 = dst_x;
1656 out_rot->y1 = dst_y;
1657 out_rot->x2 = dst_x + dst_w;
1658 out_rot->y2 = dst_y + dst_h;
1659 }
1660
1661 rstate->out_src_rect = rstate->out_rot_rect;
1662
1663 hw_blk = &rstate->rot_hw->base;
1664
1665 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001666 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001667 struct drm_plane_state *attached_state;
1668 struct sde_plane_state *attached_pstate;
1669 struct sde_plane_rot_state *attached_rstate;
1670 struct drm_rect attached_out_rect;
1671
Alan Kwong4dd64c82017-02-04 18:41:51 -08001672 attached_state = drm_atomic_get_existing_plane_state(
1673 state->state, attached_plane);
1674
1675 if (!attached_state)
1676 continue;
1677
1678 attached_pstate = to_sde_plane_state(attached_state);
1679 attached_rstate = &attached_pstate->rot;
1680
Clarence Ipd27d9632017-06-14 09:57:26 -04001681 if (attached_state->fb != state->fb)
1682 continue;
1683
1684 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) !=
1685 sde_plane_get_property(attached_pstate,
1686 PLANE_PROP_ROTATION))
Alan Kwongcdb2f282017-03-18 13:42:06 -07001687 continue;
1688
1689 found++;
1690
1691 /* skip itself */
1692 if (attached_plane == plane)
1693 continue;
1694
Alan Kwong4dd64c82017-02-04 18:41:51 -08001695 /* find bounding rotator source roi */
1696 if (attached_state->src_x < in_rot->x1)
1697 in_rot->x1 = attached_state->src_x;
1698
1699 if (attached_state->src_y < in_rot->y1)
1700 in_rot->y1 = attached_state->src_y;
1701
1702 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1703 in_rot->x2 = attached_state->src_x +
1704 attached_state->src_w;
1705
1706 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1707 in_rot->y2 = attached_state->src_y +
1708 attached_state->src_h;
1709
1710 /* find bounding rotator destination roi */
1711 dst_x = sde_plane_get_property(attached_pstate,
1712 PLANE_PROP_ROT_DST_X);
1713 dst_y = sde_plane_get_property(attached_pstate,
1714 PLANE_PROP_ROT_DST_Y);
1715 dst_w = sde_plane_get_property(attached_pstate,
1716 PLANE_PROP_ROT_DST_W);
1717 dst_h = sde_plane_get_property(attached_pstate,
1718 PLANE_PROP_ROT_DST_H);
1719 if (!dst_w && !dst_h) {
1720 attached_out_rect.x1 = attached_state->src_x;
1721 attached_out_rect.y1 = attached_state->src_y;
1722 attached_out_rect.x2 = attached_out_rect.x1 +
1723 attached_state->src_w;
1724 attached_out_rect.y2 = attached_out_rect.y1 +
1725 attached_state->src_h;
1726 drm_rect_rotate(&attached_out_rect,
1727 state->fb->width << 16,
1728 state->fb->height << 16,
1729 rstate->in_rotation);
1730 } else {
1731 attached_out_rect.x1 = dst_x;
1732 attached_out_rect.y1 = dst_y;
1733 attached_out_rect.x2 = dst_x + dst_w;
1734 attached_out_rect.y2 = dst_y + dst_h;
1735 }
1736
1737 /* find relative sspp position */
1738 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1739 xpos++;
1740
1741 if (attached_out_rect.x1 < out_rot->x1)
1742 out_rot->x1 = attached_out_rect.x1;
1743
1744 if (attached_out_rect.y1 < out_rot->y1)
1745 out_rot->y1 = attached_out_rect.y1;
1746
1747 if (attached_out_rect.x2 > out_rot->x2)
1748 out_rot->x2 = attached_out_rect.x2;
1749
1750 if (attached_out_rect.y2 > out_rot->y2)
1751 out_rot->y2 = attached_out_rect.y2;
1752
1753 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1754 attached_plane->base.id,
1755 attached_rstate->sequence_id,
1756 attached_rstate->out_src_rect.x1 >> 16,
1757 attached_state->src_w >> 16,
1758 attached_state->src_h >> 16,
1759 attached_state->src_x >> 16,
1760 attached_state->src_y >> 16,
1761 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1762 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1763 attached_rstate->out_src_rect.x1 >> 16,
1764 attached_rstate->out_src_rect.y1 >> 16);
1765 }
1766
1767 rstate->out_xpos = xpos;
1768 rstate->nplane = found;
1769
1770 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1771 plane->base.id, rstate->sequence_id,
1772 rstate->out_xpos, rstate->nplane,
1773 drm_rect_width(in_rot) >> 16,
1774 drm_rect_height(in_rot) >> 16,
1775 in_rot->x1 >> 16, in_rot->y1 >> 16,
1776 drm_rect_width(&rstate->out_rot_rect) >> 16,
1777 drm_rect_height(&rstate->out_rot_rect) >> 16,
1778 rstate->out_rot_rect.x1 >> 16,
1779 rstate->out_rot_rect.y1 >> 16);
Clarence Ipf27c6f22017-07-10 18:19:44 -04001780 SDE_EVT32_VERBOSE(DRMID(plane), rstate->sequence_id,
1781 rstate->out_xpos, rstate->nplane,
1782 in_rot->x1 >> 16, in_rot->y1 >> 16,
1783 drm_rect_width(in_rot) >> 16,
1784 drm_rect_height(in_rot) >> 16,
1785 rstate->out_rot_rect.x1 >> 16,
1786 rstate->out_rot_rect.y1 >> 16,
1787 drm_rect_width(&rstate->out_rot_rect) >> 16,
1788 drm_rect_height(&rstate->out_rot_rect) >> 16);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001789}
1790
1791/**
1792 * sde_plane_rot_submit_command - commit given state for the rotator stage
1793 * @plane: Pointer to drm plane
1794 * @state: Pointer to the state to be committed
1795 * @hw_cmd: rotator command type
1796 * return: 0 if success; error code otherwise
1797 */
1798static int sde_plane_rot_submit_command(struct drm_plane *plane,
1799 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1800{
1801 struct sde_plane *psde = to_sde_plane(plane);
1802 struct sde_plane_state *pstate = to_sde_plane_state(state);
1803 struct sde_plane_rot_state *rstate = &pstate->rot;
1804 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001805 struct drm_crtc_state *cstate;
1806 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001807 int ret, i;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001808 int fb_mode;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001809
1810 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1811 SDE_ERROR("invalid parameters\n");
1812 return -EINVAL;
1813 }
1814
Alan Kwong4aacd532017-02-04 18:51:33 -08001815 cstate = _sde_plane_get_crtc_state(state);
1816 if (IS_ERR_OR_NULL(cstate)) {
1817 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1818 return -EINVAL;
1819 }
1820 sde_cstate = to_sde_crtc_state(cstate);
1821
Alan Kwong4dd64c82017-02-04 18:41:51 -08001822 rot_cmd = &rstate->rot_cmd;
1823
1824 rot_cmd->master = (rstate->out_xpos == 0);
1825 rot_cmd->sequence_id = rstate->sequence_id;
1826 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1827 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1828 DEFAULT_REFRESH_RATE;
1829 rot_cmd->rot90 = rstate->rot90;
1830 rot_cmd->hflip = rstate->hflip;
1831 rot_cmd->vflip = rstate->vflip;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001832 fb_mode = sde_plane_get_property(pstate,
1833 PLANE_PROP_FB_TRANSLATION_MODE);
1834 if ((fb_mode == SDE_DRM_FB_SEC) ||
1835 (fb_mode == SDE_DRM_FB_SEC_DIR_TRANS))
1836 rot_cmd->secure = true;
1837 else
1838 rot_cmd->secure = false;
1839
Alan Kwong4aacd532017-02-04 18:51:33 -08001840 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1841 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001842 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1843 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001844 rot_cmd->dst_writeback = psde->sbuf_writeback;
1845
1846 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1847 rot_cmd->video_mode = true;
1848 else
1849 rot_cmd->video_mode = false;
1850
1851 rot_cmd->src_pixel_format = state->fb->pixel_format;
1852 rot_cmd->src_modifier = state->fb->modifier[0];
1853 rot_cmd->src_stride = state->fb->pitches[0];
1854
1855 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1856 if (!rot_cmd->src_format) {
1857 SDE_ERROR("failed to get src format\n");
1858 return -EINVAL;
1859 }
1860
1861 rot_cmd->src_width = state->fb->width;
1862 rot_cmd->src_height = state->fb->height;
1863 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1864 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1865 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1866 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
1867 rot_cmd->dst_rect_x = rstate->out_rot_rect.x1 >> 16;
1868 rot_cmd->dst_rect_y = rstate->out_rot_rect.y1 >> 16;
1869 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1870 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1871
1872 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1873 struct sde_hw_fmt_layout layout;
1874
1875 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Clarence Ip299fa602017-07-11 18:01:37 -04001876 sde_format_populate_layout(pstate->aspace, state->fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001877 &layout);
1878 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1879 rot_cmd->src_iova[i] = layout.plane_addr[i];
1880 rot_cmd->src_len[i] = layout.plane_size[i];
1881 }
1882 rot_cmd->src_planes = layout.num_planes;
1883
1884 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Clarence Ip299fa602017-07-11 18:01:37 -04001885 sde_format_populate_layout(pstate->aspace, rstate->out_fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001886 &layout);
1887 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1888 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1889 rot_cmd->dst_len[i] = layout.plane_size[i];
1890 }
1891 rot_cmd->dst_planes = layout.num_planes;
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001892
1893 /* VBIF remapper settings */
Alan Kwong032c2e182017-06-29 16:31:38 -04001894 for (i = 0; i < rstate->rot_hw->caps->xin_count; i++) {
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001895 const struct sde_rot_vbif_cfg *cfg =
1896 &rstate->rot_hw->caps->vbif_cfg[i];
1897
1898 _sde_plane_inline_rot_set_qos_remap(plane, cfg);
1899
1900 if (cfg->is_read) {
1901 _sde_plane_inline_rot_set_ot_limit(plane,
1902 state->crtc, cfg, rot_cmd->src_rect_w,
1903 rot_cmd->src_rect_h);
1904 } else {
1905 _sde_plane_inline_rot_set_ot_limit(plane,
1906 state->crtc, cfg, rot_cmd->dst_rect_w,
1907 rot_cmd->dst_rect_h);
1908 }
1909 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001910 }
1911
1912 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
1913 if (ret) {
1914 SDE_ERROR("failed to commit rotator %d\n", ret);
1915 return ret;
1916 }
1917
1918 rstate->out_rotation = rstate->in_rotation;
1919 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1920 DRM_MODE_FB_MODIFIERS : 0;
1921 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1922 rstate->out_fb_format = rot_cmd->dst_format;
1923 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1924
1925 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1926 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1927
1928 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1929 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1930 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1931 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1932 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1933 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1934
1935 if (rot_cmd->rot90)
1936 rstate->out_rotation &= ~DRM_ROTATE_90;
1937
1938 if (rot_cmd->hflip)
1939 rstate->out_rotation &= ~DRM_REFLECT_X;
1940
1941 if (rot_cmd->vflip)
1942 rstate->out_rotation &= ~DRM_REFLECT_Y;
1943
1944 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07001945 "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 -08001946 plane->base.id, rstate->sequence_id, hw_cmd,
1947 rot_cmd->rot90 ? 'r' : '_',
1948 rot_cmd->hflip ? 'h' : '_',
1949 rot_cmd->vflip ? 'v' : '_',
1950 rot_cmd->video_mode ? 'V' : 'C',
1951 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001952 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001953 state->fb->modifier[0],
1954 drm_rect_width(&rstate->in_rot_rect) >> 16,
1955 drm_rect_height(&rstate->in_rot_rect) >> 16,
1956 rstate->in_rot_rect.x1 >> 16,
1957 rstate->in_rot_rect.y1 >> 16);
1958
Dhaval Patel6c666622017-03-21 23:02:59 -07001959 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 -08001960 plane->base.id, rstate->sequence_id, hw_cmd,
1961 rstate->out_rotation,
1962 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001963 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001964 rstate->out_fb_modifier[0],
1965 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
1966 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
1967
1968 return ret;
1969}
1970
1971/**
Clarence Ipd27d9632017-06-14 09:57:26 -04001972 * _sde_plane_rot_get_fb - attempt to get previously allocated fb/fbo
1973 * If an fb/fbo was already created, either from a previous frame or
1974 * from another plane in the current commit cycle, attempt to reuse
1975 * it for this commit cycle as well.
1976 * @plane: Pointer to drm plane
1977 * @cstate: Pointer to crtc state
1978 * @rstate: Pointer to rotator plane state
1979 */
1980static void _sde_plane_rot_get_fb(struct drm_plane *plane,
1981 struct drm_crtc_state *cstate,
1982 struct sde_plane_rot_state *rstate)
1983{
1984 struct sde_kms_fbo *fbo;
1985 struct drm_framebuffer *fb;
1986
Clarence Ipf27c6f22017-07-10 18:19:44 -04001987 if (!plane || !cstate || !rstate || !rstate->rot_hw)
Clarence Ipd27d9632017-06-14 09:57:26 -04001988 return;
1989
1990 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1991 (u64) &rstate->rot_hw->base);
1992 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1993 (u64) &rstate->rot_hw->base);
1994 if (fb && fbo) {
1995 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
1996 rstate->sequence_id);
1997 } else if (fbo) {
1998 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1999 (u64) &rstate->rot_hw->base);
2000 fbo = NULL;
2001 } else if (fb) {
2002 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2003 (u64) &rstate->rot_hw->base);
2004 fb = NULL;
2005 }
2006
2007 rstate->out_fbo = fbo;
2008 rstate->out_fb = fb;
2009}
2010
2011/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002012 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
2013 * for rotator (pre-sspp) stage
2014 * @plane: Pointer to drm plane
2015 * @new_state: Pointer to new drm plane state
2016 * return: 0 if success; error code otherwise
2017 */
2018static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
2019 struct drm_plane_state *new_state)
2020{
2021 struct drm_framebuffer *fb = new_state->fb;
2022 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
2023 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002024 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002025 int ret;
2026
2027 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
2028 plane->base.id,
2029 new_rstate->sequence_id, fb ? fb->base.id : 0,
2030 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
2031 sde_plane_crtc_enabled(new_state));
2032
2033 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
2034 return 0;
2035
Alan Kwongcdb2f282017-03-18 13:42:06 -07002036 cstate = _sde_plane_get_crtc_state(new_state);
2037 if (IS_ERR(cstate)) {
2038 ret = PTR_ERR(cstate);
2039 SDE_ERROR("invalid crtc state %d\n", ret);
2040 return ret;
2041 }
2042
Alan Kwong4dd64c82017-02-04 18:41:51 -08002043 /* need to re-calc based on all newly validated plane states */
2044 sde_plane_rot_calc_cfg(plane, new_state);
2045
2046 /* check if stream buffer is already attached to rotator */
Clarence Ipd27d9632017-06-14 09:57:26 -04002047 if (sde_plane_enabled(new_state) && !new_rstate->out_fb)
2048 _sde_plane_rot_get_fb(plane, cstate, new_rstate);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002049
Alan Kwong4dd64c82017-02-04 18:41:51 -08002050 /* create new stream buffer if it is not available */
2051 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
2052 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
2053 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
2054
2055 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
2056 new_rstate->sequence_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002057
2058 /* check if out_fb is already attached to rotator */
2059 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
2060 new_rstate->out_fb_pixel_format,
2061 new_rstate->out_fb_modifier,
2062 new_rstate->out_fb_flags);
2063 if (!new_rstate->out_fbo) {
2064 SDE_ERROR("failed to allocate inline buffer object\n");
2065 ret = -EINVAL;
2066 goto error_create_fbo;
2067 }
2068
Alan Kwongcdb2f282017-03-18 13:42:06 -07002069 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2070 (u64) &new_rstate->rot_hw->base,
2071 new_rstate->out_fbo, &fbo_res_ops);
2072 if (ret) {
2073 SDE_ERROR("failed to add crtc resource\n");
2074 goto error_create_fbo_res;
2075 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002076
2077 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
2078 new_rstate->out_fbo);
2079 if (!new_rstate->out_fb) {
2080 SDE_ERROR("failed to create inline framebuffer\n");
2081 ret = -EINVAL;
2082 goto error_create_fb;
2083 }
Clarence Ipf27c6f22017-07-10 18:19:44 -04002084 SDE_EVT32_VERBOSE(DRMID(plane), new_rstate->sequence_id,
2085 new_rstate->out_fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002086
Alan Kwongcdb2f282017-03-18 13:42:06 -07002087 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2088 (u64) &new_rstate->rot_hw->base,
2089 new_rstate->out_fb, &fb_res_ops);
2090 if (ret) {
2091 SDE_ERROR("failed to add crtc resource %d\n", ret);
2092 goto error_create_fb_res;
2093 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002094 }
2095
2096 /* prepare rotator input buffer */
Clarence Ip299fa602017-07-11 18:01:37 -04002097 ret = msm_framebuffer_prepare(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002098 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002099 SDE_ERROR("failed to prepare input framebuffer, %d\n", ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002100 goto error_prepare_input_buffer;
2101 }
2102
2103 /* prepare rotator output buffer */
2104 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
2105 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
2106 new_rstate->sequence_id);
2107
2108 ret = msm_framebuffer_prepare(new_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002109 new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002110 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002111 SDE_ERROR("failed to prepare inline framebuffer, %d\n",
2112 ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002113 goto error_prepare_output_buffer;
2114 }
2115 }
2116
2117 return 0;
2118
2119error_prepare_output_buffer:
Clarence Ip299fa602017-07-11 18:01:37 -04002120 msm_framebuffer_cleanup(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002121error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002122 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2123 (u64) &new_rstate->rot_hw->base);
2124error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002125 new_rstate->out_fb = NULL;
2126error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002127 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2128 (u64) &new_rstate->rot_hw->base);
2129error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002130 new_rstate->out_fbo = NULL;
2131error_create_fbo:
2132 return ret;
2133}
2134
2135/**
2136 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
2137 * rotator (pre-sspp) stage
2138 * @plane: Pointer to drm plane
2139 * @old_state: Pointer to previous drm plane state
2140 * return: none
2141 */
2142static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
2143 struct drm_plane_state *old_state)
2144{
2145 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
2146 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2147 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002148 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002149 int ret;
2150
2151 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2152 old_rstate->sequence_id, old_state->fb->base.id,
2153 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
2154 sde_plane_crtc_enabled(old_state));
2155
2156 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
2157 return;
2158
Alan Kwongcdb2f282017-03-18 13:42:06 -07002159 cstate = _sde_plane_get_crtc_state(old_state);
2160 if (IS_ERR(cstate)) {
2161 ret = PTR_ERR(cstate);
2162 SDE_ERROR("invalid crtc state %d\n", ret);
2163 return;
2164 }
2165
Alan Kwong4dd64c82017-02-04 18:41:51 -08002166 if (sde_plane_crtc_enabled(old_state)) {
2167 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
2168 SDE_HW_ROT_CMD_CLEANUP);
2169 if (ret)
2170 SDE_ERROR("failed to cleanup rotator buffers\n");
2171 }
2172
2173 if (sde_plane_enabled(old_state)) {
2174 if (old_rstate->out_fb) {
2175 msm_framebuffer_cleanup(old_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002176 old_pstate->aspace);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002177 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2178 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002179 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002180 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2181 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002182 old_rstate->out_fbo = NULL;
2183 }
2184
Clarence Ip299fa602017-07-11 18:01:37 -04002185 msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002186 }
2187}
2188
2189/**
2190 * sde_plane_rot_atomic_check - verify rotator update of the given state
2191 * @plane: Pointer to drm plane
2192 * @state: Pointer to drm plane state to be validated
2193 * return: 0 if success; error code otherwise
2194 */
2195static int sde_plane_rot_atomic_check(struct drm_plane *plane,
2196 struct drm_plane_state *state)
2197{
2198 struct sde_plane *psde;
2199 struct sde_plane_state *pstate, *old_pstate;
2200 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002201 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002202 struct sde_hw_blk *hw_blk;
2203 int i, ret = 0;
2204
2205 if (!plane || !state) {
2206 SDE_ERROR("invalid plane/state\n");
2207 return -EINVAL;
2208 }
2209
2210 psde = to_sde_plane(plane);
2211 pstate = to_sde_plane_state(state);
2212 old_pstate = to_sde_plane_state(plane->state);
2213 rstate = &pstate->rot;
2214 old_rstate = &old_pstate->rot;
2215
Alan Kwongcdb2f282017-03-18 13:42:06 -07002216 /* cstate will be null if crtc is disconnected from plane */
2217 cstate = _sde_plane_get_crtc_state(state);
2218 if (IS_ERR(cstate)) {
2219 ret = PTR_ERR(cstate);
2220 SDE_ERROR("invalid crtc state %d\n", ret);
2221 return ret;
2222 }
2223
Alan Kwong4dd64c82017-02-04 18:41:51 -08002224 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2225 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
2226 !!rstate->out_sbuf, !!rstate->rot_hw,
2227 sde_plane_crtc_enabled(state));
2228
2229 rstate->in_rotation = drm_rotation_simplify(
2230 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07002231 DRM_ROTATE_0 | DRM_ROTATE_90 |
2232 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002233 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
2234 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
2235 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
2236 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
2237
Alan Kwongcdb2f282017-03-18 13:42:06 -07002238 if (sde_plane_enabled(state) && rstate->out_sbuf) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002239 SDE_DEBUG("plane%d.%d acquire rotator, fb %d\n",
2240 plane->base.id, rstate->sequence_id,
2241 state->fb ? state->fb->base.id : -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002242
Alan Kwongcdb2f282017-03-18 13:42:06 -07002243 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
2244 (u64) state->fb);
2245 if (!hw_blk) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002246 SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
2247 plane->base.id, rstate->sequence_id,
2248 state->fb ? state->fb->base.id : -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002249 return -EINVAL;
2250 }
2251
Alan Kwongcdb2f282017-03-18 13:42:06 -07002252 rstate->rot_hw = to_sde_hw_rot(hw_blk);
2253
Alan Kwong4dd64c82017-02-04 18:41:51 -08002254 if (!rstate->rot_hw->ops.commit) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002255 SDE_ERROR("plane%d.%d invalid rotator ops\n",
2256 plane->base.id, rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002257 sde_crtc_res_put(cstate,
2258 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002259 rstate->rot_hw = NULL;
2260 return -EINVAL;
2261 }
2262
2263 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002264 } else {
2265 rstate->in_fb = NULL;
2266 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002267 }
2268
2269 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002270 uint32_t fb_id;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002271
Clarence Ipf27c6f22017-07-10 18:19:44 -04002272 fb_id = state->fb ? state->fb->base.id : -1;
2273 SDE_DEBUG("plane%d.%d use rotator, fb %d\n",
2274 plane->base.id, rstate->sequence_id, fb_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002275
2276 sde_plane_rot_calc_cfg(plane, state);
2277
2278 ret = sde_plane_rot_submit_command(plane, state,
2279 SDE_HW_ROT_CMD_VALIDATE);
Clarence Ipf27c6f22017-07-10 18:19:44 -04002280 if (ret)
2281 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002282
Clarence Ipf27c6f22017-07-10 18:19:44 -04002283 /* check if stream buffer is already attached to rotator */
2284 _sde_plane_rot_get_fb(plane, cstate, rstate);
2285
2286 /* release buffer if output format configuration changes */
2287 if (rstate->out_fb &&
2288 ((rstate->out_fb_height != rstate->out_fb->height) ||
2289 (rstate->out_fb_width != rstate->out_fb->width) ||
2290 (rstate->out_fb_pixel_format !=
2291 rstate->out_fb->pixel_format) ||
2292 (rstate->out_fb_modifier[0] !=
2293 rstate->out_fb->modifier[0]) ||
2294 (rstate->out_fb_flags != rstate->out_fb->flags))) {
2295
2296 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
2297 rstate->sequence_id);
2298 SDE_EVT32_VERBOSE(DRMID(plane),
2299 rstate->sequence_id, fb_id);
2300
2301 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2302 (u64) &rstate->rot_hw->base);
2303 rstate->out_fb = NULL;
2304 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2305 (u64) &rstate->rot_hw->base);
2306 rstate->out_fbo = NULL;
2307 }
Clarence Ip4475d582017-04-18 11:36:00 -04002308 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002309
2310 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
2311 rstate->sequence_id);
2312
2313 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04002314 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
2315 rstate->out_fb_modifier[i] = state->fb ?
2316 state->fb->modifier[i] : 0x0;
2317
2318 if (state->fb) {
2319 rstate->out_fb_pixel_format = state->fb->pixel_format;
2320 rstate->out_fb_flags = state->fb->flags;
2321 rstate->out_fb_width = state->fb->width;
2322 rstate->out_fb_height = state->fb->height;
2323 } else {
2324 rstate->out_fb_pixel_format = 0x0;
2325 rstate->out_fb_flags = 0x0;
2326 rstate->out_fb_width = 0;
2327 rstate->out_fb_height = 0;
2328 }
2329
Alan Kwong4dd64c82017-02-04 18:41:51 -08002330 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002331 rstate->out_src_x = state->src_x;
2332 rstate->out_src_y = state->src_y;
2333 rstate->out_src_w = state->src_w;
2334 rstate->out_src_h = state->src_h;
2335
2336 rstate->out_fb_format = NULL;
2337 rstate->out_sbuf = false;
2338 rstate->out_fb = state->fb;
2339 }
2340
2341 return ret;
2342}
2343
2344/**
2345 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2346 * @plane: Pointer to drm plane
2347 * @old_state: Pointer to previous state
2348 * return: none
2349 */
2350static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2351 struct drm_plane_state *old_state)
2352{
2353 struct drm_plane_state *state;
2354 struct sde_plane_state *pstate;
2355 struct sde_plane_rot_state *rstate;
2356
2357 if (!plane || !plane->state) {
2358 SDE_ERROR("invalid plane/state\n");
2359 return;
2360 }
2361
2362 state = plane->state;
2363 pstate = to_sde_plane_state(state);
2364 rstate = &pstate->rot;
2365
2366 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2367 rstate->sequence_id,
2368 !!rstate->out_sbuf, !!rstate->rot_hw,
2369 sde_plane_crtc_enabled(plane->state));
2370
2371 if (!sde_plane_crtc_enabled(state))
2372 return;
2373
2374 if (!rstate->out_sbuf || !rstate->rot_hw)
2375 return;
2376
2377 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
2378}
2379
2380/**
Clarence Ipddbf7752017-05-21 18:07:30 -04002381 * sde_plane_rot_flush - perform final flush related rotator options
2382 * @plane: Pointer to drm plane
2383 * @pstate: Pointer to sde plane state
2384 */
2385static void sde_plane_rot_flush(struct drm_plane *plane,
2386 struct sde_plane_state *pstate)
2387{
2388 if (!plane || !pstate || !pstate->rot.rot_hw ||
2389 !pstate->rot.rot_hw->ops.commit)
2390 return;
2391
2392 pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
2393 &pstate->rot.rot_cmd,
2394 SDE_HW_ROT_CMD_START);
2395}
2396
2397/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002398 * sde_plane_rot_destroy_state - destroy state for rotator stage
2399 * @plane: Pointer to drm plane
2400 * @state: Pointer to state to be destroyed
2401 * return: none
2402 */
2403static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2404 struct drm_plane_state *state)
2405{
2406 struct sde_plane_state *pstate = to_sde_plane_state(state);
2407 struct sde_plane_rot_state *rstate = &pstate->rot;
2408
2409 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2410 rstate->sequence_id,
2411 !!rstate->out_sbuf, !!rstate->rot_hw,
2412 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002413}
2414
2415/**
2416 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2417 * @plane: Pointer to drm plane
2418 * @new_state: Pointer to duplicated state
2419 * return: 0 if success; error code otherwise
2420 */
2421static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2422 struct drm_plane_state *new_state)
2423{
2424 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2425 struct sde_plane_rot_state *rstate = &pstate->rot;
2426
2427 rstate->sequence_id++;
2428
2429 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2430 rstate->sequence_id,
2431 !!rstate->out_sbuf, !!rstate->rot_hw);
2432
Clarence Ipf27c6f22017-07-10 18:19:44 -04002433 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002434 rstate->out_fb = NULL;
2435 rstate->out_fbo = NULL;
2436
2437 return 0;
2438}
2439
2440/**
2441 * sde_plane_rot_install_caps - install plane rotator capabilities
2442 * @plane: Pointer to drm plane
2443 * return: none
2444 */
2445static void sde_plane_rot_install_caps(struct drm_plane *plane)
2446{
2447 struct sde_plane *psde = to_sde_plane(plane);
2448 const struct sde_format_extended *format_list;
2449 struct sde_kms_info *info;
2450 struct sde_hw_rot *rot_hw;
2451 const char *downscale_caps;
2452
2453 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2454 !psde->catalog->rot_count)
2455 return;
2456
2457 if (psde->blob_rot_caps)
2458 return;
2459
2460 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2461 if (!info)
2462 return;
2463
2464 rot_hw = sde_hw_rot_get(NULL);
2465 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2466 !rot_hw->ops.get_downscale_caps) {
2467 SDE_ERROR("invalid rotator hw\n");
2468 goto error_rot;
2469 }
2470
2471 sde_kms_info_reset(info);
2472
2473 format_list = rot_hw->ops.get_format_caps(rot_hw);
2474 if (format_list) {
2475 sde_kms_info_start(info, "pixel_formats");
2476 while (format_list->fourcc_format) {
2477 sde_kms_info_append_format(info,
2478 format_list->fourcc_format,
2479 format_list->modifier);
2480 ++format_list;
2481 }
2482 sde_kms_info_stop(info);
2483 }
2484
2485 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2486 if (downscale_caps) {
2487 sde_kms_info_start(info, "downscale_ratios");
2488 sde_kms_info_append(info, downscale_caps);
2489 sde_kms_info_stop(info);
2490 }
2491
2492 if (rot_hw->ops.get_cache_size)
2493 sde_kms_info_add_keyint(info, "cache_size",
2494 rot_hw->ops.get_cache_size(rot_hw));
2495
Alan Kwong1a915802017-03-31 12:55:46 -07002496 if (rot_hw->ops.get_maxlinewidth)
2497 sde_kms_info_add_keyint(info, "max_linewidth",
2498 rot_hw->ops.get_maxlinewidth(rot_hw));
2499
Alan Kwong4dd64c82017-02-04 18:41:51 -08002500 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
Narendra Muppalla22d17252017-05-31 15:13:39 -07002501 info->data, SDE_KMS_INFO_DATALEN(info),
2502 PLANE_PROP_ROT_CAPS_V1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002503
2504 sde_hw_rot_put(rot_hw);
2505error_rot:
2506 kfree(info);
2507}
2508
2509/**
2510 * sde_plane_rot_install_properties - install plane rotator properties
2511 * @plane: Pointer to drm plane
2512 * @catalog: Pointer to mdss configuration
2513 * return: none
2514 */
2515static void sde_plane_rot_install_properties(struct drm_plane *plane,
2516 struct sde_mdss_cfg *catalog)
2517{
2518 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002519 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2520 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002521
2522 if (!plane || !psde) {
2523 SDE_ERROR("invalid plane\n");
2524 return;
2525 } else if (!catalog) {
2526 SDE_ERROR("invalid catalog\n");
2527 return;
2528 }
2529
2530 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2531 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2532 DRM_ROTATE_180 | DRM_ROTATE_270;
2533
2534 msm_property_install_rotation(&psde->property_info,
2535 supported_rotations, PLANE_PROP_ROTATION);
2536
2537 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2538 return;
2539
2540 msm_property_install_range(&psde->property_info, "rot_dst_x",
2541 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2542 msm_property_install_range(&psde->property_info, "rot_dst_y",
2543 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2544 msm_property_install_range(&psde->property_info, "rot_dst_w",
2545 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2546 msm_property_install_range(&psde->property_info, "rot_dst_h",
2547 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2548 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2549 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2550}
2551
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002552void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002553{
Clarence Ipcb410d42016-06-26 22:52:33 -04002554 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002555
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002556 if (!drm_state)
2557 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002558
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002559 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002560
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002561 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2562 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002563}
2564
2565int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2566{
2567 struct sde_plane_state *pstate[R_MAX];
2568 const struct drm_plane_state *drm_state[R_MAX];
2569 struct sde_rect src[R_MAX], dst[R_MAX];
2570 struct sde_plane *sde_plane[R_MAX];
2571 const struct sde_format *fmt[R_MAX];
2572 bool q16_data = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002573 int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
2574 bool parallel_fetch_qualified = true;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002575
2576 for (i = 0; i < R_MAX; i++) {
2577 const struct msm_format *msm_fmt;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002578 int width_threshold;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002579
2580 drm_state[i] = i ? plane->r1 : plane->r0;
2581 pstate[i] = to_sde_plane_state(drm_state[i]);
2582 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2583
2584 if (pstate[i] == NULL) {
2585 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2586 drm_state[i]->plane->base.id);
2587 return -EINVAL;
2588 }
2589
2590 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2591 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2592 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2593 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2594 drm_state[i]->crtc_h, !q16_data);
2595
2596 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2597 SDE_ERROR_PLANE(sde_plane[i],
2598 "scaling is not supported in multirect mode\n");
2599 return -EINVAL;
2600 }
2601
2602 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2603 fmt[i] = to_sde_format(msm_fmt);
2604 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2605 SDE_ERROR_PLANE(sde_plane[i],
2606 "Unsupported format for multirect mode\n");
2607 return -EINVAL;
2608 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002609
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002610 /**
2611 * SSPP PD_MEM is split half - one for each RECT.
2612 * Tiled formats need 5 lines of buffering while fetching
2613 * whereas linear formats need only 2 lines.
2614 * So we cannot support more than half of the supported SSPP
2615 * width for tiled formats.
2616 */
2617 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
2618 if (SDE_FORMAT_IS_UBWC(fmt[i]))
2619 width_threshold /= 2;
2620
2621 if (parallel_fetch_qualified && src[i].w > width_threshold)
2622 parallel_fetch_qualified = false;
2623
2624 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002625
2626 /* Validate RECT's and set the mode */
2627
2628 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002629 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002630 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2631 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002632
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002633 goto done;
2634 }
2635
2636 /* TIME_MX Mode */
2637 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
2638 buffer_lines = 2 * fmt[R0]->tile_height;
2639
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002640 if ((dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) ||
2641 (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines)) {
2642 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2643 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002644 } else {
2645 SDE_ERROR(
2646 "No multirect mode possible for the planes (%d - %d)\n",
2647 drm_state[R0]->plane->base.id,
2648 drm_state[R1]->plane->base.id);
2649 return -EINVAL;
2650 }
2651
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002652done:
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002653 if (sde_plane[R0]->is_virtual) {
2654 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2655 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2656 } else {
2657 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2658 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2659 };
2660
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002661 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2662 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2663 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2664 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002665 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002666}
2667
Alan Kwong4dd64c82017-02-04 18:41:51 -08002668/**
2669 * sde_plane_get_ctl_flush - get control flush for the given plane
2670 * @plane: Pointer to drm plane structure
2671 * @ctl: Pointer to hardware control driver
Clarence Ip7e5f0002017-05-29 18:46:56 -04002672 * @flush_sspp: Pointer to sspp flush control word
2673 * @flush_rot: Pointer to rotator flush control word
Alan Kwong4dd64c82017-02-04 18:41:51 -08002674 */
2675void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
Clarence Ip7e5f0002017-05-29 18:46:56 -04002676 u32 *flush_sspp, u32 *flush_rot)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002677{
2678 struct sde_plane_state *pstate;
2679 struct sde_plane_rot_state *rstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002680
Clarence Ip7e5f0002017-05-29 18:46:56 -04002681 if (!plane || !flush_sspp) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002682 SDE_ERROR("invalid parameters\n");
2683 return;
2684 }
2685
2686 pstate = to_sde_plane_state(plane->state);
2687 rstate = &pstate->rot;
2688
Clarence Ip7e5f0002017-05-29 18:46:56 -04002689 *flush_sspp = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002690
Clarence Ip7e5f0002017-05-29 18:46:56 -04002691 if (!flush_rot)
2692 return;
2693
2694 *flush_rot = 0x0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002695 if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
2696 ctl->ops.get_bitmask_rot)
Clarence Ip7e5f0002017-05-29 18:46:56 -04002697 ctl->ops.get_bitmask_rot(ctl, flush_rot, rstate->rot_hw->idx);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002698}
2699
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002700static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002701 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002702{
2703 struct drm_framebuffer *fb = new_state->fb;
2704 struct sde_plane *psde = to_sde_plane(plane);
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002705 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002706 struct sde_plane_rot_state *new_rstate;
Alan Kwong4a5bd782017-06-09 15:20:52 -04002707 struct sde_hw_fmt_layout layout;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002708 struct msm_gem_address_space *aspace;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002709 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002710
2711 if (!new_state->fb)
2712 return 0;
2713
Clarence Ip13a8cf42016-09-29 17:27:47 -04002714 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002715
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002716 ret = _sde_plane_get_aspace(psde, pstate, &aspace);
2717 if (ret) {
2718 SDE_ERROR_PLANE(psde, "Failed to get aspace\n");
2719 return ret;
2720 }
2721
2722 /*cache aspace */
2723 pstate->aspace = aspace;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002724 ret = sde_plane_rot_prepare_fb(plane, new_state);
2725 if (ret) {
2726 SDE_ERROR("failed to prepare rot framebuffer\n");
2727 return ret;
2728 }
2729
2730 new_rstate = &to_sde_plane_state(new_state)->rot;
2731
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002732 ret = msm_framebuffer_prepare(new_rstate->out_fb, pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002733 if (ret) {
2734 SDE_ERROR("failed to prepare framebuffer\n");
2735 return ret;
2736 }
2737
Alan Kwong4a5bd782017-06-09 15:20:52 -04002738 /* validate framebuffer layout before commit */
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002739 ret = sde_format_populate_layout(pstate->aspace,
Alan Kwong4a5bd782017-06-09 15:20:52 -04002740 new_rstate->out_fb, &layout);
2741 if (ret) {
2742 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
2743 return ret;
2744 }
2745
Alan Kwong4dd64c82017-02-04 18:41:51 -08002746 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002747}
2748
2749static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002750 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002751{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002752 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ip299fa602017-07-11 18:01:37 -04002753 struct sde_plane_state *old_pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002754 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002755
Clarence Ip299fa602017-07-11 18:01:37 -04002756 if (!old_state || !old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002757 return;
2758
Clarence Ip299fa602017-07-11 18:01:37 -04002759 old_pstate = to_sde_plane_state(old_state);
2760
Alan Kwong4dd64c82017-02-04 18:41:51 -08002761 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2762
Clarence Ip299fa602017-07-11 18:01:37 -04002763 old_rstate = &old_pstate->rot;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002764
Clarence Ip299fa602017-07-11 18:01:37 -04002765 msm_framebuffer_cleanup(old_rstate->out_fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002766
2767 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002768}
2769
Alan Kwong4dd64c82017-02-04 18:41:51 -08002770static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002771 struct drm_plane_state *state,
2772 struct drm_plane_state *old_state)
2773{
2774 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002775 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002776 struct sde_plane_rot_state *rstate = &pstate->rot;
2777 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2778 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002779
Dhaval Patel47302cf2016-08-18 15:04:28 -07002780 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002781 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002782 return;
2783
Clarence Ip282dad62016-09-27 17:07:35 -04002784 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2785 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002786 SDE_DEBUG_PLANE(psde,
2787 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002788 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002789 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002790 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002791 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002792 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2793 pstate->multirect_mode != old_pstate->multirect_mode) {
2794 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2795 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002796 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2797 rstate->out_src_h != old_rstate->out_src_h ||
2798 rstate->out_src_x != old_rstate->out_src_x ||
2799 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002800 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002801 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002802 } else if (state->crtc_w != old_state->crtc_w ||
2803 state->crtc_h != old_state->crtc_h ||
2804 state->crtc_x != old_state->crtc_x ||
2805 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002806 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002807 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002808 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2809 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2810 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2811 pstate->excl_rect.y != old_pstate->excl_rect.y) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07002812 SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002813 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002814 }
2815
Alan Kwong4dd64c82017-02-04 18:41:51 -08002816 fb = rstate->out_fb;
2817 old_fb = old_rstate->out_fb;
2818
2819 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002820 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002821 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002822 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002823 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002824 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002825 uint64_t *new_mods = fb->modifier;
2826 uint64_t *old_mods = old_fb->modifier;
2827 uint32_t *new_pitches = fb->pitches;
2828 uint32_t *old_pitches = old_fb->pitches;
2829 uint32_t *new_offset = fb->offsets;
2830 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002831 int i;
2832
Alan Kwong4dd64c82017-02-04 18:41:51 -08002833 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002834 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002835 SDE_DEBUG_PLANE(psde,
2836 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002837 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002838 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002839 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2840 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002841 break;
2842 }
2843 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002844 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002845 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002846 SDE_DEBUG_PLANE(psde,
2847 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002848 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002849 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002850 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002851 break;
2852 }
2853 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002854 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002855 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002856 SDE_DEBUG_PLANE(psde,
2857 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002858 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002859 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002860 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2861 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002862 break;
2863 }
2864 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002865 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002866}
2867
Clarence Ip059c8c32017-06-06 17:15:54 -04002868static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
2869 const struct sde_format *fmt,
2870 uint32_t img_w, uint32_t img_h,
2871 uint32_t src_w, uint32_t src_h,
2872 uint32_t deci_w, uint32_t deci_h)
2873{
2874 int i;
2875
2876 if (!psde || !fmt) {
2877 SDE_ERROR_PLANE(psde, "invalid arguments\n");
2878 return -EINVAL;
2879 }
2880
2881 /* don't run checks unless scaler data was changed */
2882 if (psde->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK ||
2883 !psde->scaler3_cfg)
2884 return 0;
2885
2886 psde->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
2887
2888 for (i = 0; i < SDE_MAX_PLANES; i++) {
2889 uint32_t hor_req_pixels, hor_fetch_pixels;
2890 uint32_t vert_req_pixels, vert_fetch_pixels;
2891 uint32_t src_w_tmp, src_h_tmp;
2892
2893 /* re-use color plane 1's config for plane 2 */
2894 if (i == 2)
2895 continue;
2896
2897 src_w_tmp = src_w;
2898 src_h_tmp = src_h;
2899
2900 /*
2901 * For chroma plane, width is half for the following sub sampled
2902 * formats. Except in case of decimation, where hardware avoids
2903 * 1 line of decimation instead of downsampling.
2904 */
2905 if (i == 1) {
2906 if (!deci_w &&
2907 (fmt->chroma_sample == SDE_CHROMA_420 ||
2908 fmt->chroma_sample == SDE_CHROMA_H2V1))
2909 src_w_tmp >>= 1;
2910 if (!deci_h &&
2911 (fmt->chroma_sample == SDE_CHROMA_420 ||
2912 fmt->chroma_sample == SDE_CHROMA_H1V2))
2913 src_h_tmp >>= 1;
2914 }
2915
2916 hor_req_pixels = psde->pixel_ext.roi_w[i];
2917 vert_req_pixels = psde->pixel_ext.roi_h[i];
2918
2919 hor_fetch_pixels = DECIMATED_DIMENSION(src_w_tmp +
2920 (int8_t)(psde->pixel_ext.left_ftch[i] & 0xFF) +
2921 (int8_t)(psde->pixel_ext.right_ftch[i] & 0xFF),
2922 deci_w);
2923 vert_fetch_pixels = DECIMATED_DIMENSION(src_h_tmp +
2924 (int8_t)(psde->pixel_ext.top_ftch[i] & 0xFF) +
2925 (int8_t)(psde->pixel_ext.btm_ftch[i] & 0xFF),
2926 deci_h);
2927
2928 if ((hor_req_pixels != hor_fetch_pixels) ||
2929 (hor_fetch_pixels > img_w) ||
2930 (vert_req_pixels != vert_fetch_pixels) ||
2931 (vert_fetch_pixels > img_h)) {
2932 SDE_ERROR_PLANE(psde,
2933 "req %d/%d, fetch %d/%d, src %dx%d\n",
2934 hor_req_pixels, vert_req_pixels,
2935 hor_fetch_pixels, vert_fetch_pixels,
Clarence Ip3b1e2c62017-06-14 11:20:44 -04002936 img_w, img_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04002937 return -EINVAL;
2938 }
2939
2940 /*
2941 * Alpha plane can only be scaled using bilinear or pixel
2942 * repeat/drop, src_width and src_height are only specified
2943 * for Y and UV plane
2944 */
2945 if (i != 3 &&
2946 (hor_req_pixels != psde->scaler3_cfg->src_width[i] ||
2947 vert_req_pixels != psde->scaler3_cfg->src_height[i])) {
2948 SDE_ERROR_PLANE(psde,
2949 "roi[%d] %d/%d, scaler src %dx%d, src %dx%d\n",
2950 i, psde->pixel_ext.roi_w[i],
2951 psde->pixel_ext.roi_h[i],
2952 psde->scaler3_cfg->src_width[i],
2953 psde->scaler3_cfg->src_height[i],
2954 src_w, src_h);
2955 return -EINVAL;
2956 }
2957 }
2958
2959 psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
2960 return 0;
2961}
2962
Alan Kwong4dd64c82017-02-04 18:41:51 -08002963static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002964 struct drm_plane_state *state)
2965{
Clarence Ipdedbba92016-09-27 17:43:10 -04002966 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04002967 struct sde_plane *psde;
2968 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002969 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002970 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002971 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04002972 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002973 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
2974 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04002975
2976 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002977 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2978 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04002979 ret = -EINVAL;
2980 goto exit;
2981 }
2982
2983 psde = to_sde_plane(plane);
2984 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002985 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04002986
2987 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002988 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002989 ret = -EINVAL;
2990 goto exit;
2991 }
2992
Clarence Ipdedbba92016-09-27 17:43:10 -04002993 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
2994 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04002995
2996 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002997 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2998 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002999 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
3000 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04003001
Dhaval Patel47302cf2016-08-18 15:04:28 -07003002 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
3003 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04003004
Dhaval Patel47302cf2016-08-18 15:04:28 -07003005 max_upscale = psde->pipe_sblk->maxupscale;
3006 max_downscale = psde->pipe_sblk->maxdwnscale;
3007 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04003008
Clarence Ip13a8cf42016-09-29 17:27:47 -04003009 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003010 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003011
Dhaval Patel47302cf2016-08-18 15:04:28 -07003012 if (!sde_plane_enabled(state))
3013 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04003014
Alan Kwong4dd64c82017-02-04 18:41:51 -08003015 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07003016 "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 -08003017 plane->base.id, rstate->sequence_id,
3018 rstate->out_rotation,
3019 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07003020 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08003021 rstate->out_fb_modifier[0],
3022 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3023 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3024 state->crtc_w, state->crtc_h,
3025 state->crtc_x, state->crtc_y);
3026
Dhaval Patel47302cf2016-08-18 15:04:28 -07003027 fmt = to_sde_format(msm_framebuffer_format(state->fb));
3028
3029 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
3030
3031 if (SDE_FORMAT_IS_YUV(fmt) &&
3032 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04003033 !(psde->features & (BIT(SDE_SSPP_CSC)
3034 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003035 SDE_ERROR_PLANE(psde,
3036 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07003037 ret = -EINVAL;
3038
3039 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08003040 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
3041 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07003042 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08003043 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
3044 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003045 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003046 src.x, src.y, src.w, src.h);
3047 ret = -E2BIG;
3048
3049 /* valid yuv image */
3050 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
3051 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003052 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003053 src.x, src.y, src.w, src.h);
3054 ret = -EINVAL;
3055
3056 /* min dst support */
3057 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003058 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003059 dst.x, dst.y, dst.w, dst.h);
3060 ret = -EINVAL;
3061
3062 /* decimation validation */
3063 } else if (deci_w || deci_h) {
3064 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
3065 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003066 SDE_ERROR_PLANE(psde,
3067 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003068 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003069 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003070 SDE_ERROR_PLANE(psde,
3071 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003072 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003073 }
3074
Dhaval Patel47302cf2016-08-18 15:04:28 -07003075 } else if (!(psde->features & SDE_SSPP_SCALER) &&
3076 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003077 SDE_ERROR_PLANE(psde,
3078 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003079 src.w, src.h, dst.w, dst.h);
3080 ret = -EINVAL;
3081
3082 /* check decimated source width */
3083 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003084 SDE_ERROR_PLANE(psde,
3085 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003086 src.w, src_deci_w, max_linewidth);
3087 ret = -E2BIG;
3088
3089 /* check max scaler capability */
3090 } else if (((src_deci_w * max_upscale) < dst.w) ||
3091 ((src_deci_h * max_upscale) < dst.h) ||
3092 ((dst.w * max_downscale) < src_deci_w) ||
3093 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003094 SDE_ERROR_PLANE(psde,
3095 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003096 src_deci_w, src_deci_h, dst.w, dst.h);
3097 ret = -E2BIG;
Clarence Ip059c8c32017-06-06 17:15:54 -04003098 } else if (_sde_plane_validate_scaler_v2(psde, fmt,
3099 rstate->out_fb_width,
3100 rstate->out_fb_height,
3101 src.w, src.h, deci_w, deci_h)) {
3102 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003103 }
3104
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003105 /* check excl rect configs */
Clarence Ip059c8c32017-06-06 17:15:54 -04003106 if (!ret && pstate->excl_rect.w && pstate->excl_rect.h) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003107 struct sde_rect intersect;
3108
3109 /*
3110 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003111 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003112 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05003113 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003114 if (intersect.w != pstate->excl_rect.w ||
3115 intersect.h != pstate->excl_rect.h ||
3116 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003117 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07003118 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003119 pstate->excl_rect.x, pstate->excl_rect.y,
3120 pstate->excl_rect.w, pstate->excl_rect.h,
3121 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07003122 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003123 ret = -EINVAL;
3124 }
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003125 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3126 pstate->excl_rect.x, pstate->excl_rect.y,
3127 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003128 }
3129
Dhaval Patel47302cf2016-08-18 15:04:28 -07003130modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003131 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08003132 _sde_plane_sspp_atomic_check_mode_changed(psde,
3133 state, plane->state);
3134exit:
3135 return ret;
3136}
3137
3138static int sde_plane_atomic_check(struct drm_plane *plane,
3139 struct drm_plane_state *state)
3140{
3141 int ret = 0;
3142 struct sde_plane *psde;
3143 struct sde_plane_state *pstate;
3144
3145 if (!plane || !state) {
3146 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3147 plane != 0, state != 0);
3148 ret = -EINVAL;
3149 goto exit;
3150 }
3151
3152 psde = to_sde_plane(plane);
3153 pstate = to_sde_plane_state(state);
3154
3155 SDE_DEBUG_PLANE(psde, "\n");
3156
3157 ret = sde_plane_rot_atomic_check(plane, state);
3158 if (ret)
3159 goto exit;
3160
3161 ret = sde_plane_sspp_atomic_check(plane, state);
3162
Clarence Ipdbde9832016-06-26 09:48:36 -04003163exit:
3164 return ret;
3165}
3166
Clarence Ipcae1bb62016-07-07 12:07:13 -04003167/**
3168 * sde_plane_flush - final plane operations before commit flush
3169 * @plane: Pointer to drm plane structure
3170 */
3171void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04003172{
Clarence Ipcae1bb62016-07-07 12:07:13 -04003173 struct sde_plane *psde;
Clarence Ipddbf7752017-05-21 18:07:30 -04003174 struct sde_plane_state *pstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -04003175
Clarence Ipddbf7752017-05-21 18:07:30 -04003176 if (!plane || !plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003177 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04003178 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003179 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04003180
3181 psde = to_sde_plane(plane);
Clarence Ipddbf7752017-05-21 18:07:30 -04003182 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003183
3184 /*
3185 * These updates have to be done immediately before the plane flush
3186 * timing, and may not be moved to the atomic_update/mode_set functions.
3187 */
3188 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05003189 /* force white frame with 100% alpha pipe output on error */
3190 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003191 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
3192 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04003193 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003194 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
3195 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
3196
Clarence Ip56902792017-03-17 15:22:07 -04003197 /* force black color fill during suspend */
3198 if (msm_is_suspend_state(plane->dev) && suspend_blank)
3199 _sde_plane_color_fill(psde, 0x0, 0x0);
3200
Clarence Ipcae1bb62016-07-07 12:07:13 -04003201 /* flag h/w flush complete */
3202 if (plane->state)
Clarence Ipddbf7752017-05-21 18:07:30 -04003203 pstate->pending = false;
3204
3205 /* signal inline rotator start */
3206 sde_plane_rot_flush(plane, pstate);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003207}
3208
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003209static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
3210 struct drm_plane_state *old_state)
3211{
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003212 uint32_t nplanes, src_flags = 0x0;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003213 struct sde_plane *psde;
3214 struct drm_plane_state *state;
3215 struct sde_plane_state *pstate;
3216 struct sde_plane_state *old_pstate;
3217 struct sde_plane_rot_state *rstate;
3218 const struct sde_format *fmt;
3219 struct drm_crtc *crtc;
3220 struct drm_framebuffer *fb;
3221 struct sde_rect src, dst;
3222 const struct sde_rect *crtc_roi;
3223 bool q16_data = true;
3224 int idx;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003225 int mode;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003226
3227 if (!plane) {
3228 SDE_ERROR("invalid plane\n");
3229 return -EINVAL;
3230 } else if (!plane->state) {
3231 SDE_ERROR("invalid plane state\n");
3232 return -EINVAL;
3233 } else if (!old_state) {
3234 SDE_ERROR("invalid old state\n");
3235 return -EINVAL;
3236 }
3237
3238 psde = to_sde_plane(plane);
3239 state = plane->state;
3240
3241 pstate = to_sde_plane_state(state);
3242 rstate = &pstate->rot;
3243
3244 old_pstate = to_sde_plane_state(old_state);
3245
3246 crtc = state->crtc;
3247 fb = rstate->out_fb;
3248 if (!crtc || !fb) {
3249 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
3250 crtc != 0, fb != 0);
3251 return -EINVAL;
3252 }
3253 fmt = to_sde_format(msm_framebuffer_format(fb));
3254 nplanes = fmt->num_planes;
3255
3256 SDE_DEBUG(
3257 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
3258 plane->base.id, rstate->sequence_id,
3259 rstate->out_fb_width, rstate->out_fb_height,
3260 (char *) &rstate->out_fb_pixel_format,
3261 rstate->out_fb_modifier[0],
3262 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3263 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3264 rstate->out_rotation,
3265 state->crtc_w, state->crtc_h,
3266 state->crtc_x, state->crtc_y);
3267
3268 /* force reprogramming of all the parameters, if the flag is set */
3269 if (psde->revalidate) {
3270 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
3271 plane->base.id);
3272 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3273 psde->revalidate = false;
3274 }
3275
3276 /* determine what needs to be refreshed */
3277 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
3278 switch (idx) {
3279 case PLANE_PROP_SCALER_V1:
3280 case PLANE_PROP_SCALER_V2:
Clarence Ip059c8c32017-06-06 17:15:54 -04003281 case PLANE_PROP_SCALER_LUT_ED:
3282 case PLANE_PROP_SCALER_LUT_CIR:
3283 case PLANE_PROP_SCALER_LUT_SEP:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003284 case PLANE_PROP_H_DECIMATE:
3285 case PLANE_PROP_V_DECIMATE:
3286 case PLANE_PROP_SRC_CONFIG:
3287 case PLANE_PROP_ZPOS:
3288 case PLANE_PROP_EXCL_RECT_V1:
3289 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3290 break;
3291 case PLANE_PROP_CSC_V1:
3292 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3293 break;
3294 case PLANE_PROP_COLOR_FILL:
3295 /* potentially need to refresh everything */
3296 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3297 break;
3298 case PLANE_PROP_ROTATION:
3299 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3300 break;
3301 case PLANE_PROP_INFO:
3302 case PLANE_PROP_ALPHA:
3303 case PLANE_PROP_INPUT_FENCE:
3304 case PLANE_PROP_BLEND_OP:
3305 /* no special action required */
3306 break;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003307 case PLANE_PROP_FB_TRANSLATION_MODE:
3308 pstate->dirty |= SDE_PLANE_DIRTY_FB_TRANSLATION_MODE;
3309 break;
Alan Kwong2349d742017-04-20 08:27:30 -07003310 case PLANE_PROP_PREFILL_SIZE:
3311 case PLANE_PROP_PREFILL_TIME:
3312 pstate->dirty |= SDE_PLANE_DIRTY_PERF;
3313 break;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003314 case PLANE_PROP_ROT_DST_X:
3315 case PLANE_PROP_ROT_DST_Y:
3316 case PLANE_PROP_ROT_DST_W:
3317 case PLANE_PROP_ROT_DST_H:
3318 /* handled by rotator atomic update */
3319 break;
3320 default:
3321 /* unknown property, refresh everything */
3322 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
3323 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
3324 break;
3325 }
3326 }
3327
3328 /**
3329 * since plane_atomic_check is invoked before crtc_atomic_check
3330 * in the commit sequence, all the parameters for updating the
3331 * plane dirty flag will not be available during
3332 * plane_atomic_check as some features params are updated
3333 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
3334 * before sspp update.
3335 */
3336 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
3337 old_state);
3338
3339 /* re-program the output rects always in the case of partial update */
3340 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
3341 if (!sde_kms_rect_is_null(crtc_roi))
3342 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3343
3344 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
3345 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
3346
3347 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
3348
3349 /* early out if nothing dirty */
3350 if (!pstate->dirty)
3351 return 0;
3352 pstate->pending = true;
3353
3354 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
3355 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3356
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003357 /* update secure session flag */
3358 mode = sde_plane_get_property(pstate, PLANE_PROP_FB_TRANSLATION_MODE);
3359 if ((mode == SDE_DRM_FB_SEC) ||
3360 (mode == SDE_DRM_FB_SEC_DIR_TRANS))
3361 src_flags |= SDE_SSPP_SECURE_OVERLAY_SESSION;
3362
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003363 /* update roi config */
3364 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
3365 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3366 rstate->out_src_w, rstate->out_src_h, q16_data);
3367 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
3368 state->crtc_w, state->crtc_h, !q16_data);
3369
3370 SDE_DEBUG_PLANE(psde,
3371 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
3372 fb->base.id, src.x, src.y, src.w, src.h,
3373 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
3374 (char *)&fmt->base.pixel_format,
3375 SDE_FORMAT_IS_UBWC(fmt));
3376
3377 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
3378 BIT(SDE_DRM_DEINTERLACE)) {
3379 SDE_DEBUG_PLANE(psde, "deinterlace\n");
3380 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
3381 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
3382 src.h /= 2;
3383 src.y = DIV_ROUND_UP(src.y, 2);
3384 src.y &= ~0x1;
3385 }
3386
3387 /*
3388 * adjust layer mixer position of the sspp in the presence
3389 * of a partial update to the active lm origin
3390 */
3391 dst.x -= crtc_roi->x;
3392 dst.y -= crtc_roi->y;
3393
3394 psde->pipe_cfg.src_rect = src;
3395 psde->pipe_cfg.dst_rect = dst;
3396
3397 _sde_plane_setup_scaler(psde, fmt, pstate);
3398
3399 /* check for color fill */
3400 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
3401 PLANE_PROP_COLOR_FILL);
3402 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
3403 /* skip remaining processing on color fill */
3404 pstate->dirty = 0x0;
3405 } else if (psde->pipe_hw->ops.setup_rects) {
3406 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
3407 &psde->pipe_cfg,
3408 pstate->multirect_index);
3409 }
3410
Jeykumar Sankaran0532e0a2017-06-11 20:34:44 -07003411 if (psde->pipe_hw->ops.setup_pe &&
3412 (pstate->multirect_index != SDE_SSPP_RECT_1))
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003413 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
3414 &psde->pixel_ext);
3415
3416 /**
3417 * when programmed in multirect mode, scalar block will be
3418 * bypassed. Still we need to update alpha and bitwidth
3419 * ONLY for RECT0
3420 */
3421 if (psde->pipe_hw->ops.setup_scaler &&
3422 pstate->multirect_index != SDE_SSPP_RECT_1)
3423 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
3424 &psde->pipe_cfg, &psde->pixel_ext,
3425 psde->scaler3_cfg);
3426
3427 /* update excl rect */
3428 if (psde->pipe_hw->ops.setup_excl_rect)
3429 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
3430 &pstate->excl_rect,
3431 pstate->multirect_index);
3432
3433 if (psde->pipe_hw->ops.setup_multirect)
3434 psde->pipe_hw->ops.setup_multirect(
3435 psde->pipe_hw,
3436 pstate->multirect_index,
3437 pstate->multirect_mode);
3438 }
3439
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003440 if (((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) ||
3441 (src_flags & SDE_SSPP_SECURE_OVERLAY_SESSION)) &&
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003442 psde->pipe_hw->ops.setup_format) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003443 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
3444 if (rstate->out_rotation & DRM_REFLECT_X)
3445 src_flags |= SDE_SSPP_FLIP_LR;
3446 if (rstate->out_rotation & DRM_REFLECT_Y)
3447 src_flags |= SDE_SSPP_FLIP_UD;
3448
3449 /* update format */
3450 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
3451 pstate->multirect_index);
3452
Alan Kwong143f50c2017-04-28 07:34:28 -07003453 if (psde->pipe_hw->ops.setup_cdp) {
3454 struct sde_hw_pipe_cdp_cfg *cdp_cfg = &pstate->cdp_cfg;
3455
3456 memset(cdp_cfg, 0, sizeof(struct sde_hw_pipe_cdp_cfg));
3457
3458 cdp_cfg->enable = psde->catalog->perf.cdp_cfg
3459 [SDE_PERF_CDP_USAGE_RT].rd_enable;
3460 cdp_cfg->ubwc_meta_enable =
3461 SDE_FORMAT_IS_UBWC(fmt);
3462 cdp_cfg->tile_amortize_enable =
3463 SDE_FORMAT_IS_UBWC(fmt) ||
3464 SDE_FORMAT_IS_TILE(fmt);
3465 cdp_cfg->preload_ahead = SDE_WB_CDP_PRELOAD_AHEAD_64;
3466
3467 psde->pipe_hw->ops.setup_cdp(psde->pipe_hw, cdp_cfg);
3468 }
3469
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003470 if (psde->pipe_hw->ops.setup_sys_cache) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04003471 if (rstate->out_sbuf && rstate->rot_hw) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003472 if (rstate->nplane < 2)
3473 pstate->sc_cfg.op_mode =
3474 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
3475 else if (rstate->out_xpos == 0)
3476 pstate->sc_cfg.op_mode =
3477 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
3478 else
3479 pstate->sc_cfg.op_mode =
3480 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
3481
3482 pstate->sc_cfg.rd_en = true;
3483 pstate->sc_cfg.rd_scid =
3484 rstate->rot_hw->caps->scid;
3485 pstate->sc_cfg.rd_noallocate = true;
3486 pstate->sc_cfg.rd_op_type =
3487 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3488 } else {
3489 pstate->sc_cfg.op_mode =
3490 SDE_PIPE_SC_OP_MODE_OFFLINE;
3491 pstate->sc_cfg.rd_en = false;
3492 pstate->sc_cfg.rd_scid = 0;
Clarence Ipd02440b2017-05-21 18:10:01 -04003493 pstate->sc_cfg.rd_noallocate = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003494 pstate->sc_cfg.rd_op_type =
3495 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3496 }
3497
3498 psde->pipe_hw->ops.setup_sys_cache(
3499 psde->pipe_hw, &pstate->sc_cfg);
3500 }
3501
3502 /* update csc */
3503 if (SDE_FORMAT_IS_YUV(fmt))
3504 _sde_plane_setup_csc(psde);
3505 else
3506 psde->csc_ptr = 0;
3507 }
3508
3509 sde_color_process_plane_setup(plane);
3510
3511 /* update sharpening */
3512 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3513 psde->pipe_hw->ops.setup_sharpening) {
3514 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3515 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3516 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3517 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3518
3519 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3520 &psde->sharp_cfg);
3521 }
3522
3523 _sde_plane_set_qos_lut(plane, fb);
3524 _sde_plane_set_danger_lut(plane, fb);
3525
3526 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3527 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3528 _sde_plane_set_ot_limit(plane, crtc);
Alan Kwong2349d742017-04-20 08:27:30 -07003529 if (pstate->dirty & SDE_PLANE_DIRTY_PERF)
3530 _sde_plane_set_ts_prefill(plane, pstate);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003531 }
3532
Alan Kwonga62eeb82017-04-19 08:57:55 -07003533 _sde_plane_set_qos_remap(plane);
3534
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003535 /* clear dirty */
3536 pstate->dirty = 0x0;
3537
3538 return 0;
3539}
3540
Clarence Ipc652ccf2017-06-28 18:21:18 -04003541static void _sde_plane_atomic_disable(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003542 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003543{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003544 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003545 struct drm_plane_state *state;
3546 struct sde_plane_state *pstate;
Clarence Ipc652ccf2017-06-28 18:21:18 -04003547
3548 if (!plane) {
3549 SDE_ERROR("invalid plane\n");
3550 return;
3551 } else if (!plane->state) {
3552 SDE_ERROR("invalid plane state\n");
3553 return;
3554 } else if (!old_state) {
3555 SDE_ERROR("invalid old state\n");
3556 return;
3557 }
3558
3559 psde = to_sde_plane(plane);
3560 state = plane->state;
3561 pstate = to_sde_plane_state(state);
3562
3563 SDE_EVT32(DRMID(plane), is_sde_plane_virtual(plane),
3564 pstate->multirect_mode);
3565
3566 pstate->pending = true;
3567
3568 if (is_sde_plane_virtual(plane) &&
3569 psde->pipe_hw && psde->pipe_hw->ops.setup_multirect)
3570 psde->pipe_hw->ops.setup_multirect(psde->pipe_hw,
3571 SDE_SSPP_RECT_SOLO, SDE_SSPP_MULTIRECT_NONE);
3572}
3573
3574static void sde_plane_atomic_update(struct drm_plane *plane,
3575 struct drm_plane_state *old_state)
3576{
3577 struct sde_plane *psde;
3578 struct drm_plane_state *state;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003579
Clarence Ip13a8cf42016-09-29 17:27:47 -04003580 if (!plane) {
3581 SDE_ERROR("invalid plane\n");
3582 return;
3583 } else if (!plane->state) {
3584 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003585 return;
3586 }
3587
Clarence Ip13a8cf42016-09-29 17:27:47 -04003588 psde = to_sde_plane(plane);
3589 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003590 state = plane->state;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003591
Clarence Ip13a8cf42016-09-29 17:27:47 -04003592 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003593
Alan Kwong4dd64c82017-02-04 18:41:51 -08003594 sde_plane_rot_atomic_update(plane, old_state);
3595
3596 if (!sde_plane_sspp_enabled(state)) {
Clarence Ipc652ccf2017-06-28 18:21:18 -04003597 _sde_plane_atomic_disable(plane, old_state);
Clarence Ip282dad62016-09-27 17:07:35 -04003598 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003599 int ret;
3600
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003601 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003602 /* atomic_check should have ensured that this doesn't fail */
3603 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003604 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003605}
3606
Dhaval Patel47302cf2016-08-18 15:04:28 -07003607
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003608/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003609static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003610 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003611{
Clarence Ip5e2a9222016-06-26 22:38:24 -04003612 static const struct drm_prop_enum_list e_blend_op[] = {
3613 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3614 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3615 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3616 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3617 };
3618 static const struct drm_prop_enum_list e_src_config[] = {
3619 {SDE_DRM_DEINTERLACE, "deinterlace"}
3620 };
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07003621 static const struct drm_prop_enum_list e_fb_translation_mode[] = {
3622 {SDE_DRM_FB_NON_SEC, "non_sec"},
3623 {SDE_DRM_FB_SEC, "sec"},
3624 {SDE_DRM_FB_NON_SEC_DIR_TRANS, "non_sec_direct_translation"},
3625 {SDE_DRM_FB_SEC_DIR_TRANS, "sec_direct_translation"},
3626 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003627 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003628 struct sde_format_extended *virt_format_list = NULL;
Dhaval Patel4e574842016-08-23 15:11:37 -07003629 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003630 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003631 int zpos_max = 255;
3632 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003633 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003634
Clarence Ip13a8cf42016-09-29 17:27:47 -04003635 if (!plane || !psde) {
3636 SDE_ERROR("invalid plane\n");
3637 return;
3638 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3639 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3640 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003641 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003642 } else if (!catalog) {
3643 SDE_ERROR("invalid catalog\n");
3644 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003645 }
3646
Alan Kwong4dd64c82017-02-04 18:41:51 -08003647 psde->catalog = catalog;
3648
Clarence Ipc47a0692016-10-11 10:54:17 -04003649 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003650 if (catalog->mixer_count && catalog->mixer &&
3651 catalog->mixer[0].sblk->maxblendstages) {
3652 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3653 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3654 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3655 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003656 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3657 /* reserve zpos == 0 for primary planes */
3658 zpos_def = drm_plane_index(plane) + 1;
3659 }
3660
3661 msm_property_install_range(&psde->property_info, "zpos",
3662 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003663
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003664 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003665 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003666
Dhaval Patel47302cf2016-08-18 15:04:28 -07003667 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003668 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003669 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003670
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003671 if (!master_plane_id) {
3672 if (psde->pipe_sblk->maxhdeciexp) {
3673 msm_property_install_range(&psde->property_info,
3674 "h_decimate", 0x0, 0,
3675 psde->pipe_sblk->maxhdeciexp, 0,
3676 PLANE_PROP_H_DECIMATE);
3677 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003678
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003679 if (psde->pipe_sblk->maxvdeciexp) {
3680 msm_property_install_range(&psde->property_info,
3681 "v_decimate", 0x0, 0,
3682 psde->pipe_sblk->maxvdeciexp, 0,
3683 PLANE_PROP_V_DECIMATE);
3684 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003685
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003686 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003687 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003688 &psde->property_info, "scaler_v2",
3689 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3690 msm_property_install_blob(&psde->property_info,
3691 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3692 msm_property_install_blob(&psde->property_info,
3693 "lut_cir", 0,
3694 PLANE_PROP_SCALER_LUT_CIR);
3695 msm_property_install_blob(&psde->property_info,
3696 "lut_sep", 0,
3697 PLANE_PROP_SCALER_LUT_SEP);
3698 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003699 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003700 &psde->property_info, "scaler_v1", 0x0,
3701 0, ~0, 0, PLANE_PROP_SCALER_V1);
3702 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003703
Dhaval Patel0aee0972017-02-08 19:00:58 -08003704 if (psde->features & BIT(SDE_SSPP_CSC) ||
3705 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003706 msm_property_install_volatile_range(
3707 &psde->property_info, "csc_v1", 0x0,
3708 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003709
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003710 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3711 snprintf(feature_name, sizeof(feature_name), "%s%d",
3712 "SDE_SSPP_HUE_V",
3713 psde->pipe_sblk->hsic_blk.version >> 16);
3714 msm_property_install_range(&psde->property_info,
3715 feature_name, 0, 0, 0xFFFFFFFF, 0,
3716 PLANE_PROP_HUE_ADJUST);
3717 snprintf(feature_name, sizeof(feature_name), "%s%d",
3718 "SDE_SSPP_SATURATION_V",
3719 psde->pipe_sblk->hsic_blk.version >> 16);
3720 msm_property_install_range(&psde->property_info,
3721 feature_name, 0, 0, 0xFFFFFFFF, 0,
3722 PLANE_PROP_SATURATION_ADJUST);
3723 snprintf(feature_name, sizeof(feature_name), "%s%d",
3724 "SDE_SSPP_VALUE_V",
3725 psde->pipe_sblk->hsic_blk.version >> 16);
3726 msm_property_install_range(&psde->property_info,
3727 feature_name, 0, 0, 0xFFFFFFFF, 0,
3728 PLANE_PROP_VALUE_ADJUST);
3729 snprintf(feature_name, sizeof(feature_name), "%s%d",
3730 "SDE_SSPP_CONTRAST_V",
3731 psde->pipe_sblk->hsic_blk.version >> 16);
3732 msm_property_install_range(&psde->property_info,
3733 feature_name, 0, 0, 0xFFFFFFFF, 0,
3734 PLANE_PROP_CONTRAST_ADJUST);
3735 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003736 }
3737
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003738 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3739 msm_property_install_volatile_range(&psde->property_info,
3740 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3741
Alan Kwong4dd64c82017-02-04 18:41:51 -08003742 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003743
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003744 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003745 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003746
Dhaval Patel47302cf2016-08-18 15:04:28 -07003747 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3748 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3749
3750 if (psde->pipe_hw->ops.setup_solidfill)
3751 msm_property_install_range(&psde->property_info, "color_fill",
3752 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3753
Alan Kwong2349d742017-04-20 08:27:30 -07003754 msm_property_install_range(&psde->property_info,
3755 "prefill_size", 0x0, 0, ~0, 0,
3756 PLANE_PROP_PREFILL_SIZE);
3757 msm_property_install_range(&psde->property_info,
3758 "prefill_time", 0x0, 0, ~0, 0,
3759 PLANE_PROP_PREFILL_TIME);
3760
Dhaval Patel4e574842016-08-23 15:11:37 -07003761 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003762 if (!info) {
3763 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003764 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003765 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003766
3767 msm_property_install_blob(&psde->property_info, "capabilities",
3768 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3769 sde_kms_info_reset(info);
3770
Clarence Ipea3d6262016-07-15 16:20:11 -04003771 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003772
3773 if (master_plane_id) {
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003774 int index, array_size;
3775
3776 array_size = ARRAY_SIZE(plane_formats)
3777 + ARRAY_SIZE(rgb_10bit_formats);
3778 virt_format_list = kcalloc(array_size,
3779 sizeof(struct sde_format_extended), GFP_KERNEL);
3780 if (!virt_format_list) {
3781 SDE_ERROR(
3782 "failed to allocate virtual pipe format list\n");
3783 return;
3784 }
3785
3786 index = sde_copy_formats(virt_format_list, array_size,
3787 0, plane_formats, ARRAY_SIZE(plane_formats));
3788 sde_copy_formats(virt_format_list, array_size,
3789 index, rgb_10bit_formats,
3790 ARRAY_SIZE(rgb_10bit_formats));
3791
3792 format_list = virt_format_list;
3793
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003794 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003795 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003796 }
3797
Clarence Ipea3d6262016-07-15 16:20:11 -04003798 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003799 sde_kms_info_start(info, "pixel_formats");
3800 while (format_list->fourcc_format) {
3801 sde_kms_info_append_format(info,
3802 format_list->fourcc_format,
3803 format_list->modifier);
3804 ++format_list;
3805 }
3806 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003807 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003808
3809 sde_kms_info_add_keyint(info, "max_linewidth",
3810 psde->pipe_sblk->maxlinewidth);
3811 sde_kms_info_add_keyint(info, "max_upscale",
3812 psde->pipe_sblk->maxupscale);
3813 sde_kms_info_add_keyint(info, "max_downscale",
3814 psde->pipe_sblk->maxdwnscale);
3815 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3816 psde->pipe_sblk->maxhdeciexp);
3817 sde_kms_info_add_keyint(info, "max_vertical_deci",
3818 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07003819 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
3820 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07003821 msm_property_set_blob(&psde->property_info, &psde->blob_info,
Narendra Muppalla22d17252017-05-31 15:13:39 -07003822 info->data, SDE_KMS_INFO_DATALEN(info),
3823 PLANE_PROP_INFO);
Dhaval Patel4e574842016-08-23 15:11:37 -07003824
3825 kfree(info);
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003826 kfree(virt_format_list);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003827
3828 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3829 snprintf(feature_name, sizeof(feature_name), "%s%d",
3830 "SDE_SSPP_SKIN_COLOR_V",
3831 psde->pipe_sblk->memcolor_blk.version >> 16);
3832 msm_property_install_blob(&psde->property_info, feature_name, 0,
3833 PLANE_PROP_SKIN_COLOR);
3834 snprintf(feature_name, sizeof(feature_name), "%s%d",
3835 "SDE_SSPP_SKY_COLOR_V",
3836 psde->pipe_sblk->memcolor_blk.version >> 16);
3837 msm_property_install_blob(&psde->property_info, feature_name, 0,
3838 PLANE_PROP_SKY_COLOR);
3839 snprintf(feature_name, sizeof(feature_name), "%s%d",
3840 "SDE_SSPP_FOLIAGE_COLOR_V",
3841 psde->pipe_sblk->memcolor_blk.version >> 16);
3842 msm_property_install_blob(&psde->property_info, feature_name, 0,
3843 PLANE_PROP_FOLIAGE_COLOR);
3844 }
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07003845
3846 msm_property_install_enum(&psde->property_info, "fb_translation_mode",
3847 0x0,
3848 0, e_fb_translation_mode,
3849 ARRAY_SIZE(e_fb_translation_mode),
3850 PLANE_PROP_FB_TRANSLATION_MODE);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003851}
3852
Clarence Ip5fc00c52016-09-23 15:03:34 -04003853static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
3854{
3855 struct sde_drm_csc_v1 csc_v1;
3856 int i;
3857
3858 if (!psde) {
3859 SDE_ERROR("invalid plane\n");
3860 return;
3861 }
3862
3863 psde->csc_usr_ptr = NULL;
3864 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003865 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003866 return;
3867 }
3868
3869 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003870 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003871 return;
3872 }
3873
Clarence Ipb43d4592016-09-08 14:21:35 -04003874 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04003875 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
3876 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
3877 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
3878 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
3879 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
3880 }
3881 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
3882 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
3883 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
3884 }
3885 psde->csc_usr_ptr = &psde->csc_cfg;
3886}
3887
Clarence Ipb43d4592016-09-08 14:21:35 -04003888static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
3889{
3890 struct sde_drm_scaler_v1 scale_v1;
3891 struct sde_hw_pixel_ext *pe;
3892 int i;
3893
3894 if (!psde) {
3895 SDE_ERROR("invalid plane\n");
3896 return;
3897 }
3898
Clarence Ip059c8c32017-06-06 17:15:54 -04003899 psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
Clarence Ipb43d4592016-09-08 14:21:35 -04003900 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003901 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003902 return;
3903 }
3904
3905 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003906 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003907 return;
3908 }
3909
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003910 /* force property to be dirty, even if the pointer didn't change */
3911 msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V1);
3912
Clarence Ipb43d4592016-09-08 14:21:35 -04003913 /* populate from user space */
3914 pe = &(psde->pixel_ext);
3915 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3916 for (i = 0; i < SDE_MAX_PLANES; i++) {
3917 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
3918 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
3919 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
3920 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
3921
3922 pe->horz_filter[i] = scale_v1.horz_filter[i];
3923 pe->vert_filter[i] = scale_v1.vert_filter[i];
3924 }
3925 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003926 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
3927 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
3928 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
3929 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
3930 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003931
abeykun41060122016-11-28 13:02:01 -05003932 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
3933 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
3934 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
3935 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
3936 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003937 }
abeykun41060122016-11-28 13:02:01 -05003938
Clarence Ip059c8c32017-06-06 17:15:54 -04003939 psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
Clarence Ipb43d4592016-09-08 14:21:35 -04003940
Clarence Ip059c8c32017-06-06 17:15:54 -04003941 SDE_EVT32_VERBOSE(DRMID(&psde->base));
Clarence Ip13a8cf42016-09-29 17:27:47 -04003942 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003943}
3944
abeykun48f407a2016-08-25 12:06:44 -04003945static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
3946 struct sde_plane_state *pstate, void *usr)
3947{
3948 struct sde_drm_scaler_v2 scale_v2;
3949 struct sde_hw_pixel_ext *pe;
3950 int i;
3951 struct sde_hw_scaler3_cfg *cfg;
3952
Clarence Ip059c8c32017-06-06 17:15:54 -04003953 if (!psde || !psde->scaler3_cfg) {
abeykun48f407a2016-08-25 12:06:44 -04003954 SDE_ERROR("invalid plane\n");
3955 return;
3956 }
3957
3958 cfg = psde->scaler3_cfg;
Clarence Ip059c8c32017-06-06 17:15:54 -04003959 psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
abeykun48f407a2016-08-25 12:06:44 -04003960 if (!usr) {
3961 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3962 return;
3963 }
3964
3965 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
3966 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
3967 return;
3968 }
3969
Clarence Ip7e892a02017-06-13 10:16:07 -04003970 /* detach/ignore user data if 'disabled' */
3971 if (!scale_v2.enable) {
3972 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3973 return;
3974 }
3975
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003976 /* force property to be dirty, even if the pointer didn't change */
3977 msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V2);
3978
abeykun48f407a2016-08-25 12:06:44 -04003979 /* populate from user space */
3980 pe = &(psde->pixel_ext);
3981 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3982 cfg->enable = scale_v2.enable;
3983 cfg->dir_en = scale_v2.dir_en;
3984 for (i = 0; i < SDE_MAX_PLANES; i++) {
3985 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
3986 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
3987 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
3988 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
3989
3990 cfg->preload_x[i] = scale_v2.preload_x[i];
3991 cfg->preload_y[i] = scale_v2.preload_y[i];
3992 cfg->src_width[i] = scale_v2.src_width[i];
3993 cfg->src_height[i] = scale_v2.src_height[i];
3994 }
3995 cfg->dst_width = scale_v2.dst_width;
3996 cfg->dst_height = scale_v2.dst_height;
3997
3998 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
3999 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
4000 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
4001 cfg->blend_cfg = scale_v2.blend_cfg;
4002
4003 cfg->lut_flag = scale_v2.lut_flag;
4004 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
4005 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
4006 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
4007 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
4008 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
4009
4010 cfg->de.enable = scale_v2.de.enable;
4011 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
4012 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
4013 cfg->de.clip = scale_v2.de.clip;
4014 cfg->de.limit = scale_v2.de.limit;
4015 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
4016 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
4017 cfg->de.thr_low = scale_v2.de.thr_low;
4018 cfg->de.thr_high = scale_v2.de.thr_high;
4019 cfg->de.prec_shift = scale_v2.de.prec_shift;
4020 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
4021 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
4022 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
4023 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
4024 }
4025 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05004026 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
4027 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
4028 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
4029 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
4030 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04004031
abeykun41060122016-11-28 13:02:01 -05004032 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
4033 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
4034 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
4035 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
4036 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04004037 }
Clarence Ip059c8c32017-06-06 17:15:54 -04004038 psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
abeykun48f407a2016-08-25 12:06:44 -04004039
Clarence Ip059c8c32017-06-06 17:15:54 -04004040 SDE_EVT32_VERBOSE(DRMID(&psde->base), cfg->enable, cfg->de.enable,
4041 cfg->src_width[0], cfg->src_height[0],
4042 cfg->dst_width, cfg->dst_height);
abeykun48f407a2016-08-25 12:06:44 -04004043 SDE_DEBUG_PLANE(psde, "user property data copied\n");
4044}
4045
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004046static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
4047 struct sde_plane_state *pstate, void *usr_ptr)
4048{
4049 struct drm_clip_rect excl_rect_v1;
4050
4051 if (!psde) {
4052 SDE_ERROR("invalid plane\n");
4053 return;
4054 }
4055
4056 if (!usr_ptr) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004057 SDE_DEBUG_PLANE(psde, "invalid excl_rect user data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004058 return;
4059 }
4060
4061 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004062 SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004063 return;
4064 }
4065
4066 /* populate from user space */
4067 pstate->excl_rect.x = excl_rect_v1.x1;
4068 pstate->excl_rect.y = excl_rect_v1.y1;
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004069 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
4070 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
4071
4072 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
4073 pstate->excl_rect.x, pstate->excl_rect.y,
4074 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004075}
4076
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004077static int sde_plane_atomic_set_property(struct drm_plane *plane,
4078 struct drm_plane_state *state, struct drm_property *property,
4079 uint64_t val)
4080{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004081 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004082 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004083 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004084
Clarence Ip13a8cf42016-09-29 17:27:47 -04004085 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004086
4087 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004088 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004089 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004090 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004091 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04004092 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004093 ret = msm_property_atomic_set(&psde->property_info,
4094 pstate->property_values, pstate->property_blobs,
4095 property, val);
4096 if (!ret) {
4097 idx = msm_property_index(&psde->property_info,
4098 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004099 switch (idx) {
4100 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04004101 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004102 break;
4103 case PLANE_PROP_CSC_V1:
4104 _sde_plane_set_csc_v1(psde, (void *)val);
4105 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04004106 case PLANE_PROP_SCALER_V1:
4107 _sde_plane_set_scaler_v1(psde, (void *)val);
4108 break;
abeykun48f407a2016-08-25 12:06:44 -04004109 case PLANE_PROP_SCALER_V2:
4110 _sde_plane_set_scaler_v2(psde, pstate,
4111 (void *)val);
4112 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004113 case PLANE_PROP_EXCL_RECT_V1:
4114 _sde_plane_set_excl_rect_v1(psde, pstate,
4115 (void *)val);
4116 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04004117 default:
4118 /* nothing to do */
4119 break;
4120 }
Clarence Ipe78efb72016-06-24 18:35:21 -04004121 }
4122 }
4123
Alan Kwong4dd64c82017-02-04 18:41:51 -08004124 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
4125 property->name, property->base.id, val, ret);
4126
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004127 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004128}
4129
4130static int sde_plane_set_property(struct drm_plane *plane,
4131 struct drm_property *property, uint64_t val)
4132{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004133 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04004134
Clarence Ipae4e60c2016-06-26 22:44:04 -04004135 return sde_plane_atomic_set_property(plane,
4136 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004137}
4138
4139static int sde_plane_atomic_get_property(struct drm_plane *plane,
4140 const struct drm_plane_state *state,
4141 struct drm_property *property, uint64_t *val)
4142{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004143 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004144 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04004145 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004146
Clarence Ipaa0faf42016-05-30 12:07:48 -04004147 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004148 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004149 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004150 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004151 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004152 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04004153 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004154 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004155 ret = msm_property_atomic_get(&psde->property_info,
4156 pstate->property_values, pstate->property_blobs,
4157 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04004158 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004159
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004160 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004161}
4162
4163static void sde_plane_destroy(struct drm_plane *plane)
4164{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004165 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004166
Clarence Ip13a8cf42016-09-29 17:27:47 -04004167 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004168
Clarence Ip13a8cf42016-09-29 17:27:47 -04004169 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04004170 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
4171
Dhaval Patel4e574842016-08-23 15:11:37 -07004172 if (psde->blob_info)
4173 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004174 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04004175 mutex_destroy(&psde->lock);
4176
Clarence Ip4ce59322016-06-26 22:27:51 -04004177 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004178
Clarence Ip4ce59322016-06-26 22:27:51 -04004179 /* this will destroy the states as well */
4180 drm_plane_cleanup(plane);
4181
Clarence Ip4c1d9772016-06-26 09:35:38 -04004182 if (psde->pipe_hw)
4183 sde_hw_sspp_destroy(psde->pipe_hw);
4184
Clarence Ip4ce59322016-06-26 22:27:51 -04004185 kfree(psde);
4186 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004187}
4188
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004189static void sde_plane_destroy_state(struct drm_plane *plane,
4190 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004191{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004192 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04004193 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004194
Clarence Ipae4e60c2016-06-26 22:44:04 -04004195 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004196 SDE_ERROR("invalid arg(s), plane %d state %d\n",
4197 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004198 return;
4199 }
4200
Clarence Ipaa0faf42016-05-30 12:07:48 -04004201 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04004202 pstate = to_sde_plane_state(state);
4203
Clarence Ip13a8cf42016-09-29 17:27:47 -04004204 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004205
Alan Kwong4dd64c82017-02-04 18:41:51 -08004206 sde_plane_rot_destroy_state(plane, &pstate->base);
4207
Clarence Ipe78efb72016-06-24 18:35:21 -04004208 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004209 if (state->fb)
4210 drm_framebuffer_unreference(state->fb);
4211
Clarence Ipae4e60c2016-06-26 22:44:04 -04004212 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04004213 if (pstate->input_fence)
4214 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004215
Clarence Ipaa0faf42016-05-30 12:07:48 -04004216 /* destroy value helper */
4217 msm_property_destroy_state(&psde->property_info, pstate,
4218 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004219}
4220
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004221static struct drm_plane_state *
4222sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004223{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004224 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004225 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04004226 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04004227 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004228
Clarence Ip13a8cf42016-09-29 17:27:47 -04004229 if (!plane) {
4230 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004231 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004232 } else if (!plane->state) {
4233 SDE_ERROR("invalid plane state\n");
4234 return NULL;
4235 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004236
Clarence Ip730e7192016-06-26 22:45:09 -04004237 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004238 psde = to_sde_plane(plane);
4239 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004240 if (!pstate) {
4241 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004242 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004243 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004244
Clarence Ip13a8cf42016-09-29 17:27:47 -04004245 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004246
4247 /* duplicate value helper */
4248 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
4249 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004250
Clarence Ip17e908b2016-09-29 15:58:00 -04004251 /* clear out any input fence */
4252 pstate->input_fence = 0;
4253 input_fence_default = msm_property_get_default(
4254 &psde->property_info, PLANE_PROP_INPUT_FENCE);
4255 msm_property_set_property(&psde->property_info, pstate->property_values,
4256 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004257
Clarence Ip282dad62016-09-27 17:07:35 -04004258 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04004259 pstate->pending = false;
4260
Alan Kwongcdb2f282017-03-18 13:42:06 -07004261 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
4262
Alan Kwong4dd64c82017-02-04 18:41:51 -08004263 sde_plane_rot_duplicate_state(plane, &pstate->base);
4264
Clarence Ip730e7192016-06-26 22:45:09 -04004265 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004266}
4267
4268static void sde_plane_reset(struct drm_plane *plane)
4269{
Clarence Ipae4e60c2016-06-26 22:44:04 -04004270 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004271 struct sde_plane_state *pstate;
4272
Clarence Ipae4e60c2016-06-26 22:44:04 -04004273 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004274 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04004275 return;
4276 }
4277
Clarence Ip730e7192016-06-26 22:45:09 -04004278 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004279 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004280
Clarence Ipae4e60c2016-06-26 22:44:04 -04004281 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04004282 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04004283 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004284 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04004285 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004286
Clarence Ipaa0faf42016-05-30 12:07:48 -04004287 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004288 if (!pstate) {
4289 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004290 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004291 }
Clarence Ip730e7192016-06-26 22:45:09 -04004292
Clarence Ipaa0faf42016-05-30 12:07:48 -04004293 /* reset value helper */
4294 msm_property_reset_state(&psde->property_info, pstate,
4295 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004296
4297 pstate->base.plane = plane;
4298
4299 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004300}
4301
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004302#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04004303static ssize_t _sde_plane_danger_read(struct file *file,
4304 char __user *buff, size_t count, loff_t *ppos)
4305{
4306 struct sde_kms *kms = file->private_data;
4307 struct sde_mdss_cfg *cfg = kms->catalog;
4308 int len = 0;
4309 char buf[40] = {'\0'};
4310
4311 if (!cfg)
4312 return -ENODEV;
4313
4314 if (*ppos)
4315 return 0; /* the end */
4316
4317 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
4318 if (len < 0 || len >= sizeof(buf))
4319 return 0;
4320
4321 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
4322 return -EFAULT;
4323
4324 *ppos += len; /* increase offset */
4325
4326 return len;
4327}
4328
4329static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
4330{
4331 struct drm_plane *plane;
4332
4333 drm_for_each_plane(plane, kms->dev) {
4334 if (plane->fb && plane->state) {
4335 sde_plane_danger_signal_ctrl(plane, enable);
4336 SDE_DEBUG("plane:%d img:%dx%d ",
4337 plane->base.id, plane->fb->width,
4338 plane->fb->height);
4339 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
4340 plane->state->src_x >> 16,
4341 plane->state->src_y >> 16,
4342 plane->state->src_w >> 16,
4343 plane->state->src_h >> 16,
4344 plane->state->crtc_x, plane->state->crtc_y,
4345 plane->state->crtc_w, plane->state->crtc_h);
4346 } else {
4347 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
4348 }
4349 }
4350}
4351
4352static ssize_t _sde_plane_danger_write(struct file *file,
4353 const char __user *user_buf, size_t count, loff_t *ppos)
4354{
4355 struct sde_kms *kms = file->private_data;
4356 struct sde_mdss_cfg *cfg = kms->catalog;
4357 int disable_panic;
4358 char buf[10];
4359
4360 if (!cfg)
4361 return -EFAULT;
4362
4363 if (count >= sizeof(buf))
4364 return -EFAULT;
4365
4366 if (copy_from_user(buf, user_buf, count))
4367 return -EFAULT;
4368
4369 buf[count] = 0; /* end of string */
4370
4371 if (kstrtoint(buf, 0, &disable_panic))
4372 return -EFAULT;
4373
4374 if (disable_panic) {
4375 /* Disable panic signal for all active pipes */
4376 SDE_DEBUG("Disabling danger:\n");
4377 _sde_plane_set_danger_state(kms, false);
4378 kms->has_danger_ctrl = false;
4379 } else {
4380 /* Enable panic signal for all active pipes */
4381 SDE_DEBUG("Enabling danger:\n");
4382 kms->has_danger_ctrl = true;
4383 _sde_plane_set_danger_state(kms, true);
4384 }
4385
4386 return count;
4387}
4388
4389static const struct file_operations sde_plane_danger_enable = {
4390 .open = simple_open,
4391 .read = _sde_plane_danger_read,
4392 .write = _sde_plane_danger_write,
4393};
4394
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004395static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04004396{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004397 struct sde_plane *psde;
4398 struct sde_kms *kms;
4399 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04004400 const struct sde_sspp_sub_blks *sblk = 0;
4401 const struct sde_sspp_cfg *cfg = 0;
4402
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004403 if (!plane || !plane->dev) {
4404 SDE_ERROR("invalid arguments\n");
4405 return -EINVAL;
4406 }
4407
4408 priv = plane->dev->dev_private;
4409 if (!priv || !priv->kms) {
4410 SDE_ERROR("invalid KMS reference\n");
4411 return -EINVAL;
4412 }
4413
4414 kms = to_sde_kms(priv->kms);
4415 psde = to_sde_plane(plane);
4416
Clarence Ip4ce59322016-06-26 22:27:51 -04004417 if (psde && psde->pipe_hw)
4418 cfg = psde->pipe_hw->cap;
4419 if (cfg)
4420 sblk = cfg->sblk;
4421
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004422 if (!sblk)
4423 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04004424
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004425 /* create overall sub-directory for the pipe */
4426 psde->debugfs_root =
4427 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07004428 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04004429
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004430 if (!psde->debugfs_root)
4431 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04004432
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004433 /* don't error check these */
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004434 debugfs_create_x32("features", 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004435 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004436
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004437 /* add register dump support */
4438 sde_debugfs_setup_regset32(&psde->debugfs_src,
4439 sblk->src_blk.base + cfg->base,
4440 sblk->src_blk.len,
4441 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004442 sde_debugfs_create_regset32("src_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004443 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004444
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004445 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
4446 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
4447 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
4448 sblk->scaler_blk.base + cfg->base,
4449 sblk->scaler_blk.len,
4450 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004451 sde_debugfs_create_regset32("scaler_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004452 psde->debugfs_root,
4453 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07004454 debugfs_create_bool("default_scaling",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004455 0600,
Clarence Ip716ab662017-03-20 06:51:24 -07004456 psde->debugfs_root,
4457 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04004458 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004459
4460 if (cfg->features & BIT(SDE_SSPP_CSC) ||
4461 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
4462 sde_debugfs_setup_regset32(&psde->debugfs_csc,
4463 sblk->csc_blk.base + cfg->base,
4464 sblk->csc_blk.len,
4465 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004466 sde_debugfs_create_regset32("csc_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004467 psde->debugfs_root, &psde->debugfs_csc);
4468 }
4469
4470 debugfs_create_u32("xin_id",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004471 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004472 psde->debugfs_root,
4473 (u32 *) &cfg->xin_id);
4474 debugfs_create_u32("clk_ctrl",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004475 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004476 psde->debugfs_root,
4477 (u32 *) &cfg->clk_ctrl);
4478 debugfs_create_x32("creq_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004479 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004480 psde->debugfs_root,
4481 (u32 *) &sblk->creq_vblank);
4482 debugfs_create_x32("danger_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004483 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004484 psde->debugfs_root,
4485 (u32 *) &sblk->danger_vblank);
4486
4487 debugfs_create_file("disable_danger",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004488 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004489 psde->debugfs_root,
4490 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004491 debugfs_create_u32("sbuf_mode",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004492 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004493 psde->debugfs_root, &psde->sbuf_mode);
4494 debugfs_create_u32("sbuf_writeback",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004495 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004496 psde->debugfs_root,
4497 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004498
4499 return 0;
4500}
4501
4502static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4503{
4504 struct sde_plane *psde;
4505
4506 if (!plane)
4507 return;
4508 psde = to_sde_plane(plane);
4509
4510 debugfs_remove_recursive(psde->debugfs_root);
4511}
4512#else
4513static int _sde_plane_init_debugfs(struct drm_plane *plane)
4514{
4515 return 0;
4516}
4517static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4518{
4519}
4520#endif
4521
4522static int sde_plane_late_register(struct drm_plane *plane)
4523{
4524 return _sde_plane_init_debugfs(plane);
4525}
4526
4527static void sde_plane_early_unregister(struct drm_plane *plane)
4528{
4529 _sde_plane_destroy_debugfs(plane);
4530}
4531
4532static const struct drm_plane_funcs sde_plane_funcs = {
4533 .update_plane = drm_atomic_helper_update_plane,
4534 .disable_plane = drm_atomic_helper_disable_plane,
4535 .destroy = sde_plane_destroy,
4536 .set_property = sde_plane_set_property,
4537 .atomic_set_property = sde_plane_atomic_set_property,
4538 .atomic_get_property = sde_plane_atomic_get_property,
4539 .reset = sde_plane_reset,
4540 .atomic_duplicate_state = sde_plane_duplicate_state,
4541 .atomic_destroy_state = sde_plane_destroy_state,
4542 .late_register = sde_plane_late_register,
4543 .early_unregister = sde_plane_early_unregister,
4544};
4545
4546static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
4547 .prepare_fb = sde_plane_prepare_fb,
4548 .cleanup_fb = sde_plane_cleanup_fb,
4549 .atomic_check = sde_plane_atomic_check,
4550 .atomic_update = sde_plane_atomic_update,
4551};
4552
4553enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
4554{
4555 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
4556}
4557
4558bool is_sde_plane_virtual(struct drm_plane *plane)
4559{
4560 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04004561}
4562
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004563/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04004564struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04004565 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004566 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004567{
Alan Kwongdce56da2017-04-27 15:50:34 -07004568 struct drm_plane *plane = NULL, *master_plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004569 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004570 struct sde_format_extended *virt_format_list = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004571 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004572 struct msm_drm_private *priv;
4573 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004574 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04004575 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004576
4577 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004578 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004579 goto exit;
4580 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004581
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004582 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004583 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004584 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004585 goto exit;
4586 }
4587
4588 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004589 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004590 goto exit;
4591 }
4592 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004593
Clarence Ip4c1d9772016-06-26 09:35:38 -04004594 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004595 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004596 goto exit;
4597 }
4598
Clarence Ip4ce59322016-06-26 22:27:51 -04004599 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004600 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4601 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004602 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004603 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004604 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004605 }
4606
Clarence Ip4c1d9772016-06-26 09:35:38 -04004607 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004608 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004609 psde->pipe = pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004610 psde->is_virtual = (master_plane_id != 0);
Clarence Ip059c8c32017-06-06 17:15:54 -04004611 psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
Alan Kwongdce56da2017-04-27 15:50:34 -07004612 INIT_LIST_HEAD(&psde->mplane_list);
4613 master_plane = drm_plane_find(dev, master_plane_id);
4614 if (master_plane) {
4615 struct sde_plane *mpsde = to_sde_plane(master_plane);
4616
4617 list_add_tail(&psde->mplane_list, &mpsde->mplane_list);
4618 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004619
Clarence Ip4c1d9772016-06-26 09:35:38 -04004620 /* initialize underlying h/w driver */
Dhaval Pateld850b222017-06-16 17:37:37 -07004621 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog,
4622 master_plane_id != 0);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004623 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004624 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004625 ret = PTR_ERR(psde->pipe_hw);
4626 goto clean_plane;
4627 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004628 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004629 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004630 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004631
4632 /* cache features mask for later */
4633 psde->features = psde->pipe_hw->cap->features;
4634 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004635 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004636 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004637 goto clean_sspp;
4638 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004639
abeykun48f407a2016-08-25 12:06:44 -04004640 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
4641 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
4642 GFP_KERNEL);
4643 if (!psde->scaler3_cfg) {
4644 SDE_ERROR("[%u]failed to allocate scale struct\n",
4645 pipe);
4646 ret = -ENOMEM;
4647 goto clean_sspp;
4648 }
4649 }
4650
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004651 format_list = psde->pipe_sblk->format_list;
4652
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004653 if (master_plane_id) {
4654 int index, array_size;
4655
4656 array_size = ARRAY_SIZE(plane_formats)
4657 + ARRAY_SIZE(rgb_10bit_formats);
4658 virt_format_list = kcalloc(array_size,
4659 sizeof(struct sde_format_extended),
4660 GFP_KERNEL);
4661 if (!virt_format_list) {
4662 SDE_ERROR(
4663 "failed to allocate virtual pipe format list\n");
4664 goto clean_sspp;
4665 }
4666
4667 index = sde_copy_formats(virt_format_list, array_size,
4668 0, plane_formats, ARRAY_SIZE(plane_formats));
4669 sde_copy_formats(virt_format_list, array_size,
4670 index, rgb_10bit_formats,
4671 ARRAY_SIZE(rgb_10bit_formats));
4672
4673 format_list = virt_format_list;
4674 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004675
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004676 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004677 psde->formats,
4678 0,
4679 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004680
Clarence Ip4c1d9772016-06-26 09:35:38 -04004681 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004682 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004683 goto clean_sspp;
4684 }
4685
4686 if (psde->features & BIT(SDE_SSPP_CURSOR))
4687 type = DRM_PLANE_TYPE_CURSOR;
4688 else if (primary_plane)
4689 type = DRM_PLANE_TYPE_PRIMARY;
4690 else
4691 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07004692 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
4693 psde->formats, psde->nformats,
4694 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004695 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04004696 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004697
Clarence Ip4c1d9772016-06-26 09:35:38 -04004698 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004699 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004700
Clarence Ipaa0faf42016-05-30 12:07:48 -04004701 msm_property_init(&psde->property_info, &plane->base, dev,
4702 priv->plane_property, psde->property_data,
4703 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
4704 sizeof(struct sde_plane_state));
4705
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004706 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004707
Clarence Ip4ce59322016-06-26 22:27:51 -04004708 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004709 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004710
Clarence Ip730e7192016-06-26 22:45:09 -04004711 mutex_init(&psde->lock);
4712
Dhaval Patel572cfd22017-06-12 19:33:39 -07004713 SDE_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", psde->pipe_name,
4714 pipe, plane->base.id, master_plane_id);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004715 return plane;
4716
Clarence Ip4c1d9772016-06-26 09:35:38 -04004717clean_sspp:
4718 if (psde && psde->pipe_hw)
4719 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04004720
4721 if (psde && psde->scaler3_cfg)
4722 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004723clean_plane:
4724 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004725exit:
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004726 kfree(virt_format_list);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004727 return ERR_PTR(ret);
4728}