blob: 39b8863ef60971a62f28542a6d9315ffdec3c06a [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 */
18
Alan Kwong5d324e42016-07-28 22:56:18 -040019#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
20
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070021#include <drm/drm_crtc.h>
Clarence Ip4ce59322016-06-26 22:27:51 -040022#include <linux/debugfs.h>
Dhaval Patel04c7e8e2016-09-26 20:14:31 -070023#include <linux/of_irq.h>
Clarence Ip4ce59322016-06-26 22:27:51 -040024
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070025#include "msm_drv.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040026#include "msm_mmu.h"
Clarence Ip3649f8b2016-10-31 09:59:44 -040027
28#include "dsi_display.h"
29#include "dsi_drm.h"
30#include "sde_wb.h"
31
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070032#include "sde_kms.h"
Alan Kwongf5dd86c2016-08-09 18:08:17 -040033#include "sde_core_irq.h"
Clarence Ip4ce59322016-06-26 22:27:51 -040034#include "sde_formats.h"
Alan Kwong5d324e42016-07-28 22:56:18 -040035#include "sde_hw_vbif.h"
Alan Kwong83285fb2016-10-21 20:51:17 -040036#include "sde_vbif.h"
37#include "sde_encoder.h"
38#include "sde_plane.h"
39#include "sde_crtc.h"
Gopikrishnaiah Anandan7e3e3f52016-12-22 11:13:05 -080040#include "sde_reg_dma.h"
Narendra Muppalla1b0b3352015-09-29 10:16:51 -070041
Alan Kwong1a00e4d2016-07-18 09:42:30 -040042#define CREATE_TRACE_POINTS
43#include "sde_trace.h"
44
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040045static const char * const iommu_ports[] = {
46 "mdp_0",
47};
48
Clarence Ip4ce59322016-06-26 22:27:51 -040049/**
50 * Controls size of event log buffer. Specified as a power of 2.
51 */
52#define SDE_EVTLOG_SIZE 1024
53
54/*
55 * To enable overall DRM driver logging
56 * # echo 0x2 > /sys/module/drm/parameters/debug
57 *
58 * To enable DRM driver h/w logging
59 * # echo <mask> > /sys/kernel/debug/dri/0/hw_log_mask
60 *
61 * See sde_hw_mdss.h for h/w logging mask definitions (search for SDE_DBG_MASK_)
62 */
63#define SDE_DEBUGFS_DIR "msm_sde"
64#define SDE_DEBUGFS_HWMASKNAME "hw_log_mask"
65
Clarence Ipdd395242016-09-09 10:47:17 -040066/**
67 * sdecustom - enable certain driver customizations for sde clients
68 * Enabling this modifies the standard DRM behavior slightly and assumes
69 * that the clients have specific knowledge about the modifications that
70 * are involved, so don't enable this unless you know what you're doing.
71 *
72 * Parts of the driver that are affected by this setting may be located by
73 * searching for invocations of the 'sde_is_custom_client()' function.
74 *
75 * This is disabled by default.
76 */
Clarence Ipb1b3c802016-10-03 16:49:38 -040077static bool sdecustom = true;
Clarence Ipdd395242016-09-09 10:47:17 -040078module_param(sdecustom, bool, 0400);
79MODULE_PARM_DESC(sdecustom, "Enable customizations for sde clients");
80
Clarence Ip17162b52016-11-24 17:06:29 -050081static int sde_kms_hw_init(struct msm_kms *kms);
82static int _sde_kms_mmu_destroy(struct sde_kms *sde_kms);
83
Clarence Ipdd395242016-09-09 10:47:17 -040084bool sde_is_custom_client(void)
85{
86 return sdecustom;
87}
88
Alan Kwongf0fd8512016-10-24 21:39:26 -040089#ifdef CONFIG_DEBUG_FS
90static int _sde_danger_signal_status(struct seq_file *s,
91 bool danger_status)
92{
93 struct sde_kms *kms = (struct sde_kms *)s->private;
94 struct msm_drm_private *priv;
95 struct sde_danger_safe_status status;
96 int i;
97
98 if (!kms || !kms->dev || !kms->dev->dev_private || !kms->hw_mdp) {
99 SDE_ERROR("invalid arg(s)\n");
100 return 0;
101 }
102
103 priv = kms->dev->dev_private;
104 memset(&status, 0, sizeof(struct sde_danger_safe_status));
105
106 sde_power_resource_enable(&priv->phandle, kms->core_client, true);
107 if (danger_status) {
108 seq_puts(s, "\nDanger signal status:\n");
109 if (kms->hw_mdp->ops.get_danger_status)
110 kms->hw_mdp->ops.get_danger_status(kms->hw_mdp,
111 &status);
112 } else {
113 seq_puts(s, "\nSafe signal status:\n");
114 if (kms->hw_mdp->ops.get_danger_status)
115 kms->hw_mdp->ops.get_danger_status(kms->hw_mdp,
116 &status);
117 }
118 sde_power_resource_enable(&priv->phandle, kms->core_client, false);
119
120 seq_printf(s, "MDP : 0x%x\n", status.mdp);
121
122 for (i = SSPP_VIG0; i < SSPP_MAX; i++)
123 seq_printf(s, "SSPP%d : 0x%x \t", i - SSPP_VIG0,
124 status.sspp[i]);
125 seq_puts(s, "\n");
126
127 for (i = WB_0; i < WB_MAX; i++)
128 seq_printf(s, "WB%d : 0x%x \t", i - WB_0,
129 status.wb[i]);
130 seq_puts(s, "\n");
131
132 return 0;
133}
134
135#define DEFINE_SDE_DEBUGFS_SEQ_FOPS(__prefix) \
136static int __prefix ## _open(struct inode *inode, struct file *file) \
137{ \
138 return single_open(file, __prefix ## _show, inode->i_private); \
139} \
140static const struct file_operations __prefix ## _fops = { \
141 .owner = THIS_MODULE, \
142 .open = __prefix ## _open, \
143 .release = single_release, \
144 .read = seq_read, \
145 .llseek = seq_lseek, \
146}
147
148static int sde_debugfs_danger_stats_show(struct seq_file *s, void *v)
149{
150 return _sde_danger_signal_status(s, true);
151}
152DEFINE_SDE_DEBUGFS_SEQ_FOPS(sde_debugfs_danger_stats);
153
154static int sde_debugfs_safe_stats_show(struct seq_file *s, void *v)
155{
156 return _sde_danger_signal_status(s, false);
157}
158DEFINE_SDE_DEBUGFS_SEQ_FOPS(sde_debugfs_safe_stats);
159
160static void sde_debugfs_danger_destroy(struct sde_kms *sde_kms)
161{
162 debugfs_remove_recursive(sde_kms->debugfs_danger);
163 sde_kms->debugfs_danger = NULL;
164}
165
166static int sde_debugfs_danger_init(struct sde_kms *sde_kms,
167 struct dentry *parent)
168{
169 sde_kms->debugfs_danger = debugfs_create_dir("danger",
170 parent);
171 if (!sde_kms->debugfs_danger) {
172 SDE_ERROR("failed to create danger debugfs\n");
173 return -EINVAL;
174 }
175
176 debugfs_create_file("danger_status", 0644, sde_kms->debugfs_danger,
177 sde_kms, &sde_debugfs_danger_stats_fops);
178 debugfs_create_file("safe_status", 0644, sde_kms->debugfs_danger,
179 sde_kms, &sde_debugfs_safe_stats_fops);
180
181 return 0;
182}
183
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400184static int _sde_debugfs_show_regset32(struct seq_file *s, void *data)
Clarence Ip4ce59322016-06-26 22:27:51 -0400185{
Clarence Ipaac9f332016-08-31 15:46:35 -0400186 struct sde_debugfs_regset32 *regset;
187 struct sde_kms *sde_kms;
188 struct drm_device *dev;
189 struct msm_drm_private *priv;
Clarence Ip4ce59322016-06-26 22:27:51 -0400190 void __iomem *base;
Clarence Ipaac9f332016-08-31 15:46:35 -0400191 uint32_t i, addr;
Clarence Ip4ce59322016-06-26 22:27:51 -0400192
Clarence Ipaac9f332016-08-31 15:46:35 -0400193 if (!s || !s->private)
194 return 0;
Clarence Ip4ce59322016-06-26 22:27:51 -0400195
Clarence Ipaac9f332016-08-31 15:46:35 -0400196 regset = s->private;
197
198 sde_kms = regset->sde_kms;
199 if (!sde_kms || !sde_kms->mmio)
200 return 0;
201
202 dev = sde_kms->dev;
203 if (!dev)
204 return 0;
205
206 priv = dev->dev_private;
207 if (!priv)
208 return 0;
209
210 base = sde_kms->mmio + regset->offset;
211
212 /* insert padding spaces, if needed */
213 if (regset->offset & 0xF) {
214 seq_printf(s, "[%x]", regset->offset & ~0xF);
215 for (i = 0; i < (regset->offset & 0xF); i += 4)
216 seq_puts(s, " ");
217 }
218
219 if (sde_power_resource_enable(&priv->phandle,
220 sde_kms->core_client, true)) {
221 seq_puts(s, "failed to enable sde clocks\n");
222 return 0;
223 }
224
225 /* main register output */
226 for (i = 0; i < regset->blk_len; i += 4) {
227 addr = regset->offset + i;
228 if ((addr & 0xF) == 0x0)
229 seq_printf(s, i ? "\n[%x]" : "[%x]", addr);
230 seq_printf(s, " %08x", readl_relaxed(base + i));
231 }
232 seq_puts(s, "\n");
233 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
Clarence Ip4ce59322016-06-26 22:27:51 -0400234
235 return 0;
236}
237
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400238static int sde_debugfs_open_regset32(struct inode *inode,
239 struct file *file)
Clarence Ip4ce59322016-06-26 22:27:51 -0400240{
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400241 return single_open(file, _sde_debugfs_show_regset32, inode->i_private);
Clarence Ip4ce59322016-06-26 22:27:51 -0400242}
243
244static const struct file_operations sde_fops_regset32 = {
245 .open = sde_debugfs_open_regset32,
246 .read = seq_read,
247 .llseek = seq_lseek,
248 .release = single_release,
249};
250
251void sde_debugfs_setup_regset32(struct sde_debugfs_regset32 *regset,
Clarence Ipaac9f332016-08-31 15:46:35 -0400252 uint32_t offset, uint32_t length, struct sde_kms *sde_kms)
Clarence Ip4ce59322016-06-26 22:27:51 -0400253{
254 if (regset) {
255 regset->offset = offset;
256 regset->blk_len = length;
Clarence Ipaac9f332016-08-31 15:46:35 -0400257 regset->sde_kms = sde_kms;
Clarence Ip4ce59322016-06-26 22:27:51 -0400258 }
259}
260
261void *sde_debugfs_create_regset32(const char *name, umode_t mode,
262 void *parent, struct sde_debugfs_regset32 *regset)
263{
Clarence Ipaac9f332016-08-31 15:46:35 -0400264 if (!name || !regset || !regset->sde_kms || !regset->blk_len)
Clarence Ip4ce59322016-06-26 22:27:51 -0400265 return NULL;
266
267 /* make sure offset is a multiple of 4 */
268 regset->offset = round_down(regset->offset, 4);
269
270 return debugfs_create_file(name, mode, parent,
271 regset, &sde_fops_regset32);
272}
273
274void *sde_debugfs_get_root(struct sde_kms *sde_kms)
275{
276 return sde_kms ? sde_kms->debugfs_root : 0;
277}
278
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400279static int _sde_debugfs_init(struct sde_kms *sde_kms)
Clarence Ip4ce59322016-06-26 22:27:51 -0400280{
281 void *p;
282
283 p = sde_hw_util_get_log_mask_ptr();
284
285 if (!sde_kms || !p)
286 return -EINVAL;
287
288 if (sde_kms->dev && sde_kms->dev->primary)
289 sde_kms->debugfs_root = sde_kms->dev->primary->debugfs_root;
290 else
291 sde_kms->debugfs_root = debugfs_create_dir(SDE_DEBUGFS_DIR, 0);
292
293 /* allow debugfs_root to be NULL */
294 debugfs_create_x32(SDE_DEBUGFS_HWMASKNAME,
295 0644, sde_kms->debugfs_root, p);
Alan Kwongcd1c09f2016-11-04 20:37:30 -0400296
297 /* create common folder for debug information */
298 sde_kms->debugfs_debug = debugfs_create_dir("debug",
299 sde_kms->debugfs_root);
300 if (!sde_kms->debugfs_debug)
301 SDE_ERROR("failed to create debugfs debug directory\n");
302
Alan Kwongf0fd8512016-10-24 21:39:26 -0400303 sde_debugfs_danger_init(sde_kms, sde_kms->debugfs_debug);
Alan Kwong748e833d2016-10-26 12:34:48 -0400304 sde_debugfs_vbif_init(sde_kms, sde_kms->debugfs_debug);
Alan Kwongf0fd8512016-10-24 21:39:26 -0400305
Clarence Ip4ce59322016-06-26 22:27:51 -0400306 return 0;
307}
308
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400309static void _sde_debugfs_destroy(struct sde_kms *sde_kms)
Clarence Ip4ce59322016-06-26 22:27:51 -0400310{
311 /* don't need to NULL check debugfs_root */
312 if (sde_kms) {
Alan Kwong748e833d2016-10-26 12:34:48 -0400313 sde_debugfs_vbif_destroy(sde_kms);
Alan Kwongf0fd8512016-10-24 21:39:26 -0400314 sde_debugfs_danger_destroy(sde_kms);
Alan Kwongcd1c09f2016-11-04 20:37:30 -0400315 debugfs_remove_recursive(sde_kms->debugfs_debug);
316 sde_kms->debugfs_debug = 0;
Clarence Ip4ce59322016-06-26 22:27:51 -0400317 debugfs_remove_recursive(sde_kms->debugfs_root);
318 sde_kms->debugfs_root = 0;
319 }
320}
Alan Kwongf0fd8512016-10-24 21:39:26 -0400321#else
322static void sde_debugfs_danger_destroy(struct sde_kms *sde_kms,
323 struct dentry *parent)
324{
325}
326
327static int sde_debugfs_danger_init(struct sde_kms *sde_kms,
328 struct dentry *parent)
329{
330 return 0;
331}
332#endif
Clarence Ip4ce59322016-06-26 22:27:51 -0400333
Alan Kwongf5dd86c2016-08-09 18:08:17 -0400334static int sde_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
335{
Lloyd Atkinson5217336c2016-09-15 18:21:18 -0400336 struct sde_kms *sde_kms = to_sde_kms(kms);
337 struct drm_device *dev = sde_kms->dev;
338 struct msm_drm_private *priv = dev->dev_private;
339
340 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
341
Alan Kwongf5dd86c2016-08-09 18:08:17 -0400342 return sde_crtc_vblank(crtc, true);
343}
344
345static void sde_kms_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
346{
Lloyd Atkinson5217336c2016-09-15 18:21:18 -0400347 struct sde_kms *sde_kms = to_sde_kms(kms);
348 struct drm_device *dev = sde_kms->dev;
349 struct msm_drm_private *priv = dev->dev_private;
350
Alan Kwongf5dd86c2016-08-09 18:08:17 -0400351 sde_crtc_vblank(crtc, false);
Lloyd Atkinson5217336c2016-09-15 18:21:18 -0400352
353 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
Alan Kwongf5dd86c2016-08-09 18:08:17 -0400354}
355
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400356static void sde_kms_prepare_commit(struct msm_kms *kms,
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400357 struct drm_atomic_state *state)
358{
Ben Chan78647cd2016-06-26 22:02:47 -0400359 struct sde_kms *sde_kms = to_sde_kms(kms);
Dhaval Patel3949f032016-06-20 16:24:33 -0700360 struct drm_device *dev = sde_kms->dev;
361 struct msm_drm_private *priv = dev->dev_private;
Clarence Ipa36c92e2016-07-26 14:33:46 -0400362
Dhaval Patel3949f032016-06-20 16:24:33 -0700363 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400364}
365
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400366static void sde_kms_commit(struct msm_kms *kms,
367 struct drm_atomic_state *old_state)
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400368{
369 struct drm_crtc *crtc;
370 struct drm_crtc_state *old_crtc_state;
371 int i;
372
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400373 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
374 if (crtc->state->active) {
375 SDE_EVT32(DRMID(crtc));
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400376 sde_crtc_commit_kickoff(crtc);
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400377 }
378 }
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400379}
380
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400381static void sde_kms_complete_commit(struct msm_kms *kms,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400382 struct drm_atomic_state *old_state)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400383{
Ben Chan78647cd2016-06-26 22:02:47 -0400384 struct sde_kms *sde_kms = to_sde_kms(kms);
Dhaval Patel3949f032016-06-20 16:24:33 -0700385 struct drm_device *dev = sde_kms->dev;
386 struct msm_drm_private *priv = dev->dev_private;
Clarence Ip24f80662016-06-13 19:05:32 -0400387 struct drm_crtc *crtc;
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400388 struct drm_crtc_state *old_crtc_state;
Clarence Ip24f80662016-06-13 19:05:32 -0400389 int i;
Lloyd Atkinsona59eead2016-05-30 14:37:06 -0400390
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400391 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i)
392 sde_crtc_complete_commit(crtc, old_crtc_state);
Dhaval Patel3949f032016-06-20 16:24:33 -0700393 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
Lloyd Atkinsona59eead2016-05-30 14:37:06 -0400394
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400395 SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400396}
397
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400398static void sde_kms_wait_for_commit_done(struct msm_kms *kms,
Abhijit Kulkarni40e38162016-06-26 22:12:09 -0400399 struct drm_crtc *crtc)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400400{
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400401 struct drm_encoder *encoder;
402 struct drm_device *dev = crtc->dev;
403 int ret;
404
Alan Kwongf34ef982016-09-29 20:53:53 -0400405 if (!kms || !crtc || !crtc->state) {
406 SDE_ERROR("invalid params\n");
407 return;
408 }
409
410 if (!crtc->state->enable) {
411 SDE_DEBUG("[crtc:%d] not enable\n", crtc->base.id);
412 return;
413 }
414
415 if (!crtc->state->active) {
416 SDE_DEBUG("[crtc:%d] not active\n", crtc->base.id);
417 return;
418 }
419
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400420 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
421 if (encoder->crtc != crtc)
422 continue;
423 /*
424 * Wait post-flush if necessary to delay before plane_cleanup
425 * For example, wait for vsync in case of video mode panels
426 * This should be a no-op for command mode panels
427 */
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400428 SDE_EVT32(DRMID(crtc));
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400429 ret = sde_encoder_wait_for_commit_done(encoder);
430 if (ret && ret != -EWOULDBLOCK) {
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -0400431 SDE_ERROR("wait for commit done returned %d\n", ret);
Lloyd Atkinsone7bcdd22016-08-11 10:53:37 -0400432 break;
433 }
434 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400435}
Lloyd Atkinson5d722782016-05-30 14:09:41 -0400436
Clarence Ip24f80662016-06-13 19:05:32 -0400437static void sde_kms_prepare_fence(struct msm_kms *kms,
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400438 struct drm_atomic_state *old_state)
Clarence Ip24f80662016-06-13 19:05:32 -0400439{
440 struct drm_crtc *crtc;
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400441 struct drm_crtc_state *old_crtc_state;
442 int i, rc;
Clarence Ip24f80662016-06-13 19:05:32 -0400443
Clarence Ip0d0e96d2016-10-24 18:13:13 -0400444 if (!kms || !old_state || !old_state->dev || !old_state->acquire_ctx) {
445 SDE_ERROR("invalid argument(s)\n");
446 return;
447 }
448
449retry:
450 /* attempt to acquire ww mutex for connection */
451 rc = drm_modeset_lock(&old_state->dev->mode_config.connection_mutex,
452 old_state->acquire_ctx);
453
454 if (rc == -EDEADLK) {
455 drm_modeset_backoff(old_state->acquire_ctx);
456 goto retry;
457 }
458
459 /* old_state actually contains updated crtc pointers */
460 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i)
461 sde_crtc_prepare_commit(crtc, old_crtc_state);
Clarence Ip24f80662016-06-13 19:05:32 -0400462}
463
Clarence Ip3649f8b2016-10-31 09:59:44 -0400464/**
465 * _sde_kms_get_displays - query for underlying display handles and cache them
466 * @sde_kms: Pointer to sde kms structure
467 * Returns: Zero on success
468 */
469static int _sde_kms_get_displays(struct sde_kms *sde_kms)
470{
471 int rc = -ENOMEM;
472
473 if (!sde_kms) {
474 SDE_ERROR("invalid sde kms\n");
475 return -EINVAL;
476 }
477
478 /* dsi */
479 sde_kms->dsi_displays = NULL;
480 sde_kms->dsi_display_count = dsi_display_get_num_of_displays();
481 if (sde_kms->dsi_display_count) {
482 sde_kms->dsi_displays = kcalloc(sde_kms->dsi_display_count,
483 sizeof(void *),
484 GFP_KERNEL);
485 if (!sde_kms->dsi_displays) {
486 SDE_ERROR("failed to allocate dsi displays\n");
487 goto exit_deinit_dsi;
488 }
489 sde_kms->dsi_display_count =
490 dsi_display_get_active_displays(sde_kms->dsi_displays,
491 sde_kms->dsi_display_count);
492 }
493
494 /* wb */
495 sde_kms->wb_displays = NULL;
496 sde_kms->wb_display_count = sde_wb_get_num_of_displays();
497 if (sde_kms->wb_display_count) {
498 sde_kms->wb_displays = kcalloc(sde_kms->wb_display_count,
499 sizeof(void *),
500 GFP_KERNEL);
501 if (!sde_kms->wb_displays) {
502 SDE_ERROR("failed to allocate wb displays\n");
503 goto exit_deinit_wb;
504 }
505 sde_kms->wb_display_count =
506 wb_display_get_displays(sde_kms->wb_displays,
507 sde_kms->wb_display_count);
508 }
509 return 0;
510
511exit_deinit_wb:
512 kfree(sde_kms->wb_displays);
513 sde_kms->wb_display_count = 0;
514 sde_kms->wb_displays = NULL;
515
516exit_deinit_dsi:
517 kfree(sde_kms->dsi_displays);
518 sde_kms->dsi_display_count = 0;
519 sde_kms->dsi_displays = NULL;
520 return rc;
521}
522
523/**
524 * _sde_kms_release_displays - release cache of underlying display handles
525 * @sde_kms: Pointer to sde kms structure
526 */
527static void _sde_kms_release_displays(struct sde_kms *sde_kms)
528{
529 if (!sde_kms) {
530 SDE_ERROR("invalid sde kms\n");
531 return;
532 }
533
534 kfree(sde_kms->wb_displays);
535 sde_kms->wb_displays = NULL;
536 sde_kms->wb_display_count = 0;
537
538 kfree(sde_kms->dsi_displays);
539 sde_kms->dsi_displays = NULL;
540 sde_kms->dsi_display_count = 0;
541}
542
543/**
544 * _sde_kms_setup_displays - create encoders, bridges and connectors
545 * for underlying displays
546 * @dev: Pointer to drm device structure
547 * @priv: Pointer to private drm device data
548 * @sde_kms: Pointer to sde kms structure
549 * Returns: Zero on success
550 */
551static int _sde_kms_setup_displays(struct drm_device *dev,
552 struct msm_drm_private *priv,
553 struct sde_kms *sde_kms)
554{
555 static const struct sde_connector_ops dsi_ops = {
556 .post_init = dsi_conn_post_init,
557 .detect = dsi_conn_detect,
558 .get_modes = dsi_connector_get_modes,
559 .mode_valid = dsi_conn_mode_valid,
560 .get_info = dsi_display_get_info,
Lloyd Atkinson8c49c582016-11-18 14:23:54 -0500561 .set_backlight = dsi_display_set_backlight,
562 .soft_reset = dsi_display_soft_reset
Clarence Ip3649f8b2016-10-31 09:59:44 -0400563 };
564 static const struct sde_connector_ops wb_ops = {
565 .post_init = sde_wb_connector_post_init,
566 .detect = sde_wb_connector_detect,
567 .get_modes = sde_wb_connector_get_modes,
568 .set_property = sde_wb_connector_set_property,
569 .get_info = sde_wb_get_info,
Lloyd Atkinson8c49c582016-11-18 14:23:54 -0500570 .soft_reset = NULL
Clarence Ip3649f8b2016-10-31 09:59:44 -0400571 };
572 struct msm_display_info info;
573 struct drm_encoder *encoder;
574 void *display, *connector;
575 int i, max_encoders;
576 int rc = 0;
577
578 if (!dev || !priv || !sde_kms) {
579 SDE_ERROR("invalid argument(s)\n");
580 return -EINVAL;
581 }
582
583 max_encoders = sde_kms->dsi_display_count + sde_kms->wb_display_count;
584 if (max_encoders > ARRAY_SIZE(priv->encoders)) {
585 max_encoders = ARRAY_SIZE(priv->encoders);
586 SDE_ERROR("capping number of displays to %d", max_encoders);
587 }
588
589 /* dsi */
590 for (i = 0; i < sde_kms->dsi_display_count &&
591 priv->num_encoders < max_encoders; ++i) {
592 display = sde_kms->dsi_displays[i];
593 encoder = NULL;
594
595 memset(&info, 0x0, sizeof(info));
596 rc = dsi_display_get_info(&info, display);
597 if (rc) {
598 SDE_ERROR("dsi get_info %d failed\n", i);
599 continue;
600 }
601
602 encoder = sde_encoder_init(dev, &info);
603 if (IS_ERR_OR_NULL(encoder)) {
604 SDE_ERROR("encoder init failed for dsi %d\n", i);
605 continue;
606 }
607
608 rc = dsi_display_drm_bridge_init(display, encoder);
609 if (rc) {
610 SDE_ERROR("dsi bridge %d init failed, %d\n", i, rc);
611 sde_encoder_destroy(encoder);
612 continue;
613 }
614
615 connector = sde_connector_init(dev,
616 encoder,
617 0,
618 display,
619 &dsi_ops,
620 DRM_CONNECTOR_POLL_HPD,
621 DRM_MODE_CONNECTOR_DSI);
622 if (connector) {
623 priv->encoders[priv->num_encoders++] = encoder;
624 } else {
625 SDE_ERROR("dsi %d connector init failed\n", i);
626 dsi_display_drm_bridge_deinit(display);
627 sde_encoder_destroy(encoder);
628 }
629 }
630
631 /* wb */
632 for (i = 0; i < sde_kms->wb_display_count &&
633 priv->num_encoders < max_encoders; ++i) {
634 display = sde_kms->wb_displays[i];
635 encoder = NULL;
636
637 memset(&info, 0x0, sizeof(info));
638 rc = sde_wb_get_info(&info, display);
639 if (rc) {
640 SDE_ERROR("wb get_info %d failed\n", i);
641 continue;
642 }
643
644 encoder = sde_encoder_init(dev, &info);
645 if (IS_ERR_OR_NULL(encoder)) {
646 SDE_ERROR("encoder init failed for wb %d\n", i);
647 continue;
648 }
649
650 rc = sde_wb_drm_init(display, encoder);
651 if (rc) {
652 SDE_ERROR("wb bridge %d init failed, %d\n", i, rc);
653 sde_encoder_destroy(encoder);
654 continue;
655 }
656
657 connector = sde_connector_init(dev,
658 encoder,
659 0,
660 display,
661 &wb_ops,
662 DRM_CONNECTOR_POLL_HPD,
663 DRM_MODE_CONNECTOR_VIRTUAL);
664 if (connector) {
665 priv->encoders[priv->num_encoders++] = encoder;
666 } else {
667 SDE_ERROR("wb %d connector init failed\n", i);
668 sde_wb_drm_deinit(display);
669 sde_encoder_destroy(encoder);
670 }
671 }
672
673 return 0;
674}
675
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400676static void _sde_kms_drm_obj_destroy(struct sde_kms *sde_kms)
677{
678 struct msm_drm_private *priv;
679 int i;
680
681 if (!sde_kms) {
682 SDE_ERROR("invalid sde_kms\n");
683 return;
684 } else if (!sde_kms->dev) {
685 SDE_ERROR("invalid dev\n");
686 return;
687 } else if (!sde_kms->dev->dev_private) {
688 SDE_ERROR("invalid dev_private\n");
689 return;
690 }
691 priv = sde_kms->dev->dev_private;
692
693 for (i = 0; i < priv->num_crtcs; i++)
694 priv->crtcs[i]->funcs->destroy(priv->crtcs[i]);
Clarence Ip17162b52016-11-24 17:06:29 -0500695 priv->num_crtcs = 0;
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400696
697 for (i = 0; i < priv->num_planes; i++)
698 priv->planes[i]->funcs->destroy(priv->planes[i]);
Clarence Ip17162b52016-11-24 17:06:29 -0500699 priv->num_planes = 0;
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400700
701 for (i = 0; i < priv->num_connectors; i++)
702 priv->connectors[i]->funcs->destroy(priv->connectors[i]);
Clarence Ip17162b52016-11-24 17:06:29 -0500703 priv->num_connectors = 0;
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400704
705 for (i = 0; i < priv->num_encoders; i++)
706 priv->encoders[i]->funcs->destroy(priv->encoders[i]);
Clarence Ip17162b52016-11-24 17:06:29 -0500707 priv->num_encoders = 0;
708
709 _sde_kms_release_displays(sde_kms);
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400710}
711
712static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700713{
Clarence Ip2bbf7b32016-09-23 15:07:16 -0400714 struct drm_device *dev;
Dhaval Patel44f12472016-08-29 12:19:47 -0700715 struct drm_plane *primary_planes[MAX_PLANES], *plane;
716 struct drm_crtc *crtc;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700717
Clarence Ip2bbf7b32016-09-23 15:07:16 -0400718 struct msm_drm_private *priv;
719 struct sde_mdss_cfg *catalog;
Dhaval Patel44f12472016-08-29 12:19:47 -0700720
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800721 int primary_planes_idx = 0, i, ret;
722 int max_crtc_count;
723
724 u32 sspp_id[MAX_PLANES];
725 u32 master_plane_id[MAX_PLANES];
726 u32 num_virt_planes = 0;
Clarence Ip2bbf7b32016-09-23 15:07:16 -0400727
Clarence Ipdd395242016-09-09 10:47:17 -0400728 if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev) {
Clarence Ip2bbf7b32016-09-23 15:07:16 -0400729 SDE_ERROR("invalid sde_kms\n");
730 return -EINVAL;
731 }
732
733 dev = sde_kms->dev;
734 priv = dev->dev_private;
735 catalog = sde_kms->catalog;
736
Clarence Ip3649f8b2016-10-31 09:59:44 -0400737 /*
738 * Query for underlying display drivers, and create connectors,
739 * bridges and encoders for them.
740 */
741 if (!_sde_kms_get_displays(sde_kms))
742 (void)_sde_kms_setup_displays(dev, priv, sde_kms);
Clarence Ip2bbf7b32016-09-23 15:07:16 -0400743
744 max_crtc_count = min(catalog->mixer_count, priv->num_encoders);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700745
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700746 /* Create the planes */
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800747 for (i = 0; i < catalog->sspp_count; i++) {
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700748 bool primary = true;
749
750 if (catalog->sspp[i].features & BIT(SDE_SSPP_CURSOR)
Clarence Ip2bbf7b32016-09-23 15:07:16 -0400751 || primary_planes_idx >= max_crtc_count)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700752 primary = false;
753
Clarence Ip2bbf7b32016-09-23 15:07:16 -0400754 plane = sde_plane_init(dev, catalog->sspp[i].id, primary,
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800755 (1UL << max_crtc_count) - 1, 0);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700756 if (IS_ERR(plane)) {
Clarence Ip2bbf7b32016-09-23 15:07:16 -0400757 SDE_ERROR("sde_plane_init failed\n");
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700758 ret = PTR_ERR(plane);
759 goto fail;
760 }
761 priv->planes[priv->num_planes++] = plane;
762
763 if (primary)
764 primary_planes[primary_planes_idx++] = plane;
Jeykumar Sankaran2e655032017-02-04 14:05:45 -0800765
766 if (sde_hw_sspp_multirect_enabled(&catalog->sspp[i]) &&
767 sde_is_custom_client()) {
768 int priority =
769 catalog->sspp[i].sblk->smart_dma_priority;
770 sspp_id[priority - 1] = catalog->sspp[i].id;
771 master_plane_id[priority - 1] = plane->base.id;
772 num_virt_planes++;
773 }
774 }
775
776 /* Initialize smart DMA virtual planes */
777 for (i = 0; i < num_virt_planes; i++) {
778 plane = sde_plane_init(dev, sspp_id[i], false,
779 (1UL << max_crtc_count) - 1, master_plane_id[i]);
780 if (IS_ERR(plane)) {
781 SDE_ERROR("sde_plane for virtual SSPP init failed\n");
782 ret = PTR_ERR(plane);
783 goto fail;
784 }
785 priv->planes[priv->num_planes++] = plane;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700786 }
787
Dhaval Patel44f12472016-08-29 12:19:47 -0700788 max_crtc_count = min(max_crtc_count, primary_planes_idx);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700789
Dhaval Patel44f12472016-08-29 12:19:47 -0700790 /* Create one CRTC per encoder */
791 for (i = 0; i < max_crtc_count; i++) {
Lloyd Atkinsonac933642016-09-14 11:52:00 -0400792 crtc = sde_crtc_init(dev, primary_planes[i]);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700793 if (IS_ERR(crtc)) {
794 ret = PTR_ERR(crtc);
795 goto fail;
796 }
797 priv->crtcs[priv->num_crtcs++] = crtc;
798 }
799
Clarence Ipdd395242016-09-09 10:47:17 -0400800 if (sde_is_custom_client()) {
801 /* All CRTCs are compatible with all planes */
802 for (i = 0; i < priv->num_planes; i++)
803 priv->planes[i]->possible_crtcs =
804 (1 << priv->num_crtcs) - 1;
805 }
806
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400807 /* All CRTCs are compatible with all encoders */
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400808 for (i = 0; i < priv->num_encoders; i++)
809 priv->encoders[i]->possible_crtcs = (1 << priv->num_crtcs) - 1;
810
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700811 return 0;
812fail:
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400813 _sde_kms_drm_obj_destroy(sde_kms);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700814 return ret;
815}
816
Alan Kwong5a3ac752016-10-16 01:02:35 -0400817static int sde_kms_postinit(struct msm_kms *kms)
818{
819 struct sde_kms *sde_kms = to_sde_kms(kms);
820 struct drm_device *dev;
821
822 if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev) {
823 SDE_ERROR("invalid sde_kms\n");
824 return -EINVAL;
825 }
826
827 dev = sde_kms->dev;
828
Alan Kwong5a3ac752016-10-16 01:02:35 -0400829 return 0;
830}
831
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400832static long sde_kms_round_pixclk(struct msm_kms *kms, unsigned long rate,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700833 struct drm_encoder *encoder)
834{
835 return rate;
836}
837
Clarence Ip17162b52016-11-24 17:06:29 -0500838static void _sde_kms_hw_destroy(struct sde_kms *sde_kms,
839 struct platform_device *pdev)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700840{
Clarence Ip17162b52016-11-24 17:06:29 -0500841 struct drm_device *dev;
842 struct msm_drm_private *priv;
Alan Kwong5d324e42016-07-28 22:56:18 -0400843 int i;
844
Clarence Ip17162b52016-11-24 17:06:29 -0500845 if (!sde_kms || !pdev)
846 return;
847
848 dev = sde_kms->dev;
849 if (!dev)
850 return;
851
852 priv = dev->dev_private;
853 if (!priv)
854 return;
855
856 if (sde_kms->hw_intr)
857 sde_hw_intr_destroy(sde_kms->hw_intr);
858 sde_kms->hw_intr = NULL;
859
860 _sde_kms_release_displays(sde_kms);
861
862 /* safe to call these more than once during shutdown */
863 _sde_debugfs_destroy(sde_kms);
864 _sde_kms_mmu_destroy(sde_kms);
Alan Kwong67a3f792016-11-01 23:16:53 -0400865 sde_core_perf_destroy(&sde_kms->perf);
Clarence Ip17162b52016-11-24 17:06:29 -0500866
Lloyd Atkinson79f08802017-01-09 17:37:18 -0500867 if (sde_kms->catalog) {
868 for (i = 0; i < sde_kms->catalog->vbif_count; i++) {
869 u32 vbif_idx = sde_kms->catalog->vbif[i].id;
Alan Kwong5d324e42016-07-28 22:56:18 -0400870
Lloyd Atkinson79f08802017-01-09 17:37:18 -0500871 if ((vbif_idx < VBIF_MAX) && sde_kms->hw_vbif[vbif_idx])
872 sde_hw_vbif_destroy(sde_kms->hw_vbif[vbif_idx]);
873 }
Alan Kwong5d324e42016-07-28 22:56:18 -0400874 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700875
Clarence Ip17162b52016-11-24 17:06:29 -0500876 if (sde_kms->rm_init)
877 sde_rm_destroy(&sde_kms->rm);
878 sde_kms->rm_init = false;
879
880 if (sde_kms->catalog)
881 sde_hw_catalog_deinit(sde_kms->catalog);
882 sde_kms->catalog = NULL;
883
884 if (sde_kms->core_client)
885 sde_power_client_destroy(&priv->phandle, sde_kms->core_client);
886 sde_kms->core_client = NULL;
887
888 if (sde_kms->vbif[VBIF_NRT])
889 msm_iounmap(pdev, sde_kms->vbif[VBIF_NRT]);
890 sde_kms->vbif[VBIF_NRT] = NULL;
891
892 if (sde_kms->vbif[VBIF_RT])
893 msm_iounmap(pdev, sde_kms->vbif[VBIF_RT]);
894 sde_kms->vbif[VBIF_RT] = NULL;
895
896 if (sde_kms->mmio)
897 msm_iounmap(pdev, sde_kms->mmio);
898 sde_kms->mmio = NULL;
899}
900
901static void sde_kms_destroy(struct msm_kms *kms)
902{
903 struct sde_kms *sde_kms;
904 struct drm_device *dev;
905
906 if (!kms) {
907 SDE_ERROR("invalid kms\n");
908 return;
909 }
910
911 sde_kms = to_sde_kms(kms);
912 dev = sde_kms->dev;
913 if (!dev) {
914 SDE_ERROR("invalid device\n");
915 return;
916 }
917
918 _sde_kms_hw_destroy(sde_kms, dev->platformdev);
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700919 kfree(sde_kms);
920}
921
Lloyd Atkinson5217336c2016-09-15 18:21:18 -0400922static void sde_kms_preclose(struct msm_kms *kms, struct drm_file *file)
923{
924 struct sde_kms *sde_kms = to_sde_kms(kms);
925 struct drm_device *dev = sde_kms->dev;
926 struct msm_drm_private *priv = dev->dev_private;
927 unsigned int i;
928
929 for (i = 0; i < priv->num_crtcs; i++)
930 sde_crtc_cancel_pending_flip(priv->crtcs[i], file);
931}
932
Ben Chan78647cd2016-06-26 22:02:47 -0400933static const struct msm_kms_funcs kms_funcs = {
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400934 .hw_init = sde_kms_hw_init,
Alan Kwong5a3ac752016-10-16 01:02:35 -0400935 .postinit = sde_kms_postinit,
Ben Chan78647cd2016-06-26 22:02:47 -0400936 .irq_preinstall = sde_irq_preinstall,
937 .irq_postinstall = sde_irq_postinstall,
938 .irq_uninstall = sde_irq_uninstall,
939 .irq = sde_irq,
Lloyd Atkinson5217336c2016-09-15 18:21:18 -0400940 .preclose = sde_kms_preclose,
Clarence Ip24f80662016-06-13 19:05:32 -0400941 .prepare_fence = sde_kms_prepare_fence,
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400942 .prepare_commit = sde_kms_prepare_commit,
943 .commit = sde_kms_commit,
944 .complete_commit = sde_kms_complete_commit,
945 .wait_for_crtc_commit_done = sde_kms_wait_for_commit_done,
Alan Kwongf5dd86c2016-08-09 18:08:17 -0400946 .enable_vblank = sde_kms_enable_vblank,
947 .disable_vblank = sde_kms_disable_vblank,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400948 .check_modified_format = sde_format_check_modified_format,
Clarence Ip4ce59322016-06-26 22:27:51 -0400949 .get_format = sde_get_msm_format,
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400950 .round_pixclk = sde_kms_round_pixclk,
951 .destroy = sde_kms_destroy,
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700952};
953
Dhaval Patel3949f032016-06-20 16:24:33 -0700954/* the caller api needs to turn on clock before calling it */
Clarence Ip17162b52016-11-24 17:06:29 -0500955static inline void _sde_kms_core_hw_rev_init(struct sde_kms *sde_kms)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700956{
Dhaval Patel6fe7f672017-02-10 12:40:46 -0800957 return;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -0700958}
959
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400960static int _sde_kms_mmu_destroy(struct sde_kms *sde_kms)
961{
962 struct msm_mmu *mmu;
963 int i;
964
965 for (i = ARRAY_SIZE(sde_kms->mmu_id) - 1; i >= 0; i--) {
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -0400966 if (!sde_kms->mmu[i])
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -0400967 continue;
968
969 mmu = sde_kms->mmu[i];
970 msm_unregister_mmu(sde_kms->dev, mmu);
971 mmu->funcs->detach(mmu, (const char **)iommu_ports,
972 ARRAY_SIZE(iommu_ports));
973 mmu->funcs->destroy(mmu);
974 sde_kms->mmu[i] = 0;
975 sde_kms->mmu_id[i] = 0;
976 }
977
978 return 0;
979}
980
981static int _sde_kms_mmu_init(struct sde_kms *sde_kms)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400982{
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400983 struct msm_mmu *mmu;
984 int i, ret;
985
Alan Kwong112a84f2016-05-24 20:49:21 -0400986 for (i = 0; i < MSM_SMMU_DOMAIN_MAX; i++) {
987 mmu = msm_smmu_new(sde_kms->dev->dev, i);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400988 if (IS_ERR(mmu)) {
989 ret = PTR_ERR(mmu);
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -0400990 SDE_ERROR("failed to init iommu id %d: rc: %d\n", i,
991 ret);
Dhaval Patel5200c602017-01-17 15:53:37 -0800992 continue;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400993 }
994
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400995 ret = mmu->funcs->attach(mmu, (const char **)iommu_ports,
996 ARRAY_SIZE(iommu_ports));
997 if (ret) {
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -0400998 SDE_ERROR("failed to attach iommu %d: %d\n", i, ret);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400999 mmu->funcs->destroy(mmu);
Dhaval Patel5200c602017-01-17 15:53:37 -08001000 continue;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001001 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001002
Alan Kwong112a84f2016-05-24 20:49:21 -04001003 sde_kms->mmu_id[i] = msm_register_mmu(sde_kms->dev, mmu);
1004 if (sde_kms->mmu_id[i] < 0) {
1005 ret = sde_kms->mmu_id[i];
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001006 SDE_ERROR("failed to register sde iommu %d: %d\n",
1007 i, ret);
Alan Kwong112a84f2016-05-24 20:49:21 -04001008 mmu->funcs->detach(mmu, (const char **)iommu_ports,
1009 ARRAY_SIZE(iommu_ports));
Alan Kwong112a84f2016-05-24 20:49:21 -04001010 goto fail;
1011 }
1012
1013 sde_kms->mmu[i] = mmu;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001014 }
1015
1016 return 0;
1017fail:
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001018 _sde_kms_mmu_destroy(sde_kms);
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001019
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001020 return ret;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001021}
1022
Lloyd Atkinson113aefd2016-10-23 13:15:18 -04001023static void __iomem *_sde_kms_ioremap(struct platform_device *pdev,
1024 const char *name, unsigned long *out_size)
1025{
1026 struct resource *res;
1027 unsigned long size;
1028 void __iomem *ptr;
1029
1030 if (out_size)
1031 *out_size = 0;
1032
1033 if (name)
1034 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
1035 else
1036 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1037
1038 if (!res) {
1039 /* availability depends on platform */
1040 SDE_DEBUG("failed to get memory resource: %s\n", name);
1041 return ERR_PTR(-EINVAL);
1042 }
1043
1044 size = resource_size(res);
1045
1046 ptr = devm_ioremap_nocache(&pdev->dev, res->start, size);
1047 if (!ptr) {
1048 SDE_ERROR("failed to ioremap: %s\n", name);
1049 return ERR_PTR(-ENOMEM);
1050 }
1051
1052 SDE_DEBUG("IO:region %s %p %08lx\n", name, ptr, size);
1053
1054 if (out_size)
1055 *out_size = size;
1056
1057 return ptr;
1058}
1059
1060
Clarence Ip17162b52016-11-24 17:06:29 -05001061static int sde_kms_hw_init(struct msm_kms *kms)
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001062{
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001063 struct sde_kms *sde_kms;
Clarence Ip17162b52016-11-24 17:06:29 -05001064 struct drm_device *dev;
Dhaval Patel3949f032016-06-20 16:24:33 -07001065 struct msm_drm_private *priv;
Clarence Ip17162b52016-11-24 17:06:29 -05001066 int i, rc = -EINVAL;
Dhaval Patel3949f032016-06-20 16:24:33 -07001067
Clarence Ip17162b52016-11-24 17:06:29 -05001068 if (!kms) {
1069 SDE_ERROR("invalid kms\n");
1070 goto end;
1071 }
1072
1073 sde_kms = to_sde_kms(kms);
1074 dev = sde_kms->dev;
1075 if (!dev || !dev->platformdev) {
1076 SDE_ERROR("invalid device\n");
Dhaval Patel3949f032016-06-20 16:24:33 -07001077 goto end;
1078 }
1079
1080 priv = dev->dev_private;
Clarence Ip17162b52016-11-24 17:06:29 -05001081 if (!priv) {
1082 SDE_ERROR("invalid private data\n");
Dhaval Patel3949f032016-06-20 16:24:33 -07001083 goto end;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001084 }
1085
Lloyd Atkinson113aefd2016-10-23 13:15:18 -04001086 sde_kms->mmio = _sde_kms_ioremap(dev->platformdev, "mdp_phys",
1087 &sde_kms->mmio_len);
Clarence Ip17162b52016-11-24 17:06:29 -05001088 if (IS_ERR(sde_kms->mmio)) {
1089 rc = PTR_ERR(sde_kms->mmio);
1090 SDE_ERROR("mdp register memory map failed: %d\n", rc);
1091 sde_kms->mmio = NULL;
1092 goto error;
1093 }
1094 DRM_INFO("mapped mdp address space @%p\n", sde_kms->mmio);
1095
Lloyd Atkinson113aefd2016-10-23 13:15:18 -04001096 rc = sde_dbg_reg_register_base(SDE_DBG_NAME, sde_kms->mmio,
1097 sde_kms->mmio_len);
1098 if (rc)
1099 SDE_ERROR("dbg base register kms failed: %d\n", rc);
1100
1101 sde_kms->vbif[VBIF_RT] = _sde_kms_ioremap(dev->platformdev, "vbif_phys",
1102 &sde_kms->vbif_len[VBIF_RT]);
Clarence Ip17162b52016-11-24 17:06:29 -05001103 if (IS_ERR(sde_kms->vbif[VBIF_RT])) {
1104 rc = PTR_ERR(sde_kms->vbif[VBIF_RT]);
1105 SDE_ERROR("vbif register memory map failed: %d\n", rc);
1106 sde_kms->vbif[VBIF_RT] = NULL;
1107 goto error;
1108 }
1109
Lloyd Atkinson113aefd2016-10-23 13:15:18 -04001110 rc = sde_dbg_reg_register_base("vbif_rt", sde_kms->vbif[VBIF_RT],
1111 sde_kms->vbif_len[VBIF_RT]);
1112 if (rc)
1113 SDE_ERROR("dbg base register vbif_rt failed: %d\n", rc);
1114
1115 sde_kms->vbif[VBIF_NRT] = _sde_kms_ioremap(dev->platformdev,
1116 "vbif_nrt_phys", &sde_kms->vbif_len[VBIF_NRT]);
Clarence Ip17162b52016-11-24 17:06:29 -05001117 if (IS_ERR(sde_kms->vbif[VBIF_NRT])) {
1118 sde_kms->vbif[VBIF_NRT] = NULL;
1119 SDE_DEBUG("VBIF NRT is not defined");
Lloyd Atkinson113aefd2016-10-23 13:15:18 -04001120 } else {
1121 rc = sde_dbg_reg_register_base("vbif_nrt",
1122 sde_kms->vbif[VBIF_NRT],
1123 sde_kms->vbif_len[VBIF_NRT]);
1124 if (rc)
1125 SDE_ERROR("dbg base register vbif_nrt failed: %d\n",
1126 rc);
Clarence Ip17162b52016-11-24 17:06:29 -05001127 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001128
Lloyd Atkinson113aefd2016-10-23 13:15:18 -04001129 sde_kms->reg_dma = _sde_kms_ioremap(dev->platformdev, "regdma_phys",
1130 &sde_kms->reg_dma_len);
Gopikrishnaiah Anandan7e3e3f52016-12-22 11:13:05 -08001131 if (IS_ERR(sde_kms->reg_dma)) {
1132 sde_kms->reg_dma = NULL;
1133 SDE_DEBUG("REG_DMA is not defined");
Lloyd Atkinson113aefd2016-10-23 13:15:18 -04001134 } else {
1135 rc = sde_dbg_reg_register_base("vbif_nrt",
1136 sde_kms->reg_dma,
1137 sde_kms->reg_dma_len);
1138 if (rc)
1139 SDE_ERROR("dbg base register reg_dma failed: %d\n",
1140 rc);
1141
Gopikrishnaiah Anandan7e3e3f52016-12-22 11:13:05 -08001142 }
1143
Dhaval Patel3949f032016-06-20 16:24:33 -07001144 sde_kms->core_client = sde_power_client_create(&priv->phandle, "core");
1145 if (IS_ERR_OR_NULL(sde_kms->core_client)) {
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001146 rc = PTR_ERR(sde_kms->core_client);
1147 SDE_ERROR("sde power client create failed: %d\n", rc);
1148 sde_kms->core_client = NULL;
Clarence Ip17162b52016-11-24 17:06:29 -05001149 goto error;
Dhaval Patel3949f032016-06-20 16:24:33 -07001150 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001151
Dhaval Patel3949f032016-06-20 16:24:33 -07001152 rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
1153 true);
1154 if (rc) {
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001155 SDE_ERROR("resource enable failed: %d\n", rc);
Clarence Ip17162b52016-11-24 17:06:29 -05001156 goto error;
Dhaval Patel3949f032016-06-20 16:24:33 -07001157 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001158
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001159 _sde_kms_core_hw_rev_init(sde_kms);
Lloyd Atkinson11f34442016-08-11 11:19:52 -04001160
Dhaval Patelb271b842016-10-19 21:41:22 -07001161 pr_info("sde hardware revision:0x%x\n", sde_kms->core_rev);
1162
Dhaval Patel8bf7ff32016-07-20 18:13:24 -07001163 sde_kms->catalog = sde_hw_catalog_init(dev, sde_kms->core_rev);
Dhaval Patel3949f032016-06-20 16:24:33 -07001164 if (IS_ERR_OR_NULL(sde_kms->catalog)) {
Dhaval Patel3949f032016-06-20 16:24:33 -07001165 rc = PTR_ERR(sde_kms->catalog);
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001166 SDE_ERROR("catalog init failed: %d\n", rc);
1167 sde_kms->catalog = NULL;
Clarence Ip17162b52016-11-24 17:06:29 -05001168 goto power_error;
Dhaval Patel3949f032016-06-20 16:24:33 -07001169 }
1170
Lloyd Atkinson274cc462017-02-21 11:52:06 -05001171 sde_dbg_init_dbg_buses(sde_kms->core_rev);
1172
Gopikrishnaiah Anandan7e3e3f52016-12-22 11:13:05 -08001173 /* Initialize reg dma block which is a singleton */
1174 rc = sde_reg_dma_init(sde_kms->reg_dma, sde_kms->catalog,
1175 sde_kms->dev);
1176 if (rc) {
1177 SDE_ERROR("failed: reg dma init failed\n");
1178 goto power_error;
1179 }
1180
Dhaval Patel3949f032016-06-20 16:24:33 -07001181 rc = sde_rm_init(&sde_kms->rm, sde_kms->catalog, sde_kms->mmio,
Lloyd Atkinson11f34442016-08-11 11:19:52 -04001182 sde_kms->dev);
Clarence Ip17162b52016-11-24 17:06:29 -05001183 if (rc) {
1184 SDE_ERROR("rm init failed: %d\n", rc);
1185 goto power_error;
1186 }
1187
1188 sde_kms->rm_init = true;
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001189
1190 sde_kms->hw_mdp = sde_rm_get_mdp(&sde_kms->rm);
1191 if (IS_ERR_OR_NULL(sde_kms->hw_mdp)) {
1192 rc = PTR_ERR(sde_kms->hw_mdp);
1193 SDE_ERROR("failed to get hw_mdp: %d\n", rc);
1194 sde_kms->hw_mdp = NULL;
Clarence Ip17162b52016-11-24 17:06:29 -05001195 goto power_error;
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001196 }
Dhaval Patel3949f032016-06-20 16:24:33 -07001197
Alan Kwong5d324e42016-07-28 22:56:18 -04001198 for (i = 0; i < sde_kms->catalog->vbif_count; i++) {
1199 u32 vbif_idx = sde_kms->catalog->vbif[i].id;
1200
1201 sde_kms->hw_vbif[i] = sde_hw_vbif_init(vbif_idx,
1202 sde_kms->vbif[vbif_idx], sde_kms->catalog);
1203 if (IS_ERR_OR_NULL(sde_kms->hw_vbif[vbif_idx])) {
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001204 rc = PTR_ERR(sde_kms->hw_vbif[vbif_idx]);
1205 SDE_ERROR("failed to init vbif %d: %d\n", vbif_idx, rc);
Alan Kwong5d324e42016-07-28 22:56:18 -04001206 sde_kms->hw_vbif[vbif_idx] = NULL;
Clarence Ip17162b52016-11-24 17:06:29 -05001207 goto power_error;
Alan Kwong5d324e42016-07-28 22:56:18 -04001208 }
1209 }
1210
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001211 /*
1212 * Now we need to read the HW catalog and initialize resources such as
1213 * clocks, regulators, GDSC/MMAGIC, ioremap the register ranges etc
1214 */
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001215 rc = _sde_kms_mmu_init(sde_kms);
1216 if (rc) {
1217 SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc);
Clarence Ip17162b52016-11-24 17:06:29 -05001218 goto power_error;
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001219 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001220
1221 /*
Clarence Ip4ce59322016-06-26 22:27:51 -04001222 * NOTE: Calling sde_debugfs_init here so that the drm_minor device for
1223 * 'primary' is already created.
1224 */
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001225 rc = _sde_debugfs_init(sde_kms);
1226 if (rc) {
1227 SDE_ERROR("sde_debugfs init failed: %d\n", rc);
Clarence Ip17162b52016-11-24 17:06:29 -05001228 goto power_error;
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001229 }
Clarence Ip4ce59322016-06-26 22:27:51 -04001230
Alan Kwong67a3f792016-11-01 23:16:53 -04001231 rc = sde_core_perf_init(&sde_kms->perf, dev, sde_kms->catalog,
1232 &priv->phandle, priv->pclient, "core_clk_src",
1233 sde_kms->debugfs_debug);
1234 if (rc) {
1235 SDE_ERROR("failed to init perf %d\n", rc);
1236 goto perf_err;
1237 }
1238
Clarence Ip4ce59322016-06-26 22:27:51 -04001239 /*
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001240 * _sde_kms_drm_obj_init should create the DRM related objects
1241 * i.e. CRTCs, planes, encoders, connectors and so forth
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001242 */
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001243 rc = _sde_kms_drm_obj_init(sde_kms);
1244 if (rc) {
1245 SDE_ERROR("modeset init failed: %d\n", rc);
Alan Kwong67a3f792016-11-01 23:16:53 -04001246 goto drm_obj_init_err;
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001247 }
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001248
1249 dev->mode_config.min_width = 0;
1250 dev->mode_config.min_height = 0;
1251
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001252 /*
Dhaval Patel4e574842016-08-23 15:11:37 -07001253 * max crtc width is equal to the max mixer width * 2 and max height is
1254 * is 4K
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001255 */
Dhaval Patele4a5dda2016-10-13 19:29:30 -07001256 dev->mode_config.max_width = sde_kms->catalog->max_mixer_width * 2;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001257 dev->mode_config.max_height = 4096;
1258
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -04001259 /*
1260 * Support format modifiers for compression etc.
1261 */
1262 dev->mode_config.allow_fb_modifiers = true;
1263
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001264 sde_kms->hw_intr = sde_hw_intr_init(sde_kms->mmio, sde_kms->catalog);
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001265 if (IS_ERR_OR_NULL(sde_kms->hw_intr)) {
1266 rc = PTR_ERR(sde_kms->hw_intr);
1267 SDE_ERROR("hw_intr init failed: %d\n", rc);
1268 sde_kms->hw_intr = NULL;
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001269 goto hw_intr_init_err;
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001270 }
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001271
Lloyd Atkinson5217336c2016-09-15 18:21:18 -04001272 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
Clarence Ip17162b52016-11-24 17:06:29 -05001273 return 0;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001274
Lloyd Atkinson1e2497e2016-09-26 17:55:48 -04001275hw_intr_init_err:
1276 _sde_kms_drm_obj_destroy(sde_kms);
Alan Kwong67a3f792016-11-01 23:16:53 -04001277drm_obj_init_err:
1278 sde_core_perf_destroy(&sde_kms->perf);
1279perf_err:
Clarence Ip17162b52016-11-24 17:06:29 -05001280power_error:
Dhaval Patel3949f032016-06-20 16:24:33 -07001281 sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
Clarence Ip17162b52016-11-24 17:06:29 -05001282error:
Lloyd Atkinson1a0c9172016-10-04 10:01:24 -04001283 _sde_kms_hw_destroy(sde_kms, dev->platformdev);
Dhaval Patel3949f032016-06-20 16:24:33 -07001284end:
Clarence Ip17162b52016-11-24 17:06:29 -05001285 return rc;
1286}
1287
1288struct msm_kms *sde_kms_init(struct drm_device *dev)
1289{
1290 struct msm_drm_private *priv;
1291 struct sde_kms *sde_kms;
1292
1293 if (!dev || !dev->dev_private) {
1294 SDE_ERROR("drm device node invalid\n");
1295 return ERR_PTR(-EINVAL);
1296 }
1297
1298 priv = dev->dev_private;
1299
1300 sde_kms = kzalloc(sizeof(*sde_kms), GFP_KERNEL);
1301 if (!sde_kms) {
1302 SDE_ERROR("failed to allocate sde kms\n");
1303 return ERR_PTR(-ENOMEM);
1304 }
1305
1306 msm_kms_init(&sde_kms->base, &kms_funcs);
1307 sde_kms->dev = dev;
1308
1309 return &sde_kms->base;
Narendra Muppalla1b0b3352015-09-29 10:16:51 -07001310}