blob: 609ae522af066605c1a0c930719ed25e8ff4e654 [file] [log] [blame]
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001/*
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070012 */
13
14#define pr_fmt(fmt) "dsi-ctrl:[%s] " fmt, __func__
15
16#include <linux/of_device.h>
17#include <linux/err.h>
18#include <linux/regulator/consumer.h>
19#include <linux/clk.h>
20#include <linux/msm-bus.h>
21#include <linux/of_irq.h>
22#include <video/mipi_display.h>
23
24#include "msm_drv.h"
25#include "msm_kms.h"
26#include "msm_gpu.h"
Jordan Croused8e96522017-02-13 10:14:16 -070027#include "msm_mmu.h"
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070028#include "dsi_ctrl.h"
29#include "dsi_ctrl_hw.h"
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +053030#include "dsi_clk.h"
31#include "dsi_pwr.h"
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070032#include "dsi_catalog.h"
33
Dhaval Patela2430842017-06-15 14:32:36 -070034#include "sde_dbg.h"
35
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070036#define DSI_CTRL_DEFAULT_LABEL "MDSS DSI CTRL"
37
38#define DSI_CTRL_TX_TO_MS 200
39
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -070040#define TO_ON_OFF(x) ((x) ? "ON" : "OFF")
Sandeep Panda5c51ea62017-08-02 13:50:15 +053041
42#define CEIL(x, y) (((x) + ((y)-1)) / (y))
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070043/**
44 * enum dsi_ctrl_driver_ops - controller driver ops
45 */
46enum dsi_ctrl_driver_ops {
47 DSI_CTRL_OP_POWER_STATE_CHANGE,
48 DSI_CTRL_OP_CMD_ENGINE,
49 DSI_CTRL_OP_VID_ENGINE,
50 DSI_CTRL_OP_HOST_ENGINE,
51 DSI_CTRL_OP_CMD_TX,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070052 DSI_CTRL_OP_HOST_INIT,
53 DSI_CTRL_OP_TPG,
54 DSI_CTRL_OP_PHY_SW_RESET,
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -070055 DSI_CTRL_OP_ASYNC_TIMING,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070056 DSI_CTRL_OP_MAX
57};
58
59struct dsi_ctrl_list_item {
60 struct dsi_ctrl *ctrl;
61 struct list_head list;
62};
63
64static LIST_HEAD(dsi_ctrl_list);
65static DEFINE_MUTEX(dsi_ctrl_list_lock);
66
67static const enum dsi_ctrl_version dsi_ctrl_v1_4 = DSI_CTRL_VERSION_1_4;
68static const enum dsi_ctrl_version dsi_ctrl_v2_0 = DSI_CTRL_VERSION_2_0;
Shashank Babu Chinta Venkataafef8202017-04-21 13:49:56 -070069static const enum dsi_ctrl_version dsi_ctrl_v2_2 = DSI_CTRL_VERSION_2_2;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070070
71static const struct of_device_id msm_dsi_of_match[] = {
72 {
73 .compatible = "qcom,dsi-ctrl-hw-v1.4",
74 .data = &dsi_ctrl_v1_4,
75 },
76 {
77 .compatible = "qcom,dsi-ctrl-hw-v2.0",
78 .data = &dsi_ctrl_v2_0,
79 },
Shashank Babu Chinta Venkataafef8202017-04-21 13:49:56 -070080 {
81 .compatible = "qcom,dsi-ctrl-hw-v2.2",
82 .data = &dsi_ctrl_v2_2,
83 },
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070084 {}
85};
86
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -070087static ssize_t debugfs_state_info_read(struct file *file,
88 char __user *buff,
89 size_t count,
90 loff_t *ppos)
91{
92 struct dsi_ctrl *dsi_ctrl = file->private_data;
93 char *buf;
94 u32 len = 0;
95
96 if (!dsi_ctrl)
97 return -ENODEV;
98
99 if (*ppos)
100 return 0;
101
102 buf = kzalloc(SZ_4K, GFP_KERNEL);
103 if (!buf)
104 return -ENOMEM;
105
106 /* Dump current state */
107 len += snprintf((buf + len), (SZ_4K - len), "Current State:\n");
108 len += snprintf((buf + len), (SZ_4K - len),
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530109 "\tCTRL_ENGINE = %s\n",
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700110 TO_ON_OFF(dsi_ctrl->current_state.controller_state));
111 len += snprintf((buf + len), (SZ_4K - len),
112 "\tVIDEO_ENGINE = %s\n\tCOMMAND_ENGINE = %s\n",
113 TO_ON_OFF(dsi_ctrl->current_state.vid_engine_state),
114 TO_ON_OFF(dsi_ctrl->current_state.cmd_engine_state));
115
116 /* Dump clock information */
117 len += snprintf((buf + len), (SZ_4K - len), "\nClock Info:\n");
118 len += snprintf((buf + len), (SZ_4K - len),
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530119 "\tBYTE_CLK = %u, PIXEL_CLK = %u, ESC_CLK = %u\n",
120 dsi_ctrl->clk_freq.byte_clk_rate,
121 dsi_ctrl->clk_freq.pix_clk_rate,
122 dsi_ctrl->clk_freq.esc_clk_rate);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700123
124 /* TODO: make sure that this does not exceed 4K */
125 if (copy_to_user(buff, buf, len)) {
126 kfree(buf);
127 return -EFAULT;
128 }
129
130 *ppos += len;
131 kfree(buf);
132 return len;
133}
134
135static ssize_t debugfs_reg_dump_read(struct file *file,
136 char __user *buff,
137 size_t count,
138 loff_t *ppos)
139{
140 struct dsi_ctrl *dsi_ctrl = file->private_data;
141 char *buf;
142 u32 len = 0;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530143 struct dsi_clk_ctrl_info clk_info;
144 int rc = 0;
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700145
146 if (!dsi_ctrl)
147 return -ENODEV;
148
149 if (*ppos)
150 return 0;
151
152 buf = kzalloc(SZ_4K, GFP_KERNEL);
153 if (!buf)
154 return -ENOMEM;
155
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530156 clk_info.client = DSI_CLK_REQ_DSI_CLIENT;
157 clk_info.clk_type = DSI_CORE_CLK;
158 clk_info.clk_state = DSI_CLK_ON;
159
160 rc = dsi_ctrl->clk_cb.dsi_clk_cb(dsi_ctrl->clk_cb.priv, clk_info);
161 if (rc) {
162 pr_err("failed to enable DSI core clocks\n");
163 kfree(buf);
164 return rc;
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700165 }
166
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +0530167 if (dsi_ctrl->hw.ops.reg_dump_to_buffer)
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530168 len = dsi_ctrl->hw.ops.reg_dump_to_buffer(&dsi_ctrl->hw,
169 buf, SZ_4K);
170
171 clk_info.clk_state = DSI_CLK_OFF;
172 rc = dsi_ctrl->clk_cb.dsi_clk_cb(dsi_ctrl->clk_cb.priv, clk_info);
173 if (rc) {
174 pr_err("failed to disable DSI core clocks\n");
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +0530175 kfree(buf);
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530176 return rc;
177 }
178
179
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700180 /* TODO: make sure that this does not exceed 4K */
181 if (copy_to_user(buff, buf, len)) {
182 kfree(buf);
183 return -EFAULT;
184 }
185
186 *ppos += len;
187 kfree(buf);
188 return len;
189}
190
191static const struct file_operations state_info_fops = {
192 .open = simple_open,
193 .read = debugfs_state_info_read,
194};
195
196static const struct file_operations reg_dump_fops = {
197 .open = simple_open,
198 .read = debugfs_reg_dump_read,
199};
200
201static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl,
202 struct dentry *parent)
203{
204 int rc = 0;
205 struct dentry *dir, *state_file, *reg_dump;
Dhaval Patela2430842017-06-15 14:32:36 -0700206 char dbg_name[DSI_DEBUG_NAME_LEN];
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700207
208 dir = debugfs_create_dir(dsi_ctrl->name, parent);
209 if (IS_ERR_OR_NULL(dir)) {
210 rc = PTR_ERR(dir);
211 pr_err("[DSI_%d] debugfs create dir failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500212 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700213 goto error;
214 }
215
216 state_file = debugfs_create_file("state_info",
217 0444,
218 dir,
219 dsi_ctrl,
220 &state_info_fops);
221 if (IS_ERR_OR_NULL(state_file)) {
222 rc = PTR_ERR(state_file);
223 pr_err("[DSI_%d] state file failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500224 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700225 goto error_remove_dir;
226 }
227
228 reg_dump = debugfs_create_file("reg_dump",
229 0444,
230 dir,
231 dsi_ctrl,
232 &reg_dump_fops);
233 if (IS_ERR_OR_NULL(reg_dump)) {
234 rc = PTR_ERR(reg_dump);
235 pr_err("[DSI_%d] reg dump file failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500236 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700237 goto error_remove_dir;
238 }
239
240 dsi_ctrl->debugfs_root = dir;
Dhaval Patela2430842017-06-15 14:32:36 -0700241
242 snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_ctrl",
243 dsi_ctrl->cell_index);
244 sde_dbg_reg_register_base(dbg_name, dsi_ctrl->hw.base,
245 msm_iomap_size(dsi_ctrl->pdev, "dsi_ctrl"));
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700246error_remove_dir:
247 debugfs_remove(dir);
248error:
249 return rc;
250}
251
252static int dsi_ctrl_debugfs_deinit(struct dsi_ctrl *dsi_ctrl)
253{
254 debugfs_remove(dsi_ctrl->debugfs_root);
255 return 0;
256}
257
Jordan Croused8e96522017-02-13 10:14:16 -0700258static inline struct msm_gem_address_space*
259dsi_ctrl_get_aspace(struct dsi_ctrl *dsi_ctrl,
260 int domain)
261{
262 if (!dsi_ctrl || !dsi_ctrl->drm_dev)
263 return NULL;
264
265 return msm_gem_smmu_address_space_get(dsi_ctrl->drm_dev, domain);
266}
267
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700268static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl,
269 enum dsi_ctrl_driver_ops op,
270 u32 op_state)
271{
272 int rc = 0;
273 struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state;
274
275 switch (op) {
276 case DSI_CTRL_OP_POWER_STATE_CHANGE:
277 if (state->power_state == op_state) {
278 pr_debug("[%d] No change in state, pwr_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500279 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700280 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530281 } else if (state->power_state == DSI_CTRL_POWER_VREG_ON) {
Veera Sundaram Sankaran4e109162017-04-21 10:36:46 -0700282 if (state->vid_engine_state == DSI_CTRL_ENGINE_ON) {
283 pr_debug("[%d]State error: op=%d: %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500284 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700285 op_state,
Veera Sundaram Sankaran4e109162017-04-21 10:36:46 -0700286 state->vid_engine_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700287 rc = -EINVAL;
288 }
289 }
290 break;
291 case DSI_CTRL_OP_CMD_ENGINE:
292 if (state->cmd_engine_state == op_state) {
293 pr_debug("[%d] No change in state, cmd_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500294 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700295 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530296 } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700297 (state->controller_state != DSI_CTRL_ENGINE_ON)) {
298 pr_debug("[%d]State error: op=%d: %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500299 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700300 op,
301 state->power_state,
302 state->controller_state);
303 rc = -EINVAL;
304 }
305 break;
306 case DSI_CTRL_OP_VID_ENGINE:
307 if (state->vid_engine_state == op_state) {
308 pr_debug("[%d] No change in state, cmd_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500309 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700310 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530311 } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700312 (state->controller_state != DSI_CTRL_ENGINE_ON)) {
313 pr_debug("[%d]State error: op=%d: %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500314 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700315 op,
316 state->power_state,
317 state->controller_state);
318 rc = -EINVAL;
319 }
320 break;
321 case DSI_CTRL_OP_HOST_ENGINE:
322 if (state->controller_state == op_state) {
323 pr_debug("[%d] No change in state, ctrl_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500324 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700325 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530326 } else if (state->power_state != DSI_CTRL_POWER_VREG_ON) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700327 pr_debug("[%d]State error (link is off): op=%d:, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500328 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700329 op_state,
330 state->power_state);
331 rc = -EINVAL;
332 } else if ((op_state == DSI_CTRL_ENGINE_OFF) &&
333 ((state->cmd_engine_state != DSI_CTRL_ENGINE_OFF) ||
334 (state->vid_engine_state != DSI_CTRL_ENGINE_OFF))) {
335 pr_debug("[%d]State error (eng on): op=%d: %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500336 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700337 op_state,
338 state->cmd_engine_state,
339 state->vid_engine_state);
340 rc = -EINVAL;
341 }
342 break;
343 case DSI_CTRL_OP_CMD_TX:
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530344 if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700345 (state->host_initialized != true) ||
346 (state->cmd_engine_state != DSI_CTRL_ENGINE_ON)) {
347 pr_debug("[%d]State error: op=%d: %d, %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500348 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700349 op,
350 state->power_state,
351 state->host_initialized,
352 state->cmd_engine_state);
353 rc = -EINVAL;
354 }
355 break;
356 case DSI_CTRL_OP_HOST_INIT:
357 if (state->host_initialized == op_state) {
358 pr_debug("[%d] No change in state, host_init=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500359 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700360 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530361 } else if (state->power_state != DSI_CTRL_POWER_VREG_ON) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700362 pr_debug("[%d]State error: op=%d: %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500363 dsi_ctrl->cell_index, op, state->power_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700364 rc = -EINVAL;
365 }
366 break;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700367 case DSI_CTRL_OP_TPG:
368 if (state->tpg_enabled == op_state) {
369 pr_debug("[%d] No change in state, tpg_enabled=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500370 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700371 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530372 } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700373 (state->controller_state != DSI_CTRL_ENGINE_ON)) {
374 pr_debug("[%d]State error: op=%d: %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500375 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700376 op,
377 state->power_state,
378 state->controller_state);
379 rc = -EINVAL;
380 }
381 break;
382 case DSI_CTRL_OP_PHY_SW_RESET:
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530383 if (state->power_state != DSI_CTRL_POWER_VREG_ON) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700384 pr_debug("[%d]State error: op=%d: %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500385 dsi_ctrl->cell_index, op, state->power_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700386 rc = -EINVAL;
387 }
388 break;
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -0700389 case DSI_CTRL_OP_ASYNC_TIMING:
390 if (state->vid_engine_state != op_state) {
391 pr_err("[%d] Unexpected engine state vid_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500392 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -0700393 rc = -EINVAL;
394 }
395 break;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700396 default:
397 rc = -ENOTSUPP;
398 break;
399 }
400
401 return rc;
402}
403
404static void dsi_ctrl_update_state(struct dsi_ctrl *dsi_ctrl,
405 enum dsi_ctrl_driver_ops op,
406 u32 op_state)
407{
408 struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state;
409
410 switch (op) {
411 case DSI_CTRL_OP_POWER_STATE_CHANGE:
412 state->power_state = op_state;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700413 break;
414 case DSI_CTRL_OP_CMD_ENGINE:
415 state->cmd_engine_state = op_state;
416 break;
417 case DSI_CTRL_OP_VID_ENGINE:
418 state->vid_engine_state = op_state;
419 break;
420 case DSI_CTRL_OP_HOST_ENGINE:
421 state->controller_state = op_state;
422 break;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700423 case DSI_CTRL_OP_HOST_INIT:
424 state->host_initialized = (op_state == 1) ? true : false;
425 break;
426 case DSI_CTRL_OP_TPG:
427 state->tpg_enabled = (op_state == 1) ? true : false;
428 break;
429 case DSI_CTRL_OP_CMD_TX:
430 case DSI_CTRL_OP_PHY_SW_RESET:
431 default:
432 break;
433 }
434}
435
436static int dsi_ctrl_init_regmap(struct platform_device *pdev,
437 struct dsi_ctrl *ctrl)
438{
439 int rc = 0;
440 void __iomem *ptr;
441
442 ptr = msm_ioremap(pdev, "dsi_ctrl", ctrl->name);
443 if (IS_ERR(ptr)) {
444 rc = PTR_ERR(ptr);
445 return rc;
446 }
447
448 ctrl->hw.base = ptr;
449 pr_debug("[%s] map dsi_ctrl registers to %p\n", ctrl->name,
450 ctrl->hw.base);
451
Shashank Babu Chinta Venkataafef8202017-04-21 13:49:56 -0700452 switch (ctrl->version) {
453 case DSI_CTRL_VERSION_1_4:
454 case DSI_CTRL_VERSION_2_0:
455 ptr = msm_ioremap(pdev, "mmss_misc", ctrl->name);
456 if (IS_ERR(ptr)) {
457 pr_err("mmss_misc base address not found for [%s]\n",
458 ctrl->name);
459 rc = PTR_ERR(ptr);
460 return rc;
461 }
462 ctrl->hw.mmss_misc_base = ptr;
463 ctrl->hw.disp_cc_base = NULL;
464 break;
465 case DSI_CTRL_VERSION_2_2:
466 ptr = msm_ioremap(pdev, "disp_cc_base", ctrl->name);
467 if (IS_ERR(ptr)) {
468 pr_err("disp_cc base address not found for [%s]\n",
469 ctrl->name);
470 rc = PTR_ERR(ptr);
471 return rc;
472 }
473 ctrl->hw.disp_cc_base = ptr;
474 ctrl->hw.mmss_misc_base = NULL;
475 break;
476 default:
477 break;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700478 }
479
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700480 return rc;
481}
482
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700483static int dsi_ctrl_clocks_deinit(struct dsi_ctrl *ctrl)
484{
485 struct dsi_core_clk_info *core = &ctrl->clk_info.core_clks;
486 struct dsi_link_clk_info *link = &ctrl->clk_info.link_clks;
487 struct dsi_clk_link_set *rcg = &ctrl->clk_info.rcg_clks;
488
489 if (core->mdp_core_clk)
490 devm_clk_put(&ctrl->pdev->dev, core->mdp_core_clk);
491 if (core->iface_clk)
492 devm_clk_put(&ctrl->pdev->dev, core->iface_clk);
493 if (core->core_mmss_clk)
494 devm_clk_put(&ctrl->pdev->dev, core->core_mmss_clk);
495 if (core->bus_clk)
496 devm_clk_put(&ctrl->pdev->dev, core->bus_clk);
Padmanabhan Komanduru2dd6ff62016-12-19 12:31:36 +0530497 if (core->mnoc_clk)
498 devm_clk_put(&ctrl->pdev->dev, core->mnoc_clk);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700499
500 memset(core, 0x0, sizeof(*core));
501
502 if (link->byte_clk)
503 devm_clk_put(&ctrl->pdev->dev, link->byte_clk);
504 if (link->pixel_clk)
505 devm_clk_put(&ctrl->pdev->dev, link->pixel_clk);
506 if (link->esc_clk)
507 devm_clk_put(&ctrl->pdev->dev, link->esc_clk);
Padmanabhan Komanduru2dd6ff62016-12-19 12:31:36 +0530508 if (link->byte_intf_clk)
509 devm_clk_put(&ctrl->pdev->dev, link->byte_intf_clk);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700510
511 memset(link, 0x0, sizeof(*link));
512
513 if (rcg->byte_clk)
514 devm_clk_put(&ctrl->pdev->dev, rcg->byte_clk);
515 if (rcg->pixel_clk)
516 devm_clk_put(&ctrl->pdev->dev, rcg->pixel_clk);
517
518 memset(rcg, 0x0, sizeof(*rcg));
519
520 return 0;
521}
522
523static int dsi_ctrl_clocks_init(struct platform_device *pdev,
524 struct dsi_ctrl *ctrl)
525{
526 int rc = 0;
527 struct dsi_core_clk_info *core = &ctrl->clk_info.core_clks;
528 struct dsi_link_clk_info *link = &ctrl->clk_info.link_clks;
529 struct dsi_clk_link_set *rcg = &ctrl->clk_info.rcg_clks;
530
531 core->mdp_core_clk = devm_clk_get(&pdev->dev, "mdp_core_clk");
532 if (IS_ERR(core->mdp_core_clk)) {
Shashank Babu Chinta Venkata74a03f12017-02-28 11:24:51 -0800533 core->mdp_core_clk = NULL;
534 pr_debug("failed to get mdp_core_clk, rc=%d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700535 }
536
537 core->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
538 if (IS_ERR(core->iface_clk)) {
Shashank Babu Chinta Venkata74a03f12017-02-28 11:24:51 -0800539 core->iface_clk = NULL;
540 pr_debug("failed to get iface_clk, rc=%d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700541 }
542
543 core->core_mmss_clk = devm_clk_get(&pdev->dev, "core_mmss_clk");
544 if (IS_ERR(core->core_mmss_clk)) {
Shashank Babu Chinta Venkata74a03f12017-02-28 11:24:51 -0800545 core->core_mmss_clk = NULL;
546 pr_debug("failed to get core_mmss_clk, rc=%d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700547 }
548
549 core->bus_clk = devm_clk_get(&pdev->dev, "bus_clk");
550 if (IS_ERR(core->bus_clk)) {
Shashank Babu Chinta Venkata74a03f12017-02-28 11:24:51 -0800551 core->bus_clk = NULL;
552 pr_debug("failed to get bus_clk, rc=%d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700553 }
554
Padmanabhan Komanduru2dd6ff62016-12-19 12:31:36 +0530555 core->mnoc_clk = devm_clk_get(&pdev->dev, "mnoc_clk");
556 if (IS_ERR(core->mnoc_clk)) {
557 core->mnoc_clk = NULL;
558 pr_debug("can't get mnoc clock, rc=%d\n", rc);
559 }
560
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700561 link->byte_clk = devm_clk_get(&pdev->dev, "byte_clk");
562 if (IS_ERR(link->byte_clk)) {
563 rc = PTR_ERR(link->byte_clk);
564 pr_err("failed to get byte_clk, rc=%d\n", rc);
565 goto fail;
566 }
567
568 link->pixel_clk = devm_clk_get(&pdev->dev, "pixel_clk");
569 if (IS_ERR(link->pixel_clk)) {
570 rc = PTR_ERR(link->pixel_clk);
571 pr_err("failed to get pixel_clk, rc=%d\n", rc);
572 goto fail;
573 }
574
Shashank Babu Chinta Venkata2f24e982017-04-21 14:57:53 -0700575 link->esc_clk = devm_clk_get(&pdev->dev, "esc_clk");
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700576 if (IS_ERR(link->esc_clk)) {
577 rc = PTR_ERR(link->esc_clk);
578 pr_err("failed to get esc_clk, rc=%d\n", rc);
579 goto fail;
580 }
581
Padmanabhan Komanduru2dd6ff62016-12-19 12:31:36 +0530582 link->byte_intf_clk = devm_clk_get(&pdev->dev, "byte_intf_clk");
583 if (IS_ERR(link->byte_intf_clk)) {
584 link->byte_intf_clk = NULL;
585 pr_debug("can't find byte intf clk, rc=%d\n", rc);
586 }
587
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700588 rcg->byte_clk = devm_clk_get(&pdev->dev, "byte_clk_rcg");
589 if (IS_ERR(rcg->byte_clk)) {
590 rc = PTR_ERR(rcg->byte_clk);
591 pr_err("failed to get byte_clk_rcg, rc=%d\n", rc);
592 goto fail;
593 }
594
595 rcg->pixel_clk = devm_clk_get(&pdev->dev, "pixel_clk_rcg");
596 if (IS_ERR(rcg->pixel_clk)) {
597 rc = PTR_ERR(rcg->pixel_clk);
598 pr_err("failed to get pixel_clk_rcg, rc=%d\n", rc);
599 goto fail;
600 }
601
602 return 0;
603fail:
604 dsi_ctrl_clocks_deinit(ctrl);
605 return rc;
606}
607
608static int dsi_ctrl_supplies_deinit(struct dsi_ctrl *ctrl)
609{
610 int i = 0;
611 int rc = 0;
612 struct dsi_regulator_info *regs;
613
614 regs = &ctrl->pwr_info.digital;
615 for (i = 0; i < regs->count; i++) {
616 if (!regs->vregs[i].vreg)
617 pr_err("vreg is NULL, should not reach here\n");
618 else
619 devm_regulator_put(regs->vregs[i].vreg);
620 }
621
622 regs = &ctrl->pwr_info.host_pwr;
623 for (i = 0; i < regs->count; i++) {
624 if (!regs->vregs[i].vreg)
625 pr_err("vreg is NULL, should not reach here\n");
626 else
627 devm_regulator_put(regs->vregs[i].vreg);
628 }
629
630 if (!ctrl->pwr_info.host_pwr.vregs) {
631 devm_kfree(&ctrl->pdev->dev, ctrl->pwr_info.host_pwr.vregs);
632 ctrl->pwr_info.host_pwr.vregs = NULL;
633 ctrl->pwr_info.host_pwr.count = 0;
634 }
635
636 if (!ctrl->pwr_info.digital.vregs) {
637 devm_kfree(&ctrl->pdev->dev, ctrl->pwr_info.digital.vregs);
638 ctrl->pwr_info.digital.vregs = NULL;
639 ctrl->pwr_info.digital.count = 0;
640 }
641
642 return rc;
643}
644
645static int dsi_ctrl_supplies_init(struct platform_device *pdev,
646 struct dsi_ctrl *ctrl)
647{
648 int rc = 0;
649 int i = 0;
650 struct dsi_regulator_info *regs;
651 struct regulator *vreg = NULL;
652
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530653 rc = dsi_pwr_get_dt_vreg_data(&pdev->dev,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700654 &ctrl->pwr_info.digital,
655 "qcom,core-supply-entries");
Shashank Babu Chinta Venkata9a5a7b92017-04-24 18:22:41 -0700656 if (rc)
657 pr_debug("failed to get digital supply, rc = %d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700658
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530659 rc = dsi_pwr_get_dt_vreg_data(&pdev->dev,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700660 &ctrl->pwr_info.host_pwr,
661 "qcom,ctrl-supply-entries");
662 if (rc) {
663 pr_err("failed to get host power supplies, rc = %d\n", rc);
664 goto error_digital;
665 }
666
667 regs = &ctrl->pwr_info.digital;
668 for (i = 0; i < regs->count; i++) {
669 vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name);
670 if (IS_ERR(vreg)) {
671 pr_err("failed to get %s regulator\n",
672 regs->vregs[i].vreg_name);
673 rc = PTR_ERR(vreg);
674 goto error_host_pwr;
675 }
676 regs->vregs[i].vreg = vreg;
677 }
678
679 regs = &ctrl->pwr_info.host_pwr;
680 for (i = 0; i < regs->count; i++) {
681 vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name);
682 if (IS_ERR(vreg)) {
683 pr_err("failed to get %s regulator\n",
684 regs->vregs[i].vreg_name);
685 for (--i; i >= 0; i--)
686 devm_regulator_put(regs->vregs[i].vreg);
687 rc = PTR_ERR(vreg);
688 goto error_digital_put;
689 }
690 regs->vregs[i].vreg = vreg;
691 }
692
693 return rc;
694
695error_digital_put:
696 regs = &ctrl->pwr_info.digital;
697 for (i = 0; i < regs->count; i++)
698 devm_regulator_put(regs->vregs[i].vreg);
699error_host_pwr:
700 devm_kfree(&pdev->dev, ctrl->pwr_info.host_pwr.vregs);
701 ctrl->pwr_info.host_pwr.vregs = NULL;
702 ctrl->pwr_info.host_pwr.count = 0;
703error_digital:
Shashank Babu Chinta Venkata9a5a7b92017-04-24 18:22:41 -0700704 if (ctrl->pwr_info.digital.vregs)
705 devm_kfree(&pdev->dev, ctrl->pwr_info.digital.vregs);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700706 ctrl->pwr_info.digital.vregs = NULL;
707 ctrl->pwr_info.digital.count = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700708 return rc;
709}
710
711static int dsi_ctrl_axi_bus_client_init(struct platform_device *pdev,
712 struct dsi_ctrl *ctrl)
713{
714 int rc = 0;
715 struct dsi_ctrl_bus_scale_info *bus = &ctrl->axi_bus_info;
716
717 bus->bus_scale_table = msm_bus_cl_get_pdata(pdev);
718 if (IS_ERR_OR_NULL(bus->bus_scale_table)) {
719 rc = PTR_ERR(bus->bus_scale_table);
Shashank Babu Chinta Venkatacf411332017-05-10 17:30:08 -0700720 pr_debug("msm_bus_cl_get_pdata() failed, rc = %d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700721 bus->bus_scale_table = NULL;
722 return rc;
723 }
724
725 bus->bus_handle = msm_bus_scale_register_client(bus->bus_scale_table);
726 if (!bus->bus_handle) {
727 rc = -EINVAL;
728 pr_err("failed to register axi bus client\n");
729 }
730
731 return rc;
732}
733
734static int dsi_ctrl_axi_bus_client_deinit(struct dsi_ctrl *ctrl)
735{
736 struct dsi_ctrl_bus_scale_info *bus = &ctrl->axi_bus_info;
737
738 if (bus->bus_handle) {
739 msm_bus_scale_unregister_client(bus->bus_handle);
740
741 bus->bus_handle = 0;
742 }
743
744 return 0;
745}
746
747static int dsi_ctrl_validate_panel_info(struct dsi_ctrl *dsi_ctrl,
748 struct dsi_host_config *config)
749{
750 int rc = 0;
751 struct dsi_host_common_cfg *host_cfg = &config->common_config;
752
753 if (config->panel_mode >= DSI_OP_MODE_MAX) {
754 pr_err("Invalid dsi operation mode (%d)\n", config->panel_mode);
755 rc = -EINVAL;
756 goto err;
757 }
758
759 if ((host_cfg->data_lanes & (DSI_CLOCK_LANE - 1)) == 0) {
760 pr_err("No data lanes are enabled\n");
761 rc = -EINVAL;
762 goto err;
763 }
764err:
765 return rc;
766}
767
768static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530769 struct dsi_host_config *config, void *clk_handle)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700770{
771 int rc = 0;
772 u32 num_of_lanes = 0;
773 u32 bpp = 3;
774 u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane,
775 byte_clk_rate;
776 struct dsi_host_common_cfg *host_cfg = &config->common_config;
777 struct dsi_mode_info *timing = &config->video_timing;
778
779 if (host_cfg->data_lanes & DSI_DATA_LANE_0)
780 num_of_lanes++;
781 if (host_cfg->data_lanes & DSI_DATA_LANE_1)
782 num_of_lanes++;
783 if (host_cfg->data_lanes & DSI_DATA_LANE_2)
784 num_of_lanes++;
785 if (host_cfg->data_lanes & DSI_DATA_LANE_3)
786 num_of_lanes++;
787
Vara Reddy812bd722017-09-20 07:19:19 -0700788 if (config->bit_clk_rate_hz == 0) {
789 h_period = DSI_H_TOTAL_DSC(timing);
790 v_period = DSI_V_TOTAL(timing);
791 bit_rate = h_period * v_period * timing->refresh_rate * bpp * 8;
792 } else {
793 bit_rate = config->bit_clk_rate_hz * num_of_lanes;
794 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700795
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700796 bit_rate_per_lane = bit_rate;
797 do_div(bit_rate_per_lane, num_of_lanes);
798 pclk_rate = bit_rate;
799 do_div(pclk_rate, (8 * bpp));
800 byte_clk_rate = bit_rate_per_lane;
801 do_div(byte_clk_rate, 8);
802 pr_debug("bit_clk_rate = %llu, bit_clk_rate_per_lane = %llu\n",
803 bit_rate, bit_rate_per_lane);
804 pr_debug("byte_clk_rate = %llu, pclk_rate = %llu\n",
805 byte_clk_rate, pclk_rate);
806
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530807 dsi_ctrl->clk_freq.byte_clk_rate = byte_clk_rate;
808 dsi_ctrl->clk_freq.pix_clk_rate = pclk_rate;
809 dsi_ctrl->clk_freq.esc_clk_rate = config->esc_clk_rate_hz;
810
811 rc = dsi_clk_set_link_frequencies(clk_handle, dsi_ctrl->clk_freq,
Alexander Beykun32a6a182017-02-27 17:46:51 -0500812 dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700813 if (rc)
814 pr_err("Failed to update link frequencies\n");
815
816 return rc;
817}
818
819static int dsi_ctrl_enable_supplies(struct dsi_ctrl *dsi_ctrl, bool enable)
820{
821 int rc = 0;
822
823 if (enable) {
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530824 if (!dsi_ctrl->current_state.host_initialized) {
825 rc = dsi_pwr_enable_regulator(
826 &dsi_ctrl->pwr_info.host_pwr, true);
827 if (rc) {
828 pr_err("failed to enable host power regs\n");
829 goto error;
830 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700831 }
832
833 rc = dsi_pwr_enable_regulator(&dsi_ctrl->pwr_info.digital,
834 true);
835 if (rc) {
836 pr_err("failed to enable gdsc, rc=%d\n", rc);
837 (void)dsi_pwr_enable_regulator(
838 &dsi_ctrl->pwr_info.host_pwr,
839 false
840 );
841 goto error;
842 }
843 } else {
844 rc = dsi_pwr_enable_regulator(&dsi_ctrl->pwr_info.digital,
845 false);
846 if (rc) {
847 pr_err("failed to disable gdsc, rc=%d\n", rc);
848 goto error;
849 }
850
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530851 if (!dsi_ctrl->current_state.host_initialized) {
852 rc = dsi_pwr_enable_regulator(
853 &dsi_ctrl->pwr_info.host_pwr, false);
854 if (rc) {
855 pr_err("failed to disable host power regs\n");
856 goto error;
857 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700858 }
859 }
860error:
861 return rc;
862}
863
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700864static int dsi_ctrl_copy_and_pad_cmd(struct dsi_ctrl *dsi_ctrl,
865 const struct mipi_dsi_packet *packet,
866 u8 **buffer,
867 u32 *size)
868{
869 int rc = 0;
870 u8 *buf = NULL;
871 u32 len, i;
872
873 len = packet->size;
874 len += 0x3; len &= ~0x03; /* Align to 32 bits */
875
876 buf = devm_kzalloc(&dsi_ctrl->pdev->dev, len * sizeof(u8), GFP_KERNEL);
877 if (!buf)
878 return -ENOMEM;
879
880 for (i = 0; i < len; i++) {
881 if (i >= packet->size)
882 buf[i] = 0xFF;
883 else if (i < sizeof(packet->header))
884 buf[i] = packet->header[i];
885 else
886 buf[i] = packet->payload[i - sizeof(packet->header)];
887 }
888
889 if (packet->payload_length > 0)
890 buf[3] |= BIT(6);
891
Sandeep Panda79450002017-05-08 17:14:24 +0530892
893 /* send embedded BTA for read commands */
894 if ((buf[2] & 0x3f) == MIPI_DSI_DCS_READ)
895 buf[3] |= BIT(5);
896
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700897 *buffer = buf;
898 *size = len;
899
900 return rc;
901}
902
Sandeep Panda5c51ea62017-08-02 13:50:15 +0530903static void dsi_ctrl_wait_for_video_done(struct dsi_ctrl *dsi_ctrl)
904{
905 u32 v_total = 0, v_blank = 0, sleep_ms = 0, fps = 0, ret;
906 struct dsi_mode_info *timing;
907
Sandeep Pandaa2a3c8c2017-07-09 02:10:44 +0530908 /**
909 * No need to wait if the panel is not video mode or
910 * if DSI controller supports command DMA scheduling or
911 * if we are sending init commands.
912 */
913 if ((dsi_ctrl->host_config.panel_mode != DSI_OP_VIDEO_MODE) ||
914 (dsi_ctrl->version >= DSI_CTRL_VERSION_2_2) ||
915 (dsi_ctrl->current_state.vid_engine_state !=
916 DSI_CTRL_ENGINE_ON))
Sandeep Panda5c51ea62017-08-02 13:50:15 +0530917 return;
918
919 dsi_ctrl->hw.ops.clear_interrupt_status(&dsi_ctrl->hw,
920 DSI_VIDEO_MODE_FRAME_DONE);
921
922 dsi_ctrl_enable_status_interrupt(dsi_ctrl,
923 DSI_SINT_VIDEO_MODE_FRAME_DONE, NULL);
924 reinit_completion(&dsi_ctrl->irq_info.vid_frame_done);
925 ret = wait_for_completion_timeout(
926 &dsi_ctrl->irq_info.vid_frame_done,
927 msecs_to_jiffies(DSI_CTRL_TX_TO_MS));
928 if (ret <= 0)
929 pr_debug("wait for video done failed\n");
930 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
931 DSI_SINT_VIDEO_MODE_FRAME_DONE);
932
933 timing = &(dsi_ctrl->host_config.video_timing);
934 v_total = timing->v_sync_width + timing->v_back_porch +
935 timing->v_front_porch + timing->v_active;
936 v_blank = timing->v_sync_width + timing->v_back_porch;
937 fps = timing->refresh_rate;
938
939 sleep_ms = CEIL((v_blank * 1000), (v_total * fps)) + 1;
940 udelay(sleep_ms * 1000);
941}
942
Vara Reddydbeab892017-11-17 16:38:16 -0800943void dsi_message_setup_tx_mode(struct dsi_ctrl *dsi_ctrl,
944 u32 cmd_len,
945 u32 *flags)
946{
947 /**
948 * Setup the mode of transmission
949 * override cmd fetch mode during secure session
950 */
951 if (dsi_ctrl->secure_mode) {
952 *flags &= ~DSI_CTRL_CMD_FETCH_MEMORY;
953 *flags |= DSI_CTRL_CMD_FIFO_STORE;
954 pr_debug("[%s] override to TPG during secure session\n",
955 dsi_ctrl->name);
956 return;
957 }
958
959 /* Check to see if cmd len plus header is greater than fifo size */
960 if ((cmd_len + 4) > DSI_EMBEDDED_MODE_DMA_MAX_SIZE_BYTES) {
961 *flags |= DSI_CTRL_CMD_NON_EMBEDDED_MODE;
962 pr_debug("[%s] override to non-embedded mode,cmd len =%d\n",
963 dsi_ctrl->name, cmd_len);
964 return;
965 }
966}
967
968int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl,
969 u32 cmd_len,
970 u32 *flags)
971{
972 int rc = 0;
973
974 if (*flags & DSI_CTRL_CMD_FIFO_STORE) {
975 /* if command size plus header is greater than fifo size */
976 if ((cmd_len + 4) > DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE) {
977 pr_err("Cannot transfer Cmd in FIFO config\n");
978 return -ENOTSUPP;
979 }
980 if (!dsi_ctrl->hw.ops.kickoff_fifo_command) {
981 pr_err("Cannot transfer command,ops not defined\n");
982 return -ENOTSUPP;
983 }
984 }
985
986 if (*flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
987 if (*flags & DSI_CTRL_CMD_BROADCAST) {
988 pr_err("Non embedded not supported with broadcast\n");
989 return -ENOTSUPP;
990 }
991 if (!dsi_ctrl->hw.ops.kickoff_command_non_embedded_mode) {
992 pr_err(" Cannot transfer command,ops not defined\n");
993 return -ENOTSUPP;
994 }
995 }
996 return rc;
997}
998
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700999static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
1000 const struct mipi_dsi_msg *msg,
1001 u32 flags)
1002{
Clarence Ip80ada7f2017-05-04 09:55:21 -07001003 int rc = 0, ret = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001004 struct mipi_dsi_packet packet;
1005 struct dsi_ctrl_cmd_dma_fifo_info cmd;
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07001006 struct dsi_ctrl_cmd_dma_info cmd_mem;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001007 u32 hw_flags = 0;
1008 u32 length = 0;
1009 u8 *buffer = NULL;
Sandeep Pandaa2a3c8c2017-07-09 02:10:44 +05301010 u32 cnt = 0, line_no = 0x1;
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07001011 u8 *cmdbuf;
Sandeep Pandaa2a3c8c2017-07-09 02:10:44 +05301012 struct dsi_mode_info *timing;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001013
Vara Reddydbeab892017-11-17 16:38:16 -08001014 /* Select the tx mode to transfer the command */
1015 dsi_message_setup_tx_mode(dsi_ctrl, msg->tx_len, &flags);
1016
1017 /* Validate the mode before sending the command */
1018 rc = dsi_message_validate_tx_mode(dsi_ctrl, msg->tx_len, &flags);
1019 if (rc) {
1020 pr_err(" Cmd tx validation failed, cannot transfer cmd\n");
1021 rc = -ENOTSUPP;
1022 goto error;
1023 }
1024
1025 if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
1026 cmd_mem.offset = dsi_ctrl->cmd_buffer_iova;
1027 cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ?
1028 true : false;
1029 cmd_mem.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ?
1030 true : false;
1031 cmd_mem.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
1032 true : false;
1033 cmd_mem.datatype = msg->type;
1034 cmd_mem.length = msg->tx_len;
1035
1036 dsi_ctrl->cmd_len = msg->tx_len;
1037 memcpy(dsi_ctrl->vaddr, msg->tx_buf, msg->tx_len);
1038 pr_debug(" non-embedded mode , size of command =%zd\n",
1039 msg->tx_len);
1040
1041 goto kickoff;
Veera Sundaram Sankarand2a93942017-10-20 12:44:18 -07001042 }
1043
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001044 rc = mipi_dsi_create_packet(&packet, msg);
1045 if (rc) {
1046 pr_err("Failed to create message packet, rc=%d\n", rc);
1047 goto error;
1048 }
1049
Vara Reddy326612b2017-09-20 04:41:10 -07001050 rc = dsi_ctrl_copy_and_pad_cmd(dsi_ctrl,
1051 &packet,
1052 &buffer,
1053 &length);
1054 if (rc) {
1055 pr_err("[%s] failed to copy message, rc=%d\n",
1056 dsi_ctrl->name, rc);
1057 goto error;
1058 }
1059
1060 if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND))
1061 buffer[3] |= BIT(7);//set the last cmd bit in header.
1062
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07001063 if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
Vara Reddydbeab892017-11-17 16:38:16 -08001064 /* Embedded mode config is selected */
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07001065 cmd_mem.offset = dsi_ctrl->cmd_buffer_iova;
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07001066 cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ?
1067 true : false;
1068 cmd_mem.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ?
1069 true : false;
1070 cmd_mem.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
1071 true : false;
1072
1073 cmdbuf = (u8 *)(dsi_ctrl->vaddr);
Vara Reddy326612b2017-09-20 04:41:10 -07001074
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07001075 for (cnt = 0; cnt < length; cnt++)
Vara Reddy326612b2017-09-20 04:41:10 -07001076 cmdbuf[dsi_ctrl->cmd_len + cnt] = buffer[cnt];
1077
1078 dsi_ctrl->cmd_len += length;
1079
1080 if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) {
1081 goto error;
1082 } else {
1083 cmd_mem.length = dsi_ctrl->cmd_len;
1084 dsi_ctrl->cmd_len = 0;
1085 }
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07001086
1087 } else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001088 cmd.command = (u32 *)buffer;
1089 cmd.size = length;
1090 cmd.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ?
1091 true : false;
1092 cmd.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ?
1093 true : false;
1094 cmd.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
1095 true : false;
1096 }
1097
Vara Reddydbeab892017-11-17 16:38:16 -08001098kickoff:
Sandeep Pandaa2a3c8c2017-07-09 02:10:44 +05301099 timing = &(dsi_ctrl->host_config.video_timing);
1100 if (timing)
1101 line_no += timing->v_back_porch + timing->v_sync_width +
1102 timing->v_active;
1103 if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) &&
1104 dsi_ctrl->hw.ops.schedule_dma_cmd &&
1105 (dsi_ctrl->current_state.vid_engine_state ==
1106 DSI_CTRL_ENGINE_ON))
1107 dsi_ctrl->hw.ops.schedule_dma_cmd(&dsi_ctrl->hw,
1108 line_no);
1109
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001110 hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ?
1111 DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER : 0;
1112
Vara Reddy326612b2017-09-20 04:41:10 -07001113 if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND))
1114 hw_flags |= DSI_CTRL_CMD_LAST_COMMAND;
1115
Clarence Ip80ada7f2017-05-04 09:55:21 -07001116 if (flags & DSI_CTRL_CMD_DEFER_TRIGGER) {
1117 if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
Vara Reddydbeab892017-11-17 16:38:16 -08001118 if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
1119 dsi_ctrl->hw.ops.
1120 kickoff_command_non_embedded_mode(
1121 &dsi_ctrl->hw,
Clarence Ip80ada7f2017-05-04 09:55:21 -07001122 &cmd_mem,
1123 hw_flags);
Vara Reddydbeab892017-11-17 16:38:16 -08001124 } else {
1125 dsi_ctrl->hw.ops.kickoff_command(
1126 &dsi_ctrl->hw,
1127 &cmd_mem,
1128 hw_flags);
1129 }
Clarence Ip80ada7f2017-05-04 09:55:21 -07001130 } else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
1131 dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw,
1132 &cmd,
1133 hw_flags);
1134 }
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07001135 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001136
1137 if (!(flags & DSI_CTRL_CMD_DEFER_TRIGGER)) {
Sandeep Panda5c51ea62017-08-02 13:50:15 +05301138 dsi_ctrl_wait_for_video_done(dsi_ctrl);
Clarence Ip80ada7f2017-05-04 09:55:21 -07001139 dsi_ctrl_enable_status_interrupt(dsi_ctrl,
1140 DSI_SINT_CMD_MODE_DMA_DONE, NULL);
Sandeep Panda11b20d82017-06-19 12:57:27 +05301141 if (dsi_ctrl->hw.ops.mask_error_intr)
1142 dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
1143 BIT(DSI_FIFO_OVERFLOW), true);
Clarence Ip80ada7f2017-05-04 09:55:21 -07001144 reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001145
Clarence Ip80ada7f2017-05-04 09:55:21 -07001146 if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
Vara Reddydbeab892017-11-17 16:38:16 -08001147 if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
1148 dsi_ctrl->hw.ops.
1149 kickoff_command_non_embedded_mode(
1150 &dsi_ctrl->hw,
1151 &cmd_mem,
1152 hw_flags);
1153 } else {
1154 dsi_ctrl->hw.ops.kickoff_command(
1155 &dsi_ctrl->hw,
1156 &cmd_mem,
1157 hw_flags);
1158 }
Clarence Ip80ada7f2017-05-04 09:55:21 -07001159 } else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
1160 dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw,
1161 &cmd,
1162 hw_flags);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001163 }
Clarence Ip80ada7f2017-05-04 09:55:21 -07001164
1165 ret = wait_for_completion_timeout(
1166 &dsi_ctrl->irq_info.cmd_dma_done,
1167 msecs_to_jiffies(DSI_CTRL_TX_TO_MS));
1168
1169 if (ret == 0) {
Vara Reddyeeba94a2017-10-08 22:36:25 -07001170 u32 status = dsi_ctrl->hw.ops.get_interrupt_status(
1171 &dsi_ctrl->hw);
Clarence Ip80ada7f2017-05-04 09:55:21 -07001172 u32 mask = DSI_CMD_MODE_DMA_DONE;
1173
1174 if (status & mask) {
1175 status |= (DSI_CMD_MODE_DMA_DONE |
1176 DSI_BTA_DONE);
1177 dsi_ctrl->hw.ops.clear_interrupt_status(
1178 &dsi_ctrl->hw,
1179 status);
1180 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
1181 DSI_SINT_CMD_MODE_DMA_DONE);
1182 complete_all(&dsi_ctrl->irq_info.cmd_dma_done);
1183 pr_warn("dma_tx done but irq not triggered\n");
1184 } else {
1185 rc = -ETIMEDOUT;
1186 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
1187 DSI_SINT_CMD_MODE_DMA_DONE);
1188 pr_err("[DSI_%d]Command transfer failed\n",
1189 dsi_ctrl->cell_index);
1190 }
1191 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001192
Sandeep Panda11b20d82017-06-19 12:57:27 +05301193 if (dsi_ctrl->hw.ops.mask_error_intr)
1194 dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
1195 BIT(DSI_FIFO_OVERFLOW), false);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001196 dsi_ctrl->hw.ops.reset_cmd_fifo(&dsi_ctrl->hw);
Vara Reddydbeab892017-11-17 16:38:16 -08001197
1198 /*
1199 * DSI 2.2 needs a soft reset whenever we send non-embedded
1200 * mode command followed by embedded mode. Otherwise it will
1201 * result in smmu write faults with DSI as client.
1202 */
1203 if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
1204 dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
1205 dsi_ctrl->cmd_len = 0;
1206 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001207 }
1208error:
1209 if (buffer)
1210 devm_kfree(&dsi_ctrl->pdev->dev, buffer);
1211 return rc;
1212}
1213
1214static int dsi_set_max_return_size(struct dsi_ctrl *dsi_ctrl,
1215 const struct mipi_dsi_msg *rx_msg,
1216 u32 size)
1217{
1218 int rc = 0;
1219 u8 tx[2] = { (u8)(size & 0xFF), (u8)(size >> 8) };
Sandeep Panda79450002017-05-08 17:14:24 +05301220 u32 flags = DSI_CTRL_CMD_FETCH_MEMORY;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001221 struct mipi_dsi_msg msg = {
1222 .channel = rx_msg->channel,
1223 .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
1224 .tx_len = 2,
1225 .tx_buf = tx,
1226 };
1227
Sandeep Panda79450002017-05-08 17:14:24 +05301228 rc = dsi_message_tx(dsi_ctrl, &msg, flags);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001229 if (rc)
1230 pr_err("failed to send max return size packet, rc=%d\n", rc);
1231
1232 return rc;
1233}
1234
Sandeep Panda79450002017-05-08 17:14:24 +05301235/* Helper functions to support DCS read operation */
1236static int dsi_parse_short_read1_resp(const struct mipi_dsi_msg *msg,
1237 unsigned char *buff)
1238{
1239 u8 *data = msg->rx_buf;
1240 int read_len = 1;
1241
1242 if (!data)
1243 return 0;
1244
1245 /* remove dcs type */
1246 if (msg->rx_len >= 1)
1247 data[0] = buff[1];
1248 else
1249 read_len = 0;
1250
1251 return read_len;
1252}
1253
1254static int dsi_parse_short_read2_resp(const struct mipi_dsi_msg *msg,
1255 unsigned char *buff)
1256{
1257 u8 *data = msg->rx_buf;
1258 int read_len = 2;
1259
1260 if (!data)
1261 return 0;
1262
1263 /* remove dcs type */
1264 if (msg->rx_len >= 2) {
1265 data[0] = buff[1];
1266 data[1] = buff[2];
1267 } else {
1268 read_len = 0;
1269 }
1270
1271 return read_len;
1272}
1273
1274static int dsi_parse_long_read_resp(const struct mipi_dsi_msg *msg,
1275 unsigned char *buff)
1276{
1277 if (!msg->rx_buf)
1278 return 0;
1279
1280 /* remove dcs type */
1281 if (msg->rx_buf && msg->rx_len)
1282 memcpy(msg->rx_buf, buff + 4, msg->rx_len);
1283
1284 return msg->rx_len;
1285}
1286
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001287static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl,
1288 const struct mipi_dsi_msg *msg,
1289 u32 flags)
1290{
1291 int rc = 0;
Sandeep Panda79450002017-05-08 17:14:24 +05301292 u32 rd_pkt_size, total_read_len, hw_read_cnt;
1293 u32 current_read_len = 0, total_bytes_read = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001294 bool short_resp = false;
1295 bool read_done = false;
Sandeep Panda79450002017-05-08 17:14:24 +05301296 u32 dlen, diff, rlen = msg->rx_len;
1297 unsigned char *buff;
1298 char cmd;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001299
1300 if (msg->rx_len <= 2) {
1301 short_resp = true;
1302 rd_pkt_size = msg->rx_len;
1303 total_read_len = 4;
1304 } else {
1305 short_resp = false;
1306 current_read_len = 10;
1307 if (msg->rx_len < current_read_len)
1308 rd_pkt_size = msg->rx_len;
1309 else
1310 rd_pkt_size = current_read_len;
1311
1312 total_read_len = current_read_len + 6;
1313 }
Sandeep Panda79450002017-05-08 17:14:24 +05301314 buff = msg->rx_buf;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001315
1316 while (!read_done) {
1317 rc = dsi_set_max_return_size(dsi_ctrl, msg, rd_pkt_size);
1318 if (rc) {
1319 pr_err("Failed to set max return packet size, rc=%d\n",
1320 rc);
1321 goto error;
1322 }
1323
Sandeep Panda79450002017-05-08 17:14:24 +05301324 /* clear RDBK_DATA registers before proceeding */
1325 dsi_ctrl->hw.ops.clear_rdbk_register(&dsi_ctrl->hw);
1326
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001327 rc = dsi_message_tx(dsi_ctrl, msg, flags);
1328 if (rc) {
1329 pr_err("Message transmission failed, rc=%d\n", rc);
1330 goto error;
1331 }
1332
Sandeep Panda79450002017-05-08 17:14:24 +05301333 dlen = dsi_ctrl->hw.ops.get_cmd_read_data(&dsi_ctrl->hw,
1334 buff, total_bytes_read,
1335 total_read_len, rd_pkt_size,
1336 &hw_read_cnt);
1337 if (!dlen)
1338 goto error;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001339
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001340 if (short_resp)
Sandeep Panda79450002017-05-08 17:14:24 +05301341 break;
1342
1343 if (rlen <= current_read_len) {
1344 diff = current_read_len - rlen;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001345 read_done = true;
Sandeep Panda79450002017-05-08 17:14:24 +05301346 } else {
1347 diff = 0;
1348 rlen -= current_read_len;
1349 }
1350
1351 dlen -= 2; /* 2 bytes of CRC */
1352 dlen -= diff;
1353 buff += dlen;
1354 total_bytes_read += dlen;
1355 if (!read_done) {
1356 current_read_len = 14; /* Not first read */
1357 if (rlen < current_read_len)
1358 rd_pkt_size += rlen;
1359 else
1360 rd_pkt_size += current_read_len;
1361 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001362 }
Sandeep Panda79450002017-05-08 17:14:24 +05301363
1364 if (hw_read_cnt < 16 && !short_resp)
1365 buff = msg->rx_buf + (16 - hw_read_cnt);
1366 else
1367 buff = msg->rx_buf;
1368
1369 /* parse the data read from panel */
1370 cmd = buff[0];
1371 switch (cmd) {
1372 case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
1373 pr_err("Rx ACK_ERROR\n");
1374 rc = 0;
1375 break;
1376 case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
1377 case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
1378 rc = dsi_parse_short_read1_resp(msg, buff);
1379 break;
1380 case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
1381 case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
1382 rc = dsi_parse_short_read2_resp(msg, buff);
1383 break;
1384 case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
1385 case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
1386 rc = dsi_parse_long_read_resp(msg, buff);
1387 break;
1388 default:
1389 pr_warn("Invalid response\n");
1390 rc = 0;
1391 }
1392
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001393error:
1394 return rc;
1395}
1396
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001397static int dsi_enable_ulps(struct dsi_ctrl *dsi_ctrl)
1398{
1399 int rc = 0;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301400 u32 lanes = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001401 u32 ulps_lanes;
1402
1403 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE)
1404 lanes = dsi_ctrl->host_config.common_config.data_lanes;
1405
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05301406 rc = dsi_ctrl->hw.ops.wait_for_lane_idle(&dsi_ctrl->hw, lanes);
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301407 if (rc) {
1408 pr_err("lanes not entering idle, skip ULPS\n");
1409 return rc;
1410 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001411
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05301412 if (!dsi_ctrl->hw.ops.ulps_ops.ulps_request ||
1413 !dsi_ctrl->hw.ops.ulps_ops.ulps_exit) {
1414 pr_debug("DSI controller ULPS ops not present\n");
1415 return 0;
1416 }
1417
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301418 lanes |= DSI_CLOCK_LANE;
1419 dsi_ctrl->hw.ops.ulps_ops.ulps_request(&dsi_ctrl->hw, lanes);
1420
1421 ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001422
1423 if ((lanes & ulps_lanes) != lanes) {
1424 pr_err("Failed to enter ULPS, request=0x%x, actual=0x%x\n",
1425 lanes, ulps_lanes);
1426 rc = -EIO;
1427 }
1428
1429 return rc;
1430}
1431
1432static int dsi_disable_ulps(struct dsi_ctrl *dsi_ctrl)
1433{
1434 int rc = 0;
1435 u32 ulps_lanes, lanes = 0;
1436
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05301437 dsi_ctrl->hw.ops.clear_phy0_ln_err(&dsi_ctrl->hw);
1438
1439 if (!dsi_ctrl->hw.ops.ulps_ops.ulps_request ||
1440 !dsi_ctrl->hw.ops.ulps_ops.ulps_exit) {
1441 pr_debug("DSI controller ULPS ops not present\n");
1442 return 0;
1443 }
1444
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001445 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE)
1446 lanes = dsi_ctrl->host_config.common_config.data_lanes;
1447
1448 lanes |= DSI_CLOCK_LANE;
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05301449
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301450 ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001451
1452 if ((lanes & ulps_lanes) != lanes)
1453 pr_err("Mismatch between lanes in ULPS\n");
1454
1455 lanes &= ulps_lanes;
1456
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301457 dsi_ctrl->hw.ops.ulps_ops.ulps_exit(&dsi_ctrl->hw, lanes);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001458
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301459 ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001460 if (ulps_lanes & lanes) {
1461 pr_err("Lanes (0x%x) stuck in ULPS\n", ulps_lanes);
1462 rc = -EIO;
1463 }
1464
1465 return rc;
1466}
1467
1468static int dsi_ctrl_drv_state_init(struct dsi_ctrl *dsi_ctrl)
1469{
1470 int rc = 0;
1471 bool splash_enabled = false;
1472 struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state;
1473
1474 if (!splash_enabled) {
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301475 state->power_state = DSI_CTRL_POWER_VREG_OFF;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001476 state->cmd_engine_state = DSI_CTRL_ENGINE_OFF;
1477 state->vid_engine_state = DSI_CTRL_ENGINE_OFF;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001478 }
1479
1480 return rc;
1481}
1482
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001483static int dsi_ctrl_buffer_deinit(struct dsi_ctrl *dsi_ctrl)
1484{
Jordan Croused8e96522017-02-13 10:14:16 -07001485 struct msm_gem_address_space *aspace = NULL;
1486
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001487 if (dsi_ctrl->tx_cmd_buf) {
Jordan Croused8e96522017-02-13 10:14:16 -07001488 aspace = dsi_ctrl_get_aspace(dsi_ctrl,
1489 MSM_SMMU_DOMAIN_UNSECURE);
1490 if (!aspace) {
1491 pr_err("failed to get address space\n");
1492 return -ENOMEM;
1493 }
1494
1495 msm_gem_put_iova(dsi_ctrl->tx_cmd_buf, aspace);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001496
Lloyd Atkinsonbc0f5cb2017-09-13 09:29:10 -04001497 mutex_lock(&dsi_ctrl->drm_dev->struct_mutex);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001498 msm_gem_free_object(dsi_ctrl->tx_cmd_buf);
Lloyd Atkinsonbc0f5cb2017-09-13 09:29:10 -04001499 mutex_unlock(&dsi_ctrl->drm_dev->struct_mutex);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001500 dsi_ctrl->tx_cmd_buf = NULL;
1501 }
1502
1503 return 0;
1504}
1505
1506int dsi_ctrl_buffer_init(struct dsi_ctrl *dsi_ctrl)
1507{
1508 int rc = 0;
1509 u32 iova = 0;
Jordan Croused8e96522017-02-13 10:14:16 -07001510 struct msm_gem_address_space *aspace = NULL;
1511
1512 aspace = dsi_ctrl_get_aspace(dsi_ctrl, MSM_SMMU_DOMAIN_UNSECURE);
1513 if (!aspace) {
1514 pr_err("failed to get address space\n");
1515 return -ENOMEM;
1516 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001517
1518 dsi_ctrl->tx_cmd_buf = msm_gem_new(dsi_ctrl->drm_dev,
1519 SZ_4K,
1520 MSM_BO_UNCACHED);
1521
1522 if (IS_ERR(dsi_ctrl->tx_cmd_buf)) {
1523 rc = PTR_ERR(dsi_ctrl->tx_cmd_buf);
1524 pr_err("failed to allocate gem, rc=%d\n", rc);
1525 dsi_ctrl->tx_cmd_buf = NULL;
1526 goto error;
1527 }
1528
1529 dsi_ctrl->cmd_buffer_size = SZ_4K;
1530
Jordan Croused8e96522017-02-13 10:14:16 -07001531 rc = msm_gem_get_iova(dsi_ctrl->tx_cmd_buf, aspace, &iova);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001532 if (rc) {
1533 pr_err("failed to get iova, rc=%d\n", rc);
1534 (void)dsi_ctrl_buffer_deinit(dsi_ctrl);
1535 goto error;
1536 }
1537
1538 if (iova & 0x07) {
1539 pr_err("Tx command buffer is not 8 byte aligned\n");
1540 rc = -ENOTSUPP;
1541 (void)dsi_ctrl_buffer_deinit(dsi_ctrl);
1542 goto error;
1543 }
1544error:
1545 return rc;
1546}
1547
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301548static int dsi_enable_io_clamp(struct dsi_ctrl *dsi_ctrl,
1549 bool enable, bool ulps_enabled)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001550{
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001551 u32 lanes = 0;
1552
1553 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE)
1554 lanes = dsi_ctrl->host_config.common_config.data_lanes;
1555
1556 lanes |= DSI_CLOCK_LANE;
1557
1558 if (enable)
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301559 dsi_ctrl->hw.ops.clamp_enable(&dsi_ctrl->hw,
1560 lanes, ulps_enabled);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001561 else
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301562 dsi_ctrl->hw.ops.clamp_disable(&dsi_ctrl->hw,
1563 lanes, ulps_enabled);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001564
1565 return 0;
1566}
1567
Dhaval Patelabfaa082017-07-28 12:41:10 -07001568static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl,
1569 struct device_node *of_node)
1570{
1571 u32 index = 0;
1572 int rc = 0;
1573
1574 if (!dsi_ctrl || !of_node) {
1575 pr_err("invalid dsi_ctrl:%d or of_node:%d\n",
1576 dsi_ctrl != NULL, of_node != NULL);
1577 return -EINVAL;
1578 }
1579
1580 rc = of_property_read_u32(of_node, "cell-index", &index);
1581 if (rc) {
1582 pr_debug("cell index not set, default to 0\n");
1583 index = 0;
1584 }
1585
1586 dsi_ctrl->cell_index = index;
1587 dsi_ctrl->name = of_get_property(of_node, "label", NULL);
1588 if (!dsi_ctrl->name)
1589 dsi_ctrl->name = DSI_CTRL_DEFAULT_LABEL;
1590
1591 dsi_ctrl->phy_isolation_enabled = of_property_read_bool(of_node,
1592 "qcom,dsi-phy-isolation-enabled");
1593
Sravanthi Kollukudurud8809322017-10-26 15:24:13 +05301594 dsi_ctrl->null_insertion_enabled = of_property_read_bool(of_node,
1595 "qcom,null-insertion-enabled");
1596
Dhaval Patelabfaa082017-07-28 12:41:10 -07001597 return 0;
1598}
1599
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001600static int dsi_ctrl_dev_probe(struct platform_device *pdev)
1601{
1602 struct dsi_ctrl *dsi_ctrl;
1603 struct dsi_ctrl_list_item *item;
1604 const struct of_device_id *id;
1605 enum dsi_ctrl_version version;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001606 int rc = 0;
1607
1608 id = of_match_node(msm_dsi_of_match, pdev->dev.of_node);
1609 if (!id)
1610 return -ENODEV;
1611
1612 version = *(enum dsi_ctrl_version *)id->data;
1613
1614 item = devm_kzalloc(&pdev->dev, sizeof(*item), GFP_KERNEL);
1615 if (!item)
1616 return -ENOMEM;
1617
1618 dsi_ctrl = devm_kzalloc(&pdev->dev, sizeof(*dsi_ctrl), GFP_KERNEL);
1619 if (!dsi_ctrl)
1620 return -ENOMEM;
1621
Shashank Babu Chinta Venkataafef8202017-04-21 13:49:56 -07001622 dsi_ctrl->version = version;
Clarence Ip80ada7f2017-05-04 09:55:21 -07001623 dsi_ctrl->irq_info.irq_num = -1;
1624 dsi_ctrl->irq_info.irq_stat_mask = 0x0;
1625
1626 spin_lock_init(&dsi_ctrl->irq_info.irq_lock);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001627
Dhaval Patelabfaa082017-07-28 12:41:10 -07001628 rc = dsi_ctrl_dts_parse(dsi_ctrl, pdev->dev.of_node);
1629 if (rc) {
1630 pr_err("ctrl:%d dts parse failed, rc = %d\n",
1631 dsi_ctrl->cell_index, rc);
1632 goto fail;
1633 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001634
1635 rc = dsi_ctrl_init_regmap(pdev, dsi_ctrl);
1636 if (rc) {
1637 pr_err("Failed to parse register information, rc = %d\n", rc);
1638 goto fail;
1639 }
1640
1641 rc = dsi_ctrl_clocks_init(pdev, dsi_ctrl);
1642 if (rc) {
1643 pr_err("Failed to parse clock information, rc = %d\n", rc);
1644 goto fail;
1645 }
1646
1647 rc = dsi_ctrl_supplies_init(pdev, dsi_ctrl);
1648 if (rc) {
1649 pr_err("Failed to parse voltage supplies, rc = %d\n", rc);
1650 goto fail_clks;
1651 }
1652
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001653 rc = dsi_catalog_ctrl_setup(&dsi_ctrl->hw, dsi_ctrl->version,
Sravanthi Kollukudurud8809322017-10-26 15:24:13 +05301654 dsi_ctrl->cell_index, dsi_ctrl->phy_isolation_enabled,
1655 dsi_ctrl->null_insertion_enabled);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001656 if (rc) {
1657 pr_err("Catalog does not support version (%d)\n",
1658 dsi_ctrl->version);
1659 goto fail_supplies;
1660 }
1661
1662 rc = dsi_ctrl_axi_bus_client_init(pdev, dsi_ctrl);
1663 if (rc)
Shashank Babu Chinta Venkatacf411332017-05-10 17:30:08 -07001664 pr_debug("failed to init axi bus client, rc = %d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001665
1666 item->ctrl = dsi_ctrl;
1667
1668 mutex_lock(&dsi_ctrl_list_lock);
1669 list_add(&item->list, &dsi_ctrl_list);
1670 mutex_unlock(&dsi_ctrl_list_lock);
1671
1672 mutex_init(&dsi_ctrl->ctrl_lock);
Veera Sundaram Sankarand2a93942017-10-20 12:44:18 -07001673 dsi_ctrl->secure_mode = false;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001674
1675 dsi_ctrl->pdev = pdev;
1676 platform_set_drvdata(pdev, dsi_ctrl);
Dhaval Patela2430842017-06-15 14:32:36 -07001677 pr_info("Probe successful for %s\n", dsi_ctrl->name);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001678
1679 return 0;
1680
1681fail_supplies:
1682 (void)dsi_ctrl_supplies_deinit(dsi_ctrl);
1683fail_clks:
1684 (void)dsi_ctrl_clocks_deinit(dsi_ctrl);
1685fail:
1686 return rc;
1687}
1688
1689static int dsi_ctrl_dev_remove(struct platform_device *pdev)
1690{
1691 int rc = 0;
1692 struct dsi_ctrl *dsi_ctrl;
1693 struct list_head *pos, *tmp;
1694
1695 dsi_ctrl = platform_get_drvdata(pdev);
1696
1697 mutex_lock(&dsi_ctrl_list_lock);
1698 list_for_each_safe(pos, tmp, &dsi_ctrl_list) {
1699 struct dsi_ctrl_list_item *n = list_entry(pos,
1700 struct dsi_ctrl_list_item,
1701 list);
1702 if (n->ctrl == dsi_ctrl) {
1703 list_del(&n->list);
1704 break;
1705 }
1706 }
1707 mutex_unlock(&dsi_ctrl_list_lock);
1708
1709 mutex_lock(&dsi_ctrl->ctrl_lock);
1710 rc = dsi_ctrl_axi_bus_client_deinit(dsi_ctrl);
1711 if (rc)
1712 pr_err("failed to deinitialize axi bus client, rc = %d\n", rc);
1713
1714 rc = dsi_ctrl_supplies_deinit(dsi_ctrl);
1715 if (rc)
1716 pr_err("failed to deinitialize voltage supplies, rc=%d\n", rc);
1717
1718 rc = dsi_ctrl_clocks_deinit(dsi_ctrl);
1719 if (rc)
1720 pr_err("failed to deinitialize clocks, rc=%d\n", rc);
1721
1722 mutex_unlock(&dsi_ctrl->ctrl_lock);
1723
1724 mutex_destroy(&dsi_ctrl->ctrl_lock);
1725 devm_kfree(&pdev->dev, dsi_ctrl);
1726
1727 platform_set_drvdata(pdev, NULL);
1728 return 0;
1729}
1730
1731static struct platform_driver dsi_ctrl_driver = {
1732 .probe = dsi_ctrl_dev_probe,
1733 .remove = dsi_ctrl_dev_remove,
1734 .driver = {
Ajay Singh Parmar485f7362016-07-19 10:43:24 -07001735 .name = "drm_dsi_ctrl",
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001736 .of_match_table = msm_dsi_of_match,
1737 },
1738};
1739
Dhaval Patelf9f3ffe2017-08-16 16:03:10 -07001740#if defined(CONFIG_DEBUG_FS)
1741
1742void dsi_ctrl_debug_dump(void)
1743{
1744 struct list_head *pos, *tmp;
1745 struct dsi_ctrl *ctrl = NULL;
1746
1747 mutex_lock(&dsi_ctrl_list_lock);
1748 list_for_each_safe(pos, tmp, &dsi_ctrl_list) {
1749 struct dsi_ctrl_list_item *n;
1750
1751 n = list_entry(pos, struct dsi_ctrl_list_item, list);
1752 ctrl = n->ctrl;
1753 pr_err("dsi ctrl:%d\n", ctrl->cell_index);
1754 ctrl->hw.ops.debug_bus(&ctrl->hw);
1755 }
1756 mutex_unlock(&dsi_ctrl_list_lock);
1757}
1758
1759#endif
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001760/**
1761 * dsi_ctrl_get() - get a dsi_ctrl handle from an of_node
1762 * @of_node: of_node of the DSI controller.
1763 *
1764 * Gets the DSI controller handle for the corresponding of_node. The ref count
1765 * is incremented to one and all subsequent gets will fail until the original
1766 * clients calls a put.
1767 *
1768 * Return: DSI Controller handle.
1769 */
1770struct dsi_ctrl *dsi_ctrl_get(struct device_node *of_node)
1771{
1772 struct list_head *pos, *tmp;
1773 struct dsi_ctrl *ctrl = NULL;
1774
1775 mutex_lock(&dsi_ctrl_list_lock);
1776 list_for_each_safe(pos, tmp, &dsi_ctrl_list) {
1777 struct dsi_ctrl_list_item *n;
1778
1779 n = list_entry(pos, struct dsi_ctrl_list_item, list);
1780 if (n->ctrl->pdev->dev.of_node == of_node) {
1781 ctrl = n->ctrl;
1782 break;
1783 }
1784 }
1785 mutex_unlock(&dsi_ctrl_list_lock);
1786
1787 if (!ctrl) {
1788 pr_err("Device with of node not found\n");
1789 ctrl = ERR_PTR(-EPROBE_DEFER);
1790 return ctrl;
1791 }
1792
1793 mutex_lock(&ctrl->ctrl_lock);
1794 if (ctrl->refcount == 1) {
1795 pr_err("[%s] Device in use\n", ctrl->name);
Steve Cohen51668e42017-10-20 14:08:19 -04001796 mutex_unlock(&ctrl->ctrl_lock);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001797 ctrl = ERR_PTR(-EBUSY);
Steve Cohen51668e42017-10-20 14:08:19 -04001798 return ctrl;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001799 } else {
1800 ctrl->refcount++;
1801 }
1802 mutex_unlock(&ctrl->ctrl_lock);
1803 return ctrl;
1804}
1805
1806/**
1807 * dsi_ctrl_put() - releases a dsi controller handle.
1808 * @dsi_ctrl: DSI controller handle.
1809 *
1810 * Releases the DSI controller. Driver will clean up all resources and puts back
1811 * the DSI controller into reset state.
1812 */
1813void dsi_ctrl_put(struct dsi_ctrl *dsi_ctrl)
1814{
1815 mutex_lock(&dsi_ctrl->ctrl_lock);
1816
1817 if (dsi_ctrl->refcount == 0)
1818 pr_err("Unbalanced dsi_ctrl_put call\n");
1819 else
1820 dsi_ctrl->refcount--;
1821
1822 mutex_unlock(&dsi_ctrl->ctrl_lock);
1823}
1824
1825/**
1826 * dsi_ctrl_drv_init() - initialize dsi controller driver.
1827 * @dsi_ctrl: DSI controller handle.
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001828 * @parent: Parent directory for debug fs.
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001829 *
1830 * Initializes DSI controller driver. Driver should be initialized after
1831 * dsi_ctrl_get() succeeds.
1832 *
1833 * Return: error code.
1834 */
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001835int dsi_ctrl_drv_init(struct dsi_ctrl *dsi_ctrl, struct dentry *parent)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001836{
1837 int rc = 0;
1838
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001839 if (!dsi_ctrl || !parent) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001840 pr_err("Invalid params\n");
1841 return -EINVAL;
1842 }
1843
1844 mutex_lock(&dsi_ctrl->ctrl_lock);
1845 rc = dsi_ctrl_drv_state_init(dsi_ctrl);
1846 if (rc) {
1847 pr_err("Failed to initialize driver state, rc=%d\n", rc);
1848 goto error;
1849 }
1850
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001851 rc = dsi_ctrl_debugfs_init(dsi_ctrl, parent);
1852 if (rc) {
1853 pr_err("[DSI_%d] failed to init debug fs, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05001854 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001855 goto error;
1856 }
1857
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001858error:
1859 mutex_unlock(&dsi_ctrl->ctrl_lock);
1860 return rc;
1861}
1862
1863/**
1864 * dsi_ctrl_drv_deinit() - de-initializes dsi controller driver
1865 * @dsi_ctrl: DSI controller handle.
1866 *
1867 * Releases all resources acquired by dsi_ctrl_drv_init().
1868 *
1869 * Return: error code.
1870 */
1871int dsi_ctrl_drv_deinit(struct dsi_ctrl *dsi_ctrl)
1872{
1873 int rc = 0;
1874
1875 if (!dsi_ctrl) {
1876 pr_err("Invalid params\n");
1877 return -EINVAL;
1878 }
1879
1880 mutex_lock(&dsi_ctrl->ctrl_lock);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001881
1882 rc = dsi_ctrl_debugfs_deinit(dsi_ctrl);
1883 if (rc)
1884 pr_err("failed to release debugfs root, rc=%d\n", rc);
1885
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001886 rc = dsi_ctrl_buffer_deinit(dsi_ctrl);
1887 if (rc)
1888 pr_err("Failed to free cmd buffers, rc=%d\n", rc);
1889
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001890 mutex_unlock(&dsi_ctrl->ctrl_lock);
1891 return rc;
1892}
1893
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301894int dsi_ctrl_clk_cb_register(struct dsi_ctrl *dsi_ctrl,
1895 struct clk_ctrl_cb *clk_cb)
1896{
1897 if (!dsi_ctrl || !clk_cb) {
1898 pr_err("Invalid params\n");
1899 return -EINVAL;
1900 }
1901
1902 dsi_ctrl->clk_cb.priv = clk_cb->priv;
1903 dsi_ctrl->clk_cb.dsi_clk_cb = clk_cb->dsi_clk_cb;
1904 return 0;
1905}
1906
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001907/**
1908 * dsi_ctrl_phy_sw_reset() - perform a PHY software reset
1909 * @dsi_ctrl: DSI controller handle.
1910 *
1911 * Performs a PHY software reset on the DSI controller. Reset should be done
1912 * when the controller power state is DSI_CTRL_POWER_CORE_CLK_ON and the PHY is
1913 * not enabled.
1914 *
1915 * This function will fail if driver is in any other state.
1916 *
1917 * Return: error code.
1918 */
1919int dsi_ctrl_phy_sw_reset(struct dsi_ctrl *dsi_ctrl)
1920{
1921 int rc = 0;
1922
1923 if (!dsi_ctrl) {
1924 pr_err("Invalid params\n");
1925 return -EINVAL;
1926 }
1927
1928 mutex_lock(&dsi_ctrl->ctrl_lock);
1929 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_PHY_SW_RESET, 0x0);
1930 if (rc) {
1931 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05001932 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001933 goto error;
1934 }
1935
1936 dsi_ctrl->hw.ops.phy_sw_reset(&dsi_ctrl->hw);
1937
Alexander Beykun32a6a182017-02-27 17:46:51 -05001938 pr_debug("[DSI_%d] PHY soft reset done\n", dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001939 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_PHY_SW_RESET, 0x0);
1940error:
1941 mutex_unlock(&dsi_ctrl->ctrl_lock);
1942 return rc;
1943}
1944
1945/**
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07001946 * dsi_ctrl_seamless_timing_update() - update only controller timing
1947 * @dsi_ctrl: DSI controller handle.
1948 * @timing: New DSI timing info
1949 *
1950 * Updates host timing values to conduct a seamless transition to new timing
1951 * For example, to update the porch values in a dynamic fps switch.
1952 *
1953 * Return: error code.
1954 */
1955int dsi_ctrl_async_timing_update(struct dsi_ctrl *dsi_ctrl,
1956 struct dsi_mode_info *timing)
1957{
1958 struct dsi_mode_info *host_mode;
1959 int rc = 0;
1960
1961 if (!dsi_ctrl || !timing) {
1962 pr_err("Invalid params\n");
1963 return -EINVAL;
1964 }
1965
1966 mutex_lock(&dsi_ctrl->ctrl_lock);
1967
1968 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_ASYNC_TIMING,
1969 DSI_CTRL_ENGINE_ON);
1970 if (rc) {
1971 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05001972 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07001973 goto exit;
1974 }
1975
1976 host_mode = &dsi_ctrl->host_config.video_timing;
1977 memcpy(host_mode, timing, sizeof(*host_mode));
Raviteja Tamatam68892de2017-06-20 04:47:19 +05301978 dsi_ctrl->hw.ops.set_timing_db(&dsi_ctrl->hw, true);
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07001979 dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw, host_mode);
1980
1981exit:
1982 mutex_unlock(&dsi_ctrl->ctrl_lock);
1983 return rc;
1984}
1985
Raviteja Tamatam68892de2017-06-20 04:47:19 +05301986/**
1987 * dsi_ctrl_timing_db_update() - update only controller Timing DB
1988 * @dsi_ctrl: DSI controller handle.
1989 * @enable: Enable/disable Timing DB register
1990 *
1991 * Update timing db register value during dfps usecases
1992 *
1993 * Return: error code.
1994 */
1995int dsi_ctrl_timing_db_update(struct dsi_ctrl *dsi_ctrl,
1996 bool enable)
1997{
1998 int rc = 0;
1999
2000 if (!dsi_ctrl) {
2001 pr_err("Invalid dsi_ctrl\n");
2002 return -EINVAL;
2003 }
2004
2005 mutex_lock(&dsi_ctrl->ctrl_lock);
2006
2007 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_ASYNC_TIMING,
2008 DSI_CTRL_ENGINE_ON);
2009 if (rc) {
2010 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
2011 dsi_ctrl->cell_index, rc);
2012 goto exit;
2013 }
2014
2015 /*
2016 * Add HW recommended delay for dfps feature.
2017 * When prefetch is enabled, MDSS HW works on 2 vsync
2018 * boundaries i.e. mdp_vsync and panel_vsync.
2019 * In the current implementation we are only waiting
2020 * for mdp_vsync. We need to make sure that interface
2021 * flush is after panel_vsync. So, added the recommended
2022 * delays after dfps update.
2023 */
2024 usleep_range(2000, 2010);
2025
2026 dsi_ctrl->hw.ops.set_timing_db(&dsi_ctrl->hw, enable);
2027
2028exit:
2029 mutex_unlock(&dsi_ctrl->ctrl_lock);
2030 return rc;
2031}
2032
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302033int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl)
2034{
2035 int rc = 0;
2036
2037 if (!dsi_ctrl) {
2038 pr_err("Invalid params\n");
2039 return -EINVAL;
2040 }
2041
2042 mutex_lock(&dsi_ctrl->ctrl_lock);
2043
2044 dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw,
2045 &dsi_ctrl->host_config.lane_map);
2046
2047 dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
2048 &dsi_ctrl->host_config.common_config);
2049
2050 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
2051 dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
2052 &dsi_ctrl->host_config.common_config,
2053 &dsi_ctrl->host_config.u.cmd_engine);
2054
2055 dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
Lloyd Atkinson16e96de2017-04-19 11:18:14 -04002056 &dsi_ctrl->host_config.video_timing,
2057 dsi_ctrl->host_config.video_timing.h_active * 3,
2058 0x0,
2059 &dsi_ctrl->roi);
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302060 dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, true);
2061 } else {
2062 dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw,
2063 &dsi_ctrl->host_config.common_config,
2064 &dsi_ctrl->host_config.u.video_engine);
2065 dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw,
2066 &dsi_ctrl->host_config.video_timing);
2067 dsi_ctrl->hw.ops.video_engine_en(&dsi_ctrl->hw, true);
2068 }
2069
2070 dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
Sandeep Panda11b20d82017-06-19 12:57:27 +05302071 dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302072 dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true);
2073
2074 mutex_unlock(&dsi_ctrl->ctrl_lock);
2075 return rc;
2076}
2077
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002078int dsi_ctrl_set_roi(struct dsi_ctrl *dsi_ctrl, struct dsi_rect *roi,
2079 bool *changed)
2080{
2081 int rc = 0;
2082
2083 if (!dsi_ctrl || !roi || !changed) {
2084 pr_err("Invalid params\n");
2085 return -EINVAL;
2086 }
2087
2088 mutex_lock(&dsi_ctrl->ctrl_lock);
2089 if (!dsi_rect_is_equal(&dsi_ctrl->roi, roi)) {
2090 *changed = true;
2091 memcpy(&dsi_ctrl->roi, roi, sizeof(dsi_ctrl->roi));
2092 } else
2093 *changed = false;
2094 mutex_unlock(&dsi_ctrl->ctrl_lock);
2095 return rc;
2096}
2097
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05302098/**
2099 * dsi_ctrl_phy_reset_config() - Mask/unmask propagation of ahb reset signal
2100 * to DSI PHY hardware.
2101 * @dsi_ctrl: DSI controller handle.
2102 * @enable: Mask/unmask the PHY reset signal.
2103 *
2104 * Return: error code.
2105 */
2106int dsi_ctrl_phy_reset_config(struct dsi_ctrl *dsi_ctrl, bool enable)
2107{
2108 if (!dsi_ctrl) {
2109 pr_err("Invalid params\n");
2110 return -EINVAL;
2111 }
2112
2113 if (dsi_ctrl->hw.ops.phy_reset_config)
2114 dsi_ctrl->hw.ops.phy_reset_config(&dsi_ctrl->hw, enable);
2115
2116 return 0;
2117}
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302118
Clarence Ip80ada7f2017-05-04 09:55:21 -07002119static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl,
2120 unsigned long int error)
2121{
Sandeep Panda11b20d82017-06-19 12:57:27 +05302122 struct dsi_event_cb_info cb_info;
2123
2124 cb_info = dsi_ctrl->irq_info.irq_err_cb;
2125
2126 /* disable error interrupts */
2127 if (dsi_ctrl->hw.ops.error_intr_ctrl)
2128 dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, false);
2129
2130 /* clear error interrupts first */
2131 if (dsi_ctrl->hw.ops.clear_error_status)
2132 dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
2133 error);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002134
2135 /* DTLN PHY error */
Sandeep Panda11b20d82017-06-19 12:57:27 +05302136 if (error & 0x3000E00)
2137 pr_err("dsi PHY contention error: 0x%lx\n", error);
2138
2139 /* TX timeout error */
2140 if (error & 0xE0) {
2141 if (error & 0xA0) {
2142 if (cb_info.event_cb) {
2143 cb_info.event_idx = DSI_LP_Rx_TIMEOUT;
2144 (void)cb_info.event_cb(cb_info.event_usr_ptr,
2145 cb_info.event_idx,
2146 dsi_ctrl->cell_index,
2147 0, 0, 0, 0);
2148 }
2149 }
2150 pr_err("tx timeout error: 0x%lx\n", error);
2151 }
Clarence Ip80ada7f2017-05-04 09:55:21 -07002152
2153 /* DSI FIFO OVERFLOW error */
Sandeep Panda11b20d82017-06-19 12:57:27 +05302154 if (error & 0xF0000) {
2155 u32 mask = 0;
2156
2157 if (dsi_ctrl->hw.ops.get_error_mask)
2158 mask = dsi_ctrl->hw.ops.get_error_mask(&dsi_ctrl->hw);
2159 /* no need to report FIFO overflow if already masked */
2160 if (cb_info.event_cb && !(mask & 0xf0000)) {
2161 cb_info.event_idx = DSI_FIFO_OVERFLOW;
2162 (void)cb_info.event_cb(cb_info.event_usr_ptr,
2163 cb_info.event_idx,
2164 dsi_ctrl->cell_index,
2165 0, 0, 0, 0);
2166 pr_err("dsi FIFO OVERFLOW error: 0x%lx\n", error);
2167 }
Clarence Ip80ada7f2017-05-04 09:55:21 -07002168 }
2169
2170 /* DSI FIFO UNDERFLOW error */
Sandeep Panda11b20d82017-06-19 12:57:27 +05302171 if (error & 0xF00000) {
2172 if (cb_info.event_cb) {
2173 cb_info.event_idx = DSI_FIFO_UNDERFLOW;
2174 (void)cb_info.event_cb(cb_info.event_usr_ptr,
2175 cb_info.event_idx,
2176 dsi_ctrl->cell_index,
2177 0, 0, 0, 0);
2178 }
2179 pr_err("dsi FIFO UNDERFLOW error: 0x%lx\n", error);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002180 }
2181
2182 /* DSI PLL UNLOCK error */
2183 if (error & BIT(8))
Sandeep Panda11b20d82017-06-19 12:57:27 +05302184 pr_err("dsi PLL unlock error: 0x%lx\n", error);
2185
2186 /* ACK error */
2187 if (error & 0xF)
2188 pr_err("ack error: 0x%lx\n", error);
2189
2190 /* enable back DSI interrupts */
2191 if (dsi_ctrl->hw.ops.error_intr_ctrl)
2192 dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, true);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002193}
2194
2195/**
2196 * dsi_ctrl_isr - interrupt service routine for DSI CTRL component
2197 * @irq: Incoming IRQ number
2198 * @ptr: Pointer to user data structure (struct dsi_ctrl)
2199 * Returns: IRQ_HANDLED if no further action required
2200 */
2201static irqreturn_t dsi_ctrl_isr(int irq, void *ptr)
2202{
2203 struct dsi_ctrl *dsi_ctrl;
2204 struct dsi_event_cb_info cb_info;
2205 unsigned long flags;
Sandeep Panda11b20d82017-06-19 12:57:27 +05302206 uint32_t status = 0x0, i;
2207 uint64_t errors = 0x0;
Clarence Ip80ada7f2017-05-04 09:55:21 -07002208
2209 if (!ptr)
2210 return IRQ_NONE;
2211 dsi_ctrl = ptr;
2212
Sandeep Panda11b20d82017-06-19 12:57:27 +05302213 /* check status interrupts */
Clarence Ip80ada7f2017-05-04 09:55:21 -07002214 if (dsi_ctrl->hw.ops.get_interrupt_status)
2215 status = dsi_ctrl->hw.ops.get_interrupt_status(&dsi_ctrl->hw);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002216
Sandeep Panda11b20d82017-06-19 12:57:27 +05302217 /* check error interrupts */
Clarence Ip80ada7f2017-05-04 09:55:21 -07002218 if (dsi_ctrl->hw.ops.get_error_status)
2219 errors = dsi_ctrl->hw.ops.get_error_status(&dsi_ctrl->hw);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002220
Sandeep Panda11b20d82017-06-19 12:57:27 +05302221 /* clear interrupts */
2222 if (dsi_ctrl->hw.ops.clear_interrupt_status)
2223 dsi_ctrl->hw.ops.clear_interrupt_status(&dsi_ctrl->hw, 0x0);
2224
2225 /* handle DSI error recovery */
2226 if (status & DSI_ERROR)
Clarence Ip80ada7f2017-05-04 09:55:21 -07002227 dsi_ctrl_handle_error_status(dsi_ctrl, errors);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002228
2229 if (status & DSI_CMD_MODE_DMA_DONE) {
2230 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
2231 DSI_SINT_CMD_MODE_DMA_DONE);
2232 complete_all(&dsi_ctrl->irq_info.cmd_dma_done);
2233 }
2234
2235 if (status & DSI_CMD_FRAME_DONE) {
2236 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
2237 DSI_SINT_CMD_FRAME_DONE);
2238 complete_all(&dsi_ctrl->irq_info.cmd_frame_done);
2239 }
2240
2241 if (status & DSI_VIDEO_MODE_FRAME_DONE) {
2242 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
2243 DSI_SINT_VIDEO_MODE_FRAME_DONE);
2244 complete_all(&dsi_ctrl->irq_info.vid_frame_done);
2245 }
2246
2247 if (status & DSI_BTA_DONE) {
Sandeep Panda11b20d82017-06-19 12:57:27 +05302248 u32 fifo_overflow_mask = (DSI_DLN0_HS_FIFO_OVERFLOW |
2249 DSI_DLN1_HS_FIFO_OVERFLOW |
2250 DSI_DLN2_HS_FIFO_OVERFLOW |
2251 DSI_DLN3_HS_FIFO_OVERFLOW);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002252 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
2253 DSI_SINT_BTA_DONE);
2254 complete_all(&dsi_ctrl->irq_info.bta_done);
Sandeep Panda11b20d82017-06-19 12:57:27 +05302255 if (dsi_ctrl->hw.ops.clear_error_status)
2256 dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
2257 fifo_overflow_mask);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002258 }
2259
2260 for (i = 0; status && i < DSI_STATUS_INTERRUPT_COUNT; ++i) {
2261 if (status & 0x1) {
2262 spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags);
2263 cb_info = dsi_ctrl->irq_info.irq_stat_cb[i];
2264 spin_unlock_irqrestore(
2265 &dsi_ctrl->irq_info.irq_lock, flags);
2266
2267 if (cb_info.event_cb)
2268 (void)cb_info.event_cb(cb_info.event_usr_ptr,
2269 cb_info.event_idx,
Sandeep Panda11b20d82017-06-19 12:57:27 +05302270 dsi_ctrl->cell_index,
2271 irq, 0, 0, 0);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002272 }
2273 status >>= 1;
2274 }
2275
2276 return IRQ_HANDLED;
2277}
2278
2279/**
2280 * _dsi_ctrl_setup_isr - register ISR handler
2281 * @dsi_ctrl: Pointer to associated dsi_ctrl structure
2282 * Returns: Zero on success
2283 */
2284static int dsi_ctrl_setup_isr(struct dsi_ctrl *dsi_ctrl)
2285{
2286 int irq_num, rc;
2287
2288 if (!dsi_ctrl)
2289 return -EINVAL;
2290 if (dsi_ctrl->irq_info.irq_num != -1)
2291 return 0;
2292
2293 init_completion(&dsi_ctrl->irq_info.cmd_dma_done);
2294 init_completion(&dsi_ctrl->irq_info.vid_frame_done);
2295 init_completion(&dsi_ctrl->irq_info.cmd_frame_done);
2296 init_completion(&dsi_ctrl->irq_info.bta_done);
2297
2298 irq_num = platform_get_irq(dsi_ctrl->pdev, 0);
2299 if (irq_num < 0) {
2300 pr_err("[DSI_%d] Failed to get IRQ number, %d\n",
2301 dsi_ctrl->cell_index, irq_num);
2302 rc = irq_num;
2303 } else {
2304 rc = devm_request_threaded_irq(&dsi_ctrl->pdev->dev, irq_num,
2305 dsi_ctrl_isr, NULL, 0, "dsi_ctrl", dsi_ctrl);
2306 if (rc) {
2307 pr_err("[DSI_%d] Failed to request IRQ, %d\n",
2308 dsi_ctrl->cell_index, rc);
2309 } else {
2310 dsi_ctrl->irq_info.irq_num = irq_num;
2311 disable_irq_nosync(irq_num);
2312
2313 pr_info("[DSI_%d] IRQ %d registered\n",
2314 dsi_ctrl->cell_index, irq_num);
2315 }
2316 }
2317 return rc;
2318}
2319
2320/**
2321 * _dsi_ctrl_destroy_isr - unregister ISR handler
2322 * @dsi_ctrl: Pointer to associated dsi_ctrl structure
2323 */
2324static void _dsi_ctrl_destroy_isr(struct dsi_ctrl *dsi_ctrl)
2325{
2326 if (!dsi_ctrl || !dsi_ctrl->pdev || dsi_ctrl->irq_info.irq_num < 0)
2327 return;
2328
2329 if (dsi_ctrl->irq_info.irq_num != -1) {
2330 devm_free_irq(&dsi_ctrl->pdev->dev,
2331 dsi_ctrl->irq_info.irq_num, dsi_ctrl);
2332 dsi_ctrl->irq_info.irq_num = -1;
2333 }
2334}
2335
2336void dsi_ctrl_enable_status_interrupt(struct dsi_ctrl *dsi_ctrl,
2337 uint32_t intr_idx, struct dsi_event_cb_info *event_info)
2338{
2339 unsigned long flags;
2340
2341 if (!dsi_ctrl || dsi_ctrl->irq_info.irq_num == -1 ||
2342 intr_idx >= DSI_STATUS_INTERRUPT_COUNT)
2343 return;
2344
2345 spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags);
2346
2347 if (dsi_ctrl->irq_info.irq_stat_refcount[intr_idx] == 0) {
2348 /* enable irq on first request */
2349 if (dsi_ctrl->irq_info.irq_stat_mask == 0)
2350 enable_irq(dsi_ctrl->irq_info.irq_num);
2351
2352 /* update hardware mask */
2353 dsi_ctrl->irq_info.irq_stat_mask |= BIT(intr_idx);
2354 dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw,
2355 dsi_ctrl->irq_info.irq_stat_mask);
2356 }
2357 ++(dsi_ctrl->irq_info.irq_stat_refcount[intr_idx]);
2358
2359 if (event_info)
2360 dsi_ctrl->irq_info.irq_stat_cb[intr_idx] = *event_info;
2361
2362 spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags);
2363}
2364
2365void dsi_ctrl_disable_status_interrupt(struct dsi_ctrl *dsi_ctrl,
2366 uint32_t intr_idx)
2367{
2368 unsigned long flags;
2369
2370 if (!dsi_ctrl || dsi_ctrl->irq_info.irq_num == -1 ||
2371 intr_idx >= DSI_STATUS_INTERRUPT_COUNT)
2372 return;
2373
2374 spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags);
2375
2376 if (dsi_ctrl->irq_info.irq_stat_refcount[intr_idx])
2377 if (--(dsi_ctrl->irq_info.irq_stat_refcount[intr_idx]) == 0) {
2378 dsi_ctrl->irq_info.irq_stat_mask &= ~BIT(intr_idx);
2379 dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw,
2380 dsi_ctrl->irq_info.irq_stat_mask);
2381
2382 /* don't need irq if no lines are enabled */
2383 if (dsi_ctrl->irq_info.irq_stat_mask == 0)
2384 disable_irq_nosync(dsi_ctrl->irq_info.irq_num);
2385 }
2386
2387 spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags);
2388}
2389
Jeykumar Sankarana7c7bbe2017-05-31 18:12:05 -07002390int dsi_ctrl_host_timing_update(struct dsi_ctrl *dsi_ctrl)
2391{
2392 if (!dsi_ctrl) {
2393 pr_err("Invalid params\n");
2394 return -EINVAL;
2395 }
2396
2397 if (dsi_ctrl->hw.ops.host_setup)
2398 dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
2399 &dsi_ctrl->host_config.common_config);
2400
2401 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
2402 if (dsi_ctrl->hw.ops.cmd_engine_setup)
2403 dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
2404 &dsi_ctrl->host_config.common_config,
2405 &dsi_ctrl->host_config.u.cmd_engine);
2406
2407 if (dsi_ctrl->hw.ops.setup_cmd_stream)
2408 dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
2409 &dsi_ctrl->host_config.video_timing,
2410 dsi_ctrl->host_config.video_timing.h_active * 3,
2411 0x0, NULL);
2412 } else {
2413 pr_err("invalid panel mode for resolution switch\n");
2414 return -EINVAL;
2415 }
2416
2417 return 0;
2418}
2419
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302420/**
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002421 * dsi_ctrl_host_init() - Initialize DSI host hardware.
2422 * @dsi_ctrl: DSI controller handle.
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002423 * @is_splash_enabled: boolean signifying splash status.
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002424 *
2425 * Initializes DSI controller hardware with host configuration provided by
2426 * dsi_ctrl_update_host_config(). Initialization can be performed only during
2427 * DSI_CTRL_POWER_CORE_CLK_ON state and after the PHY SW reset has been
2428 * performed.
2429 *
2430 * Return: error code.
2431 */
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002432int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl, bool is_splash_enabled)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002433{
2434 int rc = 0;
2435
2436 if (!dsi_ctrl) {
2437 pr_err("Invalid params\n");
2438 return -EINVAL;
2439 }
2440
2441 mutex_lock(&dsi_ctrl->ctrl_lock);
2442 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x1);
2443 if (rc) {
2444 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002445 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002446 goto error;
2447 }
2448
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002449 /* For Splash usecases we omit hw operations as bootloader
2450 * already takes care of them
2451 */
2452 if (!is_splash_enabled) {
2453 dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002454 &dsi_ctrl->host_config.lane_map);
2455
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002456 dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002457 &dsi_ctrl->host_config.common_config);
2458
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002459 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
2460 dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002461 &dsi_ctrl->host_config.common_config,
2462 &dsi_ctrl->host_config.u.cmd_engine);
Ajay Singh Parmaraa9152d2016-05-16 18:02:07 -07002463
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002464 dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
Alexander Beykunac182352017-02-27 17:46:51 -05002465 &dsi_ctrl->host_config.video_timing,
Ajay Singh Parmaraa9152d2016-05-16 18:02:07 -07002466 dsi_ctrl->host_config.video_timing.h_active * 3,
Lloyd Atkinson16e96de2017-04-19 11:18:14 -04002467 0x0,
2468 NULL);
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002469 } else {
2470 dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002471 &dsi_ctrl->host_config.common_config,
2472 &dsi_ctrl->host_config.u.video_engine);
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002473 dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw,
Ajay Singh Parmaraa9152d2016-05-16 18:02:07 -07002474 &dsi_ctrl->host_config.video_timing);
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002475 }
Ajay Singh Parmaraa9152d2016-05-16 18:02:07 -07002476 }
2477
Clarence Ip80ada7f2017-05-04 09:55:21 -07002478 dsi_ctrl_setup_isr(dsi_ctrl);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002479
2480 dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
Sandeep Panda11b20d82017-06-19 12:57:27 +05302481 dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002482
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002483 pr_debug("[DSI_%d]Host initialization complete, continuous splash status:%d\n",
2484 dsi_ctrl->cell_index, is_splash_enabled);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002485 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x1);
2486error:
2487 mutex_unlock(&dsi_ctrl->ctrl_lock);
2488 return rc;
2489}
2490
Lloyd Atkinson8c49c582016-11-18 14:23:54 -05002491int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl)
2492{
2493 if (!dsi_ctrl)
2494 return -EINVAL;
2495
2496 mutex_lock(&dsi_ctrl->ctrl_lock);
2497 dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
2498 mutex_unlock(&dsi_ctrl->ctrl_lock);
2499
Alexander Beykun32a6a182017-02-27 17:46:51 -05002500 pr_debug("[DSI_%d]Soft reset complete\n", dsi_ctrl->cell_index);
Lloyd Atkinson8c49c582016-11-18 14:23:54 -05002501 return 0;
2502}
2503
Sandeep Panda11b20d82017-06-19 12:57:27 +05302504int dsi_ctrl_reset(struct dsi_ctrl *dsi_ctrl, int mask)
2505{
2506 int rc = 0;
2507
2508 if (!dsi_ctrl)
2509 return -EINVAL;
2510
2511 mutex_lock(&dsi_ctrl->ctrl_lock);
2512 rc = dsi_ctrl->hw.ops.ctrl_reset(&dsi_ctrl->hw, mask);
2513 mutex_unlock(&dsi_ctrl->ctrl_lock);
2514
2515 return rc;
2516}
2517
2518int dsi_ctrl_get_hw_version(struct dsi_ctrl *dsi_ctrl)
2519{
2520 int rc = 0;
2521
2522 if (!dsi_ctrl)
2523 return -EINVAL;
2524
2525 mutex_lock(&dsi_ctrl->ctrl_lock);
2526 rc = dsi_ctrl->hw.ops.get_hw_version(&dsi_ctrl->hw);
2527 mutex_unlock(&dsi_ctrl->ctrl_lock);
2528
2529 return rc;
2530}
2531
2532int dsi_ctrl_vid_engine_en(struct dsi_ctrl *dsi_ctrl, bool on)
2533{
2534 int rc = 0;
2535
2536 if (!dsi_ctrl)
2537 return -EINVAL;
2538
2539 mutex_lock(&dsi_ctrl->ctrl_lock);
2540 dsi_ctrl->hw.ops.video_engine_en(&dsi_ctrl->hw, on);
2541 mutex_unlock(&dsi_ctrl->ctrl_lock);
2542
2543 return rc;
2544}
2545
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002546/**
2547 * dsi_ctrl_host_deinit() - De-Initialize DSI host hardware.
2548 * @dsi_ctrl: DSI controller handle.
2549 *
2550 * De-initializes DSI controller hardware. It can be performed only during
2551 * DSI_CTRL_POWER_CORE_CLK_ON state after LINK clocks have been turned off.
2552 *
2553 * Return: error code.
2554 */
2555int dsi_ctrl_host_deinit(struct dsi_ctrl *dsi_ctrl)
2556{
2557 int rc = 0;
2558
2559 if (!dsi_ctrl) {
2560 pr_err("Invalid params\n");
2561 return -EINVAL;
2562 }
2563
2564 mutex_lock(&dsi_ctrl->ctrl_lock);
2565
Clarence Ip80ada7f2017-05-04 09:55:21 -07002566 _dsi_ctrl_destroy_isr(dsi_ctrl);
2567
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002568 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x0);
2569 if (rc) {
2570 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002571 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002572 pr_err("driver state check failed, rc=%d\n", rc);
2573 goto error;
2574 }
2575
Alexander Beykun32a6a182017-02-27 17:46:51 -05002576 pr_debug("[DSI_%d] Host deinitization complete\n",
2577 dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002578 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x0);
2579error:
2580 mutex_unlock(&dsi_ctrl->ctrl_lock);
2581 return rc;
2582}
2583
2584/**
2585 * dsi_ctrl_update_host_config() - update dsi host configuration
2586 * @dsi_ctrl: DSI controller handle.
2587 * @config: DSI host configuration.
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002588 * @flags: dsi_mode_flags modifying the behavior
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002589 *
2590 * Updates driver with new Host configuration to use for host initialization.
2591 * This function call will only update the software context. The stored
2592 * configuration information will be used when the host is initialized.
2593 *
2594 * Return: error code.
2595 */
2596int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl,
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002597 struct dsi_host_config *config,
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302598 int flags, void *clk_handle)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002599{
2600 int rc = 0;
2601
2602 if (!ctrl || !config) {
2603 pr_err("Invalid params\n");
2604 return -EINVAL;
2605 }
2606
2607 mutex_lock(&ctrl->ctrl_lock);
2608
2609 rc = dsi_ctrl_validate_panel_info(ctrl, config);
2610 if (rc) {
2611 pr_err("panel validation failed, rc=%d\n", rc);
2612 goto error;
2613 }
2614
Raviteja Tamatam68892de2017-06-20 04:47:19 +05302615 if (!(flags & (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR))) {
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302616 rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle);
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002617 if (rc) {
2618 pr_err("[%s] failed to update link frequencies, rc=%d\n",
2619 ctrl->name, rc);
2620 goto error;
2621 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002622 }
2623
Alexander Beykun32a6a182017-02-27 17:46:51 -05002624 pr_debug("[DSI_%d]Host config updated\n", ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002625 memcpy(&ctrl->host_config, config, sizeof(ctrl->host_config));
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002626 ctrl->mode_bounds.x = ctrl->host_config.video_timing.h_active *
2627 ctrl->horiz_index;
2628 ctrl->mode_bounds.y = 0;
2629 ctrl->mode_bounds.w = ctrl->host_config.video_timing.h_active;
2630 ctrl->mode_bounds.h = ctrl->host_config.video_timing.v_active;
2631 memcpy(&ctrl->roi, &ctrl->mode_bounds, sizeof(ctrl->mode_bounds));
2632 ctrl->roi.x = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002633error:
2634 mutex_unlock(&ctrl->ctrl_lock);
2635 return rc;
2636}
2637
2638/**
2639 * dsi_ctrl_validate_timing() - validate a video timing configuration
2640 * @dsi_ctrl: DSI controller handle.
2641 * @timing: Pointer to timing data.
2642 *
2643 * Driver will validate if the timing configuration is supported on the
2644 * controller hardware.
2645 *
2646 * Return: error code if timing is not supported.
2647 */
2648int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl,
2649 struct dsi_mode_info *mode)
2650{
2651 int rc = 0;
2652
2653 if (!dsi_ctrl || !mode) {
2654 pr_err("Invalid params\n");
2655 return -EINVAL;
2656 }
2657
2658 mutex_lock(&dsi_ctrl->ctrl_lock);
2659 mutex_unlock(&dsi_ctrl->ctrl_lock);
2660
2661 return rc;
2662}
2663
2664/**
2665 * dsi_ctrl_cmd_transfer() - Transfer commands on DSI link
2666 * @dsi_ctrl: DSI controller handle.
2667 * @msg: Message to transfer on DSI link.
2668 * @flags: Modifiers for message transfer.
2669 *
2670 * Command transfer can be done only when command engine is enabled. The
2671 * transfer API will block until either the command transfer finishes or
2672 * the timeout value is reached. If the trigger is deferred, it will return
2673 * without triggering the transfer. Command parameters are programmed to
2674 * hardware.
2675 *
2676 * Return: error code.
2677 */
2678int dsi_ctrl_cmd_transfer(struct dsi_ctrl *dsi_ctrl,
2679 const struct mipi_dsi_msg *msg,
2680 u32 flags)
2681{
2682 int rc = 0;
2683
2684 if (!dsi_ctrl || !msg) {
2685 pr_err("Invalid params\n");
2686 return -EINVAL;
2687 }
2688
2689 mutex_lock(&dsi_ctrl->ctrl_lock);
2690
2691 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_CMD_TX, 0x0);
2692 if (rc) {
2693 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002694 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002695 goto error;
2696 }
2697
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002698 if (flags & DSI_CTRL_CMD_READ) {
2699 rc = dsi_message_rx(dsi_ctrl, msg, flags);
Sandeep Panda79450002017-05-08 17:14:24 +05302700 if (rc <= 0)
2701 pr_err("read message failed read length, rc=%d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002702 } else {
2703 rc = dsi_message_tx(dsi_ctrl, msg, flags);
2704 if (rc)
2705 pr_err("command msg transfer failed, rc = %d\n", rc);
2706 }
2707
2708 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_CMD_TX, 0x0);
Ajay Singh Parmar651406a2016-07-20 17:17:49 -07002709
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002710error:
2711 mutex_unlock(&dsi_ctrl->ctrl_lock);
2712 return rc;
2713}
2714
2715/**
2716 * dsi_ctrl_cmd_tx_trigger() - Trigger a deferred command.
2717 * @dsi_ctrl: DSI controller handle.
2718 * @flags: Modifiers.
2719 *
2720 * Return: error code.
2721 */
2722int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
2723{
Clarence Ip80ada7f2017-05-04 09:55:21 -07002724 int rc = 0, ret = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002725 u32 status = 0;
2726 u32 mask = (DSI_CMD_MODE_DMA_DONE);
2727
2728 if (!dsi_ctrl) {
2729 pr_err("Invalid params\n");
2730 return -EINVAL;
2731 }
2732
Vara Reddy326612b2017-09-20 04:41:10 -07002733 /* Dont trigger the command if this is not the last ocmmand */
2734 if (!(flags & DSI_CTRL_CMD_LAST_COMMAND))
2735 return rc;
2736
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002737 mutex_lock(&dsi_ctrl->ctrl_lock);
2738
Clarence Ip80ada7f2017-05-04 09:55:21 -07002739 if (!(flags & DSI_CTRL_CMD_BROADCAST_MASTER))
2740 dsi_ctrl->hw.ops.trigger_command_dma(&dsi_ctrl->hw);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002741
2742 if ((flags & DSI_CTRL_CMD_BROADCAST) &&
Clarence Ip80ada7f2017-05-04 09:55:21 -07002743 (flags & DSI_CTRL_CMD_BROADCAST_MASTER)) {
Sandeep Pandaa2a3c8c2017-07-09 02:10:44 +05302744 dsi_ctrl_wait_for_video_done(dsi_ctrl);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002745 dsi_ctrl_enable_status_interrupt(dsi_ctrl,
2746 DSI_SINT_CMD_MODE_DMA_DONE, NULL);
Sandeep Panda11b20d82017-06-19 12:57:27 +05302747 if (dsi_ctrl->hw.ops.mask_error_intr)
2748 dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
2749 BIT(DSI_FIFO_OVERFLOW), true);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002750 reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002751
Clarence Ip80ada7f2017-05-04 09:55:21 -07002752 /* trigger command */
2753 dsi_ctrl->hw.ops.trigger_command_dma(&dsi_ctrl->hw);
2754
2755 ret = wait_for_completion_timeout(
2756 &dsi_ctrl->irq_info.cmd_dma_done,
2757 msecs_to_jiffies(DSI_CTRL_TX_TO_MS));
2758
2759 if (ret == 0) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002760 status = dsi_ctrl->hw.ops.get_interrupt_status(
2761 &dsi_ctrl->hw);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002762 if (status & mask) {
2763 status |= (DSI_CMD_MODE_DMA_DONE |
2764 DSI_BTA_DONE);
2765 dsi_ctrl->hw.ops.clear_interrupt_status(
2766 &dsi_ctrl->hw,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002767 status);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002768 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
2769 DSI_SINT_CMD_MODE_DMA_DONE);
2770 complete_all(&dsi_ctrl->irq_info.cmd_dma_done);
2771 pr_warn("dma_tx done but irq not triggered\n");
2772 } else {
2773 rc = -ETIMEDOUT;
2774 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
2775 DSI_SINT_CMD_MODE_DMA_DONE);
2776 pr_err("[DSI_%d]Command transfer failed\n",
2777 dsi_ctrl->cell_index);
2778 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002779 }
Sandeep Panda11b20d82017-06-19 12:57:27 +05302780 if (dsi_ctrl->hw.ops.mask_error_intr)
2781 dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
2782 BIT(DSI_FIFO_OVERFLOW), false);
Vara Reddydbeab892017-11-17 16:38:16 -08002783
2784 if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
2785 dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
2786 dsi_ctrl->cmd_len = 0;
2787 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002788 }
2789
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002790 mutex_unlock(&dsi_ctrl->ctrl_lock);
2791 return rc;
2792}
2793
2794/**
Rajkumar Subbiah01e6dd642017-07-05 14:47:47 -04002795 * _dsi_ctrl_cache_misr - Cache frame MISR value
2796 * @dsi_ctrl: Pointer to associated dsi_ctrl structure
2797 */
2798static void _dsi_ctrl_cache_misr(struct dsi_ctrl *dsi_ctrl)
2799{
2800 u32 misr;
2801
2802 if (!dsi_ctrl || !dsi_ctrl->hw.ops.collect_misr)
2803 return;
2804
2805 misr = dsi_ctrl->hw.ops.collect_misr(&dsi_ctrl->hw,
2806 dsi_ctrl->host_config.panel_mode);
2807
2808 if (misr)
2809 dsi_ctrl->misr_cache = misr;
2810
2811 pr_debug("DSI_%d misr_cache = %x\n", dsi_ctrl->cell_index,
2812 dsi_ctrl->misr_cache);
2813
2814}
2815
2816/**
Shashank Babu Chinta Venkata7d608732017-05-31 14:10:26 -07002817 * dsi_ctrl_update_host_engine_state_for_cont_splash() -
2818 * set engine state for dsi controller during continuous splash
2819 * @dsi_ctrl: DSI controller handle.
2820 * @state: Engine state.
2821 *
2822 * Set host engine state for DSI controller during continuous splash.
2823 *
2824 * Return: error code.
2825 */
2826int dsi_ctrl_update_host_engine_state_for_cont_splash(struct dsi_ctrl *dsi_ctrl,
2827 enum dsi_engine_state state)
2828{
2829 int rc = 0;
2830
2831 if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) {
2832 pr_err("Invalid params\n");
2833 return -EINVAL;
2834 }
2835
2836 mutex_lock(&dsi_ctrl->ctrl_lock);
2837
2838 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_ENGINE, state);
2839 if (rc) {
2840 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
2841 dsi_ctrl->cell_index, rc);
2842 goto error;
2843 }
2844
2845 pr_debug("[DSI_%d] Set host engine state = %d\n", dsi_ctrl->cell_index,
2846 state);
2847 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_ENGINE, state);
2848error:
2849 mutex_unlock(&dsi_ctrl->ctrl_lock);
2850 return rc;
2851}
2852
2853/**
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002854 * dsi_ctrl_set_power_state() - set power state for dsi controller
2855 * @dsi_ctrl: DSI controller handle.
2856 * @state: Power state.
2857 *
2858 * Set power state for DSI controller. Power state can be changed only when
2859 * Controller, Video and Command engines are turned off.
2860 *
2861 * Return: error code.
2862 */
2863int dsi_ctrl_set_power_state(struct dsi_ctrl *dsi_ctrl,
2864 enum dsi_power_state state)
2865{
2866 int rc = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002867
2868 if (!dsi_ctrl || (state >= DSI_CTRL_POWER_MAX)) {
2869 pr_err("Invalid Params\n");
2870 return -EINVAL;
2871 }
2872
2873 mutex_lock(&dsi_ctrl->ctrl_lock);
2874
2875 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_POWER_STATE_CHANGE,
2876 state);
2877 if (rc) {
2878 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002879 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002880 goto error;
2881 }
2882
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302883 if (state == DSI_CTRL_POWER_VREG_ON) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002884 rc = dsi_ctrl_enable_supplies(dsi_ctrl, true);
2885 if (rc) {
2886 pr_err("[%d]failed to enable voltage supplies, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002887 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002888 goto error;
2889 }
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302890 } else if (state == DSI_CTRL_POWER_VREG_OFF) {
Rajkumar Subbiah01e6dd642017-07-05 14:47:47 -04002891 if (dsi_ctrl->misr_enable)
2892 _dsi_ctrl_cache_misr(dsi_ctrl);
2893
Dhaval Patel4fc756b62016-08-10 11:25:48 -07002894 rc = dsi_ctrl_enable_supplies(dsi_ctrl, false);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002895 if (rc) {
2896 pr_err("[%d]failed to disable vreg supplies, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002897 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002898 goto error;
2899 }
2900 }
2901
Alexander Beykun32a6a182017-02-27 17:46:51 -05002902 pr_debug("[DSI_%d] Power state updated to %d\n", dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002903 state);
2904 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_POWER_STATE_CHANGE, state);
2905error:
2906 mutex_unlock(&dsi_ctrl->ctrl_lock);
2907 return rc;
2908}
2909
2910/**
2911 * dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller
2912 * @dsi_ctrl: DSI controller handle.
2913 * @on: enable/disable test pattern.
2914 *
2915 * Test pattern can be enabled only after Video engine (for video mode panels)
2916 * or command engine (for cmd mode panels) is enabled.
2917 *
2918 * Return: error code.
2919 */
2920int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on)
2921{
2922 int rc = 0;
2923
2924 if (!dsi_ctrl) {
2925 pr_err("Invalid params\n");
2926 return -EINVAL;
2927 }
2928
2929 mutex_lock(&dsi_ctrl->ctrl_lock);
2930
2931 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_TPG, on);
2932 if (rc) {
2933 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002934 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002935 goto error;
2936 }
2937
2938 if (on) {
2939 if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) {
2940 dsi_ctrl->hw.ops.video_test_pattern_setup(&dsi_ctrl->hw,
2941 DSI_TEST_PATTERN_INC,
2942 0xFFFF);
2943 } else {
2944 dsi_ctrl->hw.ops.cmd_test_pattern_setup(
2945 &dsi_ctrl->hw,
2946 DSI_TEST_PATTERN_INC,
2947 0xFFFF,
2948 0x0);
2949 }
2950 }
2951 dsi_ctrl->hw.ops.test_pattern_enable(&dsi_ctrl->hw, on);
2952
Alexander Beykun32a6a182017-02-27 17:46:51 -05002953 pr_debug("[DSI_%d]Set test pattern state=%d\n",
2954 dsi_ctrl->cell_index, on);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002955 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_TPG, on);
2956error:
2957 mutex_unlock(&dsi_ctrl->ctrl_lock);
2958 return rc;
2959}
2960
2961/**
2962 * dsi_ctrl_set_host_engine_state() - set host engine state
2963 * @dsi_ctrl: DSI Controller handle.
2964 * @state: Engine state.
2965 *
2966 * Host engine state can be modified only when DSI controller power state is
2967 * set to DSI_CTRL_POWER_LINK_CLK_ON and cmd, video engines are disabled.
2968 *
2969 * Return: error code.
2970 */
2971int dsi_ctrl_set_host_engine_state(struct dsi_ctrl *dsi_ctrl,
2972 enum dsi_engine_state state)
2973{
2974 int rc = 0;
2975
2976 if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) {
2977 pr_err("Invalid params\n");
2978 return -EINVAL;
2979 }
2980
2981 mutex_lock(&dsi_ctrl->ctrl_lock);
2982
2983 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_ENGINE, state);
2984 if (rc) {
2985 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002986 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002987 goto error;
2988 }
2989
2990 if (state == DSI_CTRL_ENGINE_ON)
2991 dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true);
2992 else
2993 dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, false);
2994
Alexander Beykun32a6a182017-02-27 17:46:51 -05002995 pr_debug("[DSI_%d] Set host engine state = %d\n", dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002996 state);
2997 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_ENGINE, state);
2998error:
2999 mutex_unlock(&dsi_ctrl->ctrl_lock);
3000 return rc;
3001}
3002
3003/**
3004 * dsi_ctrl_set_cmd_engine_state() - set command engine state
3005 * @dsi_ctrl: DSI Controller handle.
3006 * @state: Engine state.
3007 *
3008 * Command engine state can be modified only when DSI controller power state is
3009 * set to DSI_CTRL_POWER_LINK_CLK_ON.
3010 *
3011 * Return: error code.
3012 */
3013int dsi_ctrl_set_cmd_engine_state(struct dsi_ctrl *dsi_ctrl,
3014 enum dsi_engine_state state)
3015{
3016 int rc = 0;
3017
3018 if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) {
3019 pr_err("Invalid params\n");
3020 return -EINVAL;
3021 }
3022
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003023 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_CMD_ENGINE, state);
3024 if (rc) {
3025 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05003026 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003027 goto error;
3028 }
3029
3030 if (state == DSI_CTRL_ENGINE_ON)
3031 dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, true);
3032 else
3033 dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, false);
3034
Alexander Beykun32a6a182017-02-27 17:46:51 -05003035 pr_debug("[DSI_%d] Set cmd engine state = %d\n", dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003036 state);
3037 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_CMD_ENGINE, state);
3038error:
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003039 return rc;
3040}
3041
3042/**
3043 * dsi_ctrl_set_vid_engine_state() - set video engine state
3044 * @dsi_ctrl: DSI Controller handle.
3045 * @state: Engine state.
3046 *
3047 * Video engine state can be modified only when DSI controller power state is
3048 * set to DSI_CTRL_POWER_LINK_CLK_ON.
3049 *
3050 * Return: error code.
3051 */
3052int dsi_ctrl_set_vid_engine_state(struct dsi_ctrl *dsi_ctrl,
3053 enum dsi_engine_state state)
3054{
3055 int rc = 0;
3056 bool on;
3057
3058 if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) {
3059 pr_err("Invalid params\n");
3060 return -EINVAL;
3061 }
3062
3063 mutex_lock(&dsi_ctrl->ctrl_lock);
3064
3065 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_VID_ENGINE, state);
3066 if (rc) {
3067 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05003068 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003069 goto error;
3070 }
3071
3072 on = (state == DSI_CTRL_ENGINE_ON) ? true : false;
3073 dsi_ctrl->hw.ops.video_engine_en(&dsi_ctrl->hw, on);
3074
3075 /* perform a reset when turning off video engine */
3076 if (!on)
3077 dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
3078
Alexander Beykun32a6a182017-02-27 17:46:51 -05003079 pr_debug("[DSI_%d] Set video engine state = %d\n", dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003080 state);
3081 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_VID_ENGINE, state);
3082error:
3083 mutex_unlock(&dsi_ctrl->ctrl_lock);
3084 return rc;
3085}
3086
3087/**
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07003088 * dsi_ctrl_set_ulps() - set ULPS state for DSI lanes.
3089 * @dsi_ctrl: DSI controller handle.
3090 * @enable: enable/disable ULPS.
3091 *
3092 * ULPS can be enabled/disabled after DSI host engine is turned on.
3093 *
3094 * Return: error code.
3095 */
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003096int dsi_ctrl_set_ulps(struct dsi_ctrl *dsi_ctrl, bool enable)
3097{
3098 int rc = 0;
3099
3100 if (!dsi_ctrl) {
3101 pr_err("Invalid params\n");
3102 return -EINVAL;
3103 }
3104
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05303105 mutex_lock(&dsi_ctrl->ctrl_lock);
3106
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003107 if (enable)
3108 rc = dsi_enable_ulps(dsi_ctrl);
3109 else
3110 rc = dsi_disable_ulps(dsi_ctrl);
3111
3112 if (rc) {
3113 pr_err("[DSI_%d] Ulps state change(%d) failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05003114 dsi_ctrl->cell_index, enable, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003115 goto error;
3116 }
Alexander Beykun32a6a182017-02-27 17:46:51 -05003117 pr_debug("[DSI_%d] ULPS state = %d\n", dsi_ctrl->cell_index, enable);
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05303118
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003119error:
3120 mutex_unlock(&dsi_ctrl->ctrl_lock);
3121 return rc;
3122}
3123
3124/**
3125 * dsi_ctrl_set_clamp_state() - set clamp state for DSI phy
3126 * @dsi_ctrl: DSI controller handle.
3127 * @enable: enable/disable clamping.
3128 *
3129 * Clamps can be enabled/disabled while DSI contoller is still turned on.
3130 *
3131 * Return: error code.
3132 */
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05303133int dsi_ctrl_set_clamp_state(struct dsi_ctrl *dsi_ctrl,
3134 bool enable, bool ulps_enabled)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003135{
3136 int rc = 0;
3137
3138 if (!dsi_ctrl) {
3139 pr_err("Invalid params\n");
3140 return -EINVAL;
3141 }
3142
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05303143 if (!dsi_ctrl->hw.ops.clamp_enable ||
3144 !dsi_ctrl->hw.ops.clamp_disable) {
3145 pr_debug("No clamp control for DSI controller\n");
3146 return 0;
3147 }
3148
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003149 mutex_lock(&dsi_ctrl->ctrl_lock);
3150
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05303151 rc = dsi_enable_io_clamp(dsi_ctrl, enable, ulps_enabled);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003152 if (rc) {
Alexander Beykun32a6a182017-02-27 17:46:51 -05003153 pr_err("[DSI_%d] Failed to enable IO clamp\n",
3154 dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003155 goto error;
3156 }
3157
Alexander Beykun32a6a182017-02-27 17:46:51 -05003158 pr_debug("[DSI_%d] Clamp state = %d\n", dsi_ctrl->cell_index, enable);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003159error:
3160 mutex_unlock(&dsi_ctrl->ctrl_lock);
3161 return rc;
3162}
3163
3164/**
3165 * dsi_ctrl_set_clock_source() - set clock source fpr dsi link clocks
3166 * @dsi_ctrl: DSI controller handle.
3167 * @source_clks: Source clocks for DSI link clocks.
3168 *
3169 * Clock source should be changed while link clocks are disabled.
3170 *
3171 * Return: error code.
3172 */
3173int dsi_ctrl_set_clock_source(struct dsi_ctrl *dsi_ctrl,
3174 struct dsi_clk_link_set *source_clks)
3175{
3176 int rc = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003177
3178 if (!dsi_ctrl || !source_clks) {
3179 pr_err("Invalid params\n");
3180 return -EINVAL;
3181 }
3182
3183 mutex_lock(&dsi_ctrl->ctrl_lock);
3184
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003185 rc = dsi_clk_update_parent(source_clks, &dsi_ctrl->clk_info.rcg_clks);
3186 if (rc) {
3187 pr_err("[DSI_%d]Failed to update link clk parent, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05003188 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003189 (void)dsi_clk_update_parent(&dsi_ctrl->clk_info.pll_op_clks,
3190 &dsi_ctrl->clk_info.rcg_clks);
3191 goto error;
3192 }
3193
3194 dsi_ctrl->clk_info.pll_op_clks.byte_clk = source_clks->byte_clk;
3195 dsi_ctrl->clk_info.pll_op_clks.pixel_clk = source_clks->pixel_clk;
3196
Alexander Beykun32a6a182017-02-27 17:46:51 -05003197 pr_debug("[DSI_%d] Source clocks are updated\n", dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003198
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003199error:
3200 mutex_unlock(&dsi_ctrl->ctrl_lock);
3201 return rc;
3202}
3203
3204/**
Rajkumar Subbiah01e6dd642017-07-05 14:47:47 -04003205 * dsi_ctrl_setup_misr() - Setup frame MISR
3206 * @dsi_ctrl: DSI controller handle.
3207 * @enable: enable/disable MISR.
3208 * @frame_count: Number of frames to accumulate MISR.
3209 *
3210 * Return: error code.
3211 */
3212int dsi_ctrl_setup_misr(struct dsi_ctrl *dsi_ctrl,
3213 bool enable,
3214 u32 frame_count)
3215{
3216 if (!dsi_ctrl) {
3217 pr_err("Invalid params\n");
3218 return -EINVAL;
3219 }
3220
3221 if (!dsi_ctrl->hw.ops.setup_misr)
3222 return 0;
3223
3224 mutex_lock(&dsi_ctrl->ctrl_lock);
3225 dsi_ctrl->misr_enable = enable;
3226 dsi_ctrl->hw.ops.setup_misr(&dsi_ctrl->hw,
3227 dsi_ctrl->host_config.panel_mode,
3228 enable, frame_count);
3229 mutex_unlock(&dsi_ctrl->ctrl_lock);
3230 return 0;
3231}
3232
3233/**
3234 * dsi_ctrl_collect_misr() - Read frame MISR
3235 * @dsi_ctrl: DSI controller handle.
3236 *
3237 * Return: MISR value.
3238 */
3239u32 dsi_ctrl_collect_misr(struct dsi_ctrl *dsi_ctrl)
3240{
3241 u32 misr;
3242
3243 if (!dsi_ctrl || !dsi_ctrl->hw.ops.collect_misr)
3244 return 0;
3245
3246 misr = dsi_ctrl->hw.ops.collect_misr(&dsi_ctrl->hw,
3247 dsi_ctrl->host_config.panel_mode);
3248 if (!misr)
3249 misr = dsi_ctrl->misr_cache;
3250
3251 pr_debug("DSI_%d cached misr = %x, final = %x\n",
3252 dsi_ctrl->cell_index, dsi_ctrl->misr_cache, misr);
3253
3254 return misr;
3255}
3256
3257/**
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003258 * dsi_ctrl_drv_register() - register platform driver for dsi controller
3259 */
Ajay Singh Parmar64c19192016-06-10 16:44:56 -07003260void dsi_ctrl_drv_register(void)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003261{
3262 platform_driver_register(&dsi_ctrl_driver);
3263}
3264
3265/**
3266 * dsi_ctrl_drv_unregister() - unregister platform driver
3267 */
Ajay Singh Parmar64c19192016-06-10 16:44:56 -07003268void dsi_ctrl_drv_unregister(void)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07003269{
3270 platform_driver_unregister(&dsi_ctrl_driver);
3271}