blob: 06561499ae6b9b0cad8b1e8a5b3e49c75440f265 [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
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -070076#define SDE_QSEED3_DEFAULT_PRELOAD_H 0x4
77#define SDE_QSEED3_DEFAULT_PRELOAD_V 0x3
78
Alan Kwong4dd64c82017-02-04 18:41:51 -080079#define DEFAULT_REFRESH_RATE 60
80
Alan Kwong1a00e4d2016-07-18 09:42:30 -040081/**
82 * enum sde_plane_qos - Different qos configurations for each pipe
83 *
84 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
85 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
86 * this configuration is mutually exclusive from VBLANK_CTRL.
87 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
88 */
89enum sde_plane_qos {
90 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
91 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
92 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
93};
94
Clarence Ip5fc00c52016-09-23 15:03:34 -040095/*
96 * struct sde_plane - local sde plane structure
Jordan Croused8e96522017-02-13 10:14:16 -070097 * @aspace: address space pointer
Clarence Ip5fc00c52016-09-23 15:03:34 -040098 * @csc_cfg: Decoded user configuration for csc
99 * @csc_usr_ptr: Points to csc_cfg if valid user config available
100 * @csc_ptr: Points to sde_csc_cfg structure to use for current
Alan Kwongdce56da2017-04-27 15:50:34 -0700101 * @mplane_list: List of multirect planes of the same pipe
Alan Kwong4dd64c82017-02-04 18:41:51 -0800102 * @catalog: Points to sde catalog structure
103 * @sbuf_mode: force stream buffer mode if set
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700104 * @sbuf_writeback: force stream buffer writeback if set
105 * @revalidate: force revalidation of all the plane properties
Alan Kwong4dd64c82017-02-04 18:41:51 -0800106 * @blob_rot_caps: Pointer to rotator capability blob
Clarence Ip5fc00c52016-09-23 15:03:34 -0400107 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700108struct sde_plane {
109 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400110
Clarence Ip730e7192016-06-26 22:45:09 -0400111 struct mutex lock;
112
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400113 enum sde_sspp pipe;
114 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700115 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400116 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400117
118 struct sde_hw_pipe *pipe_hw;
119 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -0400120 struct sde_hw_sharp_cfg sharp_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400121 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400122 uint32_t color_fill;
123 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400124 bool is_rt_pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800125 bool is_virtual;
Alan Kwongdce56da2017-04-27 15:50:34 -0700126 struct list_head mplane_list;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800127 struct sde_mdss_cfg *catalog;
128 u32 sbuf_mode;
129 u32 sbuf_writeback;
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700130 bool revalidate;
Clarence Ip4ce59322016-06-26 22:27:51 -0400131
Clarence Ip373f8592016-05-26 00:58:42 -0400132 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400133 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400134 struct sde_csc_cfg *csc_ptr;
135
Clarence Ip4c1d9772016-06-26 09:35:38 -0400136 const struct sde_sspp_sub_blks *pipe_sblk;
137
Clarence Ip5e2a9222016-06-26 22:38:24 -0400138 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400139
Clarence Ipaa0faf42016-05-30 12:07:48 -0400140 struct msm_property_info property_info;
141 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700142 struct drm_property_blob *blob_info;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800143 struct drm_property_blob *blob_rot_caps;
Clarence Ip730e7192016-06-26 22:45:09 -0400144
Clarence Ip4ce59322016-06-26 22:27:51 -0400145 /* debugfs related stuff */
146 struct dentry *debugfs_root;
147 struct sde_debugfs_regset32 debugfs_src;
148 struct sde_debugfs_regset32 debugfs_scaler;
149 struct sde_debugfs_regset32 debugfs_csc;
Clarence Ip716ab662017-03-20 06:51:24 -0700150 bool debugfs_default_scale;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700151};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700152
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700153#define to_sde_plane(x) container_of(x, struct sde_plane, base)
154
Alan Kwong4dd64c82017-02-04 18:41:51 -0800155static struct sde_kms *_sde_plane_get_kms(struct drm_plane *plane)
156{
157 struct msm_drm_private *priv;
158
159 if (!plane || !plane->dev)
160 return NULL;
161 priv = plane->dev->dev_private;
162 if (!priv)
163 return NULL;
164 return to_sde_kms(priv->kms);
165}
166
Alan Kwong4aacd532017-02-04 18:51:33 -0800167/**
168 * _sde_plane_get_crtc_state - obtain crtc state attached to given plane state
169 * @pstate: Pointer to drm plane state
170 * return: Pointer to crtc state if success; pointer error, otherwise
171 */
172static struct drm_crtc_state *_sde_plane_get_crtc_state(
173 struct drm_plane_state *pstate)
174{
175 struct drm_crtc_state *cstate;
176
177 if (!pstate || !pstate->crtc)
178 return NULL;
179
180 if (pstate->state)
181 cstate = drm_atomic_get_crtc_state(pstate->state, pstate->crtc);
182 else
183 cstate = pstate->crtc->state;
184
185 return cstate;
186}
187
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400188static bool sde_plane_enabled(struct drm_plane_state *state)
189{
Clarence Ipdbde9832016-06-26 09:48:36 -0400190 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400191}
192
Alan Kwong4dd64c82017-02-04 18:41:51 -0800193static bool sde_plane_sspp_enabled(struct drm_plane_state *state)
194{
195 return state && to_sde_plane_state(state)->rot.out_fb && state->crtc;
196}
197
198/**
199 * sde_plane_crtc_enabled - determine if crtc of given plane state is enabled
200 * @state: Pointer to drm plane state
201 * return: true if plane and the associated crtc are both enabled
202 */
203static bool sde_plane_crtc_enabled(struct drm_plane_state *state)
204{
205 return sde_plane_enabled(state) && state->crtc->state &&
206 state->crtc->state->active &&
207 state->crtc->state->enable;
208}
209
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400210/**
211 * _sde_plane_calc_fill_level - calculate fill level of the given source format
212 * @plane: Pointer to drm plane
213 * @fmt: Pointer to source buffer format
214 * @src_wdith: width of source buffer
215 * Return: fill level corresponding to the source buffer/format or 0 if error
216 */
217static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
218 const struct sde_format *fmt, u32 src_width)
219{
Alan Kwongdce56da2017-04-27 15:50:34 -0700220 struct sde_plane *psde, *tmp;
221 struct sde_plane_state *pstate;
222 struct sde_plane_rot_state *rstate;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400223 u32 fixed_buff_size;
224 u32 total_fl;
Alan Kwongdce56da2017-04-27 15:50:34 -0700225 u32 hflip_bytes;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400226
Alan Kwongdce56da2017-04-27 15:50:34 -0700227 if (!plane || !fmt || !plane->state || !src_width || !fmt->bpp) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400228 SDE_ERROR("invalid arguments\n");
229 return 0;
230 }
231
232 psde = to_sde_plane(plane);
Alan Kwongdce56da2017-04-27 15:50:34 -0700233 pstate = to_sde_plane_state(plane->state);
234 rstate = &pstate->rot;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400235 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
236
Alan Kwongdce56da2017-04-27 15:50:34 -0700237 list_for_each_entry(tmp, &psde->mplane_list, mplane_list) {
238 if (!sde_plane_enabled(tmp->base.state))
239 continue;
240 SDE_DEBUG("plane%d/%d src_width:%d/%d\n",
241 psde->base.base.id, tmp->base.base.id,
242 src_width, tmp->pipe_cfg.src_rect.w);
243 src_width = max_t(u32, src_width, tmp->pipe_cfg.src_rect.w);
244 }
245
246 if ((rstate->out_rotation & DRM_REFLECT_X) &&
247 SDE_FORMAT_IS_LINEAR(fmt))
248 hflip_bytes = (src_width + 32) * fmt->bpp;
249 else
250 hflip_bytes = 0;
251
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400252 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
253 if (fmt->chroma_sample == SDE_CHROMA_420) {
254 /* NV12 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700255 total_fl = (fixed_buff_size / 2 - hflip_bytes) /
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400256 ((src_width + 32) * fmt->bpp);
257 } else {
258 /* non NV12 */
Ingrid Gallardof3db8192017-06-30 18:21:55 -0700259 total_fl = (fixed_buff_size / 2 - hflip_bytes) * 2 /
260 ((src_width + 32) * fmt->bpp);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400261 }
262 } else {
Alan Kwongdce56da2017-04-27 15:50:34 -0700263 if (pstate->multirect_mode == SDE_SSPP_MULTIRECT_PARALLEL) {
Ingrid Gallardof3db8192017-06-30 18:21:55 -0700264 total_fl = (fixed_buff_size / 2 - hflip_bytes) * 2 /
265 ((src_width + 32) * fmt->bpp);
Alan Kwongdce56da2017-04-27 15:50:34 -0700266 } else {
Ingrid Gallardof3db8192017-06-30 18:21:55 -0700267 total_fl = (fixed_buff_size - hflip_bytes) * 2 /
268 ((src_width + 32) * fmt->bpp);
Alan Kwongdce56da2017-04-27 15:50:34 -0700269 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400270 }
271
Alan Kwongdce56da2017-04-27 15:50:34 -0700272 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u hf:%d fl:%u\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400273 plane->base.id, psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700274 (char *)&fmt->base.pixel_format,
Alan Kwongdce56da2017-04-27 15:50:34 -0700275 src_width, hflip_bytes, total_fl);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400276
277 return total_fl;
278}
279
280/**
Alan Kwongdce56da2017-04-27 15:50:34 -0700281 * _sde_plane_get_qos_lut - get LUT mapping based on fill level
282 * @tbl: Pointer to LUT table
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400283 * @total_fl: fill level
284 * Return: LUT setting corresponding to the fill level
285 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700286static u64 _sde_plane_get_qos_lut(const struct sde_qos_lut_tbl *tbl,
287 u32 total_fl)
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400288{
Alan Kwongdce56da2017-04-27 15:50:34 -0700289 int i;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400290
Alan Kwongdce56da2017-04-27 15:50:34 -0700291 if (!tbl || !tbl->nentry || !tbl->entries)
292 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400293
Alan Kwongdce56da2017-04-27 15:50:34 -0700294 for (i = 0; i < tbl->nentry; i++)
295 if (total_fl <= tbl->entries[i].fl)
296 return tbl->entries[i].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400297
Alan Kwongdce56da2017-04-27 15:50:34 -0700298 /* if last fl is zero, use as default */
299 if (!tbl->entries[i-1].fl)
300 return tbl->entries[i-1].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400301
Alan Kwongdce56da2017-04-27 15:50:34 -0700302 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400303}
304
305/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400306 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
307 * @plane: Pointer to drm plane
308 * @fb: Pointer to framebuffer associated with the given plane
309 */
310static void _sde_plane_set_qos_lut(struct drm_plane *plane,
311 struct drm_framebuffer *fb)
312{
313 struct sde_plane *psde;
314 const struct sde_format *fmt = NULL;
Alan Kwongdce56da2017-04-27 15:50:34 -0700315 u64 qos_lut;
316 u32 total_fl = 0, lut_usage;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400317
318 if (!plane || !fb) {
319 SDE_ERROR("invalid arguments plane %d fb %d\n",
320 plane != 0, fb != 0);
321 return;
322 }
323
324 psde = to_sde_plane(plane);
325
Alan Kwongdce56da2017-04-27 15:50:34 -0700326 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400327 SDE_ERROR("invalid arguments\n");
328 return;
329 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
330 return;
331 }
332
333 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700334 lut_usage = SDE_QOS_LUT_USAGE_NRT;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400335 } else {
336 fmt = sde_get_sde_format_ext(
337 fb->pixel_format,
338 fb->modifier,
339 drm_format_num_planes(fb->pixel_format));
340 total_fl = _sde_plane_calc_fill_level(plane, fmt,
341 psde->pipe_cfg.src_rect.w);
342
Narendra Muppallaec11a0a2017-06-15 15:35:17 -0700343 if (fmt && SDE_FORMAT_IS_LINEAR(fmt))
Alan Kwongdce56da2017-04-27 15:50:34 -0700344 lut_usage = SDE_QOS_LUT_USAGE_LINEAR;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400345 else
Alan Kwongdce56da2017-04-27 15:50:34 -0700346 lut_usage = SDE_QOS_LUT_USAGE_MACROTILE;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400347 }
348
Alan Kwongdce56da2017-04-27 15:50:34 -0700349 qos_lut = _sde_plane_get_qos_lut(
350 &psde->catalog->perf.qos_lut_tbl[lut_usage], total_fl);
351
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400352 psde->pipe_qos_cfg.creq_lut = qos_lut;
353
354 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
355 (fmt) ? fmt->base.pixel_format : 0,
Alan Kwongdce56da2017-04-27 15:50:34 -0700356 psde->is_rt_pipe, total_fl, qos_lut, lut_usage);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400357
Alan Kwongdce56da2017-04-27 15:50:34 -0700358 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400359 plane->base.id,
360 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700361 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400362 psde->is_rt_pipe, total_fl, qos_lut);
363
364 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
365}
366
367/**
368 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
369 * @plane: Pointer to drm plane
370 * @fb: Pointer to framebuffer associated with the given plane
371 */
372static void _sde_plane_set_danger_lut(struct drm_plane *plane,
373 struct drm_framebuffer *fb)
374{
375 struct sde_plane *psde;
376 const struct sde_format *fmt = NULL;
377 u32 danger_lut, safe_lut;
378
379 if (!plane || !fb) {
380 SDE_ERROR("invalid arguments\n");
381 return;
382 }
383
384 psde = to_sde_plane(plane);
385
Alan Kwongdce56da2017-04-27 15:50:34 -0700386 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400387 SDE_ERROR("invalid arguments\n");
388 return;
389 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
390 return;
391 }
392
393 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700394 danger_lut = psde->catalog->perf.danger_lut_tbl
395 [SDE_QOS_LUT_USAGE_NRT];
396 safe_lut = psde->catalog->perf.safe_lut_tbl
397 [SDE_QOS_LUT_USAGE_NRT];
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400398 } else {
399 fmt = sde_get_sde_format_ext(
400 fb->pixel_format,
401 fb->modifier,
402 drm_format_num_planes(fb->pixel_format));
403
Narendra Muppallaec11a0a2017-06-15 15:35:17 -0700404 if (fmt && SDE_FORMAT_IS_LINEAR(fmt)) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700405 danger_lut = psde->catalog->perf.danger_lut_tbl
406 [SDE_QOS_LUT_USAGE_LINEAR];
407 safe_lut = psde->catalog->perf.safe_lut_tbl
408 [SDE_QOS_LUT_USAGE_LINEAR];
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400409 } else {
Alan Kwongdce56da2017-04-27 15:50:34 -0700410 danger_lut = psde->catalog->perf.danger_lut_tbl
411 [SDE_QOS_LUT_USAGE_MACROTILE];
412 safe_lut = psde->catalog->perf.safe_lut_tbl
413 [SDE_QOS_LUT_USAGE_MACROTILE];
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400414 }
415 }
416
417 psde->pipe_qos_cfg.danger_lut = danger_lut;
418 psde->pipe_qos_cfg.safe_lut = safe_lut;
419
420 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
421 (fmt) ? fmt->base.pixel_format : 0,
422 (fmt) ? fmt->fetch_mode : 0,
423 psde->pipe_qos_cfg.danger_lut,
424 psde->pipe_qos_cfg.safe_lut);
425
Dhaval Patel6c666622017-03-21 23:02:59 -0700426 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400427 plane->base.id,
428 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700429 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400430 fmt ? fmt->fetch_mode : -1,
431 psde->pipe_qos_cfg.danger_lut,
432 psde->pipe_qos_cfg.safe_lut);
433
434 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
435 &psde->pipe_qos_cfg);
436}
437
438/**
439 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
440 * @plane: Pointer to drm plane
441 * @enable: true to enable QoS control
442 * @flags: QoS control mode (enum sde_plane_qos)
443 */
444static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
445 bool enable, u32 flags)
446{
447 struct sde_plane *psde;
448
449 if (!plane) {
450 SDE_ERROR("invalid arguments\n");
451 return;
452 }
453
454 psde = to_sde_plane(plane);
455
456 if (!psde->pipe_hw || !psde->pipe_sblk) {
457 SDE_ERROR("invalid arguments\n");
458 return;
459 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
460 return;
461 }
462
463 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
464 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
465 psde->pipe_qos_cfg.danger_vblank =
466 psde->pipe_sblk->danger_vblank;
467 psde->pipe_qos_cfg.vblank_en = enable;
468 }
469
470 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
471 /* this feature overrules previous VBLANK_CTRL */
472 psde->pipe_qos_cfg.vblank_en = false;
473 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
474 }
475
476 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
477 psde->pipe_qos_cfg.danger_safe_en = enable;
478
479 if (!psde->is_rt_pipe) {
480 psde->pipe_qos_cfg.vblank_en = false;
481 psde->pipe_qos_cfg.danger_safe_en = false;
482 }
483
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400484 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 -0400485 plane->base.id,
486 psde->pipe - SSPP_VIG0,
487 psde->pipe_qos_cfg.danger_safe_en,
488 psde->pipe_qos_cfg.vblank_en,
489 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400490 psde->pipe_qos_cfg.danger_vblank,
491 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400492
493 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
494 &psde->pipe_qos_cfg);
495}
496
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700497void sde_plane_set_revalidate(struct drm_plane *plane, bool enable)
498{
499 struct sde_plane *psde;
500
501 if (!plane)
502 return;
503
504 psde = to_sde_plane(plane);
505 psde->revalidate = enable;
506}
507
Alan Kwongf0fd8512016-10-24 21:39:26 -0400508int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
509{
510 struct sde_plane *psde;
511 struct msm_drm_private *priv;
512 struct sde_kms *sde_kms;
513
514 if (!plane || !plane->dev) {
515 SDE_ERROR("invalid arguments\n");
516 return -EINVAL;
517 }
518
519 priv = plane->dev->dev_private;
520 if (!priv || !priv->kms) {
521 SDE_ERROR("invalid KMS reference\n");
522 return -EINVAL;
523 }
524
525 sde_kms = to_sde_kms(priv->kms);
526 psde = to_sde_plane(plane);
527
528 if (!psde->is_rt_pipe)
529 goto end;
530
531 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
532
533 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
534
535 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
536
537end:
538 return 0;
539}
540
Alan Kwong5d324e42016-07-28 22:56:18 -0400541/**
542 * _sde_plane_set_ot_limit - set OT limit for the given plane
543 * @plane: Pointer to drm plane
544 * @crtc: Pointer to drm crtc
545 */
546static void _sde_plane_set_ot_limit(struct drm_plane *plane,
547 struct drm_crtc *crtc)
548{
549 struct sde_plane *psde;
550 struct sde_vbif_set_ot_params ot_params;
551 struct msm_drm_private *priv;
552 struct sde_kms *sde_kms;
553
554 if (!plane || !plane->dev || !crtc) {
555 SDE_ERROR("invalid arguments plane %d crtc %d\n",
556 plane != 0, crtc != 0);
557 return;
558 }
559
560 priv = plane->dev->dev_private;
561 if (!priv || !priv->kms) {
562 SDE_ERROR("invalid KMS reference\n");
563 return;
564 }
565
566 sde_kms = to_sde_kms(priv->kms);
567 psde = to_sde_plane(plane);
568 if (!psde->pipe_hw) {
569 SDE_ERROR("invalid pipe reference\n");
570 return;
571 }
572
573 memset(&ot_params, 0, sizeof(ot_params));
574 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
575 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
576 ot_params.width = psde->pipe_cfg.src_rect.w;
577 ot_params.height = psde->pipe_cfg.src_rect.h;
578 ot_params.is_wfd = !psde->is_rt_pipe;
579 ot_params.frame_rate = crtc->mode.vrefresh;
580 ot_params.vbif_idx = VBIF_RT;
581 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
582 ot_params.rd = true;
583
584 sde_vbif_set_ot_limit(sde_kms, &ot_params);
585}
586
Alan Kwonga62eeb82017-04-19 08:57:55 -0700587/**
588 * _sde_plane_set_vbif_qos - set vbif QoS for the given plane
589 * @plane: Pointer to drm plane
590 */
591static void _sde_plane_set_qos_remap(struct drm_plane *plane)
592{
593 struct sde_plane *psde;
594 struct sde_vbif_set_qos_params qos_params;
595 struct msm_drm_private *priv;
596 struct sde_kms *sde_kms;
597
598 if (!plane || !plane->dev) {
599 SDE_ERROR("invalid arguments\n");
600 return;
601 }
602
603 priv = plane->dev->dev_private;
604 if (!priv || !priv->kms) {
605 SDE_ERROR("invalid KMS reference\n");
606 return;
607 }
608
609 sde_kms = to_sde_kms(priv->kms);
610 psde = to_sde_plane(plane);
611 if (!psde->pipe_hw) {
612 SDE_ERROR("invalid pipe reference\n");
613 return;
614 }
615
616 memset(&qos_params, 0, sizeof(qos_params));
617 qos_params.vbif_idx = VBIF_RT;
618 qos_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
619 qos_params.xin_id = psde->pipe_hw->cap->xin_id;
620 qos_params.num = psde->pipe_hw->idx - SSPP_VIG0;
621 qos_params.is_rt = psde->is_rt_pipe;
622
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700623 SDE_DEBUG("plane%d pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n",
Alan Kwonga62eeb82017-04-19 08:57:55 -0700624 plane->base.id, qos_params.num,
625 qos_params.vbif_idx,
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700626 qos_params.xin_id, qos_params.is_rt,
627 qos_params.clk_ctrl);
Alan Kwonga62eeb82017-04-19 08:57:55 -0700628
629 sde_vbif_set_qos_remap(sde_kms, &qos_params);
630}
631
Alan Kwong2349d742017-04-20 08:27:30 -0700632/**
633 * _sde_plane_set_ts_prefill - set prefill with traffic shaper
634 * @plane: Pointer to drm plane
635 * @pstate: Pointer to sde plane state
636 */
637static void _sde_plane_set_ts_prefill(struct drm_plane *plane,
638 struct sde_plane_state *pstate)
639{
640 struct sde_plane *psde;
641 struct sde_hw_pipe_ts_cfg cfg;
642 struct msm_drm_private *priv;
643 struct sde_kms *sde_kms;
644
645 if (!plane || !plane->dev) {
646 SDE_ERROR("invalid arguments");
647 return;
648 }
649
650 priv = plane->dev->dev_private;
651 if (!priv || !priv->kms) {
652 SDE_ERROR("invalid KMS reference\n");
653 return;
654 }
655
656 sde_kms = to_sde_kms(priv->kms);
657 psde = to_sde_plane(plane);
658 if (!psde->pipe_hw) {
659 SDE_ERROR("invalid pipe reference\n");
660 return;
661 }
662
663 if (!psde->pipe_hw || !psde->pipe_hw->ops.setup_ts_prefill)
664 return;
665
666 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_VBLANK_AMORTIZE);
667
668 memset(&cfg, 0, sizeof(cfg));
669 cfg.size = sde_plane_get_property(pstate,
670 PLANE_PROP_PREFILL_SIZE);
671 cfg.time = sde_plane_get_property(pstate,
672 PLANE_PROP_PREFILL_TIME);
673
674 SDE_DEBUG("plane%d size:%llu time:%llu\n",
675 plane->base.id, cfg.size, cfg.time);
Dhaval Patela5f75952017-07-25 11:17:41 -0700676 SDE_EVT32_VERBOSE(DRMID(plane), cfg.size, cfg.time);
Alan Kwong2349d742017-04-20 08:27:30 -0700677 psde->pipe_hw->ops.setup_ts_prefill(psde->pipe_hw, &cfg,
678 pstate->multirect_index);
679}
680
Clarence Ipcae1bb62016-07-07 12:07:13 -0400681/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400682static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400683 struct sde_plane_state *pstate, uint64_t fd)
684{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400685 if (!psde || !pstate) {
686 SDE_ERROR("invalid arg(s), plane %d state %d\n",
687 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400688 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400689 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400690
691 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400692 if (pstate->input_fence)
693 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400694
695 /* get fence pointer for later */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400696 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400697
Clarence Ip13a8cf42016-09-29 17:27:47 -0400698 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400699}
700
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700701/**
702 * _sde_plane_inline_rot_set_ot_limit - set OT limit for the given inline
703 * rotation xin client
704 * @plane: pointer to drm plane
705 * @crtc: pointer to drm crtc
706 * @cfg: pointer to rotator vbif config
707 * @rect_w: rotator frame width
708 * @rect_h: rotator frame height
709 */
710static void _sde_plane_inline_rot_set_ot_limit(struct drm_plane *plane,
711 struct drm_crtc *crtc, const struct sde_rot_vbif_cfg *cfg,
712 u32 rect_w, u32 rect_h)
713{
714 struct sde_vbif_set_ot_params ot_params;
715 struct msm_drm_private *priv;
716 struct sde_kms *sde_kms;
717
718 if (!plane || !plane->dev) {
719 SDE_ERROR("invalid arguments\n");
720 return;
721 }
722
723 priv = plane->dev->dev_private;
724 if (!priv || !priv->kms) {
725 SDE_ERROR("invalid KMS reference\n");
726 return;
727 }
728
729 sde_kms = to_sde_kms(priv->kms);
730
731 memset(&ot_params, 0, sizeof(ot_params));
732 ot_params.xin_id = cfg->xin_id;
733 ot_params.num = cfg->num;
734 ot_params.width = rect_w;
735 ot_params.height = rect_h;
736 ot_params.is_wfd = false;
737 ot_params.frame_rate = crtc->mode.vrefresh;
738 ot_params.vbif_idx = VBIF_RT;
739 ot_params.clk_ctrl = cfg->clk_ctrl;
740 ot_params.rd = cfg->is_read;
741
742 sde_vbif_set_ot_limit(sde_kms, &ot_params);
743}
744
745/**
746 * _sde_plane_inline_rot_set_qos_remap - set vbif QoS for the given inline
747 * rotation xin client
748 * @plane: Pointer to drm plane
749 * @cfg: Pointer to rotator vbif cfg
750 */
751static void _sde_plane_inline_rot_set_qos_remap(struct drm_plane *plane,
752 const struct sde_rot_vbif_cfg *cfg)
753{
754 struct sde_vbif_set_qos_params qos_params;
755 struct msm_drm_private *priv;
756 struct sde_kms *sde_kms;
757
758 if (!plane || !plane->dev) {
759 SDE_ERROR("invalid arguments\n");
760 return;
761 }
762
763 priv = plane->dev->dev_private;
764 if (!priv || !priv->kms) {
765 SDE_ERROR("invalid KMS reference\n");
766 return;
767 }
768
769 sde_kms = to_sde_kms(priv->kms);
770
771 memset(&qos_params, 0, sizeof(qos_params));
772 qos_params.vbif_idx = VBIF_RT;
773 qos_params.xin_id = cfg->xin_id;
774 qos_params.clk_ctrl = cfg->clk_ctrl;
775 qos_params.num = cfg->num;
776 qos_params.is_rt = true;
777
778 SDE_DEBUG("vbif:%d xin:%d num:%d rt:%d clk_ctrl:%d\n",
779 qos_params.vbif_idx, qos_params.xin_id,
780 qos_params.num, qos_params.is_rt, qos_params.clk_ctrl);
781
782 sde_vbif_set_qos_remap(sde_kms, &qos_params);
783}
784
Clarence Ipcae1bb62016-07-07 12:07:13 -0400785int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400786{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400787 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400788 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400789 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400790 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400791 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800792 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400793
794 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700795 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400796 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400797 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400798 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400799 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400800 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400801 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400802
Clarence Ipcae1bb62016-07-07 12:07:13 -0400803 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800804 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400805 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800806 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400807
Dhaval Patel39323d42017-03-01 23:48:24 -0800808 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400809 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400810 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
811 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400812 psde->is_error = true;
Dhaval Patel39323d42017-03-01 23:48:24 -0800813 ret = -ETIMEDOUT;
814 break;
815 case -ERESTARTSYS:
816 SDE_ERROR_PLANE(psde,
817 "%ums wait interrupted on %08X\n",
818 wait_ms, prefix);
819 psde->is_error = true;
820 ret = -ERESTARTSYS;
821 break;
822 case -EINVAL:
823 SDE_ERROR_PLANE(psde,
824 "invalid fence param for %08X\n",
825 prefix);
826 psde->is_error = true;
827 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400828 break;
829 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800830 SDE_DEBUG_PLANE(psde, "signaled\n");
831 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400832 break;
833 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700834
835 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400836 } else {
837 ret = 0;
838 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400839 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400840 return ret;
841}
842
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700843/**
844 * _sde_plane_get_aspace: gets the address space based on the
845 * fb_translation mode property
846 */
847static int _sde_plane_get_aspace(
848 struct sde_plane *psde,
849 struct sde_plane_state *pstate,
850 struct msm_gem_address_space **aspace)
851{
852 struct sde_kms *kms;
853 int mode;
854
855 if (!psde || !pstate || !aspace) {
856 SDE_ERROR("invalid parameters\n");
857 return -EINVAL;
858 }
859
860 kms = _sde_plane_get_kms(&psde->base);
861 if (!kms) {
862 SDE_ERROR("invalid kms\n");
863 return -EINVAL;
864 }
865
866 mode = sde_plane_get_property(pstate,
867 PLANE_PROP_FB_TRANSLATION_MODE);
868
869 switch (mode) {
870 case SDE_DRM_FB_NON_SEC:
871 *aspace = kms->aspace[MSM_SMMU_DOMAIN_UNSECURE];
872 if (!aspace)
873 return -EINVAL;
874 break;
875 case SDE_DRM_FB_SEC:
876 *aspace = kms->aspace[MSM_SMMU_DOMAIN_SECURE];
877 if (!aspace)
878 return -EINVAL;
879 break;
880 case SDE_DRM_FB_SEC_DIR_TRANS:
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700881 *aspace = NULL;
882 break;
883 default:
884 SDE_ERROR("invalid fb_translation mode:%d\n", mode);
885 return -EFAULT;
886 }
887
888 return 0;
889}
890
Clarence Ip282dad62016-09-27 17:07:35 -0400891static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400892 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400893 struct sde_hw_pipe_cfg *pipe_cfg,
894 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400895{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400896 struct sde_plane *psde;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700897 struct msm_gem_address_space *aspace = NULL;
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700898 int ret, mode;
899 bool secure = false;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400900
Clarence Ip13a8cf42016-09-29 17:27:47 -0400901 if (!plane || !pstate || !pipe_cfg || !fb) {
902 SDE_ERROR(
903 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
904 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400905 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400906 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400907
908 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400909 if (!psde->pipe_hw) {
910 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400911 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400912 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400913
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700914 ret = _sde_plane_get_aspace(psde, pstate, &aspace);
915 if (ret) {
916 SDE_ERROR_PLANE(psde, "Failed to get aspace %d\n", ret);
917 return;
918 }
919
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -0700920 /*
921 * framebuffer prepare is deferred for prepare_fb calls that
922 * happen during the transition from secure to non-secure.
923 * Handle the prepare at this point for such cases. This can be
924 * expected for one or two frames during the transition.
925 */
926 if (aspace && pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700927 SDE_EVT32(DRMID(plane), psde->pipe, aspace->domain_attached);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -0700928 ret = msm_framebuffer_prepare(fb, pstate->aspace);
929 if (ret) {
930 SDE_ERROR_PLANE(psde,
931 "failed to prepare framebuffer %d\n", ret);
932 return;
933 }
934 pstate->defer_prepare_fb = false;
935 }
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700936 mode = sde_plane_get_property(pstate, PLANE_PROP_FB_TRANSLATION_MODE);
937 if ((mode == SDE_DRM_FB_SEC) || (mode == SDE_DRM_FB_SEC_DIR_TRANS))
938 secure = true;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -0700939
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700940 ret = sde_format_populate_layout(aspace, fb, &pipe_cfg->layout);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400941 if (ret == -EAGAIN)
942 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
943 else if (ret)
944 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
Alan Kwongc16e0922017-05-11 14:50:46 -0700945 else if (psde->pipe_hw->ops.setup_sourceaddress) {
Dhaval Patela5f75952017-07-25 11:17:41 -0700946 SDE_EVT32_VERBOSE(psde->pipe_hw->idx,
Alan Kwongc16e0922017-05-11 14:50:46 -0700947 pipe_cfg->layout.width,
948 pipe_cfg->layout.height,
949 pipe_cfg->layout.plane_addr[0],
950 pipe_cfg->layout.plane_size[0],
951 pipe_cfg->layout.plane_addr[1],
952 pipe_cfg->layout.plane_size[1],
953 pipe_cfg->layout.plane_addr[2],
954 pipe_cfg->layout.plane_size[2],
955 pipe_cfg->layout.plane_addr[3],
956 pipe_cfg->layout.plane_size[3],
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700957 pstate->multirect_index,
958 secure);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800959 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
960 pstate->multirect_index);
Alan Kwongc16e0922017-05-11 14:50:46 -0700961 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400962}
963
abeykun48f407a2016-08-25 12:06:44 -0400964static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
965 struct sde_plane_state *pstate)
966{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500967 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400968 int ret = 0;
969
Clarence Ip172033f2017-06-13 10:52:56 -0400970 if (!psde || !pstate) {
Clarence Ip3bf8d872017-02-16 15:25:38 -0500971 SDE_ERROR("invalid args\n");
972 return -EINVAL;
Clarence Ip3bf8d872017-02-16 15:25:38 -0500973 }
974
Clarence Ip172033f2017-06-13 10:52:56 -0400975 cfg = &pstate->scaler3_cfg;
Clarence Ip3bf8d872017-02-16 15:25:38 -0500976
abeykun48f407a2016-08-25 12:06:44 -0400977 cfg->dir_lut = msm_property_get_blob(
978 &psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -0400979 &pstate->property_state, &cfg->dir_len,
abeykun48f407a2016-08-25 12:06:44 -0400980 PLANE_PROP_SCALER_LUT_ED);
981 cfg->cir_lut = msm_property_get_blob(
982 &psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -0400983 &pstate->property_state, &cfg->cir_len,
abeykun48f407a2016-08-25 12:06:44 -0400984 PLANE_PROP_SCALER_LUT_CIR);
985 cfg->sep_lut = msm_property_get_blob(
986 &psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -0400987 &pstate->property_state, &cfg->sep_len,
abeykun48f407a2016-08-25 12:06:44 -0400988 PLANE_PROP_SCALER_LUT_SEP);
989 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
990 ret = -ENODATA;
991 return ret;
992}
993
Clarence Ipcb410d42016-06-26 22:52:33 -0400994static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -0400995 struct sde_plane_state *pstate,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400996 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
997 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400998 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400999 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
1000{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001001 uint32_t decimated, i;
1002
Clarence Ip172033f2017-06-13 10:52:56 -04001003 if (!psde || !pstate || !scale_cfg || !fmt || !chroma_subsmpl_h ||
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001004 !chroma_subsmpl_v) {
Clarence Ip172033f2017-06-13 10:52:56 -04001005 SDE_ERROR(
1006 "psde %d pstate %d scale_cfg %d fmt %d smp_h %d smp_v %d\n",
1007 !!psde, !!pstate, !!scale_cfg, !!fmt, chroma_subsmpl_h,
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001008 chroma_subsmpl_v);
1009 return;
1010 }
1011
1012 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip172033f2017-06-13 10:52:56 -04001013 memset(&pstate->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001014
1015 decimated = DECIMATED_DIMENSION(src_w,
1016 psde->pipe_cfg.horz_decimation);
1017 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
1018 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
1019 decimated = DECIMATED_DIMENSION(src_h,
1020 psde->pipe_cfg.vert_decimation);
1021 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
1022 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
1023
1024
1025 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
1026 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
1027 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
1028 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
1029
1030 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
1031 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
1032 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
1033 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
1034
1035 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
1036 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
1037 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
1038 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
1039
1040 for (i = 0; i < SDE_MAX_PLANES; i++) {
1041 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
1042 psde->pipe_cfg.horz_decimation);
1043 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
1044 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001045 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
1046 scale_cfg->src_width[i] /= chroma_subsmpl_h;
1047 scale_cfg->src_height[i] /= chroma_subsmpl_v;
1048 }
1049 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
1050 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
Clarence Ip172033f2017-06-13 10:52:56 -04001051 pstate->pixel_ext.num_ext_pxls_top[i] =
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001052 scale_cfg->src_height[i];
Clarence Ip172033f2017-06-13 10:52:56 -04001053 pstate->pixel_ext.num_ext_pxls_left[i] =
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001054 scale_cfg->src_width[i];
1055 }
1056 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
1057 && (src_w == dst_w))
1058 return;
1059
1060 scale_cfg->dst_width = dst_w;
1061 scale_cfg->dst_height = dst_h;
1062 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
1063 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
1064 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
1065 scale_cfg->lut_flag = 0;
1066 scale_cfg->blend_cfg = 1;
1067 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001068}
1069
Clarence Ipcb410d42016-06-26 22:52:33 -04001070/**
Clarence Ip13a8cf42016-09-29 17:27:47 -04001071 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -04001072 * @psde: Pointer to SDE plane object
1073 * @src: Source size
1074 * @dst: Destination size
1075 * @phase_steps: Pointer to output array for phase steps
1076 * @filter: Pointer to output array for filter type
1077 * @fmt: Pointer to format definition
1078 * @chroma_subsampling: Subsampling amount for chroma channel
1079 *
1080 * Returns: 0 on success
1081 */
1082static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001083 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001084 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001085 uint32_t chroma_subsampling)
1086{
Clarence Ipcb410d42016-06-26 22:52:33 -04001087 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001088 SDE_ERROR(
1089 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
1090 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001091 return -EINVAL;
1092 }
1093
Clarence Ip4c1d9772016-06-26 09:35:38 -04001094 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -04001095 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001096 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -04001097 phase_steps[SDE_SSPP_COMP_1_2] =
1098 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
1099 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
1100 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001101
1102 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -04001103 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -04001104 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001105 (src <= dst) ? SDE_SCALE_FILTER_BIL :
1106 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001107
Clarence Ipdbde9832016-06-26 09:48:36 -04001108 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001109 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -04001110 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
1111 } else {
1112 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
1113 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001114 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -04001115 }
1116 } else {
1117 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001118 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
1119 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
1120 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001121 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001122 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001123}
1124
Clarence Ipcb410d42016-06-26 22:52:33 -04001125/**
1126 * _sde_plane_setup_pixel_ext - determine default pixel extension values
1127 * @psde: Pointer to SDE plane object
1128 * @src: Source size
1129 * @dst: Destination size
1130 * @decimated_src: Source size after decimation, if any
1131 * @phase_steps: Pointer to output array for phase steps
1132 * @out_src: Output array for pixel extension values
1133 * @out_edge1: Output array for pixel extension first edge
1134 * @out_edge2: Output array for pixel extension second edge
1135 * @filter: Pointer to array for filter type
1136 * @fmt: Pointer to format definition
1137 * @chroma_subsampling: Subsampling amount for chroma channel
1138 * @post_compare: Whether to chroma subsampled source size for comparisions
1139 */
1140static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001141 uint32_t src, uint32_t dst, uint32_t decimated_src,
1142 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -04001143 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001144 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -04001145 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001146{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001147 int64_t edge1, edge2, caf;
1148 uint32_t src_work;
1149 int i, tmp;
1150
Clarence Ipcb410d42016-06-26 22:52:33 -04001151 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -04001152 out_edge2 && filter && fmt) {
1153 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001154 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001155 caf = PHASE_STEP_UNIT_SCALE;
1156 else
1157 caf = 0;
1158
1159 for (i = 0; i < SDE_MAX_PLANES; i++) {
1160 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -04001161 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001162 src_work /= chroma_subsampling;
1163 if (post_compare)
1164 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -04001165 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001166 /* unity */
1167 edge1 = 0;
1168 edge2 = 0;
1169 } else if (dst >= src) {
1170 /* upscale */
1171 edge1 = (1 << PHASE_RESIDUAL);
1172 edge1 -= caf;
1173 edge2 = (1 << PHASE_RESIDUAL);
1174 edge2 += (dst - 1) * *(phase_steps + i);
1175 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1176 edge2 += caf;
1177 edge2 = -(edge2);
1178 } else {
1179 /* downscale */
1180 edge1 = 0;
1181 edge2 = (dst - 1) * *(phase_steps + i);
1182 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1183 edge2 += *(phase_steps + i);
1184 edge2 = -(edge2);
1185 }
1186
1187 /* only enable CAF for luma plane */
1188 caf = 0;
1189
1190 /* populate output arrays */
1191 *(out_src + i) = src_work;
1192
1193 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001194 if (edge1 >= 0) {
1195 tmp = (uint32_t)edge1;
1196 tmp >>= PHASE_STEP_SHIFT;
1197 *(out_edge1 + i) = -tmp;
1198 } else {
1199 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -04001200 *(out_edge1 + i) =
1201 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1202 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001203 }
1204 if (edge2 >= 0) {
1205 tmp = (uint32_t)edge2;
1206 tmp >>= PHASE_STEP_SHIFT;
1207 *(out_edge2 + i) = -tmp;
1208 } else {
1209 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -04001210 *(out_edge2 + i) =
1211 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1212 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001213 }
1214 }
1215 }
1216}
1217
Clarence Ip5fc00c52016-09-23 15:03:34 -04001218static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -04001219{
1220 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
1221 {
Clarence Ip373f8592016-05-26 00:58:42 -04001222 /* S15.16 format */
1223 0x00012A00, 0x00000000, 0x00019880,
1224 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1225 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -04001226 },
Clarence Ip373f8592016-05-26 00:58:42 -04001227 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -04001228 { 0xfff0, 0xff80, 0xff80,},
1229 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001230 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -04001231 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001232 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -04001233 };
abeykun1c312f62016-08-26 09:47:12 -04001234 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
1235 {
1236 /* S15.16 format */
1237 0x00012A00, 0x00000000, 0x00019880,
1238 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1239 0x00012A00, 0x00020480, 0x00000000,
1240 },
1241 /* signed bias */
1242 { 0xffc0, 0xfe00, 0xfe00,},
1243 { 0x0, 0x0, 0x0,},
1244 /* unsigned clamp */
1245 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
1246 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
1247 };
Clarence Ipe78efb72016-06-24 18:35:21 -04001248
Clarence Ip5fc00c52016-09-23 15:03:34 -04001249 if (!psde) {
1250 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001251 return;
1252 }
Clarence Ip5e2a9222016-06-26 22:38:24 -04001253
Clarence Ipcae1bb62016-07-07 12:07:13 -04001254 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001255 if (psde->csc_usr_ptr)
1256 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -04001257 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
1258 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001259 else
Clarence Ip373f8592016-05-26 00:58:42 -04001260 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001261
Clarence Ip13a8cf42016-09-29 17:27:47 -04001262 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -04001263 psde->csc_ptr->csc_mv[0],
1264 psde->csc_ptr->csc_mv[1],
1265 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -04001266}
1267
Benet Clarkeb1b4462016-06-27 14:43:06 -07001268static void sde_color_process_plane_setup(struct drm_plane *plane)
1269{
1270 struct sde_plane *psde;
1271 struct sde_plane_state *pstate;
1272 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001273 struct drm_msm_memcol *memcol = NULL;
1274 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001275
1276 psde = to_sde_plane(plane);
1277 pstate = to_sde_plane_state(plane->state);
1278
1279 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1280 if (psde->pipe_hw->ops.setup_pa_hue)
1281 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1282 saturation = (uint32_t) sde_plane_get_property(pstate,
1283 PLANE_PROP_SATURATION_ADJUST);
1284 if (psde->pipe_hw->ops.setup_pa_sat)
1285 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1286 value = (uint32_t) sde_plane_get_property(pstate,
1287 PLANE_PROP_VALUE_ADJUST);
1288 if (psde->pipe_hw->ops.setup_pa_val)
1289 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1290 contrast = (uint32_t) sde_plane_get_property(pstate,
1291 PLANE_PROP_CONTRAST_ADJUST);
1292 if (psde->pipe_hw->ops.setup_pa_cont)
1293 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001294
Benet Clarkd009b1d2016-06-27 14:45:59 -07001295 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1296 /* Skin memory color setup */
1297 memcol = msm_property_get_blob(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001298 &pstate->property_state,
Benet Clarkd009b1d2016-06-27 14:45:59 -07001299 &memcol_sz,
1300 PLANE_PROP_SKIN_COLOR);
1301 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1302 MEMCOLOR_SKIN, memcol);
1303
1304 /* Sky memory color setup */
1305 memcol = msm_property_get_blob(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001306 &pstate->property_state,
Benet Clarkd009b1d2016-06-27 14:45:59 -07001307 &memcol_sz,
1308 PLANE_PROP_SKY_COLOR);
1309 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1310 MEMCOLOR_SKY, memcol);
1311
1312 /* Foliage memory color setup */
1313 memcol = msm_property_get_blob(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001314 &pstate->property_state,
Benet Clarkd009b1d2016-06-27 14:45:59 -07001315 &memcol_sz,
1316 PLANE_PROP_FOLIAGE_COLOR);
1317 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1318 MEMCOLOR_FOLIAGE, memcol);
1319 }
1320}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001321
Clarence Ipcb410d42016-06-26 22:52:33 -04001322static void _sde_plane_setup_scaler(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -04001323 struct sde_plane_state *pstate,
1324 const struct sde_format *fmt, bool color_fill)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001325{
Clarence Ipb43d4592016-09-08 14:21:35 -04001326 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001327 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001328
Clarence Ip172033f2017-06-13 10:52:56 -04001329 if (!psde || !fmt || !pstate) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001330 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1331 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001332 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001333 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001334
Clarence Ip172033f2017-06-13 10:52:56 -04001335 pe = &pstate->pixel_ext;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001336
Clarence Ipdedbba92016-09-27 17:43:10 -04001337 psde->pipe_cfg.horz_decimation =
1338 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1339 psde->pipe_cfg.vert_decimation =
1340 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001341
1342 /* don't chroma subsample if decimating */
1343 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001344 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001345 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001346 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001347
Clarence Ip5e2a9222016-06-26 22:38:24 -04001348 /* update scaler */
1349 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ip172033f2017-06-13 10:52:56 -04001350 int rc;
abeykun48f407a2016-08-25 12:06:44 -04001351
Clarence Ip172033f2017-06-13 10:52:56 -04001352 if (!color_fill && !psde->debugfs_default_scale)
1353 rc = _sde_plane_setup_scaler3_lut(psde, pstate);
1354 else
1355 rc = -EINVAL;
1356 if (rc || pstate->scaler_check_state !=
1357 SDE_PLANE_SCLCHECK_SCALER_V2) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001358 /* calculate default config for QSEED3 */
Clarence Ip172033f2017-06-13 10:52:56 -04001359 _sde_plane_setup_scaler3(psde, pstate,
Clarence Ipcb410d42016-06-26 22:52:33 -04001360 psde->pipe_cfg.src_rect.w,
1361 psde->pipe_cfg.src_rect.h,
1362 psde->pipe_cfg.dst_rect.w,
1363 psde->pipe_cfg.dst_rect.h,
Clarence Ip172033f2017-06-13 10:52:56 -04001364 &pstate->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001365 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001366 }
Clarence Ip172033f2017-06-13 10:52:56 -04001367 } else if (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 ||
1368 color_fill || psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001369 uint32_t deci_dim, i;
1370
Clarence Ipb43d4592016-09-08 14:21:35 -04001371 /* calculate default configuration for QSEED2 */
1372 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001373
Clarence Ip13a8cf42016-09-29 17:27:47 -04001374 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001375 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1376 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001377 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001378 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001379 psde->pipe_cfg.dst_rect.w,
1380 pe->phase_step_x,
1381 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001382
Clarence Ipdbde9832016-06-26 09:48:36 -04001383 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001384 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001385 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001386 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001387 pe->phase_step_x,
1388 pe->roi_w,
1389 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001390 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001391 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001392
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001393 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001394 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001395 _sde_plane_setup_scaler2(psde,
1396 deci_dim,
1397 psde->pipe_cfg.dst_rect.h,
1398 pe->phase_step_y,
1399 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001400 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001401 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001402 pe->phase_step_y,
1403 pe->roi_h,
1404 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001405 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001406 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001407
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001408 for (i = 0; i < SDE_MAX_PLANES; i++) {
1409 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001410 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001411 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001412 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001413
1414 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001415 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001416 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001417 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001418
1419 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001420 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001421 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001422 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001423
1424 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001425 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001426 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001427 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001428 }
1429 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001430}
1431
Clarence Ipcae1bb62016-07-07 12:07:13 -04001432/**
1433 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001434 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001435 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1436 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1437 * Returns: 0 on success
1438 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001439static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001440 uint32_t color, uint32_t alpha)
1441{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001442 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001443 const struct drm_plane *plane;
Clarence Ip172033f2017-06-13 10:52:56 -04001444 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001445
Clarence Ip172033f2017-06-13 10:52:56 -04001446 if (!psde || !psde->base.state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001447 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001448 return -EINVAL;
1449 }
1450
Clarence Ipcb410d42016-06-26 22:52:33 -04001451 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001452 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001453 return -EINVAL;
1454 }
1455
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001456 plane = &psde->base;
1457 pstate = to_sde_plane_state(plane->state);
1458
Clarence Ip13a8cf42016-09-29 17:27:47 -04001459 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001460
Clarence Ipcb410d42016-06-26 22:52:33 -04001461 /*
1462 * select fill format to match user property expectation,
1463 * h/w only supports RGB variants
1464 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001465 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001466
1467 /* update sspp */
1468 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1469 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001470 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1471 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001472
1473 /* override scaler/decimation if solid fill */
1474 psde->pipe_cfg.src_rect.x = 0;
1475 psde->pipe_cfg.src_rect.y = 0;
1476 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1477 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Clarence Ip172033f2017-06-13 10:52:56 -04001478 _sde_plane_setup_scaler(psde, pstate, fmt, true);
Clarence Ipcb410d42016-06-26 22:52:33 -04001479
Clarence Ipcb410d42016-06-26 22:52:33 -04001480 if (psde->pipe_hw->ops.setup_format)
1481 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001482 fmt, SDE_SSPP_SOLID_FILL,
1483 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001484
1485 if (psde->pipe_hw->ops.setup_rects)
1486 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001487 &psde->pipe_cfg,
1488 pstate->multirect_index);
1489
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001490 if (psde->pipe_hw->ops.setup_pe)
1491 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04001492 &pstate->pixel_ext);
Dhaval Patel2bbe8702017-08-30 21:22:52 -07001493
1494 if (psde->pipe_hw->ops.setup_scaler &&
1495 pstate->multirect_index != SDE_SSPP_RECT_1)
1496 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
1497 &psde->pipe_cfg, &pstate->pixel_ext,
1498 &pstate->scaler3_cfg);
Clarence Ipcb410d42016-06-26 22:52:33 -04001499 }
1500
1501 return 0;
1502}
1503
Alan Kwong4dd64c82017-02-04 18:41:51 -08001504/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001505 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1506 */
1507static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1508{
1509 drm_framebuffer_reference(fb);
1510 return fb;
1511}
1512static void _sde_plane_fb_put(void *fb)
1513{
1514 drm_framebuffer_unreference(fb);
1515}
1516static struct sde_crtc_res_ops fb_res_ops = {
1517 .put = _sde_plane_fb_put,
1518 .get = _sde_plane_fb_get,
1519};
1520
1521/**
1522 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1523 */
1524static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1525{
1526 sde_kms_fbo_reference(fbo);
1527 return fbo;
1528}
1529static void _sde_plane_fbo_put(void *fbo)
1530{
1531 sde_kms_fbo_unreference(fbo);
1532}
1533static struct sde_crtc_res_ops fbo_res_ops = {
1534 .put = _sde_plane_fbo_put,
1535 .get = _sde_plane_fbo_get,
1536};
1537
1538/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001539 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001540 * @plane: Pointer to drm plane
1541 * return: prefill time in line
1542 */
Clarence Ipb776b532017-09-12 18:30:06 -04001543u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001544{
1545 struct drm_plane_state *state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001546 struct sde_plane_state *pstate;
1547 struct sde_plane_rot_state *rstate;
1548 struct sde_kms *sde_kms;
1549 u32 blocksize = 128;
1550 u32 prefill_line = 0;
1551
Clarence Ip7eb90452017-05-23 11:41:19 -04001552 if (!plane || !plane->state || !plane->state->fb) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001553 SDE_ERROR("invalid parameters\n");
1554 return 0;
1555 }
1556
1557 sde_kms = _sde_plane_get_kms(plane);
1558 state = plane->state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001559 pstate = to_sde_plane_state(state);
1560 rstate = &pstate->rot;
1561
Clarence Ip7eb90452017-05-23 11:41:19 -04001562 if (!sde_kms || !sde_kms->catalog) {
1563 SDE_ERROR("invalid kms\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08001564 return 0;
1565 }
1566
Clarence Ip7eb90452017-05-23 11:41:19 -04001567 if (rstate->out_fb_format)
1568 sde_format_get_block_size(rstate->out_fb_format,
1569 &blocksize, &blocksize);
1570
Alan Kwong4dd64c82017-02-04 18:41:51 -08001571 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
Alan Kwongd2681812017-08-27 21:24:43 -04001572 prefill_line = mult_frac(prefill_line, rstate->out_src_h >> 16,
1573 state->crtc_h);
1574 SDE_DEBUG(
1575 "plane%d.%d blk:%u head:%u vdst/vsrc:%u/%u prefill:%u\n",
1576 plane->base.id, rstate->sequence_id,
1577 blocksize, sde_kms->catalog->sbuf_headroom,
1578 state->crtc_h, rstate->out_src_h >> 16,
1579 prefill_line);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001580
1581 return prefill_line;
1582}
1583
1584/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08001585 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1586 * enumerating over all planes attached to the same rotator
1587 * @plane: Pointer to drm plane
1588 * @state: Pointer to drm state to be updated
Alan Kwong05109752017-08-12 20:26:45 -04001589 * return: 0 if success; error code otherwise
Alan Kwong4dd64c82017-02-04 18:41:51 -08001590 */
Alan Kwong05109752017-08-12 20:26:45 -04001591static int sde_plane_rot_calc_cfg(struct drm_plane *plane,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001592 struct drm_plane_state *state)
1593{
1594 struct sde_plane_state *pstate;
1595 struct sde_plane_rot_state *rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001596 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001597 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001598 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001599 u32 dst_x, dst_y, dst_w, dst_h;
1600 int found = 0;
1601 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001602 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001603
1604 if (!plane || !state || !state->state) {
1605 SDE_ERROR("invalid parameters\n");
Alan Kwong05109752017-08-12 20:26:45 -04001606 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001607 }
1608
Alan Kwongcdb2f282017-03-18 13:42:06 -07001609 cstate = _sde_plane_get_crtc_state(state);
1610 if (IS_ERR_OR_NULL(cstate)) {
1611 ret = PTR_ERR(cstate);
1612 SDE_ERROR("invalid crtc state %d\n", ret);
Alan Kwong05109752017-08-12 20:26:45 -04001613 return ret;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001614 }
1615
Alan Kwong4dd64c82017-02-04 18:41:51 -08001616 pstate = to_sde_plane_state(state);
1617 rstate = &pstate->rot;
1618
Alan Kwong4dd64c82017-02-04 18:41:51 -08001619 in_rot = &rstate->in_rot_rect;
1620 in_rot->x1 = state->src_x;
1621 in_rot->y1 = state->src_y;
1622 in_rot->x2 = state->src_x + state->src_w;
1623 in_rot->y2 = state->src_y + state->src_h;
1624
1625 out_rot = &rstate->out_rot_rect;
1626 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1627 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1628 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1629 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1630
1631 if (!dst_w && !dst_h) {
1632 rstate->out_rot_rect = rstate->in_rot_rect;
1633 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1634 state->fb->height << 16, rstate->in_rotation);
1635 } else {
1636 out_rot->x1 = dst_x;
1637 out_rot->y1 = dst_y;
1638 out_rot->x2 = dst_x + dst_w;
1639 out_rot->y2 = dst_y + dst_h;
1640 }
1641
1642 rstate->out_src_rect = rstate->out_rot_rect;
1643
Alan Kwong4dd64c82017-02-04 18:41:51 -08001644 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001645 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001646 struct drm_plane_state *attached_state;
1647 struct sde_plane_state *attached_pstate;
1648 struct sde_plane_rot_state *attached_rstate;
1649 struct drm_rect attached_out_rect;
1650
Alan Kwong4dd64c82017-02-04 18:41:51 -08001651 attached_state = drm_atomic_get_existing_plane_state(
1652 state->state, attached_plane);
1653
1654 if (!attached_state)
1655 continue;
1656
1657 attached_pstate = to_sde_plane_state(attached_state);
1658 attached_rstate = &attached_pstate->rot;
1659
Clarence Ipd27d9632017-06-14 09:57:26 -04001660 if (attached_state->fb != state->fb)
1661 continue;
1662
1663 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) !=
1664 sde_plane_get_property(attached_pstate,
1665 PLANE_PROP_ROTATION))
Alan Kwongcdb2f282017-03-18 13:42:06 -07001666 continue;
1667
1668 found++;
1669
1670 /* skip itself */
1671 if (attached_plane == plane)
1672 continue;
1673
Alan Kwong4dd64c82017-02-04 18:41:51 -08001674 /* find bounding rotator source roi */
1675 if (attached_state->src_x < in_rot->x1)
1676 in_rot->x1 = attached_state->src_x;
1677
1678 if (attached_state->src_y < in_rot->y1)
1679 in_rot->y1 = attached_state->src_y;
1680
1681 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1682 in_rot->x2 = attached_state->src_x +
1683 attached_state->src_w;
1684
1685 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1686 in_rot->y2 = attached_state->src_y +
1687 attached_state->src_h;
1688
1689 /* find bounding rotator destination roi */
1690 dst_x = sde_plane_get_property(attached_pstate,
1691 PLANE_PROP_ROT_DST_X);
1692 dst_y = sde_plane_get_property(attached_pstate,
1693 PLANE_PROP_ROT_DST_Y);
1694 dst_w = sde_plane_get_property(attached_pstate,
1695 PLANE_PROP_ROT_DST_W);
1696 dst_h = sde_plane_get_property(attached_pstate,
1697 PLANE_PROP_ROT_DST_H);
1698 if (!dst_w && !dst_h) {
1699 attached_out_rect.x1 = attached_state->src_x;
1700 attached_out_rect.y1 = attached_state->src_y;
1701 attached_out_rect.x2 = attached_out_rect.x1 +
1702 attached_state->src_w;
1703 attached_out_rect.y2 = attached_out_rect.y1 +
1704 attached_state->src_h;
1705 drm_rect_rotate(&attached_out_rect,
1706 state->fb->width << 16,
1707 state->fb->height << 16,
1708 rstate->in_rotation);
1709 } else {
1710 attached_out_rect.x1 = dst_x;
1711 attached_out_rect.y1 = dst_y;
1712 attached_out_rect.x2 = dst_x + dst_w;
1713 attached_out_rect.y2 = dst_y + dst_h;
1714 }
1715
Alan Kwong05109752017-08-12 20:26:45 -04001716 /* check source split left/right mismatch */
1717 if (attached_out_rect.y1 != rstate->out_src_rect.y1 ||
1718 attached_out_rect.y2 != rstate->out_src_rect.y2) {
1719 SDE_ERROR(
1720 "plane%d.%u src:%dx%d+%d+%d rot:0x%llx fb:%d plane%d.%u src:%dx%d+%d+%d rot:0x%llx fb:%d mismatch\n",
1721 plane->base.id,
1722 rstate->sequence_id,
1723 state->src_w >> 16,
1724 state->src_h >> 16,
1725 state->src_x >> 16,
1726 state->src_y >> 16,
1727 sde_plane_get_property(pstate,
1728 PLANE_PROP_ROTATION),
1729 state->fb ?
1730 state->fb->base.id :
1731 -1,
1732 attached_plane->base.id,
1733 attached_rstate->sequence_id,
1734 attached_state->src_w >> 16,
1735 attached_state->src_h >> 16,
1736 attached_state->src_x >> 16,
1737 attached_state->src_y >> 16,
1738 sde_plane_get_property(attached_pstate,
1739 PLANE_PROP_ROTATION),
1740 attached_state->fb ?
1741 attached_state->fb->base.id :
1742 -1);
1743 SDE_ERROR(
1744 "plane%d.%u sspp:%dx%d+%d+%d plane%d.%u sspp:%dx%d+%d+%d\n",
1745 plane->base.id,
1746 rstate->sequence_id,
1747 (rstate->out_src_rect.x2 -
1748 rstate->out_src_rect.x1) >> 16,
1749 (rstate->out_src_rect.y2 -
1750 rstate->out_src_rect.y1) >> 16,
1751 rstate->out_src_rect.x1 >> 16,
1752 rstate->out_src_rect.y1 >> 16,
1753 attached_plane->base.id,
1754 attached_rstate->sequence_id,
1755 (attached_out_rect.x2 -
1756 attached_out_rect.x1) >> 16,
1757 (attached_out_rect.y2 -
1758 attached_out_rect.y1) >> 16,
1759 attached_out_rect.x1 >> 16,
1760 attached_out_rect.y1 >> 16);
1761 SDE_EVT32(DRMID(plane),
1762 rstate->sequence_id,
1763 rstate->out_src_rect.x1 >> 16,
1764 rstate->out_src_rect.y1 >> 16,
1765 (rstate->out_src_rect.x2 -
1766 rstate->out_src_rect.x1) >> 16,
1767 (rstate->out_src_rect.y2 -
1768 rstate->out_src_rect.y1) >> 16,
1769 attached_plane->base.id,
1770 attached_rstate->sequence_id,
1771 attached_out_rect.x1 >> 16,
1772 attached_out_rect.y1 >> 16,
1773 (attached_out_rect.x2 -
1774 attached_out_rect.x1) >> 16,
1775 (attached_out_rect.y2 -
1776 attached_out_rect.y1) >> 16,
1777 SDE_EVTLOG_ERROR);
1778 return -EINVAL;
1779 }
1780
Alan Kwong4dd64c82017-02-04 18:41:51 -08001781 /* find relative sspp position */
1782 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1783 xpos++;
1784
1785 if (attached_out_rect.x1 < out_rot->x1)
1786 out_rot->x1 = attached_out_rect.x1;
1787
1788 if (attached_out_rect.y1 < out_rot->y1)
1789 out_rot->y1 = attached_out_rect.y1;
1790
1791 if (attached_out_rect.x2 > out_rot->x2)
1792 out_rot->x2 = attached_out_rect.x2;
1793
1794 if (attached_out_rect.y2 > out_rot->y2)
1795 out_rot->y2 = attached_out_rect.y2;
1796
1797 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1798 attached_plane->base.id,
1799 attached_rstate->sequence_id,
1800 attached_rstate->out_src_rect.x1 >> 16,
1801 attached_state->src_w >> 16,
1802 attached_state->src_h >> 16,
1803 attached_state->src_x >> 16,
1804 attached_state->src_y >> 16,
1805 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1806 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1807 attached_rstate->out_src_rect.x1 >> 16,
1808 attached_rstate->out_src_rect.y1 >> 16);
1809 }
1810
1811 rstate->out_xpos = xpos;
1812 rstate->nplane = found;
1813
1814 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1815 plane->base.id, rstate->sequence_id,
1816 rstate->out_xpos, rstate->nplane,
1817 drm_rect_width(in_rot) >> 16,
1818 drm_rect_height(in_rot) >> 16,
1819 in_rot->x1 >> 16, in_rot->y1 >> 16,
1820 drm_rect_width(&rstate->out_rot_rect) >> 16,
1821 drm_rect_height(&rstate->out_rot_rect) >> 16,
1822 rstate->out_rot_rect.x1 >> 16,
1823 rstate->out_rot_rect.y1 >> 16);
Clarence Ipeb39cce2017-07-19 14:12:43 -04001824 SDE_EVT32(DRMID(plane), rstate->sequence_id,
Clarence Ipf27c6f22017-07-10 18:19:44 -04001825 rstate->out_xpos, rstate->nplane,
1826 in_rot->x1 >> 16, in_rot->y1 >> 16,
1827 drm_rect_width(in_rot) >> 16,
1828 drm_rect_height(in_rot) >> 16,
1829 rstate->out_rot_rect.x1 >> 16,
1830 rstate->out_rot_rect.y1 >> 16,
1831 drm_rect_width(&rstate->out_rot_rect) >> 16,
1832 drm_rect_height(&rstate->out_rot_rect) >> 16);
Alan Kwong05109752017-08-12 20:26:45 -04001833
1834 return 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001835}
1836
1837/**
1838 * sde_plane_rot_submit_command - commit given state for the rotator stage
1839 * @plane: Pointer to drm plane
1840 * @state: Pointer to the state to be committed
1841 * @hw_cmd: rotator command type
1842 * return: 0 if success; error code otherwise
1843 */
1844static int sde_plane_rot_submit_command(struct drm_plane *plane,
1845 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1846{
1847 struct sde_plane *psde = to_sde_plane(plane);
1848 struct sde_plane_state *pstate = to_sde_plane_state(state);
1849 struct sde_plane_rot_state *rstate = &pstate->rot;
1850 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001851 struct drm_crtc_state *cstate;
1852 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001853 int ret, i;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001854 int fb_mode;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001855
1856 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1857 SDE_ERROR("invalid parameters\n");
1858 return -EINVAL;
1859 }
1860
Alan Kwong4aacd532017-02-04 18:51:33 -08001861 cstate = _sde_plane_get_crtc_state(state);
1862 if (IS_ERR_OR_NULL(cstate)) {
1863 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1864 return -EINVAL;
1865 }
1866 sde_cstate = to_sde_crtc_state(cstate);
1867
Alan Kwong4dd64c82017-02-04 18:41:51 -08001868 rot_cmd = &rstate->rot_cmd;
1869
1870 rot_cmd->master = (rstate->out_xpos == 0);
1871 rot_cmd->sequence_id = rstate->sequence_id;
1872 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1873 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1874 DEFAULT_REFRESH_RATE;
1875 rot_cmd->rot90 = rstate->rot90;
1876 rot_cmd->hflip = rstate->hflip;
1877 rot_cmd->vflip = rstate->vflip;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001878 fb_mode = sde_plane_get_property(pstate,
1879 PLANE_PROP_FB_TRANSLATION_MODE);
1880 if ((fb_mode == SDE_DRM_FB_SEC) ||
1881 (fb_mode == SDE_DRM_FB_SEC_DIR_TRANS))
1882 rot_cmd->secure = true;
1883 else
1884 rot_cmd->secure = false;
1885
Alan Kwong4aacd532017-02-04 18:51:33 -08001886 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1887 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001888 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1889 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001890 rot_cmd->dst_writeback = psde->sbuf_writeback;
1891
1892 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1893 rot_cmd->video_mode = true;
1894 else
1895 rot_cmd->video_mode = false;
1896
1897 rot_cmd->src_pixel_format = state->fb->pixel_format;
1898 rot_cmd->src_modifier = state->fb->modifier[0];
1899 rot_cmd->src_stride = state->fb->pitches[0];
1900
1901 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1902 if (!rot_cmd->src_format) {
1903 SDE_ERROR("failed to get src format\n");
1904 return -EINVAL;
1905 }
1906
1907 rot_cmd->src_width = state->fb->width;
1908 rot_cmd->src_height = state->fb->height;
1909 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1910 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1911 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1912 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
Alan Kwong809f3cbd2017-08-11 18:39:36 -04001913 rot_cmd->dst_rect_x = 0;
1914 rot_cmd->dst_rect_y = 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001915 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1916 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1917
1918 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1919 struct sde_hw_fmt_layout layout;
1920
1921 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Clarence Ip299fa602017-07-11 18:01:37 -04001922 sde_format_populate_layout(pstate->aspace, state->fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001923 &layout);
1924 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1925 rot_cmd->src_iova[i] = layout.plane_addr[i];
1926 rot_cmd->src_len[i] = layout.plane_size[i];
1927 }
1928 rot_cmd->src_planes = layout.num_planes;
1929
1930 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Clarence Ip299fa602017-07-11 18:01:37 -04001931 sde_format_populate_layout(pstate->aspace, rstate->out_fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001932 &layout);
1933 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1934 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1935 rot_cmd->dst_len[i] = layout.plane_size[i];
1936 }
1937 rot_cmd->dst_planes = layout.num_planes;
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001938
1939 /* VBIF remapper settings */
Alan Kwong032c2e182017-06-29 16:31:38 -04001940 for (i = 0; i < rstate->rot_hw->caps->xin_count; i++) {
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001941 const struct sde_rot_vbif_cfg *cfg =
1942 &rstate->rot_hw->caps->vbif_cfg[i];
1943
1944 _sde_plane_inline_rot_set_qos_remap(plane, cfg);
1945
1946 if (cfg->is_read) {
1947 _sde_plane_inline_rot_set_ot_limit(plane,
1948 state->crtc, cfg, rot_cmd->src_rect_w,
1949 rot_cmd->src_rect_h);
1950 } else {
1951 _sde_plane_inline_rot_set_ot_limit(plane,
1952 state->crtc, cfg, rot_cmd->dst_rect_w,
1953 rot_cmd->dst_rect_h);
1954 }
1955 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001956 }
1957
1958 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
Alan Kwong05109752017-08-12 20:26:45 -04001959 if (ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001960 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001961
1962 rstate->out_rotation = rstate->in_rotation;
1963 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1964 DRM_MODE_FB_MODIFIERS : 0;
1965 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1966 rstate->out_fb_format = rot_cmd->dst_format;
1967 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1968
1969 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1970 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1971
1972 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1973 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1974 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1975 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1976 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1977 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1978
1979 if (rot_cmd->rot90)
1980 rstate->out_rotation &= ~DRM_ROTATE_90;
1981
1982 if (rot_cmd->hflip)
1983 rstate->out_rotation &= ~DRM_REFLECT_X;
1984
1985 if (rot_cmd->vflip)
1986 rstate->out_rotation &= ~DRM_REFLECT_Y;
1987
1988 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07001989 "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 -08001990 plane->base.id, rstate->sequence_id, hw_cmd,
1991 rot_cmd->rot90 ? 'r' : '_',
1992 rot_cmd->hflip ? 'h' : '_',
1993 rot_cmd->vflip ? 'v' : '_',
1994 rot_cmd->video_mode ? 'V' : 'C',
1995 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07001996 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001997 state->fb->modifier[0],
1998 drm_rect_width(&rstate->in_rot_rect) >> 16,
1999 drm_rect_height(&rstate->in_rot_rect) >> 16,
2000 rstate->in_rot_rect.x1 >> 16,
2001 rstate->in_rot_rect.y1 >> 16);
2002
Dhaval Patel6c666622017-03-21 23:02:59 -07002003 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 -08002004 plane->base.id, rstate->sequence_id, hw_cmd,
2005 rstate->out_rotation,
2006 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002007 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002008 rstate->out_fb_modifier[0],
2009 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2010 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
2011
2012 return ret;
2013}
2014
2015/**
Clarence Ipd27d9632017-06-14 09:57:26 -04002016 * _sde_plane_rot_get_fb - attempt to get previously allocated fb/fbo
2017 * If an fb/fbo was already created, either from a previous frame or
2018 * from another plane in the current commit cycle, attempt to reuse
2019 * it for this commit cycle as well.
2020 * @plane: Pointer to drm plane
2021 * @cstate: Pointer to crtc state
2022 * @rstate: Pointer to rotator plane state
2023 */
2024static void _sde_plane_rot_get_fb(struct drm_plane *plane,
2025 struct drm_crtc_state *cstate,
2026 struct sde_plane_rot_state *rstate)
2027{
2028 struct sde_kms_fbo *fbo;
2029 struct drm_framebuffer *fb;
2030
Clarence Ipf27c6f22017-07-10 18:19:44 -04002031 if (!plane || !cstate || !rstate || !rstate->rot_hw)
Clarence Ipd27d9632017-06-14 09:57:26 -04002032 return;
2033
2034 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2035 (u64) &rstate->rot_hw->base);
2036 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2037 (u64) &rstate->rot_hw->base);
2038 if (fb && fbo) {
2039 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
2040 rstate->sequence_id);
2041 } else if (fbo) {
2042 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2043 (u64) &rstate->rot_hw->base);
2044 fbo = NULL;
2045 } else if (fb) {
2046 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2047 (u64) &rstate->rot_hw->base);
2048 fb = NULL;
2049 }
2050
2051 rstate->out_fbo = fbo;
2052 rstate->out_fb = fb;
2053}
2054
2055/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002056 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
2057 * for rotator (pre-sspp) stage
2058 * @plane: Pointer to drm plane
2059 * @new_state: Pointer to new drm plane state
2060 * return: 0 if success; error code otherwise
2061 */
2062static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
2063 struct drm_plane_state *new_state)
2064{
2065 struct drm_framebuffer *fb = new_state->fb;
2066 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
2067 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002068 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002069 int ret;
2070
2071 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
2072 plane->base.id,
2073 new_rstate->sequence_id, fb ? fb->base.id : 0,
2074 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
2075 sde_plane_crtc_enabled(new_state));
2076
2077 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
2078 return 0;
2079
Alan Kwongcdb2f282017-03-18 13:42:06 -07002080 cstate = _sde_plane_get_crtc_state(new_state);
2081 if (IS_ERR(cstate)) {
2082 ret = PTR_ERR(cstate);
2083 SDE_ERROR("invalid crtc state %d\n", ret);
2084 return ret;
2085 }
2086
Alan Kwong4dd64c82017-02-04 18:41:51 -08002087 /* need to re-calc based on all newly validated plane states */
Alan Kwong05109752017-08-12 20:26:45 -04002088 ret = sde_plane_rot_calc_cfg(plane, new_state);
2089 if (ret)
2090 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002091
2092 /* check if stream buffer is already attached to rotator */
Clarence Ipd27d9632017-06-14 09:57:26 -04002093 if (sde_plane_enabled(new_state) && !new_rstate->out_fb)
2094 _sde_plane_rot_get_fb(plane, cstate, new_rstate);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002095
Alan Kwong4dd64c82017-02-04 18:41:51 -08002096 /* create new stream buffer if it is not available */
2097 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
2098 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
2099 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
2100
2101 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
2102 new_rstate->sequence_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002103
2104 /* check if out_fb is already attached to rotator */
2105 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
2106 new_rstate->out_fb_pixel_format,
2107 new_rstate->out_fb_modifier,
2108 new_rstate->out_fb_flags);
2109 if (!new_rstate->out_fbo) {
2110 SDE_ERROR("failed to allocate inline buffer object\n");
2111 ret = -EINVAL;
2112 goto error_create_fbo;
2113 }
2114
Alan Kwongcdb2f282017-03-18 13:42:06 -07002115 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2116 (u64) &new_rstate->rot_hw->base,
2117 new_rstate->out_fbo, &fbo_res_ops);
2118 if (ret) {
2119 SDE_ERROR("failed to add crtc resource\n");
2120 goto error_create_fbo_res;
2121 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002122
2123 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
2124 new_rstate->out_fbo);
2125 if (!new_rstate->out_fb) {
2126 SDE_ERROR("failed to create inline framebuffer\n");
2127 ret = -EINVAL;
2128 goto error_create_fb;
2129 }
Clarence Ipf27c6f22017-07-10 18:19:44 -04002130 SDE_EVT32_VERBOSE(DRMID(plane), new_rstate->sequence_id,
2131 new_rstate->out_fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002132
Alan Kwongcdb2f282017-03-18 13:42:06 -07002133 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2134 (u64) &new_rstate->rot_hw->base,
2135 new_rstate->out_fb, &fb_res_ops);
2136 if (ret) {
2137 SDE_ERROR("failed to add crtc resource %d\n", ret);
2138 goto error_create_fb_res;
2139 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002140 }
2141
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002142 if (new_pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002143 SDE_EVT32(DRMID(plane));
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002144 SDE_DEBUG(
2145 "plane%d, domain not attached, prepare fb handled later\n",
2146 plane->base.id);
2147 return 0;
2148 }
2149
Alan Kwong4dd64c82017-02-04 18:41:51 -08002150 /* prepare rotator input buffer */
Clarence Ip299fa602017-07-11 18:01:37 -04002151 ret = msm_framebuffer_prepare(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002152 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002153 SDE_ERROR("failed to prepare input framebuffer, %d\n", ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002154 goto error_prepare_input_buffer;
2155 }
2156
2157 /* prepare rotator output buffer */
2158 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
2159 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
2160 new_rstate->sequence_id);
2161
2162 ret = msm_framebuffer_prepare(new_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002163 new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002164 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002165 SDE_ERROR("failed to prepare inline framebuffer, %d\n",
2166 ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002167 goto error_prepare_output_buffer;
2168 }
2169 }
2170
2171 return 0;
2172
2173error_prepare_output_buffer:
Clarence Ip299fa602017-07-11 18:01:37 -04002174 msm_framebuffer_cleanup(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002175error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002176 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2177 (u64) &new_rstate->rot_hw->base);
2178error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002179 new_rstate->out_fb = NULL;
2180error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002181 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2182 (u64) &new_rstate->rot_hw->base);
2183error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002184 new_rstate->out_fbo = NULL;
2185error_create_fbo:
2186 return ret;
2187}
2188
2189/**
2190 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
2191 * rotator (pre-sspp) stage
2192 * @plane: Pointer to drm plane
2193 * @old_state: Pointer to previous drm plane state
2194 * return: none
2195 */
2196static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
2197 struct drm_plane_state *old_state)
2198{
2199 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
2200 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2201 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002202 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002203 int ret;
2204
2205 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2206 old_rstate->sequence_id, old_state->fb->base.id,
2207 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
2208 sde_plane_crtc_enabled(old_state));
2209
2210 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
2211 return;
2212
Alan Kwongcdb2f282017-03-18 13:42:06 -07002213 cstate = _sde_plane_get_crtc_state(old_state);
2214 if (IS_ERR(cstate)) {
2215 ret = PTR_ERR(cstate);
2216 SDE_ERROR("invalid crtc state %d\n", ret);
2217 return;
2218 }
2219
Alan Kwong4dd64c82017-02-04 18:41:51 -08002220 if (sde_plane_crtc_enabled(old_state)) {
2221 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
2222 SDE_HW_ROT_CMD_CLEANUP);
2223 if (ret)
2224 SDE_ERROR("failed to cleanup rotator buffers\n");
2225 }
2226
2227 if (sde_plane_enabled(old_state)) {
2228 if (old_rstate->out_fb) {
2229 msm_framebuffer_cleanup(old_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002230 old_pstate->aspace);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002231 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2232 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002233 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002234 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2235 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002236 old_rstate->out_fbo = NULL;
2237 }
2238
Clarence Ip299fa602017-07-11 18:01:37 -04002239 msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002240 }
2241}
2242
2243/**
2244 * sde_plane_rot_atomic_check - verify rotator update of the given state
2245 * @plane: Pointer to drm plane
2246 * @state: Pointer to drm plane state to be validated
2247 * return: 0 if success; error code otherwise
2248 */
2249static int sde_plane_rot_atomic_check(struct drm_plane *plane,
2250 struct drm_plane_state *state)
2251{
2252 struct sde_plane *psde;
2253 struct sde_plane_state *pstate, *old_pstate;
2254 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002255 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002256 struct sde_hw_blk *hw_blk;
2257 int i, ret = 0;
2258
2259 if (!plane || !state) {
2260 SDE_ERROR("invalid plane/state\n");
2261 return -EINVAL;
2262 }
2263
2264 psde = to_sde_plane(plane);
2265 pstate = to_sde_plane_state(state);
2266 old_pstate = to_sde_plane_state(plane->state);
2267 rstate = &pstate->rot;
2268 old_rstate = &old_pstate->rot;
2269
Alan Kwongcdb2f282017-03-18 13:42:06 -07002270 /* cstate will be null if crtc is disconnected from plane */
2271 cstate = _sde_plane_get_crtc_state(state);
2272 if (IS_ERR(cstate)) {
2273 ret = PTR_ERR(cstate);
2274 SDE_ERROR("invalid crtc state %d\n", ret);
2275 return ret;
2276 }
2277
Alan Kwong4dd64c82017-02-04 18:41:51 -08002278 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2279 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
2280 !!rstate->out_sbuf, !!rstate->rot_hw,
2281 sde_plane_crtc_enabled(state));
2282
2283 rstate->in_rotation = drm_rotation_simplify(
2284 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07002285 DRM_ROTATE_0 | DRM_ROTATE_90 |
2286 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002287 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
2288 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
2289 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
2290 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
2291
Alan Kwongcdb2f282017-03-18 13:42:06 -07002292 if (sde_plane_enabled(state) && rstate->out_sbuf) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002293 SDE_DEBUG("plane%d.%d acquire rotator, fb %d\n",
2294 plane->base.id, rstate->sequence_id,
2295 state->fb ? state->fb->base.id : -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002296
Alan Kwongcdb2f282017-03-18 13:42:06 -07002297 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
2298 (u64) state->fb);
2299 if (!hw_blk) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002300 SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
2301 plane->base.id, rstate->sequence_id,
2302 state->fb ? state->fb->base.id : -1);
Alan Kwong310e9b02017-08-03 02:04:07 -04002303 SDE_EVT32(DRMID(plane), rstate->sequence_id,
2304 SDE_EVTLOG_ERROR);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002305 return -EINVAL;
2306 }
2307
Alan Kwongcdb2f282017-03-18 13:42:06 -07002308 rstate->rot_hw = to_sde_hw_rot(hw_blk);
2309
Alan Kwong4dd64c82017-02-04 18:41:51 -08002310 if (!rstate->rot_hw->ops.commit) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002311 SDE_ERROR("plane%d.%d invalid rotator ops\n",
2312 plane->base.id, rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002313 sde_crtc_res_put(cstate,
2314 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002315 rstate->rot_hw = NULL;
2316 return -EINVAL;
2317 }
2318
2319 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002320 } else {
2321 rstate->in_fb = NULL;
2322 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002323 }
2324
2325 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002326 uint32_t fb_id;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002327
Clarence Ipf27c6f22017-07-10 18:19:44 -04002328 fb_id = state->fb ? state->fb->base.id : -1;
2329 SDE_DEBUG("plane%d.%d use rotator, fb %d\n",
2330 plane->base.id, rstate->sequence_id, fb_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002331
Alan Kwong05109752017-08-12 20:26:45 -04002332 ret = sde_plane_rot_calc_cfg(plane, state);
2333 if (ret)
2334 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002335
2336 ret = sde_plane_rot_submit_command(plane, state,
2337 SDE_HW_ROT_CMD_VALIDATE);
Clarence Ipf27c6f22017-07-10 18:19:44 -04002338 if (ret)
2339 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002340
Clarence Ip317a9572017-08-08 18:16:26 -04002341 if (rstate->nplane != old_rstate->nplane ||
2342 rstate->out_xpos != old_rstate->out_xpos)
2343 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2344 SDE_PLANE_DIRTY_RECTS;
2345
Clarence Ipf27c6f22017-07-10 18:19:44 -04002346 /* check if stream buffer is already attached to rotator */
2347 _sde_plane_rot_get_fb(plane, cstate, rstate);
2348
2349 /* release buffer if output format configuration changes */
2350 if (rstate->out_fb &&
2351 ((rstate->out_fb_height != rstate->out_fb->height) ||
2352 (rstate->out_fb_width != rstate->out_fb->width) ||
2353 (rstate->out_fb_pixel_format !=
2354 rstate->out_fb->pixel_format) ||
2355 (rstate->out_fb_modifier[0] !=
2356 rstate->out_fb->modifier[0]) ||
2357 (rstate->out_fb_flags != rstate->out_fb->flags))) {
2358
2359 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
2360 rstate->sequence_id);
2361 SDE_EVT32_VERBOSE(DRMID(plane),
2362 rstate->sequence_id, fb_id);
2363
2364 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2365 (u64) &rstate->rot_hw->base);
2366 rstate->out_fb = NULL;
2367 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2368 (u64) &rstate->rot_hw->base);
2369 rstate->out_fbo = NULL;
2370 }
Clarence Ip4475d582017-04-18 11:36:00 -04002371 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002372
2373 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
2374 rstate->sequence_id);
2375
2376 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04002377 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
2378 rstate->out_fb_modifier[i] = state->fb ?
2379 state->fb->modifier[i] : 0x0;
2380
2381 if (state->fb) {
2382 rstate->out_fb_pixel_format = state->fb->pixel_format;
2383 rstate->out_fb_flags = state->fb->flags;
2384 rstate->out_fb_width = state->fb->width;
2385 rstate->out_fb_height = state->fb->height;
2386 } else {
2387 rstate->out_fb_pixel_format = 0x0;
2388 rstate->out_fb_flags = 0x0;
2389 rstate->out_fb_width = 0;
2390 rstate->out_fb_height = 0;
2391 }
2392
Alan Kwong4dd64c82017-02-04 18:41:51 -08002393 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002394 rstate->out_src_x = state->src_x;
2395 rstate->out_src_y = state->src_y;
2396 rstate->out_src_w = state->src_w;
2397 rstate->out_src_h = state->src_h;
2398
2399 rstate->out_fb_format = NULL;
2400 rstate->out_sbuf = false;
2401 rstate->out_fb = state->fb;
2402 }
2403
2404 return ret;
2405}
2406
2407/**
2408 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2409 * @plane: Pointer to drm plane
2410 * @old_state: Pointer to previous state
2411 * return: none
2412 */
2413static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2414 struct drm_plane_state *old_state)
2415{
2416 struct drm_plane_state *state;
2417 struct sde_plane_state *pstate;
2418 struct sde_plane_rot_state *rstate;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002419 int ret = 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002420
2421 if (!plane || !plane->state) {
2422 SDE_ERROR("invalid plane/state\n");
2423 return;
2424 }
2425
2426 state = plane->state;
2427 pstate = to_sde_plane_state(state);
2428 rstate = &pstate->rot;
2429
2430 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2431 rstate->sequence_id,
2432 !!rstate->out_sbuf, !!rstate->rot_hw,
2433 sde_plane_crtc_enabled(plane->state));
2434
2435 if (!sde_plane_crtc_enabled(state))
2436 return;
2437
2438 if (!rstate->out_sbuf || !rstate->rot_hw)
2439 return;
2440
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002441 /*
2442 * framebuffer prepare is deferred for prepare_fb calls that
2443 * happen during the transition from secure to non-secure.
2444 * Handle the prepare at this point for rotator in such cases.
2445 * This can be expected for one or two frames during the transition.
2446 */
2447 if (pstate->aspace && pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002448 SDE_EVT32(DRMID(plane), pstate->aspace->domain_attached);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002449 /* prepare rotator input buffer */
2450 ret = msm_framebuffer_prepare(state->fb, pstate->aspace);
2451 if (ret) {
2452 SDE_ERROR("p%d failed to prepare input fb %d\n",
2453 plane->base.id, ret);
2454 return;
2455 }
2456
2457 /* prepare rotator output buffer */
2458 if (sde_plane_enabled(state) && rstate->out_fb) {
2459 ret = msm_framebuffer_prepare(rstate->out_fb,
2460 pstate->aspace);
2461 if (ret) {
2462 SDE_ERROR(
2463 "p%d failed to prepare inline fb %d\n",
2464 plane->base.id, ret);
2465 goto error_prepare_output_buffer;
2466 }
2467 }
2468 }
2469
Alan Kwong4dd64c82017-02-04 18:41:51 -08002470 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002471
2472 return;
2473
2474error_prepare_output_buffer:
2475 msm_framebuffer_cleanup(state->fb, pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002476}
2477
Clarence Ip8ee49952017-09-20 11:10:50 -04002478int sde_plane_kickoff_rot(struct drm_plane *plane)
Clarence Ipddbf7752017-05-21 18:07:30 -04002479{
Clarence Ipeb39cce2017-07-19 14:12:43 -04002480 struct sde_plane_state *pstate;
2481
2482 if (!plane || !plane->state) {
2483 SDE_ERROR("invalid plane\n");
Clarence Ip8ee49952017-09-20 11:10:50 -04002484 return -EINVAL;
Clarence Ipeb39cce2017-07-19 14:12:43 -04002485 }
2486
2487 pstate = to_sde_plane_state(plane->state);
2488
2489 if (!pstate->rot.rot_hw || !pstate->rot.rot_hw->ops.commit)
Clarence Ip8ee49952017-09-20 11:10:50 -04002490 return 0;
Clarence Ipddbf7752017-05-21 18:07:30 -04002491
Clarence Ip8ee49952017-09-20 11:10:50 -04002492 return pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
Clarence Ipddbf7752017-05-21 18:07:30 -04002493 &pstate->rot.rot_cmd,
2494 SDE_HW_ROT_CMD_START);
2495}
2496
2497/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002498 * sde_plane_rot_destroy_state - destroy state for rotator stage
2499 * @plane: Pointer to drm plane
2500 * @state: Pointer to state to be destroyed
2501 * return: none
2502 */
2503static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2504 struct drm_plane_state *state)
2505{
2506 struct sde_plane_state *pstate = to_sde_plane_state(state);
2507 struct sde_plane_rot_state *rstate = &pstate->rot;
2508
2509 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2510 rstate->sequence_id,
2511 !!rstate->out_sbuf, !!rstate->rot_hw,
2512 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002513}
2514
2515/**
2516 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2517 * @plane: Pointer to drm plane
2518 * @new_state: Pointer to duplicated state
2519 * return: 0 if success; error code otherwise
2520 */
2521static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2522 struct drm_plane_state *new_state)
2523{
2524 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2525 struct sde_plane_rot_state *rstate = &pstate->rot;
2526
2527 rstate->sequence_id++;
2528
2529 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2530 rstate->sequence_id,
2531 !!rstate->out_sbuf, !!rstate->rot_hw);
2532
Clarence Ipf27c6f22017-07-10 18:19:44 -04002533 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002534 rstate->out_fb = NULL;
2535 rstate->out_fbo = NULL;
2536
2537 return 0;
2538}
2539
2540/**
2541 * sde_plane_rot_install_caps - install plane rotator capabilities
2542 * @plane: Pointer to drm plane
2543 * return: none
2544 */
2545static void sde_plane_rot_install_caps(struct drm_plane *plane)
2546{
2547 struct sde_plane *psde = to_sde_plane(plane);
2548 const struct sde_format_extended *format_list;
2549 struct sde_kms_info *info;
2550 struct sde_hw_rot *rot_hw;
2551 const char *downscale_caps;
2552
2553 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2554 !psde->catalog->rot_count)
2555 return;
2556
2557 if (psde->blob_rot_caps)
2558 return;
2559
2560 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2561 if (!info)
2562 return;
2563
2564 rot_hw = sde_hw_rot_get(NULL);
2565 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2566 !rot_hw->ops.get_downscale_caps) {
2567 SDE_ERROR("invalid rotator hw\n");
2568 goto error_rot;
2569 }
2570
2571 sde_kms_info_reset(info);
2572
2573 format_list = rot_hw->ops.get_format_caps(rot_hw);
2574 if (format_list) {
2575 sde_kms_info_start(info, "pixel_formats");
2576 while (format_list->fourcc_format) {
2577 sde_kms_info_append_format(info,
2578 format_list->fourcc_format,
2579 format_list->modifier);
2580 ++format_list;
2581 }
2582 sde_kms_info_stop(info);
2583 }
2584
2585 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2586 if (downscale_caps) {
2587 sde_kms_info_start(info, "downscale_ratios");
2588 sde_kms_info_append(info, downscale_caps);
2589 sde_kms_info_stop(info);
2590 }
2591
2592 if (rot_hw->ops.get_cache_size)
2593 sde_kms_info_add_keyint(info, "cache_size",
2594 rot_hw->ops.get_cache_size(rot_hw));
2595
Alan Kwong1a915802017-03-31 12:55:46 -07002596 if (rot_hw->ops.get_maxlinewidth)
2597 sde_kms_info_add_keyint(info, "max_linewidth",
2598 rot_hw->ops.get_maxlinewidth(rot_hw));
2599
Alan Kwong4dd64c82017-02-04 18:41:51 -08002600 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
Narendra Muppalla22d17252017-05-31 15:13:39 -07002601 info->data, SDE_KMS_INFO_DATALEN(info),
2602 PLANE_PROP_ROT_CAPS_V1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002603
2604 sde_hw_rot_put(rot_hw);
2605error_rot:
2606 kfree(info);
2607}
2608
2609/**
2610 * sde_plane_rot_install_properties - install plane rotator properties
2611 * @plane: Pointer to drm plane
2612 * @catalog: Pointer to mdss configuration
2613 * return: none
2614 */
2615static void sde_plane_rot_install_properties(struct drm_plane *plane,
2616 struct sde_mdss_cfg *catalog)
2617{
2618 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002619 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2620 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002621
2622 if (!plane || !psde) {
2623 SDE_ERROR("invalid plane\n");
2624 return;
2625 } else if (!catalog) {
2626 SDE_ERROR("invalid catalog\n");
2627 return;
2628 }
2629
2630 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2631 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2632 DRM_ROTATE_180 | DRM_ROTATE_270;
2633
2634 msm_property_install_rotation(&psde->property_info,
2635 supported_rotations, PLANE_PROP_ROTATION);
2636
2637 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2638 return;
2639
2640 msm_property_install_range(&psde->property_info, "rot_dst_x",
2641 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2642 msm_property_install_range(&psde->property_info, "rot_dst_y",
2643 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2644 msm_property_install_range(&psde->property_info, "rot_dst_w",
2645 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2646 msm_property_install_range(&psde->property_info, "rot_dst_h",
2647 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2648 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2649 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2650}
2651
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002652void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002653{
Clarence Ipcb410d42016-06-26 22:52:33 -04002654 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002655
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002656 if (!drm_state)
2657 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002658
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002659 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002660
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002661 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2662 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002663}
2664
2665int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2666{
2667 struct sde_plane_state *pstate[R_MAX];
2668 const struct drm_plane_state *drm_state[R_MAX];
2669 struct sde_rect src[R_MAX], dst[R_MAX];
2670 struct sde_plane *sde_plane[R_MAX];
2671 const struct sde_format *fmt[R_MAX];
2672 bool q16_data = true;
Steve Cohenf5d01512017-07-07 18:49:21 -04002673 int i, buffer_lines;
2674 unsigned int max_tile_height = 1;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002675 bool parallel_fetch_qualified = true;
Steve Cohenf5d01512017-07-07 18:49:21 -04002676 bool has_tiled_rect = false;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002677
2678 for (i = 0; i < R_MAX; i++) {
2679 const struct msm_format *msm_fmt;
2680
2681 drm_state[i] = i ? plane->r1 : plane->r0;
Steve Cohenf5d01512017-07-07 18:49:21 -04002682 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2683 fmt[i] = to_sde_format(msm_fmt);
2684
2685 if (SDE_FORMAT_IS_UBWC(fmt[i])) {
2686 has_tiled_rect = true;
2687 if (fmt[i]->tile_height > max_tile_height)
2688 max_tile_height = fmt[i]->tile_height;
2689 }
2690 }
2691
2692 for (i = 0; i < R_MAX; i++) {
2693 int width_threshold;
2694
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002695 pstate[i] = to_sde_plane_state(drm_state[i]);
2696 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2697
2698 if (pstate[i] == NULL) {
2699 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2700 drm_state[i]->plane->base.id);
2701 return -EINVAL;
2702 }
2703
2704 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2705 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2706 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2707 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2708 drm_state[i]->crtc_h, !q16_data);
2709
2710 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2711 SDE_ERROR_PLANE(sde_plane[i],
2712 "scaling is not supported in multirect mode\n");
2713 return -EINVAL;
2714 }
2715
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002716 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2717 SDE_ERROR_PLANE(sde_plane[i],
2718 "Unsupported format for multirect mode\n");
2719 return -EINVAL;
2720 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002721
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002722 /**
2723 * SSPP PD_MEM is split half - one for each RECT.
2724 * Tiled formats need 5 lines of buffering while fetching
2725 * whereas linear formats need only 2 lines.
2726 * So we cannot support more than half of the supported SSPP
2727 * width for tiled formats.
2728 */
2729 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
Steve Cohenf5d01512017-07-07 18:49:21 -04002730 if (has_tiled_rect)
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002731 width_threshold /= 2;
2732
2733 if (parallel_fetch_qualified && src[i].w > width_threshold)
2734 parallel_fetch_qualified = false;
2735
2736 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002737
2738 /* Validate RECT's and set the mode */
2739
2740 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002741 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002742 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2743 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002744
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002745 goto done;
2746 }
2747
2748 /* TIME_MX Mode */
Steve Cohenf5d01512017-07-07 18:49:21 -04002749 buffer_lines = 2 * max_tile_height;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002750
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002751 if ((dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) ||
2752 (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines)) {
2753 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2754 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002755 } else {
2756 SDE_ERROR(
2757 "No multirect mode possible for the planes (%d - %d)\n",
2758 drm_state[R0]->plane->base.id,
2759 drm_state[R1]->plane->base.id);
2760 return -EINVAL;
2761 }
2762
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002763done:
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002764 if (sde_plane[R0]->is_virtual) {
2765 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2766 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2767 } else {
2768 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2769 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2770 };
2771
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002772 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2773 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2774 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2775 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002776 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002777}
2778
Alan Kwong4dd64c82017-02-04 18:41:51 -08002779/**
2780 * sde_plane_get_ctl_flush - get control flush for the given plane
2781 * @plane: Pointer to drm plane structure
2782 * @ctl: Pointer to hardware control driver
Clarence Ip7e5f0002017-05-29 18:46:56 -04002783 * @flush_sspp: Pointer to sspp flush control word
2784 * @flush_rot: Pointer to rotator flush control word
Alan Kwong4dd64c82017-02-04 18:41:51 -08002785 */
2786void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
Clarence Ip7e5f0002017-05-29 18:46:56 -04002787 u32 *flush_sspp, u32 *flush_rot)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002788{
2789 struct sde_plane_state *pstate;
2790 struct sde_plane_rot_state *rstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002791
Clarence Ip7e5f0002017-05-29 18:46:56 -04002792 if (!plane || !flush_sspp) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002793 SDE_ERROR("invalid parameters\n");
2794 return;
2795 }
2796
2797 pstate = to_sde_plane_state(plane->state);
2798 rstate = &pstate->rot;
2799
Clarence Ip7e5f0002017-05-29 18:46:56 -04002800 *flush_sspp = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002801
Clarence Ip7e5f0002017-05-29 18:46:56 -04002802 if (!flush_rot)
2803 return;
2804
2805 *flush_rot = 0x0;
Clarence Ipb776b532017-09-12 18:30:06 -04002806 if (rstate && rstate->out_sbuf && rstate->rot_hw &&
Alan Kwong4dd64c82017-02-04 18:41:51 -08002807 ctl->ops.get_bitmask_rot)
Clarence Ip7e5f0002017-05-29 18:46:56 -04002808 ctl->ops.get_bitmask_rot(ctl, flush_rot, rstate->rot_hw->idx);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002809}
2810
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002811static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002812 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002813{
2814 struct drm_framebuffer *fb = new_state->fb;
2815 struct sde_plane *psde = to_sde_plane(plane);
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002816 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002817 struct sde_plane_rot_state *new_rstate;
Alan Kwong4a5bd782017-06-09 15:20:52 -04002818 struct sde_hw_fmt_layout layout;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002819 struct msm_gem_address_space *aspace;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002820 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002821
2822 if (!new_state->fb)
2823 return 0;
2824
Clarence Ip13a8cf42016-09-29 17:27:47 -04002825 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002826
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002827 ret = _sde_plane_get_aspace(psde, pstate, &aspace);
2828 if (ret) {
2829 SDE_ERROR_PLANE(psde, "Failed to get aspace\n");
2830 return ret;
2831 }
2832
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002833 /* cache aspace */
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002834 pstate->aspace = aspace;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002835
2836 /*
2837 * when transitioning from secure to non-secure,
2838 * plane->prepare_fb happens before the commit. In such case,
2839 * defer the prepare_fb and handled it late, during the commit
2840 * after attaching the domains as part of the transition
2841 */
2842 pstate->defer_prepare_fb = (aspace && !aspace->domain_attached) ?
2843 true : false;
2844
Alan Kwong4dd64c82017-02-04 18:41:51 -08002845 ret = sde_plane_rot_prepare_fb(plane, new_state);
2846 if (ret) {
2847 SDE_ERROR("failed to prepare rot framebuffer\n");
2848 return ret;
2849 }
2850
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002851 if (pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002852 SDE_EVT32(DRMID(plane), psde->pipe);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002853 SDE_DEBUG_PLANE(psde,
2854 "domain not attached, prepare_fb handled later\n");
2855 return 0;
2856 }
2857
Alan Kwong4dd64c82017-02-04 18:41:51 -08002858 new_rstate = &to_sde_plane_state(new_state)->rot;
2859
Abhijit Kulkarni1b3340c2017-06-22 12:39:37 -07002860 if (pstate->aspace) {
2861 ret = msm_framebuffer_prepare(new_rstate->out_fb,
2862 pstate->aspace);
2863 if (ret) {
2864 SDE_ERROR("failed to prepare framebuffer\n");
2865 return ret;
2866 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002867 }
2868
Alan Kwong4a5bd782017-06-09 15:20:52 -04002869 /* validate framebuffer layout before commit */
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002870 ret = sde_format_populate_layout(pstate->aspace,
Alan Kwong4a5bd782017-06-09 15:20:52 -04002871 new_rstate->out_fb, &layout);
2872 if (ret) {
2873 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
2874 return ret;
2875 }
2876
Alan Kwong4dd64c82017-02-04 18:41:51 -08002877 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002878}
2879
2880static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002881 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002882{
Alan Kwong4dd64c82017-02-04 18:41:51 -08002883 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ip299fa602017-07-11 18:01:37 -04002884 struct sde_plane_state *old_pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002885 struct sde_plane_rot_state *old_rstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002886
Clarence Ip299fa602017-07-11 18:01:37 -04002887 if (!old_state || !old_state->fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002888 return;
2889
Clarence Ip299fa602017-07-11 18:01:37 -04002890 old_pstate = to_sde_plane_state(old_state);
2891
Alan Kwong4dd64c82017-02-04 18:41:51 -08002892 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
2893
Clarence Ip299fa602017-07-11 18:01:37 -04002894 old_rstate = &old_pstate->rot;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002895
Clarence Ip299fa602017-07-11 18:01:37 -04002896 msm_framebuffer_cleanup(old_rstate->out_fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002897
2898 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002899}
2900
Alan Kwong4dd64c82017-02-04 18:41:51 -08002901static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002902 struct drm_plane_state *state,
2903 struct drm_plane_state *old_state)
2904{
2905 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002906 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002907 struct sde_plane_rot_state *rstate = &pstate->rot;
2908 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2909 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002910
Dhaval Patel47302cf2016-08-18 15:04:28 -07002911 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04002912 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07002913 return;
2914
Clarence Ip282dad62016-09-27 17:07:35 -04002915 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
2916 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002917 SDE_DEBUG_PLANE(psde,
2918 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002919 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002920 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002921 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002922 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002923 } else if (pstate->multirect_index != old_pstate->multirect_index ||
2924 pstate->multirect_mode != old_pstate->multirect_mode) {
2925 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
2926 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002927 } else if (rstate->out_src_w != old_rstate->out_src_w ||
2928 rstate->out_src_h != old_rstate->out_src_h ||
2929 rstate->out_src_x != old_rstate->out_src_x ||
2930 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002931 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002932 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002933 } else if (state->crtc_w != old_state->crtc_w ||
2934 state->crtc_h != old_state->crtc_h ||
2935 state->crtc_x != old_state->crtc_x ||
2936 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002937 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002938 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002939 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
2940 pstate->excl_rect.h != old_pstate->excl_rect.h ||
2941 pstate->excl_rect.x != old_pstate->excl_rect.x ||
2942 pstate->excl_rect.y != old_pstate->excl_rect.y) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07002943 SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08002944 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04002945 }
2946
Alan Kwong4dd64c82017-02-04 18:41:51 -08002947 fb = rstate->out_fb;
2948 old_fb = old_rstate->out_fb;
2949
2950 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002951 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08002952 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002953 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04002954 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002955 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002956 uint64_t *new_mods = fb->modifier;
2957 uint64_t *old_mods = old_fb->modifier;
2958 uint32_t *new_pitches = fb->pitches;
2959 uint32_t *old_pitches = old_fb->pitches;
2960 uint32_t *new_offset = fb->offsets;
2961 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002962 int i;
2963
Alan Kwong4dd64c82017-02-04 18:41:51 -08002964 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002965 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002966 SDE_DEBUG_PLANE(psde,
2967 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002968 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002969 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002970 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2971 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002972 break;
2973 }
2974 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002975 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002976 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002977 SDE_DEBUG_PLANE(psde,
2978 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002979 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002980 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002981 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002982 break;
2983 }
2984 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002985 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07002986 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04002987 SDE_DEBUG_PLANE(psde,
2988 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07002989 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04002990 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04002991 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2992 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07002993 break;
2994 }
2995 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04002996 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04002997}
2998
Clarence Ip059c8c32017-06-06 17:15:54 -04002999static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -04003000 struct sde_plane_state *pstate,
Clarence Ip059c8c32017-06-06 17:15:54 -04003001 const struct sde_format *fmt,
3002 uint32_t img_w, uint32_t img_h,
3003 uint32_t src_w, uint32_t src_h,
3004 uint32_t deci_w, uint32_t deci_h)
3005{
3006 int i;
3007
Clarence Ip172033f2017-06-13 10:52:56 -04003008 if (!psde || !pstate || !fmt) {
Clarence Ip059c8c32017-06-06 17:15:54 -04003009 SDE_ERROR_PLANE(psde, "invalid arguments\n");
3010 return -EINVAL;
3011 }
3012
3013 /* don't run checks unless scaler data was changed */
Clarence Ip172033f2017-06-13 10:52:56 -04003014 if (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK)
Clarence Ip059c8c32017-06-06 17:15:54 -04003015 return 0;
3016
Clarence Ip172033f2017-06-13 10:52:56 -04003017 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
Clarence Ip059c8c32017-06-06 17:15:54 -04003018
3019 for (i = 0; i < SDE_MAX_PLANES; i++) {
3020 uint32_t hor_req_pixels, hor_fetch_pixels;
3021 uint32_t vert_req_pixels, vert_fetch_pixels;
3022 uint32_t src_w_tmp, src_h_tmp;
3023
3024 /* re-use color plane 1's config for plane 2 */
3025 if (i == 2)
3026 continue;
3027
3028 src_w_tmp = src_w;
3029 src_h_tmp = src_h;
3030
3031 /*
3032 * For chroma plane, width is half for the following sub sampled
3033 * formats. Except in case of decimation, where hardware avoids
3034 * 1 line of decimation instead of downsampling.
3035 */
3036 if (i == 1) {
3037 if (!deci_w &&
3038 (fmt->chroma_sample == SDE_CHROMA_420 ||
3039 fmt->chroma_sample == SDE_CHROMA_H2V1))
3040 src_w_tmp >>= 1;
3041 if (!deci_h &&
3042 (fmt->chroma_sample == SDE_CHROMA_420 ||
3043 fmt->chroma_sample == SDE_CHROMA_H1V2))
3044 src_h_tmp >>= 1;
3045 }
3046
Clarence Ip172033f2017-06-13 10:52:56 -04003047 hor_req_pixels = pstate->pixel_ext.roi_w[i];
3048 vert_req_pixels = pstate->pixel_ext.roi_h[i];
Clarence Ip059c8c32017-06-06 17:15:54 -04003049
3050 hor_fetch_pixels = DECIMATED_DIMENSION(src_w_tmp +
Clarence Ip172033f2017-06-13 10:52:56 -04003051 (int8_t)(pstate->pixel_ext.left_ftch[i] & 0xFF) +
3052 (int8_t)(pstate->pixel_ext.right_ftch[i] & 0xFF),
3053 deci_w);
Clarence Ip059c8c32017-06-06 17:15:54 -04003054 vert_fetch_pixels = DECIMATED_DIMENSION(src_h_tmp +
Clarence Ip172033f2017-06-13 10:52:56 -04003055 (int8_t)(pstate->pixel_ext.top_ftch[i] & 0xFF) +
3056 (int8_t)(pstate->pixel_ext.btm_ftch[i] & 0xFF),
3057 deci_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04003058
3059 if ((hor_req_pixels != hor_fetch_pixels) ||
3060 (hor_fetch_pixels > img_w) ||
3061 (vert_req_pixels != vert_fetch_pixels) ||
3062 (vert_fetch_pixels > img_h)) {
3063 SDE_ERROR_PLANE(psde,
3064 "req %d/%d, fetch %d/%d, src %dx%d\n",
3065 hor_req_pixels, vert_req_pixels,
3066 hor_fetch_pixels, vert_fetch_pixels,
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003067 img_w, img_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04003068 return -EINVAL;
3069 }
3070
3071 /*
3072 * Alpha plane can only be scaled using bilinear or pixel
3073 * repeat/drop, src_width and src_height are only specified
3074 * for Y and UV plane
3075 */
3076 if (i != 3 &&
Clarence Ip172033f2017-06-13 10:52:56 -04003077 (hor_req_pixels != pstate->scaler3_cfg.src_width[i] ||
3078 vert_req_pixels != pstate->scaler3_cfg.src_height[i])) {
Clarence Ip059c8c32017-06-06 17:15:54 -04003079 SDE_ERROR_PLANE(psde,
3080 "roi[%d] %d/%d, scaler src %dx%d, src %dx%d\n",
Clarence Ip172033f2017-06-13 10:52:56 -04003081 i, pstate->pixel_ext.roi_w[i],
3082 pstate->pixel_ext.roi_h[i],
3083 pstate->scaler3_cfg.src_width[i],
3084 pstate->scaler3_cfg.src_height[i],
Clarence Ip059c8c32017-06-06 17:15:54 -04003085 src_w, src_h);
3086 return -EINVAL;
3087 }
3088 }
3089
Clarence Ip172033f2017-06-13 10:52:56 -04003090 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
Clarence Ip059c8c32017-06-06 17:15:54 -04003091 return 0;
3092}
3093
Alan Kwong4dd64c82017-02-04 18:41:51 -08003094static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003095 struct drm_plane_state *state)
3096{
Clarence Ipdedbba92016-09-27 17:43:10 -04003097 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04003098 struct sde_plane *psde;
3099 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003100 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04003101 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003102 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04003103 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003104 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
3105 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04003106
3107 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003108 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3109 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04003110 ret = -EINVAL;
3111 goto exit;
3112 }
3113
3114 psde = to_sde_plane(plane);
3115 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003116 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04003117
3118 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003119 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003120 ret = -EINVAL;
3121 goto exit;
3122 }
3123
Clarence Ipdedbba92016-09-27 17:43:10 -04003124 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
3125 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04003126
3127 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08003128 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3129 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07003130 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
3131 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04003132
Dhaval Patel47302cf2016-08-18 15:04:28 -07003133 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
3134 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04003135
Dhaval Patel47302cf2016-08-18 15:04:28 -07003136 max_upscale = psde->pipe_sblk->maxupscale;
3137 max_downscale = psde->pipe_sblk->maxdwnscale;
3138 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04003139
Clarence Ip13a8cf42016-09-29 17:27:47 -04003140 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003141 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003142
Dhaval Patel47302cf2016-08-18 15:04:28 -07003143 if (!sde_plane_enabled(state))
3144 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04003145
Alan Kwong4dd64c82017-02-04 18:41:51 -08003146 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07003147 "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 -08003148 plane->base.id, rstate->sequence_id,
3149 rstate->out_rotation,
3150 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07003151 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08003152 rstate->out_fb_modifier[0],
3153 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3154 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3155 state->crtc_w, state->crtc_h,
3156 state->crtc_x, state->crtc_y);
3157
Dhaval Patel47302cf2016-08-18 15:04:28 -07003158 fmt = to_sde_format(msm_framebuffer_format(state->fb));
3159
3160 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
3161
3162 if (SDE_FORMAT_IS_YUV(fmt) &&
3163 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04003164 !(psde->features & (BIT(SDE_SSPP_CSC)
3165 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003166 SDE_ERROR_PLANE(psde,
3167 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07003168 ret = -EINVAL;
3169
3170 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08003171 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
3172 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07003173 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08003174 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
3175 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003176 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003177 src.x, src.y, src.w, src.h);
3178 ret = -E2BIG;
3179
3180 /* valid yuv image */
3181 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
3182 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003183 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003184 src.x, src.y, src.w, src.h);
3185 ret = -EINVAL;
3186
3187 /* min dst support */
3188 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003189 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003190 dst.x, dst.y, dst.w, dst.h);
3191 ret = -EINVAL;
3192
3193 /* decimation validation */
3194 } else if (deci_w || deci_h) {
3195 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
3196 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003197 SDE_ERROR_PLANE(psde,
3198 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003199 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003200 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003201 SDE_ERROR_PLANE(psde,
3202 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003203 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003204 }
3205
Dhaval Patel47302cf2016-08-18 15:04:28 -07003206 } else if (!(psde->features & SDE_SSPP_SCALER) &&
3207 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003208 SDE_ERROR_PLANE(psde,
3209 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003210 src.w, src.h, dst.w, dst.h);
3211 ret = -EINVAL;
3212
3213 /* check decimated source width */
3214 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003215 SDE_ERROR_PLANE(psde,
3216 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003217 src.w, src_deci_w, max_linewidth);
3218 ret = -E2BIG;
3219
3220 /* check max scaler capability */
3221 } else if (((src_deci_w * max_upscale) < dst.w) ||
3222 ((src_deci_h * max_upscale) < dst.h) ||
3223 ((dst.w * max_downscale) < src_deci_w) ||
3224 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003225 SDE_ERROR_PLANE(psde,
3226 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003227 src_deci_w, src_deci_h, dst.w, dst.h);
3228 ret = -E2BIG;
Clarence Ip172033f2017-06-13 10:52:56 -04003229 } else if (_sde_plane_validate_scaler_v2(psde, pstate, fmt,
Clarence Ip059c8c32017-06-06 17:15:54 -04003230 rstate->out_fb_width,
3231 rstate->out_fb_height,
3232 src.w, src.h, deci_w, deci_h)) {
3233 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003234 }
3235
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003236 /* check excl rect configs */
Clarence Ip059c8c32017-06-06 17:15:54 -04003237 if (!ret && pstate->excl_rect.w && pstate->excl_rect.h) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003238 struct sde_rect intersect;
3239
3240 /*
3241 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003242 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003243 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05003244 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003245 if (intersect.w != pstate->excl_rect.w ||
3246 intersect.h != pstate->excl_rect.h ||
3247 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003248 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07003249 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003250 pstate->excl_rect.x, pstate->excl_rect.y,
3251 pstate->excl_rect.w, pstate->excl_rect.h,
3252 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07003253 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003254 ret = -EINVAL;
3255 }
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003256 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3257 pstate->excl_rect.x, pstate->excl_rect.y,
3258 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003259 }
3260
Dhaval Patel47302cf2016-08-18 15:04:28 -07003261modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003262 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08003263 _sde_plane_sspp_atomic_check_mode_changed(psde,
3264 state, plane->state);
3265exit:
3266 return ret;
3267}
3268
3269static int sde_plane_atomic_check(struct drm_plane *plane,
3270 struct drm_plane_state *state)
3271{
3272 int ret = 0;
3273 struct sde_plane *psde;
3274 struct sde_plane_state *pstate;
3275
3276 if (!plane || !state) {
3277 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3278 plane != 0, state != 0);
3279 ret = -EINVAL;
3280 goto exit;
3281 }
3282
3283 psde = to_sde_plane(plane);
3284 pstate = to_sde_plane_state(state);
3285
3286 SDE_DEBUG_PLANE(psde, "\n");
3287
3288 ret = sde_plane_rot_atomic_check(plane, state);
3289 if (ret)
3290 goto exit;
3291
3292 ret = sde_plane_sspp_atomic_check(plane, state);
3293
Clarence Ipdbde9832016-06-26 09:48:36 -04003294exit:
3295 return ret;
3296}
3297
Clarence Ipcae1bb62016-07-07 12:07:13 -04003298void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04003299{
Clarence Ipcae1bb62016-07-07 12:07:13 -04003300 struct sde_plane *psde;
Clarence Ipddbf7752017-05-21 18:07:30 -04003301 struct sde_plane_state *pstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -04003302
Clarence Ipddbf7752017-05-21 18:07:30 -04003303 if (!plane || !plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003304 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04003305 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003306 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04003307
3308 psde = to_sde_plane(plane);
Clarence Ipddbf7752017-05-21 18:07:30 -04003309 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003310
3311 /*
3312 * These updates have to be done immediately before the plane flush
3313 * timing, and may not be moved to the atomic_update/mode_set functions.
3314 */
3315 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05003316 /* force white frame with 100% alpha pipe output on error */
3317 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003318 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
3319 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04003320 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003321 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
3322 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
3323
Clarence Ip56902792017-03-17 15:22:07 -04003324 /* force black color fill during suspend */
Clarence Ipd86f6e42017-08-08 18:31:00 -04003325 if (sde_kms_is_suspend_state(plane->dev) && suspend_blank)
Clarence Ip56902792017-03-17 15:22:07 -04003326 _sde_plane_color_fill(psde, 0x0, 0x0);
3327
Clarence Ipcae1bb62016-07-07 12:07:13 -04003328 /* flag h/w flush complete */
3329 if (plane->state)
Clarence Ipddbf7752017-05-21 18:07:30 -04003330 pstate->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003331}
3332
Abhijit Kulkarni1b3340c2017-06-22 12:39:37 -07003333/**
3334 * sde_plane_set_error: enable/disable error condition
3335 * @plane: pointer to drm_plane structure
3336 */
3337void sde_plane_set_error(struct drm_plane *plane, bool error)
3338{
3339 struct sde_plane *psde;
3340
3341 if (!plane)
3342 return;
3343
3344 psde = to_sde_plane(plane);
3345 psde->is_error = error;
3346}
3347
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003348static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
3349 struct drm_plane_state *old_state)
3350{
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003351 uint32_t nplanes, src_flags;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003352 struct sde_plane *psde;
3353 struct drm_plane_state *state;
3354 struct sde_plane_state *pstate;
3355 struct sde_plane_state *old_pstate;
3356 struct sde_plane_rot_state *rstate;
3357 const struct sde_format *fmt;
3358 struct drm_crtc *crtc;
3359 struct drm_framebuffer *fb;
3360 struct sde_rect src, dst;
3361 const struct sde_rect *crtc_roi;
3362 bool q16_data = true;
3363 int idx;
3364
3365 if (!plane) {
3366 SDE_ERROR("invalid plane\n");
3367 return -EINVAL;
3368 } else if (!plane->state) {
3369 SDE_ERROR("invalid plane state\n");
3370 return -EINVAL;
3371 } else if (!old_state) {
3372 SDE_ERROR("invalid old state\n");
3373 return -EINVAL;
3374 }
3375
3376 psde = to_sde_plane(plane);
3377 state = plane->state;
3378
3379 pstate = to_sde_plane_state(state);
3380 rstate = &pstate->rot;
3381
3382 old_pstate = to_sde_plane_state(old_state);
3383
3384 crtc = state->crtc;
3385 fb = rstate->out_fb;
3386 if (!crtc || !fb) {
3387 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
3388 crtc != 0, fb != 0);
3389 return -EINVAL;
3390 }
3391 fmt = to_sde_format(msm_framebuffer_format(fb));
3392 nplanes = fmt->num_planes;
3393
3394 SDE_DEBUG(
3395 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
3396 plane->base.id, rstate->sequence_id,
3397 rstate->out_fb_width, rstate->out_fb_height,
3398 (char *) &rstate->out_fb_pixel_format,
3399 rstate->out_fb_modifier[0],
3400 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3401 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3402 rstate->out_rotation,
3403 state->crtc_w, state->crtc_h,
3404 state->crtc_x, state->crtc_y);
3405
3406 /* force reprogramming of all the parameters, if the flag is set */
3407 if (psde->revalidate) {
3408 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
3409 plane->base.id);
3410 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3411 psde->revalidate = false;
3412 }
3413
3414 /* determine what needs to be refreshed */
Clarence Ip4a2955d2017-07-04 18:04:33 -04003415 while ((idx = msm_property_pop_dirty(&psde->property_info,
3416 &pstate->property_state)) >= 0) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003417 switch (idx) {
3418 case PLANE_PROP_SCALER_V1:
3419 case PLANE_PROP_SCALER_V2:
Clarence Ip059c8c32017-06-06 17:15:54 -04003420 case PLANE_PROP_SCALER_LUT_ED:
3421 case PLANE_PROP_SCALER_LUT_CIR:
3422 case PLANE_PROP_SCALER_LUT_SEP:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003423 case PLANE_PROP_H_DECIMATE:
3424 case PLANE_PROP_V_DECIMATE:
3425 case PLANE_PROP_SRC_CONFIG:
3426 case PLANE_PROP_ZPOS:
3427 case PLANE_PROP_EXCL_RECT_V1:
3428 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3429 break;
3430 case PLANE_PROP_CSC_V1:
3431 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3432 break;
3433 case PLANE_PROP_COLOR_FILL:
3434 /* potentially need to refresh everything */
3435 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3436 break;
3437 case PLANE_PROP_ROTATION:
3438 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3439 break;
3440 case PLANE_PROP_INFO:
3441 case PLANE_PROP_ALPHA:
3442 case PLANE_PROP_INPUT_FENCE:
3443 case PLANE_PROP_BLEND_OP:
3444 /* no special action required */
3445 break;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003446 case PLANE_PROP_FB_TRANSLATION_MODE:
3447 pstate->dirty |= SDE_PLANE_DIRTY_FB_TRANSLATION_MODE;
3448 break;
Alan Kwong2349d742017-04-20 08:27:30 -07003449 case PLANE_PROP_PREFILL_SIZE:
3450 case PLANE_PROP_PREFILL_TIME:
3451 pstate->dirty |= SDE_PLANE_DIRTY_PERF;
3452 break;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003453 case PLANE_PROP_ROT_DST_X:
3454 case PLANE_PROP_ROT_DST_Y:
3455 case PLANE_PROP_ROT_DST_W:
3456 case PLANE_PROP_ROT_DST_H:
3457 /* handled by rotator atomic update */
3458 break;
3459 default:
3460 /* unknown property, refresh everything */
3461 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
3462 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
3463 break;
3464 }
3465 }
3466
3467 /**
3468 * since plane_atomic_check is invoked before crtc_atomic_check
3469 * in the commit sequence, all the parameters for updating the
3470 * plane dirty flag will not be available during
3471 * plane_atomic_check as some features params are updated
3472 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
3473 * before sspp update.
3474 */
3475 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
3476 old_state);
3477
3478 /* re-program the output rects always in the case of partial update */
3479 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
3480 if (!sde_kms_rect_is_null(crtc_roi))
3481 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3482
3483 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
3484 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
3485
3486 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
3487
3488 /* early out if nothing dirty */
3489 if (!pstate->dirty)
3490 return 0;
3491 pstate->pending = true;
3492
3493 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
3494 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3495
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003496 /* update secure session flag */
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003497 if (pstate->dirty & SDE_PLANE_DIRTY_FB_TRANSLATION_MODE) {
3498 bool enable = false;
3499 int mode = sde_plane_get_property(pstate,
3500 PLANE_PROP_FB_TRANSLATION_MODE);
3501
3502 if ((mode == SDE_DRM_FB_SEC) ||
3503 (mode == SDE_DRM_FB_SEC_DIR_TRANS))
3504 enable = true;
3505 /* update secure session flag */
3506 psde->pipe_hw->ops.setup_secure_address(psde->pipe_hw,
3507 pstate->multirect_index,
3508 enable);
3509 }
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003510
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003511 /* update roi config */
3512 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
3513 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3514 rstate->out_src_w, rstate->out_src_h, q16_data);
3515 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
3516 state->crtc_w, state->crtc_h, !q16_data);
3517
3518 SDE_DEBUG_PLANE(psde,
3519 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
3520 fb->base.id, src.x, src.y, src.w, src.h,
3521 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
3522 (char *)&fmt->base.pixel_format,
3523 SDE_FORMAT_IS_UBWC(fmt));
3524
3525 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
3526 BIT(SDE_DRM_DEINTERLACE)) {
3527 SDE_DEBUG_PLANE(psde, "deinterlace\n");
3528 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
3529 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
3530 src.h /= 2;
3531 src.y = DIV_ROUND_UP(src.y, 2);
3532 src.y &= ~0x1;
3533 }
3534
3535 /*
3536 * adjust layer mixer position of the sspp in the presence
3537 * of a partial update to the active lm origin
3538 */
3539 dst.x -= crtc_roi->x;
3540 dst.y -= crtc_roi->y;
3541
3542 psde->pipe_cfg.src_rect = src;
3543 psde->pipe_cfg.dst_rect = dst;
3544
Clarence Ip172033f2017-06-13 10:52:56 -04003545 _sde_plane_setup_scaler(psde, pstate, fmt, false);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003546
3547 /* check for color fill */
3548 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
3549 PLANE_PROP_COLOR_FILL);
3550 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
3551 /* skip remaining processing on color fill */
3552 pstate->dirty = 0x0;
3553 } else if (psde->pipe_hw->ops.setup_rects) {
3554 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
3555 &psde->pipe_cfg,
3556 pstate->multirect_index);
3557 }
3558
Jeykumar Sankaran0532e0a2017-06-11 20:34:44 -07003559 if (psde->pipe_hw->ops.setup_pe &&
3560 (pstate->multirect_index != SDE_SSPP_RECT_1))
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003561 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04003562 &pstate->pixel_ext);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003563
3564 /**
3565 * when programmed in multirect mode, scalar block will be
3566 * bypassed. Still we need to update alpha and bitwidth
3567 * ONLY for RECT0
3568 */
3569 if (psde->pipe_hw->ops.setup_scaler &&
3570 pstate->multirect_index != SDE_SSPP_RECT_1)
3571 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04003572 &psde->pipe_cfg, &pstate->pixel_ext,
3573 &pstate->scaler3_cfg);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003574
3575 /* update excl rect */
3576 if (psde->pipe_hw->ops.setup_excl_rect)
3577 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
3578 &pstate->excl_rect,
3579 pstate->multirect_index);
3580
3581 if (psde->pipe_hw->ops.setup_multirect)
3582 psde->pipe_hw->ops.setup_multirect(
3583 psde->pipe_hw,
3584 pstate->multirect_index,
3585 pstate->multirect_mode);
3586 }
3587
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003588 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003589 psde->pipe_hw->ops.setup_format) {
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003590 src_flags = 0x0;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003591 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
3592 if (rstate->out_rotation & DRM_REFLECT_X)
3593 src_flags |= SDE_SSPP_FLIP_LR;
3594 if (rstate->out_rotation & DRM_REFLECT_Y)
3595 src_flags |= SDE_SSPP_FLIP_UD;
3596
3597 /* update format */
3598 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
3599 pstate->multirect_index);
3600
Alan Kwong143f50c2017-04-28 07:34:28 -07003601 if (psde->pipe_hw->ops.setup_cdp) {
3602 struct sde_hw_pipe_cdp_cfg *cdp_cfg = &pstate->cdp_cfg;
3603
3604 memset(cdp_cfg, 0, sizeof(struct sde_hw_pipe_cdp_cfg));
3605
3606 cdp_cfg->enable = psde->catalog->perf.cdp_cfg
3607 [SDE_PERF_CDP_USAGE_RT].rd_enable;
3608 cdp_cfg->ubwc_meta_enable =
3609 SDE_FORMAT_IS_UBWC(fmt);
3610 cdp_cfg->tile_amortize_enable =
3611 SDE_FORMAT_IS_UBWC(fmt) ||
3612 SDE_FORMAT_IS_TILE(fmt);
3613 cdp_cfg->preload_ahead = SDE_WB_CDP_PRELOAD_AHEAD_64;
3614
Alan Kwong1b6b4572017-09-25 15:58:14 -04003615 psde->pipe_hw->ops.setup_cdp(psde->pipe_hw, cdp_cfg,
3616 pstate->multirect_index);
Alan Kwong143f50c2017-04-28 07:34:28 -07003617 }
3618
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003619 if (psde->pipe_hw->ops.setup_sys_cache) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04003620 if (rstate->out_sbuf && rstate->rot_hw) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003621 if (rstate->nplane < 2)
3622 pstate->sc_cfg.op_mode =
3623 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
3624 else if (rstate->out_xpos == 0)
3625 pstate->sc_cfg.op_mode =
3626 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
3627 else
3628 pstate->sc_cfg.op_mode =
3629 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
3630
3631 pstate->sc_cfg.rd_en = true;
3632 pstate->sc_cfg.rd_scid =
3633 rstate->rot_hw->caps->scid;
3634 pstate->sc_cfg.rd_noallocate = true;
3635 pstate->sc_cfg.rd_op_type =
3636 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3637 } else {
3638 pstate->sc_cfg.op_mode =
3639 SDE_PIPE_SC_OP_MODE_OFFLINE;
3640 pstate->sc_cfg.rd_en = false;
3641 pstate->sc_cfg.rd_scid = 0;
Clarence Ipd02440b2017-05-21 18:10:01 -04003642 pstate->sc_cfg.rd_noallocate = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003643 pstate->sc_cfg.rd_op_type =
3644 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3645 }
3646
3647 psde->pipe_hw->ops.setup_sys_cache(
3648 psde->pipe_hw, &pstate->sc_cfg);
3649 }
3650
3651 /* update csc */
3652 if (SDE_FORMAT_IS_YUV(fmt))
3653 _sde_plane_setup_csc(psde);
3654 else
3655 psde->csc_ptr = 0;
3656 }
3657
3658 sde_color_process_plane_setup(plane);
3659
3660 /* update sharpening */
3661 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3662 psde->pipe_hw->ops.setup_sharpening) {
3663 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3664 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3665 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3666 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3667
3668 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3669 &psde->sharp_cfg);
3670 }
3671
3672 _sde_plane_set_qos_lut(plane, fb);
3673 _sde_plane_set_danger_lut(plane, fb);
3674
3675 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3676 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3677 _sde_plane_set_ot_limit(plane, crtc);
Alan Kwong2349d742017-04-20 08:27:30 -07003678 if (pstate->dirty & SDE_PLANE_DIRTY_PERF)
3679 _sde_plane_set_ts_prefill(plane, pstate);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003680 }
3681
Alan Kwonga62eeb82017-04-19 08:57:55 -07003682 _sde_plane_set_qos_remap(plane);
3683
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003684 /* clear dirty */
3685 pstate->dirty = 0x0;
3686
3687 return 0;
3688}
3689
Clarence Ipc652ccf2017-06-28 18:21:18 -04003690static void _sde_plane_atomic_disable(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003691 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003692{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003693 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003694 struct drm_plane_state *state;
3695 struct sde_plane_state *pstate;
Clarence Ipc652ccf2017-06-28 18:21:18 -04003696
3697 if (!plane) {
3698 SDE_ERROR("invalid plane\n");
3699 return;
3700 } else if (!plane->state) {
3701 SDE_ERROR("invalid plane state\n");
3702 return;
3703 } else if (!old_state) {
3704 SDE_ERROR("invalid old state\n");
3705 return;
3706 }
3707
3708 psde = to_sde_plane(plane);
3709 state = plane->state;
3710 pstate = to_sde_plane_state(state);
3711
3712 SDE_EVT32(DRMID(plane), is_sde_plane_virtual(plane),
3713 pstate->multirect_mode);
3714
3715 pstate->pending = true;
3716
3717 if (is_sde_plane_virtual(plane) &&
3718 psde->pipe_hw && psde->pipe_hw->ops.setup_multirect)
3719 psde->pipe_hw->ops.setup_multirect(psde->pipe_hw,
3720 SDE_SSPP_RECT_SOLO, SDE_SSPP_MULTIRECT_NONE);
3721}
3722
3723static void sde_plane_atomic_update(struct drm_plane *plane,
3724 struct drm_plane_state *old_state)
3725{
3726 struct sde_plane *psde;
3727 struct drm_plane_state *state;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003728
Clarence Ip13a8cf42016-09-29 17:27:47 -04003729 if (!plane) {
3730 SDE_ERROR("invalid plane\n");
3731 return;
3732 } else if (!plane->state) {
3733 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003734 return;
3735 }
3736
Clarence Ip13a8cf42016-09-29 17:27:47 -04003737 psde = to_sde_plane(plane);
3738 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003739 state = plane->state;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003740
Clarence Ip13a8cf42016-09-29 17:27:47 -04003741 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003742
Alan Kwong4dd64c82017-02-04 18:41:51 -08003743 sde_plane_rot_atomic_update(plane, old_state);
3744
3745 if (!sde_plane_sspp_enabled(state)) {
Clarence Ipc652ccf2017-06-28 18:21:18 -04003746 _sde_plane_atomic_disable(plane, old_state);
Clarence Ip282dad62016-09-27 17:07:35 -04003747 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003748 int ret;
3749
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003750 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003751 /* atomic_check should have ensured that this doesn't fail */
3752 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003753 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003754}
3755
Alan Kwong346223e2017-06-30 15:29:22 -04003756void sde_plane_restore(struct drm_plane *plane)
3757{
3758 struct sde_plane *psde;
3759
3760 if (!plane || !plane->state) {
3761 SDE_ERROR("invalid plane\n");
3762 return;
3763 }
3764
3765 psde = to_sde_plane(plane);
3766
3767 /*
3768 * Revalidate is only true here if idle PC occurred and
3769 * there is no plane state update in current commit cycle.
3770 */
3771 if (!psde->revalidate)
3772 return;
3773
3774 SDE_DEBUG_PLANE(psde, "\n");
3775
3776 /* last plane state is same as current state */
3777 sde_plane_atomic_update(plane, plane->state);
3778}
Dhaval Patel47302cf2016-08-18 15:04:28 -07003779
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003780/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003781static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003782 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003783{
Clarence Ip5e2a9222016-06-26 22:38:24 -04003784 static const struct drm_prop_enum_list e_blend_op[] = {
3785 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
3786 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
3787 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
3788 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
3789 };
3790 static const struct drm_prop_enum_list e_src_config[] = {
3791 {SDE_DRM_DEINTERLACE, "deinterlace"}
3792 };
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07003793 static const struct drm_prop_enum_list e_fb_translation_mode[] = {
3794 {SDE_DRM_FB_NON_SEC, "non_sec"},
3795 {SDE_DRM_FB_SEC, "sec"},
3796 {SDE_DRM_FB_NON_SEC_DIR_TRANS, "non_sec_direct_translation"},
3797 {SDE_DRM_FB_SEC_DIR_TRANS, "sec_direct_translation"},
3798 };
Clarence Ipea3d6262016-07-15 16:20:11 -04003799 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07003800 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003801 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04003802 int zpos_max = 255;
3803 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07003804 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003805
Clarence Ip13a8cf42016-09-29 17:27:47 -04003806 if (!plane || !psde) {
3807 SDE_ERROR("invalid plane\n");
3808 return;
3809 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
3810 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
3811 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003812 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04003813 } else if (!catalog) {
3814 SDE_ERROR("invalid catalog\n");
3815 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003816 }
3817
Alan Kwong4dd64c82017-02-04 18:41:51 -08003818 psde->catalog = catalog;
3819
Clarence Ipc47a0692016-10-11 10:54:17 -04003820 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04003821 if (catalog->mixer_count && catalog->mixer &&
3822 catalog->mixer[0].sblk->maxblendstages) {
3823 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
3824 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
3825 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
3826 }
Clarence Ipc47a0692016-10-11 10:54:17 -04003827 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
3828 /* reserve zpos == 0 for primary planes */
3829 zpos_def = drm_plane_index(plane) + 1;
3830 }
3831
3832 msm_property_install_range(&psde->property_info, "zpos",
3833 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003834
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003835 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003836 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003837
Dhaval Patel47302cf2016-08-18 15:04:28 -07003838 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04003839 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07003840 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003841
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003842 if (!master_plane_id) {
3843 if (psde->pipe_sblk->maxhdeciexp) {
3844 msm_property_install_range(&psde->property_info,
3845 "h_decimate", 0x0, 0,
3846 psde->pipe_sblk->maxhdeciexp, 0,
3847 PLANE_PROP_H_DECIMATE);
3848 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003849
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003850 if (psde->pipe_sblk->maxvdeciexp) {
3851 msm_property_install_range(&psde->property_info,
3852 "v_decimate", 0x0, 0,
3853 psde->pipe_sblk->maxvdeciexp, 0,
3854 PLANE_PROP_V_DECIMATE);
3855 }
Clarence Ipdedbba92016-09-27 17:43:10 -04003856
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003857 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003858 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003859 &psde->property_info, "scaler_v2",
3860 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
3861 msm_property_install_blob(&psde->property_info,
3862 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
3863 msm_property_install_blob(&psde->property_info,
3864 "lut_cir", 0,
3865 PLANE_PROP_SCALER_LUT_CIR);
3866 msm_property_install_blob(&psde->property_info,
3867 "lut_sep", 0,
3868 PLANE_PROP_SCALER_LUT_SEP);
3869 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003870 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003871 &psde->property_info, "scaler_v1", 0x0,
3872 0, ~0, 0, PLANE_PROP_SCALER_V1);
3873 }
Clarence Ipb43d4592016-09-08 14:21:35 -04003874
Dhaval Patel0aee0972017-02-08 19:00:58 -08003875 if (psde->features & BIT(SDE_SSPP_CSC) ||
3876 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003877 msm_property_install_volatile_range(
3878 &psde->property_info, "csc_v1", 0x0,
3879 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04003880
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003881 if (psde->features & BIT(SDE_SSPP_HSIC)) {
3882 snprintf(feature_name, sizeof(feature_name), "%s%d",
3883 "SDE_SSPP_HUE_V",
3884 psde->pipe_sblk->hsic_blk.version >> 16);
3885 msm_property_install_range(&psde->property_info,
3886 feature_name, 0, 0, 0xFFFFFFFF, 0,
3887 PLANE_PROP_HUE_ADJUST);
3888 snprintf(feature_name, sizeof(feature_name), "%s%d",
3889 "SDE_SSPP_SATURATION_V",
3890 psde->pipe_sblk->hsic_blk.version >> 16);
3891 msm_property_install_range(&psde->property_info,
3892 feature_name, 0, 0, 0xFFFFFFFF, 0,
3893 PLANE_PROP_SATURATION_ADJUST);
3894 snprintf(feature_name, sizeof(feature_name), "%s%d",
3895 "SDE_SSPP_VALUE_V",
3896 psde->pipe_sblk->hsic_blk.version >> 16);
3897 msm_property_install_range(&psde->property_info,
3898 feature_name, 0, 0, 0xFFFFFFFF, 0,
3899 PLANE_PROP_VALUE_ADJUST);
3900 snprintf(feature_name, sizeof(feature_name), "%s%d",
3901 "SDE_SSPP_CONTRAST_V",
3902 psde->pipe_sblk->hsic_blk.version >> 16);
3903 msm_property_install_range(&psde->property_info,
3904 feature_name, 0, 0, 0xFFFFFFFF, 0,
3905 PLANE_PROP_CONTRAST_ADJUST);
3906 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07003907 }
3908
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003909 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
3910 msm_property_install_volatile_range(&psde->property_info,
3911 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
3912
Alan Kwong4dd64c82017-02-04 18:41:51 -08003913 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003914
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04003915 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07003916 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04003917
Dhaval Patel47302cf2016-08-18 15:04:28 -07003918 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
3919 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
3920
3921 if (psde->pipe_hw->ops.setup_solidfill)
3922 msm_property_install_range(&psde->property_info, "color_fill",
3923 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
3924
Alan Kwong2349d742017-04-20 08:27:30 -07003925 msm_property_install_range(&psde->property_info,
3926 "prefill_size", 0x0, 0, ~0, 0,
3927 PLANE_PROP_PREFILL_SIZE);
3928 msm_property_install_range(&psde->property_info,
3929 "prefill_time", 0x0, 0, ~0, 0,
3930 PLANE_PROP_PREFILL_TIME);
3931
Dhaval Patel4e574842016-08-23 15:11:37 -07003932 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04003933 if (!info) {
3934 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07003935 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003936 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003937
3938 msm_property_install_blob(&psde->property_info, "capabilities",
3939 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
3940 sde_kms_info_reset(info);
3941
Steve Cohen57428172017-07-18 10:57:17 -04003942 if (!master_plane_id) {
3943 format_list = psde->pipe_sblk->format_list;
3944 } else {
3945 format_list = psde->pipe_sblk->virt_format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003946 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07003947 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003948 }
3949
Clarence Ipea3d6262016-07-15 16:20:11 -04003950 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04003951 sde_kms_info_start(info, "pixel_formats");
3952 while (format_list->fourcc_format) {
3953 sde_kms_info_append_format(info,
3954 format_list->fourcc_format,
3955 format_list->modifier);
3956 ++format_list;
3957 }
3958 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04003959 }
Dhaval Patel4e574842016-08-23 15:11:37 -07003960
Clarence Ip1db00c12017-07-21 17:42:56 -04003961 if (psde->pipe_hw && psde->pipe_hw->ops.get_scaler_ver)
3962 sde_kms_info_add_keyint(info, "scaler_step_ver",
3963 psde->pipe_hw->ops.get_scaler_ver(psde->pipe_hw));
3964
Dhaval Patel4e574842016-08-23 15:11:37 -07003965 sde_kms_info_add_keyint(info, "max_linewidth",
3966 psde->pipe_sblk->maxlinewidth);
3967 sde_kms_info_add_keyint(info, "max_upscale",
3968 psde->pipe_sblk->maxupscale);
3969 sde_kms_info_add_keyint(info, "max_downscale",
3970 psde->pipe_sblk->maxdwnscale);
3971 sde_kms_info_add_keyint(info, "max_horizontal_deci",
3972 psde->pipe_sblk->maxhdeciexp);
3973 sde_kms_info_add_keyint(info, "max_vertical_deci",
3974 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07003975 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
3976 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07003977 msm_property_set_blob(&psde->property_info, &psde->blob_info,
Narendra Muppalla22d17252017-05-31 15:13:39 -07003978 info->data, SDE_KMS_INFO_DATALEN(info),
3979 PLANE_PROP_INFO);
Dhaval Patel4e574842016-08-23 15:11:37 -07003980
3981 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07003982
3983 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
3984 snprintf(feature_name, sizeof(feature_name), "%s%d",
3985 "SDE_SSPP_SKIN_COLOR_V",
3986 psde->pipe_sblk->memcolor_blk.version >> 16);
3987 msm_property_install_blob(&psde->property_info, feature_name, 0,
3988 PLANE_PROP_SKIN_COLOR);
3989 snprintf(feature_name, sizeof(feature_name), "%s%d",
3990 "SDE_SSPP_SKY_COLOR_V",
3991 psde->pipe_sblk->memcolor_blk.version >> 16);
3992 msm_property_install_blob(&psde->property_info, feature_name, 0,
3993 PLANE_PROP_SKY_COLOR);
3994 snprintf(feature_name, sizeof(feature_name), "%s%d",
3995 "SDE_SSPP_FOLIAGE_COLOR_V",
3996 psde->pipe_sblk->memcolor_blk.version >> 16);
3997 msm_property_install_blob(&psde->property_info, feature_name, 0,
3998 PLANE_PROP_FOLIAGE_COLOR);
3999 }
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07004000
4001 msm_property_install_enum(&psde->property_info, "fb_translation_mode",
4002 0x0,
4003 0, e_fb_translation_mode,
4004 ARRAY_SIZE(e_fb_translation_mode),
4005 PLANE_PROP_FB_TRANSLATION_MODE);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004006}
4007
Clarence Ip5fc00c52016-09-23 15:03:34 -04004008static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
4009{
4010 struct sde_drm_csc_v1 csc_v1;
4011 int i;
4012
4013 if (!psde) {
4014 SDE_ERROR("invalid plane\n");
4015 return;
4016 }
4017
4018 psde->csc_usr_ptr = NULL;
4019 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004020 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04004021 return;
4022 }
4023
4024 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004025 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04004026 return;
4027 }
4028
Clarence Ipb43d4592016-09-08 14:21:35 -04004029 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04004030 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
4031 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
4032 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
4033 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
4034 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
4035 }
4036 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
4037 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
4038 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
4039 }
4040 psde->csc_usr_ptr = &psde->csc_cfg;
4041}
4042
Clarence Ip172033f2017-06-13 10:52:56 -04004043static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde,
4044 struct sde_plane_state *pstate, void *usr)
Clarence Ipb43d4592016-09-08 14:21:35 -04004045{
4046 struct sde_drm_scaler_v1 scale_v1;
4047 struct sde_hw_pixel_ext *pe;
4048 int i;
4049
Clarence Ip172033f2017-06-13 10:52:56 -04004050 if (!psde || !pstate) {
4051 SDE_ERROR("invalid argument(s)\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004052 return;
4053 }
4054
Clarence Ip172033f2017-06-13 10:52:56 -04004055 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
Clarence Ipb43d4592016-09-08 14:21:35 -04004056 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004057 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004058 return;
4059 }
4060
4061 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004062 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004063 return;
4064 }
4065
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004066 /* force property to be dirty, even if the pointer didn't change */
Clarence Ip4a2955d2017-07-04 18:04:33 -04004067 msm_property_set_dirty(&psde->property_info,
4068 &pstate->property_state, PLANE_PROP_SCALER_V1);
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004069
Clarence Ipb43d4592016-09-08 14:21:35 -04004070 /* populate from user space */
Clarence Ip172033f2017-06-13 10:52:56 -04004071 pe = &pstate->pixel_ext;
Clarence Ipb43d4592016-09-08 14:21:35 -04004072 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
4073 for (i = 0; i < SDE_MAX_PLANES; i++) {
4074 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
4075 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
4076 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
4077 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
4078
4079 pe->horz_filter[i] = scale_v1.horz_filter[i];
4080 pe->vert_filter[i] = scale_v1.vert_filter[i];
4081 }
4082 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05004083 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
4084 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
4085 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
4086 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
4087 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04004088
abeykun41060122016-11-28 13:02:01 -05004089 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
4090 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
4091 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
4092 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
4093 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04004094 }
abeykun41060122016-11-28 13:02:01 -05004095
Clarence Ip172033f2017-06-13 10:52:56 -04004096 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
Clarence Ipb43d4592016-09-08 14:21:35 -04004097
Clarence Ip059c8c32017-06-06 17:15:54 -04004098 SDE_EVT32_VERBOSE(DRMID(&psde->base));
Clarence Ip13a8cf42016-09-29 17:27:47 -04004099 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004100}
4101
abeykun48f407a2016-08-25 12:06:44 -04004102static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
4103 struct sde_plane_state *pstate, void *usr)
4104{
4105 struct sde_drm_scaler_v2 scale_v2;
4106 struct sde_hw_pixel_ext *pe;
4107 int i;
4108 struct sde_hw_scaler3_cfg *cfg;
4109
Clarence Ip172033f2017-06-13 10:52:56 -04004110 if (!psde || !pstate) {
4111 SDE_ERROR("invalid argument(s)\n");
abeykun48f407a2016-08-25 12:06:44 -04004112 return;
4113 }
4114
Clarence Ip172033f2017-06-13 10:52:56 -04004115 cfg = &pstate->scaler3_cfg;
4116 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
abeykun48f407a2016-08-25 12:06:44 -04004117 if (!usr) {
4118 SDE_DEBUG_PLANE(psde, "scale data removed\n");
4119 return;
4120 }
4121
4122 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
4123 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
4124 return;
4125 }
4126
Clarence Ip7e892a02017-06-13 10:16:07 -04004127 /* detach/ignore user data if 'disabled' */
4128 if (!scale_v2.enable) {
4129 SDE_DEBUG_PLANE(psde, "scale data removed\n");
4130 return;
4131 }
4132
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004133 /* force property to be dirty, even if the pointer didn't change */
Clarence Ip4a2955d2017-07-04 18:04:33 -04004134 msm_property_set_dirty(&psde->property_info,
4135 &pstate->property_state, PLANE_PROP_SCALER_V2);
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004136
abeykun48f407a2016-08-25 12:06:44 -04004137 /* populate from user space */
Sravanthi Kollukuduru55b24f02017-06-22 15:11:31 +05304138 sde_set_scaler_v2(cfg, &scale_v2);
4139
Clarence Ip172033f2017-06-13 10:52:56 -04004140 pe = &pstate->pixel_ext;
abeykun48f407a2016-08-25 12:06:44 -04004141 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
abeykun48f407a2016-08-25 12:06:44 -04004142
abeykun48f407a2016-08-25 12:06:44 -04004143 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05004144 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
4145 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
4146 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
4147 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
4148 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04004149
abeykun41060122016-11-28 13:02:01 -05004150 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
4151 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
4152 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
4153 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
4154 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04004155 }
Clarence Ip172033f2017-06-13 10:52:56 -04004156 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
abeykun48f407a2016-08-25 12:06:44 -04004157
Clarence Ip059c8c32017-06-06 17:15:54 -04004158 SDE_EVT32_VERBOSE(DRMID(&psde->base), cfg->enable, cfg->de.enable,
4159 cfg->src_width[0], cfg->src_height[0],
4160 cfg->dst_width, cfg->dst_height);
abeykun48f407a2016-08-25 12:06:44 -04004161 SDE_DEBUG_PLANE(psde, "user property data copied\n");
4162}
4163
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004164static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
4165 struct sde_plane_state *pstate, void *usr_ptr)
4166{
4167 struct drm_clip_rect excl_rect_v1;
4168
4169 if (!psde) {
4170 SDE_ERROR("invalid plane\n");
4171 return;
4172 }
4173
4174 if (!usr_ptr) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004175 SDE_DEBUG_PLANE(psde, "invalid excl_rect user data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004176 return;
4177 }
4178
4179 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004180 SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004181 return;
4182 }
4183
4184 /* populate from user space */
4185 pstate->excl_rect.x = excl_rect_v1.x1;
4186 pstate->excl_rect.y = excl_rect_v1.y1;
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004187 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
4188 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
4189
4190 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
4191 pstate->excl_rect.x, pstate->excl_rect.y,
4192 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004193}
4194
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004195static int sde_plane_atomic_set_property(struct drm_plane *plane,
4196 struct drm_plane_state *state, struct drm_property *property,
4197 uint64_t val)
4198{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004199 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004200 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004201 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004202
Clarence Ip13a8cf42016-09-29 17:27:47 -04004203 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004204
4205 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004206 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004207 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004208 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004209 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04004210 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004211 ret = msm_property_atomic_set(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004212 &pstate->property_state, property, val);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004213 if (!ret) {
4214 idx = msm_property_index(&psde->property_info,
4215 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004216 switch (idx) {
4217 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04004218 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004219 break;
4220 case PLANE_PROP_CSC_V1:
4221 _sde_plane_set_csc_v1(psde, (void *)val);
4222 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04004223 case PLANE_PROP_SCALER_V1:
Clarence Ip172033f2017-06-13 10:52:56 -04004224 _sde_plane_set_scaler_v1(psde, pstate,
4225 (void *)val);
Clarence Ipb43d4592016-09-08 14:21:35 -04004226 break;
abeykun48f407a2016-08-25 12:06:44 -04004227 case PLANE_PROP_SCALER_V2:
4228 _sde_plane_set_scaler_v2(psde, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004229 (void *)val);
abeykun48f407a2016-08-25 12:06:44 -04004230 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004231 case PLANE_PROP_EXCL_RECT_V1:
4232 _sde_plane_set_excl_rect_v1(psde, pstate,
4233 (void *)val);
4234 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04004235 default:
4236 /* nothing to do */
4237 break;
4238 }
Clarence Ipe78efb72016-06-24 18:35:21 -04004239 }
4240 }
4241
Alan Kwong4dd64c82017-02-04 18:41:51 -08004242 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
4243 property->name, property->base.id, val, ret);
4244
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004245 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004246}
4247
4248static int sde_plane_set_property(struct drm_plane *plane,
4249 struct drm_property *property, uint64_t val)
4250{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004251 SDE_DEBUG("\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04004252
Clarence Ipae4e60c2016-06-26 22:44:04 -04004253 return sde_plane_atomic_set_property(plane,
4254 plane->state, property, val);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004255}
4256
4257static int sde_plane_atomic_get_property(struct drm_plane *plane,
4258 const struct drm_plane_state *state,
4259 struct drm_property *property, uint64_t *val)
4260{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004261 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004262 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04004263 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004264
Clarence Ipaa0faf42016-05-30 12:07:48 -04004265 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004266 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004267 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004268 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004269 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004270 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04004271 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004272 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004273 ret = msm_property_atomic_get(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004274 &pstate->property_state, property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04004275 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004276
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004277 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004278}
4279
4280static void sde_plane_destroy(struct drm_plane *plane)
4281{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004282 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004283
Clarence Ip13a8cf42016-09-29 17:27:47 -04004284 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004285
Clarence Ip13a8cf42016-09-29 17:27:47 -04004286 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04004287 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
4288
Dhaval Patel4e574842016-08-23 15:11:37 -07004289 if (psde->blob_info)
4290 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004291 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04004292 mutex_destroy(&psde->lock);
4293
Clarence Ip4ce59322016-06-26 22:27:51 -04004294 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004295
Clarence Ip4ce59322016-06-26 22:27:51 -04004296 /* this will destroy the states as well */
4297 drm_plane_cleanup(plane);
4298
Clarence Ip4c1d9772016-06-26 09:35:38 -04004299 if (psde->pipe_hw)
4300 sde_hw_sspp_destroy(psde->pipe_hw);
4301
Clarence Ip4ce59322016-06-26 22:27:51 -04004302 kfree(psde);
4303 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004304}
4305
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004306static void sde_plane_destroy_state(struct drm_plane *plane,
4307 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004308{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004309 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04004310 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004311
Clarence Ipae4e60c2016-06-26 22:44:04 -04004312 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004313 SDE_ERROR("invalid arg(s), plane %d state %d\n",
4314 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004315 return;
4316 }
4317
Clarence Ipaa0faf42016-05-30 12:07:48 -04004318 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04004319 pstate = to_sde_plane_state(state);
4320
Clarence Ip13a8cf42016-09-29 17:27:47 -04004321 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004322
Alan Kwong4dd64c82017-02-04 18:41:51 -08004323 sde_plane_rot_destroy_state(plane, &pstate->base);
4324
Clarence Ipe78efb72016-06-24 18:35:21 -04004325 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004326 if (state->fb)
4327 drm_framebuffer_unreference(state->fb);
4328
Clarence Ipae4e60c2016-06-26 22:44:04 -04004329 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04004330 if (pstate->input_fence)
4331 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004332
Clarence Ipaa0faf42016-05-30 12:07:48 -04004333 /* destroy value helper */
4334 msm_property_destroy_state(&psde->property_info, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004335 &pstate->property_state);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004336}
4337
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004338static struct drm_plane_state *
4339sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004340{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004341 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004342 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04004343 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04004344 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004345
Clarence Ip13a8cf42016-09-29 17:27:47 -04004346 if (!plane) {
4347 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004348 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004349 } else if (!plane->state) {
4350 SDE_ERROR("invalid plane state\n");
4351 return NULL;
4352 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004353
Clarence Ip730e7192016-06-26 22:45:09 -04004354 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004355 psde = to_sde_plane(plane);
4356 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004357 if (!pstate) {
4358 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004359 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004360 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004361
Clarence Ip13a8cf42016-09-29 17:27:47 -04004362 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004363
4364 /* duplicate value helper */
4365 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004366 &pstate->property_state, pstate->property_values);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004367
Clarence Ip17e908b2016-09-29 15:58:00 -04004368 /* clear out any input fence */
4369 pstate->input_fence = 0;
4370 input_fence_default = msm_property_get_default(
4371 &psde->property_info, PLANE_PROP_INPUT_FENCE);
Clarence Ip4a2955d2017-07-04 18:04:33 -04004372 msm_property_set_property(&psde->property_info,
4373 &pstate->property_state,
Clarence Ip17e908b2016-09-29 15:58:00 -04004374 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004375
Clarence Ip282dad62016-09-27 17:07:35 -04004376 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04004377 pstate->pending = false;
4378
Alan Kwongcdb2f282017-03-18 13:42:06 -07004379 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
4380
Alan Kwong4dd64c82017-02-04 18:41:51 -08004381 sde_plane_rot_duplicate_state(plane, &pstate->base);
4382
Clarence Ip730e7192016-06-26 22:45:09 -04004383 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004384}
4385
4386static void sde_plane_reset(struct drm_plane *plane)
4387{
Clarence Ipae4e60c2016-06-26 22:44:04 -04004388 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004389 struct sde_plane_state *pstate;
4390
Clarence Ipae4e60c2016-06-26 22:44:04 -04004391 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004392 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04004393 return;
4394 }
4395
Clarence Ip730e7192016-06-26 22:45:09 -04004396 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004397 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004398
Veera Sundaram Sankarandb43e282017-09-19 18:32:52 -07004399 if (plane->state && !sde_crtc_is_reset_required(plane->state->crtc)) {
4400 SDE_DEBUG_PLANE(psde, "avoid reset for plane\n");
4401 return;
4402 }
4403
Clarence Ipae4e60c2016-06-26 22:44:04 -04004404 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04004405 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04004406 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004407 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04004408 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004409
Clarence Ipaa0faf42016-05-30 12:07:48 -04004410 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004411 if (!pstate) {
4412 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004413 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004414 }
Clarence Ip730e7192016-06-26 22:45:09 -04004415
Clarence Ipaa0faf42016-05-30 12:07:48 -04004416 /* reset value helper */
4417 msm_property_reset_state(&psde->property_info, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004418 &pstate->property_state,
4419 pstate->property_values);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004420
4421 pstate->base.plane = plane;
4422
4423 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004424}
4425
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004426#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04004427static ssize_t _sde_plane_danger_read(struct file *file,
4428 char __user *buff, size_t count, loff_t *ppos)
4429{
4430 struct sde_kms *kms = file->private_data;
4431 struct sde_mdss_cfg *cfg = kms->catalog;
4432 int len = 0;
4433 char buf[40] = {'\0'};
4434
4435 if (!cfg)
4436 return -ENODEV;
4437
4438 if (*ppos)
4439 return 0; /* the end */
4440
4441 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
4442 if (len < 0 || len >= sizeof(buf))
4443 return 0;
4444
4445 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
4446 return -EFAULT;
4447
4448 *ppos += len; /* increase offset */
4449
4450 return len;
4451}
4452
4453static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
4454{
4455 struct drm_plane *plane;
4456
4457 drm_for_each_plane(plane, kms->dev) {
4458 if (plane->fb && plane->state) {
4459 sde_plane_danger_signal_ctrl(plane, enable);
4460 SDE_DEBUG("plane:%d img:%dx%d ",
4461 plane->base.id, plane->fb->width,
4462 plane->fb->height);
4463 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
4464 plane->state->src_x >> 16,
4465 plane->state->src_y >> 16,
4466 plane->state->src_w >> 16,
4467 plane->state->src_h >> 16,
4468 plane->state->crtc_x, plane->state->crtc_y,
4469 plane->state->crtc_w, plane->state->crtc_h);
4470 } else {
4471 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
4472 }
4473 }
4474}
4475
4476static ssize_t _sde_plane_danger_write(struct file *file,
4477 const char __user *user_buf, size_t count, loff_t *ppos)
4478{
4479 struct sde_kms *kms = file->private_data;
4480 struct sde_mdss_cfg *cfg = kms->catalog;
4481 int disable_panic;
4482 char buf[10];
4483
4484 if (!cfg)
4485 return -EFAULT;
4486
4487 if (count >= sizeof(buf))
4488 return -EFAULT;
4489
4490 if (copy_from_user(buf, user_buf, count))
4491 return -EFAULT;
4492
4493 buf[count] = 0; /* end of string */
4494
4495 if (kstrtoint(buf, 0, &disable_panic))
4496 return -EFAULT;
4497
4498 if (disable_panic) {
4499 /* Disable panic signal for all active pipes */
4500 SDE_DEBUG("Disabling danger:\n");
4501 _sde_plane_set_danger_state(kms, false);
4502 kms->has_danger_ctrl = false;
4503 } else {
4504 /* Enable panic signal for all active pipes */
4505 SDE_DEBUG("Enabling danger:\n");
4506 kms->has_danger_ctrl = true;
4507 _sde_plane_set_danger_state(kms, true);
4508 }
4509
4510 return count;
4511}
4512
4513static const struct file_operations sde_plane_danger_enable = {
4514 .open = simple_open,
4515 .read = _sde_plane_danger_read,
4516 .write = _sde_plane_danger_write,
4517};
4518
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004519static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04004520{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004521 struct sde_plane *psde;
4522 struct sde_kms *kms;
4523 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04004524 const struct sde_sspp_sub_blks *sblk = 0;
4525 const struct sde_sspp_cfg *cfg = 0;
4526
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004527 if (!plane || !plane->dev) {
4528 SDE_ERROR("invalid arguments\n");
4529 return -EINVAL;
4530 }
4531
4532 priv = plane->dev->dev_private;
4533 if (!priv || !priv->kms) {
4534 SDE_ERROR("invalid KMS reference\n");
4535 return -EINVAL;
4536 }
4537
4538 kms = to_sde_kms(priv->kms);
4539 psde = to_sde_plane(plane);
4540
Clarence Ip4ce59322016-06-26 22:27:51 -04004541 if (psde && psde->pipe_hw)
4542 cfg = psde->pipe_hw->cap;
4543 if (cfg)
4544 sblk = cfg->sblk;
4545
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004546 if (!sblk)
4547 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04004548
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004549 /* create overall sub-directory for the pipe */
4550 psde->debugfs_root =
4551 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07004552 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04004553
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004554 if (!psde->debugfs_root)
4555 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04004556
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004557 /* don't error check these */
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004558 debugfs_create_x32("features", 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004559 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004560
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004561 /* add register dump support */
4562 sde_debugfs_setup_regset32(&psde->debugfs_src,
4563 sblk->src_blk.base + cfg->base,
4564 sblk->src_blk.len,
4565 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004566 sde_debugfs_create_regset32("src_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004567 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004568
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004569 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
4570 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
4571 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
4572 sblk->scaler_blk.base + cfg->base,
4573 sblk->scaler_blk.len,
4574 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004575 sde_debugfs_create_regset32("scaler_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004576 psde->debugfs_root,
4577 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07004578 debugfs_create_bool("default_scaling",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004579 0600,
Clarence Ip716ab662017-03-20 06:51:24 -07004580 psde->debugfs_root,
4581 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04004582 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004583
4584 if (cfg->features & BIT(SDE_SSPP_CSC) ||
4585 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
4586 sde_debugfs_setup_regset32(&psde->debugfs_csc,
4587 sblk->csc_blk.base + cfg->base,
4588 sblk->csc_blk.len,
4589 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004590 sde_debugfs_create_regset32("csc_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004591 psde->debugfs_root, &psde->debugfs_csc);
4592 }
4593
4594 debugfs_create_u32("xin_id",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004595 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004596 psde->debugfs_root,
4597 (u32 *) &cfg->xin_id);
4598 debugfs_create_u32("clk_ctrl",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004599 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004600 psde->debugfs_root,
4601 (u32 *) &cfg->clk_ctrl);
4602 debugfs_create_x32("creq_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004603 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004604 psde->debugfs_root,
4605 (u32 *) &sblk->creq_vblank);
4606 debugfs_create_x32("danger_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004607 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004608 psde->debugfs_root,
4609 (u32 *) &sblk->danger_vblank);
4610
4611 debugfs_create_file("disable_danger",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004612 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004613 psde->debugfs_root,
4614 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004615 debugfs_create_u32("sbuf_mode",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004616 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004617 psde->debugfs_root, &psde->sbuf_mode);
4618 debugfs_create_u32("sbuf_writeback",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004619 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004620 psde->debugfs_root,
4621 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004622
4623 return 0;
4624}
4625
4626static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4627{
4628 struct sde_plane *psde;
4629
4630 if (!plane)
4631 return;
4632 psde = to_sde_plane(plane);
4633
4634 debugfs_remove_recursive(psde->debugfs_root);
4635}
4636#else
4637static int _sde_plane_init_debugfs(struct drm_plane *plane)
4638{
4639 return 0;
4640}
4641static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4642{
4643}
4644#endif
4645
4646static int sde_plane_late_register(struct drm_plane *plane)
4647{
4648 return _sde_plane_init_debugfs(plane);
4649}
4650
4651static void sde_plane_early_unregister(struct drm_plane *plane)
4652{
4653 _sde_plane_destroy_debugfs(plane);
4654}
4655
4656static const struct drm_plane_funcs sde_plane_funcs = {
4657 .update_plane = drm_atomic_helper_update_plane,
4658 .disable_plane = drm_atomic_helper_disable_plane,
4659 .destroy = sde_plane_destroy,
4660 .set_property = sde_plane_set_property,
4661 .atomic_set_property = sde_plane_atomic_set_property,
4662 .atomic_get_property = sde_plane_atomic_get_property,
4663 .reset = sde_plane_reset,
4664 .atomic_duplicate_state = sde_plane_duplicate_state,
4665 .atomic_destroy_state = sde_plane_destroy_state,
4666 .late_register = sde_plane_late_register,
4667 .early_unregister = sde_plane_early_unregister,
4668};
4669
4670static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
4671 .prepare_fb = sde_plane_prepare_fb,
4672 .cleanup_fb = sde_plane_cleanup_fb,
4673 .atomic_check = sde_plane_atomic_check,
4674 .atomic_update = sde_plane_atomic_update,
4675};
4676
4677enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
4678{
4679 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
4680}
4681
4682bool is_sde_plane_virtual(struct drm_plane *plane)
4683{
4684 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04004685}
4686
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004687/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04004688struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04004689 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004690 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004691{
Alan Kwongdce56da2017-04-27 15:50:34 -07004692 struct drm_plane *plane = NULL, *master_plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004693 const struct sde_format_extended *format_list;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004694 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004695 struct msm_drm_private *priv;
4696 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004697 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04004698 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004699
4700 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004701 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004702 goto exit;
4703 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004704
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004705 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004706 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004707 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004708 goto exit;
4709 }
4710
4711 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004712 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004713 goto exit;
4714 }
4715 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004716
Clarence Ip4c1d9772016-06-26 09:35:38 -04004717 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004718 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004719 goto exit;
4720 }
4721
Clarence Ip4ce59322016-06-26 22:27:51 -04004722 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004723 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4724 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004725 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004726 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004727 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004728 }
4729
Clarence Ip4c1d9772016-06-26 09:35:38 -04004730 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004731 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004732 psde->pipe = pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004733 psde->is_virtual = (master_plane_id != 0);
Alan Kwongdce56da2017-04-27 15:50:34 -07004734 INIT_LIST_HEAD(&psde->mplane_list);
4735 master_plane = drm_plane_find(dev, master_plane_id);
4736 if (master_plane) {
4737 struct sde_plane *mpsde = to_sde_plane(master_plane);
4738
4739 list_add_tail(&psde->mplane_list, &mpsde->mplane_list);
4740 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004741
Clarence Ip4c1d9772016-06-26 09:35:38 -04004742 /* initialize underlying h/w driver */
Dhaval Pateld850b222017-06-16 17:37:37 -07004743 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog,
4744 master_plane_id != 0);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004745 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004746 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004747 ret = PTR_ERR(psde->pipe_hw);
4748 goto clean_plane;
4749 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004750 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004751 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004752 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004753
4754 /* cache features mask for later */
4755 psde->features = psde->pipe_hw->cap->features;
4756 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004757 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004758 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004759 goto clean_sspp;
4760 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004761
Steve Cohen57428172017-07-18 10:57:17 -04004762 if (!master_plane_id)
4763 format_list = psde->pipe_sblk->format_list;
4764 else
4765 format_list = psde->pipe_sblk->virt_format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004766
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004767 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004768 psde->formats,
4769 0,
4770 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004771
Clarence Ip4c1d9772016-06-26 09:35:38 -04004772 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004773 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004774 goto clean_sspp;
4775 }
4776
4777 if (psde->features & BIT(SDE_SSPP_CURSOR))
4778 type = DRM_PLANE_TYPE_CURSOR;
4779 else if (primary_plane)
4780 type = DRM_PLANE_TYPE_PRIMARY;
4781 else
4782 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07004783 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
4784 psde->formats, psde->nformats,
4785 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004786 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04004787 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004788
Clarence Ip4c1d9772016-06-26 09:35:38 -04004789 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004790 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004791
Clarence Ipaa0faf42016-05-30 12:07:48 -04004792 msm_property_init(&psde->property_info, &plane->base, dev,
4793 priv->plane_property, psde->property_data,
4794 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
4795 sizeof(struct sde_plane_state));
4796
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004797 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004798
Clarence Ip4ce59322016-06-26 22:27:51 -04004799 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04004800 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04004801
Clarence Ip730e7192016-06-26 22:45:09 -04004802 mutex_init(&psde->lock);
4803
Dhaval Patel572cfd22017-06-12 19:33:39 -07004804 SDE_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", psde->pipe_name,
4805 pipe, plane->base.id, master_plane_id);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004806 return plane;
4807
Clarence Ip4c1d9772016-06-26 09:35:38 -04004808clean_sspp:
4809 if (psde && psde->pipe_hw)
4810 sde_hw_sspp_destroy(psde->pipe_hw);
4811clean_plane:
4812 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04004813exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004814 return ERR_PTR(ret);
4815}