blob: 70860501c3c5f489db5265453c8249f30c088672 [file] [log] [blame]
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -07001/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Clarence Ipd9f9fa62016-09-09 13:42:32 -040013#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040014#include <linux/sort.h>
Clarence Ip8f7366c2016-07-05 12:15:26 -040015#include <linux/debugfs.h>
Clarence Ipcae1bb62016-07-07 12:07:13 -040016#include <linux/ktime.h>
Clarence Ip4c1d9772016-06-26 09:35:38 -040017#include <uapi/drm/sde_drm.h>
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070018#include <drm/drm_mode.h>
19#include <drm/drm_crtc.h>
20#include <drm/drm_crtc_helper.h>
21#include <drm/drm_flip_work.h>
22
23#include "sde_kms.h"
24#include "sde_hw_lm.h"
Clarence Ipc475b082016-06-26 09:27:23 -040025#include "sde_hw_ctl.h"
Abhijit Kulkarni40e38162016-06-26 22:12:09 -040026#include "sde_crtc.h"
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -070027#include "sde_color_processing.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040028
Abhijit Kulkarni40e38162016-06-26 22:12:09 -040029#define CTL(i) (CTL_0 + (i))
30#define LM(i) (LM_0 + (i))
31#define INTF(i) (INTF_0 + (i))
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070032
Clarence Ip4ce59322016-06-26 22:27:51 -040033/* uncomment to enable higher level IRQ msg's */
34/*#define DBG_IRQ DBG*/
35#define DBG_IRQ(fmt, ...)
36
Clarence Ipcae1bb62016-07-07 12:07:13 -040037/* default input fence timeout, in ms */
38#define SDE_CRTC_INPUT_FENCE_TIMEOUT 2000
39
Dhaval Patel4e574842016-08-23 15:11:37 -070040/*
41 * The default input fence timeout is 2 seconds while max allowed
42 * range is 10 seconds. Any value above 10 seconds adds glitches beyond
43 * tolerance limit.
44 */
45#define SDE_CRTC_MAX_INPUT_FENCE_TIMEOUT 10000
46
Dhaval Patel48c76022016-09-01 17:51:23 -070047/* layer mixer index on sde_crtc */
48#define LEFT_MIXER 0
49#define RIGHT_MIXER 1
50
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040051static struct sde_kms *get_kms(struct drm_crtc *crtc)
52{
53 struct msm_drm_private *priv = crtc->dev->dev_private;
Abhijit Kulkarni40e38162016-06-26 22:12:09 -040054
Ben Chan78647cd2016-06-26 22:02:47 -040055 return to_sde_kms(priv->kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040056}
57
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070058static void sde_crtc_destroy(struct drm_crtc *crtc)
59{
60 struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
61
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040062 DBG("");
Clarence Ip7a753bb2016-07-07 11:47:44 -040063
64 if (!crtc)
65 return;
66
67 msm_property_destroy(&sde_crtc->property_info);
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -070068 sde_cp_crtc_destroy_properties(crtc);
Clarence Ip8f7366c2016-07-05 12:15:26 -040069 debugfs_remove_recursive(sde_crtc->debugfs_root);
Clarence Ip24f80662016-06-13 19:05:32 -040070 sde_fence_deinit(&sde_crtc->output_fence);
Clarence Ip7a753bb2016-07-07 11:47:44 -040071
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070072 drm_crtc_cleanup(crtc);
73 kfree(sde_crtc);
74}
75
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070076static bool sde_crtc_mode_fixup(struct drm_crtc *crtc,
77 const struct drm_display_mode *mode,
78 struct drm_display_mode *adjusted_mode)
79{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040080 DBG("");
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -040081
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -040082 if (msm_is_mode_seamless(adjusted_mode)) {
Dhaval Patelec10fad2016-08-22 14:40:48 -070083 SDE_DEBUG("seamless mode set requested\n");
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -040084 if (!crtc->enabled || crtc->state->active_changed) {
Dhaval Patelec10fad2016-08-22 14:40:48 -070085 SDE_ERROR("crtc state prevents seamless transition\n");
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -040086 return false;
87 }
88 }
89
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070090 return true;
91}
92
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040093static void sde_crtc_mode_set_nofb(struct drm_crtc *crtc)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070094{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040095 DBG("");
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040096}
97
Dhaval Patel48c76022016-09-01 17:51:23 -070098static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer,
99 struct sde_plane_state *pstate, struct sde_format *format)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400100{
Dhaval Patel48c76022016-09-01 17:51:23 -0700101 uint32_t blend_op, fg_alpha, bg_alpha;
102 uint32_t blend_type;
Dhaval Patel44f12472016-08-29 12:19:47 -0700103 struct sde_hw_mixer *lm = mixer->hw_lm;
104
Dhaval Patel48c76022016-09-01 17:51:23 -0700105 /* default to opaque blending */
106 fg_alpha = sde_plane_get_property(pstate, PLANE_PROP_ALPHA);
107 bg_alpha = 0xFF - fg_alpha;
108 blend_op = SDE_BLEND_FG_ALPHA_FG_CONST | SDE_BLEND_BG_ALPHA_BG_CONST;
109 blend_type = sde_plane_get_property(pstate, PLANE_PROP_BLEND_OP);
Dhaval Patel44f12472016-08-29 12:19:47 -0700110
Dhaval Patel48c76022016-09-01 17:51:23 -0700111 SDE_DEBUG("blend type:0x%x blend alpha:0x%x\n", blend_type, fg_alpha);
112
113 switch (blend_type) {
114
115 case SDE_DRM_BLEND_OP_OPAQUE:
116 blend_op = SDE_BLEND_FG_ALPHA_FG_CONST |
117 SDE_BLEND_BG_ALPHA_BG_CONST;
118 break;
119
120 case SDE_DRM_BLEND_OP_PREMULTIPLIED:
121 if (format->alpha_enable) {
122 blend_op = SDE_BLEND_FG_ALPHA_FG_CONST |
123 SDE_BLEND_BG_ALPHA_FG_PIXEL;
124 if (fg_alpha != 0xff) {
125 bg_alpha = fg_alpha;
126 blend_op |= SDE_BLEND_BG_MOD_ALPHA |
127 SDE_BLEND_BG_INV_MOD_ALPHA;
128 } else {
129 blend_op |= SDE_BLEND_BG_INV_ALPHA;
130 }
131 }
132 break;
133
134 case SDE_DRM_BLEND_OP_COVERAGE:
135 if (format->alpha_enable) {
136 blend_op = SDE_BLEND_FG_ALPHA_FG_PIXEL |
137 SDE_BLEND_BG_ALPHA_FG_PIXEL;
138 if (fg_alpha != 0xff) {
139 bg_alpha = fg_alpha;
140 blend_op |= SDE_BLEND_FG_MOD_ALPHA |
141 SDE_BLEND_FG_INV_MOD_ALPHA |
142 SDE_BLEND_BG_MOD_ALPHA |
143 SDE_BLEND_BG_INV_MOD_ALPHA;
144 } else {
145 blend_op |= SDE_BLEND_BG_INV_ALPHA;
146 }
147 }
148 break;
149 default:
150 /* do nothing */
151 break;
Clarence Ipd9f9fa62016-09-09 13:42:32 -0400152 }
Dhaval Patel48c76022016-09-01 17:51:23 -0700153
154 lm->ops.setup_blend_config(lm, pstate->stage, fg_alpha,
155 bg_alpha, blend_op);
156 SDE_DEBUG("format 0x%x, alpha_enable %u fg alpha:0x%x bg alpha:0x%x \"\
157 blend_op:0x%x\n", format->base.pixel_format,
158 format->alpha_enable, fg_alpha, bg_alpha, blend_op);
159}
160
161static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
162 struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer)
163{
164 struct drm_plane *plane;
165
166 struct sde_plane_state *pstate = NULL;
167 struct sde_format *format;
168 struct sde_hw_ctl *ctl = mixer->hw_ctl;
169 struct sde_hw_stage_cfg *stage_cfg = &sde_crtc->stage_cfg;
170
171 u32 flush_mask = 0, crtc_split_width;
172 uint32_t lm_idx = LEFT_MIXER, idx;
173 bool bg_alpha_enable[CRTC_DUAL_MIXERS] = {false};
174 bool lm_right = false;
175 int left_crtc_zpos_cnt[SDE_STAGE_MAX + 1] = {0};
176 int right_crtc_zpos_cnt[SDE_STAGE_MAX + 1] = {0};
177
178 crtc_split_width = get_crtc_split_width(crtc);
Dhaval Patel44f12472016-08-29 12:19:47 -0700179
180 drm_atomic_crtc_for_each_plane(plane, crtc) {
Dhaval Patel48c76022016-09-01 17:51:23 -0700181
Dhaval Patel44f12472016-08-29 12:19:47 -0700182 pstate = to_sde_plane_state(plane->state);
Dhaval Patel44f12472016-08-29 12:19:47 -0700183
Dhaval Patel48c76022016-09-01 17:51:23 -0700184 flush_mask = ctl->ops.get_bitmask_sspp(ctl,
185 sde_plane_pipe(plane));
Dhaval Patel44f12472016-08-29 12:19:47 -0700186
Dhaval Patel48c76022016-09-01 17:51:23 -0700187 /* always stage plane on either left or right lm */
188 if (plane->state->crtc_x >= crtc_split_width) {
189 lm_idx = RIGHT_MIXER;
190 idx = right_crtc_zpos_cnt[pstate->stage]++;
191 } else {
192 lm_idx = LEFT_MIXER;
193 idx = left_crtc_zpos_cnt[pstate->stage]++;
194 }
195
196 /* stage plane on right LM if it crosses the boundary */
197 lm_right = (lm_idx == LEFT_MIXER) &&
198 (plane->state->crtc_x + plane->state->crtc_w >
199 crtc_split_width);
200
201 stage_cfg->stage[lm_idx][pstate->stage][idx] =
202 sde_plane_pipe(plane);
203 mixer[lm_idx].flush_mask |= flush_mask;
204
205 SDE_DEBUG("crtc %d stage:%d - plane %d sspp %d fb %d\n",
Clarence Ipd9f9fa62016-09-09 13:42:32 -0400206 crtc->base.id,
Clarence Ipd9f9fa62016-09-09 13:42:32 -0400207 pstate->stage,
208 plane->base.id,
209 sde_plane_pipe(plane) - SSPP_VIG0,
210 plane->state->fb ?
211 plane->state->fb->base.id : -1);
Dhaval Patel44f12472016-08-29 12:19:47 -0700212
Dhaval Patel48c76022016-09-01 17:51:23 -0700213 format = to_sde_format(msm_framebuffer_format(pstate->base.fb));
Dhaval Patel44f12472016-08-29 12:19:47 -0700214
Dhaval Patel48c76022016-09-01 17:51:23 -0700215 /* blend config update */
216 if (pstate->stage != SDE_STAGE_BASE) {
217 _sde_crtc_setup_blend_cfg(mixer + lm_idx, pstate,
218 format);
219
220 if (bg_alpha_enable[lm_idx] && !format->alpha_enable)
221 mixer[lm_idx].mixer_op_mode = 0;
222 else
223 mixer[lm_idx].mixer_op_mode |=
224 1 << pstate->stage;
225 } else if (format->alpha_enable) {
226 bg_alpha_enable[lm_idx] = true;
227 }
228
229 if (lm_right) {
230 idx = right_crtc_zpos_cnt[pstate->stage]++;
231 stage_cfg->stage[RIGHT_MIXER][pstate->stage][idx] =
232 sde_plane_pipe(plane);
233 mixer[RIGHT_MIXER].flush_mask |= flush_mask;
234
235 /* blend config update */
236 if (pstate->stage != SDE_STAGE_BASE) {
237 _sde_crtc_setup_blend_cfg(mixer + RIGHT_MIXER,
238 pstate, format);
239
240 if (bg_alpha_enable[RIGHT_MIXER] &&
241 !format->alpha_enable)
242 mixer[RIGHT_MIXER].mixer_op_mode = 0;
243 else
244 mixer[RIGHT_MIXER].mixer_op_mode |=
245 1 << pstate->stage;
246 } else if (format->alpha_enable) {
247 bg_alpha_enable[RIGHT_MIXER] = true;
248 }
249 }
Dhaval Patel44f12472016-08-29 12:19:47 -0700250 }
Dhaval Patel44f12472016-08-29 12:19:47 -0700251}
252
Clarence Ipd9f9fa62016-09-09 13:42:32 -0400253/**
254 * _sde_crtc_blend_setup - configure crtc mixers
255 * @crtc: Pointer to drm crtc structure
256 */
257static void _sde_crtc_blend_setup(struct drm_crtc *crtc)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400258{
259 struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400260 struct sde_crtc_mixer *mixer = sde_crtc->mixers;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400261 struct sde_hw_ctl *ctl;
262 struct sde_hw_mixer *lm;
Dhaval Patel44f12472016-08-29 12:19:47 -0700263
264 int i;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400265
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400266 SDE_DEBUG("%s\n", sde_crtc->name);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400267
Dhaval Patel48c76022016-09-01 17:51:23 -0700268 if (sde_crtc->num_mixers > CRTC_DUAL_MIXERS) {
269 SDE_ERROR("invalid number mixers: %d\n", sde_crtc->num_mixers);
270 return;
271 }
272
273 for (i = 0; i < sde_crtc->num_mixers; i++) {
274 if (!mixer[i].hw_lm || !mixer[i].hw_ctl) {
275 SDE_ERROR("invalid lm or ctl assigned to mixer\n");
276 return;
277 }
278 mixer[i].mixer_op_mode = 0;
279 mixer[i].flush_mask = 0;
280 }
281
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400282 /* initialize stage cfg */
Clarence Ip8f7366c2016-07-05 12:15:26 -0400283 memset(&sde_crtc->stage_cfg, 0, sizeof(struct sde_hw_stage_cfg));
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400284
Dhaval Patel48c76022016-09-01 17:51:23 -0700285 _sde_crtc_blend_setup_mixer(crtc, sde_crtc, mixer);
286
Abhijit Kulkarni71002ba2016-06-24 18:36:28 -0400287 for (i = 0; i < sde_crtc->num_mixers; i++) {
Abhijit Kulkarni71002ba2016-06-24 18:36:28 -0400288 ctl = mixer[i].hw_ctl;
289 lm = mixer[i].hw_lm;
Abhijit Kulkarni71002ba2016-06-24 18:36:28 -0400290
Dhaval Patel48c76022016-09-01 17:51:23 -0700291 lm->ops.setup_alpha_out(lm, mixer[i].mixer_op_mode);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400292
Dhaval Patel48c76022016-09-01 17:51:23 -0700293 mixer[i].flush_mask |= ctl->ops.get_bitmask_mixer(ctl,
Abhijit Kulkarni71002ba2016-06-24 18:36:28 -0400294 mixer[i].hw_lm->idx);
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400295
296 /* stage config flush mask */
Dhaval Patel48c76022016-09-01 17:51:23 -0700297 ctl->ops.update_pending_flush(ctl, mixer[i].flush_mask);
298
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400299 SDE_DEBUG("lm %d ctl %d add mask 0x%x to pending flush\n",
Alan Kwong85767282016-10-03 18:03:37 -0400300 mixer[i].hw_lm->idx, ctl->idx, mixer[i].flush_mask);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400301
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400302 ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
Dhaval Patel44f12472016-08-29 12:19:47 -0700303 &sde_crtc->stage_cfg, i);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400304 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400305}
306
Clarence Ip24f80662016-06-13 19:05:32 -0400307void sde_crtc_prepare_fence(struct drm_crtc *crtc)
308{
309 struct sde_crtc *sde_crtc;
310
311 if (!crtc) {
312 SDE_ERROR("invalid crtc\n");
313 return;
314 }
315
316 sde_crtc = to_sde_crtc(crtc);
317
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400318 MSM_EVT(crtc->dev, crtc->base.id, 0);
Clarence Ip24f80662016-06-13 19:05:32 -0400319
320 sde_fence_prepare(&sde_crtc->output_fence);
321}
322
Abhijit Kulkarni40e38162016-06-26 22:12:09 -0400323/* if file!=NULL, this is preclose potential cancel-flip path */
324static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
325{
326 struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
327 struct drm_device *dev = crtc->dev;
328 struct drm_pending_vblank_event *event;
329 unsigned long flags;
330
331 spin_lock_irqsave(&dev->event_lock, flags);
332 event = sde_crtc->event;
333 if (event) {
334 /* if regular vblank case (!file) or if cancel-flip from
335 * preclose on file that requested flip, then send the
336 * event:
337 */
338 if (!file || (event->base.file_priv == file)) {
339 sde_crtc->event = NULL;
Dhaval Patelec10fad2016-08-22 14:40:48 -0700340 SDE_DEBUG("%s: send event: %pK\n",
341 sde_crtc->name, event);
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400342 drm_send_vblank_event(dev, sde_crtc->drm_crtc_id,
343 event);
Abhijit Kulkarni40e38162016-06-26 22:12:09 -0400344 }
345 }
346 spin_unlock_irqrestore(&dev->event_lock, flags);
347}
348
349static void sde_crtc_vblank_cb(void *data)
350{
351 struct drm_crtc *crtc = (struct drm_crtc *)data;
352 struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
Abhijit Kulkarni7acb3262016-07-05 15:27:25 -0400353 struct sde_kms *sde_kms = get_kms(crtc);
354 struct drm_device *dev = sde_kms->dev;
Abhijit Kulkarni40e38162016-06-26 22:12:09 -0400355
Alan Kwongcf42ee02016-10-04 09:19:17 -0400356 drm_handle_vblank(dev, sde_crtc->drm_crtc_id);
357 DBG_IRQ("");
358 MSM_EVT(crtc->dev, crtc->base.id, 0);
Abhijit Kulkarni40e38162016-06-26 22:12:09 -0400359}
360
Clarence Ip24f80662016-06-13 19:05:32 -0400361void sde_crtc_complete_commit(struct drm_crtc *crtc)
362{
363 if (!crtc) {
364 SDE_ERROR("invalid crtc\n");
365 return;
366 }
367
368 /* signal out fence at end of commit */
369 sde_fence_signal(&to_sde_crtc(crtc)->output_fence, 0);
370}
371
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400372/**
Clarence Ipcae1bb62016-07-07 12:07:13 -0400373 * _sde_crtc_set_input_fence_timeout - update ns version of in fence timeout
374 * @cstate: Pointer to sde crtc state
375 */
376static void _sde_crtc_set_input_fence_timeout(struct sde_crtc_state *cstate)
377{
378 if (!cstate) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700379 SDE_ERROR("invalid cstate\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400380 return;
381 }
382 cstate->input_fence_timeout_ns =
383 sde_crtc_get_property(cstate, CRTC_PROP_INPUT_FENCE_TIMEOUT);
384 cstate->input_fence_timeout_ns *= NSEC_PER_MSEC;
385}
386
387/**
388 * _sde_crtc_wait_for_fences - wait for incoming framebuffer sync fences
389 * @crtc: Pointer to CRTC object
390 */
391static void _sde_crtc_wait_for_fences(struct drm_crtc *crtc)
392{
393 struct drm_plane *plane = NULL;
394 uint32_t wait_ms = 1;
Clarence Ip8dedc232016-09-09 16:41:00 -0400395 ktime_t kt_end, kt_wait;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400396
397 DBG("");
398
399 if (!crtc || !crtc->state) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700400 SDE_ERROR("invalid crtc/state %pK\n", crtc);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400401 return;
402 }
403
404 /* use monotonic timer to limit total fence wait time */
Clarence Ip8dedc232016-09-09 16:41:00 -0400405 kt_end = ktime_add_ns(ktime_get(),
406 to_sde_crtc_state(crtc->state)->input_fence_timeout_ns);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400407
408 /*
409 * Wait for fences sequentially, as all of them need to be signalled
410 * before we can proceed.
411 *
412 * Limit total wait time to INPUT_FENCE_TIMEOUT, but still call
413 * sde_plane_wait_input_fence with wait_ms == 0 after the timeout so
414 * that each plane can check its fence status and react appropriately
415 * if its fence has timed out.
416 */
417 drm_atomic_crtc_for_each_plane(plane, crtc) {
418 if (wait_ms) {
419 /* determine updated wait time */
Clarence Ip8dedc232016-09-09 16:41:00 -0400420 kt_wait = ktime_sub(kt_end, ktime_get());
421 if (ktime_compare(kt_wait, ktime_set(0, 0)) >= 0)
422 wait_ms = ktime_to_ms(kt_wait);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400423 else
424 wait_ms = 0;
425 }
426 sde_plane_wait_input_fence(plane, wait_ms);
427 }
428}
429
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400430static void _sde_crtc_setup_mixer_for_encoder(
431 struct drm_crtc *crtc,
432 struct drm_encoder *enc)
433{
434 struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
435 struct sde_kms *sde_kms = get_kms(crtc);
436 struct sde_rm *rm = &sde_kms->rm;
437 struct sde_crtc_mixer *mixer;
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400438 struct sde_hw_ctl *last_valid_ctl = NULL;
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400439 int i;
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -0700440 struct sde_rm_hw_iter lm_iter, ctl_iter, dspp_iter;
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400441
442 sde_rm_init_hw_iter(&lm_iter, enc->base.id, SDE_HW_BLK_LM);
443 sde_rm_init_hw_iter(&ctl_iter, enc->base.id, SDE_HW_BLK_CTL);
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -0700444 sde_rm_init_hw_iter(&dspp_iter, enc->base.id, SDE_HW_BLK_DSPP);
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400445
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400446 /* Set up all the mixers and ctls reserved by this encoder */
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400447 for (i = sde_crtc->num_mixers; i < ARRAY_SIZE(sde_crtc->mixers); i++) {
448 mixer = &sde_crtc->mixers[i];
449
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400450 if (!sde_rm_get_hw(rm, &lm_iter))
451 break;
452 mixer->hw_lm = (struct sde_hw_mixer *)lm_iter.hw;
453
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400454 /* CTL may be <= LMs, if <, multiple LMs controlled by 1 CTL */
455 if (!sde_rm_get_hw(rm, &ctl_iter)) {
456 SDE_DEBUG("no ctl assigned to lm %d, using previous\n",
457 mixer->hw_lm->idx);
458 mixer->hw_ctl = last_valid_ctl;
459 } else {
460 mixer->hw_ctl = (struct sde_hw_ctl *)ctl_iter.hw;
461 last_valid_ctl = mixer->hw_ctl;
462 }
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400463
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400464 /* Shouldn't happen, mixers are always >= ctls */
465 if (!mixer->hw_ctl) {
466 SDE_ERROR("no valid ctls found for lm %d\n",
467 mixer->hw_lm->idx);
468 return;
469 }
470
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -0700471 /* Dspp may be null */
472 (void) sde_rm_get_hw(rm, &dspp_iter);
473 mixer->hw_dspp = (struct sde_hw_dspp *)dspp_iter.hw;
474
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400475 mixer->encoder = enc;
476
477 sde_crtc->num_mixers++;
Clarence Ipd9f9fa62016-09-09 13:42:32 -0400478 SDE_DEBUG("setup mixer %d: lm %d\n",
479 i, mixer->hw_lm->idx - LM_0);
480 SDE_DEBUG("setup mixer %d: ctl %d\n",
481 i, mixer->hw_ctl->idx - CTL_0);
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400482 }
483}
484
485static void _sde_crtc_setup_mixers(struct drm_crtc *crtc)
486{
487 struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
488 struct drm_encoder *enc;
489
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400490 sde_crtc->num_mixers = 0;
491 memset(sde_crtc->mixers, 0, sizeof(sde_crtc->mixers));
492
493 /* Check for mixers on all encoders attached to this crtc */
494 list_for_each_entry(enc, &crtc->dev->mode_config.encoder_list, head) {
495 if (enc->crtc != crtc)
496 continue;
497
498 _sde_crtc_setup_mixer_for_encoder(crtc, enc);
499 }
500}
501
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400502static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
503 struct drm_crtc_state *old_crtc_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700504{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400505 struct sde_crtc *sde_crtc;
506 struct drm_device *dev;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400507 unsigned long flags;
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400508 u32 i;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400509
510 DBG("");
511
Clarence Ipcae1bb62016-07-07 12:07:13 -0400512 if (!crtc) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700513 SDE_ERROR("invalid crtc\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400514 return;
515 }
516
517 sde_crtc = to_sde_crtc(crtc);
518 dev = crtc->dev;
519
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400520 if (!sde_crtc->num_mixers)
521 _sde_crtc_setup_mixers(crtc);
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400522
Lloyd Atkinson265d2212016-05-30 13:12:01 -0400523 if (sde_crtc->event) {
524 WARN_ON(sde_crtc->event);
525 } else {
526 spin_lock_irqsave(&dev->event_lock, flags);
527 sde_crtc->event = crtc->state->event;
528 spin_unlock_irqrestore(&dev->event_lock, flags);
529 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400530
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400531 /* Reset flush mask from previous commit */
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400532 for (i = 0; i < ARRAY_SIZE(sde_crtc->mixers); i++) {
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400533 struct sde_hw_ctl *ctl = sde_crtc->mixers[i].hw_ctl;
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400534
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400535 if (ctl)
536 ctl->ops.clear_pending_flush(ctl);
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400537 }
538
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400539 /*
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400540 * If no mixers have been allocated in sde_crtc_atomic_check(),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400541 * it means we are trying to flush a CRTC whose state is disabled:
542 * nothing else needs to be done.
543 */
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400544 if (unlikely(!sde_crtc->num_mixers))
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400545 return;
546
Clarence Ipd9f9fa62016-09-09 13:42:32 -0400547 _sde_crtc_blend_setup(crtc);
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -0700548 sde_cp_crtc_apply_properties(crtc);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400549
550 /*
551 * PP_DONE irq is only used by command mode for now.
552 * It is better to request pending before FLUSH and START trigger
553 * to make sure no pp_done irq missed.
554 * This is safe because no pp_done will happen before SW trigger
555 * in command mode.
556 */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700557}
558
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400559static void sde_crtc_atomic_flush(struct drm_crtc *crtc,
560 struct drm_crtc_state *old_crtc_state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700561{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400562 struct sde_crtc *sde_crtc;
563 struct drm_device *dev;
Lloyd Atkinson265d2212016-05-30 13:12:01 -0400564 struct drm_plane *plane;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400565 unsigned long flags;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700566
Clarence Ipcae1bb62016-07-07 12:07:13 -0400567 if (!crtc) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700568 SDE_ERROR("invalid crtc\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400569 return;
570 }
571
572 DBG("");
573
574 sde_crtc = to_sde_crtc(crtc);
575
576 dev = crtc->dev;
577
Lloyd Atkinson265d2212016-05-30 13:12:01 -0400578 if (sde_crtc->event) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700579 SDE_DEBUG("already received sde_crtc->event\n");
Lloyd Atkinson265d2212016-05-30 13:12:01 -0400580 } else {
Lloyd Atkinson265d2212016-05-30 13:12:01 -0400581 spin_lock_irqsave(&dev->event_lock, flags);
582 sde_crtc->event = crtc->state->event;
583 spin_unlock_irqrestore(&dev->event_lock, flags);
584 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400585
586 /*
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400587 * If no mixers has been allocated in sde_crtc_atomic_check(),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400588 * it means we are trying to flush a CRTC whose state is disabled:
589 * nothing else needs to be done.
590 */
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400591 if (unlikely(!sde_crtc->num_mixers))
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400592 return;
593
Clarence Ipcae1bb62016-07-07 12:07:13 -0400594 /* wait for acquire fences before anything else is done */
595 _sde_crtc_wait_for_fences(crtc);
596
597 /*
598 * Final plane updates: Give each plane a chance to complete all
599 * required writes/flushing before crtc's "flush
600 * everything" call below.
601 */
602 drm_atomic_crtc_for_each_plane(plane, crtc)
603 sde_plane_flush(plane);
604
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400605 /* Kickoff will be scheduled by outer layer */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700606}
607
Clarence Ip7a753bb2016-07-07 11:47:44 -0400608/**
609 * sde_crtc_destroy_state - state destroy hook
610 * @crtc: drm CRTC
611 * @state: CRTC state object to release
612 */
613static void sde_crtc_destroy_state(struct drm_crtc *crtc,
614 struct drm_crtc_state *state)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700615{
Clarence Ip7a753bb2016-07-07 11:47:44 -0400616 struct sde_crtc *sde_crtc;
617 struct sde_crtc_state *cstate;
618
619 if (!crtc || !state) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700620 SDE_ERROR("invalid argument(s)\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -0400621 return;
622 }
623
624 sde_crtc = to_sde_crtc(crtc);
625 cstate = to_sde_crtc_state(state);
626
627 DBG("");
628
629 __drm_atomic_helper_crtc_destroy_state(crtc, state);
630
631 /* destroy value helper */
632 msm_property_destroy_state(&sde_crtc->property_info, cstate,
633 cstate->property_values, cstate->property_blobs);
634}
635
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400636void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
637{
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400638 struct drm_encoder *encoder;
639 struct drm_device *dev;
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400640
641 if (!crtc) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700642 SDE_ERROR("invalid argument\n");
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400643 return;
644 }
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400645 dev = crtc->dev;
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400646
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400647 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
648 if (encoder->crtc != crtc)
649 continue;
650
651 /*
652 * Encoder will flush/start now, unless it has a tx pending.
653 * If so, it may delay and flush at an irq event (e.g. ppdone)
654 */
Clarence Ip110d15c2016-08-16 14:44:41 -0400655 sde_encoder_schedule_kickoff(encoder);
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400656 }
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400657}
658
Clarence Ip7a753bb2016-07-07 11:47:44 -0400659/**
660 * sde_crtc_duplicate_state - state duplicate hook
661 * @crtc: Pointer to drm crtc structure
662 * @Returns: Pointer to new drm_crtc_state structure
663 */
664static struct drm_crtc_state *sde_crtc_duplicate_state(struct drm_crtc *crtc)
665{
666 struct sde_crtc *sde_crtc;
667 struct sde_crtc_state *cstate, *old_cstate;
668
669 if (!crtc || !crtc->state) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700670 SDE_ERROR("invalid argument(s)\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -0400671 return NULL;
672 }
673
674 sde_crtc = to_sde_crtc(crtc);
675 old_cstate = to_sde_crtc_state(crtc->state);
676 cstate = msm_property_alloc_state(&sde_crtc->property_info);
677 if (!cstate) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700678 SDE_ERROR("failed to allocate state\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -0400679 return NULL;
680 }
681
682 /* duplicate value helper */
683 msm_property_duplicate_state(&sde_crtc->property_info,
684 old_cstate, cstate,
685 cstate->property_values, cstate->property_blobs);
686
687 /* duplicate base helper */
688 __drm_atomic_helper_crtc_duplicate_state(crtc, &cstate->base);
689
690 return &cstate->base;
691}
692
693/**
694 * sde_crtc_reset - reset hook for CRTCs
695 * Resets the atomic state for @crtc by freeing the state pointer (which might
696 * be NULL, e.g. at driver load time) and allocating a new empty state object.
697 * @crtc: Pointer to drm crtc structure
698 */
699static void sde_crtc_reset(struct drm_crtc *crtc)
700{
701 struct sde_crtc *sde_crtc;
702 struct sde_crtc_state *cstate;
703
704 if (!crtc) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700705 SDE_ERROR("invalid crtc\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -0400706 return;
707 }
708
709 /* remove previous state, if present */
710 if (crtc->state) {
711 sde_crtc_destroy_state(crtc, crtc->state);
712 crtc->state = 0;
713 }
714
715 sde_crtc = to_sde_crtc(crtc);
716 cstate = msm_property_alloc_state(&sde_crtc->property_info);
717 if (!cstate) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700718 SDE_ERROR("failed to allocate state\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -0400719 return;
720 }
721
722 /* reset value helper */
723 msm_property_reset_state(&sde_crtc->property_info, cstate,
724 cstate->property_values, cstate->property_blobs);
725
Clarence Ipcae1bb62016-07-07 12:07:13 -0400726 _sde_crtc_set_input_fence_timeout(cstate);
727
Clarence Ip7a753bb2016-07-07 11:47:44 -0400728 cstate->base.crtc = crtc;
729 crtc->state = &cstate->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700730}
731
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400732static void sde_crtc_disable(struct drm_crtc *crtc)
733{
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400734 struct sde_crtc *sde_crtc;
735
736 if (!crtc) {
737 DRM_ERROR("invalid crtc\n");
738 return;
739 }
740 sde_crtc = to_sde_crtc(crtc);
741
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400742 DBG("");
Lloyd Atkinsonc44a52e2016-08-16 16:40:17 -0400743
744 memset(sde_crtc->mixers, 0, sizeof(sde_crtc->mixers));
745 sde_crtc->num_mixers = 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400746}
747
748static void sde_crtc_enable(struct drm_crtc *crtc)
749{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400750 struct sde_crtc *sde_crtc;
751 struct sde_crtc_mixer *mixer;
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -0400752 struct sde_hw_mixer *lm;
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -0400753 struct drm_display_mode *mode;
754 struct sde_hw_mixer_cfg cfg;
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -0400755 int i;
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -0400756
Clarence Ipcae1bb62016-07-07 12:07:13 -0400757 if (!crtc) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700758 SDE_ERROR("invalid crtc\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400759 return;
760 }
761
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400762 DBG("");
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -0400763
Clarence Ipcae1bb62016-07-07 12:07:13 -0400764 sde_crtc = to_sde_crtc(crtc);
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400765 mixer = sde_crtc->mixers;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400766
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -0400767 if (WARN_ON(!crtc->state))
768 return;
769
770 mode = &crtc->state->adjusted_mode;
771
772 drm_mode_debug_printmodeline(mode);
773
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -0400774 for (i = 0; i < sde_crtc->num_mixers; i++) {
775 lm = mixer[i].hw_lm;
Dhaval Patelec10fad2016-08-22 14:40:48 -0700776 cfg.out_width = sde_crtc_mixer_width(sde_crtc, mode);
Lloyd Atkinsonaf7952d2016-06-26 22:41:26 -0400777 cfg.out_height = mode->vdisplay;
778 cfg.right_mixer = (i == 0) ? false : true;
779 cfg.flags = 0;
780 lm->ops.setup_mixer_out(lm, &cfg);
781 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400782}
783
784struct plane_state {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700785 struct sde_plane_state *sde_pstate;
786 struct drm_plane_state *drm_pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400787};
788
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400789static int sde_crtc_atomic_check(struct drm_crtc *crtc,
790 struct drm_crtc_state *state)
791{
Clarence Ipcae1bb62016-07-07 12:07:13 -0400792 struct sde_crtc *sde_crtc;
Dhaval Patelec10fad2016-08-22 14:40:48 -0700793 struct plane_state pstates[SDE_STAGE_MAX * 2];
794
795 struct drm_plane_state *pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400796 struct drm_plane *plane;
Dhaval Patelec10fad2016-08-22 14:40:48 -0700797 struct drm_display_mode *mode;
798
799 int cnt = 0, rc = 0, mixer_width, i, z_pos;
800 int left_crtc_zpos_cnt[SDE_STAGE_MAX] = {0};
801 int right_crtc_zpos_cnt[SDE_STAGE_MAX] = {0};
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400802
Clarence Ipcae1bb62016-07-07 12:07:13 -0400803 if (!crtc) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700804 SDE_ERROR("invalid crtc\n");
Clarence Ipcae1bb62016-07-07 12:07:13 -0400805 return -EINVAL;
806 }
807
Lloyd Atkinson5217336c2016-09-15 18:21:18 -0400808 if (!state->enable || !state->active) {
809 SDE_DEBUG("crtc%d -> enable %d, active %d, skip atomic_check\n",
810 crtc->base.id, state->enable, state->active);
811 return 0;
812 }
813
Clarence Ipcae1bb62016-07-07 12:07:13 -0400814 sde_crtc = to_sde_crtc(crtc);
Dhaval Patelec10fad2016-08-22 14:40:48 -0700815 mode = &state->adjusted_mode;
816 SDE_DEBUG("%s: check", sde_crtc->name);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400817
Dhaval Patelec10fad2016-08-22 14:40:48 -0700818 mixer_width = sde_crtc_mixer_width(sde_crtc, mode);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400819
Dhaval Patelec10fad2016-08-22 14:40:48 -0700820 /* get plane state for all drm planes associated with crtc state */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400821 drm_atomic_crtc_state_for_each_plane(plane, state) {
Alan Kwong85767282016-10-03 18:03:37 -0400822 pstate = drm_atomic_get_plane_state(state->state, plane);
823 if (IS_ERR(pstate)) {
824 SDE_ERROR("%s: failed to get plane:%d state\n",
825 sde_crtc->name,
826 plane->base.id);
827 rc = -EINVAL;
828 goto end;
829 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400830
Dhaval Patelec10fad2016-08-22 14:40:48 -0700831 pstates[cnt].sde_pstate = to_sde_plane_state(pstate);
832 pstates[cnt].drm_pstate = pstate;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400833 cnt++;
Dhaval Patelec10fad2016-08-22 14:40:48 -0700834
835 if (CHECK_LAYER_BOUNDS(pstate->crtc_y, pstate->crtc_h,
836 mode->vdisplay) ||
837 CHECK_LAYER_BOUNDS(pstate->crtc_x, pstate->crtc_w,
838 mode->hdisplay)) {
839 SDE_ERROR("invalid vertical/horizontal destination\n");
840 SDE_ERROR("y:%d h:%d vdisp:%d x:%d w:%d hdisp:%d\n",
841 pstate->crtc_y, pstate->crtc_h, mode->vdisplay,
842 pstate->crtc_x, pstate->crtc_w, mode->hdisplay);
843 rc = -E2BIG;
844 goto end;
845 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400846 }
847
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400848 for (i = 0; i < cnt; i++) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700849 z_pos = sde_plane_get_property(pstates[i].sde_pstate,
850 PLANE_PROP_ZPOS);
851
852 if (pstates[i].drm_pstate->crtc_x < mixer_width) {
853 if (left_crtc_zpos_cnt[z_pos] == 2) {
854 SDE_ERROR("> 2 plane @ stage%d on left\n",
855 z_pos);
856 rc = -EINVAL;
857 goto end;
858 }
859 left_crtc_zpos_cnt[z_pos]++;
860 } else {
861 if (right_crtc_zpos_cnt[z_pos] == 2) {
862 SDE_ERROR("> 2 plane @ stage%d on right\n",
863 z_pos);
864 rc = -EINVAL;
865 goto end;
866 }
867 right_crtc_zpos_cnt[z_pos]++;
868 }
869 pstates[i].sde_pstate->stage = z_pos;
870 SDE_DEBUG("%s: zpos %d", sde_crtc->name, z_pos);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400871 }
872
Dhaval Patelec10fad2016-08-22 14:40:48 -0700873end:
874 return rc;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400875}
876
Abhijit Kulkarni7acb3262016-07-05 15:27:25 -0400877int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700878{
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400879 struct drm_encoder *encoder;
880 struct drm_device *dev = crtc->dev;
Abhijit Kulkarni7acb3262016-07-05 15:27:25 -0400881
Dhaval Patelec10fad2016-08-22 14:40:48 -0700882 SDE_DEBUG("%d", en);
Lloyd Atkinsone5c2c0b2016-07-05 12:23:29 -0400883
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400884 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
885 if (encoder->crtc != crtc)
886 continue;
Alan Kwongcf42ee02016-10-04 09:19:17 -0400887
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400888 MSM_EVT(crtc->dev, crtc->base.id, en);
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400889
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400890 if (en)
891 sde_encoder_register_vblank_callback(encoder,
892 sde_crtc_vblank_cb, (void *)crtc);
893 else
894 sde_encoder_register_vblank_callback(encoder, NULL,
895 NULL);
896 }
Abhijit Kulkarni7acb3262016-07-05 15:27:25 -0400897
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700898 return 0;
899}
900
Lloyd Atkinson5217336c2016-09-15 18:21:18 -0400901void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
902{
903 struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
904
905 SDE_DEBUG("%s: cancel: %p", sde_crtc->name, file);
906 complete_flip(crtc, file);
907}
908
Clarence Ip7a753bb2016-07-07 11:47:44 -0400909/**
910 * sde_crtc_install_properties - install all drm properties for crtc
911 * @crtc: Pointer to drm crtc structure
912 */
913static void sde_crtc_install_properties(struct drm_crtc *crtc)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700914{
Clarence Ip7a753bb2016-07-07 11:47:44 -0400915 struct sde_crtc *sde_crtc;
916 struct drm_device *dev;
917
918 DBG("");
919
920 if (!crtc) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700921 SDE_ERROR("invalid crtc\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -0400922 return;
923 }
924
925 sde_crtc = to_sde_crtc(crtc);
926 dev = crtc->dev;
927
928 /* range properties */
929 msm_property_install_range(&sde_crtc->property_info,
Dhaval Patel4e574842016-08-23 15:11:37 -0700930 "input_fence_timeout", 0x0, 0, SDE_CRTC_MAX_INPUT_FENCE_TIMEOUT,
931 SDE_CRTC_INPUT_FENCE_TIMEOUT, CRTC_PROP_INPUT_FENCE_TIMEOUT);
932
933 msm_property_install_range(&sde_crtc->property_info, "output_fence",
934 0x0, 0, INR_OPEN_MAX, 0x0, CRTC_PROP_OUTPUT_FENCE);
Clarence Ip1d9728b2016-09-01 11:10:54 -0400935
936 msm_property_install_range(&sde_crtc->property_info,
937 "output_fence_offset", 0x0, 0, 1, 0,
938 CRTC_PROP_OUTPUT_FENCE_OFFSET);
Clarence Ip7a753bb2016-07-07 11:47:44 -0400939}
940
941/**
942 * sde_crtc_atomic_set_property - atomically set a crtc drm property
943 * @crtc: Pointer to drm crtc structure
944 * @state: Pointer to drm crtc state structure
945 * @property: Pointer to targeted drm property
946 * @val: Updated property value
947 * @Returns: Zero on success
948 */
949static int sde_crtc_atomic_set_property(struct drm_crtc *crtc,
950 struct drm_crtc_state *state,
951 struct drm_property *property,
952 uint64_t val)
953{
954 struct sde_crtc *sde_crtc;
955 struct sde_crtc_state *cstate;
Clarence Ipcae1bb62016-07-07 12:07:13 -0400956 int idx, ret = -EINVAL;
Clarence Ip7a753bb2016-07-07 11:47:44 -0400957
958 if (!crtc || !state || !property) {
Dhaval Patelec10fad2016-08-22 14:40:48 -0700959 SDE_ERROR("invalid argument(s)\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -0400960 } else {
961 sde_crtc = to_sde_crtc(crtc);
962 cstate = to_sde_crtc_state(state);
963 ret = msm_property_atomic_set(&sde_crtc->property_info,
964 cstate->property_values, cstate->property_blobs,
965 property, val);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400966 if (!ret) {
967 idx = msm_property_index(&sde_crtc->property_info,
968 property);
969 if (idx == CRTC_PROP_INPUT_FENCE_TIMEOUT)
970 _sde_crtc_set_input_fence_timeout(cstate);
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -0700971 } else {
972 ret = sde_cp_crtc_set_property(crtc,
973 property, val);
Clarence Ipcae1bb62016-07-07 12:07:13 -0400974 }
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -0700975 if (ret)
976 DRM_ERROR("failed to set the property\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -0400977 }
978
979 return ret;
980}
981
982/**
983 * sde_crtc_set_property - set a crtc drm property
984 * @crtc: Pointer to drm crtc structure
985 * @property: Pointer to targeted drm property
986 * @val: Updated property value
987 * @Returns: Zero on success
988 */
989static int sde_crtc_set_property(struct drm_crtc *crtc,
990 struct drm_property *property, uint64_t val)
991{
992 DBG("");
993
994 return sde_crtc_atomic_set_property(crtc, crtc->state, property, val);
995}
996
997/**
998 * sde_crtc_atomic_get_property - retrieve a crtc drm property
999 * @crtc: Pointer to drm crtc structure
1000 * @state: Pointer to drm crtc state structure
1001 * @property: Pointer to targeted drm property
1002 * @val: Pointer to variable for receiving property value
1003 * @Returns: Zero on success
1004 */
1005static int sde_crtc_atomic_get_property(struct drm_crtc *crtc,
1006 const struct drm_crtc_state *state,
1007 struct drm_property *property,
1008 uint64_t *val)
1009{
1010 struct sde_crtc *sde_crtc;
1011 struct sde_crtc_state *cstate;
Clarence Ip24f80662016-06-13 19:05:32 -04001012 int i, ret = -EINVAL;
Clarence Ip7a753bb2016-07-07 11:47:44 -04001013
1014 if (!crtc || !state) {
Dhaval Patelec10fad2016-08-22 14:40:48 -07001015 SDE_ERROR("invalid argument(s)\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -04001016 } else {
1017 sde_crtc = to_sde_crtc(crtc);
1018 cstate = to_sde_crtc_state(state);
Clarence Ip24f80662016-06-13 19:05:32 -04001019 i = msm_property_index(&sde_crtc->property_info, property);
1020 if (i == CRTC_PROP_OUTPUT_FENCE) {
Clarence Ip1d9728b2016-09-01 11:10:54 -04001021 int offset = sde_crtc_get_property(cstate,
1022 CRTC_PROP_OUTPUT_FENCE_OFFSET);
1023
1024 ret = sde_fence_create(
1025 &sde_crtc->output_fence, val, offset);
1026 if (ret)
1027 SDE_ERROR("fence create failed\n");
Clarence Ip24f80662016-06-13 19:05:32 -04001028 } else {
1029 ret = msm_property_atomic_get(&sde_crtc->property_info,
1030 cstate->property_values,
1031 cstate->property_blobs, property, val);
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -07001032 if (ret)
1033 ret = sde_cp_crtc_get_property(crtc,
1034 property, val);
Clarence Ip24f80662016-06-13 19:05:32 -04001035 }
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -07001036 if (ret)
1037 DRM_ERROR("get property failed\n");
Clarence Ip7a753bb2016-07-07 11:47:44 -04001038 }
Clarence Ip7a753bb2016-07-07 11:47:44 -04001039 return ret;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001040}
1041
Clarence Ip8f7366c2016-07-05 12:15:26 -04001042static int _sde_debugfs_mixer_read(struct seq_file *s, void *data)
1043{
1044 struct sde_crtc *sde_crtc;
1045 struct sde_crtc_mixer *m;
Dhaval Patel48c76022016-09-01 17:51:23 -07001046 int i, j, k;
Clarence Ip8f7366c2016-07-05 12:15:26 -04001047
1048 if (!s || !s->private)
1049 return -EINVAL;
1050
1051 sde_crtc = s->private;
1052 for (i = 0; i < sde_crtc->num_mixers; ++i) {
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -04001053 m = &sde_crtc->mixers[i];
Clarence Ip8f7366c2016-07-05 12:15:26 -04001054 if (!m->hw_lm) {
1055 seq_printf(s, "Mixer[%d] has no LM\n", i);
1056 } else if (!m->hw_ctl) {
1057 seq_printf(s, "Mixer[%d] has no CTL\n", i);
1058 } else {
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -04001059 seq_printf(s, "LM_%d/CTL_%d\n",
Clarence Ip8f7366c2016-07-05 12:15:26 -04001060 m->hw_lm->idx - LM_0,
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -04001061 m->hw_ctl->idx - CTL_0);
Clarence Ip8f7366c2016-07-05 12:15:26 -04001062 }
1063 }
Dhaval Patel44f12472016-08-29 12:19:47 -07001064
Dhaval Patel48c76022016-09-01 17:51:23 -07001065 for (k = 0; k < sde_crtc->num_mixers; ++k) {
1066 seq_printf(s, "Mixer[%d] stages\n", k);
1067 for (i = 0; i < SDE_STAGE_MAX; ++i) {
1068 if (i == SDE_STAGE_BASE)
1069 seq_puts(s, "Base Stage:");
1070 else
1071 seq_printf(s, "Stage %d:", i - SDE_STAGE_0);
1072
1073 for (j = 0; j < PIPES_PER_STAGE; ++j)
1074 seq_printf(s, " % 2d",
1075 sde_crtc->stage_cfg.stage[k][i][j]);
1076 seq_puts(s, "\n");
1077 }
Clarence Ip8f7366c2016-07-05 12:15:26 -04001078 }
1079 return 0;
1080}
1081
1082static int _sde_debugfs_mixer_open(struct inode *inode, struct file *file)
1083{
1084 return single_open(file, _sde_debugfs_mixer_read, inode->i_private);
1085}
1086
Gopikrishnaiah Anandan7f6ef942016-06-20 15:50:00 -07001087static void sde_crtc_suspend(struct drm_crtc *crtc)
1088{
1089 sde_cp_crtc_suspend(crtc);
1090}
1091
1092static void sde_crtc_resume(struct drm_crtc *crtc)
1093{
1094 sde_cp_crtc_resume(crtc);
1095}
1096
Clarence Ip7a753bb2016-07-07 11:47:44 -04001097static const struct drm_crtc_funcs sde_crtc_funcs = {
1098 .set_config = drm_atomic_helper_set_config,
1099 .destroy = sde_crtc_destroy,
1100 .page_flip = drm_atomic_helper_page_flip,
1101 .set_property = sde_crtc_set_property,
1102 .atomic_set_property = sde_crtc_atomic_set_property,
1103 .atomic_get_property = sde_crtc_atomic_get_property,
1104 .reset = sde_crtc_reset,
1105 .atomic_duplicate_state = sde_crtc_duplicate_state,
1106 .atomic_destroy_state = sde_crtc_destroy_state,
Gopikrishnaiah Anandan7f6ef942016-06-20 15:50:00 -07001107 .save = sde_crtc_suspend,
1108 .restore = sde_crtc_resume,
Clarence Ip7a753bb2016-07-07 11:47:44 -04001109};
1110
1111static const struct drm_crtc_helper_funcs sde_crtc_helper_funcs = {
1112 .mode_fixup = sde_crtc_mode_fixup,
1113 .mode_set_nofb = sde_crtc_mode_set_nofb,
1114 .disable = sde_crtc_disable,
1115 .enable = sde_crtc_enable,
1116 .atomic_check = sde_crtc_atomic_check,
1117 .atomic_begin = sde_crtc_atomic_begin,
1118 .atomic_flush = sde_crtc_atomic_flush,
1119};
1120
Clarence Ip8f7366c2016-07-05 12:15:26 -04001121static void _sde_crtc_init_debugfs(struct sde_crtc *sde_crtc,
1122 struct sde_kms *sde_kms)
1123{
1124 static const struct file_operations debugfs_mixer_fops = {
1125 .open = _sde_debugfs_mixer_open,
1126 .read = seq_read,
1127 .llseek = seq_lseek,
1128 .release = single_release,
1129 };
1130 if (sde_crtc && sde_kms) {
1131 sde_crtc->debugfs_root = debugfs_create_dir(sde_crtc->name,
1132 sde_debugfs_get_root(sde_kms));
1133 if (sde_crtc->debugfs_root) {
1134 /* don't error check these */
Clarence Ip8f7366c2016-07-05 12:15:26 -04001135 debugfs_create_file("mixers", 0444,
1136 sde_crtc->debugfs_root,
1137 sde_crtc, &debugfs_mixer_fops);
1138 }
1139 }
1140}
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001141
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001142/* initialize crtc */
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001143struct drm_crtc *sde_crtc_init(struct drm_device *dev,
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -04001144 struct drm_plane *plane,
1145 int drm_crtc_id)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001146{
1147 struct drm_crtc *crtc = NULL;
Clarence Ip8f7366c2016-07-05 12:15:26 -04001148 struct sde_crtc *sde_crtc = NULL;
1149 struct msm_drm_private *priv = NULL;
1150 struct sde_kms *kms = NULL;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001151
Clarence Ip8f7366c2016-07-05 12:15:26 -04001152 priv = dev->dev_private;
1153 kms = to_sde_kms(priv->kms);
1154
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001155 sde_crtc = kzalloc(sizeof(*sde_crtc), GFP_KERNEL);
1156 if (!sde_crtc)
1157 return ERR_PTR(-ENOMEM);
1158
1159 crtc = &sde_crtc->base;
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -07001160 crtc->dev = dev;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001161
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -04001162 sde_crtc->drm_crtc_id = drm_crtc_id;
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -04001163
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001164 drm_crtc_init_with_planes(dev, crtc, plane, NULL, &sde_crtc_funcs);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001165
1166 drm_crtc_helper_add(crtc, &sde_crtc_helper_funcs);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001167 plane->crtc = crtc;
1168
Clarence Ip8f7366c2016-07-05 12:15:26 -04001169 /* save user friendly CRTC name for later */
1170 snprintf(sde_crtc->name, SDE_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
1171
Clarence Ip9a74a442016-08-25 18:29:03 -04001172 /* initialize output fence support */
1173 sde_fence_init(dev, &sde_crtc->output_fence, sde_crtc->name);
Clarence Ip24f80662016-06-13 19:05:32 -04001174
1175 /* initialize debugfs support */
Clarence Ip8f7366c2016-07-05 12:15:26 -04001176 _sde_crtc_init_debugfs(sde_crtc, kms);
1177
Clarence Ip7a753bb2016-07-07 11:47:44 -04001178 /* create CRTC properties */
1179 msm_property_init(&sde_crtc->property_info, &crtc->base, dev,
1180 priv->crtc_property, sde_crtc->property_data,
1181 CRTC_PROP_COUNT, CRTC_PROP_BLOBCOUNT,
1182 sizeof(struct sde_crtc_state));
1183
1184 sde_crtc_install_properties(crtc);
Gopikrishnaiah Anandane0e5e0c2016-05-25 11:05:33 -07001185 sde_cp_crtc_init(crtc);
Clarence Ip7a753bb2016-07-07 11:47:44 -04001186
Dhaval Patelec10fad2016-08-22 14:40:48 -07001187 SDE_DEBUG("%s: successfully initialized crtc\n", sde_crtc->name);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001188 return crtc;
1189}