blob: 067c4604d95431f4dbbf1bcae7f8747cc5c13f5c [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;
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07001454 bool blend_enable = true;
Clarence Ipcb410d42016-06-26 22:52:33 -04001455
Clarence Ip172033f2017-06-13 10:52:56 -04001456 if (!psde || !psde->base.state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07001457 SDE_ERROR("invalid plane\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001458 return -EINVAL;
1459 }
1460
Clarence Ipcb410d42016-06-26 22:52:33 -04001461 if (!psde->pipe_hw) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04001462 SDE_ERROR_PLANE(psde, "invalid plane h/w pointer\n");
Clarence Ipcb410d42016-06-26 22:52:33 -04001463 return -EINVAL;
1464 }
1465
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001466 plane = &psde->base;
1467 pstate = to_sde_plane_state(plane->state);
1468
Clarence Ip13a8cf42016-09-29 17:27:47 -04001469 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04001470
Clarence Ipcb410d42016-06-26 22:52:33 -04001471 /*
1472 * select fill format to match user property expectation,
1473 * h/w only supports RGB variants
1474 */
Lloyd Atkinson9a673492016-07-05 11:41:57 -04001475 fmt = sde_get_sde_format(DRM_FORMAT_ABGR8888);
Clarence Ipcb410d42016-06-26 22:52:33 -04001476
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07001477 blend_enable = (SDE_DRM_BLEND_OP_OPAQUE !=
1478 sde_plane_get_property(pstate, PLANE_PROP_BLEND_OP));
1479
Clarence Ipcb410d42016-06-26 22:52:33 -04001480 /* update sspp */
1481 if (fmt && psde->pipe_hw->ops.setup_solidfill) {
1482 psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001483 (color & 0xFFFFFF) | ((alpha & 0xFF) << 24),
1484 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001485
1486 /* override scaler/decimation if solid fill */
1487 psde->pipe_cfg.src_rect.x = 0;
1488 psde->pipe_cfg.src_rect.y = 0;
1489 psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
1490 psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
Clarence Ip172033f2017-06-13 10:52:56 -04001491 _sde_plane_setup_scaler(psde, pstate, fmt, true);
Clarence Ipcb410d42016-06-26 22:52:33 -04001492
Clarence Ipcb410d42016-06-26 22:52:33 -04001493 if (psde->pipe_hw->ops.setup_format)
1494 psde->pipe_hw->ops.setup_format(psde->pipe_hw,
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07001495 fmt, blend_enable, SDE_SSPP_SOLID_FILL,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08001496 pstate->multirect_index);
Clarence Ipcb410d42016-06-26 22:52:33 -04001497
1498 if (psde->pipe_hw->ops.setup_rects)
1499 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001500 &psde->pipe_cfg,
1501 pstate->multirect_index);
1502
Jeykumar Sankaran9fcfa482017-02-16 16:03:14 -08001503 if (psde->pipe_hw->ops.setup_pe)
1504 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04001505 &pstate->pixel_ext);
Dhaval Patel2bbe8702017-08-30 21:22:52 -07001506
1507 if (psde->pipe_hw->ops.setup_scaler &&
1508 pstate->multirect_index != SDE_SSPP_RECT_1)
1509 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
1510 &psde->pipe_cfg, &pstate->pixel_ext,
1511 &pstate->scaler3_cfg);
Clarence Ipcb410d42016-06-26 22:52:33 -04001512 }
1513
1514 return 0;
1515}
1516
Alan Kwong4dd64c82017-02-04 18:41:51 -08001517/**
Alan Kwongcdb2f282017-03-18 13:42:06 -07001518 * _sde_plane_fb_get/put - framebuffer callback for crtc res ops
1519 */
1520static void *_sde_plane_fb_get(void *fb, u32 type, u64 tag)
1521{
1522 drm_framebuffer_reference(fb);
1523 return fb;
1524}
1525static void _sde_plane_fb_put(void *fb)
1526{
1527 drm_framebuffer_unreference(fb);
1528}
1529static struct sde_crtc_res_ops fb_res_ops = {
1530 .put = _sde_plane_fb_put,
1531 .get = _sde_plane_fb_get,
1532};
1533
1534/**
1535 * _sde_plane_fbo_get/put - framebuffer object callback for crtc res ops
1536 */
1537static void *_sde_plane_fbo_get(void *fbo, u32 type, u64 tag)
1538{
1539 sde_kms_fbo_reference(fbo);
1540 return fbo;
1541}
1542static void _sde_plane_fbo_put(void *fbo)
1543{
1544 sde_kms_fbo_unreference(fbo);
1545}
1546static struct sde_crtc_res_ops fbo_res_ops = {
1547 .put = _sde_plane_fbo_put,
1548 .get = _sde_plane_fbo_get,
1549};
1550
1551/**
Alan Kwong4aacd532017-02-04 18:51:33 -08001552 * sde_plane_rot_calc_prefill - calculate rotator start prefill
Alan Kwong4dd64c82017-02-04 18:41:51 -08001553 * @plane: Pointer to drm plane
1554 * return: prefill time in line
1555 */
Clarence Ipb776b532017-09-12 18:30:06 -04001556u32 sde_plane_rot_calc_prefill(struct drm_plane *plane)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001557{
1558 struct drm_plane_state *state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001559 struct sde_plane_state *pstate;
1560 struct sde_plane_rot_state *rstate;
1561 struct sde_kms *sde_kms;
1562 u32 blocksize = 128;
1563 u32 prefill_line = 0;
1564
Clarence Ip7eb90452017-05-23 11:41:19 -04001565 if (!plane || !plane->state || !plane->state->fb) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001566 SDE_ERROR("invalid parameters\n");
1567 return 0;
1568 }
1569
1570 sde_kms = _sde_plane_get_kms(plane);
1571 state = plane->state;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001572 pstate = to_sde_plane_state(state);
1573 rstate = &pstate->rot;
1574
Clarence Ip7eb90452017-05-23 11:41:19 -04001575 if (!sde_kms || !sde_kms->catalog) {
1576 SDE_ERROR("invalid kms\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08001577 return 0;
1578 }
1579
Clarence Ip7eb90452017-05-23 11:41:19 -04001580 if (rstate->out_fb_format)
1581 sde_format_get_block_size(rstate->out_fb_format,
1582 &blocksize, &blocksize);
1583
Alan Kwong4dd64c82017-02-04 18:41:51 -08001584 prefill_line = blocksize + sde_kms->catalog->sbuf_headroom;
Alan Kwongd2681812017-08-27 21:24:43 -04001585 prefill_line = mult_frac(prefill_line, rstate->out_src_h >> 16,
1586 state->crtc_h);
1587 SDE_DEBUG(
1588 "plane%d.%d blk:%u head:%u vdst/vsrc:%u/%u prefill:%u\n",
1589 plane->base.id, rstate->sequence_id,
1590 blocksize, sde_kms->catalog->sbuf_headroom,
1591 state->crtc_h, rstate->out_src_h >> 16,
1592 prefill_line);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001593
1594 return prefill_line;
1595}
1596
1597/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08001598 * sde_plane_rot_calc_cfg - calculate rotator/sspp configuration by
1599 * enumerating over all planes attached to the same rotator
1600 * @plane: Pointer to drm plane
1601 * @state: Pointer to drm state to be updated
Alan Kwong05109752017-08-12 20:26:45 -04001602 * return: 0 if success; error code otherwise
Alan Kwong4dd64c82017-02-04 18:41:51 -08001603 */
Alan Kwong05109752017-08-12 20:26:45 -04001604static int sde_plane_rot_calc_cfg(struct drm_plane *plane,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001605 struct drm_plane_state *state)
1606{
1607 struct sde_plane_state *pstate;
1608 struct sde_plane_rot_state *rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001609 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001610 struct drm_rect *in_rot, *out_rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001611 struct drm_plane *attached_plane;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001612 u32 dst_x, dst_y, dst_w, dst_h;
1613 int found = 0;
1614 int xpos = 0;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001615 int ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001616
1617 if (!plane || !state || !state->state) {
1618 SDE_ERROR("invalid parameters\n");
Alan Kwong05109752017-08-12 20:26:45 -04001619 return -EINVAL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001620 }
1621
Alan Kwongcdb2f282017-03-18 13:42:06 -07001622 cstate = _sde_plane_get_crtc_state(state);
1623 if (IS_ERR_OR_NULL(cstate)) {
1624 ret = PTR_ERR(cstate);
1625 SDE_ERROR("invalid crtc state %d\n", ret);
Alan Kwong05109752017-08-12 20:26:45 -04001626 return ret;
Alan Kwongcdb2f282017-03-18 13:42:06 -07001627 }
1628
Alan Kwong4dd64c82017-02-04 18:41:51 -08001629 pstate = to_sde_plane_state(state);
1630 rstate = &pstate->rot;
1631
Alan Kwong4dd64c82017-02-04 18:41:51 -08001632 in_rot = &rstate->in_rot_rect;
1633 in_rot->x1 = state->src_x;
1634 in_rot->y1 = state->src_y;
1635 in_rot->x2 = state->src_x + state->src_w;
1636 in_rot->y2 = state->src_y + state->src_h;
1637
1638 out_rot = &rstate->out_rot_rect;
1639 dst_x = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_X);
1640 dst_y = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_Y);
1641 dst_w = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_W);
1642 dst_h = sde_plane_get_property(pstate, PLANE_PROP_ROT_DST_H);
1643
1644 if (!dst_w && !dst_h) {
1645 rstate->out_rot_rect = rstate->in_rot_rect;
1646 drm_rect_rotate(&rstate->out_rot_rect, state->fb->width << 16,
1647 state->fb->height << 16, rstate->in_rotation);
1648 } else {
1649 out_rot->x1 = dst_x;
1650 out_rot->y1 = dst_y;
1651 out_rot->x2 = dst_x + dst_w;
1652 out_rot->y2 = dst_y + dst_h;
1653 }
1654
1655 rstate->out_src_rect = rstate->out_rot_rect;
1656
Alan Kwong4dd64c82017-02-04 18:41:51 -08001657 /* enumerating over all planes attached to the same rotator */
Alan Kwongcdb2f282017-03-18 13:42:06 -07001658 drm_atomic_crtc_state_for_each_plane(attached_plane, cstate) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08001659 struct drm_plane_state *attached_state;
1660 struct sde_plane_state *attached_pstate;
1661 struct sde_plane_rot_state *attached_rstate;
1662 struct drm_rect attached_out_rect;
1663
Alan Kwong4dd64c82017-02-04 18:41:51 -08001664 attached_state = drm_atomic_get_existing_plane_state(
1665 state->state, attached_plane);
1666
1667 if (!attached_state)
1668 continue;
1669
1670 attached_pstate = to_sde_plane_state(attached_state);
1671 attached_rstate = &attached_pstate->rot;
1672
Clarence Ipd27d9632017-06-14 09:57:26 -04001673 if (attached_state->fb != state->fb)
1674 continue;
1675
1676 if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) !=
1677 sde_plane_get_property(attached_pstate,
1678 PLANE_PROP_ROTATION))
Alan Kwongcdb2f282017-03-18 13:42:06 -07001679 continue;
1680
1681 found++;
1682
1683 /* skip itself */
1684 if (attached_plane == plane)
1685 continue;
1686
Alan Kwong4dd64c82017-02-04 18:41:51 -08001687 /* find bounding rotator source roi */
1688 if (attached_state->src_x < in_rot->x1)
1689 in_rot->x1 = attached_state->src_x;
1690
1691 if (attached_state->src_y < in_rot->y1)
1692 in_rot->y1 = attached_state->src_y;
1693
1694 if (attached_state->src_x + attached_state->src_w > in_rot->x2)
1695 in_rot->x2 = attached_state->src_x +
1696 attached_state->src_w;
1697
1698 if (attached_state->src_y + attached_state->src_h > in_rot->y2)
1699 in_rot->y2 = attached_state->src_y +
1700 attached_state->src_h;
1701
1702 /* find bounding rotator destination roi */
1703 dst_x = sde_plane_get_property(attached_pstate,
1704 PLANE_PROP_ROT_DST_X);
1705 dst_y = sde_plane_get_property(attached_pstate,
1706 PLANE_PROP_ROT_DST_Y);
1707 dst_w = sde_plane_get_property(attached_pstate,
1708 PLANE_PROP_ROT_DST_W);
1709 dst_h = sde_plane_get_property(attached_pstate,
1710 PLANE_PROP_ROT_DST_H);
1711 if (!dst_w && !dst_h) {
1712 attached_out_rect.x1 = attached_state->src_x;
1713 attached_out_rect.y1 = attached_state->src_y;
1714 attached_out_rect.x2 = attached_out_rect.x1 +
1715 attached_state->src_w;
1716 attached_out_rect.y2 = attached_out_rect.y1 +
1717 attached_state->src_h;
1718 drm_rect_rotate(&attached_out_rect,
1719 state->fb->width << 16,
1720 state->fb->height << 16,
1721 rstate->in_rotation);
1722 } else {
1723 attached_out_rect.x1 = dst_x;
1724 attached_out_rect.y1 = dst_y;
1725 attached_out_rect.x2 = dst_x + dst_w;
1726 attached_out_rect.y2 = dst_y + dst_h;
1727 }
1728
Alan Kwong05109752017-08-12 20:26:45 -04001729 /* check source split left/right mismatch */
1730 if (attached_out_rect.y1 != rstate->out_src_rect.y1 ||
1731 attached_out_rect.y2 != rstate->out_src_rect.y2) {
1732 SDE_ERROR(
1733 "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",
1734 plane->base.id,
1735 rstate->sequence_id,
1736 state->src_w >> 16,
1737 state->src_h >> 16,
1738 state->src_x >> 16,
1739 state->src_y >> 16,
1740 sde_plane_get_property(pstate,
1741 PLANE_PROP_ROTATION),
1742 state->fb ?
1743 state->fb->base.id :
1744 -1,
1745 attached_plane->base.id,
1746 attached_rstate->sequence_id,
1747 attached_state->src_w >> 16,
1748 attached_state->src_h >> 16,
1749 attached_state->src_x >> 16,
1750 attached_state->src_y >> 16,
1751 sde_plane_get_property(attached_pstate,
1752 PLANE_PROP_ROTATION),
1753 attached_state->fb ?
1754 attached_state->fb->base.id :
1755 -1);
1756 SDE_ERROR(
1757 "plane%d.%u sspp:%dx%d+%d+%d plane%d.%u sspp:%dx%d+%d+%d\n",
1758 plane->base.id,
1759 rstate->sequence_id,
1760 (rstate->out_src_rect.x2 -
1761 rstate->out_src_rect.x1) >> 16,
1762 (rstate->out_src_rect.y2 -
1763 rstate->out_src_rect.y1) >> 16,
1764 rstate->out_src_rect.x1 >> 16,
1765 rstate->out_src_rect.y1 >> 16,
1766 attached_plane->base.id,
1767 attached_rstate->sequence_id,
1768 (attached_out_rect.x2 -
1769 attached_out_rect.x1) >> 16,
1770 (attached_out_rect.y2 -
1771 attached_out_rect.y1) >> 16,
1772 attached_out_rect.x1 >> 16,
1773 attached_out_rect.y1 >> 16);
1774 SDE_EVT32(DRMID(plane),
1775 rstate->sequence_id,
1776 rstate->out_src_rect.x1 >> 16,
1777 rstate->out_src_rect.y1 >> 16,
1778 (rstate->out_src_rect.x2 -
1779 rstate->out_src_rect.x1) >> 16,
1780 (rstate->out_src_rect.y2 -
1781 rstate->out_src_rect.y1) >> 16,
1782 attached_plane->base.id,
1783 attached_rstate->sequence_id,
1784 attached_out_rect.x1 >> 16,
1785 attached_out_rect.y1 >> 16,
1786 (attached_out_rect.x2 -
1787 attached_out_rect.x1) >> 16,
1788 (attached_out_rect.y2 -
1789 attached_out_rect.y1) >> 16,
1790 SDE_EVTLOG_ERROR);
1791 return -EINVAL;
1792 }
1793
Alan Kwong4dd64c82017-02-04 18:41:51 -08001794 /* find relative sspp position */
1795 if (attached_out_rect.x1 < rstate->out_src_rect.x1)
1796 xpos++;
1797
1798 if (attached_out_rect.x1 < out_rot->x1)
1799 out_rot->x1 = attached_out_rect.x1;
1800
1801 if (attached_out_rect.y1 < out_rot->y1)
1802 out_rot->y1 = attached_out_rect.y1;
1803
1804 if (attached_out_rect.x2 > out_rot->x2)
1805 out_rot->x2 = attached_out_rect.x2;
1806
1807 if (attached_out_rect.y2 > out_rot->y2)
1808 out_rot->y2 = attached_out_rect.y2;
1809
1810 SDE_DEBUG("plane%d.%u src_x:%d sspp:%dx%d+%d+%d/%dx%d+%d+%d\n",
1811 attached_plane->base.id,
1812 attached_rstate->sequence_id,
1813 attached_rstate->out_src_rect.x1 >> 16,
1814 attached_state->src_w >> 16,
1815 attached_state->src_h >> 16,
1816 attached_state->src_x >> 16,
1817 attached_state->src_y >> 16,
1818 drm_rect_width(&attached_rstate->out_src_rect) >> 16,
1819 drm_rect_height(&attached_rstate->out_src_rect) >> 16,
1820 attached_rstate->out_src_rect.x1 >> 16,
1821 attached_rstate->out_src_rect.y1 >> 16);
1822 }
1823
1824 rstate->out_xpos = xpos;
1825 rstate->nplane = found;
1826
1827 SDE_DEBUG("plane%d.%u xpos:%d/%d rot:%dx%d+%d+%d/%dx%d+%d+%d\n",
1828 plane->base.id, rstate->sequence_id,
1829 rstate->out_xpos, rstate->nplane,
1830 drm_rect_width(in_rot) >> 16,
1831 drm_rect_height(in_rot) >> 16,
1832 in_rot->x1 >> 16, in_rot->y1 >> 16,
1833 drm_rect_width(&rstate->out_rot_rect) >> 16,
1834 drm_rect_height(&rstate->out_rot_rect) >> 16,
1835 rstate->out_rot_rect.x1 >> 16,
1836 rstate->out_rot_rect.y1 >> 16);
Clarence Ipeb39cce2017-07-19 14:12:43 -04001837 SDE_EVT32(DRMID(plane), rstate->sequence_id,
Clarence Ipf27c6f22017-07-10 18:19:44 -04001838 rstate->out_xpos, rstate->nplane,
1839 in_rot->x1 >> 16, in_rot->y1 >> 16,
1840 drm_rect_width(in_rot) >> 16,
1841 drm_rect_height(in_rot) >> 16,
1842 rstate->out_rot_rect.x1 >> 16,
1843 rstate->out_rot_rect.y1 >> 16,
1844 drm_rect_width(&rstate->out_rot_rect) >> 16,
1845 drm_rect_height(&rstate->out_rot_rect) >> 16);
Alan Kwong05109752017-08-12 20:26:45 -04001846
1847 return 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001848}
1849
1850/**
1851 * sde_plane_rot_submit_command - commit given state for the rotator stage
1852 * @plane: Pointer to drm plane
1853 * @state: Pointer to the state to be committed
1854 * @hw_cmd: rotator command type
1855 * return: 0 if success; error code otherwise
1856 */
1857static int sde_plane_rot_submit_command(struct drm_plane *plane,
1858 struct drm_plane_state *state, enum sde_hw_rot_cmd_type hw_cmd)
1859{
1860 struct sde_plane *psde = to_sde_plane(plane);
1861 struct sde_plane_state *pstate = to_sde_plane_state(state);
1862 struct sde_plane_rot_state *rstate = &pstate->rot;
1863 struct sde_hw_rot_cmd *rot_cmd;
Alan Kwong4aacd532017-02-04 18:51:33 -08001864 struct drm_crtc_state *cstate;
1865 struct sde_crtc_state *sde_cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001866 int ret, i;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001867 int fb_mode;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001868
1869 if (!plane || !state || !state->fb || !rstate->rot_hw) {
1870 SDE_ERROR("invalid parameters\n");
1871 return -EINVAL;
1872 }
1873
Alan Kwong4aacd532017-02-04 18:51:33 -08001874 cstate = _sde_plane_get_crtc_state(state);
1875 if (IS_ERR_OR_NULL(cstate)) {
1876 SDE_ERROR("invalid crtc state %ld\n", PTR_ERR(cstate));
1877 return -EINVAL;
1878 }
1879 sde_cstate = to_sde_crtc_state(cstate);
1880
Alan Kwong4dd64c82017-02-04 18:41:51 -08001881 rot_cmd = &rstate->rot_cmd;
1882
1883 rot_cmd->master = (rstate->out_xpos == 0);
1884 rot_cmd->sequence_id = rstate->sequence_id;
1885 rot_cmd->fps = pstate->base.crtc && pstate->base.crtc->state ?
1886 drm_mode_vrefresh(&pstate->base.crtc->state->adjusted_mode) :
1887 DEFAULT_REFRESH_RATE;
1888 rot_cmd->rot90 = rstate->rot90;
1889 rot_cmd->hflip = rstate->hflip;
1890 rot_cmd->vflip = rstate->vflip;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07001891 fb_mode = sde_plane_get_property(pstate,
1892 PLANE_PROP_FB_TRANSLATION_MODE);
1893 if ((fb_mode == SDE_DRM_FB_SEC) ||
1894 (fb_mode == SDE_DRM_FB_SEC_DIR_TRANS))
1895 rot_cmd->secure = true;
1896 else
1897 rot_cmd->secure = false;
1898
Alan Kwong4aacd532017-02-04 18:51:33 -08001899 rot_cmd->prefill_bw = sde_crtc_get_property(sde_cstate,
1900 CRTC_PROP_ROT_PREFILL_BW);
Alan Kwong8c176bf2017-02-09 19:34:32 -08001901 rot_cmd->clkrate = sde_crtc_get_property(sde_cstate,
1902 CRTC_PROP_ROT_CLK);
Alan Kwong4dd64c82017-02-04 18:41:51 -08001903 rot_cmd->dst_writeback = psde->sbuf_writeback;
1904
1905 if (sde_crtc_get_intf_mode(state->crtc) == INTF_MODE_VIDEO)
1906 rot_cmd->video_mode = true;
1907 else
1908 rot_cmd->video_mode = false;
1909
1910 rot_cmd->src_pixel_format = state->fb->pixel_format;
1911 rot_cmd->src_modifier = state->fb->modifier[0];
1912 rot_cmd->src_stride = state->fb->pitches[0];
1913
1914 rot_cmd->src_format = to_sde_format(msm_framebuffer_format(state->fb));
1915 if (!rot_cmd->src_format) {
1916 SDE_ERROR("failed to get src format\n");
1917 return -EINVAL;
1918 }
1919
1920 rot_cmd->src_width = state->fb->width;
1921 rot_cmd->src_height = state->fb->height;
1922 rot_cmd->src_rect_x = rstate->in_rot_rect.x1 >> 16;
1923 rot_cmd->src_rect_y = rstate->in_rot_rect.y1 >> 16;
1924 rot_cmd->src_rect_w = drm_rect_width(&rstate->in_rot_rect) >> 16;
1925 rot_cmd->src_rect_h = drm_rect_height(&rstate->in_rot_rect) >> 16;
Alan Kwong809f3cbd2017-08-11 18:39:36 -04001926 rot_cmd->dst_rect_x = 0;
1927 rot_cmd->dst_rect_y = 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001928 rot_cmd->dst_rect_w = drm_rect_width(&rstate->out_rot_rect) >> 16;
1929 rot_cmd->dst_rect_h = drm_rect_height(&rstate->out_rot_rect) >> 16;
1930
1931 if (hw_cmd == SDE_HW_ROT_CMD_COMMIT) {
1932 struct sde_hw_fmt_layout layout;
1933
1934 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Clarence Ip299fa602017-07-11 18:01:37 -04001935 sde_format_populate_layout(pstate->aspace, state->fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001936 &layout);
1937 for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
1938 rot_cmd->src_iova[i] = layout.plane_addr[i];
1939 rot_cmd->src_len[i] = layout.plane_size[i];
1940 }
1941 rot_cmd->src_planes = layout.num_planes;
1942
1943 memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
Clarence Ip299fa602017-07-11 18:01:37 -04001944 sde_format_populate_layout(pstate->aspace, rstate->out_fb,
Alan Kwong4dd64c82017-02-04 18:41:51 -08001945 &layout);
1946 for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
1947 rot_cmd->dst_iova[i] = layout.plane_addr[i];
1948 rot_cmd->dst_len[i] = layout.plane_size[i];
1949 }
1950 rot_cmd->dst_planes = layout.num_planes;
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001951
1952 /* VBIF remapper settings */
Alan Kwong032c2e182017-06-29 16:31:38 -04001953 for (i = 0; i < rstate->rot_hw->caps->xin_count; i++) {
Veera Sundaram Sankaran1e71ccb2017-05-24 18:48:50 -07001954 const struct sde_rot_vbif_cfg *cfg =
1955 &rstate->rot_hw->caps->vbif_cfg[i];
1956
1957 _sde_plane_inline_rot_set_qos_remap(plane, cfg);
1958
1959 if (cfg->is_read) {
1960 _sde_plane_inline_rot_set_ot_limit(plane,
1961 state->crtc, cfg, rot_cmd->src_rect_w,
1962 rot_cmd->src_rect_h);
1963 } else {
1964 _sde_plane_inline_rot_set_ot_limit(plane,
1965 state->crtc, cfg, rot_cmd->dst_rect_w,
1966 rot_cmd->dst_rect_h);
1967 }
1968 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08001969 }
1970
1971 ret = rstate->rot_hw->ops.commit(rstate->rot_hw, rot_cmd, hw_cmd);
Alan Kwong05109752017-08-12 20:26:45 -04001972 if (ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08001973 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08001974
1975 rstate->out_rotation = rstate->in_rotation;
1976 rstate->out_fb_flags = rot_cmd->dst_modifier ?
1977 DRM_MODE_FB_MODIFIERS : 0;
1978 rstate->out_fb_flags |= rot_cmd->secure ? DRM_MODE_FB_SECURE : 0;
1979 rstate->out_fb_format = rot_cmd->dst_format;
1980 rstate->out_fb_pixel_format = rot_cmd->dst_pixel_format;
1981
1982 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
1983 rstate->out_fb_modifier[i] = rot_cmd->dst_modifier;
1984
1985 rstate->out_fb_width = drm_rect_width(&rstate->out_rot_rect) >> 16;
1986 rstate->out_fb_height = drm_rect_height(&rstate->out_rot_rect) >> 16;
1987 rstate->out_src_x = rstate->out_src_rect.x1 - rstate->out_rot_rect.x1;
1988 rstate->out_src_y = rstate->out_src_rect.y1 - rstate->out_rot_rect.y1;
1989 rstate->out_src_w = drm_rect_width(&rstate->out_src_rect);
1990 rstate->out_src_h = drm_rect_height(&rstate->out_src_rect);
1991
1992 if (rot_cmd->rot90)
1993 rstate->out_rotation &= ~DRM_ROTATE_90;
1994
1995 if (rot_cmd->hflip)
1996 rstate->out_rotation &= ~DRM_REFLECT_X;
1997
1998 if (rot_cmd->vflip)
1999 rstate->out_rotation &= ~DRM_REFLECT_Y;
2000
2001 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07002002 "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 -08002003 plane->base.id, rstate->sequence_id, hw_cmd,
2004 rot_cmd->rot90 ? 'r' : '_',
2005 rot_cmd->hflip ? 'h' : '_',
2006 rot_cmd->vflip ? 'v' : '_',
2007 rot_cmd->video_mode ? 'V' : 'C',
2008 state->fb->width, state->fb->height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002009 (char *) &state->fb->pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002010 state->fb->modifier[0],
2011 drm_rect_width(&rstate->in_rot_rect) >> 16,
2012 drm_rect_height(&rstate->in_rot_rect) >> 16,
2013 rstate->in_rot_rect.x1 >> 16,
2014 rstate->in_rot_rect.y1 >> 16);
2015
Dhaval Patel6c666622017-03-21 23:02:59 -07002016 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 -08002017 plane->base.id, rstate->sequence_id, hw_cmd,
2018 rstate->out_rotation,
2019 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07002020 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08002021 rstate->out_fb_modifier[0],
2022 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
2023 rstate->out_src_x >> 16, rstate->out_src_y >> 16);
2024
2025 return ret;
2026}
2027
2028/**
Clarence Ipd27d9632017-06-14 09:57:26 -04002029 * _sde_plane_rot_get_fb - attempt to get previously allocated fb/fbo
2030 * If an fb/fbo was already created, either from a previous frame or
2031 * from another plane in the current commit cycle, attempt to reuse
2032 * it for this commit cycle as well.
2033 * @plane: Pointer to drm plane
2034 * @cstate: Pointer to crtc state
2035 * @rstate: Pointer to rotator plane state
2036 */
2037static void _sde_plane_rot_get_fb(struct drm_plane *plane,
2038 struct drm_crtc_state *cstate,
2039 struct sde_plane_rot_state *rstate)
2040{
2041 struct sde_kms_fbo *fbo;
2042 struct drm_framebuffer *fb;
2043
Clarence Ipf27c6f22017-07-10 18:19:44 -04002044 if (!plane || !cstate || !rstate || !rstate->rot_hw)
Clarence Ipd27d9632017-06-14 09:57:26 -04002045 return;
2046
2047 fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2048 (u64) &rstate->rot_hw->base);
2049 fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2050 (u64) &rstate->rot_hw->base);
2051 if (fb && fbo) {
2052 SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
2053 rstate->sequence_id);
2054 } else if (fbo) {
2055 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2056 (u64) &rstate->rot_hw->base);
2057 fbo = NULL;
2058 } else if (fb) {
2059 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2060 (u64) &rstate->rot_hw->base);
2061 fb = NULL;
2062 }
2063
2064 rstate->out_fbo = fbo;
2065 rstate->out_fb = fb;
2066}
2067
2068/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002069 * sde_plane_rot_prepare_fb - prepare framebuffer of the new state
2070 * for rotator (pre-sspp) stage
2071 * @plane: Pointer to drm plane
2072 * @new_state: Pointer to new drm plane state
2073 * return: 0 if success; error code otherwise
2074 */
2075static int sde_plane_rot_prepare_fb(struct drm_plane *plane,
2076 struct drm_plane_state *new_state)
2077{
2078 struct drm_framebuffer *fb = new_state->fb;
2079 struct sde_plane_state *new_pstate = to_sde_plane_state(new_state);
2080 struct sde_plane_rot_state *new_rstate = &new_pstate->rot;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002081 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002082 int ret;
2083
2084 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n",
2085 plane->base.id,
2086 new_rstate->sequence_id, fb ? fb->base.id : 0,
2087 !!new_rstate->out_sbuf, !!new_rstate->rot_hw,
2088 sde_plane_crtc_enabled(new_state));
2089
2090 if (!new_rstate->out_sbuf || !new_rstate->rot_hw)
2091 return 0;
2092
Alan Kwongcdb2f282017-03-18 13:42:06 -07002093 cstate = _sde_plane_get_crtc_state(new_state);
2094 if (IS_ERR(cstate)) {
2095 ret = PTR_ERR(cstate);
2096 SDE_ERROR("invalid crtc state %d\n", ret);
2097 return ret;
2098 }
2099
Alan Kwong4dd64c82017-02-04 18:41:51 -08002100 /* need to re-calc based on all newly validated plane states */
Alan Kwong05109752017-08-12 20:26:45 -04002101 ret = sde_plane_rot_calc_cfg(plane, new_state);
2102 if (ret)
2103 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002104
2105 /* check if stream buffer is already attached to rotator */
Clarence Ipd27d9632017-06-14 09:57:26 -04002106 if (sde_plane_enabled(new_state) && !new_rstate->out_fb)
2107 _sde_plane_rot_get_fb(plane, cstate, new_rstate);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002108
Alan Kwong4dd64c82017-02-04 18:41:51 -08002109 /* create new stream buffer if it is not available */
2110 if (sde_plane_enabled(new_state) && !new_rstate->out_fb) {
2111 u32 fb_w = drm_rect_width(&new_rstate->out_rot_rect) >> 16;
2112 u32 fb_h = drm_rect_height(&new_rstate->out_rot_rect) >> 16;
2113
2114 SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
2115 new_rstate->sequence_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002116
2117 /* check if out_fb is already attached to rotator */
2118 new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
2119 new_rstate->out_fb_pixel_format,
2120 new_rstate->out_fb_modifier,
2121 new_rstate->out_fb_flags);
2122 if (!new_rstate->out_fbo) {
2123 SDE_ERROR("failed to allocate inline buffer object\n");
2124 ret = -EINVAL;
2125 goto error_create_fbo;
2126 }
2127
Alan Kwongcdb2f282017-03-18 13:42:06 -07002128 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2129 (u64) &new_rstate->rot_hw->base,
2130 new_rstate->out_fbo, &fbo_res_ops);
2131 if (ret) {
2132 SDE_ERROR("failed to add crtc resource\n");
2133 goto error_create_fbo_res;
2134 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002135
2136 new_rstate->out_fb = sde_kms_fbo_create_fb(plane->dev,
2137 new_rstate->out_fbo);
2138 if (!new_rstate->out_fb) {
2139 SDE_ERROR("failed to create inline framebuffer\n");
2140 ret = -EINVAL;
2141 goto error_create_fb;
2142 }
Clarence Ipf27c6f22017-07-10 18:19:44 -04002143 SDE_EVT32_VERBOSE(DRMID(plane), new_rstate->sequence_id,
2144 new_rstate->out_fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002145
Alan Kwongcdb2f282017-03-18 13:42:06 -07002146 ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2147 (u64) &new_rstate->rot_hw->base,
2148 new_rstate->out_fb, &fb_res_ops);
2149 if (ret) {
2150 SDE_ERROR("failed to add crtc resource %d\n", ret);
2151 goto error_create_fb_res;
2152 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002153 }
2154
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002155 if (new_pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002156 SDE_EVT32(DRMID(plane));
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002157 SDE_DEBUG(
2158 "plane%d, domain not attached, prepare fb handled later\n",
2159 plane->base.id);
2160 return 0;
2161 }
2162
Alan Kwong4dd64c82017-02-04 18:41:51 -08002163 /* prepare rotator input buffer */
Clarence Ip299fa602017-07-11 18:01:37 -04002164 ret = msm_framebuffer_prepare(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002165 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002166 SDE_ERROR("failed to prepare input framebuffer, %d\n", ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002167 goto error_prepare_input_buffer;
2168 }
2169
2170 /* prepare rotator output buffer */
2171 if (sde_plane_enabled(new_state) && new_rstate->out_fb) {
2172 SDE_DEBUG("plane%d.%d prepare fb/fbo\n", plane->base.id,
2173 new_rstate->sequence_id);
2174
2175 ret = msm_framebuffer_prepare(new_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002176 new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002177 if (ret) {
Clarence Ip299fa602017-07-11 18:01:37 -04002178 SDE_ERROR("failed to prepare inline framebuffer, %d\n",
2179 ret);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002180 goto error_prepare_output_buffer;
2181 }
2182 }
2183
2184 return 0;
2185
2186error_prepare_output_buffer:
Clarence Ip299fa602017-07-11 18:01:37 -04002187 msm_framebuffer_cleanup(new_state->fb, new_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002188error_prepare_input_buffer:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002189 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2190 (u64) &new_rstate->rot_hw->base);
2191error_create_fb_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002192 new_rstate->out_fb = NULL;
2193error_create_fb:
Alan Kwongcdb2f282017-03-18 13:42:06 -07002194 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2195 (u64) &new_rstate->rot_hw->base);
2196error_create_fbo_res:
Alan Kwong4dd64c82017-02-04 18:41:51 -08002197 new_rstate->out_fbo = NULL;
2198error_create_fbo:
2199 return ret;
2200}
2201
2202/**
2203 * sde_plane_rot_cleanup_fb - cleanup framebuffer of previous state for the
2204 * rotator (pre-sspp) stage
2205 * @plane: Pointer to drm plane
2206 * @old_state: Pointer to previous drm plane state
2207 * return: none
2208 */
2209static void sde_plane_rot_cleanup_fb(struct drm_plane *plane,
2210 struct drm_plane_state *old_state)
2211{
2212 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
2213 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
2214 struct sde_hw_rot_cmd *cmd = &old_rstate->rot_cmd;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002215 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002216 int ret;
2217
2218 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2219 old_rstate->sequence_id, old_state->fb->base.id,
2220 !!old_rstate->out_sbuf, !!old_rstate->rot_hw,
2221 sde_plane_crtc_enabled(old_state));
2222
2223 if (!old_rstate->out_sbuf || !old_rstate->rot_hw)
2224 return;
2225
Alan Kwongcdb2f282017-03-18 13:42:06 -07002226 cstate = _sde_plane_get_crtc_state(old_state);
2227 if (IS_ERR(cstate)) {
2228 ret = PTR_ERR(cstate);
2229 SDE_ERROR("invalid crtc state %d\n", ret);
2230 return;
2231 }
2232
Alan Kwong4dd64c82017-02-04 18:41:51 -08002233 if (sde_plane_crtc_enabled(old_state)) {
2234 ret = old_rstate->rot_hw->ops.commit(old_rstate->rot_hw, cmd,
2235 SDE_HW_ROT_CMD_CLEANUP);
2236 if (ret)
2237 SDE_ERROR("failed to cleanup rotator buffers\n");
2238 }
2239
2240 if (sde_plane_enabled(old_state)) {
2241 if (old_rstate->out_fb) {
2242 msm_framebuffer_cleanup(old_rstate->out_fb,
Clarence Ip299fa602017-07-11 18:01:37 -04002243 old_pstate->aspace);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002244 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2245 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002246 old_rstate->out_fb = NULL;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002247 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2248 (u64) &old_rstate->rot_hw->base);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002249 old_rstate->out_fbo = NULL;
2250 }
2251
Clarence Ip299fa602017-07-11 18:01:37 -04002252 msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002253 }
2254}
2255
2256/**
2257 * sde_plane_rot_atomic_check - verify rotator update of the given state
2258 * @plane: Pointer to drm plane
2259 * @state: Pointer to drm plane state to be validated
2260 * return: 0 if success; error code otherwise
2261 */
2262static int sde_plane_rot_atomic_check(struct drm_plane *plane,
2263 struct drm_plane_state *state)
2264{
2265 struct sde_plane *psde;
2266 struct sde_plane_state *pstate, *old_pstate;
2267 struct sde_plane_rot_state *rstate, *old_rstate;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002268 struct drm_crtc_state *cstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002269 struct sde_hw_blk *hw_blk;
2270 int i, ret = 0;
2271
2272 if (!plane || !state) {
2273 SDE_ERROR("invalid plane/state\n");
2274 return -EINVAL;
2275 }
2276
2277 psde = to_sde_plane(plane);
2278 pstate = to_sde_plane_state(state);
2279 old_pstate = to_sde_plane_state(plane->state);
2280 rstate = &pstate->rot;
2281 old_rstate = &old_pstate->rot;
2282
Alan Kwongcdb2f282017-03-18 13:42:06 -07002283 /* cstate will be null if crtc is disconnected from plane */
2284 cstate = _sde_plane_get_crtc_state(state);
2285 if (IS_ERR(cstate)) {
2286 ret = PTR_ERR(cstate);
2287 SDE_ERROR("invalid crtc state %d\n", ret);
2288 return ret;
2289 }
2290
Alan Kwong4dd64c82017-02-04 18:41:51 -08002291 SDE_DEBUG("plane%d.%d FB[%u] sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2292 rstate->sequence_id, state->fb ? state->fb->base.id : 0,
2293 !!rstate->out_sbuf, !!rstate->rot_hw,
2294 sde_plane_crtc_enabled(state));
2295
2296 rstate->in_rotation = drm_rotation_simplify(
2297 sde_plane_get_property(pstate, PLANE_PROP_ROTATION),
Alan Kwong709150c2017-04-03 08:44:31 -07002298 DRM_ROTATE_0 | DRM_ROTATE_90 |
2299 DRM_REFLECT_X | DRM_REFLECT_Y);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002300 rstate->rot90 = rstate->in_rotation & DRM_ROTATE_90 ? true : false;
2301 rstate->hflip = rstate->in_rotation & DRM_REFLECT_X ? true : false;
2302 rstate->vflip = rstate->in_rotation & DRM_REFLECT_Y ? true : false;
2303 rstate->out_sbuf = psde->sbuf_mode || rstate->rot90;
2304
Alan Kwongcdb2f282017-03-18 13:42:06 -07002305 if (sde_plane_enabled(state) && rstate->out_sbuf) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002306 SDE_DEBUG("plane%d.%d acquire rotator, fb %d\n",
2307 plane->base.id, rstate->sequence_id,
2308 state->fb ? state->fb->base.id : -1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002309
Alan Kwongcdb2f282017-03-18 13:42:06 -07002310 hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
2311 (u64) state->fb);
2312 if (!hw_blk) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002313 SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
2314 plane->base.id, rstate->sequence_id,
2315 state->fb ? state->fb->base.id : -1);
Alan Kwong310e9b02017-08-03 02:04:07 -04002316 SDE_EVT32(DRMID(plane), rstate->sequence_id,
2317 SDE_EVTLOG_ERROR);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002318 return -EINVAL;
2319 }
2320
Alan Kwongcdb2f282017-03-18 13:42:06 -07002321 rstate->rot_hw = to_sde_hw_rot(hw_blk);
2322
Alan Kwong4dd64c82017-02-04 18:41:51 -08002323 if (!rstate->rot_hw->ops.commit) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002324 SDE_ERROR("plane%d.%d invalid rotator ops\n",
2325 plane->base.id, rstate->sequence_id);
Alan Kwongcdb2f282017-03-18 13:42:06 -07002326 sde_crtc_res_put(cstate,
2327 SDE_HW_BLK_ROT, (u64) state->fb);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002328 rstate->rot_hw = NULL;
2329 return -EINVAL;
2330 }
2331
2332 rstate->in_fb = state->fb;
Alan Kwongcdb2f282017-03-18 13:42:06 -07002333 } else {
2334 rstate->in_fb = NULL;
2335 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002336 }
2337
2338 if (sde_plane_enabled(state) && rstate->out_sbuf && rstate->rot_hw) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04002339 uint32_t fb_id;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002340
Clarence Ipf27c6f22017-07-10 18:19:44 -04002341 fb_id = state->fb ? state->fb->base.id : -1;
2342 SDE_DEBUG("plane%d.%d use rotator, fb %d\n",
2343 plane->base.id, rstate->sequence_id, fb_id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002344
Alan Kwong05109752017-08-12 20:26:45 -04002345 ret = sde_plane_rot_calc_cfg(plane, state);
2346 if (ret)
2347 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002348
2349 ret = sde_plane_rot_submit_command(plane, state,
2350 SDE_HW_ROT_CMD_VALIDATE);
Clarence Ipf27c6f22017-07-10 18:19:44 -04002351 if (ret)
2352 return ret;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002353
Clarence Ip317a9572017-08-08 18:16:26 -04002354 if (rstate->nplane != old_rstate->nplane ||
2355 rstate->out_xpos != old_rstate->out_xpos)
2356 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
2357 SDE_PLANE_DIRTY_RECTS;
2358
Clarence Ipf27c6f22017-07-10 18:19:44 -04002359 /* check if stream buffer is already attached to rotator */
2360 _sde_plane_rot_get_fb(plane, cstate, rstate);
2361
2362 /* release buffer if output format configuration changes */
2363 if (rstate->out_fb &&
2364 ((rstate->out_fb_height != rstate->out_fb->height) ||
2365 (rstate->out_fb_width != rstate->out_fb->width) ||
2366 (rstate->out_fb_pixel_format !=
2367 rstate->out_fb->pixel_format) ||
2368 (rstate->out_fb_modifier[0] !=
2369 rstate->out_fb->modifier[0]) ||
2370 (rstate->out_fb_flags != rstate->out_fb->flags))) {
2371
2372 SDE_DEBUG("plane%d.%d release fb/fbo\n", plane->base.id,
2373 rstate->sequence_id);
2374 SDE_EVT32_VERBOSE(DRMID(plane),
2375 rstate->sequence_id, fb_id);
2376
2377 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
2378 (u64) &rstate->rot_hw->base);
2379 rstate->out_fb = NULL;
2380 sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
2381 (u64) &rstate->rot_hw->base);
2382 rstate->out_fbo = NULL;
2383 }
Clarence Ip4475d582017-04-18 11:36:00 -04002384 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002385
2386 SDE_DEBUG("plane%d.%d bypass rotator\n", plane->base.id,
2387 rstate->sequence_id);
2388
2389 /* bypass rotator - initialize output setting as input */
Clarence Ip4475d582017-04-18 11:36:00 -04002390 for (i = 0; i < ARRAY_SIZE(rstate->out_fb_modifier); i++)
2391 rstate->out_fb_modifier[i] = state->fb ?
2392 state->fb->modifier[i] : 0x0;
2393
2394 if (state->fb) {
2395 rstate->out_fb_pixel_format = state->fb->pixel_format;
2396 rstate->out_fb_flags = state->fb->flags;
2397 rstate->out_fb_width = state->fb->width;
2398 rstate->out_fb_height = state->fb->height;
2399 } else {
2400 rstate->out_fb_pixel_format = 0x0;
2401 rstate->out_fb_flags = 0x0;
2402 rstate->out_fb_width = 0;
2403 rstate->out_fb_height = 0;
2404 }
2405
Alan Kwong4dd64c82017-02-04 18:41:51 -08002406 rstate->out_rotation = rstate->in_rotation;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002407 rstate->out_src_x = state->src_x;
2408 rstate->out_src_y = state->src_y;
2409 rstate->out_src_w = state->src_w;
2410 rstate->out_src_h = state->src_h;
2411
2412 rstate->out_fb_format = NULL;
2413 rstate->out_sbuf = false;
2414 rstate->out_fb = state->fb;
2415 }
2416
2417 return ret;
2418}
2419
2420/**
2421 * sde_plane_rot_atomic_update - perform atomic update for rotator stage
2422 * @plane: Pointer to drm plane
2423 * @old_state: Pointer to previous state
2424 * return: none
2425 */
2426static void sde_plane_rot_atomic_update(struct drm_plane *plane,
2427 struct drm_plane_state *old_state)
2428{
2429 struct drm_plane_state *state;
2430 struct sde_plane_state *pstate;
2431 struct sde_plane_rot_state *rstate;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002432 int ret = 0;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002433
2434 if (!plane || !plane->state) {
2435 SDE_ERROR("invalid plane/state\n");
2436 return;
2437 }
2438
2439 state = plane->state;
2440 pstate = to_sde_plane_state(state);
2441 rstate = &pstate->rot;
2442
2443 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2444 rstate->sequence_id,
2445 !!rstate->out_sbuf, !!rstate->rot_hw,
2446 sde_plane_crtc_enabled(plane->state));
2447
2448 if (!sde_plane_crtc_enabled(state))
2449 return;
2450
2451 if (!rstate->out_sbuf || !rstate->rot_hw)
2452 return;
2453
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002454 /*
2455 * framebuffer prepare is deferred for prepare_fb calls that
2456 * happen during the transition from secure to non-secure.
2457 * Handle the prepare at this point for rotator in such cases.
2458 * This can be expected for one or two frames during the transition.
2459 */
2460 if (pstate->aspace && pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002461 SDE_EVT32(DRMID(plane), pstate->aspace->domain_attached);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002462 /* prepare rotator input buffer */
2463 ret = msm_framebuffer_prepare(state->fb, pstate->aspace);
2464 if (ret) {
2465 SDE_ERROR("p%d failed to prepare input fb %d\n",
2466 plane->base.id, ret);
2467 return;
2468 }
2469
2470 /* prepare rotator output buffer */
2471 if (sde_plane_enabled(state) && rstate->out_fb) {
2472 ret = msm_framebuffer_prepare(rstate->out_fb,
2473 pstate->aspace);
2474 if (ret) {
2475 SDE_ERROR(
2476 "p%d failed to prepare inline fb %d\n",
2477 plane->base.id, ret);
2478 goto error_prepare_output_buffer;
2479 }
2480 }
2481 }
2482
Alan Kwong4dd64c82017-02-04 18:41:51 -08002483 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_COMMIT);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002484
2485 return;
2486
2487error_prepare_output_buffer:
2488 msm_framebuffer_cleanup(state->fb, pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002489}
2490
Clarence Ip2606dd62017-10-14 21:11:14 -04002491static bool _sde_plane_halt_requests(struct drm_plane *plane,
2492 uint32_t xin_id, bool halt_forced_clk, bool enable)
2493{
2494 struct sde_plane *psde;
2495 struct msm_drm_private *priv;
2496 struct sde_vbif_set_xin_halt_params halt_params;
2497
2498 if (!plane || !plane->dev) {
2499 SDE_ERROR("invalid arguments\n");
2500 return false;
2501 }
2502
2503 psde = to_sde_plane(plane);
2504 if (!psde->pipe_hw || !psde->pipe_hw->cap) {
2505 SDE_ERROR("invalid pipe reference\n");
2506 return false;
2507 }
2508
2509 priv = plane->dev->dev_private;
2510 if (!priv || !priv->kms) {
2511 SDE_ERROR("invalid KMS reference\n");
2512 return false;
2513 }
2514
2515 memset(&halt_params, 0, sizeof(halt_params));
2516 halt_params.vbif_idx = VBIF_RT;
2517 halt_params.xin_id = xin_id;
2518 halt_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
2519 halt_params.forced_on = halt_forced_clk;
2520 halt_params.enable = enable;
2521
2522 return sde_vbif_set_xin_halt(to_sde_kms(priv->kms), &halt_params);
2523}
2524
2525void sde_plane_halt_requests(struct drm_plane *plane, bool enable)
2526{
2527 struct sde_plane *psde;
2528
2529 if (!plane) {
2530 SDE_ERROR("invalid plane\n");
2531 return;
2532 }
2533
2534 psde = to_sde_plane(plane);
2535 if (!psde->pipe_hw || !psde->pipe_hw->cap) {
2536 SDE_ERROR("invalid pipe reference\n");
2537 return;
2538 }
2539
2540 SDE_EVT32(DRMID(plane), psde->xin_halt_forced_clk, enable);
2541
2542 psde->xin_halt_forced_clk =
2543 _sde_plane_halt_requests(plane, psde->pipe_hw->cap->xin_id,
2544 psde->xin_halt_forced_clk, enable);
2545}
2546
2547int sde_plane_reset_rot(struct drm_plane *plane, struct drm_plane_state *state)
2548{
2549 struct sde_plane *psde;
2550 struct sde_plane_state *pstate;
2551 struct sde_plane_rot_state *rstate;
2552 bool halt_ret[MAX_BLOCKS] = {false};
2553 signed int i, count;
2554
2555 if (!plane || !state) {
2556 SDE_ERROR("invalid plane\n");
2557 return -EINVAL;
2558 }
2559
2560 psde = to_sde_plane(plane);
2561 pstate = to_sde_plane_state(state);
2562 rstate = &pstate->rot;
2563
2564 /* do nothing if not master rotator plane */
2565 if (!rstate->out_sbuf || !rstate->rot_hw ||
2566 !rstate->rot_hw->caps || (rstate->out_xpos != 0))
2567 return 0;
2568
2569 count = (signed int)rstate->rot_hw->caps->xin_count;
2570 if (count > ARRAY_SIZE(halt_ret))
2571 count = ARRAY_SIZE(halt_ret);
2572
2573 SDE_DEBUG_PLANE(psde, "issuing reset for rotator\n");
2574 SDE_EVT32(DRMID(plane), count);
2575
2576 for (i = 0; i < count; i++) {
2577 const struct sde_rot_vbif_cfg *cfg =
2578 &rstate->rot_hw->caps->vbif_cfg[i];
2579
2580 halt_ret[i] = _sde_plane_halt_requests(plane, cfg->xin_id,
2581 false, true);
2582 }
2583
2584 sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_RESET);
2585
2586 for (i = count - 1; i >= 0; --i) {
2587 const struct sde_rot_vbif_cfg *cfg =
2588 &rstate->rot_hw->caps->vbif_cfg[i];
2589
2590 _sde_plane_halt_requests(plane, cfg->xin_id,
2591 halt_ret[i], false);
2592 }
2593 return 0;
2594}
2595
Clarence Ip8ee49952017-09-20 11:10:50 -04002596int sde_plane_kickoff_rot(struct drm_plane *plane)
Clarence Ipddbf7752017-05-21 18:07:30 -04002597{
Clarence Ipeb39cce2017-07-19 14:12:43 -04002598 struct sde_plane_state *pstate;
2599
2600 if (!plane || !plane->state) {
2601 SDE_ERROR("invalid plane\n");
Clarence Ip8ee49952017-09-20 11:10:50 -04002602 return -EINVAL;
Clarence Ipeb39cce2017-07-19 14:12:43 -04002603 }
2604
2605 pstate = to_sde_plane_state(plane->state);
2606
2607 if (!pstate->rot.rot_hw || !pstate->rot.rot_hw->ops.commit)
Clarence Ip8ee49952017-09-20 11:10:50 -04002608 return 0;
Clarence Ipddbf7752017-05-21 18:07:30 -04002609
Clarence Ip8ee49952017-09-20 11:10:50 -04002610 return pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
Clarence Ipddbf7752017-05-21 18:07:30 -04002611 &pstate->rot.rot_cmd,
2612 SDE_HW_ROT_CMD_START);
2613}
2614
2615/**
Alan Kwong4dd64c82017-02-04 18:41:51 -08002616 * sde_plane_rot_destroy_state - destroy state for rotator stage
2617 * @plane: Pointer to drm plane
2618 * @state: Pointer to state to be destroyed
2619 * return: none
2620 */
2621static void sde_plane_rot_destroy_state(struct drm_plane *plane,
2622 struct drm_plane_state *state)
2623{
2624 struct sde_plane_state *pstate = to_sde_plane_state(state);
2625 struct sde_plane_rot_state *rstate = &pstate->rot;
2626
2627 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d crtc:%d\n", plane->base.id,
2628 rstate->sequence_id,
2629 !!rstate->out_sbuf, !!rstate->rot_hw,
2630 sde_plane_crtc_enabled(state));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002631}
2632
2633/**
2634 * sde_plane_rot_duplicate_state - duplicate state for rotator stage
2635 * @plane: Pointer to drm plane
2636 * @new_state: Pointer to duplicated state
2637 * return: 0 if success; error code otherwise
2638 */
2639static int sde_plane_rot_duplicate_state(struct drm_plane *plane,
2640 struct drm_plane_state *new_state)
2641{
2642 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
2643 struct sde_plane_rot_state *rstate = &pstate->rot;
2644
2645 rstate->sequence_id++;
2646
2647 SDE_DEBUG("plane%d.%d sbuf:%d rot:%d\n", plane->base.id,
2648 rstate->sequence_id,
2649 !!rstate->out_sbuf, !!rstate->rot_hw);
2650
Clarence Ipf27c6f22017-07-10 18:19:44 -04002651 rstate->rot_hw = NULL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002652 rstate->out_fb = NULL;
2653 rstate->out_fbo = NULL;
2654
2655 return 0;
2656}
2657
2658/**
2659 * sde_plane_rot_install_caps - install plane rotator capabilities
2660 * @plane: Pointer to drm plane
2661 * return: none
2662 */
2663static void sde_plane_rot_install_caps(struct drm_plane *plane)
2664{
2665 struct sde_plane *psde = to_sde_plane(plane);
2666 const struct sde_format_extended *format_list;
2667 struct sde_kms_info *info;
2668 struct sde_hw_rot *rot_hw;
2669 const char *downscale_caps;
2670
2671 if (!psde->catalog || !(psde->features & BIT(SDE_SSPP_SBUF)) ||
2672 !psde->catalog->rot_count)
2673 return;
2674
2675 if (psde->blob_rot_caps)
2676 return;
2677
2678 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
2679 if (!info)
2680 return;
2681
2682 rot_hw = sde_hw_rot_get(NULL);
2683 if (!rot_hw || !rot_hw->ops.get_format_caps ||
2684 !rot_hw->ops.get_downscale_caps) {
2685 SDE_ERROR("invalid rotator hw\n");
2686 goto error_rot;
2687 }
2688
2689 sde_kms_info_reset(info);
2690
2691 format_list = rot_hw->ops.get_format_caps(rot_hw);
2692 if (format_list) {
2693 sde_kms_info_start(info, "pixel_formats");
2694 while (format_list->fourcc_format) {
2695 sde_kms_info_append_format(info,
2696 format_list->fourcc_format,
2697 format_list->modifier);
2698 ++format_list;
2699 }
2700 sde_kms_info_stop(info);
2701 }
2702
2703 downscale_caps = rot_hw->ops.get_downscale_caps(rot_hw);
2704 if (downscale_caps) {
2705 sde_kms_info_start(info, "downscale_ratios");
2706 sde_kms_info_append(info, downscale_caps);
2707 sde_kms_info_stop(info);
2708 }
2709
2710 if (rot_hw->ops.get_cache_size)
2711 sde_kms_info_add_keyint(info, "cache_size",
2712 rot_hw->ops.get_cache_size(rot_hw));
2713
Alan Kwong1a915802017-03-31 12:55:46 -07002714 if (rot_hw->ops.get_maxlinewidth)
2715 sde_kms_info_add_keyint(info, "max_linewidth",
2716 rot_hw->ops.get_maxlinewidth(rot_hw));
2717
Alan Kwong4dd64c82017-02-04 18:41:51 -08002718 msm_property_set_blob(&psde->property_info, &psde->blob_rot_caps,
Narendra Muppalla22d17252017-05-31 15:13:39 -07002719 info->data, SDE_KMS_INFO_DATALEN(info),
2720 PLANE_PROP_ROT_CAPS_V1);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002721
2722 sde_hw_rot_put(rot_hw);
2723error_rot:
2724 kfree(info);
2725}
2726
2727/**
2728 * sde_plane_rot_install_properties - install plane rotator properties
2729 * @plane: Pointer to drm plane
2730 * @catalog: Pointer to mdss configuration
2731 * return: none
2732 */
2733static void sde_plane_rot_install_properties(struct drm_plane *plane,
2734 struct sde_mdss_cfg *catalog)
2735{
2736 struct sde_plane *psde = to_sde_plane(plane);
Alan Kwong709150c2017-04-03 08:44:31 -07002737 unsigned long supported_rotations = DRM_ROTATE_0 | DRM_REFLECT_X |
2738 DRM_REFLECT_Y;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002739
2740 if (!plane || !psde) {
2741 SDE_ERROR("invalid plane\n");
2742 return;
2743 } else if (!catalog) {
2744 SDE_ERROR("invalid catalog\n");
2745 return;
2746 }
2747
2748 if ((psde->features & BIT(SDE_SSPP_SBUF)) && catalog->rot_count)
2749 supported_rotations |= DRM_ROTATE_0 | DRM_ROTATE_90 |
2750 DRM_ROTATE_180 | DRM_ROTATE_270;
2751
2752 msm_property_install_rotation(&psde->property_info,
2753 supported_rotations, PLANE_PROP_ROTATION);
2754
2755 if (!(psde->features & BIT(SDE_SSPP_SBUF)) || !catalog->rot_count)
2756 return;
2757
2758 msm_property_install_range(&psde->property_info, "rot_dst_x",
2759 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_X);
2760 msm_property_install_range(&psde->property_info, "rot_dst_y",
2761 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_Y);
2762 msm_property_install_range(&psde->property_info, "rot_dst_w",
2763 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_W);
2764 msm_property_install_range(&psde->property_info, "rot_dst_h",
2765 0, 0, U64_MAX, 0, PLANE_PROP_ROT_DST_H);
2766 msm_property_install_blob(&psde->property_info, "rot_caps_v1",
2767 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
2768}
2769
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002770void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
Clarence Ipcb410d42016-06-26 22:52:33 -04002771{
Clarence Ipcb410d42016-06-26 22:52:33 -04002772 struct sde_plane_state *pstate;
Clarence Ipcb410d42016-06-26 22:52:33 -04002773
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002774 if (!drm_state)
2775 return;
Clarence Ipcb410d42016-06-26 22:52:33 -04002776
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002777 pstate = to_sde_plane_state(drm_state);
Clarence Ipcb410d42016-06-26 22:52:33 -04002778
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002779 pstate->multirect_index = SDE_SSPP_RECT_SOLO;
2780 pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002781}
2782
2783int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
2784{
2785 struct sde_plane_state *pstate[R_MAX];
2786 const struct drm_plane_state *drm_state[R_MAX];
2787 struct sde_rect src[R_MAX], dst[R_MAX];
2788 struct sde_plane *sde_plane[R_MAX];
2789 const struct sde_format *fmt[R_MAX];
2790 bool q16_data = true;
Steve Cohenf5d01512017-07-07 18:49:21 -04002791 int i, buffer_lines;
2792 unsigned int max_tile_height = 1;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002793 bool parallel_fetch_qualified = true;
Steve Cohenf5d01512017-07-07 18:49:21 -04002794 bool has_tiled_rect = false;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002795
2796 for (i = 0; i < R_MAX; i++) {
2797 const struct msm_format *msm_fmt;
2798
2799 drm_state[i] = i ? plane->r1 : plane->r0;
Steve Cohenf5d01512017-07-07 18:49:21 -04002800 msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
2801 fmt[i] = to_sde_format(msm_fmt);
2802
2803 if (SDE_FORMAT_IS_UBWC(fmt[i])) {
2804 has_tiled_rect = true;
2805 if (fmt[i]->tile_height > max_tile_height)
2806 max_tile_height = fmt[i]->tile_height;
2807 }
2808 }
2809
2810 for (i = 0; i < R_MAX; i++) {
2811 int width_threshold;
2812
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002813 pstate[i] = to_sde_plane_state(drm_state[i]);
2814 sde_plane[i] = to_sde_plane(drm_state[i]->plane);
2815
2816 if (pstate[i] == NULL) {
2817 SDE_ERROR("SDE plane state of plane id %d is NULL\n",
2818 drm_state[i]->plane->base.id);
2819 return -EINVAL;
2820 }
2821
2822 POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
2823 drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
2824 POPULATE_RECT(&dst[i], drm_state[i]->crtc_x,
2825 drm_state[i]->crtc_y, drm_state[i]->crtc_w,
2826 drm_state[i]->crtc_h, !q16_data);
2827
2828 if (src[i].w != dst[i].w || src[i].h != dst[i].h) {
2829 SDE_ERROR_PLANE(sde_plane[i],
2830 "scaling is not supported in multirect mode\n");
2831 return -EINVAL;
2832 }
2833
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002834 if (SDE_FORMAT_IS_YUV(fmt[i])) {
2835 SDE_ERROR_PLANE(sde_plane[i],
2836 "Unsupported format for multirect mode\n");
2837 return -EINVAL;
2838 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002839
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002840 /**
2841 * SSPP PD_MEM is split half - one for each RECT.
2842 * Tiled formats need 5 lines of buffering while fetching
2843 * whereas linear formats need only 2 lines.
2844 * So we cannot support more than half of the supported SSPP
2845 * width for tiled formats.
2846 */
2847 width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
Steve Cohenf5d01512017-07-07 18:49:21 -04002848 if (has_tiled_rect)
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002849 width_threshold /= 2;
2850
2851 if (parallel_fetch_qualified && src[i].w > width_threshold)
2852 parallel_fetch_qualified = false;
2853
2854 }
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002855
2856 /* Validate RECT's and set the mode */
2857
2858 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002859 if (parallel_fetch_qualified) {
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002860 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
2861 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002862
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002863 goto done;
2864 }
2865
2866 /* TIME_MX Mode */
Steve Cohenf5d01512017-07-07 18:49:21 -04002867 buffer_lines = 2 * max_tile_height;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002868
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002869 if ((dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) ||
2870 (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines)) {
2871 pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
2872 pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002873 } else {
2874 SDE_ERROR(
2875 "No multirect mode possible for the planes (%d - %d)\n",
2876 drm_state[R0]->plane->base.id,
2877 drm_state[R1]->plane->base.id);
2878 return -EINVAL;
2879 }
2880
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08002881done:
Jeykumar Sankaranda780202017-06-11 20:27:13 -07002882 if (sde_plane[R0]->is_virtual) {
2883 pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
2884 pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
2885 } else {
2886 pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
2887 pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
2888 };
2889
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07002890 SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
2891 pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
2892 SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
2893 pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
Clarence Ip5e2a9222016-06-26 22:38:24 -04002894 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002895}
2896
Alan Kwong4dd64c82017-02-04 18:41:51 -08002897/**
2898 * sde_plane_get_ctl_flush - get control flush for the given plane
2899 * @plane: Pointer to drm plane structure
2900 * @ctl: Pointer to hardware control driver
Clarence Ip7e5f0002017-05-29 18:46:56 -04002901 * @flush_sspp: Pointer to sspp flush control word
2902 * @flush_rot: Pointer to rotator flush control word
Alan Kwong4dd64c82017-02-04 18:41:51 -08002903 */
2904void sde_plane_get_ctl_flush(struct drm_plane *plane, struct sde_hw_ctl *ctl,
Clarence Ip7e5f0002017-05-29 18:46:56 -04002905 u32 *flush_sspp, u32 *flush_rot)
Alan Kwong4dd64c82017-02-04 18:41:51 -08002906{
2907 struct sde_plane_state *pstate;
2908 struct sde_plane_rot_state *rstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002909
Clarence Ip7e5f0002017-05-29 18:46:56 -04002910 if (!plane || !flush_sspp) {
Alan Kwong4dd64c82017-02-04 18:41:51 -08002911 SDE_ERROR("invalid parameters\n");
2912 return;
2913 }
2914
2915 pstate = to_sde_plane_state(plane->state);
2916 rstate = &pstate->rot;
2917
Clarence Ip7e5f0002017-05-29 18:46:56 -04002918 *flush_sspp = ctl->ops.get_bitmask_sspp(ctl, sde_plane_pipe(plane));
Alan Kwong4dd64c82017-02-04 18:41:51 -08002919
Clarence Ip7e5f0002017-05-29 18:46:56 -04002920 if (!flush_rot)
2921 return;
2922
2923 *flush_rot = 0x0;
Clarence Ipb776b532017-09-12 18:30:06 -04002924 if (rstate && rstate->out_sbuf && rstate->rot_hw &&
Alan Kwong4dd64c82017-02-04 18:41:51 -08002925 ctl->ops.get_bitmask_rot)
Clarence Ip7e5f0002017-05-29 18:46:56 -04002926 ctl->ops.get_bitmask_rot(ctl, flush_rot, rstate->rot_hw->idx);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002927}
2928
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002929static int sde_plane_prepare_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07002930 struct drm_plane_state *new_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002931{
2932 struct drm_framebuffer *fb = new_state->fb;
2933 struct sde_plane *psde = to_sde_plane(plane);
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002934 struct sde_plane_state *pstate = to_sde_plane_state(new_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002935 struct sde_plane_rot_state *new_rstate;
Alan Kwong4a5bd782017-06-09 15:20:52 -04002936 struct sde_hw_fmt_layout layout;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002937 struct msm_gem_address_space *aspace;
Alan Kwong4dd64c82017-02-04 18:41:51 -08002938 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002939
2940 if (!new_state->fb)
2941 return 0;
2942
Clarence Ip13a8cf42016-09-29 17:27:47 -04002943 SDE_DEBUG_PLANE(psde, "FB[%u]\n", fb->base.id);
Alan Kwong4dd64c82017-02-04 18:41:51 -08002944
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002945 ret = _sde_plane_get_aspace(psde, pstate, &aspace);
2946 if (ret) {
2947 SDE_ERROR_PLANE(psde, "Failed to get aspace\n");
2948 return ret;
2949 }
2950
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002951 /* cache aspace */
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002952 pstate->aspace = aspace;
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002953
2954 /*
2955 * when transitioning from secure to non-secure,
2956 * plane->prepare_fb happens before the commit. In such case,
2957 * defer the prepare_fb and handled it late, during the commit
2958 * after attaching the domains as part of the transition
2959 */
2960 pstate->defer_prepare_fb = (aspace && !aspace->domain_attached) ?
2961 true : false;
2962
Alan Kwong4dd64c82017-02-04 18:41:51 -08002963 ret = sde_plane_rot_prepare_fb(plane, new_state);
2964 if (ret) {
2965 SDE_ERROR("failed to prepare rot framebuffer\n");
2966 return ret;
2967 }
2968
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002969 if (pstate->defer_prepare_fb) {
Veera Sundaram Sankaranfd792402017-10-13 12:50:41 -07002970 SDE_EVT32(DRMID(plane), psde->pipe);
Veera Sundaram Sankaran47e718f2017-09-13 16:47:23 -07002971 SDE_DEBUG_PLANE(psde,
2972 "domain not attached, prepare_fb handled later\n");
2973 return 0;
2974 }
2975
Alan Kwong4dd64c82017-02-04 18:41:51 -08002976 new_rstate = &to_sde_plane_state(new_state)->rot;
2977
Abhijit Kulkarni1b3340c2017-06-22 12:39:37 -07002978 if (pstate->aspace) {
2979 ret = msm_framebuffer_prepare(new_rstate->out_fb,
2980 pstate->aspace);
2981 if (ret) {
2982 SDE_ERROR("failed to prepare framebuffer\n");
2983 return ret;
2984 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08002985 }
2986
Alan Kwong4a5bd782017-06-09 15:20:52 -04002987 /* validate framebuffer layout before commit */
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07002988 ret = sde_format_populate_layout(pstate->aspace,
Alan Kwong4a5bd782017-06-09 15:20:52 -04002989 new_rstate->out_fb, &layout);
2990 if (ret) {
2991 SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
2992 return ret;
2993 }
2994
Alan Kwong4dd64c82017-02-04 18:41:51 -08002995 return 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04002996}
2997
Harsh Sahuea808372017-09-12 22:41:01 -07002998/**
2999 * _sde_plane_fetch_halt - halts vbif transactions for a plane
3000 * @plane: Pointer to plane
3001 * Returns: 0 on success
3002 */
3003static int _sde_plane_fetch_halt(struct drm_plane *plane)
3004{
3005 struct sde_plane *psde;
3006 int xin_id;
3007 enum sde_clk_ctrl_type clk_ctrl;
3008 struct msm_drm_private *priv;
3009 struct sde_kms *sde_kms;
3010
3011 psde = to_sde_plane(plane);
3012 if (!plane || !plane->dev || !psde->pipe_hw) {
3013 SDE_ERROR("invalid arguments\n");
3014 return -EINVAL;
3015 }
3016
3017 priv = plane->dev->dev_private;
3018 if (!priv || !priv->kms) {
3019 SDE_ERROR("invalid KMS reference\n");
3020 return -EINVAL;
3021 }
3022
3023 sde_kms = to_sde_kms(priv->kms);
3024 clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
3025 xin_id = psde->pipe_hw->cap->xin_id;
3026 SDE_DEBUG_PLANE(psde, "pipe:%d xin_id:%d clk_ctrl:%d\n",
3027 psde->pipe - SSPP_VIG0, xin_id, clk_ctrl);
3028 SDE_EVT32_VERBOSE(psde, psde->pipe - SSPP_VIG0, xin_id, clk_ctrl);
3029
3030 return sde_vbif_halt_plane_xin(sde_kms, xin_id, clk_ctrl);
3031}
3032
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003033static void sde_plane_cleanup_fb(struct drm_plane *plane,
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07003034 struct drm_plane_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003035{
Alan Kwong4dd64c82017-02-04 18:41:51 -08003036 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ip299fa602017-07-11 18:01:37 -04003037 struct sde_plane_state *old_pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003038 struct sde_plane_rot_state *old_rstate;
Harsh Sahuea808372017-09-12 22:41:01 -07003039 int ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003040
Harsh Sahuea808372017-09-12 22:41:01 -07003041 if (!old_state || !old_state->fb || !plane || !plane->state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003042 return;
3043
Clarence Ip299fa602017-07-11 18:01:37 -04003044 old_pstate = to_sde_plane_state(old_state);
3045
Alan Kwong4dd64c82017-02-04 18:41:51 -08003046 SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
3047
Harsh Sahuea808372017-09-12 22:41:01 -07003048 /*
3049 * plane->state gets populated for next frame after swap_state. If
3050 * plane->state->crtc pointer is not populated then it is not used in
3051 * the next frame, hence making it an unused plane.
3052 */
3053 if ((plane->state->crtc == NULL) && !psde->is_virtual) {
3054 SDE_DEBUG_PLANE(psde, "unused pipe:%u\n",
3055 psde->pipe - SSPP_VIG0);
3056
3057 /* halt this plane now */
3058 ret = _sde_plane_fetch_halt(plane);
3059 if (ret) {
3060 SDE_ERROR_PLANE(psde,
3061 "unused pipe %u halt failed\n",
3062 psde->pipe - SSPP_VIG0);
3063 SDE_EVT32(DRMID(plane), psde->pipe - SSPP_VIG0,
3064 ret, SDE_EVTLOG_ERROR);
3065 }
3066 }
3067
Clarence Ip299fa602017-07-11 18:01:37 -04003068 old_rstate = &old_pstate->rot;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003069
Clarence Ip299fa602017-07-11 18:01:37 -04003070 msm_framebuffer_cleanup(old_rstate->out_fb, old_pstate->aspace);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003071
3072 sde_plane_rot_cleanup_fb(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003073}
3074
Alan Kwong4dd64c82017-02-04 18:41:51 -08003075static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003076 struct drm_plane_state *state,
3077 struct drm_plane_state *old_state)
3078{
3079 struct sde_plane_state *pstate = to_sde_plane_state(state);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003080 struct sde_plane_state *old_pstate = to_sde_plane_state(old_state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003081 struct sde_plane_rot_state *rstate = &pstate->rot;
3082 struct sde_plane_rot_state *old_rstate = &old_pstate->rot;
3083 struct drm_framebuffer *fb, *old_fb;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003084
Dhaval Patel47302cf2016-08-18 15:04:28 -07003085 /* no need to check it again */
Clarence Ip282dad62016-09-27 17:07:35 -04003086 if (pstate->dirty == SDE_PLANE_DIRTY_ALL)
Dhaval Patel47302cf2016-08-18 15:04:28 -07003087 return;
3088
Clarence Ip282dad62016-09-27 17:07:35 -04003089 if (!sde_plane_enabled(state) || !sde_plane_enabled(old_state)
3090 || psde->is_error) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003091 SDE_DEBUG_PLANE(psde,
3092 "enabling/disabling full modeset required\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003093 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003094 } else if (to_sde_plane_state(old_state)->pending) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003095 SDE_DEBUG_PLANE(psde, "still pending\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003096 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003097 } else if (pstate->multirect_index != old_pstate->multirect_index ||
3098 pstate->multirect_mode != old_pstate->multirect_mode) {
3099 SDE_DEBUG_PLANE(psde, "multirect config updated\n");
3100 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003101 } else if (rstate->out_src_w != old_rstate->out_src_w ||
3102 rstate->out_src_h != old_rstate->out_src_h ||
3103 rstate->out_src_x != old_rstate->out_src_x ||
3104 rstate->out_src_y != old_rstate->out_src_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003105 SDE_DEBUG_PLANE(psde, "src rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003106 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003107 } else if (state->crtc_w != old_state->crtc_w ||
3108 state->crtc_h != old_state->crtc_h ||
3109 state->crtc_x != old_state->crtc_x ||
3110 state->crtc_y != old_state->crtc_y) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003111 SDE_DEBUG_PLANE(psde, "crtc rect updated\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003112 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003113 } else if (pstate->excl_rect.w != old_pstate->excl_rect.w ||
3114 pstate->excl_rect.h != old_pstate->excl_rect.h ||
3115 pstate->excl_rect.x != old_pstate->excl_rect.x ||
3116 pstate->excl_rect.y != old_pstate->excl_rect.y) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003117 SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003118 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Clarence Ip282dad62016-09-27 17:07:35 -04003119 }
3120
Alan Kwong4dd64c82017-02-04 18:41:51 -08003121 fb = rstate->out_fb;
3122 old_fb = old_rstate->out_fb;
3123
3124 if (!fb || !old_fb) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003125 SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
Alan Kwong4dd64c82017-02-04 18:41:51 -08003126 } else if (fb->pixel_format != old_fb->pixel_format) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003127 SDE_DEBUG_PLANE(psde, "format change\n");
Clarence Ip282dad62016-09-27 17:07:35 -04003128 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003129 } else {
Alan Kwong4dd64c82017-02-04 18:41:51 -08003130 uint64_t *new_mods = fb->modifier;
3131 uint64_t *old_mods = old_fb->modifier;
3132 uint32_t *new_pitches = fb->pitches;
3133 uint32_t *old_pitches = old_fb->pitches;
3134 uint32_t *new_offset = fb->offsets;
3135 uint32_t *old_offset = old_fb->offsets;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003136 int i;
3137
Alan Kwong4dd64c82017-02-04 18:41:51 -08003138 for (i = 0; i < ARRAY_SIZE(fb->modifier); i++) {
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003139 if (new_mods[i] != old_mods[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003140 SDE_DEBUG_PLANE(psde,
3141 "format modifiers change\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07003142 plane:%d new_mode:%llu old_mode:%llu\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04003143 i, new_mods[i], old_mods[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04003144 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
3145 SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003146 break;
3147 }
3148 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08003149 for (i = 0; i < ARRAY_SIZE(fb->pitches); i++) {
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04003150 if (new_pitches[i] != old_pitches[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003151 SDE_DEBUG_PLANE(psde,
3152 "pitches change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07003153 old_pitches:%u new_pitches:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04003154 i, old_pitches[i], new_pitches[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04003155 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04003156 break;
3157 }
3158 }
Alan Kwong4dd64c82017-02-04 18:41:51 -08003159 for (i = 0; i < ARRAY_SIZE(fb->offsets); i++) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07003160 if (new_offset[i] != old_offset[i]) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003161 SDE_DEBUG_PLANE(psde,
3162 "offset change plane:%d\"\
Dhaval Patel47302cf2016-08-18 15:04:28 -07003163 old_offset:%u new_offset:%u\n",
Clarence Ip13a8cf42016-09-29 17:27:47 -04003164 i, old_offset[i], new_offset[i]);
Clarence Ip282dad62016-09-27 17:07:35 -04003165 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT |
3166 SDE_PLANE_DIRTY_RECTS;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003167 break;
3168 }
3169 }
Lloyd Atkinson3ab9ef72016-07-14 17:42:41 -04003170 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003171}
3172
Clarence Ip059c8c32017-06-06 17:15:54 -04003173static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
Clarence Ip172033f2017-06-13 10:52:56 -04003174 struct sde_plane_state *pstate,
Clarence Ip059c8c32017-06-06 17:15:54 -04003175 const struct sde_format *fmt,
3176 uint32_t img_w, uint32_t img_h,
3177 uint32_t src_w, uint32_t src_h,
3178 uint32_t deci_w, uint32_t deci_h)
3179{
3180 int i;
3181
Clarence Ip172033f2017-06-13 10:52:56 -04003182 if (!psde || !pstate || !fmt) {
Clarence Ip059c8c32017-06-06 17:15:54 -04003183 SDE_ERROR_PLANE(psde, "invalid arguments\n");
3184 return -EINVAL;
3185 }
3186
Dhaval Patel9c6acc12017-10-17 10:54:32 -07003187 if (psde->debugfs_default_scale ||
3188 (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2 &&
3189 pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK))
Clarence Ip059c8c32017-06-06 17:15:54 -04003190 return 0;
3191
Clarence Ip172033f2017-06-13 10:52:56 -04003192 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
Clarence Ip059c8c32017-06-06 17:15:54 -04003193
3194 for (i = 0; i < SDE_MAX_PLANES; i++) {
3195 uint32_t hor_req_pixels, hor_fetch_pixels;
3196 uint32_t vert_req_pixels, vert_fetch_pixels;
3197 uint32_t src_w_tmp, src_h_tmp;
3198
3199 /* re-use color plane 1's config for plane 2 */
3200 if (i == 2)
3201 continue;
3202
3203 src_w_tmp = src_w;
3204 src_h_tmp = src_h;
3205
3206 /*
3207 * For chroma plane, width is half for the following sub sampled
3208 * formats. Except in case of decimation, where hardware avoids
3209 * 1 line of decimation instead of downsampling.
3210 */
3211 if (i == 1) {
3212 if (!deci_w &&
3213 (fmt->chroma_sample == SDE_CHROMA_420 ||
3214 fmt->chroma_sample == SDE_CHROMA_H2V1))
3215 src_w_tmp >>= 1;
3216 if (!deci_h &&
3217 (fmt->chroma_sample == SDE_CHROMA_420 ||
3218 fmt->chroma_sample == SDE_CHROMA_H1V2))
3219 src_h_tmp >>= 1;
3220 }
3221
Clarence Ip172033f2017-06-13 10:52:56 -04003222 hor_req_pixels = pstate->pixel_ext.roi_w[i];
3223 vert_req_pixels = pstate->pixel_ext.roi_h[i];
Clarence Ip059c8c32017-06-06 17:15:54 -04003224
3225 hor_fetch_pixels = DECIMATED_DIMENSION(src_w_tmp +
Clarence Ip172033f2017-06-13 10:52:56 -04003226 (int8_t)(pstate->pixel_ext.left_ftch[i] & 0xFF) +
3227 (int8_t)(pstate->pixel_ext.right_ftch[i] & 0xFF),
3228 deci_w);
Clarence Ip059c8c32017-06-06 17:15:54 -04003229 vert_fetch_pixels = DECIMATED_DIMENSION(src_h_tmp +
Clarence Ip172033f2017-06-13 10:52:56 -04003230 (int8_t)(pstate->pixel_ext.top_ftch[i] & 0xFF) +
3231 (int8_t)(pstate->pixel_ext.btm_ftch[i] & 0xFF),
3232 deci_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04003233
3234 if ((hor_req_pixels != hor_fetch_pixels) ||
3235 (hor_fetch_pixels > img_w) ||
3236 (vert_req_pixels != vert_fetch_pixels) ||
3237 (vert_fetch_pixels > img_h)) {
3238 SDE_ERROR_PLANE(psde,
3239 "req %d/%d, fetch %d/%d, src %dx%d\n",
3240 hor_req_pixels, vert_req_pixels,
3241 hor_fetch_pixels, vert_fetch_pixels,
Clarence Ip3b1e2c62017-06-14 11:20:44 -04003242 img_w, img_h);
Clarence Ip059c8c32017-06-06 17:15:54 -04003243 return -EINVAL;
3244 }
3245
3246 /*
3247 * Alpha plane can only be scaled using bilinear or pixel
3248 * repeat/drop, src_width and src_height are only specified
3249 * for Y and UV plane
3250 */
3251 if (i != 3 &&
Clarence Ip172033f2017-06-13 10:52:56 -04003252 (hor_req_pixels != pstate->scaler3_cfg.src_width[i] ||
3253 vert_req_pixels != pstate->scaler3_cfg.src_height[i])) {
Clarence Ip059c8c32017-06-06 17:15:54 -04003254 SDE_ERROR_PLANE(psde,
3255 "roi[%d] %d/%d, scaler src %dx%d, src %dx%d\n",
Clarence Ip172033f2017-06-13 10:52:56 -04003256 i, pstate->pixel_ext.roi_w[i],
3257 pstate->pixel_ext.roi_h[i],
3258 pstate->scaler3_cfg.src_width[i],
3259 pstate->scaler3_cfg.src_height[i],
Clarence Ip059c8c32017-06-06 17:15:54 -04003260 src_w, src_h);
3261 return -EINVAL;
3262 }
3263 }
3264
Clarence Ip172033f2017-06-13 10:52:56 -04003265 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
Clarence Ip059c8c32017-06-06 17:15:54 -04003266 return 0;
3267}
3268
Alan Kwong4dd64c82017-02-04 18:41:51 -08003269static int sde_plane_sspp_atomic_check(struct drm_plane *plane,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003270 struct drm_plane_state *state)
3271{
Clarence Ipdedbba92016-09-27 17:43:10 -04003272 int ret = 0;
Clarence Ipdbde9832016-06-26 09:48:36 -04003273 struct sde_plane *psde;
3274 struct sde_plane_state *pstate;
Alan Kwong4dd64c82017-02-04 18:41:51 -08003275 struct sde_plane_rot_state *rstate;
Lloyd Atkinson9a673492016-07-05 11:41:57 -04003276 const struct sde_format *fmt;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003277 struct sde_rect src, dst;
Clarence Ipdbde9832016-06-26 09:48:36 -04003278 uint32_t deci_w, deci_h, src_deci_w, src_deci_h;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003279 uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
3280 bool q16_data = true;
Clarence Ipdbde9832016-06-26 09:48:36 -04003281
3282 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003283 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3284 plane != 0, state != 0);
Clarence Ipdbde9832016-06-26 09:48:36 -04003285 ret = -EINVAL;
3286 goto exit;
3287 }
3288
3289 psde = to_sde_plane(plane);
3290 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08003291 rstate = &pstate->rot;
Clarence Ipdbde9832016-06-26 09:48:36 -04003292
3293 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003294 SDE_ERROR_PLANE(psde, "invalid catalog\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003295 ret = -EINVAL;
3296 goto exit;
3297 }
3298
Clarence Ipdedbba92016-09-27 17:43:10 -04003299 deci_w = sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
3300 deci_h = sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
Clarence Ipdbde9832016-06-26 09:48:36 -04003301
3302 /* src values are in Q16 fixed point, convert to integer */
Alan Kwong4dd64c82017-02-04 18:41:51 -08003303 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3304 rstate->out_src_w, rstate->out_src_h, q16_data);
Dhaval Patel47302cf2016-08-18 15:04:28 -07003305 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w,
3306 state->crtc_h, !q16_data);
Clarence Ipdbde9832016-06-26 09:48:36 -04003307
Dhaval Patel47302cf2016-08-18 15:04:28 -07003308 src_deci_w = DECIMATED_DIMENSION(src.w, deci_w);
3309 src_deci_h = DECIMATED_DIMENSION(src.h, deci_h);
Clarence Ipdbde9832016-06-26 09:48:36 -04003310
Dhaval Patel47302cf2016-08-18 15:04:28 -07003311 max_upscale = psde->pipe_sblk->maxupscale;
3312 max_downscale = psde->pipe_sblk->maxdwnscale;
3313 max_linewidth = psde->pipe_sblk->maxlinewidth;
Clarence Ipdbde9832016-06-26 09:48:36 -04003314
Clarence Ip13a8cf42016-09-29 17:27:47 -04003315 SDE_DEBUG_PLANE(psde, "check %d -> %d\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003316 sde_plane_enabled(plane->state), sde_plane_enabled(state));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003317
Dhaval Patel47302cf2016-08-18 15:04:28 -07003318 if (!sde_plane_enabled(state))
3319 goto modeset_update;
Clarence Ipdbde9832016-06-26 09:48:36 -04003320
Alan Kwong4dd64c82017-02-04 18:41:51 -08003321 SDE_DEBUG(
Dhaval Patel6c666622017-03-21 23:02:59 -07003322 "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 -08003323 plane->base.id, rstate->sequence_id,
3324 rstate->out_rotation,
3325 rstate->out_fb_width, rstate->out_fb_height,
Dhaval Patel6c666622017-03-21 23:02:59 -07003326 (char *) &rstate->out_fb_pixel_format,
Alan Kwong4dd64c82017-02-04 18:41:51 -08003327 rstate->out_fb_modifier[0],
3328 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3329 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3330 state->crtc_w, state->crtc_h,
3331 state->crtc_x, state->crtc_y);
3332
Dhaval Patel47302cf2016-08-18 15:04:28 -07003333 fmt = to_sde_format(msm_framebuffer_format(state->fb));
3334
3335 min_src_size = SDE_FORMAT_IS_YUV(fmt) ? 2 : 1;
3336
3337 if (SDE_FORMAT_IS_YUV(fmt) &&
3338 (!(psde->features & SDE_SSPP_SCALER) ||
abeykun1c312f62016-08-26 09:47:12 -04003339 !(psde->features & (BIT(SDE_SSPP_CSC)
3340 | BIT(SDE_SSPP_CSC_10BIT))))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003341 SDE_ERROR_PLANE(psde,
3342 "plane doesn't have scaler/csc for yuv\n");
Dhaval Patel47302cf2016-08-18 15:04:28 -07003343 ret = -EINVAL;
3344
3345 /* check src bounds */
Alan Kwong4dd64c82017-02-04 18:41:51 -08003346 } else if (rstate->out_fb_width > MAX_IMG_WIDTH ||
3347 rstate->out_fb_height > MAX_IMG_HEIGHT ||
Dhaval Patel47302cf2016-08-18 15:04:28 -07003348 src.w < min_src_size || src.h < min_src_size ||
Alan Kwong4dd64c82017-02-04 18:41:51 -08003349 CHECK_LAYER_BOUNDS(src.x, src.w, rstate->out_fb_width) ||
3350 CHECK_LAYER_BOUNDS(src.y, src.h, rstate->out_fb_height)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003351 SDE_ERROR_PLANE(psde, "invalid source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003352 src.x, src.y, src.w, src.h);
3353 ret = -E2BIG;
3354
3355 /* valid yuv image */
3356 } else if (SDE_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) ||
3357 (src.w & 0x1) || (src.h & 0x1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003358 SDE_ERROR_PLANE(psde, "invalid yuv source %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003359 src.x, src.y, src.w, src.h);
3360 ret = -EINVAL;
3361
3362 /* min dst support */
3363 } else if (dst.w < 0x1 || dst.h < 0x1) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003364 SDE_ERROR_PLANE(psde, "invalid dest rect %u, %u, %ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003365 dst.x, dst.y, dst.w, dst.h);
3366 ret = -EINVAL;
3367
3368 /* decimation validation */
3369 } else if (deci_w || deci_h) {
3370 if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
3371 (deci_h > psde->pipe_sblk->maxvdeciexp)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003372 SDE_ERROR_PLANE(psde,
3373 "too much decimation requested\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003374 ret = -EINVAL;
Dhaval Patel47302cf2016-08-18 15:04:28 -07003375 } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003376 SDE_ERROR_PLANE(psde,
3377 "decimation requires linear fetch\n");
Clarence Ipdbde9832016-06-26 09:48:36 -04003378 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003379 }
3380
Dhaval Patel47302cf2016-08-18 15:04:28 -07003381 } else if (!(psde->features & SDE_SSPP_SCALER) &&
3382 ((src.w != dst.w) || (src.h != dst.h))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003383 SDE_ERROR_PLANE(psde,
3384 "pipe doesn't support scaling %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003385 src.w, src.h, dst.w, dst.h);
3386 ret = -EINVAL;
3387
3388 /* check decimated source width */
3389 } else if (src_deci_w > max_linewidth) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003390 SDE_ERROR_PLANE(psde,
3391 "invalid src w:%u, deci w:%u, line w:%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003392 src.w, src_deci_w, max_linewidth);
3393 ret = -E2BIG;
3394
3395 /* check max scaler capability */
3396 } else if (((src_deci_w * max_upscale) < dst.w) ||
3397 ((src_deci_h * max_upscale) < dst.h) ||
3398 ((dst.w * max_downscale) < src_deci_w) ||
3399 ((dst.h * max_downscale) < src_deci_h)) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003400 SDE_ERROR_PLANE(psde,
3401 "too much scaling requested %ux%u->%ux%u\n",
Dhaval Patel47302cf2016-08-18 15:04:28 -07003402 src_deci_w, src_deci_h, dst.w, dst.h);
3403 ret = -E2BIG;
Clarence Ip172033f2017-06-13 10:52:56 -04003404 } else if (_sde_plane_validate_scaler_v2(psde, pstate, fmt,
Clarence Ip059c8c32017-06-06 17:15:54 -04003405 rstate->out_fb_width,
3406 rstate->out_fb_height,
3407 src.w, src.h, deci_w, deci_h)) {
3408 ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003409 }
3410
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003411 /* check excl rect configs */
Clarence Ip059c8c32017-06-06 17:15:54 -04003412 if (!ret && pstate->excl_rect.w && pstate->excl_rect.h) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003413 struct sde_rect intersect;
3414
3415 /*
3416 * Check exclusion rect against src rect.
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003417 * it must intersect with source rect.
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003418 */
Lloyd Atkinsone0e11e22017-01-17 12:08:48 -05003419 sde_kms_rect_intersect(&src, &pstate->excl_rect, &intersect);
Dhaval Patela8d6bc62017-05-10 17:40:18 -07003420 if (intersect.w != pstate->excl_rect.w ||
3421 intersect.h != pstate->excl_rect.h ||
3422 SDE_FORMAT_IS_YUV(fmt)) {
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003423 SDE_ERROR_PLANE(psde,
Dhaval Patel6c666622017-03-21 23:02:59 -07003424 "invalid excl_rect:{%d,%d,%d,%d} src:{%d,%d,%d,%d}, fmt: %4.4s\n",
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003425 pstate->excl_rect.x, pstate->excl_rect.y,
3426 pstate->excl_rect.w, pstate->excl_rect.h,
3427 src.x, src.y, src.w, src.h,
Dhaval Patel6c666622017-03-21 23:02:59 -07003428 (char *)&fmt->base.pixel_format);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003429 ret = -EINVAL;
3430 }
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07003431 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
3432 pstate->excl_rect.x, pstate->excl_rect.y,
3433 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08003434 }
3435
Dhaval Patel47302cf2016-08-18 15:04:28 -07003436modeset_update:
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04003437 if (!ret)
Alan Kwong4dd64c82017-02-04 18:41:51 -08003438 _sde_plane_sspp_atomic_check_mode_changed(psde,
3439 state, plane->state);
3440exit:
3441 return ret;
3442}
3443
3444static int sde_plane_atomic_check(struct drm_plane *plane,
3445 struct drm_plane_state *state)
3446{
3447 int ret = 0;
3448 struct sde_plane *psde;
3449 struct sde_plane_state *pstate;
3450
3451 if (!plane || !state) {
3452 SDE_ERROR("invalid arg(s), plane %d state %d\n",
3453 plane != 0, state != 0);
3454 ret = -EINVAL;
3455 goto exit;
3456 }
3457
3458 psde = to_sde_plane(plane);
3459 pstate = to_sde_plane_state(state);
3460
3461 SDE_DEBUG_PLANE(psde, "\n");
3462
3463 ret = sde_plane_rot_atomic_check(plane, state);
3464 if (ret)
3465 goto exit;
3466
3467 ret = sde_plane_sspp_atomic_check(plane, state);
3468
Clarence Ipdbde9832016-06-26 09:48:36 -04003469exit:
3470 return ret;
3471}
3472
Clarence Ipcae1bb62016-07-07 12:07:13 -04003473void sde_plane_flush(struct drm_plane *plane)
Clarence Ipdbde9832016-06-26 09:48:36 -04003474{
Clarence Ipcae1bb62016-07-07 12:07:13 -04003475 struct sde_plane *psde;
Clarence Ipddbf7752017-05-21 18:07:30 -04003476 struct sde_plane_state *pstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -04003477
Clarence Ipddbf7752017-05-21 18:07:30 -04003478 if (!plane || !plane->state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04003479 SDE_ERROR("invalid plane\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -04003480 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04003481 }
Clarence Ipcae1bb62016-07-07 12:07:13 -04003482
3483 psde = to_sde_plane(plane);
Clarence Ipddbf7752017-05-21 18:07:30 -04003484 pstate = to_sde_plane_state(plane->state);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003485
3486 /*
3487 * These updates have to be done immediately before the plane flush
3488 * timing, and may not be moved to the atomic_update/mode_set functions.
3489 */
3490 if (psde->is_error)
Clarence Ip3bf8d872017-02-16 15:25:38 -05003491 /* force white frame with 100% alpha pipe output on error */
3492 _sde_plane_color_fill(psde, 0xFFFFFF, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003493 else if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG)
3494 /* force 100% alpha */
Clarence Ip13a8cf42016-09-29 17:27:47 -04003495 _sde_plane_color_fill(psde, psde->color_fill, 0xFF);
Clarence Ipcae1bb62016-07-07 12:07:13 -04003496 else if (psde->pipe_hw && psde->csc_ptr && psde->pipe_hw->ops.setup_csc)
3497 psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
3498
3499 /* flag h/w flush complete */
3500 if (plane->state)
Clarence Ipddbf7752017-05-21 18:07:30 -04003501 pstate->pending = false;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003502}
3503
Abhijit Kulkarni1b3340c2017-06-22 12:39:37 -07003504/**
3505 * sde_plane_set_error: enable/disable error condition
3506 * @plane: pointer to drm_plane structure
3507 */
3508void sde_plane_set_error(struct drm_plane *plane, bool error)
3509{
3510 struct sde_plane *psde;
3511
3512 if (!plane)
3513 return;
3514
3515 psde = to_sde_plane(plane);
3516 psde->is_error = error;
3517}
3518
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003519static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
3520 struct drm_plane_state *old_state)
3521{
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003522 uint32_t nplanes, src_flags;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003523 struct sde_plane *psde;
3524 struct drm_plane_state *state;
3525 struct sde_plane_state *pstate;
3526 struct sde_plane_state *old_pstate;
3527 struct sde_plane_rot_state *rstate;
3528 const struct sde_format *fmt;
3529 struct drm_crtc *crtc;
3530 struct drm_framebuffer *fb;
3531 struct sde_rect src, dst;
3532 const struct sde_rect *crtc_roi;
3533 bool q16_data = true;
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07003534 bool blend_enabled = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003535 int idx;
3536
3537 if (!plane) {
3538 SDE_ERROR("invalid plane\n");
3539 return -EINVAL;
3540 } else if (!plane->state) {
3541 SDE_ERROR("invalid plane state\n");
3542 return -EINVAL;
3543 } else if (!old_state) {
3544 SDE_ERROR("invalid old state\n");
3545 return -EINVAL;
3546 }
3547
3548 psde = to_sde_plane(plane);
3549 state = plane->state;
3550
3551 pstate = to_sde_plane_state(state);
3552 rstate = &pstate->rot;
3553
3554 old_pstate = to_sde_plane_state(old_state);
3555
3556 crtc = state->crtc;
3557 fb = rstate->out_fb;
3558 if (!crtc || !fb) {
3559 SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
3560 crtc != 0, fb != 0);
3561 return -EINVAL;
3562 }
3563 fmt = to_sde_format(msm_framebuffer_format(fb));
3564 nplanes = fmt->num_planes;
3565
3566 SDE_DEBUG(
3567 "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
3568 plane->base.id, rstate->sequence_id,
3569 rstate->out_fb_width, rstate->out_fb_height,
3570 (char *) &rstate->out_fb_pixel_format,
3571 rstate->out_fb_modifier[0],
3572 rstate->out_src_w >> 16, rstate->out_src_h >> 16,
3573 rstate->out_src_x >> 16, rstate->out_src_y >> 16,
3574 rstate->out_rotation,
3575 state->crtc_w, state->crtc_h,
3576 state->crtc_x, state->crtc_y);
3577
3578 /* force reprogramming of all the parameters, if the flag is set */
3579 if (psde->revalidate) {
3580 SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
3581 plane->base.id);
3582 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3583 psde->revalidate = false;
3584 }
3585
3586 /* determine what needs to be refreshed */
Clarence Ip4a2955d2017-07-04 18:04:33 -04003587 while ((idx = msm_property_pop_dirty(&psde->property_info,
3588 &pstate->property_state)) >= 0) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003589 switch (idx) {
3590 case PLANE_PROP_SCALER_V1:
3591 case PLANE_PROP_SCALER_V2:
Clarence Ip059c8c32017-06-06 17:15:54 -04003592 case PLANE_PROP_SCALER_LUT_ED:
3593 case PLANE_PROP_SCALER_LUT_CIR:
3594 case PLANE_PROP_SCALER_LUT_SEP:
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003595 case PLANE_PROP_H_DECIMATE:
3596 case PLANE_PROP_V_DECIMATE:
3597 case PLANE_PROP_SRC_CONFIG:
3598 case PLANE_PROP_ZPOS:
3599 case PLANE_PROP_EXCL_RECT_V1:
3600 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3601 break;
3602 case PLANE_PROP_CSC_V1:
3603 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3604 break;
3605 case PLANE_PROP_COLOR_FILL:
3606 /* potentially need to refresh everything */
3607 pstate->dirty = SDE_PLANE_DIRTY_ALL;
3608 break;
3609 case PLANE_PROP_ROTATION:
3610 pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
3611 break;
3612 case PLANE_PROP_INFO:
3613 case PLANE_PROP_ALPHA:
3614 case PLANE_PROP_INPUT_FENCE:
3615 case PLANE_PROP_BLEND_OP:
3616 /* no special action required */
3617 break;
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003618 case PLANE_PROP_FB_TRANSLATION_MODE:
3619 pstate->dirty |= SDE_PLANE_DIRTY_FB_TRANSLATION_MODE;
3620 break;
Alan Kwong2349d742017-04-20 08:27:30 -07003621 case PLANE_PROP_PREFILL_SIZE:
3622 case PLANE_PROP_PREFILL_TIME:
3623 pstate->dirty |= SDE_PLANE_DIRTY_PERF;
3624 break;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003625 case PLANE_PROP_ROT_DST_X:
3626 case PLANE_PROP_ROT_DST_Y:
3627 case PLANE_PROP_ROT_DST_W:
3628 case PLANE_PROP_ROT_DST_H:
3629 /* handled by rotator atomic update */
3630 break;
3631 default:
3632 /* unknown property, refresh everything */
3633 pstate->dirty |= SDE_PLANE_DIRTY_ALL;
3634 SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
3635 break;
3636 }
3637 }
3638
3639 /**
3640 * since plane_atomic_check is invoked before crtc_atomic_check
3641 * in the commit sequence, all the parameters for updating the
3642 * plane dirty flag will not be available during
3643 * plane_atomic_check as some features params are updated
3644 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
3645 * before sspp update.
3646 */
3647 _sde_plane_sspp_atomic_check_mode_changed(psde, state,
3648 old_state);
3649
3650 /* re-program the output rects always in the case of partial update */
3651 sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
3652 if (!sde_kms_rect_is_null(crtc_roi))
3653 pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
3654
3655 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
3656 memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
3657
3658 _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
3659
3660 /* early out if nothing dirty */
3661 if (!pstate->dirty)
3662 return 0;
3663 pstate->pending = true;
3664
3665 psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
3666 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
3667
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003668 /* update secure session flag */
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003669 if (pstate->dirty & SDE_PLANE_DIRTY_FB_TRANSLATION_MODE) {
3670 bool enable = false;
3671 int mode = sde_plane_get_property(pstate,
3672 PLANE_PROP_FB_TRANSLATION_MODE);
3673
3674 if ((mode == SDE_DRM_FB_SEC) ||
3675 (mode == SDE_DRM_FB_SEC_DIR_TRANS))
3676 enable = true;
3677 /* update secure session flag */
3678 psde->pipe_hw->ops.setup_secure_address(psde->pipe_hw,
3679 pstate->multirect_index,
3680 enable);
3681 }
Abhijit Kulkarni333d6c02017-05-01 18:32:18 -07003682
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003683 /* update roi config */
3684 if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
3685 POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
3686 rstate->out_src_w, rstate->out_src_h, q16_data);
3687 POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
3688 state->crtc_w, state->crtc_h, !q16_data);
3689
3690 SDE_DEBUG_PLANE(psde,
3691 "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
3692 fb->base.id, src.x, src.y, src.w, src.h,
3693 crtc->base.id, dst.x, dst.y, dst.w, dst.h,
3694 (char *)&fmt->base.pixel_format,
3695 SDE_FORMAT_IS_UBWC(fmt));
3696
3697 if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
3698 BIT(SDE_DRM_DEINTERLACE)) {
3699 SDE_DEBUG_PLANE(psde, "deinterlace\n");
3700 for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
3701 psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
3702 src.h /= 2;
3703 src.y = DIV_ROUND_UP(src.y, 2);
3704 src.y &= ~0x1;
3705 }
3706
3707 /*
3708 * adjust layer mixer position of the sspp in the presence
3709 * of a partial update to the active lm origin
3710 */
3711 dst.x -= crtc_roi->x;
3712 dst.y -= crtc_roi->y;
3713
3714 psde->pipe_cfg.src_rect = src;
3715 psde->pipe_cfg.dst_rect = dst;
3716
Clarence Ip172033f2017-06-13 10:52:56 -04003717 _sde_plane_setup_scaler(psde, pstate, fmt, false);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003718
3719 /* check for color fill */
3720 psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
3721 PLANE_PROP_COLOR_FILL);
3722 if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
3723 /* skip remaining processing on color fill */
3724 pstate->dirty = 0x0;
3725 } else if (psde->pipe_hw->ops.setup_rects) {
3726 psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
3727 &psde->pipe_cfg,
3728 pstate->multirect_index);
3729 }
3730
Jeykumar Sankaran0532e0a2017-06-11 20:34:44 -07003731 if (psde->pipe_hw->ops.setup_pe &&
3732 (pstate->multirect_index != SDE_SSPP_RECT_1))
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003733 psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04003734 &pstate->pixel_ext);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003735
3736 /**
3737 * when programmed in multirect mode, scalar block will be
3738 * bypassed. Still we need to update alpha and bitwidth
3739 * ONLY for RECT0
3740 */
3741 if (psde->pipe_hw->ops.setup_scaler &&
3742 pstate->multirect_index != SDE_SSPP_RECT_1)
3743 psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
Clarence Ip172033f2017-06-13 10:52:56 -04003744 &psde->pipe_cfg, &pstate->pixel_ext,
3745 &pstate->scaler3_cfg);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003746
3747 /* update excl rect */
3748 if (psde->pipe_hw->ops.setup_excl_rect)
3749 psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
3750 &pstate->excl_rect,
3751 pstate->multirect_index);
3752
3753 if (psde->pipe_hw->ops.setup_multirect)
3754 psde->pipe_hw->ops.setup_multirect(
3755 psde->pipe_hw,
3756 pstate->multirect_index,
3757 pstate->multirect_mode);
3758 }
3759
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003760 if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003761 psde->pipe_hw->ops.setup_format) {
Abhijit Kulkarnia1a4b782017-07-12 15:08:38 -07003762 src_flags = 0x0;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003763 SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
3764 if (rstate->out_rotation & DRM_REFLECT_X)
3765 src_flags |= SDE_SSPP_FLIP_LR;
3766 if (rstate->out_rotation & DRM_REFLECT_Y)
3767 src_flags |= SDE_SSPP_FLIP_UD;
3768
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07003769 blend_enabled = (SDE_DRM_BLEND_OP_OPAQUE !=
3770 sde_plane_get_property(pstate, PLANE_PROP_BLEND_OP));
3771
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003772 /* update format */
Prabhanjan Kandula32c4c922017-10-23 15:03:23 -07003773 psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt,
3774 blend_enabled, src_flags,
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003775 pstate->multirect_index);
3776
Alan Kwong143f50c2017-04-28 07:34:28 -07003777 if (psde->pipe_hw->ops.setup_cdp) {
3778 struct sde_hw_pipe_cdp_cfg *cdp_cfg = &pstate->cdp_cfg;
3779
3780 memset(cdp_cfg, 0, sizeof(struct sde_hw_pipe_cdp_cfg));
3781
3782 cdp_cfg->enable = psde->catalog->perf.cdp_cfg
3783 [SDE_PERF_CDP_USAGE_RT].rd_enable;
3784 cdp_cfg->ubwc_meta_enable =
3785 SDE_FORMAT_IS_UBWC(fmt);
3786 cdp_cfg->tile_amortize_enable =
3787 SDE_FORMAT_IS_UBWC(fmt) ||
3788 SDE_FORMAT_IS_TILE(fmt);
3789 cdp_cfg->preload_ahead = SDE_WB_CDP_PRELOAD_AHEAD_64;
3790
Alan Kwong1b6b4572017-09-25 15:58:14 -04003791 psde->pipe_hw->ops.setup_cdp(psde->pipe_hw, cdp_cfg,
3792 pstate->multirect_index);
Alan Kwong143f50c2017-04-28 07:34:28 -07003793 }
3794
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003795 if (psde->pipe_hw->ops.setup_sys_cache) {
Clarence Ipf27c6f22017-07-10 18:19:44 -04003796 if (rstate->out_sbuf && rstate->rot_hw) {
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003797 if (rstate->nplane < 2)
3798 pstate->sc_cfg.op_mode =
3799 SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
3800 else if (rstate->out_xpos == 0)
3801 pstate->sc_cfg.op_mode =
3802 SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
3803 else
3804 pstate->sc_cfg.op_mode =
3805 SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
3806
3807 pstate->sc_cfg.rd_en = true;
3808 pstate->sc_cfg.rd_scid =
3809 rstate->rot_hw->caps->scid;
3810 pstate->sc_cfg.rd_noallocate = true;
3811 pstate->sc_cfg.rd_op_type =
3812 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3813 } else {
3814 pstate->sc_cfg.op_mode =
3815 SDE_PIPE_SC_OP_MODE_OFFLINE;
3816 pstate->sc_cfg.rd_en = false;
3817 pstate->sc_cfg.rd_scid = 0;
Clarence Ipd02440b2017-05-21 18:10:01 -04003818 pstate->sc_cfg.rd_noallocate = true;
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003819 pstate->sc_cfg.rd_op_type =
3820 SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
3821 }
3822
3823 psde->pipe_hw->ops.setup_sys_cache(
3824 psde->pipe_hw, &pstate->sc_cfg);
3825 }
3826
3827 /* update csc */
3828 if (SDE_FORMAT_IS_YUV(fmt))
3829 _sde_plane_setup_csc(psde);
3830 else
3831 psde->csc_ptr = 0;
3832 }
3833
3834 sde_color_process_plane_setup(plane);
3835
3836 /* update sharpening */
3837 if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
3838 psde->pipe_hw->ops.setup_sharpening) {
3839 psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
3840 psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
3841 psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
3842 psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
3843
3844 psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
3845 &psde->sharp_cfg);
3846 }
3847
3848 _sde_plane_set_qos_lut(plane, fb);
3849 _sde_plane_set_danger_lut(plane, fb);
3850
3851 if (plane->type != DRM_PLANE_TYPE_CURSOR) {
3852 _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
3853 _sde_plane_set_ot_limit(plane, crtc);
Alan Kwong2349d742017-04-20 08:27:30 -07003854 if (pstate->dirty & SDE_PLANE_DIRTY_PERF)
3855 _sde_plane_set_ts_prefill(plane, pstate);
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003856 }
3857
Alan Kwonga62eeb82017-04-19 08:57:55 -07003858 _sde_plane_set_qos_remap(plane);
3859
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003860 /* clear dirty */
3861 pstate->dirty = 0x0;
3862
3863 return 0;
3864}
3865
Clarence Ipc652ccf2017-06-28 18:21:18 -04003866static void _sde_plane_atomic_disable(struct drm_plane *plane,
Clarence Ipe78efb72016-06-24 18:35:21 -04003867 struct drm_plane_state *old_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07003868{
Clarence Ip13a8cf42016-09-29 17:27:47 -04003869 struct sde_plane *psde;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003870 struct drm_plane_state *state;
3871 struct sde_plane_state *pstate;
Clarence Ipc652ccf2017-06-28 18:21:18 -04003872
3873 if (!plane) {
3874 SDE_ERROR("invalid plane\n");
3875 return;
3876 } else if (!plane->state) {
3877 SDE_ERROR("invalid plane state\n");
3878 return;
3879 } else if (!old_state) {
3880 SDE_ERROR("invalid old state\n");
3881 return;
3882 }
3883
3884 psde = to_sde_plane(plane);
3885 state = plane->state;
3886 pstate = to_sde_plane_state(state);
3887
3888 SDE_EVT32(DRMID(plane), is_sde_plane_virtual(plane),
3889 pstate->multirect_mode);
3890
3891 pstate->pending = true;
3892
3893 if (is_sde_plane_virtual(plane) &&
3894 psde->pipe_hw && psde->pipe_hw->ops.setup_multirect)
3895 psde->pipe_hw->ops.setup_multirect(psde->pipe_hw,
3896 SDE_SSPP_RECT_SOLO, SDE_SSPP_MULTIRECT_NONE);
3897}
3898
3899static void sde_plane_atomic_update(struct drm_plane *plane,
3900 struct drm_plane_state *old_state)
3901{
3902 struct sde_plane *psde;
3903 struct drm_plane_state *state;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003904
Clarence Ip13a8cf42016-09-29 17:27:47 -04003905 if (!plane) {
3906 SDE_ERROR("invalid plane\n");
3907 return;
3908 } else if (!plane->state) {
3909 SDE_ERROR("invalid plane state\n");
Clarence Ip5e2a9222016-06-26 22:38:24 -04003910 return;
3911 }
3912
Clarence Ip13a8cf42016-09-29 17:27:47 -04003913 psde = to_sde_plane(plane);
3914 psde->is_error = false;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003915 state = plane->state;
Clarence Ip5e2a9222016-06-26 22:38:24 -04003916
Clarence Ip13a8cf42016-09-29 17:27:47 -04003917 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04003918
Alan Kwong4dd64c82017-02-04 18:41:51 -08003919 sde_plane_rot_atomic_update(plane, old_state);
3920
3921 if (!sde_plane_sspp_enabled(state)) {
Clarence Ipc652ccf2017-06-28 18:21:18 -04003922 _sde_plane_atomic_disable(plane, old_state);
Clarence Ip282dad62016-09-27 17:07:35 -04003923 } else {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003924 int ret;
3925
Jeykumar Sankarane964dc72017-05-10 19:26:43 -07003926 ret = sde_plane_sspp_atomic_update(plane, old_state);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003927 /* atomic_check should have ensured that this doesn't fail */
3928 WARN_ON(ret < 0);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003929 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04003930}
3931
Alan Kwong346223e2017-06-30 15:29:22 -04003932void sde_plane_restore(struct drm_plane *plane)
3933{
3934 struct sde_plane *psde;
3935
3936 if (!plane || !plane->state) {
3937 SDE_ERROR("invalid plane\n");
3938 return;
3939 }
3940
3941 psde = to_sde_plane(plane);
3942
3943 /*
3944 * Revalidate is only true here if idle PC occurred and
3945 * there is no plane state update in current commit cycle.
3946 */
3947 if (!psde->revalidate)
3948 return;
3949
3950 SDE_DEBUG_PLANE(psde, "\n");
3951
3952 /* last plane state is same as current state */
3953 sde_plane_atomic_update(plane, plane->state);
3954}
Dhaval Patel47302cf2016-08-18 15:04:28 -07003955
Lloyd Atkinsone08229c2017-10-02 17:53:30 -04003956int sde_plane_helper_reset_custom_properties(struct drm_plane *plane,
3957 struct drm_plane_state *plane_state)
3958{
3959 struct sde_plane *psde;
3960 struct sde_plane_state *pstate;
3961 struct drm_property *drm_prop;
3962 enum msm_mdp_plane_property prop_idx;
3963
3964 if (!plane || !plane_state) {
3965 SDE_ERROR("invalid params\n");
3966 return -EINVAL;
3967 }
3968
3969 psde = to_sde_plane(plane);
3970 pstate = to_sde_plane_state(plane_state);
3971
3972 for (prop_idx = 0; prop_idx < PLANE_PROP_COUNT; prop_idx++) {
3973 uint64_t val = pstate->property_values[prop_idx].value;
3974 uint64_t def;
3975 int ret;
3976
3977 drm_prop = msm_property_index_to_drm_property(
3978 &psde->property_info, prop_idx);
3979 if (!drm_prop) {
3980 /* not all props will be installed, based on caps */
3981 SDE_DEBUG_PLANE(psde, "invalid property index %d\n",
3982 prop_idx);
3983 continue;
3984 }
3985
3986 def = msm_property_get_default(&psde->property_info, prop_idx);
3987 if (val == def)
3988 continue;
3989
3990 SDE_DEBUG_PLANE(psde, "set prop %s idx %d from %llu to %llu\n",
3991 drm_prop->name, prop_idx, val, def);
3992
3993 ret = drm_atomic_plane_set_property(plane, plane_state,
3994 drm_prop, def);
3995 if (ret) {
3996 SDE_ERROR_PLANE(psde,
3997 "set property failed, idx %d ret %d\n",
3998 prop_idx, ret);
3999 continue;
4000 }
4001 }
4002
4003 return 0;
4004}
4005
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004006/* helper to install properties which are common to planes and crtcs */
Dhaval Patel47302cf2016-08-18 15:04:28 -07004007static void _sde_plane_install_properties(struct drm_plane *plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004008 struct sde_mdss_cfg *catalog, u32 master_plane_id)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004009{
Clarence Ip5e2a9222016-06-26 22:38:24 -04004010 static const struct drm_prop_enum_list e_blend_op[] = {
4011 {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
4012 {SDE_DRM_BLEND_OP_OPAQUE, "opaque"},
4013 {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"},
4014 {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}
4015 };
4016 static const struct drm_prop_enum_list e_src_config[] = {
4017 {SDE_DRM_DEINTERLACE, "deinterlace"}
4018 };
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07004019 static const struct drm_prop_enum_list e_fb_translation_mode[] = {
4020 {SDE_DRM_FB_NON_SEC, "non_sec"},
4021 {SDE_DRM_FB_SEC, "sec"},
4022 {SDE_DRM_FB_NON_SEC_DIR_TRANS, "non_sec_direct_translation"},
4023 {SDE_DRM_FB_SEC_DIR_TRANS, "sec_direct_translation"},
4024 };
Clarence Ipea3d6262016-07-15 16:20:11 -04004025 const struct sde_format_extended *format_list;
Dhaval Patel4e574842016-08-23 15:11:37 -07004026 struct sde_kms_info *info;
Clarence Ip5e2a9222016-06-26 22:38:24 -04004027 struct sde_plane *psde = to_sde_plane(plane);
Clarence Ipc47a0692016-10-11 10:54:17 -04004028 int zpos_max = 255;
4029 int zpos_def = 0;
Benet Clarkeb1b4462016-06-27 14:43:06 -07004030 char feature_name[256];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004031
Clarence Ip13a8cf42016-09-29 17:27:47 -04004032 if (!plane || !psde) {
4033 SDE_ERROR("invalid plane\n");
4034 return;
4035 } else if (!psde->pipe_hw || !psde->pipe_sblk) {
4036 SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
4037 psde->pipe_hw != 0, psde->pipe_sblk != 0);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004038 return;
Clarence Ipc47a0692016-10-11 10:54:17 -04004039 } else if (!catalog) {
4040 SDE_ERROR("invalid catalog\n");
4041 return;
Clarence Ip5e2a9222016-06-26 22:38:24 -04004042 }
4043
Alan Kwong4dd64c82017-02-04 18:41:51 -08004044 psde->catalog = catalog;
4045
Clarence Ipc47a0692016-10-11 10:54:17 -04004046 if (sde_is_custom_client()) {
Clarence Ip649989a2016-10-21 14:28:34 -04004047 if (catalog->mixer_count && catalog->mixer &&
4048 catalog->mixer[0].sblk->maxblendstages) {
4049 zpos_max = catalog->mixer[0].sblk->maxblendstages - 1;
4050 if (zpos_max > SDE_STAGE_MAX - SDE_STAGE_0 - 1)
4051 zpos_max = SDE_STAGE_MAX - SDE_STAGE_0 - 1;
4052 }
Clarence Ipc47a0692016-10-11 10:54:17 -04004053 } else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
4054 /* reserve zpos == 0 for primary planes */
4055 zpos_def = drm_plane_index(plane) + 1;
4056 }
4057
4058 msm_property_install_range(&psde->property_info, "zpos",
4059 0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004060
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04004061 msm_property_install_range(&psde->property_info, "alpha",
Dhaval Patel47302cf2016-08-18 15:04:28 -07004062 0x0, 0, 255, 255, PLANE_PROP_ALPHA);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004063
Dhaval Patel47302cf2016-08-18 15:04:28 -07004064 /* linux default file descriptor range on each process */
Clarence Ipcae1bb62016-07-07 12:07:13 -04004065 msm_property_install_range(&psde->property_info, "input_fence",
Dhaval Patel4e574842016-08-23 15:11:37 -07004066 0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004067
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004068 if (!master_plane_id) {
4069 if (psde->pipe_sblk->maxhdeciexp) {
4070 msm_property_install_range(&psde->property_info,
4071 "h_decimate", 0x0, 0,
4072 psde->pipe_sblk->maxhdeciexp, 0,
4073 PLANE_PROP_H_DECIMATE);
4074 }
Clarence Ipdedbba92016-09-27 17:43:10 -04004075
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004076 if (psde->pipe_sblk->maxvdeciexp) {
4077 msm_property_install_range(&psde->property_info,
4078 "v_decimate", 0x0, 0,
4079 psde->pipe_sblk->maxvdeciexp, 0,
4080 PLANE_PROP_V_DECIMATE);
4081 }
Clarence Ipdedbba92016-09-27 17:43:10 -04004082
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004083 if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004084 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004085 &psde->property_info, "scaler_v2",
4086 0x0, 0, ~0, 0, PLANE_PROP_SCALER_V2);
4087 msm_property_install_blob(&psde->property_info,
4088 "lut_ed", 0, PLANE_PROP_SCALER_LUT_ED);
4089 msm_property_install_blob(&psde->property_info,
4090 "lut_cir", 0,
4091 PLANE_PROP_SCALER_LUT_CIR);
4092 msm_property_install_blob(&psde->property_info,
4093 "lut_sep", 0,
4094 PLANE_PROP_SCALER_LUT_SEP);
4095 } else if (psde->features & SDE_SSPP_SCALER) {
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004096 msm_property_install_range(
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004097 &psde->property_info, "scaler_v1", 0x0,
4098 0, ~0, 0, PLANE_PROP_SCALER_V1);
4099 }
Clarence Ipb43d4592016-09-08 14:21:35 -04004100
Dhaval Patel0aee0972017-02-08 19:00:58 -08004101 if (psde->features & BIT(SDE_SSPP_CSC) ||
4102 psde->features & BIT(SDE_SSPP_CSC_10BIT))
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004103 msm_property_install_volatile_range(
4104 &psde->property_info, "csc_v1", 0x0,
4105 0, ~0, 0, PLANE_PROP_CSC_V1);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004106
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004107 if (psde->features & BIT(SDE_SSPP_HSIC)) {
4108 snprintf(feature_name, sizeof(feature_name), "%s%d",
4109 "SDE_SSPP_HUE_V",
4110 psde->pipe_sblk->hsic_blk.version >> 16);
4111 msm_property_install_range(&psde->property_info,
4112 feature_name, 0, 0, 0xFFFFFFFF, 0,
4113 PLANE_PROP_HUE_ADJUST);
4114 snprintf(feature_name, sizeof(feature_name), "%s%d",
4115 "SDE_SSPP_SATURATION_V",
4116 psde->pipe_sblk->hsic_blk.version >> 16);
4117 msm_property_install_range(&psde->property_info,
4118 feature_name, 0, 0, 0xFFFFFFFF, 0,
4119 PLANE_PROP_SATURATION_ADJUST);
4120 snprintf(feature_name, sizeof(feature_name), "%s%d",
4121 "SDE_SSPP_VALUE_V",
4122 psde->pipe_sblk->hsic_blk.version >> 16);
4123 msm_property_install_range(&psde->property_info,
4124 feature_name, 0, 0, 0xFFFFFFFF, 0,
4125 PLANE_PROP_VALUE_ADJUST);
4126 snprintf(feature_name, sizeof(feature_name), "%s%d",
4127 "SDE_SSPP_CONTRAST_V",
4128 psde->pipe_sblk->hsic_blk.version >> 16);
4129 msm_property_install_range(&psde->property_info,
4130 feature_name, 0, 0, 0xFFFFFFFF, 0,
4131 PLANE_PROP_CONTRAST_ADJUST);
4132 }
Benet Clarkeb1b4462016-06-27 14:43:06 -07004133 }
4134
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004135 if (psde->features & BIT(SDE_SSPP_EXCL_RECT))
4136 msm_property_install_volatile_range(&psde->property_info,
4137 "excl_rect_v1", 0x0, 0, ~0, 0, PLANE_PROP_EXCL_RECT_V1);
4138
Alan Kwong4dd64c82017-02-04 18:41:51 -08004139 sde_plane_rot_install_properties(plane, catalog);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004140
Lloyd Atkinson38ad8c92016-07-06 10:39:32 -04004141 msm_property_install_enum(&psde->property_info, "blend_op", 0x0, 0,
Dhaval Patel47302cf2016-08-18 15:04:28 -07004142 e_blend_op, ARRAY_SIZE(e_blend_op), PLANE_PROP_BLEND_OP);
Clarence Ip5e2a9222016-06-26 22:38:24 -04004143
Dhaval Patel47302cf2016-08-18 15:04:28 -07004144 msm_property_install_enum(&psde->property_info, "src_config", 0x0, 1,
4145 e_src_config, ARRAY_SIZE(e_src_config), PLANE_PROP_SRC_CONFIG);
4146
4147 if (psde->pipe_hw->ops.setup_solidfill)
4148 msm_property_install_range(&psde->property_info, "color_fill",
4149 0, 0, 0xFFFFFFFF, 0, PLANE_PROP_COLOR_FILL);
4150
Alan Kwong2349d742017-04-20 08:27:30 -07004151 msm_property_install_range(&psde->property_info,
4152 "prefill_size", 0x0, 0, ~0, 0,
4153 PLANE_PROP_PREFILL_SIZE);
4154 msm_property_install_range(&psde->property_info,
4155 "prefill_time", 0x0, 0, ~0, 0,
4156 PLANE_PROP_PREFILL_TIME);
4157
Dhaval Patel4e574842016-08-23 15:11:37 -07004158 info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004159 if (!info) {
4160 SDE_ERROR("failed to allocate info memory\n");
Dhaval Patel4e574842016-08-23 15:11:37 -07004161 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004162 }
Dhaval Patel4e574842016-08-23 15:11:37 -07004163
4164 msm_property_install_blob(&psde->property_info, "capabilities",
4165 DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_INFO);
4166 sde_kms_info_reset(info);
4167
Steve Cohen57428172017-07-18 10:57:17 -04004168 if (!master_plane_id) {
4169 format_list = psde->pipe_sblk->format_list;
4170 } else {
4171 format_list = psde->pipe_sblk->virt_format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004172 sde_kms_info_add_keyint(info, "primary_smart_plane_id",
Jeykumar Sankaranf55e65b2017-05-10 21:46:14 -07004173 master_plane_id);
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004174 }
4175
Clarence Ipea3d6262016-07-15 16:20:11 -04004176 if (format_list) {
Clarence Ipea3d6262016-07-15 16:20:11 -04004177 sde_kms_info_start(info, "pixel_formats");
4178 while (format_list->fourcc_format) {
4179 sde_kms_info_append_format(info,
4180 format_list->fourcc_format,
4181 format_list->modifier);
4182 ++format_list;
4183 }
4184 sde_kms_info_stop(info);
Clarence Ipea3d6262016-07-15 16:20:11 -04004185 }
Dhaval Patel4e574842016-08-23 15:11:37 -07004186
Clarence Ip1db00c12017-07-21 17:42:56 -04004187 if (psde->pipe_hw && psde->pipe_hw->ops.get_scaler_ver)
4188 sde_kms_info_add_keyint(info, "scaler_step_ver",
4189 psde->pipe_hw->ops.get_scaler_ver(psde->pipe_hw));
4190
Dhaval Patel4e574842016-08-23 15:11:37 -07004191 sde_kms_info_add_keyint(info, "max_linewidth",
4192 psde->pipe_sblk->maxlinewidth);
4193 sde_kms_info_add_keyint(info, "max_upscale",
4194 psde->pipe_sblk->maxupscale);
4195 sde_kms_info_add_keyint(info, "max_downscale",
4196 psde->pipe_sblk->maxdwnscale);
4197 sde_kms_info_add_keyint(info, "max_horizontal_deci",
4198 psde->pipe_sblk->maxhdeciexp);
4199 sde_kms_info_add_keyint(info, "max_vertical_deci",
4200 psde->pipe_sblk->maxvdeciexp);
Alan Kwong6259a382017-04-04 06:18:02 -07004201 sde_kms_info_add_keyint(info, "max_per_pipe_bw",
4202 psde->pipe_sblk->max_per_pipe_bw * 1000LL);
Dhaval Patel4e574842016-08-23 15:11:37 -07004203 msm_property_set_blob(&psde->property_info, &psde->blob_info,
Narendra Muppalla22d17252017-05-31 15:13:39 -07004204 info->data, SDE_KMS_INFO_DATALEN(info),
4205 PLANE_PROP_INFO);
Dhaval Patel4e574842016-08-23 15:11:37 -07004206
4207 kfree(info);
Benet Clarkd009b1d2016-06-27 14:45:59 -07004208
4209 if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
4210 snprintf(feature_name, sizeof(feature_name), "%s%d",
4211 "SDE_SSPP_SKIN_COLOR_V",
4212 psde->pipe_sblk->memcolor_blk.version >> 16);
4213 msm_property_install_blob(&psde->property_info, feature_name, 0,
4214 PLANE_PROP_SKIN_COLOR);
4215 snprintf(feature_name, sizeof(feature_name), "%s%d",
4216 "SDE_SSPP_SKY_COLOR_V",
4217 psde->pipe_sblk->memcolor_blk.version >> 16);
4218 msm_property_install_blob(&psde->property_info, feature_name, 0,
4219 PLANE_PROP_SKY_COLOR);
4220 snprintf(feature_name, sizeof(feature_name), "%s%d",
4221 "SDE_SSPP_FOLIAGE_COLOR_V",
4222 psde->pipe_sblk->memcolor_blk.version >> 16);
4223 msm_property_install_blob(&psde->property_info, feature_name, 0,
4224 PLANE_PROP_FOLIAGE_COLOR);
4225 }
Abhijit Kulkarni50d69442017-04-11 19:50:47 -07004226
4227 msm_property_install_enum(&psde->property_info, "fb_translation_mode",
4228 0x0,
4229 0, e_fb_translation_mode,
4230 ARRAY_SIZE(e_fb_translation_mode),
4231 PLANE_PROP_FB_TRANSLATION_MODE);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004232}
4233
Clarence Ip5fc00c52016-09-23 15:03:34 -04004234static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
4235{
4236 struct sde_drm_csc_v1 csc_v1;
4237 int i;
4238
4239 if (!psde) {
4240 SDE_ERROR("invalid plane\n");
4241 return;
4242 }
4243
4244 psde->csc_usr_ptr = NULL;
4245 if (!usr_ptr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004246 SDE_DEBUG_PLANE(psde, "csc data removed\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04004247 return;
4248 }
4249
4250 if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004251 SDE_ERROR_PLANE(psde, "failed to copy csc data\n");
Clarence Ip5fc00c52016-09-23 15:03:34 -04004252 return;
4253 }
4254
Clarence Ipb43d4592016-09-08 14:21:35 -04004255 /* populate from user space */
Clarence Ip5fc00c52016-09-23 15:03:34 -04004256 for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
4257 psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
4258 for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
4259 psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
4260 psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
4261 }
4262 for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
4263 psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
4264 psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
4265 }
4266 psde->csc_usr_ptr = &psde->csc_cfg;
4267}
4268
Clarence Ip172033f2017-06-13 10:52:56 -04004269static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde,
4270 struct sde_plane_state *pstate, void *usr)
Clarence Ipb43d4592016-09-08 14:21:35 -04004271{
4272 struct sde_drm_scaler_v1 scale_v1;
4273 struct sde_hw_pixel_ext *pe;
4274 int i;
4275
Clarence Ip172033f2017-06-13 10:52:56 -04004276 if (!psde || !pstate) {
4277 SDE_ERROR("invalid argument(s)\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004278 return;
4279 }
4280
Clarence Ip172033f2017-06-13 10:52:56 -04004281 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
Clarence Ipb43d4592016-09-08 14:21:35 -04004282 if (!usr) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004283 SDE_DEBUG_PLANE(psde, "scale data removed\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004284 return;
4285 }
4286
4287 if (copy_from_user(&scale_v1, usr, sizeof(scale_v1))) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004288 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004289 return;
4290 }
4291
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004292 /* force property to be dirty, even if the pointer didn't change */
Clarence Ip4a2955d2017-07-04 18:04:33 -04004293 msm_property_set_dirty(&psde->property_info,
4294 &pstate->property_state, PLANE_PROP_SCALER_V1);
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004295
Clarence Ipb43d4592016-09-08 14:21:35 -04004296 /* populate from user space */
Clarence Ip172033f2017-06-13 10:52:56 -04004297 pe = &pstate->pixel_ext;
Clarence Ipb43d4592016-09-08 14:21:35 -04004298 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
4299 for (i = 0; i < SDE_MAX_PLANES; i++) {
4300 pe->init_phase_x[i] = scale_v1.init_phase_x[i];
4301 pe->phase_step_x[i] = scale_v1.phase_step_x[i];
4302 pe->init_phase_y[i] = scale_v1.init_phase_y[i];
4303 pe->phase_step_y[i] = scale_v1.phase_step_y[i];
4304
4305 pe->horz_filter[i] = scale_v1.horz_filter[i];
4306 pe->vert_filter[i] = scale_v1.vert_filter[i];
4307 }
4308 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05004309 pe->left_ftch[i] = scale_v1.pe.left_ftch[i];
4310 pe->right_ftch[i] = scale_v1.pe.right_ftch[i];
4311 pe->left_rpt[i] = scale_v1.pe.left_rpt[i];
4312 pe->right_rpt[i] = scale_v1.pe.right_rpt[i];
4313 pe->roi_w[i] = scale_v1.pe.num_ext_pxls_lr[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04004314
abeykun41060122016-11-28 13:02:01 -05004315 pe->top_ftch[i] = scale_v1.pe.top_ftch[i];
4316 pe->btm_ftch[i] = scale_v1.pe.btm_ftch[i];
4317 pe->top_rpt[i] = scale_v1.pe.top_rpt[i];
4318 pe->btm_rpt[i] = scale_v1.pe.btm_rpt[i];
4319 pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
Clarence Ipb43d4592016-09-08 14:21:35 -04004320 }
abeykun41060122016-11-28 13:02:01 -05004321
Clarence Ip172033f2017-06-13 10:52:56 -04004322 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
Clarence Ipb43d4592016-09-08 14:21:35 -04004323
Clarence Ip059c8c32017-06-06 17:15:54 -04004324 SDE_EVT32_VERBOSE(DRMID(&psde->base));
Clarence Ip13a8cf42016-09-29 17:27:47 -04004325 SDE_DEBUG_PLANE(psde, "user property data copied\n");
Clarence Ipb43d4592016-09-08 14:21:35 -04004326}
4327
abeykun48f407a2016-08-25 12:06:44 -04004328static inline void _sde_plane_set_scaler_v2(struct sde_plane *psde,
4329 struct sde_plane_state *pstate, void *usr)
4330{
4331 struct sde_drm_scaler_v2 scale_v2;
4332 struct sde_hw_pixel_ext *pe;
4333 int i;
4334 struct sde_hw_scaler3_cfg *cfg;
4335
Clarence Ip172033f2017-06-13 10:52:56 -04004336 if (!psde || !pstate) {
4337 SDE_ERROR("invalid argument(s)\n");
abeykun48f407a2016-08-25 12:06:44 -04004338 return;
4339 }
4340
Clarence Ip172033f2017-06-13 10:52:56 -04004341 cfg = &pstate->scaler3_cfg;
4342 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
abeykun48f407a2016-08-25 12:06:44 -04004343 if (!usr) {
4344 SDE_DEBUG_PLANE(psde, "scale data removed\n");
4345 return;
4346 }
4347
4348 if (copy_from_user(&scale_v2, usr, sizeof(scale_v2))) {
4349 SDE_ERROR_PLANE(psde, "failed to copy scale data\n");
4350 return;
4351 }
4352
Clarence Ip7e892a02017-06-13 10:16:07 -04004353 /* detach/ignore user data if 'disabled' */
4354 if (!scale_v2.enable) {
4355 SDE_DEBUG_PLANE(psde, "scale data removed\n");
4356 return;
4357 }
4358
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004359 /* force property to be dirty, even if the pointer didn't change */
Clarence Ip4a2955d2017-07-04 18:04:33 -04004360 msm_property_set_dirty(&psde->property_info,
4361 &pstate->property_state, PLANE_PROP_SCALER_V2);
Clarence Ip3b1e2c62017-06-14 11:20:44 -04004362
abeykun48f407a2016-08-25 12:06:44 -04004363 /* populate from user space */
Sravanthi Kollukuduru55b24f02017-06-22 15:11:31 +05304364 sde_set_scaler_v2(cfg, &scale_v2);
4365
Clarence Ip172033f2017-06-13 10:52:56 -04004366 pe = &pstate->pixel_ext;
abeykun48f407a2016-08-25 12:06:44 -04004367 memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
abeykun48f407a2016-08-25 12:06:44 -04004368
abeykun48f407a2016-08-25 12:06:44 -04004369 for (i = 0; i < SDE_MAX_PLANES; i++) {
abeykun41060122016-11-28 13:02:01 -05004370 pe->left_ftch[i] = scale_v2.pe.left_ftch[i];
4371 pe->right_ftch[i] = scale_v2.pe.right_ftch[i];
4372 pe->left_rpt[i] = scale_v2.pe.left_rpt[i];
4373 pe->right_rpt[i] = scale_v2.pe.right_rpt[i];
4374 pe->roi_w[i] = scale_v2.pe.num_ext_pxls_lr[i];
abeykun48f407a2016-08-25 12:06:44 -04004375
abeykun41060122016-11-28 13:02:01 -05004376 pe->top_ftch[i] = scale_v2.pe.top_ftch[i];
4377 pe->btm_ftch[i] = scale_v2.pe.btm_ftch[i];
4378 pe->top_rpt[i] = scale_v2.pe.top_rpt[i];
4379 pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
4380 pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
abeykun48f407a2016-08-25 12:06:44 -04004381 }
Clarence Ip172033f2017-06-13 10:52:56 -04004382 pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
abeykun48f407a2016-08-25 12:06:44 -04004383
Clarence Ip059c8c32017-06-06 17:15:54 -04004384 SDE_EVT32_VERBOSE(DRMID(&psde->base), cfg->enable, cfg->de.enable,
4385 cfg->src_width[0], cfg->src_height[0],
4386 cfg->dst_width, cfg->dst_height);
abeykun48f407a2016-08-25 12:06:44 -04004387 SDE_DEBUG_PLANE(psde, "user property data copied\n");
4388}
4389
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004390static void _sde_plane_set_excl_rect_v1(struct sde_plane *psde,
4391 struct sde_plane_state *pstate, void *usr_ptr)
4392{
4393 struct drm_clip_rect excl_rect_v1;
4394
4395 if (!psde) {
4396 SDE_ERROR("invalid plane\n");
4397 return;
4398 }
4399
4400 if (!usr_ptr) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004401 SDE_DEBUG_PLANE(psde, "invalid excl_rect user data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004402 return;
4403 }
4404
4405 if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004406 SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004407 return;
4408 }
4409
4410 /* populate from user space */
4411 pstate->excl_rect.x = excl_rect_v1.x1;
4412 pstate->excl_rect.y = excl_rect_v1.y1;
Veera Sundaram Sankaran58e12812017-05-05 11:51:09 -07004413 pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
4414 pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
4415
4416 SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
4417 pstate->excl_rect.x, pstate->excl_rect.y,
4418 pstate->excl_rect.w, pstate->excl_rect.h);
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004419}
4420
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004421static int sde_plane_atomic_set_property(struct drm_plane *plane,
4422 struct drm_plane_state *state, struct drm_property *property,
4423 uint64_t val)
4424{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004425 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004426 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004427 int idx, ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004428
Clarence Ip13a8cf42016-09-29 17:27:47 -04004429 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004430
4431 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004432 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004433 } else if (!state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004434 SDE_ERROR_PLANE(psde, "invalid state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004435 } else {
Clarence Ip4c1d9772016-06-26 09:35:38 -04004436 pstate = to_sde_plane_state(state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004437 ret = msm_property_atomic_set(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004438 &pstate->property_state, property, val);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004439 if (!ret) {
4440 idx = msm_property_index(&psde->property_info,
4441 property);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004442 switch (idx) {
4443 case PLANE_PROP_INPUT_FENCE:
Clarence Ip13a8cf42016-09-29 17:27:47 -04004444 _sde_plane_set_input_fence(psde, pstate, val);
Clarence Ip5fc00c52016-09-23 15:03:34 -04004445 break;
4446 case PLANE_PROP_CSC_V1:
4447 _sde_plane_set_csc_v1(psde, (void *)val);
4448 break;
Clarence Ipb43d4592016-09-08 14:21:35 -04004449 case PLANE_PROP_SCALER_V1:
Clarence Ip172033f2017-06-13 10:52:56 -04004450 _sde_plane_set_scaler_v1(psde, pstate,
4451 (void *)val);
Clarence Ipb43d4592016-09-08 14:21:35 -04004452 break;
abeykun48f407a2016-08-25 12:06:44 -04004453 case PLANE_PROP_SCALER_V2:
4454 _sde_plane_set_scaler_v2(psde, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004455 (void *)val);
abeykun48f407a2016-08-25 12:06:44 -04004456 break;
Veera Sundaram Sankaran02dd6ac2016-12-22 15:08:29 -08004457 case PLANE_PROP_EXCL_RECT_V1:
4458 _sde_plane_set_excl_rect_v1(psde, pstate,
4459 (void *)val);
4460 break;
Clarence Ip5fc00c52016-09-23 15:03:34 -04004461 default:
4462 /* nothing to do */
4463 break;
4464 }
Clarence Ipe78efb72016-06-24 18:35:21 -04004465 }
4466 }
4467
Alan Kwong4dd64c82017-02-04 18:41:51 -08004468 SDE_DEBUG_PLANE(psde, "%s[%d] <= 0x%llx ret=%d\n",
4469 property->name, property->base.id, val, ret);
4470
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004471 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004472}
4473
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004474static int sde_plane_atomic_get_property(struct drm_plane *plane,
4475 const struct drm_plane_state *state,
4476 struct drm_property *property, uint64_t *val)
4477{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004478 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004479 struct sde_plane_state *pstate;
Clarence Ipaa0faf42016-05-30 12:07:48 -04004480 int ret = -EINVAL;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004481
Clarence Ipaa0faf42016-05-30 12:07:48 -04004482 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004483 SDE_ERROR("invalid plane\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004484 } else if (!state) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004485 SDE_ERROR("invalid state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004486 } else {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004487 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip4c1d9772016-06-26 09:35:38 -04004488 pstate = to_sde_plane_state(state);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004489 sde_plane_rot_install_caps(plane);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004490 ret = msm_property_atomic_get(&psde->property_info,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004491 &pstate->property_state, property, val);
Clarence Ipe78efb72016-06-24 18:35:21 -04004492 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004493
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004494 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004495}
4496
4497static void sde_plane_destroy(struct drm_plane *plane)
4498{
Clarence Ip13a8cf42016-09-29 17:27:47 -04004499 struct sde_plane *psde = plane ? to_sde_plane(plane) : NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004500
Clarence Ip13a8cf42016-09-29 17:27:47 -04004501 SDE_DEBUG_PLANE(psde, "\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004502
Clarence Ip13a8cf42016-09-29 17:27:47 -04004503 if (psde) {
Alan Kwong1a00e4d2016-07-18 09:42:30 -04004504 _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
4505
Dhaval Patel4e574842016-08-23 15:11:37 -07004506 if (psde->blob_info)
4507 drm_property_unreference_blob(psde->blob_info);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004508 msm_property_destroy(&psde->property_info);
Clarence Ip730e7192016-06-26 22:45:09 -04004509 mutex_destroy(&psde->lock);
4510
Clarence Ip4ce59322016-06-26 22:27:51 -04004511 drm_plane_helper_disable(plane);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004512
Clarence Ip4ce59322016-06-26 22:27:51 -04004513 /* this will destroy the states as well */
4514 drm_plane_cleanup(plane);
4515
Clarence Ip4c1d9772016-06-26 09:35:38 -04004516 if (psde->pipe_hw)
4517 sde_hw_sspp_destroy(psde->pipe_hw);
4518
Clarence Ip4ce59322016-06-26 22:27:51 -04004519 kfree(psde);
4520 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004521}
4522
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004523static void sde_plane_destroy_state(struct drm_plane *plane,
4524 struct drm_plane_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004525{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004526 struct sde_plane *psde;
Clarence Ipe78efb72016-06-24 18:35:21 -04004527 struct sde_plane_state *pstate;
Clarence Ipe78efb72016-06-24 18:35:21 -04004528
Clarence Ipae4e60c2016-06-26 22:44:04 -04004529 if (!plane || !state) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004530 SDE_ERROR("invalid arg(s), plane %d state %d\n",
4531 plane != 0, state != 0);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004532 return;
4533 }
4534
Clarence Ipaa0faf42016-05-30 12:07:48 -04004535 psde = to_sde_plane(plane);
Clarence Ip730e7192016-06-26 22:45:09 -04004536 pstate = to_sde_plane_state(state);
4537
Clarence Ip13a8cf42016-09-29 17:27:47 -04004538 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004539
Alan Kwong4dd64c82017-02-04 18:41:51 -08004540 sde_plane_rot_destroy_state(plane, &pstate->base);
4541
Clarence Ipe78efb72016-06-24 18:35:21 -04004542 /* remove ref count for frame buffers */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004543 if (state->fb)
4544 drm_framebuffer_unreference(state->fb);
4545
Clarence Ipae4e60c2016-06-26 22:44:04 -04004546 /* remove ref count for fence */
Clarence Ipcae1bb62016-07-07 12:07:13 -04004547 if (pstate->input_fence)
4548 sde_sync_put(pstate->input_fence);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004549
Clarence Ipaa0faf42016-05-30 12:07:48 -04004550 /* destroy value helper */
4551 msm_property_destroy_state(&psde->property_info, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004552 &pstate->property_state);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004553}
4554
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004555static struct drm_plane_state *
4556sde_plane_duplicate_state(struct drm_plane *plane)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004557{
Clarence Ipaa0faf42016-05-30 12:07:48 -04004558 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004559 struct sde_plane_state *pstate;
Clarence Ip730e7192016-06-26 22:45:09 -04004560 struct sde_plane_state *old_state;
Clarence Ip17e908b2016-09-29 15:58:00 -04004561 uint64_t input_fence_default;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004562
Clarence Ip13a8cf42016-09-29 17:27:47 -04004563 if (!plane) {
4564 SDE_ERROR("invalid plane\n");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004565 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004566 } else if (!plane->state) {
4567 SDE_ERROR("invalid plane state\n");
4568 return NULL;
4569 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004570
Clarence Ip730e7192016-06-26 22:45:09 -04004571 old_state = to_sde_plane_state(plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004572 psde = to_sde_plane(plane);
4573 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004574 if (!pstate) {
4575 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004576 return NULL;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004577 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004578
Clarence Ip13a8cf42016-09-29 17:27:47 -04004579 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004580
4581 /* duplicate value helper */
4582 msm_property_duplicate_state(&psde->property_info, old_state, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004583 &pstate->property_state, pstate->property_values);
Clarence Ipae4e60c2016-06-26 22:44:04 -04004584
Clarence Ip17e908b2016-09-29 15:58:00 -04004585 /* clear out any input fence */
4586 pstate->input_fence = 0;
4587 input_fence_default = msm_property_get_default(
4588 &psde->property_info, PLANE_PROP_INPUT_FENCE);
Clarence Ip4a2955d2017-07-04 18:04:33 -04004589 msm_property_set_property(&psde->property_info,
4590 &pstate->property_state,
Clarence Ip17e908b2016-09-29 15:58:00 -04004591 PLANE_PROP_INPUT_FENCE, input_fence_default);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004592
Clarence Ip282dad62016-09-27 17:07:35 -04004593 pstate->dirty = 0x0;
Clarence Ip730e7192016-06-26 22:45:09 -04004594 pstate->pending = false;
4595
Alan Kwongcdb2f282017-03-18 13:42:06 -07004596 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base);
4597
Alan Kwong4dd64c82017-02-04 18:41:51 -08004598 sde_plane_rot_duplicate_state(plane, &pstate->base);
4599
Clarence Ip730e7192016-06-26 22:45:09 -04004600 return &pstate->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004601}
4602
4603static void sde_plane_reset(struct drm_plane *plane)
4604{
Clarence Ipae4e60c2016-06-26 22:44:04 -04004605 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004606 struct sde_plane_state *pstate;
4607
Clarence Ipae4e60c2016-06-26 22:44:04 -04004608 if (!plane) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004609 SDE_ERROR("invalid plane\n");
Clarence Ipae4e60c2016-06-26 22:44:04 -04004610 return;
4611 }
4612
Clarence Ip730e7192016-06-26 22:45:09 -04004613 psde = to_sde_plane(plane);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004614 SDE_DEBUG_PLANE(psde, "\n");
Clarence Ip730e7192016-06-26 22:45:09 -04004615
Veera Sundaram Sankarandb43e282017-09-19 18:32:52 -07004616 if (plane->state && !sde_crtc_is_reset_required(plane->state->crtc)) {
4617 SDE_DEBUG_PLANE(psde, "avoid reset for plane\n");
4618 return;
4619 }
4620
Clarence Ipae4e60c2016-06-26 22:44:04 -04004621 /* remove previous state, if present */
Clarence Ipaa0faf42016-05-30 12:07:48 -04004622 if (plane->state) {
Clarence Ipae4e60c2016-06-26 22:44:04 -04004623 sde_plane_destroy_state(plane, plane->state);
Clarence Ipaa0faf42016-05-30 12:07:48 -04004624 plane->state = 0;
Clarence Ipae4e60c2016-06-26 22:44:04 -04004625 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004626
Clarence Ipaa0faf42016-05-30 12:07:48 -04004627 pstate = msm_property_alloc_state(&psde->property_info);
Clarence Ip13a8cf42016-09-29 17:27:47 -04004628 if (!pstate) {
4629 SDE_ERROR_PLANE(psde, "failed to allocate state\n");
Clarence Ipaa0faf42016-05-30 12:07:48 -04004630 return;
Clarence Ip13a8cf42016-09-29 17:27:47 -04004631 }
Clarence Ip730e7192016-06-26 22:45:09 -04004632
Clarence Ipaa0faf42016-05-30 12:07:48 -04004633 /* reset value helper */
4634 msm_property_reset_state(&psde->property_info, pstate,
Clarence Ip4a2955d2017-07-04 18:04:33 -04004635 &pstate->property_state,
4636 pstate->property_values);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004637
4638 pstate->base.plane = plane;
4639
4640 plane->state = &pstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004641}
4642
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004643#ifdef CONFIG_DEBUG_FS
Alan Kwongf0fd8512016-10-24 21:39:26 -04004644static ssize_t _sde_plane_danger_read(struct file *file,
4645 char __user *buff, size_t count, loff_t *ppos)
4646{
4647 struct sde_kms *kms = file->private_data;
4648 struct sde_mdss_cfg *cfg = kms->catalog;
4649 int len = 0;
4650 char buf[40] = {'\0'};
4651
4652 if (!cfg)
4653 return -ENODEV;
4654
4655 if (*ppos)
4656 return 0; /* the end */
4657
4658 len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl);
4659 if (len < 0 || len >= sizeof(buf))
4660 return 0;
4661
4662 if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
4663 return -EFAULT;
4664
4665 *ppos += len; /* increase offset */
4666
4667 return len;
4668}
4669
4670static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable)
4671{
4672 struct drm_plane *plane;
4673
4674 drm_for_each_plane(plane, kms->dev) {
4675 if (plane->fb && plane->state) {
4676 sde_plane_danger_signal_ctrl(plane, enable);
4677 SDE_DEBUG("plane:%d img:%dx%d ",
4678 plane->base.id, plane->fb->width,
4679 plane->fb->height);
4680 SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
4681 plane->state->src_x >> 16,
4682 plane->state->src_y >> 16,
4683 plane->state->src_w >> 16,
4684 plane->state->src_h >> 16,
4685 plane->state->crtc_x, plane->state->crtc_y,
4686 plane->state->crtc_w, plane->state->crtc_h);
4687 } else {
4688 SDE_DEBUG("Inactive plane:%d\n", plane->base.id);
4689 }
4690 }
4691}
4692
4693static ssize_t _sde_plane_danger_write(struct file *file,
4694 const char __user *user_buf, size_t count, loff_t *ppos)
4695{
4696 struct sde_kms *kms = file->private_data;
4697 struct sde_mdss_cfg *cfg = kms->catalog;
4698 int disable_panic;
4699 char buf[10];
4700
4701 if (!cfg)
4702 return -EFAULT;
4703
4704 if (count >= sizeof(buf))
4705 return -EFAULT;
4706
4707 if (copy_from_user(buf, user_buf, count))
4708 return -EFAULT;
4709
4710 buf[count] = 0; /* end of string */
4711
4712 if (kstrtoint(buf, 0, &disable_panic))
4713 return -EFAULT;
4714
4715 if (disable_panic) {
4716 /* Disable panic signal for all active pipes */
4717 SDE_DEBUG("Disabling danger:\n");
4718 _sde_plane_set_danger_state(kms, false);
4719 kms->has_danger_ctrl = false;
4720 } else {
4721 /* Enable panic signal for all active pipes */
4722 SDE_DEBUG("Enabling danger:\n");
4723 kms->has_danger_ctrl = true;
4724 _sde_plane_set_danger_state(kms, true);
4725 }
4726
4727 return count;
4728}
4729
4730static const struct file_operations sde_plane_danger_enable = {
4731 .open = simple_open,
4732 .read = _sde_plane_danger_read,
4733 .write = _sde_plane_danger_write,
4734};
4735
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004736static int _sde_plane_init_debugfs(struct drm_plane *plane)
Clarence Ip4ce59322016-06-26 22:27:51 -04004737{
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004738 struct sde_plane *psde;
4739 struct sde_kms *kms;
4740 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -04004741 const struct sde_sspp_sub_blks *sblk = 0;
4742 const struct sde_sspp_cfg *cfg = 0;
4743
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004744 if (!plane || !plane->dev) {
4745 SDE_ERROR("invalid arguments\n");
4746 return -EINVAL;
4747 }
4748
4749 priv = plane->dev->dev_private;
4750 if (!priv || !priv->kms) {
4751 SDE_ERROR("invalid KMS reference\n");
4752 return -EINVAL;
4753 }
4754
4755 kms = to_sde_kms(priv->kms);
4756 psde = to_sde_plane(plane);
4757
Clarence Ip4ce59322016-06-26 22:27:51 -04004758 if (psde && psde->pipe_hw)
4759 cfg = psde->pipe_hw->cap;
4760 if (cfg)
4761 sblk = cfg->sblk;
4762
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004763 if (!sblk)
4764 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -04004765
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004766 /* create overall sub-directory for the pipe */
4767 psde->debugfs_root =
4768 debugfs_create_dir(psde->pipe_name,
Lloyd Atkinson09e64bf2017-04-13 14:09:59 -07004769 plane->dev->primary->debugfs_root);
Clarence Ip4ce59322016-06-26 22:27:51 -04004770
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004771 if (!psde->debugfs_root)
4772 return -ENOMEM;
Clarence Ip4ce59322016-06-26 22:27:51 -04004773
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004774 /* don't error check these */
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004775 debugfs_create_x32("features", 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004776 psde->debugfs_root, &psde->features);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004777
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004778 /* add register dump support */
4779 sde_debugfs_setup_regset32(&psde->debugfs_src,
4780 sblk->src_blk.base + cfg->base,
4781 sblk->src_blk.len,
4782 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004783 sde_debugfs_create_regset32("src_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004784 psde->debugfs_root, &psde->debugfs_src);
Alan Kwongf0fd8512016-10-24 21:39:26 -04004785
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004786 if (cfg->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
4787 cfg->features & BIT(SDE_SSPP_SCALER_QSEED2)) {
4788 sde_debugfs_setup_regset32(&psde->debugfs_scaler,
4789 sblk->scaler_blk.base + cfg->base,
4790 sblk->scaler_blk.len,
4791 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004792 sde_debugfs_create_regset32("scaler_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004793 psde->debugfs_root,
4794 &psde->debugfs_scaler);
Clarence Ip716ab662017-03-20 06:51:24 -07004795 debugfs_create_bool("default_scaling",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004796 0600,
Clarence Ip716ab662017-03-20 06:51:24 -07004797 psde->debugfs_root,
4798 &psde->debugfs_default_scale);
Clarence Ip4ce59322016-06-26 22:27:51 -04004799 }
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004800
4801 if (cfg->features & BIT(SDE_SSPP_CSC) ||
4802 cfg->features & BIT(SDE_SSPP_CSC_10BIT)) {
4803 sde_debugfs_setup_regset32(&psde->debugfs_csc,
4804 sblk->csc_blk.base + cfg->base,
4805 sblk->csc_blk.len,
4806 kms);
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004807 sde_debugfs_create_regset32("csc_blk", 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004808 psde->debugfs_root, &psde->debugfs_csc);
4809 }
4810
4811 debugfs_create_u32("xin_id",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004812 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004813 psde->debugfs_root,
4814 (u32 *) &cfg->xin_id);
4815 debugfs_create_u32("clk_ctrl",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004816 0400,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004817 psde->debugfs_root,
4818 (u32 *) &cfg->clk_ctrl);
4819 debugfs_create_x32("creq_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004820 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004821 psde->debugfs_root,
4822 (u32 *) &sblk->creq_vblank);
4823 debugfs_create_x32("danger_vblank",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004824 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004825 psde->debugfs_root,
4826 (u32 *) &sblk->danger_vblank);
4827
4828 debugfs_create_file("disable_danger",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004829 0600,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004830 psde->debugfs_root,
4831 kms, &sde_plane_danger_enable);
Alan Kwong4dd64c82017-02-04 18:41:51 -08004832 debugfs_create_u32("sbuf_mode",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004833 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004834 psde->debugfs_root, &psde->sbuf_mode);
4835 debugfs_create_u32("sbuf_writeback",
Lloyd Atkinson8de415a2017-05-23 11:31:16 -04004836 0600,
Alan Kwong4dd64c82017-02-04 18:41:51 -08004837 psde->debugfs_root,
4838 &psde->sbuf_writeback);
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004839
4840 return 0;
4841}
4842
4843static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4844{
4845 struct sde_plane *psde;
4846
4847 if (!plane)
4848 return;
4849 psde = to_sde_plane(plane);
4850
4851 debugfs_remove_recursive(psde->debugfs_root);
4852}
4853#else
4854static int _sde_plane_init_debugfs(struct drm_plane *plane)
4855{
4856 return 0;
4857}
4858static void _sde_plane_destroy_debugfs(struct drm_plane *plane)
4859{
4860}
4861#endif
4862
4863static int sde_plane_late_register(struct drm_plane *plane)
4864{
4865 return _sde_plane_init_debugfs(plane);
4866}
4867
4868static void sde_plane_early_unregister(struct drm_plane *plane)
4869{
4870 _sde_plane_destroy_debugfs(plane);
4871}
4872
4873static const struct drm_plane_funcs sde_plane_funcs = {
4874 .update_plane = drm_atomic_helper_update_plane,
4875 .disable_plane = drm_atomic_helper_disable_plane,
4876 .destroy = sde_plane_destroy,
Clarence Ip569d5af2017-10-14 21:09:01 -04004877 .set_property = drm_atomic_helper_plane_set_property,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -07004878 .atomic_set_property = sde_plane_atomic_set_property,
4879 .atomic_get_property = sde_plane_atomic_get_property,
4880 .reset = sde_plane_reset,
4881 .atomic_duplicate_state = sde_plane_duplicate_state,
4882 .atomic_destroy_state = sde_plane_destroy_state,
4883 .late_register = sde_plane_late_register,
4884 .early_unregister = sde_plane_early_unregister,
4885};
4886
4887static const struct drm_plane_helper_funcs sde_plane_helper_funcs = {
4888 .prepare_fb = sde_plane_prepare_fb,
4889 .cleanup_fb = sde_plane_cleanup_fb,
4890 .atomic_check = sde_plane_atomic_check,
4891 .atomic_update = sde_plane_atomic_update,
4892};
4893
4894enum sde_sspp sde_plane_pipe(struct drm_plane *plane)
4895{
4896 return plane ? to_sde_plane(plane)->pipe : SSPP_NONE;
4897}
4898
4899bool is_sde_plane_virtual(struct drm_plane *plane)
4900{
4901 return plane ? to_sde_plane(plane)->is_virtual : false;
Clarence Ip4ce59322016-06-26 22:27:51 -04004902}
4903
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004904/* initialize plane */
Clarence Ipe78efb72016-06-24 18:35:21 -04004905struct drm_plane *sde_plane_init(struct drm_device *dev,
Clarence Ip2bbf7b32016-09-23 15:07:16 -04004906 uint32_t pipe, bool primary_plane,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004907 unsigned long possible_crtcs, u32 master_plane_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004908{
Alan Kwongdce56da2017-04-27 15:50:34 -07004909 struct drm_plane *plane = NULL, *master_plane = NULL;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004910 const struct sde_format_extended *format_list;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004911 struct sde_plane *psde;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004912 struct msm_drm_private *priv;
4913 struct sde_kms *kms;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004914 enum drm_plane_type type;
Clarence Ipc47a0692016-10-11 10:54:17 -04004915 int ret = -EINVAL;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004916
4917 if (!dev) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004918 SDE_ERROR("[%u]device is NULL\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004919 goto exit;
4920 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004921
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004922 priv = dev->dev_private;
Ben Chan78647cd2016-06-26 22:02:47 -04004923 if (!priv) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004924 SDE_ERROR("[%u]private data is NULL\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004925 goto exit;
4926 }
4927
4928 if (!priv->kms) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004929 SDE_ERROR("[%u]invalid KMS reference\n", pipe);
Ben Chan78647cd2016-06-26 22:02:47 -04004930 goto exit;
4931 }
4932 kms = to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004933
Clarence Ip4c1d9772016-06-26 09:35:38 -04004934 if (!kms->catalog) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004935 SDE_ERROR("[%u]invalid catalog reference\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004936 goto exit;
4937 }
4938
Clarence Ip4ce59322016-06-26 22:27:51 -04004939 /* create and zero local structure */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004940 psde = kzalloc(sizeof(*psde), GFP_KERNEL);
4941 if (!psde) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004942 SDE_ERROR("[%u]failed to allocate local plane struct\n", pipe);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004943 ret = -ENOMEM;
Clarence Ip4c1d9772016-06-26 09:35:38 -04004944 goto exit;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004945 }
4946
Clarence Ip4c1d9772016-06-26 09:35:38 -04004947 /* cache local stuff for later */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004948 plane = &psde->base;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004949 psde->pipe = pipe;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004950 psde->is_virtual = (master_plane_id != 0);
Alan Kwongdce56da2017-04-27 15:50:34 -07004951 INIT_LIST_HEAD(&psde->mplane_list);
4952 master_plane = drm_plane_find(dev, master_plane_id);
4953 if (master_plane) {
4954 struct sde_plane *mpsde = to_sde_plane(master_plane);
4955
4956 list_add_tail(&psde->mplane_list, &mpsde->mplane_list);
4957 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004958
Clarence Ip4c1d9772016-06-26 09:35:38 -04004959 /* initialize underlying h/w driver */
Dhaval Pateld850b222017-06-16 17:37:37 -07004960 psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog,
4961 master_plane_id != 0);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004962 if (IS_ERR(psde->pipe_hw)) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004963 SDE_ERROR("[%u]SSPP init failed\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004964 ret = PTR_ERR(psde->pipe_hw);
4965 goto clean_plane;
4966 } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004967 SDE_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004968 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04004969 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004970
4971 /* cache features mask for later */
4972 psde->features = psde->pipe_hw->cap->features;
4973 psde->pipe_sblk = psde->pipe_hw->cap->sblk;
Clarence Ipea3d6262016-07-15 16:20:11 -04004974 if (!psde->pipe_sblk) {
Clarence Ip13a8cf42016-09-29 17:27:47 -04004975 SDE_ERROR("[%u]invalid sblk\n", pipe);
Clarence Ipea3d6262016-07-15 16:20:11 -04004976 goto clean_sspp;
4977 }
Clarence Ip4c1d9772016-06-26 09:35:38 -04004978
Steve Cohen57428172017-07-18 10:57:17 -04004979 if (!master_plane_id)
4980 format_list = psde->pipe_sblk->format_list;
4981 else
4982 format_list = psde->pipe_sblk->virt_format_list;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004983
Jeykumar Sankaran6d343142017-03-15 18:41:10 -07004984 psde->nformats = sde_populate_formats(format_list,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08004985 psde->formats,
4986 0,
4987 ARRAY_SIZE(psde->formats));
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07004988
Clarence Ip4c1d9772016-06-26 09:35:38 -04004989 if (!psde->nformats) {
Dhaval Patel47302cf2016-08-18 15:04:28 -07004990 SDE_ERROR("[%u]no valid formats for plane\n", pipe);
Clarence Ip4c1d9772016-06-26 09:35:38 -04004991 goto clean_sspp;
4992 }
4993
4994 if (psde->features & BIT(SDE_SSPP_CURSOR))
4995 type = DRM_PLANE_TYPE_CURSOR;
4996 else if (primary_plane)
4997 type = DRM_PLANE_TYPE_PRIMARY;
4998 else
4999 type = DRM_PLANE_TYPE_OVERLAY;
Dhaval Patel04c7e8e2016-09-26 20:14:31 -07005000 ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
5001 psde->formats, psde->nformats,
5002 type, NULL);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005003 if (ret)
Clarence Ip4c1d9772016-06-26 09:35:38 -04005004 goto clean_sspp;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005005
Clarence Ip4c1d9772016-06-26 09:35:38 -04005006 /* success! finalize initialization */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04005007 drm_plane_helper_add(plane, &sde_plane_helper_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005008
Clarence Ipaa0faf42016-05-30 12:07:48 -04005009 msm_property_init(&psde->property_info, &plane->base, dev,
5010 priv->plane_property, psde->property_data,
5011 PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
5012 sizeof(struct sde_plane_state));
5013
Jeykumar Sankaran2e655032017-02-04 14:05:45 -08005014 _sde_plane_install_properties(plane, kms->catalog, master_plane_id);
Clarence Ip5e2a9222016-06-26 22:38:24 -04005015
Clarence Ip4ce59322016-06-26 22:27:51 -04005016 /* save user friendly pipe name for later */
Clarence Ip5e2a9222016-06-26 22:38:24 -04005017 snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
Clarence Ip4ce59322016-06-26 22:27:51 -04005018
Clarence Ip730e7192016-06-26 22:45:09 -04005019 mutex_init(&psde->lock);
5020
Dhaval Patel572cfd22017-06-12 19:33:39 -07005021 SDE_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", psde->pipe_name,
5022 pipe, plane->base.id, master_plane_id);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005023 return plane;
5024
Clarence Ip4c1d9772016-06-26 09:35:38 -04005025clean_sspp:
5026 if (psde && psde->pipe_hw)
5027 sde_hw_sspp_destroy(psde->pipe_hw);
5028clean_plane:
5029 kfree(psde);
Ben Chan78647cd2016-06-26 22:02:47 -04005030exit:
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07005031 return ERR_PTR(ret);
5032}