blob: fb3523d3fc1a23ebb96fcbfc28f0370c7e1e0771 [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
Jordan Croused8e96522017-02-13 10:14:16 -0700133 struct msm_gem_address_space *aspace;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400134
Clarence Ip730e7192016-06-26 22:45:09 -0400135 struct mutex lock;
136
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400137 enum sde_sspp pipe;
138 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700139 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400140 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400141
142 struct sde_hw_pipe *pipe_hw;
143 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -0400144 struct sde_hw_sharp_cfg sharp_cfg;
abeykun48f407a2016-08-25 12:06:44 -0400145 struct sde_hw_scaler3_cfg *scaler3_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400146 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400147 uint32_t color_fill;
148 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400149 bool is_rt_pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800150 bool is_virtual;
Alan Kwongdce56da2017-04-27 15:50:34 -0700151 struct list_head mplane_list;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800152 struct sde_mdss_cfg *catalog;
153 u32 sbuf_mode;
154 u32 sbuf_writeback;
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700155 bool revalidate;
Clarence Ip4ce59322016-06-26 22:27:51 -0400156
Clarence Ipb43d4592016-09-08 14:21:35 -0400157 struct sde_hw_pixel_ext pixel_ext;
Clarence Ip059c8c32017-06-06 17:15:54 -0400158 enum sde_plane_sclcheck_state scaler_check_state;
Clarence Ipb43d4592016-09-08 14:21:35 -0400159
Clarence Ip373f8592016-05-26 00:58:42 -0400160 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400161 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400162 struct sde_csc_cfg *csc_ptr;
163
Clarence Ip4c1d9772016-06-26 09:35:38 -0400164 const struct sde_sspp_sub_blks *pipe_sblk;
165
Clarence Ip5e2a9222016-06-26 22:38:24 -0400166 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400167
Clarence Ipaa0faf42016-05-30 12:07:48 -0400168 struct msm_property_info property_info;
169 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700170 struct drm_property_blob *blob_info;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800171 struct drm_property_blob *blob_rot_caps;
Clarence Ip730e7192016-06-26 22:45:09 -0400172
Clarence Ip4ce59322016-06-26 22:27:51 -0400173 /* debugfs related stuff */
174 struct dentry *debugfs_root;
175 struct sde_debugfs_regset32 debugfs_src;
176 struct sde_debugfs_regset32 debugfs_scaler;
177 struct sde_debugfs_regset32 debugfs_csc;
Clarence Ip716ab662017-03-20 06:51:24 -0700178 bool debugfs_default_scale;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700179};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700180
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700181#define to_sde_plane(x) container_of(x, struct sde_plane, base)
182
Alan Kwong4dd64c82017-02-04 18:41:51 -0800183static struct sde_kms *_sde_plane_get_kms(struct drm_plane *plane)
184{
185 struct msm_drm_private *priv;
186
187 if (!plane || !plane->dev)
188 return NULL;
189 priv = plane->dev->dev_private;
190 if (!priv)
191 return NULL;
192 return to_sde_kms(priv->kms);
193}
194
Alan Kwong4aacd532017-02-04 18:51:33 -0800195/**
196 * _sde_plane_get_crtc_state - obtain crtc state attached to given plane state
197 * @pstate: Pointer to drm plane state
198 * return: Pointer to crtc state if success; pointer error, otherwise
199 */
200static struct drm_crtc_state *_sde_plane_get_crtc_state(
201 struct drm_plane_state *pstate)
202{
203 struct drm_crtc_state *cstate;
204
205 if (!pstate || !pstate->crtc)
206 return NULL;
207
208 if (pstate->state)
209 cstate = drm_atomic_get_crtc_state(pstate->state, pstate->crtc);
210 else
211 cstate = pstate->crtc->state;
212
213 return cstate;
214}
215
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400216static bool sde_plane_enabled(struct drm_plane_state *state)
217{
Clarence Ipdbde9832016-06-26 09:48:36 -0400218 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400219}
220
Alan Kwong4dd64c82017-02-04 18:41:51 -0800221static bool sde_plane_sspp_enabled(struct drm_plane_state *state)
222{
223 return state && to_sde_plane_state(state)->rot.out_fb && state->crtc;
224}
225
226/**
227 * sde_plane_crtc_enabled - determine if crtc of given plane state is enabled
228 * @state: Pointer to drm plane state
229 * return: true if plane and the associated crtc are both enabled
230 */
231static bool sde_plane_crtc_enabled(struct drm_plane_state *state)
232{
233 return sde_plane_enabled(state) && state->crtc->state &&
234 state->crtc->state->active &&
235 state->crtc->state->enable;
236}
237
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400238/**
239 * _sde_plane_calc_fill_level - calculate fill level of the given source format
240 * @plane: Pointer to drm plane
241 * @fmt: Pointer to source buffer format
242 * @src_wdith: width of source buffer
243 * Return: fill level corresponding to the source buffer/format or 0 if error
244 */
245static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
246 const struct sde_format *fmt, u32 src_width)
247{
Alan Kwongdce56da2017-04-27 15:50:34 -0700248 struct sde_plane *psde, *tmp;
249 struct sde_plane_state *pstate;
250 struct sde_plane_rot_state *rstate;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400251 u32 fixed_buff_size;
252 u32 total_fl;
Alan Kwongdce56da2017-04-27 15:50:34 -0700253 u32 hflip_bytes;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400254
Alan Kwongdce56da2017-04-27 15:50:34 -0700255 if (!plane || !fmt || !plane->state || !src_width || !fmt->bpp) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400256 SDE_ERROR("invalid arguments\n");
257 return 0;
258 }
259
260 psde = to_sde_plane(plane);
Alan Kwongdce56da2017-04-27 15:50:34 -0700261 pstate = to_sde_plane_state(plane->state);
262 rstate = &pstate->rot;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400263 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
264
Alan Kwongdce56da2017-04-27 15:50:34 -0700265 list_for_each_entry(tmp, &psde->mplane_list, mplane_list) {
266 if (!sde_plane_enabled(tmp->base.state))
267 continue;
268 SDE_DEBUG("plane%d/%d src_width:%d/%d\n",
269 psde->base.base.id, tmp->base.base.id,
270 src_width, tmp->pipe_cfg.src_rect.w);
271 src_width = max_t(u32, src_width, tmp->pipe_cfg.src_rect.w);
272 }
273
274 if ((rstate->out_rotation & DRM_REFLECT_X) &&
275 SDE_FORMAT_IS_LINEAR(fmt))
276 hflip_bytes = (src_width + 32) * fmt->bpp;
277 else
278 hflip_bytes = 0;
279
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400280 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
281 if (fmt->chroma_sample == SDE_CHROMA_420) {
282 /* NV12 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700283 total_fl = (fixed_buff_size / 2 - hflip_bytes) /
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400284 ((src_width + 32) * fmt->bpp);
285 } else {
286 /* non NV12 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700287 total_fl = (fixed_buff_size / 2 - hflip_bytes) /
288 ((src_width + 32) * fmt->bpp * 2);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400289 }
290 } else {
Alan Kwongdce56da2017-04-27 15:50:34 -0700291 if (pstate->multirect_mode == SDE_SSPP_MULTIRECT_PARALLEL) {
292 total_fl = (fixed_buff_size / 2 - hflip_bytes) /
293 ((src_width + 32) * fmt->bpp * 2);
294 } else {
295 total_fl = (fixed_buff_size - hflip_bytes) /
296 ((src_width + 32) * fmt->bpp * 2);
297 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400298 }
299
Alan Kwongdce56da2017-04-27 15:50:34 -0700300 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u hf:%d fl:%u\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400301 plane->base.id, psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700302 (char *)&fmt->base.pixel_format,
Alan Kwongdce56da2017-04-27 15:50:34 -0700303 src_width, hflip_bytes, total_fl);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400304
305 return total_fl;
306}
307
308/**
Alan Kwongdce56da2017-04-27 15:50:34 -0700309 * _sde_plane_get_qos_lut - get LUT mapping based on fill level
310 * @tbl: Pointer to LUT table
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400311 * @total_fl: fill level
312 * Return: LUT setting corresponding to the fill level
313 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700314static u64 _sde_plane_get_qos_lut(const struct sde_qos_lut_tbl *tbl,
315 u32 total_fl)
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400316{
Alan Kwongdce56da2017-04-27 15:50:34 -0700317 int i;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400318
Alan Kwongdce56da2017-04-27 15:50:34 -0700319 if (!tbl || !tbl->nentry || !tbl->entries)
320 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400321
Alan Kwongdce56da2017-04-27 15:50:34 -0700322 for (i = 0; i < tbl->nentry; i++)
323 if (total_fl <= tbl->entries[i].fl)
324 return tbl->entries[i].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400325
Alan Kwongdce56da2017-04-27 15:50:34 -0700326 /* if last fl is zero, use as default */
327 if (!tbl->entries[i-1].fl)
328 return tbl->entries[i-1].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400329
Alan Kwongdce56da2017-04-27 15:50:34 -0700330 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400331}
332
333/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400334 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
335 * @plane: Pointer to drm plane
336 * @fb: Pointer to framebuffer associated with the given plane
337 */
338static void _sde_plane_set_qos_lut(struct drm_plane *plane,
339 struct drm_framebuffer *fb)
340{
341 struct sde_plane *psde;
342 const struct sde_format *fmt = NULL;
Alan Kwongdce56da2017-04-27 15:50:34 -0700343 u64 qos_lut;
344 u32 total_fl = 0, lut_usage;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400345
346 if (!plane || !fb) {
347 SDE_ERROR("invalid arguments plane %d fb %d\n",
348 plane != 0, fb != 0);
349 return;
350 }
351
352 psde = to_sde_plane(plane);
353
Alan Kwongdce56da2017-04-27 15:50:34 -0700354 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400355 SDE_ERROR("invalid arguments\n");
356 return;
357 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
358 return;
359 }
360
361 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700362 lut_usage = SDE_QOS_LUT_USAGE_NRT;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400363 } else {
364 fmt = sde_get_sde_format_ext(
365 fb->pixel_format,
366 fb->modifier,
367 drm_format_num_planes(fb->pixel_format));
368 total_fl = _sde_plane_calc_fill_level(plane, fmt,
369 psde->pipe_cfg.src_rect.w);
370
371 if (SDE_FORMAT_IS_LINEAR(fmt))
Alan Kwongdce56da2017-04-27 15:50:34 -0700372 lut_usage = SDE_QOS_LUT_USAGE_LINEAR;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400373 else
Alan Kwongdce56da2017-04-27 15:50:34 -0700374 lut_usage = SDE_QOS_LUT_USAGE_MACROTILE;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400375 }
376
Alan Kwongdce56da2017-04-27 15:50:34 -0700377 qos_lut = _sde_plane_get_qos_lut(
378 &psde->catalog->perf.qos_lut_tbl[lut_usage], total_fl);
379
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400380 psde->pipe_qos_cfg.creq_lut = qos_lut;
381
382 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
383 (fmt) ? fmt->base.pixel_format : 0,
Alan Kwongdce56da2017-04-27 15:50:34 -0700384 psde->is_rt_pipe, total_fl, qos_lut, lut_usage);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400385
Alan Kwongdce56da2017-04-27 15:50:34 -0700386 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400387 plane->base.id,
388 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700389 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400390 psde->is_rt_pipe, total_fl, qos_lut);
391
392 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
393}
394
395/**
396 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
397 * @plane: Pointer to drm plane
398 * @fb: Pointer to framebuffer associated with the given plane
399 */
400static void _sde_plane_set_danger_lut(struct drm_plane *plane,
401 struct drm_framebuffer *fb)
402{
403 struct sde_plane *psde;
404 const struct sde_format *fmt = NULL;
405 u32 danger_lut, safe_lut;
406
407 if (!plane || !fb) {
408 SDE_ERROR("invalid arguments\n");
409 return;
410 }
411
412 psde = to_sde_plane(plane);
413
Alan Kwongdce56da2017-04-27 15:50:34 -0700414 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400415 SDE_ERROR("invalid arguments\n");
416 return;
417 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
418 return;
419 }
420
421 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700422 danger_lut = psde->catalog->perf.danger_lut_tbl
423 [SDE_QOS_LUT_USAGE_NRT];
424 safe_lut = psde->catalog->perf.safe_lut_tbl
425 [SDE_QOS_LUT_USAGE_NRT];
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400426 } else {
427 fmt = sde_get_sde_format_ext(
428 fb->pixel_format,
429 fb->modifier,
430 drm_format_num_planes(fb->pixel_format));
431
432 if (SDE_FORMAT_IS_LINEAR(fmt)) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700433 danger_lut = psde->catalog->perf.danger_lut_tbl
434 [SDE_QOS_LUT_USAGE_LINEAR];
435 safe_lut = psde->catalog->perf.safe_lut_tbl
436 [SDE_QOS_LUT_USAGE_LINEAR];
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400437 } else {
Alan Kwongdce56da2017-04-27 15:50:34 -0700438 danger_lut = psde->catalog->perf.danger_lut_tbl
439 [SDE_QOS_LUT_USAGE_MACROTILE];
440 safe_lut = psde->catalog->perf.safe_lut_tbl
441 [SDE_QOS_LUT_USAGE_MACROTILE];
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400442 }
443 }
444
445 psde->pipe_qos_cfg.danger_lut = danger_lut;
446 psde->pipe_qos_cfg.safe_lut = safe_lut;
447
448 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
449 (fmt) ? fmt->base.pixel_format : 0,
450 (fmt) ? fmt->fetch_mode : 0,
451 psde->pipe_qos_cfg.danger_lut,
452 psde->pipe_qos_cfg.safe_lut);
453
Dhaval Patel6c666622017-03-21 23:02:59 -0700454 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400455 plane->base.id,
456 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700457 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400458 fmt ? fmt->fetch_mode : -1,
459 psde->pipe_qos_cfg.danger_lut,
460 psde->pipe_qos_cfg.safe_lut);
461
462 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
463 &psde->pipe_qos_cfg);
464}
465
466/**
467 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
468 * @plane: Pointer to drm plane
469 * @enable: true to enable QoS control
470 * @flags: QoS control mode (enum sde_plane_qos)
471 */
472static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
473 bool enable, u32 flags)
474{
475 struct sde_plane *psde;
476
477 if (!plane) {
478 SDE_ERROR("invalid arguments\n");
479 return;
480 }
481
482 psde = to_sde_plane(plane);
483
484 if (!psde->pipe_hw || !psde->pipe_sblk) {
485 SDE_ERROR("invalid arguments\n");
486 return;
487 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
488 return;
489 }
490
491 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
492 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
493 psde->pipe_qos_cfg.danger_vblank =
494 psde->pipe_sblk->danger_vblank;
495 psde->pipe_qos_cfg.vblank_en = enable;
496 }
497
498 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
499 /* this feature overrules previous VBLANK_CTRL */
500 psde->pipe_qos_cfg.vblank_en = false;
501 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
502 }
503
504 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
505 psde->pipe_qos_cfg.danger_safe_en = enable;
506
507 if (!psde->is_rt_pipe) {
508 psde->pipe_qos_cfg.vblank_en = false;
509 psde->pipe_qos_cfg.danger_safe_en = false;
510 }
511
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400512 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 -0400513 plane->base.id,
514 psde->pipe - SSPP_VIG0,
515 psde->pipe_qos_cfg.danger_safe_en,
516 psde->pipe_qos_cfg.vblank_en,
517 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400518 psde->pipe_qos_cfg.danger_vblank,
519 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400520
521 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
522 &psde->pipe_qos_cfg);
523}
524
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700525void sde_plane_set_revalidate(struct drm_plane *plane, bool enable)
526{
527 struct sde_plane *psde;
528
529 if (!plane)
530 return;
531
532 psde = to_sde_plane(plane);
533 psde->revalidate = enable;
534}
535
Alan Kwongf0fd8512016-10-24 21:39:26 -0400536int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
537{
538 struct sde_plane *psde;
539 struct msm_drm_private *priv;
540 struct sde_kms *sde_kms;
541
542 if (!plane || !plane->dev) {
543 SDE_ERROR("invalid arguments\n");
544 return -EINVAL;
545 }
546
547 priv = plane->dev->dev_private;
548 if (!priv || !priv->kms) {
549 SDE_ERROR("invalid KMS reference\n");
550 return -EINVAL;
551 }
552
553 sde_kms = to_sde_kms(priv->kms);
554 psde = to_sde_plane(plane);
555
556 if (!psde->is_rt_pipe)
557 goto end;
558
559 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
560
561 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
562
563 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
564
565end:
566 return 0;
567}
568
Alan Kwong5d324e42016-07-28 22:56:18 -0400569/**
570 * _sde_plane_set_ot_limit - set OT limit for the given plane
571 * @plane: Pointer to drm plane
572 * @crtc: Pointer to drm crtc
573 */
574static void _sde_plane_set_ot_limit(struct drm_plane *plane,
575 struct drm_crtc *crtc)
576{
577 struct sde_plane *psde;
578 struct sde_vbif_set_ot_params ot_params;
579 struct msm_drm_private *priv;
580 struct sde_kms *sde_kms;
581
582 if (!plane || !plane->dev || !crtc) {
583 SDE_ERROR("invalid arguments plane %d crtc %d\n",
584 plane != 0, crtc != 0);
585 return;
586 }
587
588 priv = plane->dev->dev_private;
589 if (!priv || !priv->kms) {
590 SDE_ERROR("invalid KMS reference\n");
591 return;
592 }
593
594 sde_kms = to_sde_kms(priv->kms);
595 psde = to_sde_plane(plane);
596 if (!psde->pipe_hw) {
597 SDE_ERROR("invalid pipe reference\n");
598 return;
599 }
600
601 memset(&ot_params, 0, sizeof(ot_params));
602 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
603 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
604 ot_params.width = psde->pipe_cfg.src_rect.w;
605 ot_params.height = psde->pipe_cfg.src_rect.h;
606 ot_params.is_wfd = !psde->is_rt_pipe;
607 ot_params.frame_rate = crtc->mode.vrefresh;
608 ot_params.vbif_idx = VBIF_RT;
609 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
610 ot_params.rd = true;
611
612 sde_vbif_set_ot_limit(sde_kms, &ot_params);
613}
614
Alan Kwonga62eeb82017-04-19 08:57:55 -0700615/**
616 * _sde_plane_set_vbif_qos - set vbif QoS for the given plane
617 * @plane: Pointer to drm plane
618 */
619static void _sde_plane_set_qos_remap(struct drm_plane *plane)
620{
621 struct sde_plane *psde;
622 struct sde_vbif_set_qos_params qos_params;
623 struct msm_drm_private *priv;
624 struct sde_kms *sde_kms;
625
626 if (!plane || !plane->dev) {
627 SDE_ERROR("invalid arguments\n");
628 return;
629 }
630
631 priv = plane->dev->dev_private;
632 if (!priv || !priv->kms) {
633 SDE_ERROR("invalid KMS reference\n");
634 return;
635 }
636
637 sde_kms = to_sde_kms(priv->kms);
638 psde = to_sde_plane(plane);
639 if (!psde->pipe_hw) {
640 SDE_ERROR("invalid pipe reference\n");
641 return;
642 }
643
644 memset(&qos_params, 0, sizeof(qos_params));
645 qos_params.vbif_idx = VBIF_RT;
646 qos_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
647 qos_params.xin_id = psde->pipe_hw->cap->xin_id;
648 qos_params.num = psde->pipe_hw->idx - SSPP_VIG0;
649 qos_params.is_rt = psde->is_rt_pipe;
650
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700651 SDE_DEBUG("plane%d pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n",
Alan Kwonga62eeb82017-04-19 08:57:55 -0700652 plane->base.id, qos_params.num,
653 qos_params.vbif_idx,
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700654 qos_params.xin_id, qos_params.is_rt,
655 qos_params.clk_ctrl);
Alan Kwonga62eeb82017-04-19 08:57:55 -0700656
657 sde_vbif_set_qos_remap(sde_kms, &qos_params);
658}
659
Alan Kwong2349d742017-04-20 08:27:30 -0700660/**
661 * _sde_plane_set_ts_prefill - set prefill with traffic shaper
662 * @plane: Pointer to drm plane
663 * @pstate: Pointer to sde plane state
664 */
665static void _sde_plane_set_ts_prefill(struct drm_plane *plane,
666 struct sde_plane_state *pstate)
667{
668 struct sde_plane *psde;
669 struct sde_hw_pipe_ts_cfg cfg;
670 struct msm_drm_private *priv;
671 struct sde_kms *sde_kms;
672
673 if (!plane || !plane->dev) {
674 SDE_ERROR("invalid arguments");
675 return;
676 }
677
678 priv = plane->dev->dev_private;
679 if (!priv || !priv->kms) {
680 SDE_ERROR("invalid KMS reference\n");
681 return;
682 }
683
684 sde_kms = to_sde_kms(priv->kms);
685 psde = to_sde_plane(plane);
686 if (!psde->pipe_hw) {
687 SDE_ERROR("invalid pipe reference\n");
688 return;
689 }
690
691 if (!psde->pipe_hw || !psde->pipe_hw->ops.setup_ts_prefill)
692 return;
693
694 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_VBLANK_AMORTIZE);
695
696 memset(&cfg, 0, sizeof(cfg));
697 cfg.size = sde_plane_get_property(pstate,
698 PLANE_PROP_PREFILL_SIZE);
699 cfg.time = sde_plane_get_property(pstate,
700 PLANE_PROP_PREFILL_TIME);
701
702 SDE_DEBUG("plane%d size:%llu time:%llu\n",
703 plane->base.id, cfg.size, cfg.time);
704 SDE_EVT32(DRMID(plane), cfg.size, cfg.time);
705 psde->pipe_hw->ops.setup_ts_prefill(psde->pipe_hw, &cfg,
706 pstate->multirect_index);
707}
708
Clarence Ipcae1bb62016-07-07 12:07:13 -0400709/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400710static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400711 struct sde_plane_state *pstate, uint64_t fd)
712{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400713 if (!psde || !pstate) {
714 SDE_ERROR("invalid arg(s), plane %d state %d\n",
715 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400716 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400717 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400718
719 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400720 if (pstate->input_fence)
721 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400722
723 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400724 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400725
Clarence Ip13a8cf42016-09-29 17:27:47 -0400726 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400727}
728
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700729/**
730 * _sde_plane_inline_rot_set_ot_limit - set OT limit for the given inline
731 * rotation xin client
732 * @plane: pointer to drm plane
733 * @crtc: pointer to drm crtc
734 * @cfg: pointer to rotator vbif config
735 * @rect_w: rotator frame width
736 * @rect_h: rotator frame height
737 */
738static void _sde_plane_inline_rot_set_ot_limit(struct drm_plane *plane,
739 struct drm_crtc *crtc, const struct sde_rot_vbif_cfg *cfg,
740 u32 rect_w, u32 rect_h)
741{
742 struct sde_vbif_set_ot_params ot_params;
743 struct msm_drm_private *priv;
744 struct sde_kms *sde_kms;
745
746 if (!plane || !plane->dev) {
747 SDE_ERROR("invalid arguments\n");
748 return;
749 }
750
751 priv = plane->dev->dev_private;
752 if (!priv || !priv->kms) {
753 SDE_ERROR("invalid KMS reference\n");
754 return;
755 }
756
757 sde_kms = to_sde_kms(priv->kms);
758
759 memset(&ot_params, 0, sizeof(ot_params));
760 ot_params.xin_id = cfg->xin_id;
761 ot_params.num = cfg->num;
762 ot_params.width = rect_w;
763 ot_params.height = rect_h;
764 ot_params.is_wfd = false;
765 ot_params.frame_rate = crtc->mode.vrefresh;
766 ot_params.vbif_idx = VBIF_RT;
767 ot_params.clk_ctrl = cfg->clk_ctrl;
768 ot_params.rd = cfg->is_read;
769
770 sde_vbif_set_ot_limit(sde_kms, &ot_params);
771}
772
773/**
774 * _sde_plane_inline_rot_set_qos_remap - set vbif QoS for the given inline
775 * rotation xin client
776 * @plane: Pointer to drm plane
777 * @cfg: Pointer to rotator vbif cfg
778 */
779static void _sde_plane_inline_rot_set_qos_remap(struct drm_plane *plane,
780 const struct sde_rot_vbif_cfg *cfg)
781{
782 struct sde_vbif_set_qos_params qos_params;
783 struct msm_drm_private *priv;
784 struct sde_kms *sde_kms;
785
786 if (!plane || !plane->dev) {
787 SDE_ERROR("invalid arguments\n");
788 return;
789 }
790
791 priv = plane->dev->dev_private;
792 if (!priv || !priv->kms) {
793 SDE_ERROR("invalid KMS reference\n");
794 return;
795 }
796
797 sde_kms = to_sde_kms(priv->kms);
798
799 memset(&qos_params, 0, sizeof(qos_params));
800 qos_params.vbif_idx = VBIF_RT;
801 qos_params.xin_id = cfg->xin_id;
802 qos_params.clk_ctrl = cfg->clk_ctrl;
803 qos_params.num = cfg->num;
804 qos_params.is_rt = true;
805
806 SDE_DEBUG("vbif:%d xin:%d num:%d rt:%d clk_ctrl:%d\n",
807 qos_params.vbif_idx, qos_params.xin_id,
808 qos_params.num, qos_params.is_rt, qos_params.clk_ctrl);
809
810 sde_vbif_set_qos_remap(sde_kms, &qos_params);
811}
812
Clarence Ipcae1bb62016-07-07 12:07:13 -0400813int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400814{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400815 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400816 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400817 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400818 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400819 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800820 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400821
822 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700823 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400824 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400825 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400826 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400827 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400828 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400829 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400830
Clarence Ipcae1bb62016-07-07 12:07:13 -0400831 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800832 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400833 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800834 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400835
Dhaval Patel39323d42017-03-01 23:48:24 -0800836 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400837 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400838 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
839 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400840 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800841 ret = -ETIMEDOUT;
842 break;
843 case -ERESTARTSYS:
844 SDE_ERROR_PLANE(psde,
845 "%ums wait interrupted on %08X\n",
846 wait_ms, prefix);
847 psde->is_error = true;
848 ret = -ERESTARTSYS;
849 break;
850 case -EINVAL:
851 SDE_ERROR_PLANE(psde,
852 "invalid fence param for %08X\n",
853 prefix);
854 psde->is_error = true;
855 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400856 break;
857 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800858 SDE_DEBUG_PLANE(psde, "signaled\n");
859 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400860 break;
861 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700862
863 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400864 } else {
865 ret = 0;
866 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400867 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400868 return ret;
869}
870
Clarence Ip282dad62016-09-27 17:07:35 -0400871static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400872 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400873 struct sde_hw_pipe_cfg *pipe_cfg,
874 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400875{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400876 struct sde_plane *psde;
Clarence Ip282dad62016-09-27 17:07:35 -0400877 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400878
Clarence Ip13a8cf42016-09-29 17:27:47 -0400879 if (!plane || !pstate || !pipe_cfg || !fb) {
880 SDE_ERROR(
881 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
882 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400883 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400884 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400885
886 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400887 if (!psde->pipe_hw) {
888 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400889 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400890 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400891
Jordan Croused8e96522017-02-13 10:14:16 -0700892 ret = sde_format_populate_layout(psde->aspace, fb, &pipe_cfg->layout);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400893 if (ret == -EAGAIN)
894 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
895 else if (ret)
896 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
Alan Kwongc16e0922017-05-11 14:50:46 -0700897 else if (psde->pipe_hw->ops.setup_sourceaddress) {
898 SDE_EVT32(psde->pipe_hw->idx,
899 pipe_cfg->layout.width,
900 pipe_cfg->layout.height,
901 pipe_cfg->layout.plane_addr[0],
902 pipe_cfg->layout.plane_size[0],
903 pipe_cfg->layout.plane_addr[1],
904 pipe_cfg->layout.plane_size[1],
905 pipe_cfg->layout.plane_addr[2],
906 pipe_cfg->layout.plane_size[2],
907 pipe_cfg->layout.plane_addr[3],
908 pipe_cfg->layout.plane_size[3],
909 pstate->multirect_index);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800910 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
911 pstate->multirect_index);
Alan Kwongc16e0922017-05-11 14:50:46 -0700912 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400913}
914
abeykun48f407a2016-08-25 12:06:44 -0400915static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
916 struct sde_plane_state *pstate)
917{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500918 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400919 int ret = 0;
920
Clarence Ip3bf8d872017-02-16 15:25:38 -0500921 if (!psde || !psde->scaler3_cfg) {
922 SDE_ERROR("invalid args\n");
923 return -EINVAL;
924 } else if (!pstate) {
925 /* pstate is expected to be null on forced color fill */
926 SDE_DEBUG("null pstate\n");
927 return -EINVAL;
928 }
929
930 cfg = psde->scaler3_cfg;
931
abeykun48f407a2016-08-25 12:06:44 -0400932 cfg->dir_lut = msm_property_get_blob(
933 &psde->property_info,
934 pstate->property_blobs, &cfg->dir_len,
935 PLANE_PROP_SCALER_LUT_ED);
936 cfg->cir_lut = msm_property_get_blob(
937 &psde->property_info,
938 pstate->property_blobs, &cfg->cir_len,
939 PLANE_PROP_SCALER_LUT_CIR);
940 cfg->sep_lut = msm_property_get_blob(
941 &psde->property_info,
942 pstate->property_blobs, &cfg->sep_len,
943 PLANE_PROP_SCALER_LUT_SEP);
944 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
945 ret = -ENODATA;
946 return ret;
947}
948
Clarence Ipcb410d42016-06-26 22:52:33 -0400949static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400950 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
951 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400952 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400953 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
954{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700955 uint32_t decimated, i;
956
957 if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
958 !chroma_subsmpl_v) {
959 SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
960 , psde, scale_cfg, fmt, chroma_subsmpl_h,
961 chroma_subsmpl_v);
962 return;
963 }
964
965 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip716ab662017-03-20 06:51:24 -0700966 memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700967
968 decimated = DECIMATED_DIMENSION(src_w,
969 psde->pipe_cfg.horz_decimation);
970 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
971 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
972 decimated = DECIMATED_DIMENSION(src_h,
973 psde->pipe_cfg.vert_decimation);
974 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
975 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
976
977
978 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
979 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
980 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
981 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
982
983 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
984 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
985 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
986 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
987
988 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
989 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
990 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
991 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
992
993 for (i = 0; i < SDE_MAX_PLANES; i++) {
994 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
995 psde->pipe_cfg.horz_decimation);
996 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
997 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -0700998 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
999 scale_cfg->src_width[i] /= chroma_subsmpl_h;
1000 scale_cfg->src_height[i] /= chroma_subsmpl_v;
1001 }
1002 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
1003 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
1004 psde->pixel_ext.num_ext_pxls_top[i] =
1005 scale_cfg->src_height[i];
1006 psde->pixel_ext.num_ext_pxls_left[i] =
1007 scale_cfg->src_width[i];
1008 }
1009 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
1010 && (src_w == dst_w))
1011 return;
1012
1013 scale_cfg->dst_width = dst_w;
1014 scale_cfg->dst_height = dst_h;
1015 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
1016 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
1017 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
1018 scale_cfg->lut_flag = 0;
1019 scale_cfg->blend_cfg = 1;
1020 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001021}
1022
Clarence Ipcb410d42016-06-26 22:52:33 -04001023/**
Clarence Ip13a8cf42016-09-29 17:27:47 -04001024 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -04001025 * @psde: Pointer to SDE plane object
1026 * @src: Source size
1027 * @dst: Destination size
1028 * @phase_steps: Pointer to output array for phase steps
1029 * @filter: Pointer to output array for filter type
1030 * @fmt: Pointer to format definition
1031 * @chroma_subsampling: Subsampling amount for chroma channel
1032 *
1033 * Returns: 0 on success
1034 */
1035static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001036 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001037 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001038 uint32_t chroma_subsampling)
1039{
Clarence Ipcb410d42016-06-26 22:52:33 -04001040 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001041 SDE_ERROR(
1042 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
1043 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001044 return -EINVAL;
1045 }
1046
Clarence Ip4c1d9772016-06-26 09:35:38 -04001047 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -04001048 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001049 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -04001050 phase_steps[SDE_SSPP_COMP_1_2] =
1051 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
1052 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
1053 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001054
1055 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -04001056 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -04001057 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001058 (src <= dst) ? SDE_SCALE_FILTER_BIL :
1059 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001060
Clarence Ipdbde9832016-06-26 09:48:36 -04001061 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001062 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -04001063 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
1064 } else {
1065 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
1066 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001067 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -04001068 }
1069 } else {
1070 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001071 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
1072 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
1073 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001074 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001075 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001076}
1077
Clarence Ipcb410d42016-06-26 22:52:33 -04001078/**
1079 * _sde_plane_setup_pixel_ext - determine default pixel extension values
1080 * @psde: Pointer to SDE plane object
1081 * @src: Source size
1082 * @dst: Destination size
1083 * @decimated_src: Source size after decimation, if any
1084 * @phase_steps: Pointer to output array for phase steps
1085 * @out_src: Output array for pixel extension values
1086 * @out_edge1: Output array for pixel extension first edge
1087 * @out_edge2: Output array for pixel extension second edge
1088 * @filter: Pointer to array for filter type
1089 * @fmt: Pointer to format definition
1090 * @chroma_subsampling: Subsampling amount for chroma channel
1091 * @post_compare: Whether to chroma subsampled source size for comparisions
1092 */
1093static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001094 uint32_t src, uint32_t dst, uint32_t decimated_src,
1095 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -04001096 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001097 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -04001098 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001099{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001100 int64_t edge1, edge2, caf;
1101 uint32_t src_work;
1102 int i, tmp;
1103
Clarence Ipcb410d42016-06-26 22:52:33 -04001104 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -04001105 out_edge2 && filter && fmt) {
1106 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001107 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001108 caf = PHASE_STEP_UNIT_SCALE;
1109 else
1110 caf = 0;
1111
1112 for (i = 0; i < SDE_MAX_PLANES; i++) {
1113 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -04001114 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001115 src_work /= chroma_subsampling;
1116 if (post_compare)
1117 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -04001118 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001119 /* unity */
1120 edge1 = 0;
1121 edge2 = 0;
1122 } else if (dst >= src) {
1123 /* upscale */
1124 edge1 = (1 << PHASE_RESIDUAL);
1125 edge1 -= caf;
1126 edge2 = (1 << PHASE_RESIDUAL);
1127 edge2 += (dst - 1) * *(phase_steps + i);
1128 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1129 edge2 += caf;
1130 edge2 = -(edge2);
1131 } else {
1132 /* downscale */
1133 edge1 = 0;
1134 edge2 = (dst - 1) * *(phase_steps + i);
1135 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1136 edge2 += *(phase_steps + i);
1137 edge2 = -(edge2);
1138 }
1139
1140 /* only enable CAF for luma plane */
1141 caf = 0;
1142
1143 /* populate output arrays */
1144 *(out_src + i) = src_work;
1145
1146 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001147 if (edge1 >= 0) {
1148 tmp = (uint32_t)edge1;
1149 tmp >>= PHASE_STEP_SHIFT;
1150 *(out_edge1 + i) = -tmp;
1151 } else {
1152 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -04001153 *(out_edge1 + i) =
1154 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1155 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001156 }
1157 if (edge2 >= 0) {
1158 tmp = (uint32_t)edge2;
1159 tmp >>= PHASE_STEP_SHIFT;
1160 *(out_edge2 + i) = -tmp;
1161 } else {
1162 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -04001163 *(out_edge2 + i) =
1164 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1165 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001166 }
1167 }
1168 }
1169}
1170
Clarence Ip5fc00c52016-09-23 15:03:34 -04001171static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -04001172{
1173 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
1174 {
Clarence Ip373f8592016-05-26 00:58:42 -04001175 /* S15.16 format */
1176 0x00012A00, 0x00000000, 0x00019880,
1177 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1178 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -04001179 },
Clarence Ip373f8592016-05-26 00:58:42 -04001180 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -04001181 { 0xfff0, 0xff80, 0xff80,},
1182 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001183 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -04001184 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001185 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -04001186 };
abeykun1c312f62016-08-26 09:47:12 -04001187 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
1188 {
1189 /* S15.16 format */
1190 0x00012A00, 0x00000000, 0x00019880,
1191 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1192 0x00012A00, 0x00020480, 0x00000000,
1193 },
1194 /* signed bias */
1195 { 0xffc0, 0xfe00, 0xfe00,},
1196 { 0x0, 0x0, 0x0,},
1197 /* unsigned clamp */
1198 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
1199 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
1200 };
Clarence Ipe78efb72016-06-24 18:35:21 -04001201
Clarence Ip5fc00c52016-09-23 15:03:34 -04001202 if (!psde) {
1203 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001204 return;
1205 }
Clarence Ip5e2a9222016-06-26 22:38:24 -04001206
Clarence Ipcae1bb62016-07-07 12:07:13 -04001207 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001208 if (psde->csc_usr_ptr)
1209 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -04001210 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
1211 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001212 else
Clarence Ip373f8592016-05-26 00:58:42 -04001213 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001214
Clarence Ip13a8cf42016-09-29 17:27:47 -04001215 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -04001216 psde->csc_ptr->csc_mv[0],
1217 psde->csc_ptr->csc_mv[1],
1218 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -04001219}
1220
Benet Clarkeb1b4462016-06-27 14:43:06 -07001221static void sde_color_process_plane_setup(struct drm_plane *plane)
1222{
1223 struct sde_plane *psde;
1224 struct sde_plane_state *pstate;
1225 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001226 struct drm_msm_memcol *memcol = NULL;
1227 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001228
1229 psde = to_sde_plane(plane);
1230 pstate = to_sde_plane_state(plane->state);
1231
1232 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1233 if (psde->pipe_hw->ops.setup_pa_hue)
1234 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1235 saturation = (uint32_t) sde_plane_get_property(pstate,
1236 PLANE_PROP_SATURATION_ADJUST);
1237 if (psde->pipe_hw->ops.setup_pa_sat)
1238 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1239 value = (uint32_t) sde_plane_get_property(pstate,
1240 PLANE_PROP_VALUE_ADJUST);
1241 if (psde->pipe_hw->ops.setup_pa_val)
1242 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1243 contrast = (uint32_t) sde_plane_get_property(pstate,
1244 PLANE_PROP_CONTRAST_ADJUST);
1245 if (psde->pipe_hw->ops.setup_pa_cont)
1246 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001247
Benet Clarkd009b1d2016-06-27 14:45:59 -07001248 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1249 /* Skin memory color setup */
1250 memcol = msm_property_get_blob(&psde->property_info,
1251 pstate->property_blobs,
1252 &memcol_sz,
1253 PLANE_PROP_SKIN_COLOR);
1254 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1255 MEMCOLOR_SKIN, memcol);
1256
1257 /* Sky memory color setup */
1258 memcol = msm_property_get_blob(&psde->property_info,
1259 pstate->property_blobs,
1260 &memcol_sz,
1261 PLANE_PROP_SKY_COLOR);
1262 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1263 MEMCOLOR_SKY, memcol);
1264
1265 /* Foliage memory color setup */
1266 memcol = msm_property_get_blob(&psde->property_info,
1267 pstate->property_blobs,
1268 &memcol_sz,
1269 PLANE_PROP_FOLIAGE_COLOR);
1270 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1271 MEMCOLOR_FOLIAGE, memcol);
1272 }
1273}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001274
Clarence Ipcb410d42016-06-26 22:52:33 -04001275static void _sde_plane_setup_scaler(struct sde_plane *psde,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001276 const struct sde_format *fmt,
Clarence Ipcb410d42016-06-26 22:52:33 -04001277 struct sde_plane_state *pstate)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001278{
Clarence Ipb43d4592016-09-08 14:21:35 -04001279 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001280 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001281
Clarence Ipb43d4592016-09-08 14:21:35 -04001282 if (!psde || !fmt) {
1283 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1284 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001285 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001286 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001287
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001288 pe = &(psde->pixel_ext);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001289
Clarence Ipdedbba92016-09-27 17:43:10 -04001290 psde->pipe_cfg.horz_decimation =
1291 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1292 psde->pipe_cfg.vert_decimation =
1293 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001294
1295 /* don't chroma subsample if decimating */
1296 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001297 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001298 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001299 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001300
Clarence Ip5e2a9222016-06-26 22:38:24 -04001301 /* update scaler */
1302 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
abeykun48f407a2016-08-25 12:06:44 -04001303 int error;
1304
1305 error = _sde_plane_setup_scaler3_lut(psde, pstate);
Clarence Ip059c8c32017-06-06 17:15:54 -04001306 if (error || psde->debugfs_default_scale ||
1307 psde->scaler_check_state !=
1308 SDE_PLANE_SCLCHECK_SCALER_V2) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001309 /* calculate default config for QSEED3 */
Clarence Ipcb410d42016-06-26 22:52:33 -04001310 _sde_plane_setup_scaler3(psde,
1311 psde->pipe_cfg.src_rect.w,
1312 psde->pipe_cfg.src_rect.h,
1313 psde->pipe_cfg.dst_rect.w,
1314 psde->pipe_cfg.dst_rect.h,
abeykun48f407a2016-08-25 12:06:44 -04001315 psde->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001316 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001317 }
Clarence Ip059c8c32017-06-06 17:15:54 -04001318 } else if (psde->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 ||
1319 !pstate || psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001320 uint32_t deci_dim, i;
1321
Clarence Ipb43d4592016-09-08 14:21:35 -04001322 /* calculate default configuration for QSEED2 */
1323 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001324
Clarence Ip13a8cf42016-09-29 17:27:47 -04001325 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001326 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1327 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001328 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001329 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001330 psde->pipe_cfg.dst_rect.w,
1331 pe->phase_step_x,
1332 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001333
Clarence Ipdbde9832016-06-26 09:48:36 -04001334 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001335 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001336 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001337 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001338 pe->phase_step_x,
1339 pe->roi_w,
1340 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001341 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001342 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001343
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001344 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001345 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001346 _sde_plane_setup_scaler2(psde,
1347 deci_dim,
1348 psde->pipe_cfg.dst_rect.h,
1349 pe->phase_step_y,
1350 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001351 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001352 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001353 pe->phase_step_y,
1354 pe->roi_h,
1355 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001356 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001357 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001358
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001359 for (i = 0; i < SDE_MAX_PLANES; i++) {
1360 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001361 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001362 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001363 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001364
1365 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001366 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001367 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001368 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001369
1370 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001371 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001372 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001373 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001374
1375 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001376 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001377 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001378 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001379 }
1380 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001381}
1382
Clarence Ipcae1bb62016-07-07 12:07:13 -04001383/**
1384 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001385 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001386 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1387 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1388 * Returns: 0 on success
1389 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001390static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001391 uint32_t color, uint32_t alpha)
1392{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001393 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001394 const struct drm_plane *plane;
1395 const struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001396
Clarence Ip13a8cf42016-09-29 17:27:47 -04001397 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001398 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001399 return -EINVAL;
1400 }
1401
Clarence Ipcb410d42016-06-26 22:52:33 -04001402 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001403 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001404 return -EINVAL;
1405 }
1406
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001407 plane = &psde->base;
1408 pstate = to_sde_plane_state(plane->state);
1409
Clarence Ip13a8cf42016-09-29 17:27:47 -04001410 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001411
Clarence Ipcb410d42016-06-26 22:52:33 -04001412 /*
1413 * select fill format to match user property expectation,
1414 * h/w only supports RGB variants
1415 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001416 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001417
1418 /* update sspp */
1419 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1420 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001421 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1422 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001423
1424 /* override scaler/decimation if solid fill */
1425 psde->pipe_cfg.src_rect.x = 0;
1426 psde->pipe_cfg.src_rect.y = 0;
1427 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1428 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Dhaval Patele4b6bb22017-03-27 17:22:21 -07001429 _sde_plane_setup_scaler(psde, fmt, 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001430
Clarence Ipcb410d42016-06-26 22:52:33 -04001431 if (psde->pipe_hw->ops.setup_format)
1432 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001433 fmt, SDE_SSPP_SOLID_FILL,
1434 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001435
1436 if (psde->pipe_hw->ops.setup_rects)
1437 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001438 &psde->pipe_cfg,
1439 pstate->multirect_index);
1440
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001441 if (psde->pipe_hw->ops.setup_pe)
1442 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
1443 &psde->pixel_ext);
Clarence Ipcb410d42016-06-26 22:52:33 -04001444 }
1445
1446 return 0;
1447}
1448
Alan Kwong4dd64c82017-02-04 18:41:51 -08001449/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001450 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1451 */
1452static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1453{
1454 drm_framebuffer_reference(fb);
1455 return fb;
1456}
1457static void _sde_plane_fb_put(void *fb)
1458{
1459 drm_framebuffer_unreference(fb);
1460}
1461static struct sde_crtc_res_ops fb_res_ops = {
1462 .put = _sde_plane_fb_put,
1463 .get = _sde_plane_fb_get,
1464};
1465
1466/**
1467 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1468 */
1469static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1470{
1471 sde_kms_fbo_reference(fbo);
1472 return fbo;
1473}
1474static void _sde_plane_fbo_put(void *fbo)
1475{
1476 sde_kms_fbo_unreference(fbo);
1477}
1478static struct sde_crtc_res_ops fbo_res_ops = {
1479 .put = _sde_plane_fbo_put,
1480 .get = _sde_plane_fbo_get,
1481};
1482
1483/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001484 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001485 * @plane: Pointer to drm plane
1486 * return: prefill time in line
1487 */
1488static u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
1489{
1490 struct drm_plane_state *state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001491 struct sde_plane_state *pstate;
1492 struct sde_plane_rot_state *rstate;
1493 struct sde_kms *sde_kms;
1494 u32 blocksize = 128;
1495 u32 prefill_line = 0;
1496
Clarence Ip7eb90452017-05-23 11:41:19 -04001497 if (!plane || !plane->state || !plane->state->fb) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001498 SDE_ERROR("invalid parameters\n");
1499 return 0;
1500 }
1501
1502 sde_kms = _sde_plane_get_kms(plane);
1503 state = plane->state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001504 pstate = to_sde_plane_state(state);
1505 rstate = &pstate->rot;
1506
Clarence Ip7eb90452017-05-23 11:41:19 -04001507 if (!sde_kms || !sde_kms->catalog) {
1508 SDE_ERROR("invalid kms\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08001509 return 0;
1510 }
1511
Clarence Ip7eb90452017-05-23 11:41:19 -04001512 if (rstate->out_fb_format)
1513 sde_format_get_block_size(rstate->out_fb_format,
1514 &blocksize, &blocksize);
1515
Alan Kwong4dd64c82017-02-04 18:41:51 -08001516 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
1517
1518 SDE_DEBUG("plane%d prefill:%u\n", plane->base.id, prefill_line);
1519
1520 return prefill_line;
1521}
1522
1523/**
1524 * sde_plane_is_sbuf_mode - check if sspp of given plane is in streaming
1525 * buffer mode
1526 * @plane: Pointer to drm plane
1527 * @prefill: Pointer to prefill line count
1528 * return: true if sspp is in stream buffer mode
1529 */
1530bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill)
1531{
1532 struct sde_plane_state *pstate = plane && plane->state ?
1533 to_sde_plane_state(plane->state) : NULL;
1534 struct sde_plane_rot_state *rstate = pstate ? &pstate->rot : NULL;
1535 bool sbuf_mode = rstate ? rstate->out_sbuf : false;
1536
Clarence Ip7eb90452017-05-23 11:41:19 -04001537 if (prefill)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001538 *prefill = sde_plane_rot_calc_prefill(plane);
1539
1540 return sbuf_mode;
1541}
1542
1543/**
1544 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1545 * enumerating over all planes attached to the same rotator
1546 * @plane: Pointer to drm plane
1547 * @state: Pointer to drm state to be updated
1548 * return: none
1549 */
1550static void sde_plane_rot_calc_cfg(struct drm_plane *plane,
1551 struct drm_plane_state *state)
1552{
1553 struct sde_plane_state *pstate;
1554 struct sde_plane_rot_state *rstate;
1555 struct sde_hw_blk *hw_blk;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001556 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001557 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001558 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001559 u32 dst_x, dst_y, dst_w, dst_h;
1560 int found = 0;
1561 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001562 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001563
1564 if (!plane || !state || !state->state) {
1565 SDE_ERROR("invalid parameters\n");
1566 return;
1567 }
1568
Alan Kwongcdb2f282017-03-18 13:42:06 -07001569 cstate = _sde_plane_get_crtc_state(state);
1570 if (IS_ERR_OR_NULL(cstate)) {
1571 ret = PTR_ERR(cstate);
1572 SDE_ERROR("invalid crtc state %d\n", ret);
1573 return;
1574 }
1575
Alan Kwong4dd64c82017-02-04 18:41:51 -08001576 pstate = to_sde_plane_state(state);
1577 rstate = &pstate->rot;
1578
1579 if (!rstate->rot_hw) {
1580 SDE_ERROR("invalid rotator hw\n");
1581 return;
1582 }
1583
1584 in_rot = &rstate->in_rot_rect;
1585 in_rot->x1 = state->src_x;
1586 in_rot->y1 = state->src_y;
1587 in_rot->x2 = state->src_x + state->src_w;
1588 in_rot->y2 = state->src_y + state->src_h;
1589
1590 out_rot = &rstate->out_rot_rect;
1591 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1592 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1593 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1594 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1595
1596 if (!dst_w && !dst_h) {
1597 rstate->out_rot_rect = rstate->in_rot_rect;
1598 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1599 state->fb->height << 16, rstate->in_rotation);
1600 } else {
1601 out_rot->x1 = dst_x;
1602 out_rot->y1 = dst_y;
1603 out_rot->x2 = dst_x + dst_w;
1604 out_rot->y2 = dst_y + dst_h;
1605 }
1606
1607 rstate->out_src_rect = rstate->out_rot_rect;
1608
1609 hw_blk = &rstate->rot_hw->base;
1610
1611 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001612 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001613 struct drm_plane_state *attached_state;
1614 struct sde_plane_state *attached_pstate;
1615 struct sde_plane_rot_state *attached_rstate;
1616 struct drm_rect attached_out_rect;
1617
Alan Kwong4dd64c82017-02-04 18:41:51 -08001618 attached_state = drm_atomic_get_existing_plane_state(
1619 state->state, attached_plane);
1620
1621 if (!attached_state)
1622 continue;
1623
1624 attached_pstate = to_sde_plane_state(attached_state);
1625 attached_rstate = &attached_pstate->rot;
1626
Clarence Ipd27d9632017-06-14 09:57:26 -04001627 if (attached_state->fb != state->fb)
1628 continue;
1629
1630 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) !=
1631 sde_plane_get_property(attached_pstate,
1632 PLANE_PROP_ROTATION))
Alan Kwongcdb2f282017-03-18 13:42:06 -07001633 continue;
1634
1635 found++;
1636
1637 /* skip itself */
1638 if (attached_plane == plane)
1639 continue;
1640
Alan Kwong4dd64c82017-02-04 18:41:51 -08001641 /* find bounding rotator source roi */
1642 if (attached_state->src_x < in_rot->x1)
1643 in_rot->x1 = attached_state->src_x;
1644
1645 if (attached_state->src_y < in_rot->y1)
1646 in_rot->y1 = attached_state->src_y;
1647
1648 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1649 in_rot->x2 = attached_state->src_x +
1650 attached_state->src_w;
1651
1652 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1653 in_rot->y2 = attached_state->src_y +
1654 attached_state->src_h;
1655
1656 /* find bounding rotator destination roi */
1657 dst_x = sde_plane_get_property(attached_pstate,
1658 PLANE_PROP_ROT_DST_X);
1659 dst_y = sde_plane_get_property(attached_pstate,
1660 PLANE_PROP_ROT_DST_Y);
1661 dst_w = sde_plane_get_property(attached_pstate,
1662 PLANE_PROP_ROT_DST_W);
1663 dst_h = sde_plane_get_property(attached_pstate,
1664 PLANE_PROP_ROT_DST_H);
1665 if (!dst_w && !dst_h) {
1666 attached_out_rect.x1 = attached_state->src_x;
1667 attached_out_rect.y1 = attached_state->src_y;
1668 attached_out_rect.x2 = attached_out_rect.x1 +
1669 attached_state->src_w;
1670 attached_out_rect.y2 = attached_out_rect.y1 +
1671 attached_state->src_h;
1672 drm_rect_rotate(&attached_out_rect,
1673 state->fb->width << 16,
1674 state->fb->height << 16,
1675 rstate->in_rotation);
1676 } else {
1677 attached_out_rect.x1 = dst_x;
1678 attached_out_rect.y1 = dst_y;
1679 attached_out_rect.x2 = dst_x + dst_w;
1680 attached_out_rect.y2 = dst_y + dst_h;
1681 }
1682
1683 /* find relative sspp position */
1684 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1685 xpos++;
1686
1687 if (attached_out_rect.x1 < out_rot->x1)
1688 out_rot->x1 = attached_out_rect.x1;
1689
1690 if (attached_out_rect.y1 < out_rot->y1)
1691 out_rot->y1 = attached_out_rect.y1;
1692
1693 if (attached_out_rect.x2 > out_rot->x2)
1694 out_rot->x2 = attached_out_rect.x2;
1695
1696 if (attached_out_rect.y2 > out_rot->y2)
1697 out_rot->y2 = attached_out_rect.y2;
1698
1699 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1700 attached_plane->base.id,
1701 attached_rstate->sequence_id,
1702 attached_rstate->out_src_rect.x1 >> 16,
1703 attached_state->src_w >> 16,
1704 attached_state->src_h >> 16,
1705 attached_state->src_x >> 16,
1706 attached_state->src_y >> 16,
1707 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1708 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1709 attached_rstate->out_src_rect.x1 >> 16,
1710 attached_rstate->out_src_rect.y1 >> 16);
1711 }
1712
1713 rstate->out_xpos = xpos;
1714 rstate->nplane = found;
1715
1716 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1717 plane->base.id, rstate->sequence_id,
1718 rstate->out_xpos, rstate->nplane,
1719 drm_rect_width(in_rot) >> 16,
1720 drm_rect_height(in_rot) >> 16,
1721 in_rot->x1 >> 16, in_rot->y1 >> 16,
1722 drm_rect_width(&rstate->out_rot_rect) >> 16,
1723 drm_rect_height(&rstate->out_rot_rect) >> 16,
1724 rstate->out_rot_rect.x1 >> 16,
1725 rstate->out_rot_rect.y1 >> 16);
1726}
1727
1728/**
1729 * sde_plane_rot_submit_command - commit given state for the rotator stage
1730 * @plane: Pointer to drm plane
1731 * @state: Pointer to the state to be committed
1732 * @hw_cmd: rotator command type
1733 * return: 0 if success; error code otherwise
1734 */
1735static int sde_plane_rot_submit_command(struct drm_plane *plane,
1736 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1737{
1738 struct sde_plane *psde = to_sde_plane(plane);
1739 struct sde_plane_state *pstate = to_sde_plane_state(state);
1740 struct sde_plane_rot_state *rstate = &pstate->rot;
1741 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001742 struct drm_crtc_state *cstate;
1743 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001744 int ret, i;
1745
1746 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1747 SDE_ERROR("invalid parameters\n");
1748 return -EINVAL;
1749 }
1750
Alan Kwong4aacd532017-02-04 18:51:33 -08001751 cstate = _sde_plane_get_crtc_state(state);
1752 if (IS_ERR_OR_NULL(cstate)) {
1753 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1754 return -EINVAL;
1755 }
1756 sde_cstate = to_sde_crtc_state(cstate);
1757
Alan Kwong4dd64c82017-02-04 18:41:51 -08001758 rot_cmd = &rstate->rot_cmd;
1759
1760 rot_cmd->master = (rstate->out_xpos == 0);
1761 rot_cmd->sequence_id = rstate->sequence_id;
1762 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1763 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1764 DEFAULT_REFRESH_RATE;
1765 rot_cmd->rot90 = rstate->rot90;
1766 rot_cmd->hflip = rstate->hflip;
1767 rot_cmd->vflip = rstate->vflip;
1768 rot_cmd->secure = state->fb->flags & DRM_MODE_FB_SECURE ? true : false;
Alan Kwong4aacd532017-02-04 18:51:33 -08001769 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1770 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001771 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1772 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001773 rot_cmd->dst_writeback = psde->sbuf_writeback;
1774
1775 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1776 rot_cmd->video_mode = true;
1777 else
1778 rot_cmd->video_mode = false;
1779
1780 rot_cmd->src_pixel_format = state->fb->pixel_format;
1781 rot_cmd->src_modifier = state->fb->modifier[0];
1782 rot_cmd->src_stride = state->fb->pitches[0];
1783
1784 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1785 if (!rot_cmd->src_format) {
1786 SDE_ERROR("failed to get src format\n");
1787 return -EINVAL;
1788 }
1789
1790 rot_cmd->src_width = state->fb->width;
1791 rot_cmd->src_height = state->fb->height;
1792 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1793 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1794 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1795 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
1796 rot_cmd->dst_rect_x = rstate->out_rot_rect.x1 >> 16;
1797 rot_cmd->dst_rect_y = rstate->out_rot_rect.y1 >> 16;
1798 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1799 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1800
1801 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1802 struct sde_hw_fmt_layout layout;
1803
1804 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Jordan Croused8e96522017-02-13 10:14:16 -07001805 sde_format_populate_layout(rstate->aspace, state->fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001806 &layout);
1807 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1808 rot_cmd->src_iova[i] = layout.plane_addr[i];
1809 rot_cmd->src_len[i] = layout.plane_size[i];
1810 }
1811 rot_cmd->src_planes = layout.num_planes;
1812
1813 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Jordan Croused8e96522017-02-13 10:14:16 -07001814 sde_format_populate_layout(rstate->aspace, rstate->out_fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001815 &layout);
1816 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1817 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1818 rot_cmd->dst_len[i] = layout.plane_size[i];
1819 }
1820 rot_cmd->dst_planes = layout.num_planes;
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001821
1822 /* VBIF remapper settings */
1823 for (i = 0; rstate->rot_hw->caps->xin_count; i++) {
1824 const struct sde_rot_vbif_cfg *cfg =
1825 &rstate->rot_hw->caps->vbif_cfg[i];
1826
1827 _sde_plane_inline_rot_set_qos_remap(plane, cfg);
1828
1829 if (cfg->is_read) {
1830 _sde_plane_inline_rot_set_ot_limit(plane,
1831 state->crtc, cfg, rot_cmd->src_rect_w,
1832 rot_cmd->src_rect_h);
1833 } else {
1834 _sde_plane_inline_rot_set_ot_limit(plane,
1835 state->crtc, cfg, rot_cmd->dst_rect_w,
1836 rot_cmd->dst_rect_h);
1837 }
1838 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001839 }
1840
1841 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
1842 if (ret) {
1843 SDE_ERROR("failed to commit rotator %d\n", ret);
1844 return ret;
1845 }
1846
1847 rstate->out_rotation = rstate->in_rotation;
1848 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1849 DRM_MODE_FB_MODIFIERS : 0;
1850 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1851 rstate->out_fb_format = rot_cmd->dst_format;
1852 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1853
1854 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1855 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1856
1857 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1858 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1859 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1860 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1861 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1862 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1863
1864 if (rot_cmd->rot90)
1865 rstate->out_rotation &= ~DRM_ROTATE_90;
1866
1867 if (rot_cmd->hflip)
1868 rstate->out_rotation &= ~DRM_REFLECT_X;
1869
1870 if (rot_cmd->vflip)
1871 rstate->out_rotation &= ~DRM_REFLECT_Y;
1872
1873 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07001874 "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 -08001875 plane->base.id, rstate->sequence_id, hw_cmd,
1876 rot_cmd->rot90 ? 'r' : '_',
1877 rot_cmd->hflip ? 'h' : '_',
1878 rot_cmd->vflip ? 'v' : '_',
1879 rot_cmd->video_mode ? 'V' : 'C',
1880 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001881 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001882 state->fb->modifier[0],
1883 drm_rect_width(&rstate->in_rot_rect) >> 16,
1884 drm_rect_height(&rstate->in_rot_rect) >> 16,
1885 rstate->in_rot_rect.x1 >> 16,
1886 rstate->in_rot_rect.y1 >> 16);
1887
Dhaval Patel6c666622017-03-21 23:02:59 -07001888 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 -08001889 plane->base.id, rstate->sequence_id, hw_cmd,
1890 rstate->out_rotation,
1891 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001892 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001893 rstate->out_fb_modifier[0],
1894 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
1895 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
1896
1897 return ret;
1898}
1899
1900/**
Clarence Ipd27d9632017-06-14 09:57:26 -04001901 * _sde_plane_rot_get_fb - attempt to get previously allocated fb/fbo
1902 * If an fb/fbo was already created, either from a previous frame or
1903 * from another plane in the current commit cycle, attempt to reuse
1904 * it for this commit cycle as well.
1905 * @plane: Pointer to drm plane
1906 * @cstate: Pointer to crtc state
1907 * @rstate: Pointer to rotator plane state
1908 */
1909static void _sde_plane_rot_get_fb(struct drm_plane *plane,
1910 struct drm_crtc_state *cstate,
1911 struct sde_plane_rot_state *rstate)
1912{
1913 struct sde_kms_fbo *fbo;
1914 struct drm_framebuffer *fb;
1915
1916 if (!plane || !cstate || !rstate)
1917 return;
1918
1919 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1920 (u64) &rstate->rot_hw->base);
1921 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1922 (u64) &rstate->rot_hw->base);
1923 if (fb && fbo) {
1924 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
1925 rstate->sequence_id);
1926 } else if (fbo) {
1927 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
1928 (u64) &rstate->rot_hw->base);
1929 fbo = NULL;
1930 } else if (fb) {
1931 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1932 (u64) &rstate->rot_hw->base);
1933 fb = NULL;
1934 }
1935
1936 rstate->out_fbo = fbo;
1937 rstate->out_fb = fb;
1938}
1939
1940/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08001941 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
1942 * for rotator (pre-sspp) stage
1943 * @plane: Pointer to drm plane
1944 * @new_state: Pointer to new drm plane state
1945 * return: 0 if success; error code otherwise
1946 */
1947static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
1948 struct drm_plane_state *new_state)
1949{
1950 struct drm_framebuffer *fb = new_state->fb;
1951 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
1952 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001953 struct drm_crtc_state *cstate;
Jordan Croused8e96522017-02-13 10:14:16 -07001954 struct sde_kms *kms = _sde_plane_get_kms(plane);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001955 int ret;
1956
1957 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
1958 plane->base.id,
1959 new_rstate->sequence_id, fb ? fb->base.id : 0,
1960 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
1961 sde_plane_crtc_enabled(new_state));
1962
Jordan Croused8e96522017-02-13 10:14:16 -07001963 if (!kms)
1964 return -EINVAL;
1965
Alan Kwong4dd64c82017-02-04 18:41:51 -08001966 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
1967 return 0;
1968
Alan Kwongcdb2f282017-03-18 13:42:06 -07001969 cstate = _sde_plane_get_crtc_state(new_state);
1970 if (IS_ERR(cstate)) {
1971 ret = PTR_ERR(cstate);
1972 SDE_ERROR("invalid crtc state %d\n", ret);
1973 return ret;
1974 }
1975
Alan Kwong4dd64c82017-02-04 18:41:51 -08001976 /* need to re-calc based on all newly validated plane states */
1977 sde_plane_rot_calc_cfg(plane, new_state);
1978
1979 /* check if stream buffer is already attached to rotator */
Clarence Ipd27d9632017-06-14 09:57:26 -04001980 if (sde_plane_enabled(new_state) && !new_rstate->out_fb)
1981 _sde_plane_rot_get_fb(plane, cstate, new_rstate);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001982
1983 /* release buffer if output format configuration changes */
1984 if (new_rstate->out_fb &&
1985 ((new_rstate->out_fb_height != new_rstate->out_fb->height) ||
1986 (new_rstate->out_fb_width != new_rstate->out_fb->width) ||
1987 (new_rstate->out_fb_pixel_format !=
1988 new_rstate->out_fb->pixel_format) ||
1989 (new_rstate->out_fb_modifier[0] !=
1990 new_rstate->out_fb->modifier[0]) ||
1991 (new_rstate->out_fb_flags != new_rstate->out_fb->flags))) {
1992
1993 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
1994 new_rstate->sequence_id);
1995
Alan Kwongcdb2f282017-03-18 13:42:06 -07001996 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
1997 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001998 new_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001999 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2000 (u64) &new_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002001 new_rstate->out_fbo = NULL;
2002 }
2003
2004 /* create new stream buffer if it is not available */
2005 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
2006 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
2007 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
2008
2009 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
2010 new_rstate->sequence_id);
2011
2012 if (new_state->fb->flags & DRM_MODE_FB_SECURE)
Jordan Croused8e96522017-02-13 10:14:16 -07002013 new_rstate->aspace =
2014 kms->aspace[MSM_SMMU_DOMAIN_SECURE];
Alan Kwong4dd64c82017-02-04 18:41:51 -08002015 else
Jordan Croused8e96522017-02-13 10:14:16 -07002016 new_rstate->aspace =
2017 kms->aspace[MSM_SMMU_DOMAIN_UNSECURE];
Alan Kwong4dd64c82017-02-04 18:41:51 -08002018
2019 /* check if out_fb is already attached to rotator */
2020 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
2021 new_rstate->out_fb_pixel_format,
2022 new_rstate->out_fb_modifier,
2023 new_rstate->out_fb_flags);
2024 if (!new_rstate->out_fbo) {
2025 SDE_ERROR("failed to allocate inline buffer object\n");
2026 ret = -EINVAL;
2027 goto error_create_fbo;
2028 }
2029
Alan Kwongcdb2f282017-03-18 13:42:06 -07002030 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2031 (u64) &new_rstate->rot_hw->base,
2032 new_rstate->out_fbo, &fbo_res_ops);
2033 if (ret) {
2034 SDE_ERROR("failed to add crtc resource\n");
2035 goto error_create_fbo_res;
2036 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002037
2038 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
2039 new_rstate->out_fbo);
2040 if (!new_rstate->out_fb) {
2041 SDE_ERROR("failed to create inline framebuffer\n");
2042 ret = -EINVAL;
2043 goto error_create_fb;
2044 }
2045
Alan Kwongcdb2f282017-03-18 13:42:06 -07002046 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2047 (u64) &new_rstate->rot_hw->base,
2048 new_rstate->out_fb, &fb_res_ops);
2049 if (ret) {
2050 SDE_ERROR("failed to add crtc resource %d\n", ret);
2051 goto error_create_fb_res;
2052 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002053 }
2054
2055 /* prepare rotator input buffer */
Jordan Croused8e96522017-02-13 10:14:16 -07002056 ret = msm_framebuffer_prepare(new_state->fb, new_rstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002057 if (ret) {
2058 SDE_ERROR("failed to prepare input framebuffer\n");
2059 goto error_prepare_input_buffer;
2060 }
2061
2062 /* prepare rotator output buffer */
2063 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
2064 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
2065 new_rstate->sequence_id);
2066
2067 ret = msm_framebuffer_prepare(new_rstate->out_fb,
Jordan Croused8e96522017-02-13 10:14:16 -07002068 new_rstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002069 if (ret) {
2070 SDE_ERROR("failed to prepare inline framebuffer\n");
2071 goto error_prepare_output_buffer;
2072 }
2073 }
2074
2075 return 0;
2076
2077error_prepare_output_buffer:
Jordan Croused8e96522017-02-13 10:14:16 -07002078 msm_framebuffer_cleanup(new_state->fb, new_rstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002079error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002080 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2081 (u64) &new_rstate->rot_hw->base);
2082error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002083 new_rstate->out_fb = NULL;
2084error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002085 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2086 (u64) &new_rstate->rot_hw->base);
2087error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002088 new_rstate->out_fbo = NULL;
2089error_create_fbo:
2090 return ret;
2091}
2092
2093/**
2094 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
2095 * rotator (pre-sspp) stage
2096 * @plane: Pointer to drm plane
2097 * @old_state: Pointer to previous drm plane state
2098 * return: none
2099 */
2100static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
2101 struct drm_plane_state *old_state)
2102{
2103 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
2104 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2105 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002106 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002107 int ret;
2108
2109 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2110 old_rstate->sequence_id, old_state->fb->base.id,
2111 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
2112 sde_plane_crtc_enabled(old_state));
2113
2114 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
2115 return;
2116
Alan Kwongcdb2f282017-03-18 13:42:06 -07002117 cstate = _sde_plane_get_crtc_state(old_state);
2118 if (IS_ERR(cstate)) {
2119 ret = PTR_ERR(cstate);
2120 SDE_ERROR("invalid crtc state %d\n", ret);
2121 return;
2122 }
2123
Alan Kwong4dd64c82017-02-04 18:41:51 -08002124 if (sde_plane_crtc_enabled(old_state)) {
2125 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
2126 SDE_HW_ROT_CMD_CLEANUP);
2127 if (ret)
2128 SDE_ERROR("failed to cleanup rotator buffers\n");
2129 }
2130
2131 if (sde_plane_enabled(old_state)) {
2132 if (old_rstate->out_fb) {
2133 msm_framebuffer_cleanup(old_rstate->out_fb,
Jordan Croused8e96522017-02-13 10:14:16 -07002134 old_rstate->aspace);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002135 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2136 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002137 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002138 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2139 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002140 old_rstate->out_fbo = NULL;
2141 }
2142
Jordan Croused8e96522017-02-13 10:14:16 -07002143 msm_framebuffer_cleanup(old_state->fb, old_rstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002144 }
2145}
2146
2147/**
2148 * sde_plane_rot_atomic_check - verify rotator update of the given state
2149 * @plane: Pointer to drm plane
2150 * @state: Pointer to drm plane state to be validated
2151 * return: 0 if success; error code otherwise
2152 */
2153static int sde_plane_rot_atomic_check(struct drm_plane *plane,
2154 struct drm_plane_state *state)
2155{
2156 struct sde_plane *psde;
2157 struct sde_plane_state *pstate, *old_pstate;
2158 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002159 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002160 struct sde_hw_blk *hw_blk;
2161 int i, ret = 0;
2162
2163 if (!plane || !state) {
2164 SDE_ERROR("invalid plane/state\n");
2165 return -EINVAL;
2166 }
2167
2168 psde = to_sde_plane(plane);
2169 pstate = to_sde_plane_state(state);
2170 old_pstate = to_sde_plane_state(plane->state);
2171 rstate = &pstate->rot;
2172 old_rstate = &old_pstate->rot;
Jordan Croused8e96522017-02-13 10:14:16 -07002173 rstate->aspace = psde->aspace;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002174
Alan Kwongcdb2f282017-03-18 13:42:06 -07002175 /* cstate will be null if crtc is disconnected from plane */
2176 cstate = _sde_plane_get_crtc_state(state);
2177 if (IS_ERR(cstate)) {
2178 ret = PTR_ERR(cstate);
2179 SDE_ERROR("invalid crtc state %d\n", ret);
2180 return ret;
2181 }
2182
Alan Kwong4dd64c82017-02-04 18:41:51 -08002183 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2184 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
2185 !!rstate->out_sbuf, !!rstate->rot_hw,
2186 sde_plane_crtc_enabled(state));
2187
2188 rstate->in_rotation = drm_rotation_simplify(
2189 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07002190 DRM_ROTATE_0 | DRM_ROTATE_90 |
2191 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002192 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
2193 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
2194 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
2195 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
2196
Alan Kwongcdb2f282017-03-18 13:42:06 -07002197 if (sde_plane_enabled(state) && rstate->out_sbuf) {
2198 SDE_DEBUG("plane%d.%d acquire rotator\n",
Alan Kwong4dd64c82017-02-04 18:41:51 -08002199 plane->base.id, rstate->sequence_id);
2200
Alan Kwongcdb2f282017-03-18 13:42:06 -07002201 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
2202 (u64) state->fb);
2203 if (!hw_blk) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002204 SDE_ERROR("plane%d no available rotator\n",
2205 plane->base.id);
2206 return -EINVAL;
2207 }
2208
Alan Kwongcdb2f282017-03-18 13:42:06 -07002209 rstate->rot_hw = to_sde_hw_rot(hw_blk);
2210
Alan Kwong4dd64c82017-02-04 18:41:51 -08002211 if (!rstate->rot_hw->ops.commit) {
2212 SDE_ERROR("plane%d invalid rotator ops\n",
2213 plane->base.id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002214 sde_crtc_res_put(cstate,
2215 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002216 rstate->rot_hw = NULL;
2217 return -EINVAL;
2218 }
2219
2220 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002221 } else {
2222 rstate->in_fb = NULL;
2223 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002224 }
2225
2226 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
2227
2228 SDE_DEBUG("plane%d.%d use rotator\n",
2229 plane->base.id, rstate->sequence_id);
2230
2231 sde_plane_rot_calc_cfg(plane, state);
2232
Clarence Ipd27d9632017-06-14 09:57:26 -04002233 /* attempt to reuse stream buffer if already available */
2234 if (sde_plane_enabled(state))
2235 _sde_plane_rot_get_fb(plane, cstate, rstate);
2236
Alan Kwong4dd64c82017-02-04 18:41:51 -08002237 ret = sde_plane_rot_submit_command(plane, state,
2238 SDE_HW_ROT_CMD_VALIDATE);
2239
Clarence Ip4475d582017-04-18 11:36:00 -04002240 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002241
2242 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
2243 rstate->sequence_id);
2244
2245 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04002246 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
2247 rstate->out_fb_modifier[i] = state->fb ?
2248 state->fb->modifier[i] : 0x0;
2249
2250 if (state->fb) {
2251 rstate->out_fb_pixel_format = state->fb->pixel_format;
2252 rstate->out_fb_flags = state->fb->flags;
2253 rstate->out_fb_width = state->fb->width;
2254 rstate->out_fb_height = state->fb->height;
2255 } else {
2256 rstate->out_fb_pixel_format = 0x0;
2257 rstate->out_fb_flags = 0x0;
2258 rstate->out_fb_width = 0;
2259 rstate->out_fb_height = 0;
2260 }
2261
Alan Kwong4dd64c82017-02-04 18:41:51 -08002262 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002263 rstate->out_src_x = state->src_x;
2264 rstate->out_src_y = state->src_y;
2265 rstate->out_src_w = state->src_w;
2266 rstate->out_src_h = state->src_h;
2267
2268 rstate->out_fb_format = NULL;
2269 rstate->out_sbuf = false;
2270 rstate->out_fb = state->fb;
2271 }
2272
2273 return ret;
2274}
2275
2276/**
2277 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2278 * @plane: Pointer to drm plane
2279 * @old_state: Pointer to previous state
2280 * return: none
2281 */
2282static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2283 struct drm_plane_state *old_state)
2284{
2285 struct drm_plane_state *state;
2286 struct sde_plane_state *pstate;
2287 struct sde_plane_rot_state *rstate;
2288
2289 if (!plane || !plane->state) {
2290 SDE_ERROR("invalid plane/state\n");
2291 return;
2292 }
2293
2294 state = plane->state;
2295 pstate = to_sde_plane_state(state);
2296 rstate = &pstate->rot;
2297
2298 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2299 rstate->sequence_id,
2300 !!rstate->out_sbuf, !!rstate->rot_hw,
2301 sde_plane_crtc_enabled(plane->state));
2302
2303 if (!sde_plane_crtc_enabled(state))
2304 return;
2305
2306 if (!rstate->out_sbuf || !rstate->rot_hw)
2307 return;
2308
2309 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
2310}
2311
2312/**
Clarence Ipddbf7752017-05-21 18:07:30 -04002313 * sde_plane_rot_flush - perform final flush related rotator options
2314 * @plane: Pointer to drm plane
2315 * @pstate: Pointer to sde plane state
2316 */
2317static void sde_plane_rot_flush(struct drm_plane *plane,
2318 struct sde_plane_state *pstate)
2319{
2320 if (!plane || !pstate || !pstate->rot.rot_hw ||
2321 !pstate->rot.rot_hw->ops.commit)
2322 return;
2323
2324 pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
2325 &pstate->rot.rot_cmd,
2326 SDE_HW_ROT_CMD_START);
2327}
2328
2329/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002330 * sde_plane_rot_destroy_state - destroy state for rotator stage
2331 * @plane: Pointer to drm plane
2332 * @state: Pointer to state to be destroyed
2333 * return: none
2334 */
2335static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2336 struct drm_plane_state *state)
2337{
2338 struct sde_plane_state *pstate = to_sde_plane_state(state);
2339 struct sde_plane_rot_state *rstate = &pstate->rot;
2340
2341 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2342 rstate->sequence_id,
2343 !!rstate->out_sbuf, !!rstate->rot_hw,
2344 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002345}
2346
2347/**
2348 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2349 * @plane: Pointer to drm plane
2350 * @new_state: Pointer to duplicated state
2351 * return: 0 if success; error code otherwise
2352 */
2353static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2354 struct drm_plane_state *new_state)
2355{
2356 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2357 struct sde_plane_rot_state *rstate = &pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002358 struct drm_crtc_state *cstate;
2359 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002360
2361 rstate->sequence_id++;
2362
2363 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2364 rstate->sequence_id,
2365 !!rstate->out_sbuf, !!rstate->rot_hw);
2366
Alan Kwongcdb2f282017-03-18 13:42:06 -07002367 cstate = _sde_plane_get_crtc_state(new_state);
2368 if (IS_ERR(cstate)) {
2369 ret = PTR_ERR(cstate);
2370 SDE_ERROR("invalid crtc state %d\n", ret);
2371 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002372 }
2373
Alan Kwongcdb2f282017-03-18 13:42:06 -07002374 if (rstate->rot_hw && cstate)
2375 sde_crtc_res_get(cstate, SDE_HW_BLK_ROT, (u64) rstate->in_fb);
2376 else if (rstate->rot_hw && !cstate)
2377 SDE_ERROR("plane%d.%d zombie rotator hw\n",
2378 plane->base.id, rstate->sequence_id);
2379
Alan Kwong4dd64c82017-02-04 18:41:51 -08002380 rstate->out_fb = NULL;
2381 rstate->out_fbo = NULL;
2382
2383 return 0;
2384}
2385
2386/**
2387 * sde_plane_rot_install_caps - install plane rotator capabilities
2388 * @plane: Pointer to drm plane
2389 * return: none
2390 */
2391static void sde_plane_rot_install_caps(struct drm_plane *plane)
2392{
2393 struct sde_plane *psde = to_sde_plane(plane);
2394 const struct sde_format_extended *format_list;
2395 struct sde_kms_info *info;
2396 struct sde_hw_rot *rot_hw;
2397 const char *downscale_caps;
2398
2399 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2400 !psde->catalog->rot_count)
2401 return;
2402
2403 if (psde->blob_rot_caps)
2404 return;
2405
2406 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2407 if (!info)
2408 return;
2409
2410 rot_hw = sde_hw_rot_get(NULL);
2411 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2412 !rot_hw->ops.get_downscale_caps) {
2413 SDE_ERROR("invalid rotator hw\n");
2414 goto error_rot;
2415 }
2416
2417 sde_kms_info_reset(info);
2418
2419 format_list = rot_hw->ops.get_format_caps(rot_hw);
2420 if (format_list) {
2421 sde_kms_info_start(info, "pixel_formats");
2422 while (format_list->fourcc_format) {
2423 sde_kms_info_append_format(info,
2424 format_list->fourcc_format,
2425 format_list->modifier);
2426 ++format_list;
2427 }
2428 sde_kms_info_stop(info);
2429 }
2430
2431 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2432 if (downscale_caps) {
2433 sde_kms_info_start(info, "downscale_ratios");
2434 sde_kms_info_append(info, downscale_caps);
2435 sde_kms_info_stop(info);
2436 }
2437
2438 if (rot_hw->ops.get_cache_size)
2439 sde_kms_info_add_keyint(info, "cache_size",
2440 rot_hw->ops.get_cache_size(rot_hw));
2441
Alan Kwong1a915802017-03-31 12:55:46 -07002442 if (rot_hw->ops.get_maxlinewidth)
2443 sde_kms_info_add_keyint(info, "max_linewidth",
2444 rot_hw->ops.get_maxlinewidth(rot_hw));
2445
Alan Kwong4dd64c82017-02-04 18:41:51 -08002446 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
Narendra Muppalla22d17252017-05-31 15:13:39 -07002447 info->data, SDE_KMS_INFO_DATALEN(info),
2448 PLANE_PROP_ROT_CAPS_V1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002449
2450 sde_hw_rot_put(rot_hw);
2451error_rot:
2452 kfree(info);
2453}
2454
2455/**
2456 * sde_plane_rot_install_properties - install plane rotator properties
2457 * @plane: Pointer to drm plane
2458 * @catalog: Pointer to mdss configuration
2459 * return: none
2460 */
2461static void sde_plane_rot_install_properties(struct drm_plane *plane,
2462 struct sde_mdss_cfg *catalog)
2463{
2464 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002465 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2466 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002467
2468 if (!plane || !psde) {
2469 SDE_ERROR("invalid plane\n");
2470 return;
2471 } else if (!catalog) {
2472 SDE_ERROR("invalid catalog\n");
2473 return;
2474 }
2475
2476 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2477 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2478 DRM_ROTATE_180 | DRM_ROTATE_270;
2479
2480 msm_property_install_rotation(&psde->property_info,
2481 supported_rotations, PLANE_PROP_ROTATION);
2482
2483 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2484 return;
2485
2486 msm_property_install_range(&psde->property_info, "rot_dst_x",
2487 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2488 msm_property_install_range(&psde->property_info, "rot_dst_y",
2489 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2490 msm_property_install_range(&psde->property_info, "rot_dst_w",
2491 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2492 msm_property_install_range(&psde->property_info, "rot_dst_h",
2493 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2494 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2495 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2496}
2497
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002498void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002499{
Clarence Ipcb410d42016-06-26 22:52:33 -04002500 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002501
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002502 if (!drm_state)
2503 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002504
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002505 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002506
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002507 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2508 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002509}
2510
2511int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2512{
2513 struct sde_plane_state *pstate[R_MAX];
2514 const struct drm_plane_state *drm_state[R_MAX];
2515 struct sde_rect src[R_MAX], dst[R_MAX];
2516 struct sde_plane *sde_plane[R_MAX];
2517 const struct sde_format *fmt[R_MAX];
2518 bool q16_data = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002519 int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
2520 bool parallel_fetch_qualified = true;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002521
2522 for (i = 0; i < R_MAX; i++) {
2523 const struct msm_format *msm_fmt;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002524 int width_threshold;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002525
2526 drm_state[i] = i ? plane->r1 : plane->r0;
2527 pstate[i] = to_sde_plane_state(drm_state[i]);
2528 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2529
2530 if (pstate[i] == NULL) {
2531 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2532 drm_state[i]->plane->base.id);
2533 return -EINVAL;
2534 }
2535
2536 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2537 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2538 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2539 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2540 drm_state[i]->crtc_h, !q16_data);
2541
2542 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2543 SDE_ERROR_PLANE(sde_plane[i],
2544 "scaling is not supported in multirect mode\n");
2545 return -EINVAL;
2546 }
2547
2548 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2549 fmt[i] = to_sde_format(msm_fmt);
2550 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2551 SDE_ERROR_PLANE(sde_plane[i],
2552 "Unsupported format for multirect mode\n");
2553 return -EINVAL;
2554 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002555
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002556 /**
2557 * SSPP PD_MEM is split half - one for each RECT.
2558 * Tiled formats need 5 lines of buffering while fetching
2559 * whereas linear formats need only 2 lines.
2560 * So we cannot support more than half of the supported SSPP
2561 * width for tiled formats.
2562 */
2563 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
2564 if (SDE_FORMAT_IS_UBWC(fmt[i]))
2565 width_threshold /= 2;
2566
2567 if (parallel_fetch_qualified && src[i].w > width_threshold)
2568 parallel_fetch_qualified = false;
2569
2570 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002571
2572 /* Validate RECT's and set the mode */
2573
2574 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002575 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002576 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2577 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002578
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002579 goto done;
2580 }
2581
2582 /* TIME_MX Mode */
2583 if (SDE_FORMAT_IS_UBWC(fmt[R0]))
2584 buffer_lines = 2 * fmt[R0]->tile_height;
2585
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002586 if ((dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) ||
2587 (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines)) {
2588 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2589 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002590 } else {
2591 SDE_ERROR(
2592 "No multirect mode possible for the planes (%d - %d)\n",
2593 drm_state[R0]->plane->base.id,
2594 drm_state[R1]->plane->base.id);
2595 return -EINVAL;
2596 }
2597
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002598done:
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002599 if (sde_plane[R0]->is_virtual) {
2600 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2601 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2602 } else {
2603 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2604 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2605 };
2606
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002607 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2608 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2609 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2610 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002611 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002612}
2613
Alan Kwong4dd64c82017-02-04 18:41:51 -08002614/**
2615 * sde_plane_get_ctl_flush - get control flush for the given plane
2616 * @plane: Pointer to drm plane structure
2617 * @ctl: Pointer to hardware control driver
Clarence Ip7e5f0002017-05-29 18:46:56 -04002618 * @flush_sspp: Pointer to sspp flush control word
2619 * @flush_rot: Pointer to rotator flush control word
Alan Kwong4dd64c82017-02-04 18:41:51 -08002620 */
2621void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
Clarence Ip7e5f0002017-05-29 18:46:56 -04002622 u32 *flush_sspp, u32 *flush_rot)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002623{
2624 struct sde_plane_state *pstate;
2625 struct sde_plane_rot_state *rstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002626
Clarence Ip7e5f0002017-05-29 18:46:56 -04002627 if (!plane || !flush_sspp) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002628 SDE_ERROR("invalid parameters\n");
2629 return;
2630 }
2631
2632 pstate = to_sde_plane_state(plane->state);
2633 rstate = &pstate->rot;
2634
Clarence Ip7e5f0002017-05-29 18:46:56 -04002635 *flush_sspp = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002636
Clarence Ip7e5f0002017-05-29 18:46:56 -04002637 if (!flush_rot)
2638 return;
2639
2640 *flush_rot = 0x0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002641 if (sde_plane_is_sbuf_mode(plane, NULL) && rstate->rot_hw &&
2642 ctl->ops.get_bitmask_rot)
Clarence Ip7e5f0002017-05-29 18:46:56 -04002643 ctl->ops.get_bitmask_rot(ctl, flush_rot, rstate->rot_hw->idx);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002644}
2645
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002646static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002647 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002648{
2649 struct drm_framebuffer *fb = new_state->fb;
2650 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002651 struct sde_plane_rot_state *new_rstate;
Alan Kwong4a5bd782017-06-09 15:20:52 -04002652 struct sde_hw_fmt_layout layout;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002653 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002654
2655 if (!new_state->fb)
2656 return 0;
2657
Clarence Ip13a8cf42016-09-29 17:27:47 -04002658 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002659
2660 ret = sde_plane_rot_prepare_fb(plane, new_state);
2661 if (ret) {
2662 SDE_ERROR("failed to prepare rot framebuffer\n");
2663 return ret;
2664 }
2665
2666 new_rstate = &to_sde_plane_state(new_state)->rot;
2667
Jordan Croused8e96522017-02-13 10:14:16 -07002668 ret = msm_framebuffer_prepare(new_rstate->out_fb, psde->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002669 if (ret) {
2670 SDE_ERROR("failed to prepare framebuffer\n");
2671 return ret;
2672 }
2673
Alan Kwong4a5bd782017-06-09 15:20:52 -04002674 /* validate framebuffer layout before commit */
Jordan Croused8e96522017-02-13 10:14:16 -07002675 ret = sde_format_populate_layout(psde->aspace,
Alan Kwong4a5bd782017-06-09 15:20:52 -04002676 new_rstate->out_fb, &layout);
2677 if (ret) {
2678 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
2679 return ret;
2680 }
2681
Alan Kwong4dd64c82017-02-04 18:41:51 -08002682 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002683}
2684
2685static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002686 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002687{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002688 struct sde_plane *psde = to_sde_plane(plane);
2689 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002690
Alan Kwong4dd64c82017-02-04 18:41:51 -08002691 if (!old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002692 return;
2693
Alan Kwong4dd64c82017-02-04 18:41:51 -08002694 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2695
2696 old_rstate = &to_sde_plane_state(old_state)->rot;
2697
Jordan Croused8e96522017-02-13 10:14:16 -07002698 msm_framebuffer_cleanup(old_rstate->out_fb, old_rstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002699
2700 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002701}
2702
Alan Kwong4dd64c82017-02-04 18:41:51 -08002703static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002704 struct drm_plane_state *state,
2705 struct drm_plane_state *old_state)
2706{
2707 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002708 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002709 struct sde_plane_rot_state *rstate = &pstate->rot;
2710 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2711 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002712
Dhaval Patel47302cf2016-08-18 15:04:28 -07002713 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002714 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002715 return;
2716
Clarence Ip282dad62016-09-27 17:07:35 -04002717 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2718 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002719 SDE_DEBUG_PLANE(psde,
2720 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002721 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002722 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002723 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002724 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002725 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2726 pstate->multirect_mode != old_pstate->multirect_mode) {
2727 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2728 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002729 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2730 rstate->out_src_h != old_rstate->out_src_h ||
2731 rstate->out_src_x != old_rstate->out_src_x ||
2732 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002733 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002734 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002735 } else if (state->crtc_w != old_state->crtc_w ||
2736 state->crtc_h != old_state->crtc_h ||
2737 state->crtc_x != old_state->crtc_x ||
2738 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002739 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002740 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002741 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2742 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2743 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2744 pstate->excl_rect.y != old_pstate->excl_rect.y) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07002745 SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002746 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002747 }
2748
Alan Kwong4dd64c82017-02-04 18:41:51 -08002749 fb = rstate->out_fb;
2750 old_fb = old_rstate->out_fb;
2751
2752 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002753 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002754 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002755 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002756 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002757 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002758 uint64_t *new_mods = fb->modifier;
2759 uint64_t *old_mods = old_fb->modifier;
2760 uint32_t *new_pitches = fb->pitches;
2761 uint32_t *old_pitches = old_fb->pitches;
2762 uint32_t *new_offset = fb->offsets;
2763 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002764 int i;
2765
Alan Kwong4dd64c82017-02-04 18:41:51 -08002766 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002767 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002768 SDE_DEBUG_PLANE(psde,
2769 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002770 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002771 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002772 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2773 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002774 break;
2775 }
2776 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002777 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002778 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002779 SDE_DEBUG_PLANE(psde,
2780 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002781 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002782 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002783 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002784 break;
2785 }
2786 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002787 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002788 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002789 SDE_DEBUG_PLANE(psde,
2790 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002791 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002792 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002793 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2794 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002795 break;
2796 }
2797 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002798 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002799}
2800
Clarence Ip059c8c32017-06-06 17:15:54 -04002801static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
2802 const struct sde_format *fmt,
2803 uint32_t img_w, uint32_t img_h,
2804 uint32_t src_w, uint32_t src_h,
2805 uint32_t deci_w, uint32_t deci_h)
2806{
2807 int i;
2808
2809 if (!psde || !fmt) {
2810 SDE_ERROR_PLANE(psde, "invalid arguments\n");
2811 return -EINVAL;
2812 }
2813
2814 /* don't run checks unless scaler data was changed */
2815 if (psde->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK ||
2816 !psde->scaler3_cfg)
2817 return 0;
2818
2819 psde->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
2820
2821 for (i = 0; i < SDE_MAX_PLANES; i++) {
2822 uint32_t hor_req_pixels, hor_fetch_pixels;
2823 uint32_t vert_req_pixels, vert_fetch_pixels;
2824 uint32_t src_w_tmp, src_h_tmp;
2825
2826 /* re-use color plane 1's config for plane 2 */
2827 if (i == 2)
2828 continue;
2829
2830 src_w_tmp = src_w;
2831 src_h_tmp = src_h;
2832
2833 /*
2834 * For chroma plane, width is half for the following sub sampled
2835 * formats. Except in case of decimation, where hardware avoids
2836 * 1 line of decimation instead of downsampling.
2837 */
2838 if (i == 1) {
2839 if (!deci_w &&
2840 (fmt->chroma_sample == SDE_CHROMA_420 ||
2841 fmt->chroma_sample == SDE_CHROMA_H2V1))
2842 src_w_tmp >>= 1;
2843 if (!deci_h &&
2844 (fmt->chroma_sample == SDE_CHROMA_420 ||
2845 fmt->chroma_sample == SDE_CHROMA_H1V2))
2846 src_h_tmp >>= 1;
2847 }
2848
2849 hor_req_pixels = psde->pixel_ext.roi_w[i];
2850 vert_req_pixels = psde->pixel_ext.roi_h[i];
2851
2852 hor_fetch_pixels = DECIMATED_DIMENSION(src_w_tmp +
2853 (int8_t)(psde->pixel_ext.left_ftch[i] & 0xFF) +
2854 (int8_t)(psde->pixel_ext.right_ftch[i] & 0xFF),
2855 deci_w);
2856 vert_fetch_pixels = DECIMATED_DIMENSION(src_h_tmp +
2857 (int8_t)(psde->pixel_ext.top_ftch[i] & 0xFF) +
2858 (int8_t)(psde->pixel_ext.btm_ftch[i] & 0xFF),
2859 deci_h);
2860
2861 if ((hor_req_pixels != hor_fetch_pixels) ||
2862 (hor_fetch_pixels > img_w) ||
2863 (vert_req_pixels != vert_fetch_pixels) ||
2864 (vert_fetch_pixels > img_h)) {
2865 SDE_ERROR_PLANE(psde,
2866 "req %d/%d, fetch %d/%d, src %dx%d\n",
2867 hor_req_pixels, vert_req_pixels,
2868 hor_fetch_pixels, vert_fetch_pixels,
Clarence Ip3b1e2c62017-06-14 11:20:44 -04002869 img_w, img_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04002870 return -EINVAL;
2871 }
2872
2873 /*
2874 * Alpha plane can only be scaled using bilinear or pixel
2875 * repeat/drop, src_width and src_height are only specified
2876 * for Y and UV plane
2877 */
2878 if (i != 3 &&
2879 (hor_req_pixels != psde->scaler3_cfg->src_width[i] ||
2880 vert_req_pixels != psde->scaler3_cfg->src_height[i])) {
2881 SDE_ERROR_PLANE(psde,
2882 "roi[%d] %d/%d, scaler src %dx%d, src %dx%d\n",
2883 i, psde->pixel_ext.roi_w[i],
2884 psde->pixel_ext.roi_h[i],
2885 psde->scaler3_cfg->src_width[i],
2886 psde->scaler3_cfg->src_height[i],
2887 src_w, src_h);
2888 return -EINVAL;
2889 }
2890 }
2891
2892 psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
2893 return 0;
2894}
2895
Alan Kwong4dd64c82017-02-04 18:41:51 -08002896static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002897 struct drm_plane_state *state)
2898{
Clarence Ipdedbba92016-09-27 17:43:10 -04002899 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04002900 struct sde_plane *psde;
2901 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002902 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04002903 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002904 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04002905 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002906 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
2907 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04002908
2909 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002910 SDE_ERROR("invalid arg(s), plane %d state %d\n",
2911 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04002912 ret = -EINVAL;
2913 goto exit;
2914 }
2915
2916 psde = to_sde_plane(plane);
2917 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002918 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04002919
2920 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002921 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04002922 ret = -EINVAL;
2923 goto exit;
2924 }
2925
Clarence Ipdedbba92016-09-27 17:43:10 -04002926 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
2927 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04002928
2929 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002930 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
2931 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07002932 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
2933 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04002934
Dhaval Patel47302cf2016-08-18 15:04:28 -07002935 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
2936 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04002937
Dhaval Patel47302cf2016-08-18 15:04:28 -07002938 max_upscale = psde->pipe_sblk->maxupscale;
2939 max_downscale = psde->pipe_sblk->maxdwnscale;
2940 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04002941
Clarence Ip13a8cf42016-09-29 17:27:47 -04002942 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002943 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002944
Dhaval Patel47302cf2016-08-18 15:04:28 -07002945 if (!sde_plane_enabled(state))
2946 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04002947
Alan Kwong4dd64c82017-02-04 18:41:51 -08002948 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002949 "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 -08002950 plane->base.id, rstate->sequence_id,
2951 rstate->out_rotation,
2952 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002953 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002954 rstate->out_fb_modifier[0],
2955 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2956 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
2957 state->crtc_w, state->crtc_h,
2958 state->crtc_x, state->crtc_y);
2959
Dhaval Patel47302cf2016-08-18 15:04:28 -07002960 fmt = to_sde_format(msm_framebuffer_format(state->fb));
2961
2962 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
2963
2964 if (SDE_FORMAT_IS_YUV(fmt) &&
2965 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04002966 !(psde->features & (BIT(SDE_SSPP_CSC)
2967 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002968 SDE_ERROR_PLANE(psde,
2969 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07002970 ret = -EINVAL;
2971
2972 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08002973 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
2974 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07002975 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08002976 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
2977 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002978 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002979 src.x, src.y, src.w, src.h);
2980 ret = -E2BIG;
2981
2982 /* valid yuv image */
2983 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
2984 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002985 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002986 src.x, src.y, src.w, src.h);
2987 ret = -EINVAL;
2988
2989 /* min dst support */
2990 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002991 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07002992 dst.x, dst.y, dst.w, dst.h);
2993 ret = -EINVAL;
2994
2995 /* decimation validation */
2996 } else if (deci_w || deci_h) {
2997 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
2998 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002999 SDE_ERROR_PLANE(psde,
3000 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003001 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003002 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003003 SDE_ERROR_PLANE(psde,
3004 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003005 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003006 }
3007
Dhaval Patel47302cf2016-08-18 15:04:28 -07003008 } else if (!(psde->features & SDE_SSPP_SCALER) &&
3009 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003010 SDE_ERROR_PLANE(psde,
3011 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003012 src.w, src.h, dst.w, dst.h);
3013 ret = -EINVAL;
3014
3015 /* check decimated source width */
3016 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003017 SDE_ERROR_PLANE(psde,
3018 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003019 src.w, src_deci_w, max_linewidth);
3020 ret = -E2BIG;
3021
3022 /* check max scaler capability */
3023 } else if (((src_deci_w * max_upscale) < dst.w) ||
3024 ((src_deci_h * max_upscale) < dst.h) ||
3025 ((dst.w * max_downscale) < src_deci_w) ||
3026 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003027 SDE_ERROR_PLANE(psde,
3028 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003029 src_deci_w, src_deci_h, dst.w, dst.h);
3030 ret = -E2BIG;
Clarence Ip059c8c32017-06-06 17:15:54 -04003031 } else if (_sde_plane_validate_scaler_v2(psde, fmt,
3032 rstate->out_fb_width,
3033 rstate->out_fb_height,
3034 src.w, src.h, deci_w, deci_h)) {
3035 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003036 }
3037
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003038 /* check excl rect configs */
Clarence Ip059c8c32017-06-06 17:15:54 -04003039 if (!ret && pstate->excl_rect.w && pstate->excl_rect.h) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003040 struct sde_rect intersect;
3041
3042 /*
3043 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003044 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003045 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05003046 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003047 if (intersect.w != pstate->excl_rect.w ||
3048 intersect.h != pstate->excl_rect.h ||
3049 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003050 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07003051 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003052 pstate->excl_rect.x, pstate->excl_rect.y,
3053 pstate->excl_rect.w, pstate->excl_rect.h,
3054 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07003055 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003056 ret = -EINVAL;
3057 }
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003058 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3059 pstate->excl_rect.x, pstate->excl_rect.y,
3060 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003061 }
3062
Dhaval Patel47302cf2016-08-18 15:04:28 -07003063modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003064 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08003065 _sde_plane_sspp_atomic_check_mode_changed(psde,
3066 state, plane->state);
3067exit:
3068 return ret;
3069}
3070
3071static int sde_plane_atomic_check(struct drm_plane *plane,
3072 struct drm_plane_state *state)
3073{
3074 int ret = 0;
3075 struct sde_plane *psde;
3076 struct sde_plane_state *pstate;
3077
3078 if (!plane || !state) {
3079 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3080 plane != 0, state != 0);
3081 ret = -EINVAL;
3082 goto exit;
3083 }
3084
3085 psde = to_sde_plane(plane);
3086 pstate = to_sde_plane_state(state);
3087
3088 SDE_DEBUG_PLANE(psde, "\n");
3089
3090 ret = sde_plane_rot_atomic_check(plane, state);
3091 if (ret)
3092 goto exit;
3093
3094 ret = sde_plane_sspp_atomic_check(plane, state);
3095
Clarence Ipdbde9832016-06-26 09:48:36 -04003096exit:
3097 return ret;
3098}
3099
Clarence Ipcae1bb62016-07-07 12:07:13 -04003100/**
3101 * sde_plane_flush - final plane operations before commit flush
3102 * @plane: Pointer to drm plane structure
3103 */
3104void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04003105{
Clarence Ipcae1bb62016-07-07 12:07:13 -04003106 struct sde_plane *psde;
Clarence Ipddbf7752017-05-21 18:07:30 -04003107 struct sde_plane_state *pstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -04003108
Clarence Ipddbf7752017-05-21 18:07:30 -04003109 if (!plane || !plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003110 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04003111 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003112 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04003113
3114 psde = to_sde_plane(plane);
Clarence Ipddbf7752017-05-21 18:07:30 -04003115 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003116
3117 /*
3118 * These updates have to be done immediately before the plane flush
3119 * timing, and may not be moved to the atomic_update/mode_set functions.
3120 */
3121 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05003122 /* force white frame with 100% alpha pipe output on error */
3123 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003124 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
3125 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04003126 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003127 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
3128 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
3129
Clarence Ip56902792017-03-17 15:22:07 -04003130 /* force black color fill during suspend */
3131 if (msm_is_suspend_state(plane->dev) && suspend_blank)
3132 _sde_plane_color_fill(psde, 0x0, 0x0);
3133
Clarence Ipcae1bb62016-07-07 12:07:13 -04003134 /* flag h/w flush complete */
3135 if (plane->state)
Clarence Ipddbf7752017-05-21 18:07:30 -04003136 pstate->pending = false;
3137
3138 /* signal inline rotator start */
3139 sde_plane_rot_flush(plane, pstate);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003140}
3141
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003142static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
3143 struct drm_plane_state *old_state)
3144{
3145 uint32_t nplanes, src_flags;
3146 struct sde_plane *psde;
3147 struct drm_plane_state *state;
3148 struct sde_plane_state *pstate;
3149 struct sde_plane_state *old_pstate;
3150 struct sde_plane_rot_state *rstate;
3151 const struct sde_format *fmt;
3152 struct drm_crtc *crtc;
3153 struct drm_framebuffer *fb;
3154 struct sde_rect src, dst;
3155 const struct sde_rect *crtc_roi;
3156 bool q16_data = true;
3157 int idx;
3158
3159 if (!plane) {
3160 SDE_ERROR("invalid plane\n");
3161 return -EINVAL;
3162 } else if (!plane->state) {
3163 SDE_ERROR("invalid plane state\n");
3164 return -EINVAL;
3165 } else if (!old_state) {
3166 SDE_ERROR("invalid old state\n");
3167 return -EINVAL;
3168 }
3169
3170 psde = to_sde_plane(plane);
3171 state = plane->state;
3172
3173 pstate = to_sde_plane_state(state);
3174 rstate = &pstate->rot;
3175
3176 old_pstate = to_sde_plane_state(old_state);
3177
3178 crtc = state->crtc;
3179 fb = rstate->out_fb;
3180 if (!crtc || !fb) {
3181 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
3182 crtc != 0, fb != 0);
3183 return -EINVAL;
3184 }
3185 fmt = to_sde_format(msm_framebuffer_format(fb));
3186 nplanes = fmt->num_planes;
3187
3188 SDE_DEBUG(
3189 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
3190 plane->base.id, rstate->sequence_id,
3191 rstate->out_fb_width, rstate->out_fb_height,
3192 (char *) &rstate->out_fb_pixel_format,
3193 rstate->out_fb_modifier[0],
3194 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3195 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3196 rstate->out_rotation,
3197 state->crtc_w, state->crtc_h,
3198 state->crtc_x, state->crtc_y);
3199
3200 /* force reprogramming of all the parameters, if the flag is set */
3201 if (psde->revalidate) {
3202 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
3203 plane->base.id);
3204 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3205 psde->revalidate = false;
3206 }
3207
3208 /* determine what needs to be refreshed */
3209 while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
3210 switch (idx) {
3211 case PLANE_PROP_SCALER_V1:
3212 case PLANE_PROP_SCALER_V2:
Clarence Ip059c8c32017-06-06 17:15:54 -04003213 case PLANE_PROP_SCALER_LUT_ED:
3214 case PLANE_PROP_SCALER_LUT_CIR:
3215 case PLANE_PROP_SCALER_LUT_SEP:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003216 case PLANE_PROP_H_DECIMATE:
3217 case PLANE_PROP_V_DECIMATE:
3218 case PLANE_PROP_SRC_CONFIG:
3219 case PLANE_PROP_ZPOS:
3220 case PLANE_PROP_EXCL_RECT_V1:
3221 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3222 break;
3223 case PLANE_PROP_CSC_V1:
3224 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3225 break;
3226 case PLANE_PROP_COLOR_FILL:
3227 /* potentially need to refresh everything */
3228 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3229 break;
3230 case PLANE_PROP_ROTATION:
3231 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3232 break;
3233 case PLANE_PROP_INFO:
3234 case PLANE_PROP_ALPHA:
3235 case PLANE_PROP_INPUT_FENCE:
3236 case PLANE_PROP_BLEND_OP:
3237 /* no special action required */
3238 break;
Alan Kwong2349d742017-04-20 08:27:30 -07003239 case PLANE_PROP_PREFILL_SIZE:
3240 case PLANE_PROP_PREFILL_TIME:
3241 pstate->dirty |= SDE_PLANE_DIRTY_PERF;
3242 break;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003243 case PLANE_PROP_ROT_DST_X:
3244 case PLANE_PROP_ROT_DST_Y:
3245 case PLANE_PROP_ROT_DST_W:
3246 case PLANE_PROP_ROT_DST_H:
3247 /* handled by rotator atomic update */
3248 break;
3249 default:
3250 /* unknown property, refresh everything */
3251 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
3252 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
3253 break;
3254 }
3255 }
3256
3257 /**
3258 * since plane_atomic_check is invoked before crtc_atomic_check
3259 * in the commit sequence, all the parameters for updating the
3260 * plane dirty flag will not be available during
3261 * plane_atomic_check as some features params are updated
3262 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
3263 * before sspp update.
3264 */
3265 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
3266 old_state);
3267
3268 /* re-program the output rects always in the case of partial update */
3269 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
3270 if (!sde_kms_rect_is_null(crtc_roi))
3271 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3272
3273 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
3274 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
3275
3276 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
3277
3278 /* early out if nothing dirty */
3279 if (!pstate->dirty)
3280 return 0;
3281 pstate->pending = true;
3282
3283 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
3284 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3285
3286 /* update roi config */
3287 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
3288 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3289 rstate->out_src_w, rstate->out_src_h, q16_data);
3290 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
3291 state->crtc_w, state->crtc_h, !q16_data);
3292
3293 SDE_DEBUG_PLANE(psde,
3294 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
3295 fb->base.id, src.x, src.y, src.w, src.h,
3296 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
3297 (char *)&fmt->base.pixel_format,
3298 SDE_FORMAT_IS_UBWC(fmt));
3299
3300 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
3301 BIT(SDE_DRM_DEINTERLACE)) {
3302 SDE_DEBUG_PLANE(psde, "deinterlace\n");
3303 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
3304 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
3305 src.h /= 2;
3306 src.y = DIV_ROUND_UP(src.y, 2);
3307 src.y &= ~0x1;
3308 }
3309
3310 /*
3311 * adjust layer mixer position of the sspp in the presence
3312 * of a partial update to the active lm origin
3313 */
3314 dst.x -= crtc_roi->x;
3315 dst.y -= crtc_roi->y;
3316
3317 psde->pipe_cfg.src_rect = src;
3318 psde->pipe_cfg.dst_rect = dst;
3319
3320 _sde_plane_setup_scaler(psde, fmt, pstate);
3321
3322 /* check for color fill */
3323 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
3324 PLANE_PROP_COLOR_FILL);
3325 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
3326 /* skip remaining processing on color fill */
3327 pstate->dirty = 0x0;
3328 } else if (psde->pipe_hw->ops.setup_rects) {
3329 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
3330 &psde->pipe_cfg,
3331 pstate->multirect_index);
3332 }
3333
Jeykumar Sankaran0532e0a2017-06-11 20:34:44 -07003334 if (psde->pipe_hw->ops.setup_pe &&
3335 (pstate->multirect_index != SDE_SSPP_RECT_1))
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003336 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
3337 &psde->pixel_ext);
3338
3339 /**
3340 * when programmed in multirect mode, scalar block will be
3341 * bypassed. Still we need to update alpha and bitwidth
3342 * ONLY for RECT0
3343 */
3344 if (psde->pipe_hw->ops.setup_scaler &&
3345 pstate->multirect_index != SDE_SSPP_RECT_1)
3346 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
3347 &psde->pipe_cfg, &psde->pixel_ext,
3348 psde->scaler3_cfg);
3349
3350 /* update excl rect */
3351 if (psde->pipe_hw->ops.setup_excl_rect)
3352 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
3353 &pstate->excl_rect,
3354 pstate->multirect_index);
3355
3356 if (psde->pipe_hw->ops.setup_multirect)
3357 psde->pipe_hw->ops.setup_multirect(
3358 psde->pipe_hw,
3359 pstate->multirect_index,
3360 pstate->multirect_mode);
3361 }
3362
3363 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
3364 psde->pipe_hw->ops.setup_format) {
3365 src_flags = 0x0;
3366 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
3367 if (rstate->out_rotation & DRM_REFLECT_X)
3368 src_flags |= SDE_SSPP_FLIP_LR;
3369 if (rstate->out_rotation & DRM_REFLECT_Y)
3370 src_flags |= SDE_SSPP_FLIP_UD;
3371
3372 /* update format */
3373 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
3374 pstate->multirect_index);
3375
Alan Kwong143f50c2017-04-28 07:34:28 -07003376 if (psde->pipe_hw->ops.setup_cdp) {
3377 struct sde_hw_pipe_cdp_cfg *cdp_cfg = &pstate->cdp_cfg;
3378
3379 memset(cdp_cfg, 0, sizeof(struct sde_hw_pipe_cdp_cfg));
3380
3381 cdp_cfg->enable = psde->catalog->perf.cdp_cfg
3382 [SDE_PERF_CDP_USAGE_RT].rd_enable;
3383 cdp_cfg->ubwc_meta_enable =
3384 SDE_FORMAT_IS_UBWC(fmt);
3385 cdp_cfg->tile_amortize_enable =
3386 SDE_FORMAT_IS_UBWC(fmt) ||
3387 SDE_FORMAT_IS_TILE(fmt);
3388 cdp_cfg->preload_ahead = SDE_WB_CDP_PRELOAD_AHEAD_64;
3389
3390 psde->pipe_hw->ops.setup_cdp(psde->pipe_hw, cdp_cfg);
3391 }
3392
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003393 if (psde->pipe_hw->ops.setup_sys_cache) {
3394 if (rstate->out_sbuf) {
3395 if (rstate->nplane < 2)
3396 pstate->sc_cfg.op_mode =
3397 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
3398 else if (rstate->out_xpos == 0)
3399 pstate->sc_cfg.op_mode =
3400 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
3401 else
3402 pstate->sc_cfg.op_mode =
3403 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
3404
3405 pstate->sc_cfg.rd_en = true;
3406 pstate->sc_cfg.rd_scid =
3407 rstate->rot_hw->caps->scid;
3408 pstate->sc_cfg.rd_noallocate = true;
3409 pstate->sc_cfg.rd_op_type =
3410 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3411 } else {
3412 pstate->sc_cfg.op_mode =
3413 SDE_PIPE_SC_OP_MODE_OFFLINE;
3414 pstate->sc_cfg.rd_en = false;
3415 pstate->sc_cfg.rd_scid = 0;
Clarence Ipd02440b2017-05-21 18:10:01 -04003416 pstate->sc_cfg.rd_noallocate = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003417 pstate->sc_cfg.rd_op_type =
3418 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3419 }
3420
3421 psde->pipe_hw->ops.setup_sys_cache(
3422 psde->pipe_hw, &pstate->sc_cfg);
3423 }
3424
3425 /* update csc */
3426 if (SDE_FORMAT_IS_YUV(fmt))
3427 _sde_plane_setup_csc(psde);
3428 else
3429 psde->csc_ptr = 0;
3430 }
3431
3432 sde_color_process_plane_setup(plane);
3433
3434 /* update sharpening */
3435 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3436 psde->pipe_hw->ops.setup_sharpening) {
3437 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3438 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3439 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3440 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3441
3442 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3443 &psde->sharp_cfg);
3444 }
3445
3446 _sde_plane_set_qos_lut(plane, fb);
3447 _sde_plane_set_danger_lut(plane, fb);
3448
3449 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3450 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3451 _sde_plane_set_ot_limit(plane, crtc);
Alan Kwong2349d742017-04-20 08:27:30 -07003452 if (pstate->dirty & SDE_PLANE_DIRTY_PERF)
3453 _sde_plane_set_ts_prefill(plane, pstate);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003454 }
3455
Alan Kwonga62eeb82017-04-19 08:57:55 -07003456 _sde_plane_set_qos_remap(plane);
3457
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003458 /* clear dirty */
3459 pstate->dirty = 0x0;
3460
3461 return 0;
3462}
3463
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003464static void sde_plane_atomic_update(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003465 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003466{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003467 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003468 struct drm_plane_state *state;
3469 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003470 struct sde_plane_state *old_pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003471
Clarence Ip13a8cf42016-09-29 17:27:47 -04003472 if (!plane) {
3473 SDE_ERROR("invalid plane\n");
3474 return;
3475 } else if (!plane->state) {
3476 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003477 return;
3478 }
3479
Clarence Ip13a8cf42016-09-29 17:27:47 -04003480 psde = to_sde_plane(plane);
3481 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003482 state = plane->state;
3483 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003484 old_pstate = to_sde_plane_state(old_state);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003485
Clarence Ip13a8cf42016-09-29 17:27:47 -04003486 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003487
Alan Kwong4dd64c82017-02-04 18:41:51 -08003488 sde_plane_rot_atomic_update(plane, old_state);
3489
3490 if (!sde_plane_sspp_enabled(state)) {
Clarence Ip5e2a9222016-06-26 22:38:24 -04003491 pstate->pending = true;
Clarence Ip282dad62016-09-27 17:07:35 -04003492 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003493 int ret;
3494
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003495 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003496 /* atomic_check should have ensured that this doesn't fail */
3497 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003498 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003499}
3500
Dhaval Patel47302cf2016-08-18 15:04:28 -07003501
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003502/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003503static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003504 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003505{
Clarence Ip5e2a9222016-06-26 22:38:24 -04003506 static const struct drm_prop_enum_list e_blend_op[] = {
3507 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3508 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3509 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3510 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3511 };
3512 static const struct drm_prop_enum_list e_src_config[] = {
3513 {SDE_DRM_DEINTERLACE, "deinterlace"}
3514 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003515 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003516 struct sde_format_extended *virt_format_list = NULL;
Dhaval Patel4e574842016-08-23 15:11:37 -07003517 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003518 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003519 int zpos_max = 255;
3520 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003521 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003522
Clarence Ip13a8cf42016-09-29 17:27:47 -04003523 if (!plane || !psde) {
3524 SDE_ERROR("invalid plane\n");
3525 return;
3526 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3527 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3528 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003529 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003530 } else if (!catalog) {
3531 SDE_ERROR("invalid catalog\n");
3532 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003533 }
3534
Alan Kwong4dd64c82017-02-04 18:41:51 -08003535 psde->catalog = catalog;
3536
Clarence Ipc47a0692016-10-11 10:54:17 -04003537 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003538 if (catalog->mixer_count && catalog->mixer &&
3539 catalog->mixer[0].sblk->maxblendstages) {
3540 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3541 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3542 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3543 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003544 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3545 /* reserve zpos == 0 for primary planes */
3546 zpos_def = drm_plane_index(plane) + 1;
3547 }
3548
3549 msm_property_install_range(&psde->property_info, "zpos",
3550 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003551
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003552 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003553 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003554
Dhaval Patel47302cf2016-08-18 15:04:28 -07003555 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003556 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003557 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003558
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003559 if (!master_plane_id) {
3560 if (psde->pipe_sblk->maxhdeciexp) {
3561 msm_property_install_range(&psde->property_info,
3562 "h_decimate", 0x0, 0,
3563 psde->pipe_sblk->maxhdeciexp, 0,
3564 PLANE_PROP_H_DECIMATE);
3565 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003566
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003567 if (psde->pipe_sblk->maxvdeciexp) {
3568 msm_property_install_range(&psde->property_info,
3569 "v_decimate", 0x0, 0,
3570 psde->pipe_sblk->maxvdeciexp, 0,
3571 PLANE_PROP_V_DECIMATE);
3572 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003573
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003574 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003575 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003576 &psde->property_info, "scaler_v2",
3577 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3578 msm_property_install_blob(&psde->property_info,
3579 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3580 msm_property_install_blob(&psde->property_info,
3581 "lut_cir", 0,
3582 PLANE_PROP_SCALER_LUT_CIR);
3583 msm_property_install_blob(&psde->property_info,
3584 "lut_sep", 0,
3585 PLANE_PROP_SCALER_LUT_SEP);
3586 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003587 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003588 &psde->property_info, "scaler_v1", 0x0,
3589 0, ~0, 0, PLANE_PROP_SCALER_V1);
3590 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003591
Dhaval Patel0aee0972017-02-08 19:00:58 -08003592 if (psde->features & BIT(SDE_SSPP_CSC) ||
3593 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003594 msm_property_install_volatile_range(
3595 &psde->property_info, "csc_v1", 0x0,
3596 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003597
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003598 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3599 snprintf(feature_name, sizeof(feature_name), "%s%d",
3600 "SDE_SSPP_HUE_V",
3601 psde->pipe_sblk->hsic_blk.version >> 16);
3602 msm_property_install_range(&psde->property_info,
3603 feature_name, 0, 0, 0xFFFFFFFF, 0,
3604 PLANE_PROP_HUE_ADJUST);
3605 snprintf(feature_name, sizeof(feature_name), "%s%d",
3606 "SDE_SSPP_SATURATION_V",
3607 psde->pipe_sblk->hsic_blk.version >> 16);
3608 msm_property_install_range(&psde->property_info,
3609 feature_name, 0, 0, 0xFFFFFFFF, 0,
3610 PLANE_PROP_SATURATION_ADJUST);
3611 snprintf(feature_name, sizeof(feature_name), "%s%d",
3612 "SDE_SSPP_VALUE_V",
3613 psde->pipe_sblk->hsic_blk.version >> 16);
3614 msm_property_install_range(&psde->property_info,
3615 feature_name, 0, 0, 0xFFFFFFFF, 0,
3616 PLANE_PROP_VALUE_ADJUST);
3617 snprintf(feature_name, sizeof(feature_name), "%s%d",
3618 "SDE_SSPP_CONTRAST_V",
3619 psde->pipe_sblk->hsic_blk.version >> 16);
3620 msm_property_install_range(&psde->property_info,
3621 feature_name, 0, 0, 0xFFFFFFFF, 0,
3622 PLANE_PROP_CONTRAST_ADJUST);
3623 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003624 }
3625
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003626 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3627 msm_property_install_volatile_range(&psde->property_info,
3628 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3629
Alan Kwong4dd64c82017-02-04 18:41:51 -08003630 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003631
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003632 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003633 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003634
Dhaval Patel47302cf2016-08-18 15:04:28 -07003635 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3636 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3637
3638 if (psde->pipe_hw->ops.setup_solidfill)
3639 msm_property_install_range(&psde->property_info, "color_fill",
3640 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3641
Alan Kwong2349d742017-04-20 08:27:30 -07003642 msm_property_install_range(&psde->property_info,
3643 "prefill_size", 0x0, 0, ~0, 0,
3644 PLANE_PROP_PREFILL_SIZE);
3645 msm_property_install_range(&psde->property_info,
3646 "prefill_time", 0x0, 0, ~0, 0,
3647 PLANE_PROP_PREFILL_TIME);
3648
Dhaval Patel4e574842016-08-23 15:11:37 -07003649 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003650 if (!info) {
3651 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003652 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003653 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003654
3655 msm_property_install_blob(&psde->property_info, "capabilities",
3656 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3657 sde_kms_info_reset(info);
3658
Clarence Ipea3d6262016-07-15 16:20:11 -04003659 format_list = psde->pipe_sblk->format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003660
3661 if (master_plane_id) {
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003662 int index, array_size;
3663
3664 array_size = ARRAY_SIZE(plane_formats)
3665 + ARRAY_SIZE(rgb_10bit_formats);
3666 virt_format_list = kcalloc(array_size,
3667 sizeof(struct sde_format_extended), GFP_KERNEL);
3668 if (!virt_format_list) {
3669 SDE_ERROR(
3670 "failed to allocate virtual pipe format list\n");
3671 return;
3672 }
3673
3674 index = sde_copy_formats(virt_format_list, array_size,
3675 0, plane_formats, ARRAY_SIZE(plane_formats));
3676 sde_copy_formats(virt_format_list, array_size,
3677 index, rgb_10bit_formats,
3678 ARRAY_SIZE(rgb_10bit_formats));
3679
3680 format_list = virt_format_list;
3681
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003682 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003683 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003684 }
3685
Clarence Ipea3d6262016-07-15 16:20:11 -04003686 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003687 sde_kms_info_start(info, "pixel_formats");
3688 while (format_list->fourcc_format) {
3689 sde_kms_info_append_format(info,
3690 format_list->fourcc_format,
3691 format_list->modifier);
3692 ++format_list;
3693 }
3694 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003695 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003696
3697 sde_kms_info_add_keyint(info, "max_linewidth",
3698 psde->pipe_sblk->maxlinewidth);
3699 sde_kms_info_add_keyint(info, "max_upscale",
3700 psde->pipe_sblk->maxupscale);
3701 sde_kms_info_add_keyint(info, "max_downscale",
3702 psde->pipe_sblk->maxdwnscale);
3703 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3704 psde->pipe_sblk->maxhdeciexp);
3705 sde_kms_info_add_keyint(info, "max_vertical_deci",
3706 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07003707 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
3708 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07003709 msm_property_set_blob(&psde->property_info, &psde->blob_info,
Narendra Muppalla22d17252017-05-31 15:13:39 -07003710 info->data, SDE_KMS_INFO_DATALEN(info),
3711 PLANE_PROP_INFO);
Dhaval Patel4e574842016-08-23 15:11:37 -07003712
3713 kfree(info);
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003714 kfree(virt_format_list);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003715
3716 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3717 snprintf(feature_name, sizeof(feature_name), "%s%d",
3718 "SDE_SSPP_SKIN_COLOR_V",
3719 psde->pipe_sblk->memcolor_blk.version >> 16);
3720 msm_property_install_blob(&psde->property_info, feature_name, 0,
3721 PLANE_PROP_SKIN_COLOR);
3722 snprintf(feature_name, sizeof(feature_name), "%s%d",
3723 "SDE_SSPP_SKY_COLOR_V",
3724 psde->pipe_sblk->memcolor_blk.version >> 16);
3725 msm_property_install_blob(&psde->property_info, feature_name, 0,
3726 PLANE_PROP_SKY_COLOR);
3727 snprintf(feature_name, sizeof(feature_name), "%s%d",
3728 "SDE_SSPP_FOLIAGE_COLOR_V",
3729 psde->pipe_sblk->memcolor_blk.version >> 16);
3730 msm_property_install_blob(&psde->property_info, feature_name, 0,
3731 PLANE_PROP_FOLIAGE_COLOR);
3732 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003733}
3734
Clarence Ip5fc00c52016-09-23 15:03:34 -04003735static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
3736{
3737 struct sde_drm_csc_v1 csc_v1;
3738 int i;
3739
3740 if (!psde) {
3741 SDE_ERROR("invalid plane\n");
3742 return;
3743 }
3744
3745 psde->csc_usr_ptr = NULL;
3746 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003747 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003748 return;
3749 }
3750
3751 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003752 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04003753 return;
3754 }
3755
Clarence Ipb43d4592016-09-08 14:21:35 -04003756 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04003757 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
3758 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
3759 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
3760 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
3761 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
3762 }
3763 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
3764 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
3765 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
3766 }
3767 psde->csc_usr_ptr = &psde->csc_cfg;
3768}
3769
Clarence Ipb43d4592016-09-08 14:21:35 -04003770static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
3771{
3772 struct sde_drm_scaler_v1 scale_v1;
3773 struct sde_hw_pixel_ext *pe;
3774 int i;
3775
3776 if (!psde) {
3777 SDE_ERROR("invalid plane\n");
3778 return;
3779 }
3780
Clarence Ip059c8c32017-06-06 17:15:54 -04003781 psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
Clarence Ipb43d4592016-09-08 14:21:35 -04003782 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003783 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003784 return;
3785 }
3786
3787 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003788 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003789 return;
3790 }
3791
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003792 /* force property to be dirty, even if the pointer didn't change */
3793 msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V1);
3794
Clarence Ipb43d4592016-09-08 14:21:35 -04003795 /* populate from user space */
3796 pe = &(psde->pixel_ext);
3797 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3798 for (i = 0; i < SDE_MAX_PLANES; i++) {
3799 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
3800 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
3801 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
3802 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
3803
3804 pe->horz_filter[i] = scale_v1.horz_filter[i];
3805 pe->vert_filter[i] = scale_v1.vert_filter[i];
3806 }
3807 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003808 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
3809 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
3810 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
3811 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
3812 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003813
abeykun41060122016-11-28 13:02:01 -05003814 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
3815 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
3816 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
3817 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
3818 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04003819 }
abeykun41060122016-11-28 13:02:01 -05003820
Clarence Ip059c8c32017-06-06 17:15:54 -04003821 psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
Clarence Ipb43d4592016-09-08 14:21:35 -04003822
Clarence Ip059c8c32017-06-06 17:15:54 -04003823 SDE_EVT32_VERBOSE(DRMID(&psde->base));
Clarence Ip13a8cf42016-09-29 17:27:47 -04003824 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04003825}
3826
abeykun48f407a2016-08-25 12:06:44 -04003827static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
3828 struct sde_plane_state *pstate, void *usr)
3829{
3830 struct sde_drm_scaler_v2 scale_v2;
3831 struct sde_hw_pixel_ext *pe;
3832 int i;
3833 struct sde_hw_scaler3_cfg *cfg;
3834
Clarence Ip059c8c32017-06-06 17:15:54 -04003835 if (!psde || !psde->scaler3_cfg) {
abeykun48f407a2016-08-25 12:06:44 -04003836 SDE_ERROR("invalid plane\n");
3837 return;
3838 }
3839
3840 cfg = psde->scaler3_cfg;
Clarence Ip059c8c32017-06-06 17:15:54 -04003841 psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
abeykun48f407a2016-08-25 12:06:44 -04003842 if (!usr) {
3843 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3844 return;
3845 }
3846
3847 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
3848 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
3849 return;
3850 }
3851
Clarence Ip7e892a02017-06-13 10:16:07 -04003852 /* detach/ignore user data if 'disabled' */
3853 if (!scale_v2.enable) {
3854 SDE_DEBUG_PLANE(psde, "scale data removed\n");
3855 return;
3856 }
3857
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003858 /* force property to be dirty, even if the pointer didn't change */
3859 msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V2);
3860
abeykun48f407a2016-08-25 12:06:44 -04003861 /* populate from user space */
3862 pe = &(psde->pixel_ext);
3863 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
3864 cfg->enable = scale_v2.enable;
3865 cfg->dir_en = scale_v2.dir_en;
3866 for (i = 0; i < SDE_MAX_PLANES; i++) {
3867 cfg->init_phase_x[i] = scale_v2.init_phase_x[i];
3868 cfg->phase_step_x[i] = scale_v2.phase_step_x[i];
3869 cfg->init_phase_y[i] = scale_v2.init_phase_y[i];
3870 cfg->phase_step_y[i] = scale_v2.phase_step_y[i];
3871
3872 cfg->preload_x[i] = scale_v2.preload_x[i];
3873 cfg->preload_y[i] = scale_v2.preload_y[i];
3874 cfg->src_width[i] = scale_v2.src_width[i];
3875 cfg->src_height[i] = scale_v2.src_height[i];
3876 }
3877 cfg->dst_width = scale_v2.dst_width;
3878 cfg->dst_height = scale_v2.dst_height;
3879
3880 cfg->y_rgb_filter_cfg = scale_v2.y_rgb_filter_cfg;
3881 cfg->uv_filter_cfg = scale_v2.uv_filter_cfg;
3882 cfg->alpha_filter_cfg = scale_v2.alpha_filter_cfg;
3883 cfg->blend_cfg = scale_v2.blend_cfg;
3884
3885 cfg->lut_flag = scale_v2.lut_flag;
3886 cfg->dir_lut_idx = scale_v2.dir_lut_idx;
3887 cfg->y_rgb_cir_lut_idx = scale_v2.y_rgb_cir_lut_idx;
3888 cfg->uv_cir_lut_idx = scale_v2.uv_cir_lut_idx;
3889 cfg->y_rgb_sep_lut_idx = scale_v2.y_rgb_sep_lut_idx;
3890 cfg->uv_sep_lut_idx = scale_v2.uv_sep_lut_idx;
3891
3892 cfg->de.enable = scale_v2.de.enable;
3893 cfg->de.sharpen_level1 = scale_v2.de.sharpen_level1;
3894 cfg->de.sharpen_level2 = scale_v2.de.sharpen_level2;
3895 cfg->de.clip = scale_v2.de.clip;
3896 cfg->de.limit = scale_v2.de.limit;
3897 cfg->de.thr_quiet = scale_v2.de.thr_quiet;
3898 cfg->de.thr_dieout = scale_v2.de.thr_dieout;
3899 cfg->de.thr_low = scale_v2.de.thr_low;
3900 cfg->de.thr_high = scale_v2.de.thr_high;
3901 cfg->de.prec_shift = scale_v2.de.prec_shift;
3902 for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
3903 cfg->de.adjust_a[i] = scale_v2.de.adjust_a[i];
3904 cfg->de.adjust_b[i] = scale_v2.de.adjust_b[i];
3905 cfg->de.adjust_c[i] = scale_v2.de.adjust_c[i];
3906 }
3907 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05003908 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
3909 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
3910 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
3911 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
3912 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04003913
abeykun41060122016-11-28 13:02:01 -05003914 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
3915 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
3916 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
3917 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
3918 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04003919 }
Clarence Ip059c8c32017-06-06 17:15:54 -04003920 psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
abeykun48f407a2016-08-25 12:06:44 -04003921
Clarence Ip059c8c32017-06-06 17:15:54 -04003922 SDE_EVT32_VERBOSE(DRMID(&psde->base), cfg->enable, cfg->de.enable,
3923 cfg->src_width[0], cfg->src_height[0],
3924 cfg->dst_width, cfg->dst_height);
abeykun48f407a2016-08-25 12:06:44 -04003925 SDE_DEBUG_PLANE(psde, "user property data copied\n");
3926}
3927
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003928static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
3929 struct sde_plane_state *pstate, void *usr_ptr)
3930{
3931 struct drm_clip_rect excl_rect_v1;
3932
3933 if (!psde) {
3934 SDE_ERROR("invalid plane\n");
3935 return;
3936 }
3937
3938 if (!usr_ptr) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003939 SDE_DEBUG_PLANE(psde, "invalid excl_rect user data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003940 return;
3941 }
3942
3943 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003944 SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003945 return;
3946 }
3947
3948 /* populate from user space */
3949 pstate->excl_rect.x = excl_rect_v1.x1;
3950 pstate->excl_rect.y = excl_rect_v1.y1;
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003951 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
3952 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
3953
3954 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3955 pstate->excl_rect.x, pstate->excl_rect.y,
3956 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003957}
3958
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003959static int sde_plane_atomic_set_property(struct drm_plane *plane,
3960 struct drm_plane_state *state, struct drm_property *property,
3961 uint64_t val)
3962{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003963 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003964 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04003965 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003966
Clarence Ip13a8cf42016-09-29 17:27:47 -04003967 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003968
3969 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003970 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04003971 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003972 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04003973 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04003974 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04003975 ret = msm_property_atomic_set(&psde->property_info,
3976 pstate->property_values, pstate->property_blobs,
3977 property, val);
3978 if (!ret) {
3979 idx = msm_property_index(&psde->property_info,
3980 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003981 switch (idx) {
3982 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04003983 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003984 break;
3985 case PLANE_PROP_CSC_V1:
3986 _sde_plane_set_csc_v1(psde, (void *)val);
3987 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04003988 case PLANE_PROP_SCALER_V1:
3989 _sde_plane_set_scaler_v1(psde, (void *)val);
3990 break;
abeykun48f407a2016-08-25 12:06:44 -04003991 case PLANE_PROP_SCALER_V2:
3992 _sde_plane_set_scaler_v2(psde, pstate,
3993 (void *)val);
3994 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003995 case PLANE_PROP_EXCL_RECT_V1:
3996 _sde_plane_set_excl_rect_v1(psde, pstate,
3997 (void *)val);
3998 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04003999 default:
4000 /* nothing to do */
4001 break;
4002 }
Clarence Ipe78efb72016-06-24 18:35:21 -04004003 }
4004 }
4005
Alan Kwong4dd64c82017-02-04 18:41:51 -08004006 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
4007 property->name, property->base.id, val, ret);
4008
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004009 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004010}
4011
4012static int sde_plane_set_property(struct drm_plane *plane,
4013 struct drm_property *property, uint64_t val)
4014{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004015 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04004016
Clarence Ipae4e60c2016-06-26 22:44:04 -04004017 return sde_plane_atomic_set_property(plane,
4018 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004019}
4020
4021static int sde_plane_atomic_get_property(struct drm_plane *plane,
4022 const struct drm_plane_state *state,
4023 struct drm_property *property, uint64_t *val)
4024{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004025 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004026 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04004027 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004028
Clarence Ipaa0faf42016-05-30 12:07:48 -04004029 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004030 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004031 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004032 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004033 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004034 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04004035 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004036 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004037 ret = msm_property_atomic_get(&psde->property_info,
4038 pstate->property_values, pstate->property_blobs,
4039 property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04004040 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004041
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004042 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004043}
4044
4045static void sde_plane_destroy(struct drm_plane *plane)
4046{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004047 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004048
Clarence Ip13a8cf42016-09-29 17:27:47 -04004049 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004050
Clarence Ip13a8cf42016-09-29 17:27:47 -04004051 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04004052 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
4053
Dhaval Patel4e574842016-08-23 15:11:37 -07004054 if (psde->blob_info)
4055 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004056 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04004057 mutex_destroy(&psde->lock);
4058
Clarence Ip4ce59322016-06-26 22:27:51 -04004059 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004060
Clarence Ip4ce59322016-06-26 22:27:51 -04004061 /* this will destroy the states as well */
4062 drm_plane_cleanup(plane);
4063
Clarence Ip4c1d9772016-06-26 09:35:38 -04004064 if (psde->pipe_hw)
4065 sde_hw_sspp_destroy(psde->pipe_hw);
4066
Clarence Ip4ce59322016-06-26 22:27:51 -04004067 kfree(psde);
4068 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004069}
4070
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004071static void sde_plane_destroy_state(struct drm_plane *plane,
4072 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004073{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004074 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04004075 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004076
Clarence Ipae4e60c2016-06-26 22:44:04 -04004077 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004078 SDE_ERROR("invalid arg(s), plane %d state %d\n",
4079 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004080 return;
4081 }
4082
Clarence Ipaa0faf42016-05-30 12:07:48 -04004083 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04004084 pstate = to_sde_plane_state(state);
4085
Clarence Ip13a8cf42016-09-29 17:27:47 -04004086 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004087
Alan Kwong4dd64c82017-02-04 18:41:51 -08004088 sde_plane_rot_destroy_state(plane, &pstate->base);
4089
Clarence Ipe78efb72016-06-24 18:35:21 -04004090 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004091 if (state->fb)
4092 drm_framebuffer_unreference(state->fb);
4093
Clarence Ipae4e60c2016-06-26 22:44:04 -04004094 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04004095 if (pstate->input_fence)
4096 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004097
Clarence Ipaa0faf42016-05-30 12:07:48 -04004098 /* destroy value helper */
4099 msm_property_destroy_state(&psde->property_info, pstate,
4100 pstate->property_values, pstate->property_blobs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004101}
4102
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004103static struct drm_plane_state *
4104sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004105{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004106 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004107 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04004108 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04004109 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004110
Clarence Ip13a8cf42016-09-29 17:27:47 -04004111 if (!plane) {
4112 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004113 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004114 } else if (!plane->state) {
4115 SDE_ERROR("invalid plane state\n");
4116 return NULL;
4117 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004118
Clarence Ip730e7192016-06-26 22:45:09 -04004119 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004120 psde = to_sde_plane(plane);
4121 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004122 if (!pstate) {
4123 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004124 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004125 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004126
Clarence Ip13a8cf42016-09-29 17:27:47 -04004127 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004128
4129 /* duplicate value helper */
4130 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
4131 pstate->property_values, pstate->property_blobs);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004132
Clarence Ip17e908b2016-09-29 15:58:00 -04004133 /* clear out any input fence */
4134 pstate->input_fence = 0;
4135 input_fence_default = msm_property_get_default(
4136 &psde->property_info, PLANE_PROP_INPUT_FENCE);
4137 msm_property_set_property(&psde->property_info, pstate->property_values,
4138 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004139
Clarence Ip282dad62016-09-27 17:07:35 -04004140 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04004141 pstate->pending = false;
4142
Alan Kwongcdb2f282017-03-18 13:42:06 -07004143 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
4144
Alan Kwong4dd64c82017-02-04 18:41:51 -08004145 sde_plane_rot_duplicate_state(plane, &pstate->base);
4146
Clarence Ip730e7192016-06-26 22:45:09 -04004147 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004148}
4149
4150static void sde_plane_reset(struct drm_plane *plane)
4151{
Clarence Ipae4e60c2016-06-26 22:44:04 -04004152 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004153 struct sde_plane_state *pstate;
4154
Clarence Ipae4e60c2016-06-26 22:44:04 -04004155 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004156 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04004157 return;
4158 }
4159
Clarence Ip730e7192016-06-26 22:45:09 -04004160 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004161 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004162
Clarence Ipae4e60c2016-06-26 22:44:04 -04004163 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04004164 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04004165 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004166 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04004167 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004168
Clarence Ipaa0faf42016-05-30 12:07:48 -04004169 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004170 if (!pstate) {
4171 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004172 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004173 }
Clarence Ip730e7192016-06-26 22:45:09 -04004174
Clarence Ipaa0faf42016-05-30 12:07:48 -04004175 /* reset value helper */
4176 msm_property_reset_state(&psde->property_info, pstate,
4177 pstate->property_values, pstate->property_blobs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004178
4179 pstate->base.plane = plane;
4180
4181 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004182}
4183
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004184#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04004185static ssize_t _sde_plane_danger_read(struct file *file,
4186 char __user *buff, size_t count, loff_t *ppos)
4187{
4188 struct sde_kms *kms = file->private_data;
4189 struct sde_mdss_cfg *cfg = kms->catalog;
4190 int len = 0;
4191 char buf[40] = {'\0'};
4192
4193 if (!cfg)
4194 return -ENODEV;
4195
4196 if (*ppos)
4197 return 0; /* the end */
4198
4199 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
4200 if (len < 0 || len >= sizeof(buf))
4201 return 0;
4202
4203 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
4204 return -EFAULT;
4205
4206 *ppos += len; /* increase offset */
4207
4208 return len;
4209}
4210
4211static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
4212{
4213 struct drm_plane *plane;
4214
4215 drm_for_each_plane(plane, kms->dev) {
4216 if (plane->fb && plane->state) {
4217 sde_plane_danger_signal_ctrl(plane, enable);
4218 SDE_DEBUG("plane:%d img:%dx%d ",
4219 plane->base.id, plane->fb->width,
4220 plane->fb->height);
4221 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
4222 plane->state->src_x >> 16,
4223 plane->state->src_y >> 16,
4224 plane->state->src_w >> 16,
4225 plane->state->src_h >> 16,
4226 plane->state->crtc_x, plane->state->crtc_y,
4227 plane->state->crtc_w, plane->state->crtc_h);
4228 } else {
4229 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
4230 }
4231 }
4232}
4233
4234static ssize_t _sde_plane_danger_write(struct file *file,
4235 const char __user *user_buf, size_t count, loff_t *ppos)
4236{
4237 struct sde_kms *kms = file->private_data;
4238 struct sde_mdss_cfg *cfg = kms->catalog;
4239 int disable_panic;
4240 char buf[10];
4241
4242 if (!cfg)
4243 return -EFAULT;
4244
4245 if (count >= sizeof(buf))
4246 return -EFAULT;
4247
4248 if (copy_from_user(buf, user_buf, count))
4249 return -EFAULT;
4250
4251 buf[count] = 0; /* end of string */
4252
4253 if (kstrtoint(buf, 0, &disable_panic))
4254 return -EFAULT;
4255
4256 if (disable_panic) {
4257 /* Disable panic signal for all active pipes */
4258 SDE_DEBUG("Disabling danger:\n");
4259 _sde_plane_set_danger_state(kms, false);
4260 kms->has_danger_ctrl = false;
4261 } else {
4262 /* Enable panic signal for all active pipes */
4263 SDE_DEBUG("Enabling danger:\n");
4264 kms->has_danger_ctrl = true;
4265 _sde_plane_set_danger_state(kms, true);
4266 }
4267
4268 return count;
4269}
4270
4271static const struct file_operations sde_plane_danger_enable = {
4272 .open = simple_open,
4273 .read = _sde_plane_danger_read,
4274 .write = _sde_plane_danger_write,
4275};
4276
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004277static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04004278{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004279 struct sde_plane *psde;
4280 struct sde_kms *kms;
4281 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04004282 const struct sde_sspp_sub_blks *sblk = 0;
4283 const struct sde_sspp_cfg *cfg = 0;
4284
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004285 if (!plane || !plane->dev) {
4286 SDE_ERROR("invalid arguments\n");
4287 return -EINVAL;
4288 }
4289
4290 priv = plane->dev->dev_private;
4291 if (!priv || !priv->kms) {
4292 SDE_ERROR("invalid KMS reference\n");
4293 return -EINVAL;
4294 }
4295
4296 kms = to_sde_kms(priv->kms);
4297 psde = to_sde_plane(plane);
4298
Clarence Ip4ce59322016-06-26 22:27:51 -04004299 if (psde && psde->pipe_hw)
4300 cfg = psde->pipe_hw->cap;
4301 if (cfg)
4302 sblk = cfg->sblk;
4303
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004304 if (!sblk)
4305 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04004306
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004307 /* create overall sub-directory for the pipe */
4308 psde->debugfs_root =
4309 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07004310 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04004311
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004312 if (!psde->debugfs_root)
4313 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04004314
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004315 /* don't error check these */
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004316 debugfs_create_x32("features", 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004317 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004318
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004319 /* add register dump support */
4320 sde_debugfs_setup_regset32(&psde->debugfs_src,
4321 sblk->src_blk.base + cfg->base,
4322 sblk->src_blk.len,
4323 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004324 sde_debugfs_create_regset32("src_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004325 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004326
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004327 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
4328 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
4329 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
4330 sblk->scaler_blk.base + cfg->base,
4331 sblk->scaler_blk.len,
4332 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004333 sde_debugfs_create_regset32("scaler_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004334 psde->debugfs_root,
4335 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07004336 debugfs_create_bool("default_scaling",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004337 0600,
Clarence Ip716ab662017-03-20 06:51:24 -07004338 psde->debugfs_root,
4339 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04004340 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004341
4342 if (cfg->features & BIT(SDE_SSPP_CSC) ||
4343 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
4344 sde_debugfs_setup_regset32(&psde->debugfs_csc,
4345 sblk->csc_blk.base + cfg->base,
4346 sblk->csc_blk.len,
4347 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004348 sde_debugfs_create_regset32("csc_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004349 psde->debugfs_root, &psde->debugfs_csc);
4350 }
4351
4352 debugfs_create_u32("xin_id",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004353 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004354 psde->debugfs_root,
4355 (u32 *) &cfg->xin_id);
4356 debugfs_create_u32("clk_ctrl",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004357 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004358 psde->debugfs_root,
4359 (u32 *) &cfg->clk_ctrl);
4360 debugfs_create_x32("creq_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004361 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004362 psde->debugfs_root,
4363 (u32 *) &sblk->creq_vblank);
4364 debugfs_create_x32("danger_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004365 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004366 psde->debugfs_root,
4367 (u32 *) &sblk->danger_vblank);
4368
4369 debugfs_create_file("disable_danger",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004370 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004371 psde->debugfs_root,
4372 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004373 debugfs_create_u32("sbuf_mode",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004374 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004375 psde->debugfs_root, &psde->sbuf_mode);
4376 debugfs_create_u32("sbuf_writeback",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004377 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004378 psde->debugfs_root,
4379 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004380
4381 return 0;
4382}
4383
4384static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4385{
4386 struct sde_plane *psde;
4387
4388 if (!plane)
4389 return;
4390 psde = to_sde_plane(plane);
4391
4392 debugfs_remove_recursive(psde->debugfs_root);
4393}
4394#else
4395static int _sde_plane_init_debugfs(struct drm_plane *plane)
4396{
4397 return 0;
4398}
4399static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4400{
4401}
4402#endif
4403
4404static int sde_plane_late_register(struct drm_plane *plane)
4405{
4406 return _sde_plane_init_debugfs(plane);
4407}
4408
4409static void sde_plane_early_unregister(struct drm_plane *plane)
4410{
4411 _sde_plane_destroy_debugfs(plane);
4412}
4413
4414static const struct drm_plane_funcs sde_plane_funcs = {
4415 .update_plane = drm_atomic_helper_update_plane,
4416 .disable_plane = drm_atomic_helper_disable_plane,
4417 .destroy = sde_plane_destroy,
4418 .set_property = sde_plane_set_property,
4419 .atomic_set_property = sde_plane_atomic_set_property,
4420 .atomic_get_property = sde_plane_atomic_get_property,
4421 .reset = sde_plane_reset,
4422 .atomic_duplicate_state = sde_plane_duplicate_state,
4423 .atomic_destroy_state = sde_plane_destroy_state,
4424 .late_register = sde_plane_late_register,
4425 .early_unregister = sde_plane_early_unregister,
4426};
4427
4428static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
4429 .prepare_fb = sde_plane_prepare_fb,
4430 .cleanup_fb = sde_plane_cleanup_fb,
4431 .atomic_check = sde_plane_atomic_check,
4432 .atomic_update = sde_plane_atomic_update,
4433};
4434
4435enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
4436{
4437 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
4438}
4439
4440bool is_sde_plane_virtual(struct drm_plane *plane)
4441{
4442 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04004443}
4444
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004445/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04004446struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04004447 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004448 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004449{
Alan Kwongdce56da2017-04-27 15:50:34 -07004450 struct drm_plane *plane = NULL, *master_plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004451 const struct sde_format_extended *format_list;
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004452 struct sde_format_extended *virt_format_list = NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004453 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004454 struct msm_drm_private *priv;
4455 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004456 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04004457 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004458
4459 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004460 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004461 goto exit;
4462 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004463
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004464 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004465 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004466 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004467 goto exit;
4468 }
4469
4470 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004471 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004472 goto exit;
4473 }
4474 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004475
Clarence Ip4c1d9772016-06-26 09:35:38 -04004476 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004477 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004478 goto exit;
4479 }
4480
Clarence Ip4ce59322016-06-26 22:27:51 -04004481 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004482 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4483 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004484 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004485 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004486 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004487 }
4488
Clarence Ip4c1d9772016-06-26 09:35:38 -04004489 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004490 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004491 psde->pipe = pipe;
Jordan Croused8e96522017-02-13 10:14:16 -07004492 psde->aspace = kms->aspace[MSM_SMMU_DOMAIN_UNSECURE];
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004493 psde->is_virtual = (master_plane_id != 0);
Clarence Ip059c8c32017-06-06 17:15:54 -04004494 psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
Alan Kwongdce56da2017-04-27 15:50:34 -07004495 INIT_LIST_HEAD(&psde->mplane_list);
4496 master_plane = drm_plane_find(dev, master_plane_id);
4497 if (master_plane) {
4498 struct sde_plane *mpsde = to_sde_plane(master_plane);
4499
4500 list_add_tail(&psde->mplane_list, &mpsde->mplane_list);
4501 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004502
Clarence Ip4c1d9772016-06-26 09:35:38 -04004503 /* initialize underlying h/w driver */
Dhaval Pateld850b222017-06-16 17:37:37 -07004504 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog,
4505 master_plane_id != 0);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004506 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004507 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004508 ret = PTR_ERR(psde->pipe_hw);
4509 goto clean_plane;
4510 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004511 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004512 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004513 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004514
4515 /* cache features mask for later */
4516 psde->features = psde->pipe_hw->cap->features;
4517 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004518 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004519 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004520 goto clean_sspp;
4521 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004522
abeykun48f407a2016-08-25 12:06:44 -04004523 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
4524 psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
4525 GFP_KERNEL);
4526 if (!psde->scaler3_cfg) {
4527 SDE_ERROR("[%u]failed to allocate scale struct\n",
4528 pipe);
4529 ret = -ENOMEM;
4530 goto clean_sspp;
4531 }
4532 }
4533
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004534 format_list = psde->pipe_sblk->format_list;
4535
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004536 if (master_plane_id) {
4537 int index, array_size;
4538
4539 array_size = ARRAY_SIZE(plane_formats)
4540 + ARRAY_SIZE(rgb_10bit_formats);
4541 virt_format_list = kcalloc(array_size,
4542 sizeof(struct sde_format_extended),
4543 GFP_KERNEL);
4544 if (!virt_format_list) {
4545 SDE_ERROR(
4546 "failed to allocate virtual pipe format list\n");
4547 goto clean_sspp;
4548 }
4549
4550 index = sde_copy_formats(virt_format_list, array_size,
4551 0, plane_formats, ARRAY_SIZE(plane_formats));
4552 sde_copy_formats(virt_format_list, array_size,
4553 index, rgb_10bit_formats,
4554 ARRAY_SIZE(rgb_10bit_formats));
4555
4556 format_list = virt_format_list;
4557 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004558
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004559 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004560 psde->formats,
4561 0,
4562 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004563
Clarence Ip4c1d9772016-06-26 09:35:38 -04004564 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004565 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004566 goto clean_sspp;
4567 }
4568
4569 if (psde->features & BIT(SDE_SSPP_CURSOR))
4570 type = DRM_PLANE_TYPE_CURSOR;
4571 else if (primary_plane)
4572 type = DRM_PLANE_TYPE_PRIMARY;
4573 else
4574 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07004575 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
4576 psde->formats, psde->nformats,
4577 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004578 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04004579 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004580
Clarence Ip4c1d9772016-06-26 09:35:38 -04004581 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004582 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004583
Clarence Ipaa0faf42016-05-30 12:07:48 -04004584 msm_property_init(&psde->property_info, &plane->base, dev,
4585 priv->plane_property, psde->property_data,
4586 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
4587 sizeof(struct sde_plane_state));
4588
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004589 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004590
Clarence Ip4ce59322016-06-26 22:27:51 -04004591 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004592 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004593
Clarence Ip730e7192016-06-26 22:45:09 -04004594 mutex_init(&psde->lock);
4595
Dhaval Patel572cfd22017-06-12 19:33:39 -07004596 SDE_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", psde->pipe_name,
4597 pipe, plane->base.id, master_plane_id);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004598 return plane;
4599
Clarence Ip4c1d9772016-06-26 09:35:38 -04004600clean_sspp:
4601 if (psde && psde->pipe_hw)
4602 sde_hw_sspp_destroy(psde->pipe_hw);
abeykun48f407a2016-08-25 12:06:44 -04004603
4604 if (psde && psde->scaler3_cfg)
4605 kfree(psde->scaler3_cfg);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004606clean_plane:
4607 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004608exit:
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004609 kfree(virt_format_list);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004610 return ERR_PTR(ret);
4611}