blob: e477462698810b8ee6f97a0276e4a76719671dd5 [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 Ip13a8cf42016-09-29 17:27:47 -040041#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
42 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
43
44#define SDE_ERROR_PLANE(pl, fmt, ...) SDE_ERROR("plane%d " fmt,\
45 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
46
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040047#define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
48#define PHASE_STEP_SHIFT 21
49#define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
50#define PHASE_RESIDUAL 15
51
Clarence Ipe78efb72016-06-24 18:35:21 -040052#define SHARP_STRENGTH_DEFAULT 32
53#define SHARP_EDGE_THR_DEFAULT 112
54#define SHARP_SMOOTH_THR_DEFAULT 8
55#define SHARP_NOISE_THR_DEFAULT 2
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040056
Clarence Ip5e2a9222016-06-26 22:38:24 -040057#define SDE_NAME_SIZE 12
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070058
Clarence Ipcae1bb62016-07-07 12:07:13 -040059#define SDE_PLANE_COLOR_FILL_FLAG BIT(31)
60
Jeykumar Sankaran2e655032017-02-04 14:05:45 -080061/* multirect rect index */
62enum {
63 R0,
64 R1,
65 R_MAX
66};
67
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -070068#define SDE_QSEED3_DEFAULT_PRELOAD_H 0x4
69#define SDE_QSEED3_DEFAULT_PRELOAD_V 0x3
70
Alan Kwong4dd64c82017-02-04 18:41:51 -080071#define DEFAULT_REFRESH_RATE 60
72
Alan Kwong1a00e4d2016-07-18 09:42:30 -040073/**
74 * enum sde_plane_qos - Different qos configurations for each pipe
75 *
76 * @SDE_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
77 * @SDE_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
78 * this configuration is mutually exclusive from VBLANK_CTRL.
79 * @SDE_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
80 */
81enum sde_plane_qos {
82 SDE_PLANE_QOS_VBLANK_CTRL = BIT(0),
83 SDE_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
84 SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
85};
86
Clarence Ip5fc00c52016-09-23 15:03:34 -040087/*
88 * struct sde_plane - local sde plane structure
Jordan Croused8e96522017-02-13 10:14:16 -070089 * @aspace: address space pointer
Clarence Ip5fc00c52016-09-23 15:03:34 -040090 * @csc_cfg: Decoded user configuration for csc
91 * @csc_usr_ptr: Points to csc_cfg if valid user config available
92 * @csc_ptr: Points to sde_csc_cfg structure to use for current
Alan Kwongdce56da2017-04-27 15:50:34 -070093 * @mplane_list: List of multirect planes of the same pipe
Alan Kwong4dd64c82017-02-04 18:41:51 -080094 * @catalog: Points to sde catalog structure
95 * @sbuf_mode: force stream buffer mode if set
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -070096 * @sbuf_writeback: force stream buffer writeback if set
97 * @revalidate: force revalidation of all the plane properties
Clarence Ip2606dd62017-10-14 21:11:14 -040098 * @xin_halt_forced_clk: whether or not clocks were forced on for xin halt
Alan Kwong4dd64c82017-02-04 18:41:51 -080099 * @blob_rot_caps: Pointer to rotator capability blob
Clarence Ip5fc00c52016-09-23 15:03:34 -0400100 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700101struct sde_plane {
102 struct drm_plane base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400103
Clarence Ip730e7192016-06-26 22:45:09 -0400104 struct mutex lock;
105
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400106 enum sde_sspp pipe;
107 uint32_t features; /* capabilities from catalog */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700108 uint32_t nformats;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400109 uint32_t formats[64];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400110
111 struct sde_hw_pipe *pipe_hw;
112 struct sde_hw_pipe_cfg pipe_cfg;
Clarence Ipe78efb72016-06-24 18:35:21 -0400113 struct sde_hw_sharp_cfg sharp_cfg;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400114 struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400115 uint32_t color_fill;
116 bool is_error;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400117 bool is_rt_pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800118 bool is_virtual;
Alan Kwongdce56da2017-04-27 15:50:34 -0700119 struct list_head mplane_list;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800120 struct sde_mdss_cfg *catalog;
121 u32 sbuf_mode;
122 u32 sbuf_writeback;
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700123 bool revalidate;
Clarence Ip2606dd62017-10-14 21:11:14 -0400124 bool xin_halt_forced_clk;
Clarence Ip4ce59322016-06-26 22:27:51 -0400125
Clarence Ip373f8592016-05-26 00:58:42 -0400126 struct sde_csc_cfg csc_cfg;
Clarence Ip5fc00c52016-09-23 15:03:34 -0400127 struct sde_csc_cfg *csc_usr_ptr;
Clarence Ip373f8592016-05-26 00:58:42 -0400128 struct sde_csc_cfg *csc_ptr;
129
Clarence Ip4c1d9772016-06-26 09:35:38 -0400130 const struct sde_sspp_sub_blks *pipe_sblk;
131
Clarence Ip5e2a9222016-06-26 22:38:24 -0400132 char pipe_name[SDE_NAME_SIZE];
Clarence Ip4ce59322016-06-26 22:27:51 -0400133
Clarence Ipaa0faf42016-05-30 12:07:48 -0400134 struct msm_property_info property_info;
135 struct msm_property_data property_data[PLANE_PROP_COUNT];
Dhaval Patel4e574842016-08-23 15:11:37 -0700136 struct drm_property_blob *blob_info;
Alan Kwong4dd64c82017-02-04 18:41:51 -0800137 struct drm_property_blob *blob_rot_caps;
Clarence Ip730e7192016-06-26 22:45:09 -0400138
Clarence Ip4ce59322016-06-26 22:27:51 -0400139 /* debugfs related stuff */
140 struct dentry *debugfs_root;
141 struct sde_debugfs_regset32 debugfs_src;
142 struct sde_debugfs_regset32 debugfs_scaler;
143 struct sde_debugfs_regset32 debugfs_csc;
Clarence Ip716ab662017-03-20 06:51:24 -0700144 bool debugfs_default_scale;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700145};
Dhaval Patel47302cf2016-08-18 15:04:28 -0700146
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700147#define to_sde_plane(x) container_of(x, struct sde_plane, base)
148
Alan Kwong4dd64c82017-02-04 18:41:51 -0800149static struct sde_kms *_sde_plane_get_kms(struct drm_plane *plane)
150{
151 struct msm_drm_private *priv;
152
153 if (!plane || !plane->dev)
154 return NULL;
155 priv = plane->dev->dev_private;
156 if (!priv)
157 return NULL;
158 return to_sde_kms(priv->kms);
159}
160
Alan Kwong4aacd532017-02-04 18:51:33 -0800161/**
162 * _sde_plane_get_crtc_state - obtain crtc state attached to given plane state
163 * @pstate: Pointer to drm plane state
164 * return: Pointer to crtc state if success; pointer error, otherwise
165 */
166static struct drm_crtc_state *_sde_plane_get_crtc_state(
167 struct drm_plane_state *pstate)
168{
169 struct drm_crtc_state *cstate;
170
171 if (!pstate || !pstate->crtc)
172 return NULL;
173
174 if (pstate->state)
175 cstate = drm_atomic_get_crtc_state(pstate->state, pstate->crtc);
176 else
177 cstate = pstate->crtc->state;
178
179 return cstate;
180}
181
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400182static bool sde_plane_enabled(struct drm_plane_state *state)
183{
Clarence Ipdbde9832016-06-26 09:48:36 -0400184 return state && state->fb && state->crtc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400185}
186
Alan Kwong4dd64c82017-02-04 18:41:51 -0800187static bool sde_plane_sspp_enabled(struct drm_plane_state *state)
188{
189 return state && to_sde_plane_state(state)->rot.out_fb && state->crtc;
190}
191
192/**
193 * sde_plane_crtc_enabled - determine if crtc of given plane state is enabled
194 * @state: Pointer to drm plane state
195 * return: true if plane and the associated crtc are both enabled
196 */
197static bool sde_plane_crtc_enabled(struct drm_plane_state *state)
198{
199 return sde_plane_enabled(state) && state->crtc->state &&
200 state->crtc->state->active &&
201 state->crtc->state->enable;
202}
203
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400204/**
205 * _sde_plane_calc_fill_level - calculate fill level of the given source format
206 * @plane: Pointer to drm plane
207 * @fmt: Pointer to source buffer format
208 * @src_wdith: width of source buffer
209 * Return: fill level corresponding to the source buffer/format or 0 if error
210 */
211static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
212 const struct sde_format *fmt, u32 src_width)
213{
Alan Kwongdce56da2017-04-27 15:50:34 -0700214 struct sde_plane *psde, *tmp;
215 struct sde_plane_state *pstate;
216 struct sde_plane_rot_state *rstate;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400217 u32 fixed_buff_size;
218 u32 total_fl;
Alan Kwongdce56da2017-04-27 15:50:34 -0700219 u32 hflip_bytes;
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700220 u32 unused_space;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400221
Alan Kwongdce56da2017-04-27 15:50:34 -0700222 if (!plane || !fmt || !plane->state || !src_width || !fmt->bpp) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400223 SDE_ERROR("invalid arguments\n");
224 return 0;
225 }
226
227 psde = to_sde_plane(plane);
Alan Kwongdce56da2017-04-27 15:50:34 -0700228 pstate = to_sde_plane_state(plane->state);
229 rstate = &pstate->rot;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400230 fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
231
Alan Kwongdce56da2017-04-27 15:50:34 -0700232 list_for_each_entry(tmp, &psde->mplane_list, mplane_list) {
233 if (!sde_plane_enabled(tmp->base.state))
234 continue;
235 SDE_DEBUG("plane%d/%d src_width:%d/%d\n",
236 psde->base.base.id, tmp->base.base.id,
237 src_width, tmp->pipe_cfg.src_rect.w);
238 src_width = max_t(u32, src_width, tmp->pipe_cfg.src_rect.w);
239 }
240
241 if ((rstate->out_rotation & DRM_REFLECT_X) &&
242 SDE_FORMAT_IS_LINEAR(fmt))
243 hflip_bytes = (src_width + 32) * fmt->bpp;
244 else
245 hflip_bytes = 0;
246
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400247 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700248
249 unused_space = 23 * 128;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400250 if (fmt->chroma_sample == SDE_CHROMA_420) {
251 /* NV12 */
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700252 total_fl = (fixed_buff_size / 2 - hflip_bytes -
253 unused_space) / ((src_width + 32) * fmt->bpp);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400254 } else {
255 /* non NV12 */
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700256 total_fl = (fixed_buff_size / 2 - hflip_bytes -
257 unused_space) * 2 / ((src_width + 32) *
258 fmt->bpp);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400259 }
260 } else {
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700261
262 unused_space = 6 * 128;
Alan Kwongdce56da2017-04-27 15:50:34 -0700263 if (pstate->multirect_mode == SDE_SSPP_MULTIRECT_PARALLEL) {
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700264 total_fl = (fixed_buff_size / 2 - hflip_bytes -
265 unused_space) * 2 / ((src_width + 32) *
266 fmt->bpp);
Alan Kwongdce56da2017-04-27 15:50:34 -0700267 } else {
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700268 total_fl = (fixed_buff_size - hflip_bytes -
269 unused_space) * 2 / ((src_width + 32) *
270 fmt->bpp);
Alan Kwongdce56da2017-04-27 15:50:34 -0700271 }
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400272 }
273
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700274 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u hf:%d us:%d fl:%u\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400275 plane->base.id, psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700276 (char *)&fmt->base.pixel_format,
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700277 src_width, hflip_bytes, unused_space, total_fl);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400278
279 return total_fl;
280}
281
282/**
Alan Kwongdce56da2017-04-27 15:50:34 -0700283 * _sde_plane_get_qos_lut - get LUT mapping based on fill level
284 * @tbl: Pointer to LUT table
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400285 * @total_fl: fill level
286 * Return: LUT setting corresponding to the fill level
287 */
Alan Kwongdce56da2017-04-27 15:50:34 -0700288static u64 _sde_plane_get_qos_lut(const struct sde_qos_lut_tbl *tbl,
289 u32 total_fl)
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400290{
Alan Kwongdce56da2017-04-27 15:50:34 -0700291 int i;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400292
Alan Kwongdce56da2017-04-27 15:50:34 -0700293 if (!tbl || !tbl->nentry || !tbl->entries)
294 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400295
Alan Kwongdce56da2017-04-27 15:50:34 -0700296 for (i = 0; i < tbl->nentry; i++)
297 if (total_fl <= tbl->entries[i].fl)
298 return tbl->entries[i].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400299
Alan Kwongdce56da2017-04-27 15:50:34 -0700300 /* if last fl is zero, use as default */
301 if (!tbl->entries[i-1].fl)
302 return tbl->entries[i-1].lut;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400303
Alan Kwongdce56da2017-04-27 15:50:34 -0700304 return 0;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400305}
306
307/**
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400308 * _sde_plane_set_qos_lut - set QoS LUT of the given plane
309 * @plane: Pointer to drm plane
310 * @fb: Pointer to framebuffer associated with the given plane
311 */
312static void _sde_plane_set_qos_lut(struct drm_plane *plane,
313 struct drm_framebuffer *fb)
314{
315 struct sde_plane *psde;
316 const struct sde_format *fmt = NULL;
Alan Kwongdce56da2017-04-27 15:50:34 -0700317 u64 qos_lut;
318 u32 total_fl = 0, lut_usage;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400319
320 if (!plane || !fb) {
321 SDE_ERROR("invalid arguments plane %d fb %d\n",
322 plane != 0, fb != 0);
323 return;
324 }
325
326 psde = to_sde_plane(plane);
327
Alan Kwongdce56da2017-04-27 15:50:34 -0700328 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400329 SDE_ERROR("invalid arguments\n");
330 return;
331 } else if (!psde->pipe_hw->ops.setup_creq_lut) {
332 return;
333 }
334
335 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700336 lut_usage = SDE_QOS_LUT_USAGE_NRT;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400337 } else {
338 fmt = sde_get_sde_format_ext(
339 fb->pixel_format,
340 fb->modifier,
341 drm_format_num_planes(fb->pixel_format));
342 total_fl = _sde_plane_calc_fill_level(plane, fmt,
343 psde->pipe_cfg.src_rect.w);
344
Narendra Muppallaec11a0a2017-06-15 15:35:17 -0700345 if (fmt && SDE_FORMAT_IS_LINEAR(fmt))
Alan Kwongdce56da2017-04-27 15:50:34 -0700346 lut_usage = SDE_QOS_LUT_USAGE_LINEAR;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400347 else
Alan Kwongdce56da2017-04-27 15:50:34 -0700348 lut_usage = SDE_QOS_LUT_USAGE_MACROTILE;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400349 }
350
Alan Kwongdce56da2017-04-27 15:50:34 -0700351 qos_lut = _sde_plane_get_qos_lut(
352 &psde->catalog->perf.qos_lut_tbl[lut_usage], total_fl);
353
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400354 psde->pipe_qos_cfg.creq_lut = qos_lut;
355
356 trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
357 (fmt) ? fmt->base.pixel_format : 0,
Alan Kwongdce56da2017-04-27 15:50:34 -0700358 psde->is_rt_pipe, total_fl, qos_lut, lut_usage);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400359
Alan Kwongdce56da2017-04-27 15:50:34 -0700360 SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400361 plane->base.id,
362 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700363 fmt ? (char *)&fmt->base.pixel_format : NULL,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400364 psde->is_rt_pipe, total_fl, qos_lut);
365
366 psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
367}
368
369/**
370 * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
371 * @plane: Pointer to drm plane
372 * @fb: Pointer to framebuffer associated with the given plane
373 */
374static void _sde_plane_set_danger_lut(struct drm_plane *plane,
375 struct drm_framebuffer *fb)
376{
377 struct sde_plane *psde;
378 const struct sde_format *fmt = NULL;
379 u32 danger_lut, safe_lut;
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700380 u32 total_fl = 0, lut_usage;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400381
382 if (!plane || !fb) {
383 SDE_ERROR("invalid arguments\n");
384 return;
385 }
386
387 psde = to_sde_plane(plane);
388
Alan Kwongdce56da2017-04-27 15:50:34 -0700389 if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400390 SDE_ERROR("invalid arguments\n");
391 return;
392 } else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
393 return;
394 }
395
396 if (!psde->is_rt_pipe) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700397 danger_lut = psde->catalog->perf.danger_lut_tbl
398 [SDE_QOS_LUT_USAGE_NRT];
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700399 lut_usage = SDE_QOS_LUT_USAGE_NRT;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400400 } else {
401 fmt = sde_get_sde_format_ext(
402 fb->pixel_format,
403 fb->modifier,
404 drm_format_num_planes(fb->pixel_format));
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700405 total_fl = _sde_plane_calc_fill_level(plane, fmt,
406 psde->pipe_cfg.src_rect.w);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400407
Narendra Muppallaec11a0a2017-06-15 15:35:17 -0700408 if (fmt && SDE_FORMAT_IS_LINEAR(fmt)) {
Alan Kwongdce56da2017-04-27 15:50:34 -0700409 danger_lut = psde->catalog->perf.danger_lut_tbl
410 [SDE_QOS_LUT_USAGE_LINEAR];
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700411 lut_usage = SDE_QOS_LUT_USAGE_LINEAR;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400412 } else {
Alan Kwongdce56da2017-04-27 15:50:34 -0700413 danger_lut = psde->catalog->perf.danger_lut_tbl
414 [SDE_QOS_LUT_USAGE_MACROTILE];
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700415 lut_usage = SDE_QOS_LUT_USAGE_MACROTILE;
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400416 }
417 }
418
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700419 safe_lut = (u32) _sde_plane_get_qos_lut(
420 &psde->catalog->perf.sfe_lut_tbl[lut_usage], total_fl);
421
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400422 psde->pipe_qos_cfg.danger_lut = danger_lut;
423 psde->pipe_qos_cfg.safe_lut = safe_lut;
424
425 trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
426 (fmt) ? fmt->base.pixel_format : 0,
427 (fmt) ? fmt->fetch_mode : 0,
428 psde->pipe_qos_cfg.danger_lut,
429 psde->pipe_qos_cfg.safe_lut);
430
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700431 SDE_DEBUG("plane%u: pnum:%d fmt:%4.4s mode:%d fl:%d luts[0x%x,0x%x]\n",
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400432 plane->base.id,
433 psde->pipe - SSPP_VIG0,
Dhaval Patel6c666622017-03-21 23:02:59 -0700434 fmt ? (char *)&fmt->base.pixel_format : NULL,
Ingrid Gallardo3b720fc2017-10-06 17:23:55 -0700435 fmt ? fmt->fetch_mode : -1, total_fl,
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400436 psde->pipe_qos_cfg.danger_lut,
437 psde->pipe_qos_cfg.safe_lut);
438
439 psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
440 &psde->pipe_qos_cfg);
441}
442
443/**
444 * _sde_plane_set_qos_ctrl - set QoS control of the given plane
445 * @plane: Pointer to drm plane
446 * @enable: true to enable QoS control
447 * @flags: QoS control mode (enum sde_plane_qos)
448 */
449static void _sde_plane_set_qos_ctrl(struct drm_plane *plane,
450 bool enable, u32 flags)
451{
452 struct sde_plane *psde;
453
454 if (!plane) {
455 SDE_ERROR("invalid arguments\n");
456 return;
457 }
458
459 psde = to_sde_plane(plane);
460
461 if (!psde->pipe_hw || !psde->pipe_sblk) {
462 SDE_ERROR("invalid arguments\n");
463 return;
464 } else if (!psde->pipe_hw->ops.setup_qos_ctrl) {
465 return;
466 }
467
468 if (flags & SDE_PLANE_QOS_VBLANK_CTRL) {
469 psde->pipe_qos_cfg.creq_vblank = psde->pipe_sblk->creq_vblank;
470 psde->pipe_qos_cfg.danger_vblank =
471 psde->pipe_sblk->danger_vblank;
472 psde->pipe_qos_cfg.vblank_en = enable;
473 }
474
475 if (flags & SDE_PLANE_QOS_VBLANK_AMORTIZE) {
476 /* this feature overrules previous VBLANK_CTRL */
477 psde->pipe_qos_cfg.vblank_en = false;
478 psde->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
479 }
480
481 if (flags & SDE_PLANE_QOS_PANIC_CTRL)
482 psde->pipe_qos_cfg.danger_safe_en = enable;
483
484 if (!psde->is_rt_pipe) {
485 psde->pipe_qos_cfg.vblank_en = false;
486 psde->pipe_qos_cfg.danger_safe_en = false;
487 }
488
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400489 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 -0400490 plane->base.id,
491 psde->pipe - SSPP_VIG0,
492 psde->pipe_qos_cfg.danger_safe_en,
493 psde->pipe_qos_cfg.vblank_en,
494 psde->pipe_qos_cfg.creq_vblank,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400495 psde->pipe_qos_cfg.danger_vblank,
496 psde->is_rt_pipe);
Alan Kwong1a00e4d2016-07-18 09:42:30 -0400497
498 psde->pipe_hw->ops.setup_qos_ctrl(psde->pipe_hw,
499 &psde->pipe_qos_cfg);
500}
501
Veera Sundaram Sankaran82916e02017-03-29 18:44:22 -0700502void sde_plane_set_revalidate(struct drm_plane *plane, bool enable)
503{
504 struct sde_plane *psde;
505
506 if (!plane)
507 return;
508
509 psde = to_sde_plane(plane);
510 psde->revalidate = enable;
511}
512
Alan Kwongf0fd8512016-10-24 21:39:26 -0400513int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
514{
515 struct sde_plane *psde;
516 struct msm_drm_private *priv;
517 struct sde_kms *sde_kms;
518
519 if (!plane || !plane->dev) {
520 SDE_ERROR("invalid arguments\n");
521 return -EINVAL;
522 }
523
524 priv = plane->dev->dev_private;
525 if (!priv || !priv->kms) {
526 SDE_ERROR("invalid KMS reference\n");
527 return -EINVAL;
528 }
529
530 sde_kms = to_sde_kms(priv->kms);
531 psde = to_sde_plane(plane);
532
533 if (!psde->is_rt_pipe)
534 goto end;
535
536 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
537
538 _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
539
540 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
541
542end:
543 return 0;
544}
545
Alan Kwong5d324e42016-07-28 22:56:18 -0400546/**
547 * _sde_plane_set_ot_limit - set OT limit for the given plane
548 * @plane: Pointer to drm plane
549 * @crtc: Pointer to drm crtc
550 */
551static void _sde_plane_set_ot_limit(struct drm_plane *plane,
552 struct drm_crtc *crtc)
553{
554 struct sde_plane *psde;
555 struct sde_vbif_set_ot_params ot_params;
556 struct msm_drm_private *priv;
557 struct sde_kms *sde_kms;
558
559 if (!plane || !plane->dev || !crtc) {
560 SDE_ERROR("invalid arguments plane %d crtc %d\n",
561 plane != 0, crtc != 0);
562 return;
563 }
564
565 priv = plane->dev->dev_private;
566 if (!priv || !priv->kms) {
567 SDE_ERROR("invalid KMS reference\n");
568 return;
569 }
570
571 sde_kms = to_sde_kms(priv->kms);
572 psde = to_sde_plane(plane);
573 if (!psde->pipe_hw) {
574 SDE_ERROR("invalid pipe reference\n");
575 return;
576 }
577
578 memset(&ot_params, 0, sizeof(ot_params));
579 ot_params.xin_id = psde->pipe_hw->cap->xin_id;
580 ot_params.num = psde->pipe_hw->idx - SSPP_NONE;
581 ot_params.width = psde->pipe_cfg.src_rect.w;
582 ot_params.height = psde->pipe_cfg.src_rect.h;
583 ot_params.is_wfd = !psde->is_rt_pipe;
584 ot_params.frame_rate = crtc->mode.vrefresh;
585 ot_params.vbif_idx = VBIF_RT;
586 ot_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
587 ot_params.rd = true;
588
589 sde_vbif_set_ot_limit(sde_kms, &ot_params);
590}
591
Alan Kwonga62eeb82017-04-19 08:57:55 -0700592/**
593 * _sde_plane_set_vbif_qos - set vbif QoS for the given plane
594 * @plane: Pointer to drm plane
595 */
596static void _sde_plane_set_qos_remap(struct drm_plane *plane)
597{
598 struct sde_plane *psde;
599 struct sde_vbif_set_qos_params qos_params;
600 struct msm_drm_private *priv;
601 struct sde_kms *sde_kms;
602
603 if (!plane || !plane->dev) {
604 SDE_ERROR("invalid arguments\n");
605 return;
606 }
607
608 priv = plane->dev->dev_private;
609 if (!priv || !priv->kms) {
610 SDE_ERROR("invalid KMS reference\n");
611 return;
612 }
613
614 sde_kms = to_sde_kms(priv->kms);
615 psde = to_sde_plane(plane);
616 if (!psde->pipe_hw) {
617 SDE_ERROR("invalid pipe reference\n");
618 return;
619 }
620
621 memset(&qos_params, 0, sizeof(qos_params));
622 qos_params.vbif_idx = VBIF_RT;
623 qos_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
624 qos_params.xin_id = psde->pipe_hw->cap->xin_id;
625 qos_params.num = psde->pipe_hw->idx - SSPP_VIG0;
626 qos_params.is_rt = psde->is_rt_pipe;
627
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700628 SDE_DEBUG("plane%d pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n",
Alan Kwonga62eeb82017-04-19 08:57:55 -0700629 plane->base.id, qos_params.num,
630 qos_params.vbif_idx,
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700631 qos_params.xin_id, qos_params.is_rt,
632 qos_params.clk_ctrl);
Alan Kwonga62eeb82017-04-19 08:57:55 -0700633
634 sde_vbif_set_qos_remap(sde_kms, &qos_params);
635}
636
Alan Kwong2349d742017-04-20 08:27:30 -0700637/**
638 * _sde_plane_set_ts_prefill - set prefill with traffic shaper
639 * @plane: Pointer to drm plane
640 * @pstate: Pointer to sde plane state
641 */
642static void _sde_plane_set_ts_prefill(struct drm_plane *plane,
643 struct sde_plane_state *pstate)
644{
645 struct sde_plane *psde;
646 struct sde_hw_pipe_ts_cfg cfg;
647 struct msm_drm_private *priv;
648 struct sde_kms *sde_kms;
649
650 if (!plane || !plane->dev) {
651 SDE_ERROR("invalid arguments");
652 return;
653 }
654
655 priv = plane->dev->dev_private;
656 if (!priv || !priv->kms) {
657 SDE_ERROR("invalid KMS reference\n");
658 return;
659 }
660
661 sde_kms = to_sde_kms(priv->kms);
662 psde = to_sde_plane(plane);
663 if (!psde->pipe_hw) {
664 SDE_ERROR("invalid pipe reference\n");
665 return;
666 }
667
668 if (!psde->pipe_hw || !psde->pipe_hw->ops.setup_ts_prefill)
669 return;
670
671 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_VBLANK_AMORTIZE);
672
673 memset(&cfg, 0, sizeof(cfg));
674 cfg.size = sde_plane_get_property(pstate,
675 PLANE_PROP_PREFILL_SIZE);
676 cfg.time = sde_plane_get_property(pstate,
677 PLANE_PROP_PREFILL_TIME);
678
679 SDE_DEBUG("plane%d size:%llu time:%llu\n",
680 plane->base.id, cfg.size, cfg.time);
Dhaval Patela5f75952017-07-25 11:17:41 -0700681 SDE_EVT32_VERBOSE(DRMID(plane), cfg.size, cfg.time);
Alan Kwong2349d742017-04-20 08:27:30 -0700682 psde->pipe_hw->ops.setup_ts_prefill(psde->pipe_hw, &cfg,
683 pstate->multirect_index);
684}
685
Clarence Ipcae1bb62016-07-07 12:07:13 -0400686/* helper to update a state's input fence pointer from the property */
Clarence Ip13a8cf42016-09-29 17:27:47 -0400687static void _sde_plane_set_input_fence(struct sde_plane *psde,
Clarence Ipae4e60c2016-06-26 22:44:04 -0400688 struct sde_plane_state *pstate, uint64_t fd)
689{
Clarence Ip13a8cf42016-09-29 17:27:47 -0400690 if (!psde || !pstate) {
691 SDE_ERROR("invalid arg(s), plane %d state %d\n",
692 psde != 0, pstate != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400693 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400694 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400695
696 /* clear previous reference */
Clarence Ipcae1bb62016-07-07 12:07:13 -0400697 if (pstate->input_fence)
698 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400699
700 /* get fence pointer for later */
Lloyd Atkinsone08229c2017-10-02 17:53:30 -0400701 if (fd == 0)
702 pstate->input_fence = NULL;
703 else
704 pstate->input_fence = sde_sync_get(fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400705
Clarence Ip13a8cf42016-09-29 17:27:47 -0400706 SDE_DEBUG_PLANE(psde, "0x%llX\n", fd);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400707}
708
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -0700709/**
710 * _sde_plane_inline_rot_set_ot_limit - set OT limit for the given inline
711 * rotation xin client
712 * @plane: pointer to drm plane
713 * @crtc: pointer to drm crtc
714 * @cfg: pointer to rotator vbif config
715 * @rect_w: rotator frame width
716 * @rect_h: rotator frame height
717 */
718static void _sde_plane_inline_rot_set_ot_limit(struct drm_plane *plane,
719 struct drm_crtc *crtc, const struct sde_rot_vbif_cfg *cfg,
720 u32 rect_w, u32 rect_h)
721{
722 struct sde_vbif_set_ot_params ot_params;
723 struct msm_drm_private *priv;
724 struct sde_kms *sde_kms;
725
726 if (!plane || !plane->dev) {
727 SDE_ERROR("invalid arguments\n");
728 return;
729 }
730
731 priv = plane->dev->dev_private;
732 if (!priv || !priv->kms) {
733 SDE_ERROR("invalid KMS reference\n");
734 return;
735 }
736
737 sde_kms = to_sde_kms(priv->kms);
738
739 memset(&ot_params, 0, sizeof(ot_params));
740 ot_params.xin_id = cfg->xin_id;
741 ot_params.num = cfg->num;
742 ot_params.width = rect_w;
743 ot_params.height = rect_h;
744 ot_params.is_wfd = false;
745 ot_params.frame_rate = crtc->mode.vrefresh;
746 ot_params.vbif_idx = VBIF_RT;
747 ot_params.clk_ctrl = cfg->clk_ctrl;
748 ot_params.rd = cfg->is_read;
749
750 sde_vbif_set_ot_limit(sde_kms, &ot_params);
751}
752
753/**
754 * _sde_plane_inline_rot_set_qos_remap - set vbif QoS for the given inline
755 * rotation xin client
756 * @plane: Pointer to drm plane
757 * @cfg: Pointer to rotator vbif cfg
758 */
759static void _sde_plane_inline_rot_set_qos_remap(struct drm_plane *plane,
760 const struct sde_rot_vbif_cfg *cfg)
761{
762 struct sde_vbif_set_qos_params qos_params;
763 struct msm_drm_private *priv;
764 struct sde_kms *sde_kms;
765
766 if (!plane || !plane->dev) {
767 SDE_ERROR("invalid arguments\n");
768 return;
769 }
770
771 priv = plane->dev->dev_private;
772 if (!priv || !priv->kms) {
773 SDE_ERROR("invalid KMS reference\n");
774 return;
775 }
776
777 sde_kms = to_sde_kms(priv->kms);
778
779 memset(&qos_params, 0, sizeof(qos_params));
780 qos_params.vbif_idx = VBIF_RT;
781 qos_params.xin_id = cfg->xin_id;
782 qos_params.clk_ctrl = cfg->clk_ctrl;
783 qos_params.num = cfg->num;
784 qos_params.is_rt = true;
785
786 SDE_DEBUG("vbif:%d xin:%d num:%d rt:%d clk_ctrl:%d\n",
787 qos_params.vbif_idx, qos_params.xin_id,
788 qos_params.num, qos_params.is_rt, qos_params.clk_ctrl);
789
790 sde_vbif_set_qos_remap(sde_kms, &qos_params);
791}
792
Clarence Ipcae1bb62016-07-07 12:07:13 -0400793int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
Clarence Ipae4e60c2016-06-26 22:44:04 -0400794{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400795 struct sde_plane *psde;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400796 struct sde_plane_state *pstate;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400797 uint32_t prefix;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400798 void *input_fence;
Clarence Ipcb410d42016-06-26 22:52:33 -0400799 int ret = -EINVAL;
Dhaval Patel39323d42017-03-01 23:48:24 -0800800 signed long rc;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400801
802 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -0700803 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400804 } else if (!plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -0400805 SDE_ERROR_PLANE(to_sde_plane(plane), "invalid state\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -0400806 } else {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400807 psde = to_sde_plane(plane);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400808 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400809 input_fence = pstate->input_fence;
Clarence Ipae4e60c2016-06-26 22:44:04 -0400810
Clarence Ipcae1bb62016-07-07 12:07:13 -0400811 if (input_fence) {
Dhaval Patel39323d42017-03-01 23:48:24 -0800812 psde->is_error = false;
Clarence Ip78a04ed2016-10-04 15:57:45 -0400813 prefix = sde_sync_get_name_prefix(input_fence);
Dhaval Patel39323d42017-03-01 23:48:24 -0800814 rc = sde_sync_wait(input_fence, wait_ms);
Clarence Ip78a04ed2016-10-04 15:57:45 -0400815
Dhaval Patel39323d42017-03-01 23:48:24 -0800816 switch (rc) {
Clarence Ipcae1bb62016-07-07 12:07:13 -0400817 case 0:
Clarence Ip78a04ed2016-10-04 15:57:45 -0400818 SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
819 wait_ms, prefix);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400820 psde->is_error = true;
Dhaval Patel2a3c37a2017-10-25 12:30:36 -0700821 sde_kms_timeline_status(plane->dev);
Dhaval Patel39323d42017-03-01 23:48:24 -0800822 ret = -ETIMEDOUT;
823 break;
824 case -ERESTARTSYS:
825 SDE_ERROR_PLANE(psde,
826 "%ums wait interrupted on %08X\n",
827 wait_ms, prefix);
828 psde->is_error = true;
829 ret = -ERESTARTSYS;
830 break;
831 case -EINVAL:
832 SDE_ERROR_PLANE(psde,
833 "invalid fence param for %08X\n",
834 prefix);
835 psde->is_error = true;
836 ret = -EINVAL;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400837 break;
838 default:
Dhaval Patel39323d42017-03-01 23:48:24 -0800839 SDE_DEBUG_PLANE(psde, "signaled\n");
840 ret = 0;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400841 break;
842 }
Dhaval Patel6c666622017-03-21 23:02:59 -0700843
844 SDE_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
Clarence Ipcb410d42016-06-26 22:52:33 -0400845 } else {
846 ret = 0;
847 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400848 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400849 return ret;
850}
851
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700852/**
853 * _sde_plane_get_aspace: gets the address space based on the
854 * fb_translation mode property
855 */
856static int _sde_plane_get_aspace(
857 struct sde_plane *psde,
858 struct sde_plane_state *pstate,
859 struct msm_gem_address_space **aspace)
860{
861 struct sde_kms *kms;
862 int mode;
863
864 if (!psde || !pstate || !aspace) {
865 SDE_ERROR("invalid parameters\n");
866 return -EINVAL;
867 }
868
869 kms = _sde_plane_get_kms(&psde->base);
870 if (!kms) {
871 SDE_ERROR("invalid kms\n");
872 return -EINVAL;
873 }
874
875 mode = sde_plane_get_property(pstate,
876 PLANE_PROP_FB_TRANSLATION_MODE);
877
878 switch (mode) {
879 case SDE_DRM_FB_NON_SEC:
880 *aspace = kms->aspace[MSM_SMMU_DOMAIN_UNSECURE];
881 if (!aspace)
882 return -EINVAL;
883 break;
884 case SDE_DRM_FB_SEC:
885 *aspace = kms->aspace[MSM_SMMU_DOMAIN_SECURE];
886 if (!aspace)
887 return -EINVAL;
888 break;
889 case SDE_DRM_FB_SEC_DIR_TRANS:
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700890 *aspace = NULL;
891 break;
892 default:
893 SDE_ERROR("invalid fb_translation mode:%d\n", mode);
894 return -EFAULT;
895 }
896
897 return 0;
898}
899
Clarence Ip282dad62016-09-27 17:07:35 -0400900static inline void _sde_plane_set_scanout(struct drm_plane *plane,
Clarence Ip5e2a9222016-06-26 22:38:24 -0400901 struct sde_plane_state *pstate,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400902 struct sde_hw_pipe_cfg *pipe_cfg,
903 struct drm_framebuffer *fb)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400904{
Clarence Ipae4e60c2016-06-26 22:44:04 -0400905 struct sde_plane *psde;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700906 struct msm_gem_address_space *aspace = NULL;
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700907 int ret, mode;
908 bool secure = false;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400909
Clarence Ip13a8cf42016-09-29 17:27:47 -0400910 if (!plane || !pstate || !pipe_cfg || !fb) {
911 SDE_ERROR(
912 "invalid arg(s), plane %d state %d cfg %d fb %d\n",
913 plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -0400914 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -0400915 }
Clarence Ipae4e60c2016-06-26 22:44:04 -0400916
917 psde = to_sde_plane(plane);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400918 if (!psde->pipe_hw) {
919 SDE_ERROR_PLANE(psde, "invalid pipe_hw\n");
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400920 return;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400921 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400922
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700923 ret = _sde_plane_get_aspace(psde, pstate, &aspace);
924 if (ret) {
925 SDE_ERROR_PLANE(psde, "Failed to get aspace %d\n", ret);
926 return;
927 }
928
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -0700929 /*
930 * framebuffer prepare is deferred for prepare_fb calls that
931 * happen during the transition from secure to non-secure.
932 * Handle the prepare at this point for such cases. This can be
933 * expected for one or two frames during the transition.
934 */
935 if (aspace && pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700936 SDE_EVT32(DRMID(plane), psde->pipe, aspace->domain_attached);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -0700937 ret = msm_framebuffer_prepare(fb, pstate->aspace);
938 if (ret) {
939 SDE_ERROR_PLANE(psde,
940 "failed to prepare framebuffer %d\n", ret);
941 return;
942 }
943 pstate->defer_prepare_fb = false;
944 }
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700945 mode = sde_plane_get_property(pstate, PLANE_PROP_FB_TRANSLATION_MODE);
946 if ((mode == SDE_DRM_FB_SEC) || (mode == SDE_DRM_FB_SEC_DIR_TRANS))
947 secure = true;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -0700948
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -0700949 ret = sde_format_populate_layout(aspace, fb, &pipe_cfg->layout);
Clarence Ipb6eb2362016-09-08 16:18:13 -0400950 if (ret == -EAGAIN)
951 SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
952 else if (ret)
953 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
Alan Kwongc16e0922017-05-11 14:50:46 -0700954 else if (psde->pipe_hw->ops.setup_sourceaddress) {
Dhaval Patela5f75952017-07-25 11:17:41 -0700955 SDE_EVT32_VERBOSE(psde->pipe_hw->idx,
Alan Kwongc16e0922017-05-11 14:50:46 -0700956 pipe_cfg->layout.width,
957 pipe_cfg->layout.height,
958 pipe_cfg->layout.plane_addr[0],
959 pipe_cfg->layout.plane_size[0],
960 pipe_cfg->layout.plane_addr[1],
961 pipe_cfg->layout.plane_size[1],
962 pipe_cfg->layout.plane_addr[2],
963 pipe_cfg->layout.plane_size[2],
964 pipe_cfg->layout.plane_addr[3],
965 pipe_cfg->layout.plane_size[3],
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -0700966 pstate->multirect_index,
967 secure);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800968 psde->pipe_hw->ops.setup_sourceaddress(psde->pipe_hw, pipe_cfg,
969 pstate->multirect_index);
Alan Kwongc16e0922017-05-11 14:50:46 -0700970 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400971}
972
abeykun48f407a2016-08-25 12:06:44 -0400973static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde,
974 struct sde_plane_state *pstate)
975{
Clarence Ip3bf8d872017-02-16 15:25:38 -0500976 struct sde_hw_scaler3_cfg *cfg;
abeykun48f407a2016-08-25 12:06:44 -0400977 int ret = 0;
978
Clarence Ip172033f2017-06-13 10:52:56 -0400979 if (!psde || !pstate) {
Clarence Ip3bf8d872017-02-16 15:25:38 -0500980 SDE_ERROR("invalid args\n");
981 return -EINVAL;
Clarence Ip3bf8d872017-02-16 15:25:38 -0500982 }
983
Clarence Ip172033f2017-06-13 10:52:56 -0400984 cfg = &pstate->scaler3_cfg;
Clarence Ip3bf8d872017-02-16 15:25:38 -0500985
abeykun48f407a2016-08-25 12:06:44 -0400986 cfg->dir_lut = msm_property_get_blob(
987 &psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -0400988 &pstate->property_state, &cfg->dir_len,
abeykun48f407a2016-08-25 12:06:44 -0400989 PLANE_PROP_SCALER_LUT_ED);
990 cfg->cir_lut = msm_property_get_blob(
991 &psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -0400992 &pstate->property_state, &cfg->cir_len,
abeykun48f407a2016-08-25 12:06:44 -0400993 PLANE_PROP_SCALER_LUT_CIR);
994 cfg->sep_lut = msm_property_get_blob(
995 &psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -0400996 &pstate->property_state, &cfg->sep_len,
abeykun48f407a2016-08-25 12:06:44 -0400997 PLANE_PROP_SCALER_LUT_SEP);
998 if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
999 ret = -ENODATA;
1000 return ret;
1001}
1002
Clarence Ipcb410d42016-06-26 22:52:33 -04001003static void _sde_plane_setup_scaler3(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -04001004 struct sde_plane_state *pstate,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001005 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
1006 struct sde_hw_scaler3_cfg *scale_cfg,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001007 const struct sde_format *fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001008 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v)
1009{
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001010 uint32_t decimated, i;
1011
Clarence Ip172033f2017-06-13 10:52:56 -04001012 if (!psde || !pstate || !scale_cfg || !fmt || !chroma_subsmpl_h ||
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001013 !chroma_subsmpl_v) {
Clarence Ip172033f2017-06-13 10:52:56 -04001014 SDE_ERROR(
1015 "psde %d pstate %d scale_cfg %d fmt %d smp_h %d smp_v %d\n",
1016 !!psde, !!pstate, !!scale_cfg, !!fmt, chroma_subsmpl_h,
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001017 chroma_subsmpl_v);
1018 return;
1019 }
1020
1021 memset(scale_cfg, 0, sizeof(*scale_cfg));
Clarence Ip172033f2017-06-13 10:52:56 -04001022 memset(&pstate->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001023
1024 decimated = DECIMATED_DIMENSION(src_w,
1025 psde->pipe_cfg.horz_decimation);
1026 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] =
1027 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w);
1028 decimated = DECIMATED_DIMENSION(src_h,
1029 psde->pipe_cfg.vert_decimation);
1030 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] =
1031 mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h);
1032
1033
1034 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] =
1035 scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v;
1036 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] =
1037 scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h;
1038
1039 scale_cfg->phase_step_x[SDE_SSPP_COMP_2] =
1040 scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2];
1041 scale_cfg->phase_step_y[SDE_SSPP_COMP_2] =
1042 scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2];
1043
1044 scale_cfg->phase_step_x[SDE_SSPP_COMP_3] =
1045 scale_cfg->phase_step_x[SDE_SSPP_COMP_0];
1046 scale_cfg->phase_step_y[SDE_SSPP_COMP_3] =
1047 scale_cfg->phase_step_y[SDE_SSPP_COMP_0];
1048
1049 for (i = 0; i < SDE_MAX_PLANES; i++) {
1050 scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w,
1051 psde->pipe_cfg.horz_decimation);
1052 scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h,
1053 psde->pipe_cfg.vert_decimation);
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001054 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) {
1055 scale_cfg->src_width[i] /= chroma_subsmpl_h;
1056 scale_cfg->src_height[i] /= chroma_subsmpl_v;
1057 }
1058 scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
1059 scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
Clarence Ip172033f2017-06-13 10:52:56 -04001060 pstate->pixel_ext.num_ext_pxls_top[i] =
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001061 scale_cfg->src_height[i];
Clarence Ip172033f2017-06-13 10:52:56 -04001062 pstate->pixel_ext.num_ext_pxls_left[i] =
Gopikrishnaiah Anandanf4c34292016-10-20 15:42:04 -07001063 scale_cfg->src_width[i];
1064 }
1065 if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
1066 && (src_w == dst_w))
1067 return;
1068
1069 scale_cfg->dst_width = dst_w;
1070 scale_cfg->dst_height = dst_h;
1071 scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
1072 scale_cfg->uv_filter_cfg = SDE_SCALE_BIL;
1073 scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL;
1074 scale_cfg->lut_flag = 0;
1075 scale_cfg->blend_cfg = 1;
1076 scale_cfg->enable = 1;
Clarence Ip5e2a9222016-06-26 22:38:24 -04001077}
1078
Clarence Ipcb410d42016-06-26 22:52:33 -04001079/**
Clarence Ip13a8cf42016-09-29 17:27:47 -04001080 * _sde_plane_setup_scaler2 - determine default scaler phase steps/filter type
Clarence Ipcb410d42016-06-26 22:52:33 -04001081 * @psde: Pointer to SDE plane object
1082 * @src: Source size
1083 * @dst: Destination size
1084 * @phase_steps: Pointer to output array for phase steps
1085 * @filter: Pointer to output array for filter type
1086 * @fmt: Pointer to format definition
1087 * @chroma_subsampling: Subsampling amount for chroma channel
1088 *
1089 * Returns: 0 on success
1090 */
1091static int _sde_plane_setup_scaler2(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001092 uint32_t src, uint32_t dst, uint32_t *phase_steps,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001093 enum sde_hw_filter *filter, const struct sde_format *fmt,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001094 uint32_t chroma_subsampling)
1095{
Clarence Ipcb410d42016-06-26 22:52:33 -04001096 if (!psde || !phase_steps || !filter || !fmt) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001097 SDE_ERROR(
1098 "invalid arg(s), plane %d phase %d filter %d fmt %d\n",
1099 psde != 0, phase_steps != 0, filter != 0, fmt != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001100 return -EINVAL;
1101 }
1102
Clarence Ip4c1d9772016-06-26 09:35:38 -04001103 /* calculate phase steps, leave init phase as zero */
Clarence Ipe78efb72016-06-24 18:35:21 -04001104 phase_steps[SDE_SSPP_COMP_0] =
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001105 mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
Clarence Ipe78efb72016-06-24 18:35:21 -04001106 phase_steps[SDE_SSPP_COMP_1_2] =
1107 phase_steps[SDE_SSPP_COMP_0] / chroma_subsampling;
1108 phase_steps[SDE_SSPP_COMP_2] = phase_steps[SDE_SSPP_COMP_1_2];
1109 phase_steps[SDE_SSPP_COMP_3] = phase_steps[SDE_SSPP_COMP_0];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001110
1111 /* calculate scaler config, if necessary */
Clarence Ipdbde9832016-06-26 09:48:36 -04001112 if (SDE_FORMAT_IS_YUV(fmt) || src != dst) {
Clarence Ipe78efb72016-06-24 18:35:21 -04001113 filter[SDE_SSPP_COMP_3] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001114 (src <= dst) ? SDE_SCALE_FILTER_BIL :
1115 SDE_SCALE_FILTER_PCMN;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001116
Clarence Ipdbde9832016-06-26 09:48:36 -04001117 if (SDE_FORMAT_IS_YUV(fmt)) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001118 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_CA;
Clarence Ipe78efb72016-06-24 18:35:21 -04001119 filter[SDE_SSPP_COMP_1_2] = filter[SDE_SSPP_COMP_3];
1120 } else {
1121 filter[SDE_SSPP_COMP_0] = filter[SDE_SSPP_COMP_3];
1122 filter[SDE_SSPP_COMP_1_2] =
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001123 SDE_SCALE_FILTER_NEAREST;
Clarence Ipe78efb72016-06-24 18:35:21 -04001124 }
1125 } else {
1126 /* disable scaler */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001127 filter[SDE_SSPP_COMP_0] = SDE_SCALE_FILTER_MAX;
1128 filter[SDE_SSPP_COMP_1_2] = SDE_SCALE_FILTER_MAX;
1129 filter[SDE_SSPP_COMP_3] = SDE_SCALE_FILTER_MAX;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001130 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001131 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001132}
1133
Clarence Ipcb410d42016-06-26 22:52:33 -04001134/**
1135 * _sde_plane_setup_pixel_ext - determine default pixel extension values
1136 * @psde: Pointer to SDE plane object
1137 * @src: Source size
1138 * @dst: Destination size
1139 * @decimated_src: Source size after decimation, if any
1140 * @phase_steps: Pointer to output array for phase steps
1141 * @out_src: Output array for pixel extension values
1142 * @out_edge1: Output array for pixel extension first edge
1143 * @out_edge2: Output array for pixel extension second edge
1144 * @filter: Pointer to array for filter type
1145 * @fmt: Pointer to format definition
1146 * @chroma_subsampling: Subsampling amount for chroma channel
1147 * @post_compare: Whether to chroma subsampled source size for comparisions
1148 */
1149static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001150 uint32_t src, uint32_t dst, uint32_t decimated_src,
1151 uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
Clarence Ipe78efb72016-06-24 18:35:21 -04001152 int *out_edge2, enum sde_hw_filter *filter,
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001153 const struct sde_format *fmt, uint32_t chroma_subsampling,
Clarence Ipe78efb72016-06-24 18:35:21 -04001154 bool post_compare)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001155{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001156 int64_t edge1, edge2, caf;
1157 uint32_t src_work;
1158 int i, tmp;
1159
Clarence Ipcb410d42016-06-26 22:52:33 -04001160 if (psde && phase_steps && out_src && out_edge1 &&
Clarence Ipe78efb72016-06-24 18:35:21 -04001161 out_edge2 && filter && fmt) {
1162 /* handle CAF for YUV formats */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001163 if (SDE_FORMAT_IS_YUV(fmt) && *filter == SDE_SCALE_FILTER_CA)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001164 caf = PHASE_STEP_UNIT_SCALE;
1165 else
1166 caf = 0;
1167
1168 for (i = 0; i < SDE_MAX_PLANES; i++) {
1169 src_work = decimated_src;
Clarence Ipe78efb72016-06-24 18:35:21 -04001170 if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001171 src_work /= chroma_subsampling;
1172 if (post_compare)
1173 src = src_work;
Clarence Ipdbde9832016-06-26 09:48:36 -04001174 if (!SDE_FORMAT_IS_YUV(fmt) && (src == dst)) {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001175 /* unity */
1176 edge1 = 0;
1177 edge2 = 0;
1178 } else if (dst >= src) {
1179 /* upscale */
1180 edge1 = (1 << PHASE_RESIDUAL);
1181 edge1 -= caf;
1182 edge2 = (1 << PHASE_RESIDUAL);
1183 edge2 += (dst - 1) * *(phase_steps + i);
1184 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1185 edge2 += caf;
1186 edge2 = -(edge2);
1187 } else {
1188 /* downscale */
1189 edge1 = 0;
1190 edge2 = (dst - 1) * *(phase_steps + i);
1191 edge2 -= (src_work - 1) * PHASE_STEP_UNIT_SCALE;
1192 edge2 += *(phase_steps + i);
1193 edge2 = -(edge2);
1194 }
1195
1196 /* only enable CAF for luma plane */
1197 caf = 0;
1198
1199 /* populate output arrays */
1200 *(out_src + i) = src_work;
1201
1202 /* edge updates taken from __pxl_extn_helper */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001203 if (edge1 >= 0) {
1204 tmp = (uint32_t)edge1;
1205 tmp >>= PHASE_STEP_SHIFT;
1206 *(out_edge1 + i) = -tmp;
1207 } else {
1208 tmp = (uint32_t)(-edge1);
Clarence Ipe78efb72016-06-24 18:35:21 -04001209 *(out_edge1 + i) =
1210 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1211 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001212 }
1213 if (edge2 >= 0) {
1214 tmp = (uint32_t)edge2;
1215 tmp >>= PHASE_STEP_SHIFT;
1216 *(out_edge2 + i) = -tmp;
1217 } else {
1218 tmp = (uint32_t)(-edge2);
Clarence Ipe78efb72016-06-24 18:35:21 -04001219 *(out_edge2 + i) =
1220 (tmp + PHASE_STEP_UNIT_SCALE - 1) >>
1221 PHASE_STEP_SHIFT;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001222 }
1223 }
1224 }
1225}
1226
Clarence Ip5fc00c52016-09-23 15:03:34 -04001227static inline void _sde_plane_setup_csc(struct sde_plane *psde)
Clarence Ipe78efb72016-06-24 18:35:21 -04001228{
1229 static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
1230 {
Clarence Ip373f8592016-05-26 00:58:42 -04001231 /* S15.16 format */
1232 0x00012A00, 0x00000000, 0x00019880,
1233 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1234 0x00012A00, 0x00020480, 0x00000000,
Clarence Ipe78efb72016-06-24 18:35:21 -04001235 },
Clarence Ip373f8592016-05-26 00:58:42 -04001236 /* signed bias */
Clarence Ipe78efb72016-06-24 18:35:21 -04001237 { 0xfff0, 0xff80, 0xff80,},
1238 { 0x0, 0x0, 0x0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001239 /* unsigned clamp */
Clarence Ipe78efb72016-06-24 18:35:21 -04001240 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
Clarence Ip373f8592016-05-26 00:58:42 -04001241 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
Clarence Ipe78efb72016-06-24 18:35:21 -04001242 };
abeykun1c312f62016-08-26 09:47:12 -04001243 static const struct sde_csc_cfg sde_csc10_YUV2RGB_601L = {
1244 {
1245 /* S15.16 format */
1246 0x00012A00, 0x00000000, 0x00019880,
1247 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
1248 0x00012A00, 0x00020480, 0x00000000,
1249 },
1250 /* signed bias */
1251 { 0xffc0, 0xfe00, 0xfe00,},
1252 { 0x0, 0x0, 0x0,},
1253 /* unsigned clamp */
1254 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
1255 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
1256 };
Clarence Ipe78efb72016-06-24 18:35:21 -04001257
Clarence Ip5fc00c52016-09-23 15:03:34 -04001258 if (!psde) {
1259 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04001260 return;
1261 }
Clarence Ip5e2a9222016-06-26 22:38:24 -04001262
Clarence Ipcae1bb62016-07-07 12:07:13 -04001263 /* revert to kernel default if override not available */
Clarence Ip5fc00c52016-09-23 15:03:34 -04001264 if (psde->csc_usr_ptr)
1265 psde->csc_ptr = psde->csc_usr_ptr;
abeykun1c312f62016-08-26 09:47:12 -04001266 else if (BIT(SDE_SSPP_CSC_10BIT) & psde->features)
1267 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc10_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001268 else
Clarence Ip373f8592016-05-26 00:58:42 -04001269 psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
Clarence Ip5fc00c52016-09-23 15:03:34 -04001270
Clarence Ip13a8cf42016-09-29 17:27:47 -04001271 SDE_DEBUG_PLANE(psde, "using 0x%X 0x%X 0x%X...\n",
Clarence Ip5fc00c52016-09-23 15:03:34 -04001272 psde->csc_ptr->csc_mv[0],
1273 psde->csc_ptr->csc_mv[1],
1274 psde->csc_ptr->csc_mv[2]);
Clarence Ipe78efb72016-06-24 18:35:21 -04001275}
1276
Benet Clarkeb1b4462016-06-27 14:43:06 -07001277static void sde_color_process_plane_setup(struct drm_plane *plane)
1278{
1279 struct sde_plane *psde;
1280 struct sde_plane_state *pstate;
1281 uint32_t hue, saturation, value, contrast;
Benet Clarkd009b1d2016-06-27 14:45:59 -07001282 struct drm_msm_memcol *memcol = NULL;
1283 size_t memcol_sz = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07001284
1285 psde = to_sde_plane(plane);
1286 pstate = to_sde_plane_state(plane->state);
1287
1288 hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
1289 if (psde->pipe_hw->ops.setup_pa_hue)
1290 psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
1291 saturation = (uint32_t) sde_plane_get_property(pstate,
1292 PLANE_PROP_SATURATION_ADJUST);
1293 if (psde->pipe_hw->ops.setup_pa_sat)
1294 psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
1295 value = (uint32_t) sde_plane_get_property(pstate,
1296 PLANE_PROP_VALUE_ADJUST);
1297 if (psde->pipe_hw->ops.setup_pa_val)
1298 psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
1299 contrast = (uint32_t) sde_plane_get_property(pstate,
1300 PLANE_PROP_CONTRAST_ADJUST);
1301 if (psde->pipe_hw->ops.setup_pa_cont)
1302 psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
Benet Clarkeb1b4462016-06-27 14:43:06 -07001303
Benet Clarkd009b1d2016-06-27 14:45:59 -07001304 if (psde->pipe_hw->ops.setup_pa_memcolor) {
1305 /* Skin memory color setup */
1306 memcol = msm_property_get_blob(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001307 &pstate->property_state,
Benet Clarkd009b1d2016-06-27 14:45:59 -07001308 &memcol_sz,
1309 PLANE_PROP_SKIN_COLOR);
1310 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1311 MEMCOLOR_SKIN, memcol);
1312
1313 /* Sky memory color setup */
1314 memcol = msm_property_get_blob(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001315 &pstate->property_state,
Benet Clarkd009b1d2016-06-27 14:45:59 -07001316 &memcol_sz,
1317 PLANE_PROP_SKY_COLOR);
1318 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1319 MEMCOLOR_SKY, memcol);
1320
1321 /* Foliage memory color setup */
1322 memcol = msm_property_get_blob(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04001323 &pstate->property_state,
Benet Clarkd009b1d2016-06-27 14:45:59 -07001324 &memcol_sz,
1325 PLANE_PROP_FOLIAGE_COLOR);
1326 psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
1327 MEMCOLOR_FOLIAGE, memcol);
1328 }
1329}
Benet Clarkeb1b4462016-06-27 14:43:06 -07001330
Clarence Ipcb410d42016-06-26 22:52:33 -04001331static void _sde_plane_setup_scaler(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -04001332 struct sde_plane_state *pstate,
1333 const struct sde_format *fmt, bool color_fill)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001334{
Clarence Ipb43d4592016-09-08 14:21:35 -04001335 struct sde_hw_pixel_ext *pe;
Clarence Ipcb410d42016-06-26 22:52:33 -04001336 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001337
Clarence Ip172033f2017-06-13 10:52:56 -04001338 if (!psde || !fmt || !pstate) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001339 SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
1340 psde != 0, fmt != 0, pstate != 0);
Clarence Ipcb410d42016-06-26 22:52:33 -04001341 return;
Clarence Ipb43d4592016-09-08 14:21:35 -04001342 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001343
Clarence Ip172033f2017-06-13 10:52:56 -04001344 pe = &pstate->pixel_ext;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001345
Clarence Ipdedbba92016-09-27 17:43:10 -04001346 psde->pipe_cfg.horz_decimation =
1347 sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
1348 psde->pipe_cfg.vert_decimation =
1349 sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001350
1351 /* don't chroma subsample if decimating */
1352 chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001353 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001354 chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001355 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
Clarence Ip04ec67d2016-05-26 01:16:15 -04001356
Clarence Ip5e2a9222016-06-26 22:38:24 -04001357 /* update scaler */
1358 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ip172033f2017-06-13 10:52:56 -04001359 int rc;
abeykun48f407a2016-08-25 12:06:44 -04001360
Clarence Ip172033f2017-06-13 10:52:56 -04001361 if (!color_fill && !psde->debugfs_default_scale)
1362 rc = _sde_plane_setup_scaler3_lut(psde, pstate);
1363 else
1364 rc = -EINVAL;
1365 if (rc || pstate->scaler_check_state !=
1366 SDE_PLANE_SCLCHECK_SCALER_V2) {
Clarence Ipb43d4592016-09-08 14:21:35 -04001367 /* calculate default config for QSEED3 */
Clarence Ip172033f2017-06-13 10:52:56 -04001368 _sde_plane_setup_scaler3(psde, pstate,
Clarence Ipcb410d42016-06-26 22:52:33 -04001369 psde->pipe_cfg.src_rect.w,
1370 psde->pipe_cfg.src_rect.h,
1371 psde->pipe_cfg.dst_rect.w,
1372 psde->pipe_cfg.dst_rect.h,
Clarence Ip172033f2017-06-13 10:52:56 -04001373 &pstate->scaler3_cfg, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001374 chroma_subsmpl_h, chroma_subsmpl_v);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001375 }
Clarence Ip172033f2017-06-13 10:52:56 -04001376 } else if (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 ||
1377 color_fill || psde->debugfs_default_scale) {
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001378 uint32_t deci_dim, i;
1379
Clarence Ipb43d4592016-09-08 14:21:35 -04001380 /* calculate default configuration for QSEED2 */
1381 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001382
Clarence Ip13a8cf42016-09-29 17:27:47 -04001383 SDE_DEBUG_PLANE(psde, "default config\n");
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001384 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
1385 psde->pipe_cfg.horz_decimation);
Clarence Ipb43d4592016-09-08 14:21:35 -04001386 _sde_plane_setup_scaler2(psde,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001387 deci_dim,
Clarence Ipb43d4592016-09-08 14:21:35 -04001388 psde->pipe_cfg.dst_rect.w,
1389 pe->phase_step_x,
1390 pe->horz_filter, fmt, chroma_subsmpl_h);
Clarence Ip5e2a9222016-06-26 22:38:24 -04001391
Clarence Ipdbde9832016-06-26 09:48:36 -04001392 if (SDE_FORMAT_IS_YUV(fmt))
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001393 deci_dim &= ~0x1;
Clarence Ipcb410d42016-06-26 22:52:33 -04001394 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001395 psde->pipe_cfg.dst_rect.w, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001396 pe->phase_step_x,
1397 pe->roi_w,
1398 pe->num_ext_pxls_left,
Clarence Ipe78efb72016-06-24 18:35:21 -04001399 pe->num_ext_pxls_right, pe->horz_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001400 chroma_subsmpl_h, 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001401
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001402 deci_dim = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001403 psde->pipe_cfg.vert_decimation);
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001404 _sde_plane_setup_scaler2(psde,
1405 deci_dim,
1406 psde->pipe_cfg.dst_rect.h,
1407 pe->phase_step_y,
1408 pe->vert_filter, fmt, chroma_subsmpl_v);
Clarence Ipcb410d42016-06-26 22:52:33 -04001409 _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
Lloyd Atkinsoncd43ca62016-11-29 14:13:11 -05001410 psde->pipe_cfg.dst_rect.h, deci_dim,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001411 pe->phase_step_y,
1412 pe->roi_h,
1413 pe->num_ext_pxls_top,
Clarence Ipe78efb72016-06-24 18:35:21 -04001414 pe->num_ext_pxls_btm, pe->vert_filter, fmt,
Clarence Ip5e2a9222016-06-26 22:38:24 -04001415 chroma_subsmpl_v, 1);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001416
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001417 for (i = 0; i < SDE_MAX_PLANES; i++) {
1418 if (pe->num_ext_pxls_left[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001419 pe->left_rpt[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001420 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001421 pe->left_ftch[i] = pe->num_ext_pxls_left[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001422
1423 if (pe->num_ext_pxls_right[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001424 pe->right_rpt[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001425 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001426 pe->right_ftch[i] = pe->num_ext_pxls_right[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001427
1428 if (pe->num_ext_pxls_top[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001429 pe->top_rpt[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001430 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001431 pe->top_ftch[i] = pe->num_ext_pxls_top[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001432
1433 if (pe->num_ext_pxls_btm[i] >= 0)
Clarence Ipb43d4592016-09-08 14:21:35 -04001434 pe->btm_rpt[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001435 else
Clarence Ipb43d4592016-09-08 14:21:35 -04001436 pe->btm_ftch[i] = pe->num_ext_pxls_btm[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001437 }
1438 }
Clarence Ipcb410d42016-06-26 22:52:33 -04001439}
1440
Clarence Ipcae1bb62016-07-07 12:07:13 -04001441/**
1442 * _sde_plane_color_fill - enables color fill on plane
Clarence Ip13a8cf42016-09-29 17:27:47 -04001443 * @psde: Pointer to SDE plane object
Clarence Ipcae1bb62016-07-07 12:07:13 -04001444 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
1445 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
1446 * Returns: 0 on success
1447 */
Clarence Ip13a8cf42016-09-29 17:27:47 -04001448static int _sde_plane_color_fill(struct sde_plane *psde,
Clarence Ipcb410d42016-06-26 22:52:33 -04001449 uint32_t color, uint32_t alpha)
1450{
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001451 const struct sde_format *fmt;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001452 const struct drm_plane *plane;
Clarence Ip172033f2017-06-13 10:52:56 -04001453 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04001454
Clarence Ip172033f2017-06-13 10:52:56 -04001455 if (!psde || !psde->base.state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001456 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001457 return -EINVAL;
1458 }
1459
Clarence Ipcb410d42016-06-26 22:52:33 -04001460 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001461 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001462 return -EINVAL;
1463 }
1464
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001465 plane = &psde->base;
1466 pstate = to_sde_plane_state(plane->state);
1467
Clarence Ip13a8cf42016-09-29 17:27:47 -04001468 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001469
Clarence Ipcb410d42016-06-26 22:52:33 -04001470 /*
1471 * select fill format to match user property expectation,
1472 * h/w only supports RGB variants
1473 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001474 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001475
1476 /* update sspp */
1477 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1478 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001479 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1480 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001481
1482 /* override scaler/decimation if solid fill */
1483 psde->pipe_cfg.src_rect.x = 0;
1484 psde->pipe_cfg.src_rect.y = 0;
1485 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1486 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Clarence Ip172033f2017-06-13 10:52:56 -04001487 _sde_plane_setup_scaler(psde, pstate, fmt, true);
Clarence Ipcb410d42016-06-26 22:52:33 -04001488
Clarence Ipcb410d42016-06-26 22:52:33 -04001489 if (psde->pipe_hw->ops.setup_format)
1490 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001491 fmt, SDE_SSPP_SOLID_FILL,
1492 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001493
1494 if (psde->pipe_hw->ops.setup_rects)
1495 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001496 &psde->pipe_cfg,
1497 pstate->multirect_index);
1498
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001499 if (psde->pipe_hw->ops.setup_pe)
1500 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04001501 &pstate->pixel_ext);
Dhaval Patel2bbe8702017-08-30 21:22:52 -07001502
1503 if (psde->pipe_hw->ops.setup_scaler &&
1504 pstate->multirect_index != SDE_SSPP_RECT_1)
1505 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
1506 &psde->pipe_cfg, &pstate->pixel_ext,
1507 &pstate->scaler3_cfg);
Clarence Ipcb410d42016-06-26 22:52:33 -04001508 }
1509
1510 return 0;
1511}
1512
Alan Kwong4dd64c82017-02-04 18:41:51 -08001513/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001514 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1515 */
1516static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1517{
1518 drm_framebuffer_reference(fb);
1519 return fb;
1520}
1521static void _sde_plane_fb_put(void *fb)
1522{
1523 drm_framebuffer_unreference(fb);
1524}
1525static struct sde_crtc_res_ops fb_res_ops = {
1526 .put = _sde_plane_fb_put,
1527 .get = _sde_plane_fb_get,
1528};
1529
1530/**
1531 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1532 */
1533static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1534{
1535 sde_kms_fbo_reference(fbo);
1536 return fbo;
1537}
1538static void _sde_plane_fbo_put(void *fbo)
1539{
1540 sde_kms_fbo_unreference(fbo);
1541}
1542static struct sde_crtc_res_ops fbo_res_ops = {
1543 .put = _sde_plane_fbo_put,
1544 .get = _sde_plane_fbo_get,
1545};
1546
1547/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001548 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001549 * @plane: Pointer to drm plane
1550 * return: prefill time in line
1551 */
Clarence Ipb776b532017-09-12 18:30:06 -04001552u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001553{
1554 struct drm_plane_state *state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001555 struct sde_plane_state *pstate;
1556 struct sde_plane_rot_state *rstate;
1557 struct sde_kms *sde_kms;
1558 u32 blocksize = 128;
1559 u32 prefill_line = 0;
1560
Clarence Ip7eb90452017-05-23 11:41:19 -04001561 if (!plane || !plane->state || !plane->state->fb) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001562 SDE_ERROR("invalid parameters\n");
1563 return 0;
1564 }
1565
1566 sde_kms = _sde_plane_get_kms(plane);
1567 state = plane->state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001568 pstate = to_sde_plane_state(state);
1569 rstate = &pstate->rot;
1570
Clarence Ip7eb90452017-05-23 11:41:19 -04001571 if (!sde_kms || !sde_kms->catalog) {
1572 SDE_ERROR("invalid kms\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08001573 return 0;
1574 }
1575
Clarence Ip7eb90452017-05-23 11:41:19 -04001576 if (rstate->out_fb_format)
1577 sde_format_get_block_size(rstate->out_fb_format,
1578 &blocksize, &blocksize);
1579
Alan Kwong4dd64c82017-02-04 18:41:51 -08001580 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
Alan Kwongd2681812017-08-27 21:24:43 -04001581 prefill_line = mult_frac(prefill_line, rstate->out_src_h >> 16,
1582 state->crtc_h);
1583 SDE_DEBUG(
1584 "plane%d.%d blk:%u head:%u vdst/vsrc:%u/%u prefill:%u\n",
1585 plane->base.id, rstate->sequence_id,
1586 blocksize, sde_kms->catalog->sbuf_headroom,
1587 state->crtc_h, rstate->out_src_h >> 16,
1588 prefill_line);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001589
1590 return prefill_line;
1591}
1592
1593/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08001594 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1595 * enumerating over all planes attached to the same rotator
1596 * @plane: Pointer to drm plane
1597 * @state: Pointer to drm state to be updated
Alan Kwong05109752017-08-12 20:26:45 -04001598 * return: 0 if success; error code otherwise
Alan Kwong4dd64c82017-02-04 18:41:51 -08001599 */
Alan Kwong05109752017-08-12 20:26:45 -04001600static int sde_plane_rot_calc_cfg(struct drm_plane *plane,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001601 struct drm_plane_state *state)
1602{
1603 struct sde_plane_state *pstate;
1604 struct sde_plane_rot_state *rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001605 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001606 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001607 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001608 u32 dst_x, dst_y, dst_w, dst_h;
1609 int found = 0;
1610 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001611 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001612
1613 if (!plane || !state || !state->state) {
1614 SDE_ERROR("invalid parameters\n");
Alan Kwong05109752017-08-12 20:26:45 -04001615 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001616 }
1617
Alan Kwongcdb2f282017-03-18 13:42:06 -07001618 cstate = _sde_plane_get_crtc_state(state);
1619 if (IS_ERR_OR_NULL(cstate)) {
1620 ret = PTR_ERR(cstate);
1621 SDE_ERROR("invalid crtc state %d\n", ret);
Alan Kwong05109752017-08-12 20:26:45 -04001622 return ret;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001623 }
1624
Alan Kwong4dd64c82017-02-04 18:41:51 -08001625 pstate = to_sde_plane_state(state);
1626 rstate = &pstate->rot;
1627
Alan Kwong4dd64c82017-02-04 18:41:51 -08001628 in_rot = &rstate->in_rot_rect;
1629 in_rot->x1 = state->src_x;
1630 in_rot->y1 = state->src_y;
1631 in_rot->x2 = state->src_x + state->src_w;
1632 in_rot->y2 = state->src_y + state->src_h;
1633
1634 out_rot = &rstate->out_rot_rect;
1635 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1636 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1637 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1638 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1639
1640 if (!dst_w && !dst_h) {
1641 rstate->out_rot_rect = rstate->in_rot_rect;
1642 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1643 state->fb->height << 16, rstate->in_rotation);
1644 } else {
1645 out_rot->x1 = dst_x;
1646 out_rot->y1 = dst_y;
1647 out_rot->x2 = dst_x + dst_w;
1648 out_rot->y2 = dst_y + dst_h;
1649 }
1650
1651 rstate->out_src_rect = rstate->out_rot_rect;
1652
Alan Kwong4dd64c82017-02-04 18:41:51 -08001653 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001654 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001655 struct drm_plane_state *attached_state;
1656 struct sde_plane_state *attached_pstate;
1657 struct sde_plane_rot_state *attached_rstate;
1658 struct drm_rect attached_out_rect;
1659
Alan Kwong4dd64c82017-02-04 18:41:51 -08001660 attached_state = drm_atomic_get_existing_plane_state(
1661 state->state, attached_plane);
1662
1663 if (!attached_state)
1664 continue;
1665
1666 attached_pstate = to_sde_plane_state(attached_state);
1667 attached_rstate = &attached_pstate->rot;
1668
Clarence Ipd27d9632017-06-14 09:57:26 -04001669 if (attached_state->fb != state->fb)
1670 continue;
1671
1672 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) !=
1673 sde_plane_get_property(attached_pstate,
1674 PLANE_PROP_ROTATION))
Alan Kwongcdb2f282017-03-18 13:42:06 -07001675 continue;
1676
1677 found++;
1678
1679 /* skip itself */
1680 if (attached_plane == plane)
1681 continue;
1682
Alan Kwong4dd64c82017-02-04 18:41:51 -08001683 /* find bounding rotator source roi */
1684 if (attached_state->src_x < in_rot->x1)
1685 in_rot->x1 = attached_state->src_x;
1686
1687 if (attached_state->src_y < in_rot->y1)
1688 in_rot->y1 = attached_state->src_y;
1689
1690 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1691 in_rot->x2 = attached_state->src_x +
1692 attached_state->src_w;
1693
1694 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1695 in_rot->y2 = attached_state->src_y +
1696 attached_state->src_h;
1697
1698 /* find bounding rotator destination roi */
1699 dst_x = sde_plane_get_property(attached_pstate,
1700 PLANE_PROP_ROT_DST_X);
1701 dst_y = sde_plane_get_property(attached_pstate,
1702 PLANE_PROP_ROT_DST_Y);
1703 dst_w = sde_plane_get_property(attached_pstate,
1704 PLANE_PROP_ROT_DST_W);
1705 dst_h = sde_plane_get_property(attached_pstate,
1706 PLANE_PROP_ROT_DST_H);
1707 if (!dst_w && !dst_h) {
1708 attached_out_rect.x1 = attached_state->src_x;
1709 attached_out_rect.y1 = attached_state->src_y;
1710 attached_out_rect.x2 = attached_out_rect.x1 +
1711 attached_state->src_w;
1712 attached_out_rect.y2 = attached_out_rect.y1 +
1713 attached_state->src_h;
1714 drm_rect_rotate(&attached_out_rect,
1715 state->fb->width << 16,
1716 state->fb->height << 16,
1717 rstate->in_rotation);
1718 } else {
1719 attached_out_rect.x1 = dst_x;
1720 attached_out_rect.y1 = dst_y;
1721 attached_out_rect.x2 = dst_x + dst_w;
1722 attached_out_rect.y2 = dst_y + dst_h;
1723 }
1724
Alan Kwong05109752017-08-12 20:26:45 -04001725 /* check source split left/right mismatch */
1726 if (attached_out_rect.y1 != rstate->out_src_rect.y1 ||
1727 attached_out_rect.y2 != rstate->out_src_rect.y2) {
1728 SDE_ERROR(
1729 "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",
1730 plane->base.id,
1731 rstate->sequence_id,
1732 state->src_w >> 16,
1733 state->src_h >> 16,
1734 state->src_x >> 16,
1735 state->src_y >> 16,
1736 sde_plane_get_property(pstate,
1737 PLANE_PROP_ROTATION),
1738 state->fb ?
1739 state->fb->base.id :
1740 -1,
1741 attached_plane->base.id,
1742 attached_rstate->sequence_id,
1743 attached_state->src_w >> 16,
1744 attached_state->src_h >> 16,
1745 attached_state->src_x >> 16,
1746 attached_state->src_y >> 16,
1747 sde_plane_get_property(attached_pstate,
1748 PLANE_PROP_ROTATION),
1749 attached_state->fb ?
1750 attached_state->fb->base.id :
1751 -1);
1752 SDE_ERROR(
1753 "plane%d.%u sspp:%dx%d+%d+%d plane%d.%u sspp:%dx%d+%d+%d\n",
1754 plane->base.id,
1755 rstate->sequence_id,
1756 (rstate->out_src_rect.x2 -
1757 rstate->out_src_rect.x1) >> 16,
1758 (rstate->out_src_rect.y2 -
1759 rstate->out_src_rect.y1) >> 16,
1760 rstate->out_src_rect.x1 >> 16,
1761 rstate->out_src_rect.y1 >> 16,
1762 attached_plane->base.id,
1763 attached_rstate->sequence_id,
1764 (attached_out_rect.x2 -
1765 attached_out_rect.x1) >> 16,
1766 (attached_out_rect.y2 -
1767 attached_out_rect.y1) >> 16,
1768 attached_out_rect.x1 >> 16,
1769 attached_out_rect.y1 >> 16);
1770 SDE_EVT32(DRMID(plane),
1771 rstate->sequence_id,
1772 rstate->out_src_rect.x1 >> 16,
1773 rstate->out_src_rect.y1 >> 16,
1774 (rstate->out_src_rect.x2 -
1775 rstate->out_src_rect.x1) >> 16,
1776 (rstate->out_src_rect.y2 -
1777 rstate->out_src_rect.y1) >> 16,
1778 attached_plane->base.id,
1779 attached_rstate->sequence_id,
1780 attached_out_rect.x1 >> 16,
1781 attached_out_rect.y1 >> 16,
1782 (attached_out_rect.x2 -
1783 attached_out_rect.x1) >> 16,
1784 (attached_out_rect.y2 -
1785 attached_out_rect.y1) >> 16,
1786 SDE_EVTLOG_ERROR);
1787 return -EINVAL;
1788 }
1789
Alan Kwong4dd64c82017-02-04 18:41:51 -08001790 /* find relative sspp position */
1791 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1792 xpos++;
1793
1794 if (attached_out_rect.x1 < out_rot->x1)
1795 out_rot->x1 = attached_out_rect.x1;
1796
1797 if (attached_out_rect.y1 < out_rot->y1)
1798 out_rot->y1 = attached_out_rect.y1;
1799
1800 if (attached_out_rect.x2 > out_rot->x2)
1801 out_rot->x2 = attached_out_rect.x2;
1802
1803 if (attached_out_rect.y2 > out_rot->y2)
1804 out_rot->y2 = attached_out_rect.y2;
1805
1806 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1807 attached_plane->base.id,
1808 attached_rstate->sequence_id,
1809 attached_rstate->out_src_rect.x1 >> 16,
1810 attached_state->src_w >> 16,
1811 attached_state->src_h >> 16,
1812 attached_state->src_x >> 16,
1813 attached_state->src_y >> 16,
1814 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1815 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1816 attached_rstate->out_src_rect.x1 >> 16,
1817 attached_rstate->out_src_rect.y1 >> 16);
1818 }
1819
1820 rstate->out_xpos = xpos;
1821 rstate->nplane = found;
1822
1823 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1824 plane->base.id, rstate->sequence_id,
1825 rstate->out_xpos, rstate->nplane,
1826 drm_rect_width(in_rot) >> 16,
1827 drm_rect_height(in_rot) >> 16,
1828 in_rot->x1 >> 16, in_rot->y1 >> 16,
1829 drm_rect_width(&rstate->out_rot_rect) >> 16,
1830 drm_rect_height(&rstate->out_rot_rect) >> 16,
1831 rstate->out_rot_rect.x1 >> 16,
1832 rstate->out_rot_rect.y1 >> 16);
Clarence Ipeb39cce2017-07-19 14:12:43 -04001833 SDE_EVT32(DRMID(plane), rstate->sequence_id,
Clarence Ipf27c6f22017-07-10 18:19:44 -04001834 rstate->out_xpos, rstate->nplane,
1835 in_rot->x1 >> 16, in_rot->y1 >> 16,
1836 drm_rect_width(in_rot) >> 16,
1837 drm_rect_height(in_rot) >> 16,
1838 rstate->out_rot_rect.x1 >> 16,
1839 rstate->out_rot_rect.y1 >> 16,
1840 drm_rect_width(&rstate->out_rot_rect) >> 16,
1841 drm_rect_height(&rstate->out_rot_rect) >> 16);
Alan Kwong05109752017-08-12 20:26:45 -04001842
1843 return 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001844}
1845
1846/**
1847 * sde_plane_rot_submit_command - commit given state for the rotator stage
1848 * @plane: Pointer to drm plane
1849 * @state: Pointer to the state to be committed
1850 * @hw_cmd: rotator command type
1851 * return: 0 if success; error code otherwise
1852 */
1853static int sde_plane_rot_submit_command(struct drm_plane *plane,
1854 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1855{
1856 struct sde_plane *psde = to_sde_plane(plane);
1857 struct sde_plane_state *pstate = to_sde_plane_state(state);
1858 struct sde_plane_rot_state *rstate = &pstate->rot;
1859 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001860 struct drm_crtc_state *cstate;
1861 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001862 int ret, i;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001863 int fb_mode;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001864
1865 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1866 SDE_ERROR("invalid parameters\n");
1867 return -EINVAL;
1868 }
1869
Alan Kwong4aacd532017-02-04 18:51:33 -08001870 cstate = _sde_plane_get_crtc_state(state);
1871 if (IS_ERR_OR_NULL(cstate)) {
1872 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1873 return -EINVAL;
1874 }
1875 sde_cstate = to_sde_crtc_state(cstate);
1876
Alan Kwong4dd64c82017-02-04 18:41:51 -08001877 rot_cmd = &rstate->rot_cmd;
1878
1879 rot_cmd->master = (rstate->out_xpos == 0);
1880 rot_cmd->sequence_id = rstate->sequence_id;
1881 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1882 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1883 DEFAULT_REFRESH_RATE;
1884 rot_cmd->rot90 = rstate->rot90;
1885 rot_cmd->hflip = rstate->hflip;
1886 rot_cmd->vflip = rstate->vflip;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001887 fb_mode = sde_plane_get_property(pstate,
1888 PLANE_PROP_FB_TRANSLATION_MODE);
1889 if ((fb_mode == SDE_DRM_FB_SEC) ||
1890 (fb_mode == SDE_DRM_FB_SEC_DIR_TRANS))
1891 rot_cmd->secure = true;
1892 else
1893 rot_cmd->secure = false;
1894
Alan Kwong4aacd532017-02-04 18:51:33 -08001895 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1896 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001897 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1898 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001899 rot_cmd->dst_writeback = psde->sbuf_writeback;
1900
1901 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1902 rot_cmd->video_mode = true;
1903 else
1904 rot_cmd->video_mode = false;
1905
1906 rot_cmd->src_pixel_format = state->fb->pixel_format;
1907 rot_cmd->src_modifier = state->fb->modifier[0];
1908 rot_cmd->src_stride = state->fb->pitches[0];
1909
1910 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1911 if (!rot_cmd->src_format) {
1912 SDE_ERROR("failed to get src format\n");
1913 return -EINVAL;
1914 }
1915
1916 rot_cmd->src_width = state->fb->width;
1917 rot_cmd->src_height = state->fb->height;
1918 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1919 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1920 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1921 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
Alan Kwong809f3cbd2017-08-11 18:39:36 -04001922 rot_cmd->dst_rect_x = 0;
1923 rot_cmd->dst_rect_y = 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001924 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1925 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1926
1927 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1928 struct sde_hw_fmt_layout layout;
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, state->fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001932 &layout);
1933 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1934 rot_cmd->src_iova[i] = layout.plane_addr[i];
1935 rot_cmd->src_len[i] = layout.plane_size[i];
1936 }
1937 rot_cmd->src_planes = layout.num_planes;
1938
1939 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Clarence Ip299fa602017-07-11 18:01:37 -04001940 sde_format_populate_layout(pstate->aspace, rstate->out_fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001941 &layout);
1942 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1943 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1944 rot_cmd->dst_len[i] = layout.plane_size[i];
1945 }
1946 rot_cmd->dst_planes = layout.num_planes;
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001947
1948 /* VBIF remapper settings */
Alan Kwong032c2e182017-06-29 16:31:38 -04001949 for (i = 0; i < rstate->rot_hw->caps->xin_count; i++) {
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001950 const struct sde_rot_vbif_cfg *cfg =
1951 &rstate->rot_hw->caps->vbif_cfg[i];
1952
1953 _sde_plane_inline_rot_set_qos_remap(plane, cfg);
1954
1955 if (cfg->is_read) {
1956 _sde_plane_inline_rot_set_ot_limit(plane,
1957 state->crtc, cfg, rot_cmd->src_rect_w,
1958 rot_cmd->src_rect_h);
1959 } else {
1960 _sde_plane_inline_rot_set_ot_limit(plane,
1961 state->crtc, cfg, rot_cmd->dst_rect_w,
1962 rot_cmd->dst_rect_h);
1963 }
1964 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001965 }
1966
1967 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
Alan Kwong05109752017-08-12 20:26:45 -04001968 if (ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001969 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001970
1971 rstate->out_rotation = rstate->in_rotation;
1972 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1973 DRM_MODE_FB_MODIFIERS : 0;
1974 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1975 rstate->out_fb_format = rot_cmd->dst_format;
1976 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1977
1978 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1979 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1980
1981 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1982 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1983 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1984 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1985 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1986 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1987
1988 if (rot_cmd->rot90)
1989 rstate->out_rotation &= ~DRM_ROTATE_90;
1990
1991 if (rot_cmd->hflip)
1992 rstate->out_rotation &= ~DRM_REFLECT_X;
1993
1994 if (rot_cmd->vflip)
1995 rstate->out_rotation &= ~DRM_REFLECT_Y;
1996
1997 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07001998 "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 -08001999 plane->base.id, rstate->sequence_id, hw_cmd,
2000 rot_cmd->rot90 ? 'r' : '_',
2001 rot_cmd->hflip ? 'h' : '_',
2002 rot_cmd->vflip ? 'v' : '_',
2003 rot_cmd->video_mode ? 'V' : 'C',
2004 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002005 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002006 state->fb->modifier[0],
2007 drm_rect_width(&rstate->in_rot_rect) >> 16,
2008 drm_rect_height(&rstate->in_rot_rect) >> 16,
2009 rstate->in_rot_rect.x1 >> 16,
2010 rstate->in_rot_rect.y1 >> 16);
2011
Dhaval Patel6c666622017-03-21 23:02:59 -07002012 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 -08002013 plane->base.id, rstate->sequence_id, hw_cmd,
2014 rstate->out_rotation,
2015 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002016 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002017 rstate->out_fb_modifier[0],
2018 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2019 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
2020
2021 return ret;
2022}
2023
2024/**
Clarence Ipd27d9632017-06-14 09:57:26 -04002025 * _sde_plane_rot_get_fb - attempt to get previously allocated fb/fbo
2026 * If an fb/fbo was already created, either from a previous frame or
2027 * from another plane in the current commit cycle, attempt to reuse
2028 * it for this commit cycle as well.
2029 * @plane: Pointer to drm plane
2030 * @cstate: Pointer to crtc state
2031 * @rstate: Pointer to rotator plane state
2032 */
2033static void _sde_plane_rot_get_fb(struct drm_plane *plane,
2034 struct drm_crtc_state *cstate,
2035 struct sde_plane_rot_state *rstate)
2036{
2037 struct sde_kms_fbo *fbo;
2038 struct drm_framebuffer *fb;
2039
Clarence Ipf27c6f22017-07-10 18:19:44 -04002040 if (!plane || !cstate || !rstate || !rstate->rot_hw)
Clarence Ipd27d9632017-06-14 09:57:26 -04002041 return;
2042
2043 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2044 (u64) &rstate->rot_hw->base);
2045 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2046 (u64) &rstate->rot_hw->base);
2047 if (fb && fbo) {
2048 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
2049 rstate->sequence_id);
2050 } else if (fbo) {
2051 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2052 (u64) &rstate->rot_hw->base);
2053 fbo = NULL;
2054 } else if (fb) {
2055 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2056 (u64) &rstate->rot_hw->base);
2057 fb = NULL;
2058 }
2059
2060 rstate->out_fbo = fbo;
2061 rstate->out_fb = fb;
2062}
2063
2064/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002065 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
2066 * for rotator (pre-sspp) stage
2067 * @plane: Pointer to drm plane
2068 * @new_state: Pointer to new drm plane state
2069 * return: 0 if success; error code otherwise
2070 */
2071static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
2072 struct drm_plane_state *new_state)
2073{
2074 struct drm_framebuffer *fb = new_state->fb;
2075 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
2076 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002077 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002078 int ret;
2079
2080 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
2081 plane->base.id,
2082 new_rstate->sequence_id, fb ? fb->base.id : 0,
2083 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
2084 sde_plane_crtc_enabled(new_state));
2085
2086 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
2087 return 0;
2088
Alan Kwongcdb2f282017-03-18 13:42:06 -07002089 cstate = _sde_plane_get_crtc_state(new_state);
2090 if (IS_ERR(cstate)) {
2091 ret = PTR_ERR(cstate);
2092 SDE_ERROR("invalid crtc state %d\n", ret);
2093 return ret;
2094 }
2095
Alan Kwong4dd64c82017-02-04 18:41:51 -08002096 /* need to re-calc based on all newly validated plane states */
Alan Kwong05109752017-08-12 20:26:45 -04002097 ret = sde_plane_rot_calc_cfg(plane, new_state);
2098 if (ret)
2099 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002100
2101 /* check if stream buffer is already attached to rotator */
Clarence Ipd27d9632017-06-14 09:57:26 -04002102 if (sde_plane_enabled(new_state) && !new_rstate->out_fb)
2103 _sde_plane_rot_get_fb(plane, cstate, new_rstate);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002104
Alan Kwong4dd64c82017-02-04 18:41:51 -08002105 /* create new stream buffer if it is not available */
2106 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
2107 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
2108 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
2109
2110 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
2111 new_rstate->sequence_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002112
2113 /* check if out_fb is already attached to rotator */
2114 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
2115 new_rstate->out_fb_pixel_format,
2116 new_rstate->out_fb_modifier,
2117 new_rstate->out_fb_flags);
2118 if (!new_rstate->out_fbo) {
2119 SDE_ERROR("failed to allocate inline buffer object\n");
2120 ret = -EINVAL;
2121 goto error_create_fbo;
2122 }
2123
Alan Kwongcdb2f282017-03-18 13:42:06 -07002124 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2125 (u64) &new_rstate->rot_hw->base,
2126 new_rstate->out_fbo, &fbo_res_ops);
2127 if (ret) {
2128 SDE_ERROR("failed to add crtc resource\n");
2129 goto error_create_fbo_res;
2130 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002131
2132 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
2133 new_rstate->out_fbo);
2134 if (!new_rstate->out_fb) {
2135 SDE_ERROR("failed to create inline framebuffer\n");
2136 ret = -EINVAL;
2137 goto error_create_fb;
2138 }
Clarence Ipf27c6f22017-07-10 18:19:44 -04002139 SDE_EVT32_VERBOSE(DRMID(plane), new_rstate->sequence_id,
2140 new_rstate->out_fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002141
Alan Kwongcdb2f282017-03-18 13:42:06 -07002142 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2143 (u64) &new_rstate->rot_hw->base,
2144 new_rstate->out_fb, &fb_res_ops);
2145 if (ret) {
2146 SDE_ERROR("failed to add crtc resource %d\n", ret);
2147 goto error_create_fb_res;
2148 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002149 }
2150
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002151 if (new_pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002152 SDE_EVT32(DRMID(plane));
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002153 SDE_DEBUG(
2154 "plane%d, domain not attached, prepare fb handled later\n",
2155 plane->base.id);
2156 return 0;
2157 }
2158
Alan Kwong4dd64c82017-02-04 18:41:51 -08002159 /* prepare rotator input buffer */
Clarence Ip299fa602017-07-11 18:01:37 -04002160 ret = msm_framebuffer_prepare(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002161 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002162 SDE_ERROR("failed to prepare input framebuffer, %d\n", ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002163 goto error_prepare_input_buffer;
2164 }
2165
2166 /* prepare rotator output buffer */
2167 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
2168 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
2169 new_rstate->sequence_id);
2170
2171 ret = msm_framebuffer_prepare(new_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002172 new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002173 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002174 SDE_ERROR("failed to prepare inline framebuffer, %d\n",
2175 ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002176 goto error_prepare_output_buffer;
2177 }
2178 }
2179
2180 return 0;
2181
2182error_prepare_output_buffer:
Clarence Ip299fa602017-07-11 18:01:37 -04002183 msm_framebuffer_cleanup(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002184error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002185 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2186 (u64) &new_rstate->rot_hw->base);
2187error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002188 new_rstate->out_fb = NULL;
2189error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002190 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2191 (u64) &new_rstate->rot_hw->base);
2192error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002193 new_rstate->out_fbo = NULL;
2194error_create_fbo:
2195 return ret;
2196}
2197
2198/**
2199 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
2200 * rotator (pre-sspp) stage
2201 * @plane: Pointer to drm plane
2202 * @old_state: Pointer to previous drm plane state
2203 * return: none
2204 */
2205static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
2206 struct drm_plane_state *old_state)
2207{
2208 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
2209 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2210 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002211 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002212 int ret;
2213
2214 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2215 old_rstate->sequence_id, old_state->fb->base.id,
2216 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
2217 sde_plane_crtc_enabled(old_state));
2218
2219 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
2220 return;
2221
Alan Kwongcdb2f282017-03-18 13:42:06 -07002222 cstate = _sde_plane_get_crtc_state(old_state);
2223 if (IS_ERR(cstate)) {
2224 ret = PTR_ERR(cstate);
2225 SDE_ERROR("invalid crtc state %d\n", ret);
2226 return;
2227 }
2228
Alan Kwong4dd64c82017-02-04 18:41:51 -08002229 if (sde_plane_crtc_enabled(old_state)) {
2230 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
2231 SDE_HW_ROT_CMD_CLEANUP);
2232 if (ret)
2233 SDE_ERROR("failed to cleanup rotator buffers\n");
2234 }
2235
2236 if (sde_plane_enabled(old_state)) {
2237 if (old_rstate->out_fb) {
2238 msm_framebuffer_cleanup(old_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002239 old_pstate->aspace);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002240 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2241 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002242 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002243 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2244 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002245 old_rstate->out_fbo = NULL;
2246 }
2247
Clarence Ip299fa602017-07-11 18:01:37 -04002248 msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002249 }
2250}
2251
2252/**
2253 * sde_plane_rot_atomic_check - verify rotator update of the given state
2254 * @plane: Pointer to drm plane
2255 * @state: Pointer to drm plane state to be validated
2256 * return: 0 if success; error code otherwise
2257 */
2258static int sde_plane_rot_atomic_check(struct drm_plane *plane,
2259 struct drm_plane_state *state)
2260{
2261 struct sde_plane *psde;
2262 struct sde_plane_state *pstate, *old_pstate;
2263 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002264 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002265 struct sde_hw_blk *hw_blk;
2266 int i, ret = 0;
2267
2268 if (!plane || !state) {
2269 SDE_ERROR("invalid plane/state\n");
2270 return -EINVAL;
2271 }
2272
2273 psde = to_sde_plane(plane);
2274 pstate = to_sde_plane_state(state);
2275 old_pstate = to_sde_plane_state(plane->state);
2276 rstate = &pstate->rot;
2277 old_rstate = &old_pstate->rot;
2278
Alan Kwongcdb2f282017-03-18 13:42:06 -07002279 /* cstate will be null if crtc is disconnected from plane */
2280 cstate = _sde_plane_get_crtc_state(state);
2281 if (IS_ERR(cstate)) {
2282 ret = PTR_ERR(cstate);
2283 SDE_ERROR("invalid crtc state %d\n", ret);
2284 return ret;
2285 }
2286
Alan Kwong4dd64c82017-02-04 18:41:51 -08002287 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2288 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
2289 !!rstate->out_sbuf, !!rstate->rot_hw,
2290 sde_plane_crtc_enabled(state));
2291
2292 rstate->in_rotation = drm_rotation_simplify(
2293 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07002294 DRM_ROTATE_0 | DRM_ROTATE_90 |
2295 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002296 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
2297 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
2298 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
2299 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
2300
Alan Kwongcdb2f282017-03-18 13:42:06 -07002301 if (sde_plane_enabled(state) && rstate->out_sbuf) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002302 SDE_DEBUG("plane%d.%d acquire rotator, fb %d\n",
2303 plane->base.id, rstate->sequence_id,
2304 state->fb ? state->fb->base.id : -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002305
Alan Kwongcdb2f282017-03-18 13:42:06 -07002306 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
2307 (u64) state->fb);
2308 if (!hw_blk) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002309 SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
2310 plane->base.id, rstate->sequence_id,
2311 state->fb ? state->fb->base.id : -1);
Alan Kwong310e9b02017-08-03 02:04:07 -04002312 SDE_EVT32(DRMID(plane), rstate->sequence_id,
2313 SDE_EVTLOG_ERROR);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002314 return -EINVAL;
2315 }
2316
Alan Kwongcdb2f282017-03-18 13:42:06 -07002317 rstate->rot_hw = to_sde_hw_rot(hw_blk);
2318
Alan Kwong4dd64c82017-02-04 18:41:51 -08002319 if (!rstate->rot_hw->ops.commit) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002320 SDE_ERROR("plane%d.%d invalid rotator ops\n",
2321 plane->base.id, rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002322 sde_crtc_res_put(cstate,
2323 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002324 rstate->rot_hw = NULL;
2325 return -EINVAL;
2326 }
2327
2328 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002329 } else {
2330 rstate->in_fb = NULL;
2331 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002332 }
2333
2334 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002335 uint32_t fb_id;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002336
Clarence Ipf27c6f22017-07-10 18:19:44 -04002337 fb_id = state->fb ? state->fb->base.id : -1;
2338 SDE_DEBUG("plane%d.%d use rotator, fb %d\n",
2339 plane->base.id, rstate->sequence_id, fb_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002340
Alan Kwong05109752017-08-12 20:26:45 -04002341 ret = sde_plane_rot_calc_cfg(plane, state);
2342 if (ret)
2343 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002344
2345 ret = sde_plane_rot_submit_command(plane, state,
2346 SDE_HW_ROT_CMD_VALIDATE);
Clarence Ipf27c6f22017-07-10 18:19:44 -04002347 if (ret)
2348 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002349
Clarence Ip317a9572017-08-08 18:16:26 -04002350 if (rstate->nplane != old_rstate->nplane ||
2351 rstate->out_xpos != old_rstate->out_xpos)
2352 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2353 SDE_PLANE_DIRTY_RECTS;
2354
Clarence Ipf27c6f22017-07-10 18:19:44 -04002355 /* check if stream buffer is already attached to rotator */
2356 _sde_plane_rot_get_fb(plane, cstate, rstate);
2357
2358 /* release buffer if output format configuration changes */
2359 if (rstate->out_fb &&
2360 ((rstate->out_fb_height != rstate->out_fb->height) ||
2361 (rstate->out_fb_width != rstate->out_fb->width) ||
2362 (rstate->out_fb_pixel_format !=
2363 rstate->out_fb->pixel_format) ||
2364 (rstate->out_fb_modifier[0] !=
2365 rstate->out_fb->modifier[0]) ||
2366 (rstate->out_fb_flags != rstate->out_fb->flags))) {
2367
2368 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
2369 rstate->sequence_id);
2370 SDE_EVT32_VERBOSE(DRMID(plane),
2371 rstate->sequence_id, fb_id);
2372
2373 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2374 (u64) &rstate->rot_hw->base);
2375 rstate->out_fb = NULL;
2376 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2377 (u64) &rstate->rot_hw->base);
2378 rstate->out_fbo = NULL;
2379 }
Clarence Ip4475d582017-04-18 11:36:00 -04002380 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002381
2382 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
2383 rstate->sequence_id);
2384
2385 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04002386 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
2387 rstate->out_fb_modifier[i] = state->fb ?
2388 state->fb->modifier[i] : 0x0;
2389
2390 if (state->fb) {
2391 rstate->out_fb_pixel_format = state->fb->pixel_format;
2392 rstate->out_fb_flags = state->fb->flags;
2393 rstate->out_fb_width = state->fb->width;
2394 rstate->out_fb_height = state->fb->height;
2395 } else {
2396 rstate->out_fb_pixel_format = 0x0;
2397 rstate->out_fb_flags = 0x0;
2398 rstate->out_fb_width = 0;
2399 rstate->out_fb_height = 0;
2400 }
2401
Alan Kwong4dd64c82017-02-04 18:41:51 -08002402 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002403 rstate->out_src_x = state->src_x;
2404 rstate->out_src_y = state->src_y;
2405 rstate->out_src_w = state->src_w;
2406 rstate->out_src_h = state->src_h;
2407
2408 rstate->out_fb_format = NULL;
2409 rstate->out_sbuf = false;
2410 rstate->out_fb = state->fb;
2411 }
2412
2413 return ret;
2414}
2415
2416/**
2417 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2418 * @plane: Pointer to drm plane
2419 * @old_state: Pointer to previous state
2420 * return: none
2421 */
2422static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2423 struct drm_plane_state *old_state)
2424{
2425 struct drm_plane_state *state;
2426 struct sde_plane_state *pstate;
2427 struct sde_plane_rot_state *rstate;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002428 int ret = 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002429
2430 if (!plane || !plane->state) {
2431 SDE_ERROR("invalid plane/state\n");
2432 return;
2433 }
2434
2435 state = plane->state;
2436 pstate = to_sde_plane_state(state);
2437 rstate = &pstate->rot;
2438
2439 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2440 rstate->sequence_id,
2441 !!rstate->out_sbuf, !!rstate->rot_hw,
2442 sde_plane_crtc_enabled(plane->state));
2443
2444 if (!sde_plane_crtc_enabled(state))
2445 return;
2446
2447 if (!rstate->out_sbuf || !rstate->rot_hw)
2448 return;
2449
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002450 /*
2451 * framebuffer prepare is deferred for prepare_fb calls that
2452 * happen during the transition from secure to non-secure.
2453 * Handle the prepare at this point for rotator in such cases.
2454 * This can be expected for one or two frames during the transition.
2455 */
2456 if (pstate->aspace && pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002457 SDE_EVT32(DRMID(plane), pstate->aspace->domain_attached);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002458 /* prepare rotator input buffer */
2459 ret = msm_framebuffer_prepare(state->fb, pstate->aspace);
2460 if (ret) {
2461 SDE_ERROR("p%d failed to prepare input fb %d\n",
2462 plane->base.id, ret);
2463 return;
2464 }
2465
2466 /* prepare rotator output buffer */
2467 if (sde_plane_enabled(state) && rstate->out_fb) {
2468 ret = msm_framebuffer_prepare(rstate->out_fb,
2469 pstate->aspace);
2470 if (ret) {
2471 SDE_ERROR(
2472 "p%d failed to prepare inline fb %d\n",
2473 plane->base.id, ret);
2474 goto error_prepare_output_buffer;
2475 }
2476 }
2477 }
2478
Alan Kwong4dd64c82017-02-04 18:41:51 -08002479 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002480
2481 return;
2482
2483error_prepare_output_buffer:
2484 msm_framebuffer_cleanup(state->fb, pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002485}
2486
Clarence Ip2606dd62017-10-14 21:11:14 -04002487static bool _sde_plane_halt_requests(struct drm_plane *plane,
2488 uint32_t xin_id, bool halt_forced_clk, bool enable)
2489{
2490 struct sde_plane *psde;
2491 struct msm_drm_private *priv;
2492 struct sde_vbif_set_xin_halt_params halt_params;
2493
2494 if (!plane || !plane->dev) {
2495 SDE_ERROR("invalid arguments\n");
2496 return false;
2497 }
2498
2499 psde = to_sde_plane(plane);
2500 if (!psde->pipe_hw || !psde->pipe_hw->cap) {
2501 SDE_ERROR("invalid pipe reference\n");
2502 return false;
2503 }
2504
2505 priv = plane->dev->dev_private;
2506 if (!priv || !priv->kms) {
2507 SDE_ERROR("invalid KMS reference\n");
2508 return false;
2509 }
2510
2511 memset(&halt_params, 0, sizeof(halt_params));
2512 halt_params.vbif_idx = VBIF_RT;
2513 halt_params.xin_id = xin_id;
2514 halt_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
2515 halt_params.forced_on = halt_forced_clk;
2516 halt_params.enable = enable;
2517
2518 return sde_vbif_set_xin_halt(to_sde_kms(priv->kms), &halt_params);
2519}
2520
2521void sde_plane_halt_requests(struct drm_plane *plane, bool enable)
2522{
2523 struct sde_plane *psde;
2524
2525 if (!plane) {
2526 SDE_ERROR("invalid plane\n");
2527 return;
2528 }
2529
2530 psde = to_sde_plane(plane);
2531 if (!psde->pipe_hw || !psde->pipe_hw->cap) {
2532 SDE_ERROR("invalid pipe reference\n");
2533 return;
2534 }
2535
2536 SDE_EVT32(DRMID(plane), psde->xin_halt_forced_clk, enable);
2537
2538 psde->xin_halt_forced_clk =
2539 _sde_plane_halt_requests(plane, psde->pipe_hw->cap->xin_id,
2540 psde->xin_halt_forced_clk, enable);
2541}
2542
2543int sde_plane_reset_rot(struct drm_plane *plane, struct drm_plane_state *state)
2544{
2545 struct sde_plane *psde;
2546 struct sde_plane_state *pstate;
2547 struct sde_plane_rot_state *rstate;
2548 bool halt_ret[MAX_BLOCKS] = {false};
2549 signed int i, count;
2550
2551 if (!plane || !state) {
2552 SDE_ERROR("invalid plane\n");
2553 return -EINVAL;
2554 }
2555
2556 psde = to_sde_plane(plane);
2557 pstate = to_sde_plane_state(state);
2558 rstate = &pstate->rot;
2559
2560 /* do nothing if not master rotator plane */
2561 if (!rstate->out_sbuf || !rstate->rot_hw ||
2562 !rstate->rot_hw->caps || (rstate->out_xpos != 0))
2563 return 0;
2564
2565 count = (signed int)rstate->rot_hw->caps->xin_count;
2566 if (count > ARRAY_SIZE(halt_ret))
2567 count = ARRAY_SIZE(halt_ret);
2568
2569 SDE_DEBUG_PLANE(psde, "issuing reset for rotator\n");
2570 SDE_EVT32(DRMID(plane), count);
2571
2572 for (i = 0; i < count; i++) {
2573 const struct sde_rot_vbif_cfg *cfg =
2574 &rstate->rot_hw->caps->vbif_cfg[i];
2575
2576 halt_ret[i] = _sde_plane_halt_requests(plane, cfg->xin_id,
2577 false, true);
2578 }
2579
2580 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_RESET);
2581
2582 for (i = count - 1; i >= 0; --i) {
2583 const struct sde_rot_vbif_cfg *cfg =
2584 &rstate->rot_hw->caps->vbif_cfg[i];
2585
2586 _sde_plane_halt_requests(plane, cfg->xin_id,
2587 halt_ret[i], false);
2588 }
2589 return 0;
2590}
2591
Clarence Ip8ee49952017-09-20 11:10:50 -04002592int sde_plane_kickoff_rot(struct drm_plane *plane)
Clarence Ipddbf7752017-05-21 18:07:30 -04002593{
Clarence Ipeb39cce2017-07-19 14:12:43 -04002594 struct sde_plane_state *pstate;
2595
2596 if (!plane || !plane->state) {
2597 SDE_ERROR("invalid plane\n");
Clarence Ip8ee49952017-09-20 11:10:50 -04002598 return -EINVAL;
Clarence Ipeb39cce2017-07-19 14:12:43 -04002599 }
2600
2601 pstate = to_sde_plane_state(plane->state);
2602
2603 if (!pstate->rot.rot_hw || !pstate->rot.rot_hw->ops.commit)
Clarence Ip8ee49952017-09-20 11:10:50 -04002604 return 0;
Clarence Ipddbf7752017-05-21 18:07:30 -04002605
Clarence Ip8ee49952017-09-20 11:10:50 -04002606 return pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
Clarence Ipddbf7752017-05-21 18:07:30 -04002607 &pstate->rot.rot_cmd,
2608 SDE_HW_ROT_CMD_START);
2609}
2610
2611/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002612 * sde_plane_rot_destroy_state - destroy state for rotator stage
2613 * @plane: Pointer to drm plane
2614 * @state: Pointer to state to be destroyed
2615 * return: none
2616 */
2617static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2618 struct drm_plane_state *state)
2619{
2620 struct sde_plane_state *pstate = to_sde_plane_state(state);
2621 struct sde_plane_rot_state *rstate = &pstate->rot;
2622
2623 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2624 rstate->sequence_id,
2625 !!rstate->out_sbuf, !!rstate->rot_hw,
2626 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002627}
2628
2629/**
2630 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2631 * @plane: Pointer to drm plane
2632 * @new_state: Pointer to duplicated state
2633 * return: 0 if success; error code otherwise
2634 */
2635static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2636 struct drm_plane_state *new_state)
2637{
2638 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2639 struct sde_plane_rot_state *rstate = &pstate->rot;
2640
2641 rstate->sequence_id++;
2642
2643 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2644 rstate->sequence_id,
2645 !!rstate->out_sbuf, !!rstate->rot_hw);
2646
Clarence Ipf27c6f22017-07-10 18:19:44 -04002647 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002648 rstate->out_fb = NULL;
2649 rstate->out_fbo = NULL;
2650
2651 return 0;
2652}
2653
2654/**
2655 * sde_plane_rot_install_caps - install plane rotator capabilities
2656 * @plane: Pointer to drm plane
2657 * return: none
2658 */
2659static void sde_plane_rot_install_caps(struct drm_plane *plane)
2660{
2661 struct sde_plane *psde = to_sde_plane(plane);
2662 const struct sde_format_extended *format_list;
2663 struct sde_kms_info *info;
2664 struct sde_hw_rot *rot_hw;
2665 const char *downscale_caps;
2666
2667 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2668 !psde->catalog->rot_count)
2669 return;
2670
2671 if (psde->blob_rot_caps)
2672 return;
2673
2674 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2675 if (!info)
2676 return;
2677
2678 rot_hw = sde_hw_rot_get(NULL);
2679 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2680 !rot_hw->ops.get_downscale_caps) {
2681 SDE_ERROR("invalid rotator hw\n");
2682 goto error_rot;
2683 }
2684
2685 sde_kms_info_reset(info);
2686
2687 format_list = rot_hw->ops.get_format_caps(rot_hw);
2688 if (format_list) {
2689 sde_kms_info_start(info, "pixel_formats");
2690 while (format_list->fourcc_format) {
2691 sde_kms_info_append_format(info,
2692 format_list->fourcc_format,
2693 format_list->modifier);
2694 ++format_list;
2695 }
2696 sde_kms_info_stop(info);
2697 }
2698
2699 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2700 if (downscale_caps) {
2701 sde_kms_info_start(info, "downscale_ratios");
2702 sde_kms_info_append(info, downscale_caps);
2703 sde_kms_info_stop(info);
2704 }
2705
2706 if (rot_hw->ops.get_cache_size)
2707 sde_kms_info_add_keyint(info, "cache_size",
2708 rot_hw->ops.get_cache_size(rot_hw));
2709
Alan Kwong1a915802017-03-31 12:55:46 -07002710 if (rot_hw->ops.get_maxlinewidth)
2711 sde_kms_info_add_keyint(info, "max_linewidth",
2712 rot_hw->ops.get_maxlinewidth(rot_hw));
2713
Alan Kwong4dd64c82017-02-04 18:41:51 -08002714 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
Narendra Muppalla22d17252017-05-31 15:13:39 -07002715 info->data, SDE_KMS_INFO_DATALEN(info),
2716 PLANE_PROP_ROT_CAPS_V1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002717
2718 sde_hw_rot_put(rot_hw);
2719error_rot:
2720 kfree(info);
2721}
2722
2723/**
2724 * sde_plane_rot_install_properties - install plane rotator properties
2725 * @plane: Pointer to drm plane
2726 * @catalog: Pointer to mdss configuration
2727 * return: none
2728 */
2729static void sde_plane_rot_install_properties(struct drm_plane *plane,
2730 struct sde_mdss_cfg *catalog)
2731{
2732 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002733 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2734 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002735
2736 if (!plane || !psde) {
2737 SDE_ERROR("invalid plane\n");
2738 return;
2739 } else if (!catalog) {
2740 SDE_ERROR("invalid catalog\n");
2741 return;
2742 }
2743
2744 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2745 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2746 DRM_ROTATE_180 | DRM_ROTATE_270;
2747
2748 msm_property_install_rotation(&psde->property_info,
2749 supported_rotations, PLANE_PROP_ROTATION);
2750
2751 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2752 return;
2753
2754 msm_property_install_range(&psde->property_info, "rot_dst_x",
2755 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2756 msm_property_install_range(&psde->property_info, "rot_dst_y",
2757 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2758 msm_property_install_range(&psde->property_info, "rot_dst_w",
2759 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2760 msm_property_install_range(&psde->property_info, "rot_dst_h",
2761 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2762 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2763 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2764}
2765
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002766void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002767{
Clarence Ipcb410d42016-06-26 22:52:33 -04002768 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002769
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002770 if (!drm_state)
2771 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002772
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002773 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002774
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002775 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2776 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002777}
2778
2779int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2780{
2781 struct sde_plane_state *pstate[R_MAX];
2782 const struct drm_plane_state *drm_state[R_MAX];
2783 struct sde_rect src[R_MAX], dst[R_MAX];
2784 struct sde_plane *sde_plane[R_MAX];
2785 const struct sde_format *fmt[R_MAX];
2786 bool q16_data = true;
Steve Cohenf5d01512017-07-07 18:49:21 -04002787 int i, buffer_lines;
2788 unsigned int max_tile_height = 1;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002789 bool parallel_fetch_qualified = true;
Steve Cohenf5d01512017-07-07 18:49:21 -04002790 bool has_tiled_rect = false;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002791
2792 for (i = 0; i < R_MAX; i++) {
2793 const struct msm_format *msm_fmt;
2794
2795 drm_state[i] = i ? plane->r1 : plane->r0;
Steve Cohenf5d01512017-07-07 18:49:21 -04002796 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2797 fmt[i] = to_sde_format(msm_fmt);
2798
2799 if (SDE_FORMAT_IS_UBWC(fmt[i])) {
2800 has_tiled_rect = true;
2801 if (fmt[i]->tile_height > max_tile_height)
2802 max_tile_height = fmt[i]->tile_height;
2803 }
2804 }
2805
2806 for (i = 0; i < R_MAX; i++) {
2807 int width_threshold;
2808
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002809 pstate[i] = to_sde_plane_state(drm_state[i]);
2810 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2811
2812 if (pstate[i] == NULL) {
2813 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2814 drm_state[i]->plane->base.id);
2815 return -EINVAL;
2816 }
2817
2818 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2819 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2820 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2821 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2822 drm_state[i]->crtc_h, !q16_data);
2823
2824 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2825 SDE_ERROR_PLANE(sde_plane[i],
2826 "scaling is not supported in multirect mode\n");
2827 return -EINVAL;
2828 }
2829
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002830 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2831 SDE_ERROR_PLANE(sde_plane[i],
2832 "Unsupported format for multirect mode\n");
2833 return -EINVAL;
2834 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002835
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002836 /**
2837 * SSPP PD_MEM is split half - one for each RECT.
2838 * Tiled formats need 5 lines of buffering while fetching
2839 * whereas linear formats need only 2 lines.
2840 * So we cannot support more than half of the supported SSPP
2841 * width for tiled formats.
2842 */
2843 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
Steve Cohenf5d01512017-07-07 18:49:21 -04002844 if (has_tiled_rect)
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002845 width_threshold /= 2;
2846
2847 if (parallel_fetch_qualified && src[i].w > width_threshold)
2848 parallel_fetch_qualified = false;
2849
2850 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002851
2852 /* Validate RECT's and set the mode */
2853
2854 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002855 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002856 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2857 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002858
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002859 goto done;
2860 }
2861
2862 /* TIME_MX Mode */
Steve Cohenf5d01512017-07-07 18:49:21 -04002863 buffer_lines = 2 * max_tile_height;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002864
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002865 if ((dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) ||
2866 (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines)) {
2867 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2868 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002869 } else {
2870 SDE_ERROR(
2871 "No multirect mode possible for the planes (%d - %d)\n",
2872 drm_state[R0]->plane->base.id,
2873 drm_state[R1]->plane->base.id);
2874 return -EINVAL;
2875 }
2876
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002877done:
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002878 if (sde_plane[R0]->is_virtual) {
2879 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2880 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2881 } else {
2882 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2883 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2884 };
2885
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002886 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2887 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2888 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2889 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002890 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002891}
2892
Alan Kwong4dd64c82017-02-04 18:41:51 -08002893/**
2894 * sde_plane_get_ctl_flush - get control flush for the given plane
2895 * @plane: Pointer to drm plane structure
2896 * @ctl: Pointer to hardware control driver
Clarence Ip7e5f0002017-05-29 18:46:56 -04002897 * @flush_sspp: Pointer to sspp flush control word
2898 * @flush_rot: Pointer to rotator flush control word
Alan Kwong4dd64c82017-02-04 18:41:51 -08002899 */
2900void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
Clarence Ip7e5f0002017-05-29 18:46:56 -04002901 u32 *flush_sspp, u32 *flush_rot)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002902{
2903 struct sde_plane_state *pstate;
2904 struct sde_plane_rot_state *rstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002905
Clarence Ip7e5f0002017-05-29 18:46:56 -04002906 if (!plane || !flush_sspp) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002907 SDE_ERROR("invalid parameters\n");
2908 return;
2909 }
2910
2911 pstate = to_sde_plane_state(plane->state);
2912 rstate = &pstate->rot;
2913
Clarence Ip7e5f0002017-05-29 18:46:56 -04002914 *flush_sspp = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002915
Clarence Ip7e5f0002017-05-29 18:46:56 -04002916 if (!flush_rot)
2917 return;
2918
2919 *flush_rot = 0x0;
Clarence Ipb776b532017-09-12 18:30:06 -04002920 if (rstate && rstate->out_sbuf && rstate->rot_hw &&
Alan Kwong4dd64c82017-02-04 18:41:51 -08002921 ctl->ops.get_bitmask_rot)
Clarence Ip7e5f0002017-05-29 18:46:56 -04002922 ctl->ops.get_bitmask_rot(ctl, flush_rot, rstate->rot_hw->idx);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002923}
2924
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002925static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002926 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002927{
2928 struct drm_framebuffer *fb = new_state->fb;
2929 struct sde_plane *psde = to_sde_plane(plane);
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002930 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002931 struct sde_plane_rot_state *new_rstate;
Alan Kwong4a5bd782017-06-09 15:20:52 -04002932 struct sde_hw_fmt_layout layout;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002933 struct msm_gem_address_space *aspace;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002934 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002935
2936 if (!new_state->fb)
2937 return 0;
2938
Clarence Ip13a8cf42016-09-29 17:27:47 -04002939 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002940
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002941 ret = _sde_plane_get_aspace(psde, pstate, &aspace);
2942 if (ret) {
2943 SDE_ERROR_PLANE(psde, "Failed to get aspace\n");
2944 return ret;
2945 }
2946
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002947 /* cache aspace */
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002948 pstate->aspace = aspace;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002949
2950 /*
2951 * when transitioning from secure to non-secure,
2952 * plane->prepare_fb happens before the commit. In such case,
2953 * defer the prepare_fb and handled it late, during the commit
2954 * after attaching the domains as part of the transition
2955 */
2956 pstate->defer_prepare_fb = (aspace && !aspace->domain_attached) ?
2957 true : false;
2958
Alan Kwong4dd64c82017-02-04 18:41:51 -08002959 ret = sde_plane_rot_prepare_fb(plane, new_state);
2960 if (ret) {
2961 SDE_ERROR("failed to prepare rot framebuffer\n");
2962 return ret;
2963 }
2964
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002965 if (pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002966 SDE_EVT32(DRMID(plane), psde->pipe);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002967 SDE_DEBUG_PLANE(psde,
2968 "domain not attached, prepare_fb handled later\n");
2969 return 0;
2970 }
2971
Alan Kwong4dd64c82017-02-04 18:41:51 -08002972 new_rstate = &to_sde_plane_state(new_state)->rot;
2973
Abhijit Kulkarni1b3340c2017-06-22 12:39:37 -07002974 if (pstate->aspace) {
2975 ret = msm_framebuffer_prepare(new_rstate->out_fb,
2976 pstate->aspace);
2977 if (ret) {
2978 SDE_ERROR("failed to prepare framebuffer\n");
2979 return ret;
2980 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002981 }
2982
Alan Kwong4a5bd782017-06-09 15:20:52 -04002983 /* validate framebuffer layout before commit */
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002984 ret = sde_format_populate_layout(pstate->aspace,
Alan Kwong4a5bd782017-06-09 15:20:52 -04002985 new_rstate->out_fb, &layout);
2986 if (ret) {
2987 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
2988 return ret;
2989 }
2990
Alan Kwong4dd64c82017-02-04 18:41:51 -08002991 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002992}
2993
Harsh Sahuea808372017-09-12 22:41:01 -07002994/**
2995 * _sde_plane_fetch_halt - halts vbif transactions for a plane
2996 * @plane: Pointer to plane
2997 * Returns: 0 on success
2998 */
2999static int _sde_plane_fetch_halt(struct drm_plane *plane)
3000{
3001 struct sde_plane *psde;
3002 int xin_id;
3003 enum sde_clk_ctrl_type clk_ctrl;
3004 struct msm_drm_private *priv;
3005 struct sde_kms *sde_kms;
3006
3007 psde = to_sde_plane(plane);
3008 if (!plane || !plane->dev || !psde->pipe_hw) {
3009 SDE_ERROR("invalid arguments\n");
3010 return -EINVAL;
3011 }
3012
3013 priv = plane->dev->dev_private;
3014 if (!priv || !priv->kms) {
3015 SDE_ERROR("invalid KMS reference\n");
3016 return -EINVAL;
3017 }
3018
3019 sde_kms = to_sde_kms(priv->kms);
3020 clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
3021 xin_id = psde->pipe_hw->cap->xin_id;
3022 SDE_DEBUG_PLANE(psde, "pipe:%d xin_id:%d clk_ctrl:%d\n",
3023 psde->pipe - SSPP_VIG0, xin_id, clk_ctrl);
3024 SDE_EVT32_VERBOSE(psde, psde->pipe - SSPP_VIG0, xin_id, clk_ctrl);
3025
3026 return sde_vbif_halt_plane_xin(sde_kms, xin_id, clk_ctrl);
3027}
3028
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003029static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07003030 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003031{
Alan Kwong4dd64c82017-02-04 18:41:51 -08003032 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ip299fa602017-07-11 18:01:37 -04003033 struct sde_plane_state *old_pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003034 struct sde_plane_rot_state *old_rstate;
Harsh Sahuea808372017-09-12 22:41:01 -07003035 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003036
Harsh Sahuea808372017-09-12 22:41:01 -07003037 if (!old_state || !old_state->fb || !plane || !plane->state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003038 return;
3039
Clarence Ip299fa602017-07-11 18:01:37 -04003040 old_pstate = to_sde_plane_state(old_state);
3041
Alan Kwong4dd64c82017-02-04 18:41:51 -08003042 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
3043
Harsh Sahuea808372017-09-12 22:41:01 -07003044 /*
3045 * plane->state gets populated for next frame after swap_state. If
3046 * plane->state->crtc pointer is not populated then it is not used in
3047 * the next frame, hence making it an unused plane.
3048 */
3049 if ((plane->state->crtc == NULL) && !psde->is_virtual) {
3050 SDE_DEBUG_PLANE(psde, "unused pipe:%u\n",
3051 psde->pipe - SSPP_VIG0);
3052
3053 /* halt this plane now */
3054 ret = _sde_plane_fetch_halt(plane);
3055 if (ret) {
3056 SDE_ERROR_PLANE(psde,
3057 "unused pipe %u halt failed\n",
3058 psde->pipe - SSPP_VIG0);
3059 SDE_EVT32(DRMID(plane), psde->pipe - SSPP_VIG0,
3060 ret, SDE_EVTLOG_ERROR);
3061 }
3062 }
3063
Clarence Ip299fa602017-07-11 18:01:37 -04003064 old_rstate = &old_pstate->rot;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003065
Clarence Ip299fa602017-07-11 18:01:37 -04003066 msm_framebuffer_cleanup(old_rstate->out_fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003067
3068 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003069}
3070
Alan Kwong4dd64c82017-02-04 18:41:51 -08003071static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003072 struct drm_plane_state *state,
3073 struct drm_plane_state *old_state)
3074{
3075 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003076 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003077 struct sde_plane_rot_state *rstate = &pstate->rot;
3078 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
3079 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003080
Dhaval Patel47302cf2016-08-18 15:04:28 -07003081 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04003082 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07003083 return;
3084
Clarence Ip282dad62016-09-27 17:07:35 -04003085 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
3086 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003087 SDE_DEBUG_PLANE(psde,
3088 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003089 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003090 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003091 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003092 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003093 } else if (pstate->multirect_index != old_pstate->multirect_index ||
3094 pstate->multirect_mode != old_pstate->multirect_mode) {
3095 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
3096 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003097 } else if (rstate->out_src_w != old_rstate->out_src_w ||
3098 rstate->out_src_h != old_rstate->out_src_h ||
3099 rstate->out_src_x != old_rstate->out_src_x ||
3100 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003101 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003102 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003103 } else if (state->crtc_w != old_state->crtc_w ||
3104 state->crtc_h != old_state->crtc_h ||
3105 state->crtc_x != old_state->crtc_x ||
3106 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003107 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003108 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003109 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
3110 pstate->excl_rect.h != old_pstate->excl_rect.h ||
3111 pstate->excl_rect.x != old_pstate->excl_rect.x ||
3112 pstate->excl_rect.y != old_pstate->excl_rect.y) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003113 SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003114 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04003115 }
3116
Alan Kwong4dd64c82017-02-04 18:41:51 -08003117 fb = rstate->out_fb;
3118 old_fb = old_rstate->out_fb;
3119
3120 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003121 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08003122 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003123 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003124 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003125 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08003126 uint64_t *new_mods = fb->modifier;
3127 uint64_t *old_mods = old_fb->modifier;
3128 uint32_t *new_pitches = fb->pitches;
3129 uint32_t *old_pitches = old_fb->pitches;
3130 uint32_t *new_offset = fb->offsets;
3131 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003132 int i;
3133
Alan Kwong4dd64c82017-02-04 18:41:51 -08003134 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003135 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003136 SDE_DEBUG_PLANE(psde,
3137 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07003138 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04003139 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04003140 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
3141 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003142 break;
3143 }
3144 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08003145 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04003146 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003147 SDE_DEBUG_PLANE(psde,
3148 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07003149 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04003150 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04003151 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04003152 break;
3153 }
3154 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08003155 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003156 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003157 SDE_DEBUG_PLANE(psde,
3158 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07003159 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04003160 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04003161 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
3162 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003163 break;
3164 }
3165 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04003166 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003167}
3168
Clarence Ip059c8c32017-06-06 17:15:54 -04003169static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -04003170 struct sde_plane_state *pstate,
Clarence Ip059c8c32017-06-06 17:15:54 -04003171 const struct sde_format *fmt,
3172 uint32_t img_w, uint32_t img_h,
3173 uint32_t src_w, uint32_t src_h,
3174 uint32_t deci_w, uint32_t deci_h)
3175{
3176 int i;
3177
Clarence Ip172033f2017-06-13 10:52:56 -04003178 if (!psde || !pstate || !fmt) {
Clarence Ip059c8c32017-06-06 17:15:54 -04003179 SDE_ERROR_PLANE(psde, "invalid arguments\n");
3180 return -EINVAL;
3181 }
3182
Dhaval Patel9c6acc12017-10-17 10:54:32 -07003183 if (psde->debugfs_default_scale ||
3184 (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2 &&
3185 pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK))
Clarence Ip059c8c32017-06-06 17:15:54 -04003186 return 0;
3187
Clarence Ip172033f2017-06-13 10:52:56 -04003188 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
Clarence Ip059c8c32017-06-06 17:15:54 -04003189
3190 for (i = 0; i < SDE_MAX_PLANES; i++) {
3191 uint32_t hor_req_pixels, hor_fetch_pixels;
3192 uint32_t vert_req_pixels, vert_fetch_pixels;
3193 uint32_t src_w_tmp, src_h_tmp;
3194
3195 /* re-use color plane 1's config for plane 2 */
3196 if (i == 2)
3197 continue;
3198
3199 src_w_tmp = src_w;
3200 src_h_tmp = src_h;
3201
3202 /*
3203 * For chroma plane, width is half for the following sub sampled
3204 * formats. Except in case of decimation, where hardware avoids
3205 * 1 line of decimation instead of downsampling.
3206 */
3207 if (i == 1) {
3208 if (!deci_w &&
3209 (fmt->chroma_sample == SDE_CHROMA_420 ||
3210 fmt->chroma_sample == SDE_CHROMA_H2V1))
3211 src_w_tmp >>= 1;
3212 if (!deci_h &&
3213 (fmt->chroma_sample == SDE_CHROMA_420 ||
3214 fmt->chroma_sample == SDE_CHROMA_H1V2))
3215 src_h_tmp >>= 1;
3216 }
3217
Clarence Ip172033f2017-06-13 10:52:56 -04003218 hor_req_pixels = pstate->pixel_ext.roi_w[i];
3219 vert_req_pixels = pstate->pixel_ext.roi_h[i];
Clarence Ip059c8c32017-06-06 17:15:54 -04003220
3221 hor_fetch_pixels = DECIMATED_DIMENSION(src_w_tmp +
Clarence Ip172033f2017-06-13 10:52:56 -04003222 (int8_t)(pstate->pixel_ext.left_ftch[i] & 0xFF) +
3223 (int8_t)(pstate->pixel_ext.right_ftch[i] & 0xFF),
3224 deci_w);
Clarence Ip059c8c32017-06-06 17:15:54 -04003225 vert_fetch_pixels = DECIMATED_DIMENSION(src_h_tmp +
Clarence Ip172033f2017-06-13 10:52:56 -04003226 (int8_t)(pstate->pixel_ext.top_ftch[i] & 0xFF) +
3227 (int8_t)(pstate->pixel_ext.btm_ftch[i] & 0xFF),
3228 deci_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04003229
3230 if ((hor_req_pixels != hor_fetch_pixels) ||
3231 (hor_fetch_pixels > img_w) ||
3232 (vert_req_pixels != vert_fetch_pixels) ||
3233 (vert_fetch_pixels > img_h)) {
3234 SDE_ERROR_PLANE(psde,
3235 "req %d/%d, fetch %d/%d, src %dx%d\n",
3236 hor_req_pixels, vert_req_pixels,
3237 hor_fetch_pixels, vert_fetch_pixels,
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003238 img_w, img_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04003239 return -EINVAL;
3240 }
3241
3242 /*
3243 * Alpha plane can only be scaled using bilinear or pixel
3244 * repeat/drop, src_width and src_height are only specified
3245 * for Y and UV plane
3246 */
3247 if (i != 3 &&
Clarence Ip172033f2017-06-13 10:52:56 -04003248 (hor_req_pixels != pstate->scaler3_cfg.src_width[i] ||
3249 vert_req_pixels != pstate->scaler3_cfg.src_height[i])) {
Clarence Ip059c8c32017-06-06 17:15:54 -04003250 SDE_ERROR_PLANE(psde,
3251 "roi[%d] %d/%d, scaler src %dx%d, src %dx%d\n",
Clarence Ip172033f2017-06-13 10:52:56 -04003252 i, pstate->pixel_ext.roi_w[i],
3253 pstate->pixel_ext.roi_h[i],
3254 pstate->scaler3_cfg.src_width[i],
3255 pstate->scaler3_cfg.src_height[i],
Clarence Ip059c8c32017-06-06 17:15:54 -04003256 src_w, src_h);
3257 return -EINVAL;
3258 }
3259 }
3260
Clarence Ip172033f2017-06-13 10:52:56 -04003261 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
Clarence Ip059c8c32017-06-06 17:15:54 -04003262 return 0;
3263}
3264
Alan Kwong4dd64c82017-02-04 18:41:51 -08003265static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003266 struct drm_plane_state *state)
3267{
Clarence Ipdedbba92016-09-27 17:43:10 -04003268 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04003269 struct sde_plane *psde;
3270 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003271 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04003272 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003273 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04003274 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003275 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
3276 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04003277
3278 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003279 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3280 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04003281 ret = -EINVAL;
3282 goto exit;
3283 }
3284
3285 psde = to_sde_plane(plane);
3286 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003287 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04003288
3289 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003290 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003291 ret = -EINVAL;
3292 goto exit;
3293 }
3294
Clarence Ipdedbba92016-09-27 17:43:10 -04003295 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
3296 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04003297
3298 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08003299 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3300 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07003301 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
3302 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04003303
Dhaval Patel47302cf2016-08-18 15:04:28 -07003304 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
3305 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04003306
Dhaval Patel47302cf2016-08-18 15:04:28 -07003307 max_upscale = psde->pipe_sblk->maxupscale;
3308 max_downscale = psde->pipe_sblk->maxdwnscale;
3309 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04003310
Clarence Ip13a8cf42016-09-29 17:27:47 -04003311 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003312 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003313
Dhaval Patel47302cf2016-08-18 15:04:28 -07003314 if (!sde_plane_enabled(state))
3315 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04003316
Alan Kwong4dd64c82017-02-04 18:41:51 -08003317 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07003318 "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 -08003319 plane->base.id, rstate->sequence_id,
3320 rstate->out_rotation,
3321 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07003322 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08003323 rstate->out_fb_modifier[0],
3324 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3325 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3326 state->crtc_w, state->crtc_h,
3327 state->crtc_x, state->crtc_y);
3328
Dhaval Patel47302cf2016-08-18 15:04:28 -07003329 fmt = to_sde_format(msm_framebuffer_format(state->fb));
3330
3331 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
3332
3333 if (SDE_FORMAT_IS_YUV(fmt) &&
3334 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04003335 !(psde->features & (BIT(SDE_SSPP_CSC)
3336 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003337 SDE_ERROR_PLANE(psde,
3338 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07003339 ret = -EINVAL;
3340
3341 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08003342 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
3343 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07003344 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08003345 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
3346 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003347 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003348 src.x, src.y, src.w, src.h);
3349 ret = -E2BIG;
3350
3351 /* valid yuv image */
3352 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
3353 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003354 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003355 src.x, src.y, src.w, src.h);
3356 ret = -EINVAL;
3357
3358 /* min dst support */
3359 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003360 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003361 dst.x, dst.y, dst.w, dst.h);
3362 ret = -EINVAL;
3363
3364 /* decimation validation */
3365 } else if (deci_w || deci_h) {
3366 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
3367 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003368 SDE_ERROR_PLANE(psde,
3369 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003370 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003371 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003372 SDE_ERROR_PLANE(psde,
3373 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003374 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003375 }
3376
Dhaval Patel47302cf2016-08-18 15:04:28 -07003377 } else if (!(psde->features & SDE_SSPP_SCALER) &&
3378 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003379 SDE_ERROR_PLANE(psde,
3380 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003381 src.w, src.h, dst.w, dst.h);
3382 ret = -EINVAL;
3383
3384 /* check decimated source width */
3385 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003386 SDE_ERROR_PLANE(psde,
3387 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003388 src.w, src_deci_w, max_linewidth);
3389 ret = -E2BIG;
3390
3391 /* check max scaler capability */
3392 } else if (((src_deci_w * max_upscale) < dst.w) ||
3393 ((src_deci_h * max_upscale) < dst.h) ||
3394 ((dst.w * max_downscale) < src_deci_w) ||
3395 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003396 SDE_ERROR_PLANE(psde,
3397 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003398 src_deci_w, src_deci_h, dst.w, dst.h);
3399 ret = -E2BIG;
Clarence Ip172033f2017-06-13 10:52:56 -04003400 } else if (_sde_plane_validate_scaler_v2(psde, pstate, fmt,
Clarence Ip059c8c32017-06-06 17:15:54 -04003401 rstate->out_fb_width,
3402 rstate->out_fb_height,
3403 src.w, src.h, deci_w, deci_h)) {
3404 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003405 }
3406
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003407 /* check excl rect configs */
Clarence Ip059c8c32017-06-06 17:15:54 -04003408 if (!ret && pstate->excl_rect.w && pstate->excl_rect.h) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003409 struct sde_rect intersect;
3410
3411 /*
3412 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003413 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003414 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05003415 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003416 if (intersect.w != pstate->excl_rect.w ||
3417 intersect.h != pstate->excl_rect.h ||
3418 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003419 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07003420 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003421 pstate->excl_rect.x, pstate->excl_rect.y,
3422 pstate->excl_rect.w, pstate->excl_rect.h,
3423 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07003424 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003425 ret = -EINVAL;
3426 }
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003427 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3428 pstate->excl_rect.x, pstate->excl_rect.y,
3429 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003430 }
3431
Dhaval Patel47302cf2016-08-18 15:04:28 -07003432modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003433 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08003434 _sde_plane_sspp_atomic_check_mode_changed(psde,
3435 state, plane->state);
3436exit:
3437 return ret;
3438}
3439
3440static int sde_plane_atomic_check(struct drm_plane *plane,
3441 struct drm_plane_state *state)
3442{
3443 int ret = 0;
3444 struct sde_plane *psde;
3445 struct sde_plane_state *pstate;
3446
3447 if (!plane || !state) {
3448 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3449 plane != 0, state != 0);
3450 ret = -EINVAL;
3451 goto exit;
3452 }
3453
3454 psde = to_sde_plane(plane);
3455 pstate = to_sde_plane_state(state);
3456
3457 SDE_DEBUG_PLANE(psde, "\n");
3458
3459 ret = sde_plane_rot_atomic_check(plane, state);
3460 if (ret)
3461 goto exit;
3462
3463 ret = sde_plane_sspp_atomic_check(plane, state);
3464
Clarence Ipdbde9832016-06-26 09:48:36 -04003465exit:
3466 return ret;
3467}
3468
Clarence Ipcae1bb62016-07-07 12:07:13 -04003469void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04003470{
Clarence Ipcae1bb62016-07-07 12:07:13 -04003471 struct sde_plane *psde;
Clarence Ipddbf7752017-05-21 18:07:30 -04003472 struct sde_plane_state *pstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -04003473
Clarence Ipddbf7752017-05-21 18:07:30 -04003474 if (!plane || !plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003475 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04003476 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003477 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04003478
3479 psde = to_sde_plane(plane);
Clarence Ipddbf7752017-05-21 18:07:30 -04003480 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003481
3482 /*
3483 * These updates have to be done immediately before the plane flush
3484 * timing, and may not be moved to the atomic_update/mode_set functions.
3485 */
3486 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05003487 /* force white frame with 100% alpha pipe output on error */
3488 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003489 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
3490 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04003491 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003492 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
3493 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
3494
3495 /* flag h/w flush complete */
3496 if (plane->state)
Clarence Ipddbf7752017-05-21 18:07:30 -04003497 pstate->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003498}
3499
Abhijit Kulkarni1b3340c2017-06-22 12:39:37 -07003500/**
3501 * sde_plane_set_error: enable/disable error condition
3502 * @plane: pointer to drm_plane structure
3503 */
3504void sde_plane_set_error(struct drm_plane *plane, bool error)
3505{
3506 struct sde_plane *psde;
3507
3508 if (!plane)
3509 return;
3510
3511 psde = to_sde_plane(plane);
3512 psde->is_error = error;
3513}
3514
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003515static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
3516 struct drm_plane_state *old_state)
3517{
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003518 uint32_t nplanes, src_flags;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003519 struct sde_plane *psde;
3520 struct drm_plane_state *state;
3521 struct sde_plane_state *pstate;
3522 struct sde_plane_state *old_pstate;
3523 struct sde_plane_rot_state *rstate;
3524 const struct sde_format *fmt;
3525 struct drm_crtc *crtc;
3526 struct drm_framebuffer *fb;
3527 struct sde_rect src, dst;
3528 const struct sde_rect *crtc_roi;
3529 bool q16_data = true;
3530 int idx;
3531
3532 if (!plane) {
3533 SDE_ERROR("invalid plane\n");
3534 return -EINVAL;
3535 } else if (!plane->state) {
3536 SDE_ERROR("invalid plane state\n");
3537 return -EINVAL;
3538 } else if (!old_state) {
3539 SDE_ERROR("invalid old state\n");
3540 return -EINVAL;
3541 }
3542
3543 psde = to_sde_plane(plane);
3544 state = plane->state;
3545
3546 pstate = to_sde_plane_state(state);
3547 rstate = &pstate->rot;
3548
3549 old_pstate = to_sde_plane_state(old_state);
3550
3551 crtc = state->crtc;
3552 fb = rstate->out_fb;
3553 if (!crtc || !fb) {
3554 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
3555 crtc != 0, fb != 0);
3556 return -EINVAL;
3557 }
3558 fmt = to_sde_format(msm_framebuffer_format(fb));
3559 nplanes = fmt->num_planes;
3560
3561 SDE_DEBUG(
3562 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
3563 plane->base.id, rstate->sequence_id,
3564 rstate->out_fb_width, rstate->out_fb_height,
3565 (char *) &rstate->out_fb_pixel_format,
3566 rstate->out_fb_modifier[0],
3567 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3568 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3569 rstate->out_rotation,
3570 state->crtc_w, state->crtc_h,
3571 state->crtc_x, state->crtc_y);
3572
3573 /* force reprogramming of all the parameters, if the flag is set */
3574 if (psde->revalidate) {
3575 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
3576 plane->base.id);
3577 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3578 psde->revalidate = false;
3579 }
3580
3581 /* determine what needs to be refreshed */
Clarence Ip4a2955d2017-07-04 18:04:33 -04003582 while ((idx = msm_property_pop_dirty(&psde->property_info,
3583 &pstate->property_state)) >= 0) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003584 switch (idx) {
3585 case PLANE_PROP_SCALER_V1:
3586 case PLANE_PROP_SCALER_V2:
Clarence Ip059c8c32017-06-06 17:15:54 -04003587 case PLANE_PROP_SCALER_LUT_ED:
3588 case PLANE_PROP_SCALER_LUT_CIR:
3589 case PLANE_PROP_SCALER_LUT_SEP:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003590 case PLANE_PROP_H_DECIMATE:
3591 case PLANE_PROP_V_DECIMATE:
3592 case PLANE_PROP_SRC_CONFIG:
3593 case PLANE_PROP_ZPOS:
3594 case PLANE_PROP_EXCL_RECT_V1:
3595 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3596 break;
3597 case PLANE_PROP_CSC_V1:
3598 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3599 break;
3600 case PLANE_PROP_COLOR_FILL:
3601 /* potentially need to refresh everything */
3602 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3603 break;
3604 case PLANE_PROP_ROTATION:
3605 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3606 break;
3607 case PLANE_PROP_INFO:
3608 case PLANE_PROP_ALPHA:
3609 case PLANE_PROP_INPUT_FENCE:
3610 case PLANE_PROP_BLEND_OP:
3611 /* no special action required */
3612 break;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003613 case PLANE_PROP_FB_TRANSLATION_MODE:
3614 pstate->dirty |= SDE_PLANE_DIRTY_FB_TRANSLATION_MODE;
3615 break;
Alan Kwong2349d742017-04-20 08:27:30 -07003616 case PLANE_PROP_PREFILL_SIZE:
3617 case PLANE_PROP_PREFILL_TIME:
3618 pstate->dirty |= SDE_PLANE_DIRTY_PERF;
3619 break;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003620 case PLANE_PROP_ROT_DST_X:
3621 case PLANE_PROP_ROT_DST_Y:
3622 case PLANE_PROP_ROT_DST_W:
3623 case PLANE_PROP_ROT_DST_H:
3624 /* handled by rotator atomic update */
3625 break;
3626 default:
3627 /* unknown property, refresh everything */
3628 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
3629 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
3630 break;
3631 }
3632 }
3633
3634 /**
3635 * since plane_atomic_check is invoked before crtc_atomic_check
3636 * in the commit sequence, all the parameters for updating the
3637 * plane dirty flag will not be available during
3638 * plane_atomic_check as some features params are updated
3639 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
3640 * before sspp update.
3641 */
3642 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
3643 old_state);
3644
3645 /* re-program the output rects always in the case of partial update */
3646 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
3647 if (!sde_kms_rect_is_null(crtc_roi))
3648 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3649
3650 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
3651 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
3652
3653 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
3654
3655 /* early out if nothing dirty */
3656 if (!pstate->dirty)
3657 return 0;
3658 pstate->pending = true;
3659
3660 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
3661 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3662
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003663 /* update secure session flag */
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003664 if (pstate->dirty & SDE_PLANE_DIRTY_FB_TRANSLATION_MODE) {
3665 bool enable = false;
3666 int mode = sde_plane_get_property(pstate,
3667 PLANE_PROP_FB_TRANSLATION_MODE);
3668
3669 if ((mode == SDE_DRM_FB_SEC) ||
3670 (mode == SDE_DRM_FB_SEC_DIR_TRANS))
3671 enable = true;
3672 /* update secure session flag */
3673 psde->pipe_hw->ops.setup_secure_address(psde->pipe_hw,
3674 pstate->multirect_index,
3675 enable);
3676 }
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003677
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003678 /* update roi config */
3679 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
3680 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3681 rstate->out_src_w, rstate->out_src_h, q16_data);
3682 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
3683 state->crtc_w, state->crtc_h, !q16_data);
3684
3685 SDE_DEBUG_PLANE(psde,
3686 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
3687 fb->base.id, src.x, src.y, src.w, src.h,
3688 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
3689 (char *)&fmt->base.pixel_format,
3690 SDE_FORMAT_IS_UBWC(fmt));
3691
3692 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
3693 BIT(SDE_DRM_DEINTERLACE)) {
3694 SDE_DEBUG_PLANE(psde, "deinterlace\n");
3695 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
3696 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
3697 src.h /= 2;
3698 src.y = DIV_ROUND_UP(src.y, 2);
3699 src.y &= ~0x1;
3700 }
3701
3702 /*
3703 * adjust layer mixer position of the sspp in the presence
3704 * of a partial update to the active lm origin
3705 */
3706 dst.x -= crtc_roi->x;
3707 dst.y -= crtc_roi->y;
3708
3709 psde->pipe_cfg.src_rect = src;
3710 psde->pipe_cfg.dst_rect = dst;
3711
Clarence Ip172033f2017-06-13 10:52:56 -04003712 _sde_plane_setup_scaler(psde, pstate, fmt, false);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003713
3714 /* check for color fill */
3715 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
3716 PLANE_PROP_COLOR_FILL);
3717 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
3718 /* skip remaining processing on color fill */
3719 pstate->dirty = 0x0;
3720 } else if (psde->pipe_hw->ops.setup_rects) {
3721 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
3722 &psde->pipe_cfg,
3723 pstate->multirect_index);
3724 }
3725
Jeykumar Sankaran0532e0a2017-06-11 20:34:44 -07003726 if (psde->pipe_hw->ops.setup_pe &&
3727 (pstate->multirect_index != SDE_SSPP_RECT_1))
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003728 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04003729 &pstate->pixel_ext);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003730
3731 /**
3732 * when programmed in multirect mode, scalar block will be
3733 * bypassed. Still we need to update alpha and bitwidth
3734 * ONLY for RECT0
3735 */
3736 if (psde->pipe_hw->ops.setup_scaler &&
3737 pstate->multirect_index != SDE_SSPP_RECT_1)
3738 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04003739 &psde->pipe_cfg, &pstate->pixel_ext,
3740 &pstate->scaler3_cfg);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003741
3742 /* update excl rect */
3743 if (psde->pipe_hw->ops.setup_excl_rect)
3744 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
3745 &pstate->excl_rect,
3746 pstate->multirect_index);
3747
3748 if (psde->pipe_hw->ops.setup_multirect)
3749 psde->pipe_hw->ops.setup_multirect(
3750 psde->pipe_hw,
3751 pstate->multirect_index,
3752 pstate->multirect_mode);
3753 }
3754
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003755 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003756 psde->pipe_hw->ops.setup_format) {
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003757 src_flags = 0x0;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003758 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
3759 if (rstate->out_rotation & DRM_REFLECT_X)
3760 src_flags |= SDE_SSPP_FLIP_LR;
3761 if (rstate->out_rotation & DRM_REFLECT_Y)
3762 src_flags |= SDE_SSPP_FLIP_UD;
3763
3764 /* update format */
3765 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
3766 pstate->multirect_index);
3767
Alan Kwong143f50c2017-04-28 07:34:28 -07003768 if (psde->pipe_hw->ops.setup_cdp) {
3769 struct sde_hw_pipe_cdp_cfg *cdp_cfg = &pstate->cdp_cfg;
3770
3771 memset(cdp_cfg, 0, sizeof(struct sde_hw_pipe_cdp_cfg));
3772
3773 cdp_cfg->enable = psde->catalog->perf.cdp_cfg
3774 [SDE_PERF_CDP_USAGE_RT].rd_enable;
3775 cdp_cfg->ubwc_meta_enable =
3776 SDE_FORMAT_IS_UBWC(fmt);
3777 cdp_cfg->tile_amortize_enable =
3778 SDE_FORMAT_IS_UBWC(fmt) ||
3779 SDE_FORMAT_IS_TILE(fmt);
3780 cdp_cfg->preload_ahead = SDE_WB_CDP_PRELOAD_AHEAD_64;
3781
Alan Kwong1b6b4572017-09-25 15:58:14 -04003782 psde->pipe_hw->ops.setup_cdp(psde->pipe_hw, cdp_cfg,
3783 pstate->multirect_index);
Alan Kwong143f50c2017-04-28 07:34:28 -07003784 }
3785
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003786 if (psde->pipe_hw->ops.setup_sys_cache) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04003787 if (rstate->out_sbuf && rstate->rot_hw) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003788 if (rstate->nplane < 2)
3789 pstate->sc_cfg.op_mode =
3790 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
3791 else if (rstate->out_xpos == 0)
3792 pstate->sc_cfg.op_mode =
3793 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
3794 else
3795 pstate->sc_cfg.op_mode =
3796 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
3797
3798 pstate->sc_cfg.rd_en = true;
3799 pstate->sc_cfg.rd_scid =
3800 rstate->rot_hw->caps->scid;
3801 pstate->sc_cfg.rd_noallocate = true;
3802 pstate->sc_cfg.rd_op_type =
3803 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3804 } else {
3805 pstate->sc_cfg.op_mode =
3806 SDE_PIPE_SC_OP_MODE_OFFLINE;
3807 pstate->sc_cfg.rd_en = false;
3808 pstate->sc_cfg.rd_scid = 0;
Clarence Ipd02440b2017-05-21 18:10:01 -04003809 pstate->sc_cfg.rd_noallocate = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003810 pstate->sc_cfg.rd_op_type =
3811 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3812 }
3813
3814 psde->pipe_hw->ops.setup_sys_cache(
3815 psde->pipe_hw, &pstate->sc_cfg);
3816 }
3817
3818 /* update csc */
3819 if (SDE_FORMAT_IS_YUV(fmt))
3820 _sde_plane_setup_csc(psde);
3821 else
3822 psde->csc_ptr = 0;
3823 }
3824
3825 sde_color_process_plane_setup(plane);
3826
3827 /* update sharpening */
3828 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3829 psde->pipe_hw->ops.setup_sharpening) {
3830 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3831 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3832 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3833 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3834
3835 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3836 &psde->sharp_cfg);
3837 }
3838
3839 _sde_plane_set_qos_lut(plane, fb);
3840 _sde_plane_set_danger_lut(plane, fb);
3841
3842 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3843 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3844 _sde_plane_set_ot_limit(plane, crtc);
Alan Kwong2349d742017-04-20 08:27:30 -07003845 if (pstate->dirty & SDE_PLANE_DIRTY_PERF)
3846 _sde_plane_set_ts_prefill(plane, pstate);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003847 }
3848
Alan Kwonga62eeb82017-04-19 08:57:55 -07003849 _sde_plane_set_qos_remap(plane);
3850
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003851 /* clear dirty */
3852 pstate->dirty = 0x0;
3853
3854 return 0;
3855}
3856
Clarence Ipc652ccf2017-06-28 18:21:18 -04003857static void _sde_plane_atomic_disable(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003858 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003859{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003860 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003861 struct drm_plane_state *state;
3862 struct sde_plane_state *pstate;
Clarence Ipc652ccf2017-06-28 18:21:18 -04003863
3864 if (!plane) {
3865 SDE_ERROR("invalid plane\n");
3866 return;
3867 } else if (!plane->state) {
3868 SDE_ERROR("invalid plane state\n");
3869 return;
3870 } else if (!old_state) {
3871 SDE_ERROR("invalid old state\n");
3872 return;
3873 }
3874
3875 psde = to_sde_plane(plane);
3876 state = plane->state;
3877 pstate = to_sde_plane_state(state);
3878
3879 SDE_EVT32(DRMID(plane), is_sde_plane_virtual(plane),
3880 pstate->multirect_mode);
3881
3882 pstate->pending = true;
3883
3884 if (is_sde_plane_virtual(plane) &&
3885 psde->pipe_hw && psde->pipe_hw->ops.setup_multirect)
3886 psde->pipe_hw->ops.setup_multirect(psde->pipe_hw,
3887 SDE_SSPP_RECT_SOLO, SDE_SSPP_MULTIRECT_NONE);
3888}
3889
3890static void sde_plane_atomic_update(struct drm_plane *plane,
3891 struct drm_plane_state *old_state)
3892{
3893 struct sde_plane *psde;
3894 struct drm_plane_state *state;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003895
Clarence Ip13a8cf42016-09-29 17:27:47 -04003896 if (!plane) {
3897 SDE_ERROR("invalid plane\n");
3898 return;
3899 } else if (!plane->state) {
3900 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003901 return;
3902 }
3903
Clarence Ip13a8cf42016-09-29 17:27:47 -04003904 psde = to_sde_plane(plane);
3905 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003906 state = plane->state;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003907
Clarence Ip13a8cf42016-09-29 17:27:47 -04003908 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003909
Alan Kwong4dd64c82017-02-04 18:41:51 -08003910 sde_plane_rot_atomic_update(plane, old_state);
3911
3912 if (!sde_plane_sspp_enabled(state)) {
Clarence Ipc652ccf2017-06-28 18:21:18 -04003913 _sde_plane_atomic_disable(plane, old_state);
Clarence Ip282dad62016-09-27 17:07:35 -04003914 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003915 int ret;
3916
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003917 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003918 /* atomic_check should have ensured that this doesn't fail */
3919 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003920 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003921}
3922
Alan Kwong346223e2017-06-30 15:29:22 -04003923void sde_plane_restore(struct drm_plane *plane)
3924{
3925 struct sde_plane *psde;
3926
3927 if (!plane || !plane->state) {
3928 SDE_ERROR("invalid plane\n");
3929 return;
3930 }
3931
3932 psde = to_sde_plane(plane);
3933
3934 /*
3935 * Revalidate is only true here if idle PC occurred and
3936 * there is no plane state update in current commit cycle.
3937 */
3938 if (!psde->revalidate)
3939 return;
3940
3941 SDE_DEBUG_PLANE(psde, "\n");
3942
3943 /* last plane state is same as current state */
3944 sde_plane_atomic_update(plane, plane->state);
3945}
Dhaval Patel47302cf2016-08-18 15:04:28 -07003946
Lloyd Atkinsone08229c2017-10-02 17:53:30 -04003947int sde_plane_helper_reset_custom_properties(struct drm_plane *plane,
3948 struct drm_plane_state *plane_state)
3949{
3950 struct sde_plane *psde;
3951 struct sde_plane_state *pstate;
3952 struct drm_property *drm_prop;
3953 enum msm_mdp_plane_property prop_idx;
3954
3955 if (!plane || !plane_state) {
3956 SDE_ERROR("invalid params\n");
3957 return -EINVAL;
3958 }
3959
3960 psde = to_sde_plane(plane);
3961 pstate = to_sde_plane_state(plane_state);
3962
3963 for (prop_idx = 0; prop_idx < PLANE_PROP_COUNT; prop_idx++) {
3964 uint64_t val = pstate->property_values[prop_idx].value;
3965 uint64_t def;
3966 int ret;
3967
3968 drm_prop = msm_property_index_to_drm_property(
3969 &psde->property_info, prop_idx);
3970 if (!drm_prop) {
3971 /* not all props will be installed, based on caps */
3972 SDE_DEBUG_PLANE(psde, "invalid property index %d\n",
3973 prop_idx);
3974 continue;
3975 }
3976
3977 def = msm_property_get_default(&psde->property_info, prop_idx);
3978 if (val == def)
3979 continue;
3980
3981 SDE_DEBUG_PLANE(psde, "set prop %s idx %d from %llu to %llu\n",
3982 drm_prop->name, prop_idx, val, def);
3983
3984 ret = drm_atomic_plane_set_property(plane, plane_state,
3985 drm_prop, def);
3986 if (ret) {
3987 SDE_ERROR_PLANE(psde,
3988 "set property failed, idx %d ret %d\n",
3989 prop_idx, ret);
3990 continue;
3991 }
3992 }
3993
3994 return 0;
3995}
3996
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003997/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07003998static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08003999 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004000{
Clarence Ip5e2a9222016-06-26 22:38:24 -04004001 static const struct drm_prop_enum_list e_blend_op[] = {
4002 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
4003 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
4004 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
4005 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
4006 };
4007 static const struct drm_prop_enum_list e_src_config[] = {
4008 {SDE_DRM_DEINTERLACE, "deinterlace"}
4009 };
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07004010 static const struct drm_prop_enum_list e_fb_translation_mode[] = {
4011 {SDE_DRM_FB_NON_SEC, "non_sec"},
4012 {SDE_DRM_FB_SEC, "sec"},
4013 {SDE_DRM_FB_NON_SEC_DIR_TRANS, "non_sec_direct_translation"},
4014 {SDE_DRM_FB_SEC_DIR_TRANS, "sec_direct_translation"},
4015 };
Clarence Ipea3d6262016-07-15 16:20:11 -04004016 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07004017 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04004018 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04004019 int zpos_max = 255;
4020 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07004021 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004022
Clarence Ip13a8cf42016-09-29 17:27:47 -04004023 if (!plane || !psde) {
4024 SDE_ERROR("invalid plane\n");
4025 return;
4026 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
4027 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
4028 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004029 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04004030 } else if (!catalog) {
4031 SDE_ERROR("invalid catalog\n");
4032 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04004033 }
4034
Alan Kwong4dd64c82017-02-04 18:41:51 -08004035 psde->catalog = catalog;
4036
Clarence Ipc47a0692016-10-11 10:54:17 -04004037 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04004038 if (catalog->mixer_count && catalog->mixer &&
4039 catalog->mixer[0].sblk->maxblendstages) {
4040 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
4041 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
4042 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
4043 }
Clarence Ipc47a0692016-10-11 10:54:17 -04004044 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
4045 /* reserve zpos == 0 for primary planes */
4046 zpos_def = drm_plane_index(plane) + 1;
4047 }
4048
4049 msm_property_install_range(&psde->property_info, "zpos",
4050 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004051
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04004052 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07004053 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004054
Dhaval Patel47302cf2016-08-18 15:04:28 -07004055 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04004056 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07004057 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004058
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004059 if (!master_plane_id) {
4060 if (psde->pipe_sblk->maxhdeciexp) {
4061 msm_property_install_range(&psde->property_info,
4062 "h_decimate", 0x0, 0,
4063 psde->pipe_sblk->maxhdeciexp, 0,
4064 PLANE_PROP_H_DECIMATE);
4065 }
Clarence Ipdedbba92016-09-27 17:43:10 -04004066
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004067 if (psde->pipe_sblk->maxvdeciexp) {
4068 msm_property_install_range(&psde->property_info,
4069 "v_decimate", 0x0, 0,
4070 psde->pipe_sblk->maxvdeciexp, 0,
4071 PLANE_PROP_V_DECIMATE);
4072 }
Clarence Ipdedbba92016-09-27 17:43:10 -04004073
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004074 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004075 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004076 &psde->property_info, "scaler_v2",
4077 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
4078 msm_property_install_blob(&psde->property_info,
4079 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
4080 msm_property_install_blob(&psde->property_info,
4081 "lut_cir", 0,
4082 PLANE_PROP_SCALER_LUT_CIR);
4083 msm_property_install_blob(&psde->property_info,
4084 "lut_sep", 0,
4085 PLANE_PROP_SCALER_LUT_SEP);
4086 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004087 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004088 &psde->property_info, "scaler_v1", 0x0,
4089 0, ~0, 0, PLANE_PROP_SCALER_V1);
4090 }
Clarence Ipb43d4592016-09-08 14:21:35 -04004091
Dhaval Patel0aee0972017-02-08 19:00:58 -08004092 if (psde->features & BIT(SDE_SSPP_CSC) ||
4093 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004094 msm_property_install_volatile_range(
4095 &psde->property_info, "csc_v1", 0x0,
4096 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004097
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004098 if (psde->features & BIT(SDE_SSPP_HSIC)) {
4099 snprintf(feature_name, sizeof(feature_name), "%s%d",
4100 "SDE_SSPP_HUE_V",
4101 psde->pipe_sblk->hsic_blk.version >> 16);
4102 msm_property_install_range(&psde->property_info,
4103 feature_name, 0, 0, 0xFFFFFFFF, 0,
4104 PLANE_PROP_HUE_ADJUST);
4105 snprintf(feature_name, sizeof(feature_name), "%s%d",
4106 "SDE_SSPP_SATURATION_V",
4107 psde->pipe_sblk->hsic_blk.version >> 16);
4108 msm_property_install_range(&psde->property_info,
4109 feature_name, 0, 0, 0xFFFFFFFF, 0,
4110 PLANE_PROP_SATURATION_ADJUST);
4111 snprintf(feature_name, sizeof(feature_name), "%s%d",
4112 "SDE_SSPP_VALUE_V",
4113 psde->pipe_sblk->hsic_blk.version >> 16);
4114 msm_property_install_range(&psde->property_info,
4115 feature_name, 0, 0, 0xFFFFFFFF, 0,
4116 PLANE_PROP_VALUE_ADJUST);
4117 snprintf(feature_name, sizeof(feature_name), "%s%d",
4118 "SDE_SSPP_CONTRAST_V",
4119 psde->pipe_sblk->hsic_blk.version >> 16);
4120 msm_property_install_range(&psde->property_info,
4121 feature_name, 0, 0, 0xFFFFFFFF, 0,
4122 PLANE_PROP_CONTRAST_ADJUST);
4123 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07004124 }
4125
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004126 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
4127 msm_property_install_volatile_range(&psde->property_info,
4128 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
4129
Alan Kwong4dd64c82017-02-04 18:41:51 -08004130 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004131
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04004132 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07004133 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004134
Dhaval Patel47302cf2016-08-18 15:04:28 -07004135 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
4136 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
4137
4138 if (psde->pipe_hw->ops.setup_solidfill)
4139 msm_property_install_range(&psde->property_info, "color_fill",
4140 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
4141
Alan Kwong2349d742017-04-20 08:27:30 -07004142 msm_property_install_range(&psde->property_info,
4143 "prefill_size", 0x0, 0, ~0, 0,
4144 PLANE_PROP_PREFILL_SIZE);
4145 msm_property_install_range(&psde->property_info,
4146 "prefill_time", 0x0, 0, ~0, 0,
4147 PLANE_PROP_PREFILL_TIME);
4148
Dhaval Patel4e574842016-08-23 15:11:37 -07004149 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004150 if (!info) {
4151 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07004152 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004153 }
Dhaval Patel4e574842016-08-23 15:11:37 -07004154
4155 msm_property_install_blob(&psde->property_info, "capabilities",
4156 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
4157 sde_kms_info_reset(info);
4158
Steve Cohen57428172017-07-18 10:57:17 -04004159 if (!master_plane_id) {
4160 format_list = psde->pipe_sblk->format_list;
4161 } else {
4162 format_list = psde->pipe_sblk->virt_format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004163 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004164 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004165 }
4166
Clarence Ipea3d6262016-07-15 16:20:11 -04004167 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04004168 sde_kms_info_start(info, "pixel_formats");
4169 while (format_list->fourcc_format) {
4170 sde_kms_info_append_format(info,
4171 format_list->fourcc_format,
4172 format_list->modifier);
4173 ++format_list;
4174 }
4175 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04004176 }
Dhaval Patel4e574842016-08-23 15:11:37 -07004177
Clarence Ip1db00c12017-07-21 17:42:56 -04004178 if (psde->pipe_hw && psde->pipe_hw->ops.get_scaler_ver)
4179 sde_kms_info_add_keyint(info, "scaler_step_ver",
4180 psde->pipe_hw->ops.get_scaler_ver(psde->pipe_hw));
4181
Dhaval Patel4e574842016-08-23 15:11:37 -07004182 sde_kms_info_add_keyint(info, "max_linewidth",
4183 psde->pipe_sblk->maxlinewidth);
4184 sde_kms_info_add_keyint(info, "max_upscale",
4185 psde->pipe_sblk->maxupscale);
4186 sde_kms_info_add_keyint(info, "max_downscale",
4187 psde->pipe_sblk->maxdwnscale);
4188 sde_kms_info_add_keyint(info, "max_horizontal_deci",
4189 psde->pipe_sblk->maxhdeciexp);
4190 sde_kms_info_add_keyint(info, "max_vertical_deci",
4191 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07004192 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
4193 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07004194 msm_property_set_blob(&psde->property_info, &psde->blob_info,
Narendra Muppalla22d17252017-05-31 15:13:39 -07004195 info->data, SDE_KMS_INFO_DATALEN(info),
4196 PLANE_PROP_INFO);
Dhaval Patel4e574842016-08-23 15:11:37 -07004197
4198 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07004199
4200 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
4201 snprintf(feature_name, sizeof(feature_name), "%s%d",
4202 "SDE_SSPP_SKIN_COLOR_V",
4203 psde->pipe_sblk->memcolor_blk.version >> 16);
4204 msm_property_install_blob(&psde->property_info, feature_name, 0,
4205 PLANE_PROP_SKIN_COLOR);
4206 snprintf(feature_name, sizeof(feature_name), "%s%d",
4207 "SDE_SSPP_SKY_COLOR_V",
4208 psde->pipe_sblk->memcolor_blk.version >> 16);
4209 msm_property_install_blob(&psde->property_info, feature_name, 0,
4210 PLANE_PROP_SKY_COLOR);
4211 snprintf(feature_name, sizeof(feature_name), "%s%d",
4212 "SDE_SSPP_FOLIAGE_COLOR_V",
4213 psde->pipe_sblk->memcolor_blk.version >> 16);
4214 msm_property_install_blob(&psde->property_info, feature_name, 0,
4215 PLANE_PROP_FOLIAGE_COLOR);
4216 }
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07004217
4218 msm_property_install_enum(&psde->property_info, "fb_translation_mode",
4219 0x0,
4220 0, e_fb_translation_mode,
4221 ARRAY_SIZE(e_fb_translation_mode),
4222 PLANE_PROP_FB_TRANSLATION_MODE);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004223}
4224
Clarence Ip5fc00c52016-09-23 15:03:34 -04004225static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
4226{
4227 struct sde_drm_csc_v1 csc_v1;
4228 int i;
4229
4230 if (!psde) {
4231 SDE_ERROR("invalid plane\n");
4232 return;
4233 }
4234
4235 psde->csc_usr_ptr = NULL;
4236 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004237 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04004238 return;
4239 }
4240
4241 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004242 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04004243 return;
4244 }
4245
Clarence Ipb43d4592016-09-08 14:21:35 -04004246 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04004247 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
4248 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
4249 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
4250 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
4251 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
4252 }
4253 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
4254 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
4255 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
4256 }
4257 psde->csc_usr_ptr = &psde->csc_cfg;
4258}
4259
Clarence Ip172033f2017-06-13 10:52:56 -04004260static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde,
4261 struct sde_plane_state *pstate, void *usr)
Clarence Ipb43d4592016-09-08 14:21:35 -04004262{
4263 struct sde_drm_scaler_v1 scale_v1;
4264 struct sde_hw_pixel_ext *pe;
4265 int i;
4266
Clarence Ip172033f2017-06-13 10:52:56 -04004267 if (!psde || !pstate) {
4268 SDE_ERROR("invalid argument(s)\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004269 return;
4270 }
4271
Clarence Ip172033f2017-06-13 10:52:56 -04004272 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
Clarence Ipb43d4592016-09-08 14:21:35 -04004273 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004274 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004275 return;
4276 }
4277
4278 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004279 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004280 return;
4281 }
4282
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004283 /* force property to be dirty, even if the pointer didn't change */
Clarence Ip4a2955d2017-07-04 18:04:33 -04004284 msm_property_set_dirty(&psde->property_info,
4285 &pstate->property_state, PLANE_PROP_SCALER_V1);
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004286
Clarence Ipb43d4592016-09-08 14:21:35 -04004287 /* populate from user space */
Clarence Ip172033f2017-06-13 10:52:56 -04004288 pe = &pstate->pixel_ext;
Clarence Ipb43d4592016-09-08 14:21:35 -04004289 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
4290 for (i = 0; i < SDE_MAX_PLANES; i++) {
4291 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
4292 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
4293 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
4294 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
4295
4296 pe->horz_filter[i] = scale_v1.horz_filter[i];
4297 pe->vert_filter[i] = scale_v1.vert_filter[i];
4298 }
4299 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05004300 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
4301 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
4302 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
4303 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
4304 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04004305
abeykun41060122016-11-28 13:02:01 -05004306 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
4307 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
4308 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
4309 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
4310 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04004311 }
abeykun41060122016-11-28 13:02:01 -05004312
Clarence Ip172033f2017-06-13 10:52:56 -04004313 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
Clarence Ipb43d4592016-09-08 14:21:35 -04004314
Clarence Ip059c8c32017-06-06 17:15:54 -04004315 SDE_EVT32_VERBOSE(DRMID(&psde->base));
Clarence Ip13a8cf42016-09-29 17:27:47 -04004316 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004317}
4318
abeykun48f407a2016-08-25 12:06:44 -04004319static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
4320 struct sde_plane_state *pstate, void *usr)
4321{
4322 struct sde_drm_scaler_v2 scale_v2;
4323 struct sde_hw_pixel_ext *pe;
4324 int i;
4325 struct sde_hw_scaler3_cfg *cfg;
4326
Clarence Ip172033f2017-06-13 10:52:56 -04004327 if (!psde || !pstate) {
4328 SDE_ERROR("invalid argument(s)\n");
abeykun48f407a2016-08-25 12:06:44 -04004329 return;
4330 }
4331
Clarence Ip172033f2017-06-13 10:52:56 -04004332 cfg = &pstate->scaler3_cfg;
4333 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
abeykun48f407a2016-08-25 12:06:44 -04004334 if (!usr) {
4335 SDE_DEBUG_PLANE(psde, "scale data removed\n");
4336 return;
4337 }
4338
4339 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
4340 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
4341 return;
4342 }
4343
Clarence Ip7e892a02017-06-13 10:16:07 -04004344 /* detach/ignore user data if 'disabled' */
4345 if (!scale_v2.enable) {
4346 SDE_DEBUG_PLANE(psde, "scale data removed\n");
4347 return;
4348 }
4349
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004350 /* force property to be dirty, even if the pointer didn't change */
Clarence Ip4a2955d2017-07-04 18:04:33 -04004351 msm_property_set_dirty(&psde->property_info,
4352 &pstate->property_state, PLANE_PROP_SCALER_V2);
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004353
abeykun48f407a2016-08-25 12:06:44 -04004354 /* populate from user space */
Sravanthi Kollukuduru55b24f02017-06-22 15:11:31 +05304355 sde_set_scaler_v2(cfg, &scale_v2);
4356
Clarence Ip172033f2017-06-13 10:52:56 -04004357 pe = &pstate->pixel_ext;
abeykun48f407a2016-08-25 12:06:44 -04004358 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
abeykun48f407a2016-08-25 12:06:44 -04004359
abeykun48f407a2016-08-25 12:06:44 -04004360 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05004361 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
4362 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
4363 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
4364 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
4365 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04004366
abeykun41060122016-11-28 13:02:01 -05004367 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
4368 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
4369 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
4370 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
4371 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04004372 }
Clarence Ip172033f2017-06-13 10:52:56 -04004373 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
abeykun48f407a2016-08-25 12:06:44 -04004374
Clarence Ip059c8c32017-06-06 17:15:54 -04004375 SDE_EVT32_VERBOSE(DRMID(&psde->base), cfg->enable, cfg->de.enable,
4376 cfg->src_width[0], cfg->src_height[0],
4377 cfg->dst_width, cfg->dst_height);
abeykun48f407a2016-08-25 12:06:44 -04004378 SDE_DEBUG_PLANE(psde, "user property data copied\n");
4379}
4380
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004381static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
4382 struct sde_plane_state *pstate, void *usr_ptr)
4383{
4384 struct drm_clip_rect excl_rect_v1;
4385
4386 if (!psde) {
4387 SDE_ERROR("invalid plane\n");
4388 return;
4389 }
4390
4391 if (!usr_ptr) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004392 SDE_DEBUG_PLANE(psde, "invalid excl_rect user data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004393 return;
4394 }
4395
4396 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004397 SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004398 return;
4399 }
4400
4401 /* populate from user space */
4402 pstate->excl_rect.x = excl_rect_v1.x1;
4403 pstate->excl_rect.y = excl_rect_v1.y1;
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004404 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
4405 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
4406
4407 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
4408 pstate->excl_rect.x, pstate->excl_rect.y,
4409 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004410}
4411
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004412static int sde_plane_atomic_set_property(struct drm_plane *plane,
4413 struct drm_plane_state *state, struct drm_property *property,
4414 uint64_t val)
4415{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004416 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004417 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004418 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004419
Clarence Ip13a8cf42016-09-29 17:27:47 -04004420 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004421
4422 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004423 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004424 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004425 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004426 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04004427 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004428 ret = msm_property_atomic_set(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004429 &pstate->property_state, property, val);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004430 if (!ret) {
4431 idx = msm_property_index(&psde->property_info,
4432 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004433 switch (idx) {
4434 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04004435 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004436 break;
4437 case PLANE_PROP_CSC_V1:
4438 _sde_plane_set_csc_v1(psde, (void *)val);
4439 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04004440 case PLANE_PROP_SCALER_V1:
Clarence Ip172033f2017-06-13 10:52:56 -04004441 _sde_plane_set_scaler_v1(psde, pstate,
4442 (void *)val);
Clarence Ipb43d4592016-09-08 14:21:35 -04004443 break;
abeykun48f407a2016-08-25 12:06:44 -04004444 case PLANE_PROP_SCALER_V2:
4445 _sde_plane_set_scaler_v2(psde, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004446 (void *)val);
abeykun48f407a2016-08-25 12:06:44 -04004447 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004448 case PLANE_PROP_EXCL_RECT_V1:
4449 _sde_plane_set_excl_rect_v1(psde, pstate,
4450 (void *)val);
4451 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04004452 default:
4453 /* nothing to do */
4454 break;
4455 }
Clarence Ipe78efb72016-06-24 18:35:21 -04004456 }
4457 }
4458
Alan Kwong4dd64c82017-02-04 18:41:51 -08004459 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
4460 property->name, property->base.id, val, ret);
4461
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004462 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004463}
4464
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004465static int sde_plane_atomic_get_property(struct drm_plane *plane,
4466 const struct drm_plane_state *state,
4467 struct drm_property *property, uint64_t *val)
4468{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004469 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004470 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04004471 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004472
Clarence Ipaa0faf42016-05-30 12:07:48 -04004473 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004474 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004475 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004476 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004477 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004478 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04004479 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004480 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004481 ret = msm_property_atomic_get(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004482 &pstate->property_state, property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04004483 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004484
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004485 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004486}
4487
4488static void sde_plane_destroy(struct drm_plane *plane)
4489{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004490 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004491
Clarence Ip13a8cf42016-09-29 17:27:47 -04004492 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004493
Clarence Ip13a8cf42016-09-29 17:27:47 -04004494 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04004495 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
4496
Dhaval Patel4e574842016-08-23 15:11:37 -07004497 if (psde->blob_info)
4498 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004499 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04004500 mutex_destroy(&psde->lock);
4501
Clarence Ip4ce59322016-06-26 22:27:51 -04004502 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004503
Clarence Ip4ce59322016-06-26 22:27:51 -04004504 /* this will destroy the states as well */
4505 drm_plane_cleanup(plane);
4506
Clarence Ip4c1d9772016-06-26 09:35:38 -04004507 if (psde->pipe_hw)
4508 sde_hw_sspp_destroy(psde->pipe_hw);
4509
Clarence Ip4ce59322016-06-26 22:27:51 -04004510 kfree(psde);
4511 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004512}
4513
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004514static void sde_plane_destroy_state(struct drm_plane *plane,
4515 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004516{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004517 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04004518 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004519
Clarence Ipae4e60c2016-06-26 22:44:04 -04004520 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004521 SDE_ERROR("invalid arg(s), plane %d state %d\n",
4522 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004523 return;
4524 }
4525
Clarence Ipaa0faf42016-05-30 12:07:48 -04004526 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04004527 pstate = to_sde_plane_state(state);
4528
Clarence Ip13a8cf42016-09-29 17:27:47 -04004529 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004530
Alan Kwong4dd64c82017-02-04 18:41:51 -08004531 sde_plane_rot_destroy_state(plane, &pstate->base);
4532
Clarence Ipe78efb72016-06-24 18:35:21 -04004533 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004534 if (state->fb)
4535 drm_framebuffer_unreference(state->fb);
4536
Clarence Ipae4e60c2016-06-26 22:44:04 -04004537 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04004538 if (pstate->input_fence)
4539 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004540
Clarence Ipaa0faf42016-05-30 12:07:48 -04004541 /* destroy value helper */
4542 msm_property_destroy_state(&psde->property_info, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004543 &pstate->property_state);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004544}
4545
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004546static struct drm_plane_state *
4547sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004548{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004549 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004550 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04004551 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04004552 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004553
Clarence Ip13a8cf42016-09-29 17:27:47 -04004554 if (!plane) {
4555 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004556 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004557 } else if (!plane->state) {
4558 SDE_ERROR("invalid plane state\n");
4559 return NULL;
4560 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004561
Clarence Ip730e7192016-06-26 22:45:09 -04004562 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004563 psde = to_sde_plane(plane);
4564 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004565 if (!pstate) {
4566 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004567 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004568 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004569
Clarence Ip13a8cf42016-09-29 17:27:47 -04004570 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004571
4572 /* duplicate value helper */
4573 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004574 &pstate->property_state, pstate->property_values);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004575
Clarence Ip17e908b2016-09-29 15:58:00 -04004576 /* clear out any input fence */
4577 pstate->input_fence = 0;
4578 input_fence_default = msm_property_get_default(
4579 &psde->property_info, PLANE_PROP_INPUT_FENCE);
Clarence Ip4a2955d2017-07-04 18:04:33 -04004580 msm_property_set_property(&psde->property_info,
4581 &pstate->property_state,
Clarence Ip17e908b2016-09-29 15:58:00 -04004582 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004583
Clarence Ip282dad62016-09-27 17:07:35 -04004584 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04004585 pstate->pending = false;
4586
Alan Kwongcdb2f282017-03-18 13:42:06 -07004587 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
4588
Alan Kwong4dd64c82017-02-04 18:41:51 -08004589 sde_plane_rot_duplicate_state(plane, &pstate->base);
4590
Clarence Ip730e7192016-06-26 22:45:09 -04004591 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004592}
4593
4594static void sde_plane_reset(struct drm_plane *plane)
4595{
Clarence Ipae4e60c2016-06-26 22:44:04 -04004596 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004597 struct sde_plane_state *pstate;
4598
Clarence Ipae4e60c2016-06-26 22:44:04 -04004599 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004600 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04004601 return;
4602 }
4603
Clarence Ip730e7192016-06-26 22:45:09 -04004604 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004605 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004606
Veera Sundaram Sankarandb43e282017-09-19 18:32:52 -07004607 if (plane->state && !sde_crtc_is_reset_required(plane->state->crtc)) {
4608 SDE_DEBUG_PLANE(psde, "avoid reset for plane\n");
4609 return;
4610 }
4611
Clarence Ipae4e60c2016-06-26 22:44:04 -04004612 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04004613 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04004614 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004615 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04004616 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004617
Clarence Ipaa0faf42016-05-30 12:07:48 -04004618 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004619 if (!pstate) {
4620 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004621 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004622 }
Clarence Ip730e7192016-06-26 22:45:09 -04004623
Clarence Ipaa0faf42016-05-30 12:07:48 -04004624 /* reset value helper */
4625 msm_property_reset_state(&psde->property_info, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004626 &pstate->property_state,
4627 pstate->property_values);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004628
4629 pstate->base.plane = plane;
4630
4631 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004632}
4633
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004634#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04004635static ssize_t _sde_plane_danger_read(struct file *file,
4636 char __user *buff, size_t count, loff_t *ppos)
4637{
4638 struct sde_kms *kms = file->private_data;
4639 struct sde_mdss_cfg *cfg = kms->catalog;
4640 int len = 0;
4641 char buf[40] = {'\0'};
4642
4643 if (!cfg)
4644 return -ENODEV;
4645
4646 if (*ppos)
4647 return 0; /* the end */
4648
4649 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
4650 if (len < 0 || len >= sizeof(buf))
4651 return 0;
4652
4653 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
4654 return -EFAULT;
4655
4656 *ppos += len; /* increase offset */
4657
4658 return len;
4659}
4660
4661static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
4662{
4663 struct drm_plane *plane;
4664
4665 drm_for_each_plane(plane, kms->dev) {
4666 if (plane->fb && plane->state) {
4667 sde_plane_danger_signal_ctrl(plane, enable);
4668 SDE_DEBUG("plane:%d img:%dx%d ",
4669 plane->base.id, plane->fb->width,
4670 plane->fb->height);
4671 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
4672 plane->state->src_x >> 16,
4673 plane->state->src_y >> 16,
4674 plane->state->src_w >> 16,
4675 plane->state->src_h >> 16,
4676 plane->state->crtc_x, plane->state->crtc_y,
4677 plane->state->crtc_w, plane->state->crtc_h);
4678 } else {
4679 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
4680 }
4681 }
4682}
4683
4684static ssize_t _sde_plane_danger_write(struct file *file,
4685 const char __user *user_buf, size_t count, loff_t *ppos)
4686{
4687 struct sde_kms *kms = file->private_data;
4688 struct sde_mdss_cfg *cfg = kms->catalog;
4689 int disable_panic;
4690 char buf[10];
4691
4692 if (!cfg)
4693 return -EFAULT;
4694
4695 if (count >= sizeof(buf))
4696 return -EFAULT;
4697
4698 if (copy_from_user(buf, user_buf, count))
4699 return -EFAULT;
4700
4701 buf[count] = 0; /* end of string */
4702
4703 if (kstrtoint(buf, 0, &disable_panic))
4704 return -EFAULT;
4705
4706 if (disable_panic) {
4707 /* Disable panic signal for all active pipes */
4708 SDE_DEBUG("Disabling danger:\n");
4709 _sde_plane_set_danger_state(kms, false);
4710 kms->has_danger_ctrl = false;
4711 } else {
4712 /* Enable panic signal for all active pipes */
4713 SDE_DEBUG("Enabling danger:\n");
4714 kms->has_danger_ctrl = true;
4715 _sde_plane_set_danger_state(kms, true);
4716 }
4717
4718 return count;
4719}
4720
4721static const struct file_operations sde_plane_danger_enable = {
4722 .open = simple_open,
4723 .read = _sde_plane_danger_read,
4724 .write = _sde_plane_danger_write,
4725};
4726
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004727static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04004728{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004729 struct sde_plane *psde;
4730 struct sde_kms *kms;
4731 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04004732 const struct sde_sspp_sub_blks *sblk = 0;
4733 const struct sde_sspp_cfg *cfg = 0;
4734
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004735 if (!plane || !plane->dev) {
4736 SDE_ERROR("invalid arguments\n");
4737 return -EINVAL;
4738 }
4739
4740 priv = plane->dev->dev_private;
4741 if (!priv || !priv->kms) {
4742 SDE_ERROR("invalid KMS reference\n");
4743 return -EINVAL;
4744 }
4745
4746 kms = to_sde_kms(priv->kms);
4747 psde = to_sde_plane(plane);
4748
Clarence Ip4ce59322016-06-26 22:27:51 -04004749 if (psde && psde->pipe_hw)
4750 cfg = psde->pipe_hw->cap;
4751 if (cfg)
4752 sblk = cfg->sblk;
4753
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004754 if (!sblk)
4755 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04004756
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004757 /* create overall sub-directory for the pipe */
4758 psde->debugfs_root =
4759 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07004760 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04004761
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004762 if (!psde->debugfs_root)
4763 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04004764
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004765 /* don't error check these */
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004766 debugfs_create_x32("features", 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004767 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004768
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004769 /* add register dump support */
4770 sde_debugfs_setup_regset32(&psde->debugfs_src,
4771 sblk->src_blk.base + cfg->base,
4772 sblk->src_blk.len,
4773 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004774 sde_debugfs_create_regset32("src_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004775 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004776
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004777 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
4778 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
4779 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
4780 sblk->scaler_blk.base + cfg->base,
4781 sblk->scaler_blk.len,
4782 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004783 sde_debugfs_create_regset32("scaler_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004784 psde->debugfs_root,
4785 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07004786 debugfs_create_bool("default_scaling",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004787 0600,
Clarence Ip716ab662017-03-20 06:51:24 -07004788 psde->debugfs_root,
4789 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04004790 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004791
4792 if (cfg->features & BIT(SDE_SSPP_CSC) ||
4793 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
4794 sde_debugfs_setup_regset32(&psde->debugfs_csc,
4795 sblk->csc_blk.base + cfg->base,
4796 sblk->csc_blk.len,
4797 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004798 sde_debugfs_create_regset32("csc_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004799 psde->debugfs_root, &psde->debugfs_csc);
4800 }
4801
4802 debugfs_create_u32("xin_id",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004803 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004804 psde->debugfs_root,
4805 (u32 *) &cfg->xin_id);
4806 debugfs_create_u32("clk_ctrl",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004807 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004808 psde->debugfs_root,
4809 (u32 *) &cfg->clk_ctrl);
4810 debugfs_create_x32("creq_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004811 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004812 psde->debugfs_root,
4813 (u32 *) &sblk->creq_vblank);
4814 debugfs_create_x32("danger_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004815 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004816 psde->debugfs_root,
4817 (u32 *) &sblk->danger_vblank);
4818
4819 debugfs_create_file("disable_danger",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004820 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004821 psde->debugfs_root,
4822 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004823 debugfs_create_u32("sbuf_mode",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004824 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004825 psde->debugfs_root, &psde->sbuf_mode);
4826 debugfs_create_u32("sbuf_writeback",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004827 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004828 psde->debugfs_root,
4829 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004830
4831 return 0;
4832}
4833
4834static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4835{
4836 struct sde_plane *psde;
4837
4838 if (!plane)
4839 return;
4840 psde = to_sde_plane(plane);
4841
4842 debugfs_remove_recursive(psde->debugfs_root);
4843}
4844#else
4845static int _sde_plane_init_debugfs(struct drm_plane *plane)
4846{
4847 return 0;
4848}
4849static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4850{
4851}
4852#endif
4853
4854static int sde_plane_late_register(struct drm_plane *plane)
4855{
4856 return _sde_plane_init_debugfs(plane);
4857}
4858
4859static void sde_plane_early_unregister(struct drm_plane *plane)
4860{
4861 _sde_plane_destroy_debugfs(plane);
4862}
4863
4864static const struct drm_plane_funcs sde_plane_funcs = {
4865 .update_plane = drm_atomic_helper_update_plane,
4866 .disable_plane = drm_atomic_helper_disable_plane,
4867 .destroy = sde_plane_destroy,
Clarence Ip569d5af2017-10-14 21:09:01 -04004868 .set_property = drm_atomic_helper_plane_set_property,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004869 .atomic_set_property = sde_plane_atomic_set_property,
4870 .atomic_get_property = sde_plane_atomic_get_property,
4871 .reset = sde_plane_reset,
4872 .atomic_duplicate_state = sde_plane_duplicate_state,
4873 .atomic_destroy_state = sde_plane_destroy_state,
4874 .late_register = sde_plane_late_register,
4875 .early_unregister = sde_plane_early_unregister,
4876};
4877
4878static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
4879 .prepare_fb = sde_plane_prepare_fb,
4880 .cleanup_fb = sde_plane_cleanup_fb,
4881 .atomic_check = sde_plane_atomic_check,
4882 .atomic_update = sde_plane_atomic_update,
4883};
4884
4885enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
4886{
4887 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
4888}
4889
4890bool is_sde_plane_virtual(struct drm_plane *plane)
4891{
4892 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04004893}
4894
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004895/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04004896struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04004897 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004898 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004899{
Alan Kwongdce56da2017-04-27 15:50:34 -07004900 struct drm_plane *plane = NULL, *master_plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004901 const struct sde_format_extended *format_list;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004902 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004903 struct msm_drm_private *priv;
4904 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004905 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04004906 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004907
4908 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004909 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004910 goto exit;
4911 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004912
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004913 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004914 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004915 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004916 goto exit;
4917 }
4918
4919 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004920 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004921 goto exit;
4922 }
4923 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004924
Clarence Ip4c1d9772016-06-26 09:35:38 -04004925 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004926 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004927 goto exit;
4928 }
4929
Clarence Ip4ce59322016-06-26 22:27:51 -04004930 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004931 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4932 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004933 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004934 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004935 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004936 }
4937
Clarence Ip4c1d9772016-06-26 09:35:38 -04004938 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004939 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004940 psde->pipe = pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004941 psde->is_virtual = (master_plane_id != 0);
Alan Kwongdce56da2017-04-27 15:50:34 -07004942 INIT_LIST_HEAD(&psde->mplane_list);
4943 master_plane = drm_plane_find(dev, master_plane_id);
4944 if (master_plane) {
4945 struct sde_plane *mpsde = to_sde_plane(master_plane);
4946
4947 list_add_tail(&psde->mplane_list, &mpsde->mplane_list);
4948 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004949
Clarence Ip4c1d9772016-06-26 09:35:38 -04004950 /* initialize underlying h/w driver */
Dhaval Pateld850b222017-06-16 17:37:37 -07004951 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog,
4952 master_plane_id != 0);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004953 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004954 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004955 ret = PTR_ERR(psde->pipe_hw);
4956 goto clean_plane;
4957 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004958 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004959 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004960 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004961
4962 /* cache features mask for later */
4963 psde->features = psde->pipe_hw->cap->features;
4964 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004965 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004966 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004967 goto clean_sspp;
4968 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004969
Steve Cohen57428172017-07-18 10:57:17 -04004970 if (!master_plane_id)
4971 format_list = psde->pipe_sblk->format_list;
4972 else
4973 format_list = psde->pipe_sblk->virt_format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004974
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004975 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004976 psde->formats,
4977 0,
4978 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004979
Clarence Ip4c1d9772016-06-26 09:35:38 -04004980 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004981 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004982 goto clean_sspp;
4983 }
4984
4985 if (psde->features & BIT(SDE_SSPP_CURSOR))
4986 type = DRM_PLANE_TYPE_CURSOR;
4987 else if (primary_plane)
4988 type = DRM_PLANE_TYPE_PRIMARY;
4989 else
4990 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07004991 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
4992 psde->formats, psde->nformats,
4993 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004994 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04004995 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004996
Clarence Ip4c1d9772016-06-26 09:35:38 -04004997 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004998 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004999
Clarence Ipaa0faf42016-05-30 12:07:48 -04005000 msm_property_init(&psde->property_info, &plane->base, dev,
5001 priv->plane_property, psde->property_data,
5002 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
5003 sizeof(struct sde_plane_state));
5004
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08005005 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04005006
Clarence Ip4ce59322016-06-26 22:27:51 -04005007 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04005008 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04005009
Clarence Ip730e7192016-06-26 22:45:09 -04005010 mutex_init(&psde->lock);
5011
Dhaval Patel572cfd22017-06-12 19:33:39 -07005012 SDE_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", psde->pipe_name,
5013 pipe, plane->base.id, master_plane_id);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005014 return plane;
5015
Clarence Ip4c1d9772016-06-26 09:35:38 -04005016clean_sspp:
5017 if (psde && psde->pipe_hw)
5018 sde_hw_sspp_destroy(psde->pipe_hw);
5019clean_plane:
5020 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04005021exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005022 return ERR_PTR(ret);
5023}