blob: 6af4118165b739d75022eadbd2ad9bfd1a6dd6a3 [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")
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070041/**
42 * enum dsi_ctrl_driver_ops - controller driver ops
43 */
44enum dsi_ctrl_driver_ops {
45 DSI_CTRL_OP_POWER_STATE_CHANGE,
46 DSI_CTRL_OP_CMD_ENGINE,
47 DSI_CTRL_OP_VID_ENGINE,
48 DSI_CTRL_OP_HOST_ENGINE,
49 DSI_CTRL_OP_CMD_TX,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070050 DSI_CTRL_OP_HOST_INIT,
51 DSI_CTRL_OP_TPG,
52 DSI_CTRL_OP_PHY_SW_RESET,
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -070053 DSI_CTRL_OP_ASYNC_TIMING,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070054 DSI_CTRL_OP_MAX
55};
56
57struct dsi_ctrl_list_item {
58 struct dsi_ctrl *ctrl;
59 struct list_head list;
60};
61
62static LIST_HEAD(dsi_ctrl_list);
63static DEFINE_MUTEX(dsi_ctrl_list_lock);
64
65static const enum dsi_ctrl_version dsi_ctrl_v1_4 = DSI_CTRL_VERSION_1_4;
66static const enum dsi_ctrl_version dsi_ctrl_v2_0 = DSI_CTRL_VERSION_2_0;
Shashank Babu Chinta Venkataafef8202017-04-21 13:49:56 -070067static const enum dsi_ctrl_version dsi_ctrl_v2_2 = DSI_CTRL_VERSION_2_2;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070068
69static const struct of_device_id msm_dsi_of_match[] = {
70 {
71 .compatible = "qcom,dsi-ctrl-hw-v1.4",
72 .data = &dsi_ctrl_v1_4,
73 },
74 {
75 .compatible = "qcom,dsi-ctrl-hw-v2.0",
76 .data = &dsi_ctrl_v2_0,
77 },
Shashank Babu Chinta Venkataafef8202017-04-21 13:49:56 -070078 {
79 .compatible = "qcom,dsi-ctrl-hw-v2.2",
80 .data = &dsi_ctrl_v2_2,
81 },
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -070082 {}
83};
84
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -070085static ssize_t debugfs_state_info_read(struct file *file,
86 char __user *buff,
87 size_t count,
88 loff_t *ppos)
89{
90 struct dsi_ctrl *dsi_ctrl = file->private_data;
91 char *buf;
92 u32 len = 0;
93
94 if (!dsi_ctrl)
95 return -ENODEV;
96
97 if (*ppos)
98 return 0;
99
100 buf = kzalloc(SZ_4K, GFP_KERNEL);
101 if (!buf)
102 return -ENOMEM;
103
104 /* Dump current state */
105 len += snprintf((buf + len), (SZ_4K - len), "Current State:\n");
106 len += snprintf((buf + len), (SZ_4K - len),
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530107 "\tCTRL_ENGINE = %s\n",
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700108 TO_ON_OFF(dsi_ctrl->current_state.controller_state));
109 len += snprintf((buf + len), (SZ_4K - len),
110 "\tVIDEO_ENGINE = %s\n\tCOMMAND_ENGINE = %s\n",
111 TO_ON_OFF(dsi_ctrl->current_state.vid_engine_state),
112 TO_ON_OFF(dsi_ctrl->current_state.cmd_engine_state));
113
114 /* Dump clock information */
115 len += snprintf((buf + len), (SZ_4K - len), "\nClock Info:\n");
116 len += snprintf((buf + len), (SZ_4K - len),
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530117 "\tBYTE_CLK = %u, PIXEL_CLK = %u, ESC_CLK = %u\n",
118 dsi_ctrl->clk_freq.byte_clk_rate,
119 dsi_ctrl->clk_freq.pix_clk_rate,
120 dsi_ctrl->clk_freq.esc_clk_rate);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700121
122 /* TODO: make sure that this does not exceed 4K */
123 if (copy_to_user(buff, buf, len)) {
124 kfree(buf);
125 return -EFAULT;
126 }
127
128 *ppos += len;
129 kfree(buf);
130 return len;
131}
132
133static ssize_t debugfs_reg_dump_read(struct file *file,
134 char __user *buff,
135 size_t count,
136 loff_t *ppos)
137{
138 struct dsi_ctrl *dsi_ctrl = file->private_data;
139 char *buf;
140 u32 len = 0;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530141 struct dsi_clk_ctrl_info clk_info;
142 int rc = 0;
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700143
144 if (!dsi_ctrl)
145 return -ENODEV;
146
147 if (*ppos)
148 return 0;
149
150 buf = kzalloc(SZ_4K, GFP_KERNEL);
151 if (!buf)
152 return -ENOMEM;
153
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530154 clk_info.client = DSI_CLK_REQ_DSI_CLIENT;
155 clk_info.clk_type = DSI_CORE_CLK;
156 clk_info.clk_state = DSI_CLK_ON;
157
158 rc = dsi_ctrl->clk_cb.dsi_clk_cb(dsi_ctrl->clk_cb.priv, clk_info);
159 if (rc) {
160 pr_err("failed to enable DSI core clocks\n");
161 kfree(buf);
162 return rc;
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700163 }
164
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +0530165 if (dsi_ctrl->hw.ops.reg_dump_to_buffer)
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530166 len = dsi_ctrl->hw.ops.reg_dump_to_buffer(&dsi_ctrl->hw,
167 buf, SZ_4K);
168
169 clk_info.clk_state = DSI_CLK_OFF;
170 rc = dsi_ctrl->clk_cb.dsi_clk_cb(dsi_ctrl->clk_cb.priv, clk_info);
171 if (rc) {
172 pr_err("failed to disable DSI core clocks\n");
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +0530173 kfree(buf);
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530174 return rc;
175 }
176
177
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700178 /* TODO: make sure that this does not exceed 4K */
179 if (copy_to_user(buff, buf, len)) {
180 kfree(buf);
181 return -EFAULT;
182 }
183
184 *ppos += len;
185 kfree(buf);
186 return len;
187}
188
189static const struct file_operations state_info_fops = {
190 .open = simple_open,
191 .read = debugfs_state_info_read,
192};
193
194static const struct file_operations reg_dump_fops = {
195 .open = simple_open,
196 .read = debugfs_reg_dump_read,
197};
198
199static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl,
200 struct dentry *parent)
201{
202 int rc = 0;
203 struct dentry *dir, *state_file, *reg_dump;
Dhaval Patela2430842017-06-15 14:32:36 -0700204 char dbg_name[DSI_DEBUG_NAME_LEN];
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700205
206 dir = debugfs_create_dir(dsi_ctrl->name, parent);
207 if (IS_ERR_OR_NULL(dir)) {
208 rc = PTR_ERR(dir);
209 pr_err("[DSI_%d] debugfs create dir failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500210 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700211 goto error;
212 }
213
214 state_file = debugfs_create_file("state_info",
215 0444,
216 dir,
217 dsi_ctrl,
218 &state_info_fops);
219 if (IS_ERR_OR_NULL(state_file)) {
220 rc = PTR_ERR(state_file);
221 pr_err("[DSI_%d] state file failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500222 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700223 goto error_remove_dir;
224 }
225
226 reg_dump = debugfs_create_file("reg_dump",
227 0444,
228 dir,
229 dsi_ctrl,
230 &reg_dump_fops);
231 if (IS_ERR_OR_NULL(reg_dump)) {
232 rc = PTR_ERR(reg_dump);
233 pr_err("[DSI_%d] reg dump file failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500234 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700235 goto error_remove_dir;
236 }
237
238 dsi_ctrl->debugfs_root = dir;
Dhaval Patela2430842017-06-15 14:32:36 -0700239
240 snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_ctrl",
241 dsi_ctrl->cell_index);
242 sde_dbg_reg_register_base(dbg_name, dsi_ctrl->hw.base,
243 msm_iomap_size(dsi_ctrl->pdev, "dsi_ctrl"));
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -0700244error_remove_dir:
245 debugfs_remove(dir);
246error:
247 return rc;
248}
249
250static int dsi_ctrl_debugfs_deinit(struct dsi_ctrl *dsi_ctrl)
251{
252 debugfs_remove(dsi_ctrl->debugfs_root);
253 return 0;
254}
255
Jordan Croused8e96522017-02-13 10:14:16 -0700256static inline struct msm_gem_address_space*
257dsi_ctrl_get_aspace(struct dsi_ctrl *dsi_ctrl,
258 int domain)
259{
260 if (!dsi_ctrl || !dsi_ctrl->drm_dev)
261 return NULL;
262
263 return msm_gem_smmu_address_space_get(dsi_ctrl->drm_dev, domain);
264}
265
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700266static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl,
267 enum dsi_ctrl_driver_ops op,
268 u32 op_state)
269{
270 int rc = 0;
271 struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state;
272
273 switch (op) {
274 case DSI_CTRL_OP_POWER_STATE_CHANGE:
275 if (state->power_state == op_state) {
276 pr_debug("[%d] No change in state, pwr_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500277 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700278 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530279 } else if (state->power_state == DSI_CTRL_POWER_VREG_ON) {
Veera Sundaram Sankaran4e109162017-04-21 10:36:46 -0700280 if (state->vid_engine_state == DSI_CTRL_ENGINE_ON) {
281 pr_debug("[%d]State error: op=%d: %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500282 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700283 op_state,
Veera Sundaram Sankaran4e109162017-04-21 10:36:46 -0700284 state->vid_engine_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700285 rc = -EINVAL;
286 }
287 }
288 break;
289 case DSI_CTRL_OP_CMD_ENGINE:
290 if (state->cmd_engine_state == op_state) {
291 pr_debug("[%d] No change in state, cmd_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500292 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700293 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530294 } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700295 (state->controller_state != DSI_CTRL_ENGINE_ON)) {
296 pr_debug("[%d]State error: op=%d: %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500297 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700298 op,
299 state->power_state,
300 state->controller_state);
301 rc = -EINVAL;
302 }
303 break;
304 case DSI_CTRL_OP_VID_ENGINE:
305 if (state->vid_engine_state == op_state) {
306 pr_debug("[%d] No change in state, cmd_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500307 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700308 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530309 } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700310 (state->controller_state != DSI_CTRL_ENGINE_ON)) {
311 pr_debug("[%d]State error: op=%d: %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500312 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700313 op,
314 state->power_state,
315 state->controller_state);
316 rc = -EINVAL;
317 }
318 break;
319 case DSI_CTRL_OP_HOST_ENGINE:
320 if (state->controller_state == op_state) {
321 pr_debug("[%d] No change in state, ctrl_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500322 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700323 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530324 } else if (state->power_state != DSI_CTRL_POWER_VREG_ON) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700325 pr_debug("[%d]State error (link is off): op=%d:, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500326 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700327 op_state,
328 state->power_state);
329 rc = -EINVAL;
330 } else if ((op_state == DSI_CTRL_ENGINE_OFF) &&
331 ((state->cmd_engine_state != DSI_CTRL_ENGINE_OFF) ||
332 (state->vid_engine_state != DSI_CTRL_ENGINE_OFF))) {
333 pr_debug("[%d]State error (eng on): op=%d: %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500334 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700335 op_state,
336 state->cmd_engine_state,
337 state->vid_engine_state);
338 rc = -EINVAL;
339 }
340 break;
341 case DSI_CTRL_OP_CMD_TX:
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530342 if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700343 (state->host_initialized != true) ||
344 (state->cmd_engine_state != DSI_CTRL_ENGINE_ON)) {
345 pr_debug("[%d]State error: op=%d: %d, %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500346 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700347 op,
348 state->power_state,
349 state->host_initialized,
350 state->cmd_engine_state);
351 rc = -EINVAL;
352 }
353 break;
354 case DSI_CTRL_OP_HOST_INIT:
355 if (state->host_initialized == op_state) {
356 pr_debug("[%d] No change in state, host_init=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500357 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700358 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530359 } else if (state->power_state != DSI_CTRL_POWER_VREG_ON) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700360 pr_debug("[%d]State error: op=%d: %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500361 dsi_ctrl->cell_index, op, state->power_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700362 rc = -EINVAL;
363 }
364 break;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700365 case DSI_CTRL_OP_TPG:
366 if (state->tpg_enabled == op_state) {
367 pr_debug("[%d] No change in state, tpg_enabled=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500368 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700369 rc = -EINVAL;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530370 } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700371 (state->controller_state != DSI_CTRL_ENGINE_ON)) {
372 pr_debug("[%d]State error: op=%d: %d, %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500373 dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700374 op,
375 state->power_state,
376 state->controller_state);
377 rc = -EINVAL;
378 }
379 break;
380 case DSI_CTRL_OP_PHY_SW_RESET:
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530381 if (state->power_state != DSI_CTRL_POWER_VREG_ON) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700382 pr_debug("[%d]State error: op=%d: %d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500383 dsi_ctrl->cell_index, op, state->power_state);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700384 rc = -EINVAL;
385 }
386 break;
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -0700387 case DSI_CTRL_OP_ASYNC_TIMING:
388 if (state->vid_engine_state != op_state) {
389 pr_err("[%d] Unexpected engine state vid_state=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -0500390 dsi_ctrl->cell_index, op_state);
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -0700391 rc = -EINVAL;
392 }
393 break;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700394 default:
395 rc = -ENOTSUPP;
396 break;
397 }
398
399 return rc;
400}
401
402static void dsi_ctrl_update_state(struct dsi_ctrl *dsi_ctrl,
403 enum dsi_ctrl_driver_ops op,
404 u32 op_state)
405{
406 struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state;
407
408 switch (op) {
409 case DSI_CTRL_OP_POWER_STATE_CHANGE:
410 state->power_state = op_state;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700411 break;
412 case DSI_CTRL_OP_CMD_ENGINE:
413 state->cmd_engine_state = op_state;
414 break;
415 case DSI_CTRL_OP_VID_ENGINE:
416 state->vid_engine_state = op_state;
417 break;
418 case DSI_CTRL_OP_HOST_ENGINE:
419 state->controller_state = op_state;
420 break;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700421 case DSI_CTRL_OP_HOST_INIT:
422 state->host_initialized = (op_state == 1) ? true : false;
423 break;
424 case DSI_CTRL_OP_TPG:
425 state->tpg_enabled = (op_state == 1) ? true : false;
426 break;
427 case DSI_CTRL_OP_CMD_TX:
428 case DSI_CTRL_OP_PHY_SW_RESET:
429 default:
430 break;
431 }
432}
433
434static int dsi_ctrl_init_regmap(struct platform_device *pdev,
435 struct dsi_ctrl *ctrl)
436{
437 int rc = 0;
438 void __iomem *ptr;
439
440 ptr = msm_ioremap(pdev, "dsi_ctrl", ctrl->name);
441 if (IS_ERR(ptr)) {
442 rc = PTR_ERR(ptr);
443 return rc;
444 }
445
446 ctrl->hw.base = ptr;
447 pr_debug("[%s] map dsi_ctrl registers to %p\n", ctrl->name,
448 ctrl->hw.base);
449
Shashank Babu Chinta Venkataafef8202017-04-21 13:49:56 -0700450 switch (ctrl->version) {
451 case DSI_CTRL_VERSION_1_4:
452 case DSI_CTRL_VERSION_2_0:
453 ptr = msm_ioremap(pdev, "mmss_misc", ctrl->name);
454 if (IS_ERR(ptr)) {
455 pr_err("mmss_misc base address not found for [%s]\n",
456 ctrl->name);
457 rc = PTR_ERR(ptr);
458 return rc;
459 }
460 ctrl->hw.mmss_misc_base = ptr;
461 ctrl->hw.disp_cc_base = NULL;
462 break;
463 case DSI_CTRL_VERSION_2_2:
464 ptr = msm_ioremap(pdev, "disp_cc_base", ctrl->name);
465 if (IS_ERR(ptr)) {
466 pr_err("disp_cc base address not found for [%s]\n",
467 ctrl->name);
468 rc = PTR_ERR(ptr);
469 return rc;
470 }
471 ctrl->hw.disp_cc_base = ptr;
472 ctrl->hw.mmss_misc_base = NULL;
473 break;
474 default:
475 break;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700476 }
477
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700478 return rc;
479}
480
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700481static int dsi_ctrl_clocks_deinit(struct dsi_ctrl *ctrl)
482{
483 struct dsi_core_clk_info *core = &ctrl->clk_info.core_clks;
484 struct dsi_link_clk_info *link = &ctrl->clk_info.link_clks;
485 struct dsi_clk_link_set *rcg = &ctrl->clk_info.rcg_clks;
486
487 if (core->mdp_core_clk)
488 devm_clk_put(&ctrl->pdev->dev, core->mdp_core_clk);
489 if (core->iface_clk)
490 devm_clk_put(&ctrl->pdev->dev, core->iface_clk);
491 if (core->core_mmss_clk)
492 devm_clk_put(&ctrl->pdev->dev, core->core_mmss_clk);
493 if (core->bus_clk)
494 devm_clk_put(&ctrl->pdev->dev, core->bus_clk);
Padmanabhan Komanduru2dd6ff62016-12-19 12:31:36 +0530495 if (core->mnoc_clk)
496 devm_clk_put(&ctrl->pdev->dev, core->mnoc_clk);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700497
498 memset(core, 0x0, sizeof(*core));
499
500 if (link->byte_clk)
501 devm_clk_put(&ctrl->pdev->dev, link->byte_clk);
502 if (link->pixel_clk)
503 devm_clk_put(&ctrl->pdev->dev, link->pixel_clk);
504 if (link->esc_clk)
505 devm_clk_put(&ctrl->pdev->dev, link->esc_clk);
Padmanabhan Komanduru2dd6ff62016-12-19 12:31:36 +0530506 if (link->byte_intf_clk)
507 devm_clk_put(&ctrl->pdev->dev, link->byte_intf_clk);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700508
509 memset(link, 0x0, sizeof(*link));
510
511 if (rcg->byte_clk)
512 devm_clk_put(&ctrl->pdev->dev, rcg->byte_clk);
513 if (rcg->pixel_clk)
514 devm_clk_put(&ctrl->pdev->dev, rcg->pixel_clk);
515
516 memset(rcg, 0x0, sizeof(*rcg));
517
518 return 0;
519}
520
521static int dsi_ctrl_clocks_init(struct platform_device *pdev,
522 struct dsi_ctrl *ctrl)
523{
524 int rc = 0;
525 struct dsi_core_clk_info *core = &ctrl->clk_info.core_clks;
526 struct dsi_link_clk_info *link = &ctrl->clk_info.link_clks;
527 struct dsi_clk_link_set *rcg = &ctrl->clk_info.rcg_clks;
528
529 core->mdp_core_clk = devm_clk_get(&pdev->dev, "mdp_core_clk");
530 if (IS_ERR(core->mdp_core_clk)) {
Shashank Babu Chinta Venkata74a03f12017-02-28 11:24:51 -0800531 core->mdp_core_clk = NULL;
532 pr_debug("failed to get mdp_core_clk, rc=%d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700533 }
534
535 core->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
536 if (IS_ERR(core->iface_clk)) {
Shashank Babu Chinta Venkata74a03f12017-02-28 11:24:51 -0800537 core->iface_clk = NULL;
538 pr_debug("failed to get iface_clk, rc=%d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700539 }
540
541 core->core_mmss_clk = devm_clk_get(&pdev->dev, "core_mmss_clk");
542 if (IS_ERR(core->core_mmss_clk)) {
Shashank Babu Chinta Venkata74a03f12017-02-28 11:24:51 -0800543 core->core_mmss_clk = NULL;
544 pr_debug("failed to get core_mmss_clk, rc=%d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700545 }
546
547 core->bus_clk = devm_clk_get(&pdev->dev, "bus_clk");
548 if (IS_ERR(core->bus_clk)) {
Shashank Babu Chinta Venkata74a03f12017-02-28 11:24:51 -0800549 core->bus_clk = NULL;
550 pr_debug("failed to get bus_clk, rc=%d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700551 }
552
Padmanabhan Komanduru2dd6ff62016-12-19 12:31:36 +0530553 core->mnoc_clk = devm_clk_get(&pdev->dev, "mnoc_clk");
554 if (IS_ERR(core->mnoc_clk)) {
555 core->mnoc_clk = NULL;
556 pr_debug("can't get mnoc clock, rc=%d\n", rc);
557 }
558
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700559 link->byte_clk = devm_clk_get(&pdev->dev, "byte_clk");
560 if (IS_ERR(link->byte_clk)) {
561 rc = PTR_ERR(link->byte_clk);
562 pr_err("failed to get byte_clk, rc=%d\n", rc);
563 goto fail;
564 }
565
566 link->pixel_clk = devm_clk_get(&pdev->dev, "pixel_clk");
567 if (IS_ERR(link->pixel_clk)) {
568 rc = PTR_ERR(link->pixel_clk);
569 pr_err("failed to get pixel_clk, rc=%d\n", rc);
570 goto fail;
571 }
572
Shashank Babu Chinta Venkata2f24e982017-04-21 14:57:53 -0700573 link->esc_clk = devm_clk_get(&pdev->dev, "esc_clk");
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700574 if (IS_ERR(link->esc_clk)) {
575 rc = PTR_ERR(link->esc_clk);
576 pr_err("failed to get esc_clk, rc=%d\n", rc);
577 goto fail;
578 }
579
Padmanabhan Komanduru2dd6ff62016-12-19 12:31:36 +0530580 link->byte_intf_clk = devm_clk_get(&pdev->dev, "byte_intf_clk");
581 if (IS_ERR(link->byte_intf_clk)) {
582 link->byte_intf_clk = NULL;
583 pr_debug("can't find byte intf clk, rc=%d\n", rc);
584 }
585
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700586 rcg->byte_clk = devm_clk_get(&pdev->dev, "byte_clk_rcg");
587 if (IS_ERR(rcg->byte_clk)) {
588 rc = PTR_ERR(rcg->byte_clk);
589 pr_err("failed to get byte_clk_rcg, rc=%d\n", rc);
590 goto fail;
591 }
592
593 rcg->pixel_clk = devm_clk_get(&pdev->dev, "pixel_clk_rcg");
594 if (IS_ERR(rcg->pixel_clk)) {
595 rc = PTR_ERR(rcg->pixel_clk);
596 pr_err("failed to get pixel_clk_rcg, rc=%d\n", rc);
597 goto fail;
598 }
599
600 return 0;
601fail:
602 dsi_ctrl_clocks_deinit(ctrl);
603 return rc;
604}
605
606static int dsi_ctrl_supplies_deinit(struct dsi_ctrl *ctrl)
607{
608 int i = 0;
609 int rc = 0;
610 struct dsi_regulator_info *regs;
611
612 regs = &ctrl->pwr_info.digital;
613 for (i = 0; i < regs->count; i++) {
614 if (!regs->vregs[i].vreg)
615 pr_err("vreg is NULL, should not reach here\n");
616 else
617 devm_regulator_put(regs->vregs[i].vreg);
618 }
619
620 regs = &ctrl->pwr_info.host_pwr;
621 for (i = 0; i < regs->count; i++) {
622 if (!regs->vregs[i].vreg)
623 pr_err("vreg is NULL, should not reach here\n");
624 else
625 devm_regulator_put(regs->vregs[i].vreg);
626 }
627
628 if (!ctrl->pwr_info.host_pwr.vregs) {
629 devm_kfree(&ctrl->pdev->dev, ctrl->pwr_info.host_pwr.vregs);
630 ctrl->pwr_info.host_pwr.vregs = NULL;
631 ctrl->pwr_info.host_pwr.count = 0;
632 }
633
634 if (!ctrl->pwr_info.digital.vregs) {
635 devm_kfree(&ctrl->pdev->dev, ctrl->pwr_info.digital.vregs);
636 ctrl->pwr_info.digital.vregs = NULL;
637 ctrl->pwr_info.digital.count = 0;
638 }
639
640 return rc;
641}
642
643static int dsi_ctrl_supplies_init(struct platform_device *pdev,
644 struct dsi_ctrl *ctrl)
645{
646 int rc = 0;
647 int i = 0;
648 struct dsi_regulator_info *regs;
649 struct regulator *vreg = NULL;
650
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530651 rc = dsi_pwr_get_dt_vreg_data(&pdev->dev,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700652 &ctrl->pwr_info.digital,
653 "qcom,core-supply-entries");
Shashank Babu Chinta Venkata9a5a7b92017-04-24 18:22:41 -0700654 if (rc)
655 pr_debug("failed to get digital supply, rc = %d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700656
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530657 rc = dsi_pwr_get_dt_vreg_data(&pdev->dev,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700658 &ctrl->pwr_info.host_pwr,
659 "qcom,ctrl-supply-entries");
660 if (rc) {
661 pr_err("failed to get host power supplies, rc = %d\n", rc);
662 goto error_digital;
663 }
664
665 regs = &ctrl->pwr_info.digital;
666 for (i = 0; i < regs->count; i++) {
667 vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name);
668 if (IS_ERR(vreg)) {
669 pr_err("failed to get %s regulator\n",
670 regs->vregs[i].vreg_name);
671 rc = PTR_ERR(vreg);
672 goto error_host_pwr;
673 }
674 regs->vregs[i].vreg = vreg;
675 }
676
677 regs = &ctrl->pwr_info.host_pwr;
678 for (i = 0; i < regs->count; i++) {
679 vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name);
680 if (IS_ERR(vreg)) {
681 pr_err("failed to get %s regulator\n",
682 regs->vregs[i].vreg_name);
683 for (--i; i >= 0; i--)
684 devm_regulator_put(regs->vregs[i].vreg);
685 rc = PTR_ERR(vreg);
686 goto error_digital_put;
687 }
688 regs->vregs[i].vreg = vreg;
689 }
690
691 return rc;
692
693error_digital_put:
694 regs = &ctrl->pwr_info.digital;
695 for (i = 0; i < regs->count; i++)
696 devm_regulator_put(regs->vregs[i].vreg);
697error_host_pwr:
698 devm_kfree(&pdev->dev, ctrl->pwr_info.host_pwr.vregs);
699 ctrl->pwr_info.host_pwr.vregs = NULL;
700 ctrl->pwr_info.host_pwr.count = 0;
701error_digital:
Shashank Babu Chinta Venkata9a5a7b92017-04-24 18:22:41 -0700702 if (ctrl->pwr_info.digital.vregs)
703 devm_kfree(&pdev->dev, ctrl->pwr_info.digital.vregs);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700704 ctrl->pwr_info.digital.vregs = NULL;
705 ctrl->pwr_info.digital.count = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700706 return rc;
707}
708
709static int dsi_ctrl_axi_bus_client_init(struct platform_device *pdev,
710 struct dsi_ctrl *ctrl)
711{
712 int rc = 0;
713 struct dsi_ctrl_bus_scale_info *bus = &ctrl->axi_bus_info;
714
715 bus->bus_scale_table = msm_bus_cl_get_pdata(pdev);
716 if (IS_ERR_OR_NULL(bus->bus_scale_table)) {
717 rc = PTR_ERR(bus->bus_scale_table);
Shashank Babu Chinta Venkatacf411332017-05-10 17:30:08 -0700718 pr_debug("msm_bus_cl_get_pdata() failed, rc = %d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700719 bus->bus_scale_table = NULL;
720 return rc;
721 }
722
723 bus->bus_handle = msm_bus_scale_register_client(bus->bus_scale_table);
724 if (!bus->bus_handle) {
725 rc = -EINVAL;
726 pr_err("failed to register axi bus client\n");
727 }
728
729 return rc;
730}
731
732static int dsi_ctrl_axi_bus_client_deinit(struct dsi_ctrl *ctrl)
733{
734 struct dsi_ctrl_bus_scale_info *bus = &ctrl->axi_bus_info;
735
736 if (bus->bus_handle) {
737 msm_bus_scale_unregister_client(bus->bus_handle);
738
739 bus->bus_handle = 0;
740 }
741
742 return 0;
743}
744
745static int dsi_ctrl_validate_panel_info(struct dsi_ctrl *dsi_ctrl,
746 struct dsi_host_config *config)
747{
748 int rc = 0;
749 struct dsi_host_common_cfg *host_cfg = &config->common_config;
750
751 if (config->panel_mode >= DSI_OP_MODE_MAX) {
752 pr_err("Invalid dsi operation mode (%d)\n", config->panel_mode);
753 rc = -EINVAL;
754 goto err;
755 }
756
757 if ((host_cfg->data_lanes & (DSI_CLOCK_LANE - 1)) == 0) {
758 pr_err("No data lanes are enabled\n");
759 rc = -EINVAL;
760 goto err;
761 }
762err:
763 return rc;
764}
765
766static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530767 struct dsi_host_config *config, void *clk_handle)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700768{
769 int rc = 0;
770 u32 num_of_lanes = 0;
771 u32 bpp = 3;
772 u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane,
773 byte_clk_rate;
774 struct dsi_host_common_cfg *host_cfg = &config->common_config;
775 struct dsi_mode_info *timing = &config->video_timing;
776
777 if (host_cfg->data_lanes & DSI_DATA_LANE_0)
778 num_of_lanes++;
779 if (host_cfg->data_lanes & DSI_DATA_LANE_1)
780 num_of_lanes++;
781 if (host_cfg->data_lanes & DSI_DATA_LANE_2)
782 num_of_lanes++;
783 if (host_cfg->data_lanes & DSI_DATA_LANE_3)
784 num_of_lanes++;
785
Alexander Beykunac182352017-02-27 17:46:51 -0500786 h_period = DSI_H_TOTAL_DSC(timing);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700787 v_period = DSI_V_TOTAL(timing);
788
789 bit_rate = h_period * v_period * timing->refresh_rate * bpp * 8;
790 bit_rate_per_lane = bit_rate;
791 do_div(bit_rate_per_lane, num_of_lanes);
792 pclk_rate = bit_rate;
793 do_div(pclk_rate, (8 * bpp));
794 byte_clk_rate = bit_rate_per_lane;
795 do_div(byte_clk_rate, 8);
796 pr_debug("bit_clk_rate = %llu, bit_clk_rate_per_lane = %llu\n",
797 bit_rate, bit_rate_per_lane);
798 pr_debug("byte_clk_rate = %llu, pclk_rate = %llu\n",
799 byte_clk_rate, pclk_rate);
800
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530801 dsi_ctrl->clk_freq.byte_clk_rate = byte_clk_rate;
802 dsi_ctrl->clk_freq.pix_clk_rate = pclk_rate;
803 dsi_ctrl->clk_freq.esc_clk_rate = config->esc_clk_rate_hz;
804
805 rc = dsi_clk_set_link_frequencies(clk_handle, dsi_ctrl->clk_freq,
Alexander Beykun32a6a182017-02-27 17:46:51 -0500806 dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700807 if (rc)
808 pr_err("Failed to update link frequencies\n");
809
810 return rc;
811}
812
813static int dsi_ctrl_enable_supplies(struct dsi_ctrl *dsi_ctrl, bool enable)
814{
815 int rc = 0;
816
817 if (enable) {
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530818 if (!dsi_ctrl->current_state.host_initialized) {
819 rc = dsi_pwr_enable_regulator(
820 &dsi_ctrl->pwr_info.host_pwr, true);
821 if (rc) {
822 pr_err("failed to enable host power regs\n");
823 goto error;
824 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700825 }
826
827 rc = dsi_pwr_enable_regulator(&dsi_ctrl->pwr_info.digital,
828 true);
829 if (rc) {
830 pr_err("failed to enable gdsc, rc=%d\n", rc);
831 (void)dsi_pwr_enable_regulator(
832 &dsi_ctrl->pwr_info.host_pwr,
833 false
834 );
835 goto error;
836 }
837 } else {
838 rc = dsi_pwr_enable_regulator(&dsi_ctrl->pwr_info.digital,
839 false);
840 if (rc) {
841 pr_err("failed to disable gdsc, rc=%d\n", rc);
842 goto error;
843 }
844
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +0530845 if (!dsi_ctrl->current_state.host_initialized) {
846 rc = dsi_pwr_enable_regulator(
847 &dsi_ctrl->pwr_info.host_pwr, false);
848 if (rc) {
849 pr_err("failed to disable host power regs\n");
850 goto error;
851 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700852 }
853 }
854error:
855 return rc;
856}
857
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700858static int dsi_ctrl_copy_and_pad_cmd(struct dsi_ctrl *dsi_ctrl,
859 const struct mipi_dsi_packet *packet,
860 u8 **buffer,
861 u32 *size)
862{
863 int rc = 0;
864 u8 *buf = NULL;
865 u32 len, i;
866
867 len = packet->size;
868 len += 0x3; len &= ~0x03; /* Align to 32 bits */
869
870 buf = devm_kzalloc(&dsi_ctrl->pdev->dev, len * sizeof(u8), GFP_KERNEL);
871 if (!buf)
872 return -ENOMEM;
873
874 for (i = 0; i < len; i++) {
875 if (i >= packet->size)
876 buf[i] = 0xFF;
877 else if (i < sizeof(packet->header))
878 buf[i] = packet->header[i];
879 else
880 buf[i] = packet->payload[i - sizeof(packet->header)];
881 }
882
883 if (packet->payload_length > 0)
884 buf[3] |= BIT(6);
885
886 buf[3] |= BIT(7);
887 *buffer = buf;
888 *size = len;
889
890 return rc;
891}
892
893static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
894 const struct mipi_dsi_msg *msg,
895 u32 flags)
896{
Clarence Ip80ada7f2017-05-04 09:55:21 -0700897 int rc = 0, ret = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700898 struct mipi_dsi_packet packet;
899 struct dsi_ctrl_cmd_dma_fifo_info cmd;
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -0700900 struct dsi_ctrl_cmd_dma_info cmd_mem;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700901 u32 hw_flags = 0;
902 u32 length = 0;
903 u8 *buffer = NULL;
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -0700904 u32 cnt = 0;
905 u8 *cmdbuf;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700906
907 rc = mipi_dsi_create_packet(&packet, msg);
908 if (rc) {
909 pr_err("Failed to create message packet, rc=%d\n", rc);
910 goto error;
911 }
912
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -0700913 if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
914 rc = dsi_ctrl_copy_and_pad_cmd(dsi_ctrl,
915 &packet,
916 &buffer,
917 &length);
918
919 if (rc) {
920 pr_err("[%s] failed to copy message, rc=%d\n",
921 dsi_ctrl->name, rc);
922 goto error;
923 }
924
925 cmd_mem.offset = dsi_ctrl->cmd_buffer_iova;
926 cmd_mem.length = length;
927 cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ?
928 true : false;
929 cmd_mem.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ?
930 true : false;
931 cmd_mem.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
932 true : false;
933
934 cmdbuf = (u8 *)(dsi_ctrl->vaddr);
935 for (cnt = 0; cnt < length; cnt++)
936 cmdbuf[cnt] = buffer[cnt];
937
938 } else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700939 rc = dsi_ctrl_copy_and_pad_cmd(dsi_ctrl,
940 &packet,
941 &buffer,
942 &length);
943 if (rc) {
944 pr_err("[%s] failed to copy message, rc=%d\n",
945 dsi_ctrl->name, rc);
946 goto error;
947 }
948 cmd.command = (u32 *)buffer;
949 cmd.size = length;
950 cmd.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ?
951 true : false;
952 cmd.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ?
953 true : false;
954 cmd.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
955 true : false;
956 }
957
958 hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ?
959 DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER : 0;
960
Clarence Ip80ada7f2017-05-04 09:55:21 -0700961 if (flags & DSI_CTRL_CMD_DEFER_TRIGGER) {
962 if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
963 dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw,
964 &cmd_mem,
965 hw_flags);
966 } else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
967 dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw,
968 &cmd,
969 hw_flags);
970 }
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -0700971 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700972
973 if (!(flags & DSI_CTRL_CMD_DEFER_TRIGGER)) {
Clarence Ip80ada7f2017-05-04 09:55:21 -0700974 dsi_ctrl_enable_status_interrupt(dsi_ctrl,
975 DSI_SINT_CMD_MODE_DMA_DONE, NULL);
976 reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700977
Clarence Ip80ada7f2017-05-04 09:55:21 -0700978 if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
979 dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw,
980 &cmd_mem,
981 hw_flags);
982 } else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
983 dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw,
984 &cmd,
985 hw_flags);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -0700986 }
Clarence Ip80ada7f2017-05-04 09:55:21 -0700987
988 ret = wait_for_completion_timeout(
989 &dsi_ctrl->irq_info.cmd_dma_done,
990 msecs_to_jiffies(DSI_CTRL_TX_TO_MS));
991
992 if (ret == 0) {
993 u32 status = 0;
994 u32 mask = DSI_CMD_MODE_DMA_DONE;
995
996 if (status & mask) {
997 status |= (DSI_CMD_MODE_DMA_DONE |
998 DSI_BTA_DONE);
999 dsi_ctrl->hw.ops.clear_interrupt_status(
1000 &dsi_ctrl->hw,
1001 status);
1002 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
1003 DSI_SINT_CMD_MODE_DMA_DONE);
1004 complete_all(&dsi_ctrl->irq_info.cmd_dma_done);
1005 pr_warn("dma_tx done but irq not triggered\n");
1006 } else {
1007 rc = -ETIMEDOUT;
1008 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
1009 DSI_SINT_CMD_MODE_DMA_DONE);
1010 pr_err("[DSI_%d]Command transfer failed\n",
1011 dsi_ctrl->cell_index);
1012 }
1013 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001014
1015 dsi_ctrl->hw.ops.reset_cmd_fifo(&dsi_ctrl->hw);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001016 }
1017error:
1018 if (buffer)
1019 devm_kfree(&dsi_ctrl->pdev->dev, buffer);
1020 return rc;
1021}
1022
1023static int dsi_set_max_return_size(struct dsi_ctrl *dsi_ctrl,
1024 const struct mipi_dsi_msg *rx_msg,
1025 u32 size)
1026{
1027 int rc = 0;
1028 u8 tx[2] = { (u8)(size & 0xFF), (u8)(size >> 8) };
1029 struct mipi_dsi_msg msg = {
1030 .channel = rx_msg->channel,
1031 .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
1032 .tx_len = 2,
1033 .tx_buf = tx,
1034 };
1035
1036 rc = dsi_message_tx(dsi_ctrl, &msg, 0x0);
1037 if (rc)
1038 pr_err("failed to send max return size packet, rc=%d\n", rc);
1039
1040 return rc;
1041}
1042
1043static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl,
1044 const struct mipi_dsi_msg *msg,
1045 u32 flags)
1046{
1047 int rc = 0;
1048 u32 rd_pkt_size;
1049 u32 total_read_len;
1050 u32 bytes_read = 0, tot_bytes_read = 0;
1051 u32 current_read_len;
1052 bool short_resp = false;
1053 bool read_done = false;
1054
1055 if (msg->rx_len <= 2) {
1056 short_resp = true;
1057 rd_pkt_size = msg->rx_len;
1058 total_read_len = 4;
1059 } else {
1060 short_resp = false;
1061 current_read_len = 10;
1062 if (msg->rx_len < current_read_len)
1063 rd_pkt_size = msg->rx_len;
1064 else
1065 rd_pkt_size = current_read_len;
1066
1067 total_read_len = current_read_len + 6;
1068 }
1069
1070 while (!read_done) {
1071 rc = dsi_set_max_return_size(dsi_ctrl, msg, rd_pkt_size);
1072 if (rc) {
1073 pr_err("Failed to set max return packet size, rc=%d\n",
1074 rc);
1075 goto error;
1076 }
1077
1078 rc = dsi_message_tx(dsi_ctrl, msg, flags);
1079 if (rc) {
1080 pr_err("Message transmission failed, rc=%d\n", rc);
1081 goto error;
1082 }
1083
1084
1085 tot_bytes_read += bytes_read;
1086 if (short_resp)
1087 read_done = true;
1088 else if (msg->rx_len <= tot_bytes_read)
1089 read_done = true;
1090 }
1091error:
1092 return rc;
1093}
1094
1095
1096static int dsi_enable_ulps(struct dsi_ctrl *dsi_ctrl)
1097{
1098 int rc = 0;
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301099 u32 lanes = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001100 u32 ulps_lanes;
1101
1102 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE)
1103 lanes = dsi_ctrl->host_config.common_config.data_lanes;
1104
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05301105 rc = dsi_ctrl->hw.ops.wait_for_lane_idle(&dsi_ctrl->hw, lanes);
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301106 if (rc) {
1107 pr_err("lanes not entering idle, skip ULPS\n");
1108 return rc;
1109 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001110
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05301111 if (!dsi_ctrl->hw.ops.ulps_ops.ulps_request ||
1112 !dsi_ctrl->hw.ops.ulps_ops.ulps_exit) {
1113 pr_debug("DSI controller ULPS ops not present\n");
1114 return 0;
1115 }
1116
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301117 lanes |= DSI_CLOCK_LANE;
1118 dsi_ctrl->hw.ops.ulps_ops.ulps_request(&dsi_ctrl->hw, lanes);
1119
1120 ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001121
1122 if ((lanes & ulps_lanes) != lanes) {
1123 pr_err("Failed to enter ULPS, request=0x%x, actual=0x%x\n",
1124 lanes, ulps_lanes);
1125 rc = -EIO;
1126 }
1127
1128 return rc;
1129}
1130
1131static int dsi_disable_ulps(struct dsi_ctrl *dsi_ctrl)
1132{
1133 int rc = 0;
1134 u32 ulps_lanes, lanes = 0;
1135
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05301136 dsi_ctrl->hw.ops.clear_phy0_ln_err(&dsi_ctrl->hw);
1137
1138 if (!dsi_ctrl->hw.ops.ulps_ops.ulps_request ||
1139 !dsi_ctrl->hw.ops.ulps_ops.ulps_exit) {
1140 pr_debug("DSI controller ULPS ops not present\n");
1141 return 0;
1142 }
1143
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001144 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE)
1145 lanes = dsi_ctrl->host_config.common_config.data_lanes;
1146
1147 lanes |= DSI_CLOCK_LANE;
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05301148
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301149 ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001150
1151 if ((lanes & ulps_lanes) != lanes)
1152 pr_err("Mismatch between lanes in ULPS\n");
1153
1154 lanes &= ulps_lanes;
1155
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301156 dsi_ctrl->hw.ops.ulps_ops.ulps_exit(&dsi_ctrl->hw, lanes);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001157
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301158 ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001159 if (ulps_lanes & lanes) {
1160 pr_err("Lanes (0x%x) stuck in ULPS\n", ulps_lanes);
1161 rc = -EIO;
1162 }
1163
1164 return rc;
1165}
1166
1167static int dsi_ctrl_drv_state_init(struct dsi_ctrl *dsi_ctrl)
1168{
1169 int rc = 0;
1170 bool splash_enabled = false;
1171 struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state;
1172
1173 if (!splash_enabled) {
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301174 state->power_state = DSI_CTRL_POWER_VREG_OFF;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001175 state->cmd_engine_state = DSI_CTRL_ENGINE_OFF;
1176 state->vid_engine_state = DSI_CTRL_ENGINE_OFF;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001177 }
1178
1179 return rc;
1180}
1181
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001182static int dsi_ctrl_buffer_deinit(struct dsi_ctrl *dsi_ctrl)
1183{
Jordan Croused8e96522017-02-13 10:14:16 -07001184 struct msm_gem_address_space *aspace = NULL;
1185
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001186 if (dsi_ctrl->tx_cmd_buf) {
Jordan Croused8e96522017-02-13 10:14:16 -07001187 aspace = dsi_ctrl_get_aspace(dsi_ctrl,
1188 MSM_SMMU_DOMAIN_UNSECURE);
1189 if (!aspace) {
1190 pr_err("failed to get address space\n");
1191 return -ENOMEM;
1192 }
1193
1194 msm_gem_put_iova(dsi_ctrl->tx_cmd_buf, aspace);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001195
1196 msm_gem_free_object(dsi_ctrl->tx_cmd_buf);
1197 dsi_ctrl->tx_cmd_buf = NULL;
1198 }
1199
1200 return 0;
1201}
1202
1203int dsi_ctrl_buffer_init(struct dsi_ctrl *dsi_ctrl)
1204{
1205 int rc = 0;
1206 u32 iova = 0;
Jordan Croused8e96522017-02-13 10:14:16 -07001207 struct msm_gem_address_space *aspace = NULL;
1208
1209 aspace = dsi_ctrl_get_aspace(dsi_ctrl, MSM_SMMU_DOMAIN_UNSECURE);
1210 if (!aspace) {
1211 pr_err("failed to get address space\n");
1212 return -ENOMEM;
1213 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001214
1215 dsi_ctrl->tx_cmd_buf = msm_gem_new(dsi_ctrl->drm_dev,
1216 SZ_4K,
1217 MSM_BO_UNCACHED);
1218
1219 if (IS_ERR(dsi_ctrl->tx_cmd_buf)) {
1220 rc = PTR_ERR(dsi_ctrl->tx_cmd_buf);
1221 pr_err("failed to allocate gem, rc=%d\n", rc);
1222 dsi_ctrl->tx_cmd_buf = NULL;
1223 goto error;
1224 }
1225
1226 dsi_ctrl->cmd_buffer_size = SZ_4K;
1227
Jordan Croused8e96522017-02-13 10:14:16 -07001228 rc = msm_gem_get_iova(dsi_ctrl->tx_cmd_buf, aspace, &iova);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001229 if (rc) {
1230 pr_err("failed to get iova, rc=%d\n", rc);
1231 (void)dsi_ctrl_buffer_deinit(dsi_ctrl);
1232 goto error;
1233 }
1234
1235 if (iova & 0x07) {
1236 pr_err("Tx command buffer is not 8 byte aligned\n");
1237 rc = -ENOTSUPP;
1238 (void)dsi_ctrl_buffer_deinit(dsi_ctrl);
1239 goto error;
1240 }
1241error:
1242 return rc;
1243}
1244
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301245static int dsi_enable_io_clamp(struct dsi_ctrl *dsi_ctrl,
1246 bool enable, bool ulps_enabled)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001247{
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001248 u32 lanes = 0;
1249
1250 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE)
1251 lanes = dsi_ctrl->host_config.common_config.data_lanes;
1252
1253 lanes |= DSI_CLOCK_LANE;
1254
1255 if (enable)
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301256 dsi_ctrl->hw.ops.clamp_enable(&dsi_ctrl->hw,
1257 lanes, ulps_enabled);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001258 else
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301259 dsi_ctrl->hw.ops.clamp_disable(&dsi_ctrl->hw,
1260 lanes, ulps_enabled);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001261
1262 return 0;
1263}
1264
1265static int dsi_ctrl_dev_probe(struct platform_device *pdev)
1266{
1267 struct dsi_ctrl *dsi_ctrl;
1268 struct dsi_ctrl_list_item *item;
1269 const struct of_device_id *id;
1270 enum dsi_ctrl_version version;
1271 u32 index = 0;
1272 int rc = 0;
1273
1274 id = of_match_node(msm_dsi_of_match, pdev->dev.of_node);
1275 if (!id)
1276 return -ENODEV;
1277
1278 version = *(enum dsi_ctrl_version *)id->data;
1279
1280 item = devm_kzalloc(&pdev->dev, sizeof(*item), GFP_KERNEL);
1281 if (!item)
1282 return -ENOMEM;
1283
1284 dsi_ctrl = devm_kzalloc(&pdev->dev, sizeof(*dsi_ctrl), GFP_KERNEL);
1285 if (!dsi_ctrl)
1286 return -ENOMEM;
1287
1288 rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &index);
1289 if (rc) {
1290 pr_debug("cell index not set, default to 0\n");
1291 index = 0;
1292 }
1293
Alexander Beykun32a6a182017-02-27 17:46:51 -05001294 dsi_ctrl->cell_index = index;
Shashank Babu Chinta Venkataafef8202017-04-21 13:49:56 -07001295 dsi_ctrl->version = version;
Clarence Ip80ada7f2017-05-04 09:55:21 -07001296 dsi_ctrl->irq_info.irq_num = -1;
1297 dsi_ctrl->irq_info.irq_stat_mask = 0x0;
1298
1299 spin_lock_init(&dsi_ctrl->irq_info.irq_lock);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001300
1301 dsi_ctrl->name = of_get_property(pdev->dev.of_node, "label", NULL);
1302 if (!dsi_ctrl->name)
1303 dsi_ctrl->name = DSI_CTRL_DEFAULT_LABEL;
1304
1305 rc = dsi_ctrl_init_regmap(pdev, dsi_ctrl);
1306 if (rc) {
1307 pr_err("Failed to parse register information, rc = %d\n", rc);
1308 goto fail;
1309 }
1310
1311 rc = dsi_ctrl_clocks_init(pdev, dsi_ctrl);
1312 if (rc) {
1313 pr_err("Failed to parse clock information, rc = %d\n", rc);
1314 goto fail;
1315 }
1316
1317 rc = dsi_ctrl_supplies_init(pdev, dsi_ctrl);
1318 if (rc) {
1319 pr_err("Failed to parse voltage supplies, rc = %d\n", rc);
1320 goto fail_clks;
1321 }
1322
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001323 rc = dsi_catalog_ctrl_setup(&dsi_ctrl->hw, dsi_ctrl->version,
Alexander Beykun32a6a182017-02-27 17:46:51 -05001324 dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001325 if (rc) {
1326 pr_err("Catalog does not support version (%d)\n",
1327 dsi_ctrl->version);
1328 goto fail_supplies;
1329 }
1330
1331 rc = dsi_ctrl_axi_bus_client_init(pdev, dsi_ctrl);
1332 if (rc)
Shashank Babu Chinta Venkatacf411332017-05-10 17:30:08 -07001333 pr_debug("failed to init axi bus client, rc = %d\n", rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001334
1335 item->ctrl = dsi_ctrl;
1336
1337 mutex_lock(&dsi_ctrl_list_lock);
1338 list_add(&item->list, &dsi_ctrl_list);
1339 mutex_unlock(&dsi_ctrl_list_lock);
1340
1341 mutex_init(&dsi_ctrl->ctrl_lock);
1342
1343 dsi_ctrl->pdev = pdev;
1344 platform_set_drvdata(pdev, dsi_ctrl);
Dhaval Patela2430842017-06-15 14:32:36 -07001345 pr_info("Probe successful for %s\n", dsi_ctrl->name);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001346
1347 return 0;
1348
1349fail_supplies:
1350 (void)dsi_ctrl_supplies_deinit(dsi_ctrl);
1351fail_clks:
1352 (void)dsi_ctrl_clocks_deinit(dsi_ctrl);
1353fail:
1354 return rc;
1355}
1356
1357static int dsi_ctrl_dev_remove(struct platform_device *pdev)
1358{
1359 int rc = 0;
1360 struct dsi_ctrl *dsi_ctrl;
1361 struct list_head *pos, *tmp;
1362
1363 dsi_ctrl = platform_get_drvdata(pdev);
1364
1365 mutex_lock(&dsi_ctrl_list_lock);
1366 list_for_each_safe(pos, tmp, &dsi_ctrl_list) {
1367 struct dsi_ctrl_list_item *n = list_entry(pos,
1368 struct dsi_ctrl_list_item,
1369 list);
1370 if (n->ctrl == dsi_ctrl) {
1371 list_del(&n->list);
1372 break;
1373 }
1374 }
1375 mutex_unlock(&dsi_ctrl_list_lock);
1376
1377 mutex_lock(&dsi_ctrl->ctrl_lock);
1378 rc = dsi_ctrl_axi_bus_client_deinit(dsi_ctrl);
1379 if (rc)
1380 pr_err("failed to deinitialize axi bus client, rc = %d\n", rc);
1381
1382 rc = dsi_ctrl_supplies_deinit(dsi_ctrl);
1383 if (rc)
1384 pr_err("failed to deinitialize voltage supplies, rc=%d\n", rc);
1385
1386 rc = dsi_ctrl_clocks_deinit(dsi_ctrl);
1387 if (rc)
1388 pr_err("failed to deinitialize clocks, rc=%d\n", rc);
1389
1390 mutex_unlock(&dsi_ctrl->ctrl_lock);
1391
1392 mutex_destroy(&dsi_ctrl->ctrl_lock);
1393 devm_kfree(&pdev->dev, dsi_ctrl);
1394
1395 platform_set_drvdata(pdev, NULL);
1396 return 0;
1397}
1398
1399static struct platform_driver dsi_ctrl_driver = {
1400 .probe = dsi_ctrl_dev_probe,
1401 .remove = dsi_ctrl_dev_remove,
1402 .driver = {
Ajay Singh Parmar485f7362016-07-19 10:43:24 -07001403 .name = "drm_dsi_ctrl",
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001404 .of_match_table = msm_dsi_of_match,
1405 },
1406};
1407
1408/**
1409 * dsi_ctrl_get() - get a dsi_ctrl handle from an of_node
1410 * @of_node: of_node of the DSI controller.
1411 *
1412 * Gets the DSI controller handle for the corresponding of_node. The ref count
1413 * is incremented to one and all subsequent gets will fail until the original
1414 * clients calls a put.
1415 *
1416 * Return: DSI Controller handle.
1417 */
1418struct dsi_ctrl *dsi_ctrl_get(struct device_node *of_node)
1419{
1420 struct list_head *pos, *tmp;
1421 struct dsi_ctrl *ctrl = NULL;
1422
1423 mutex_lock(&dsi_ctrl_list_lock);
1424 list_for_each_safe(pos, tmp, &dsi_ctrl_list) {
1425 struct dsi_ctrl_list_item *n;
1426
1427 n = list_entry(pos, struct dsi_ctrl_list_item, list);
1428 if (n->ctrl->pdev->dev.of_node == of_node) {
1429 ctrl = n->ctrl;
1430 break;
1431 }
1432 }
1433 mutex_unlock(&dsi_ctrl_list_lock);
1434
1435 if (!ctrl) {
1436 pr_err("Device with of node not found\n");
1437 ctrl = ERR_PTR(-EPROBE_DEFER);
1438 return ctrl;
1439 }
1440
1441 mutex_lock(&ctrl->ctrl_lock);
1442 if (ctrl->refcount == 1) {
1443 pr_err("[%s] Device in use\n", ctrl->name);
1444 ctrl = ERR_PTR(-EBUSY);
1445 } else {
1446 ctrl->refcount++;
1447 }
1448 mutex_unlock(&ctrl->ctrl_lock);
1449 return ctrl;
1450}
1451
1452/**
1453 * dsi_ctrl_put() - releases a dsi controller handle.
1454 * @dsi_ctrl: DSI controller handle.
1455 *
1456 * Releases the DSI controller. Driver will clean up all resources and puts back
1457 * the DSI controller into reset state.
1458 */
1459void dsi_ctrl_put(struct dsi_ctrl *dsi_ctrl)
1460{
1461 mutex_lock(&dsi_ctrl->ctrl_lock);
1462
1463 if (dsi_ctrl->refcount == 0)
1464 pr_err("Unbalanced dsi_ctrl_put call\n");
1465 else
1466 dsi_ctrl->refcount--;
1467
1468 mutex_unlock(&dsi_ctrl->ctrl_lock);
1469}
1470
1471/**
1472 * dsi_ctrl_drv_init() - initialize dsi controller driver.
1473 * @dsi_ctrl: DSI controller handle.
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001474 * @parent: Parent directory for debug fs.
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001475 *
1476 * Initializes DSI controller driver. Driver should be initialized after
1477 * dsi_ctrl_get() succeeds.
1478 *
1479 * Return: error code.
1480 */
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001481int dsi_ctrl_drv_init(struct dsi_ctrl *dsi_ctrl, struct dentry *parent)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001482{
1483 int rc = 0;
1484
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001485 if (!dsi_ctrl || !parent) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001486 pr_err("Invalid params\n");
1487 return -EINVAL;
1488 }
1489
1490 mutex_lock(&dsi_ctrl->ctrl_lock);
1491 rc = dsi_ctrl_drv_state_init(dsi_ctrl);
1492 if (rc) {
1493 pr_err("Failed to initialize driver state, rc=%d\n", rc);
1494 goto error;
1495 }
1496
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001497 rc = dsi_ctrl_debugfs_init(dsi_ctrl, parent);
1498 if (rc) {
1499 pr_err("[DSI_%d] failed to init debug fs, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05001500 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001501 goto error;
1502 }
1503
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001504error:
1505 mutex_unlock(&dsi_ctrl->ctrl_lock);
1506 return rc;
1507}
1508
1509/**
1510 * dsi_ctrl_drv_deinit() - de-initializes dsi controller driver
1511 * @dsi_ctrl: DSI controller handle.
1512 *
1513 * Releases all resources acquired by dsi_ctrl_drv_init().
1514 *
1515 * Return: error code.
1516 */
1517int dsi_ctrl_drv_deinit(struct dsi_ctrl *dsi_ctrl)
1518{
1519 int rc = 0;
1520
1521 if (!dsi_ctrl) {
1522 pr_err("Invalid params\n");
1523 return -EINVAL;
1524 }
1525
1526 mutex_lock(&dsi_ctrl->ctrl_lock);
Ajay Singh Parmar48ea4272016-06-27 11:44:34 -07001527
1528 rc = dsi_ctrl_debugfs_deinit(dsi_ctrl);
1529 if (rc)
1530 pr_err("failed to release debugfs root, rc=%d\n", rc);
1531
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001532 rc = dsi_ctrl_buffer_deinit(dsi_ctrl);
1533 if (rc)
1534 pr_err("Failed to free cmd buffers, rc=%d\n", rc);
1535
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001536 mutex_unlock(&dsi_ctrl->ctrl_lock);
1537 return rc;
1538}
1539
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301540int dsi_ctrl_clk_cb_register(struct dsi_ctrl *dsi_ctrl,
1541 struct clk_ctrl_cb *clk_cb)
1542{
1543 if (!dsi_ctrl || !clk_cb) {
1544 pr_err("Invalid params\n");
1545 return -EINVAL;
1546 }
1547
1548 dsi_ctrl->clk_cb.priv = clk_cb->priv;
1549 dsi_ctrl->clk_cb.dsi_clk_cb = clk_cb->dsi_clk_cb;
1550 return 0;
1551}
1552
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001553/**
1554 * dsi_ctrl_phy_sw_reset() - perform a PHY software reset
1555 * @dsi_ctrl: DSI controller handle.
1556 *
1557 * Performs a PHY software reset on the DSI controller. Reset should be done
1558 * when the controller power state is DSI_CTRL_POWER_CORE_CLK_ON and the PHY is
1559 * not enabled.
1560 *
1561 * This function will fail if driver is in any other state.
1562 *
1563 * Return: error code.
1564 */
1565int dsi_ctrl_phy_sw_reset(struct dsi_ctrl *dsi_ctrl)
1566{
1567 int rc = 0;
1568
1569 if (!dsi_ctrl) {
1570 pr_err("Invalid params\n");
1571 return -EINVAL;
1572 }
1573
1574 mutex_lock(&dsi_ctrl->ctrl_lock);
1575 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_PHY_SW_RESET, 0x0);
1576 if (rc) {
1577 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05001578 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001579 goto error;
1580 }
1581
1582 dsi_ctrl->hw.ops.phy_sw_reset(&dsi_ctrl->hw);
1583
Alexander Beykun32a6a182017-02-27 17:46:51 -05001584 pr_debug("[DSI_%d] PHY soft reset done\n", dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001585 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_PHY_SW_RESET, 0x0);
1586error:
1587 mutex_unlock(&dsi_ctrl->ctrl_lock);
1588 return rc;
1589}
1590
1591/**
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07001592 * dsi_ctrl_seamless_timing_update() - update only controller timing
1593 * @dsi_ctrl: DSI controller handle.
1594 * @timing: New DSI timing info
1595 *
1596 * Updates host timing values to conduct a seamless transition to new timing
1597 * For example, to update the porch values in a dynamic fps switch.
1598 *
1599 * Return: error code.
1600 */
1601int dsi_ctrl_async_timing_update(struct dsi_ctrl *dsi_ctrl,
1602 struct dsi_mode_info *timing)
1603{
1604 struct dsi_mode_info *host_mode;
1605 int rc = 0;
1606
1607 if (!dsi_ctrl || !timing) {
1608 pr_err("Invalid params\n");
1609 return -EINVAL;
1610 }
1611
1612 mutex_lock(&dsi_ctrl->ctrl_lock);
1613
1614 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_ASYNC_TIMING,
1615 DSI_CTRL_ENGINE_ON);
1616 if (rc) {
1617 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05001618 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07001619 goto exit;
1620 }
1621
1622 host_mode = &dsi_ctrl->host_config.video_timing;
1623 memcpy(host_mode, timing, sizeof(*host_mode));
1624
1625 dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw, host_mode);
1626
1627exit:
1628 mutex_unlock(&dsi_ctrl->ctrl_lock);
1629 return rc;
1630}
1631
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301632int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl)
1633{
1634 int rc = 0;
1635
1636 if (!dsi_ctrl) {
1637 pr_err("Invalid params\n");
1638 return -EINVAL;
1639 }
1640
1641 mutex_lock(&dsi_ctrl->ctrl_lock);
1642
1643 dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw,
1644 &dsi_ctrl->host_config.lane_map);
1645
1646 dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
1647 &dsi_ctrl->host_config.common_config);
1648
1649 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
1650 dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
1651 &dsi_ctrl->host_config.common_config,
1652 &dsi_ctrl->host_config.u.cmd_engine);
1653
1654 dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
Lloyd Atkinson16e96de2017-04-19 11:18:14 -04001655 &dsi_ctrl->host_config.video_timing,
1656 dsi_ctrl->host_config.video_timing.h_active * 3,
1657 0x0,
1658 &dsi_ctrl->roi);
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301659 dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, true);
1660 } else {
1661 dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw,
1662 &dsi_ctrl->host_config.common_config,
1663 &dsi_ctrl->host_config.u.video_engine);
1664 dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw,
1665 &dsi_ctrl->host_config.video_timing);
1666 dsi_ctrl->hw.ops.video_engine_en(&dsi_ctrl->hw, true);
1667 }
1668
1669 dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
1670 dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0x0);
1671 dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true);
1672
1673 mutex_unlock(&dsi_ctrl->ctrl_lock);
1674 return rc;
1675}
1676
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04001677int dsi_ctrl_set_roi(struct dsi_ctrl *dsi_ctrl, struct dsi_rect *roi,
1678 bool *changed)
1679{
1680 int rc = 0;
1681
1682 if (!dsi_ctrl || !roi || !changed) {
1683 pr_err("Invalid params\n");
1684 return -EINVAL;
1685 }
1686
1687 mutex_lock(&dsi_ctrl->ctrl_lock);
1688 if (!dsi_rect_is_equal(&dsi_ctrl->roi, roi)) {
1689 *changed = true;
1690 memcpy(&dsi_ctrl->roi, roi, sizeof(dsi_ctrl->roi));
1691 } else
1692 *changed = false;
1693 mutex_unlock(&dsi_ctrl->ctrl_lock);
1694 return rc;
1695}
1696
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05301697/**
1698 * dsi_ctrl_phy_reset_config() - Mask/unmask propagation of ahb reset signal
1699 * to DSI PHY hardware.
1700 * @dsi_ctrl: DSI controller handle.
1701 * @enable: Mask/unmask the PHY reset signal.
1702 *
1703 * Return: error code.
1704 */
1705int dsi_ctrl_phy_reset_config(struct dsi_ctrl *dsi_ctrl, bool enable)
1706{
1707 if (!dsi_ctrl) {
1708 pr_err("Invalid params\n");
1709 return -EINVAL;
1710 }
1711
1712 if (dsi_ctrl->hw.ops.phy_reset_config)
1713 dsi_ctrl->hw.ops.phy_reset_config(&dsi_ctrl->hw, enable);
1714
1715 return 0;
1716}
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301717
Clarence Ip80ada7f2017-05-04 09:55:21 -07001718static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl,
1719 unsigned long int error)
1720{
1721 pr_err("%s: %lu\n", __func__, error);
1722
1723 /* DTLN PHY error */
1724 if (error & 0x3000e00)
1725 if (dsi_ctrl->hw.ops.clear_error_status)
1726 dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
1727 0x3000e00);
1728
1729 /* DSI FIFO OVERFLOW error */
1730 if (error & 0xf0000) {
1731 if (dsi_ctrl->hw.ops.clear_error_status)
1732 dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
1733 0xf0000);
1734 }
1735
1736 /* DSI FIFO UNDERFLOW error */
1737 if (error & 0xf00000) {
1738 if (dsi_ctrl->hw.ops.clear_error_status)
1739 dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
1740 0xf00000);
1741 }
1742
1743 /* DSI PLL UNLOCK error */
1744 if (error & BIT(8))
1745 if (dsi_ctrl->hw.ops.clear_error_status)
1746 dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
1747 BIT(8));
1748}
1749
1750/**
1751 * dsi_ctrl_isr - interrupt service routine for DSI CTRL component
1752 * @irq: Incoming IRQ number
1753 * @ptr: Pointer to user data structure (struct dsi_ctrl)
1754 * Returns: IRQ_HANDLED if no further action required
1755 */
1756static irqreturn_t dsi_ctrl_isr(int irq, void *ptr)
1757{
1758 struct dsi_ctrl *dsi_ctrl;
1759 struct dsi_event_cb_info cb_info;
1760 unsigned long flags;
1761 uint32_t cell_index, status, i;
1762 uint64_t errors;
1763
1764 if (!ptr)
1765 return IRQ_NONE;
1766 dsi_ctrl = ptr;
1767
1768 /* clear status interrupts */
1769 if (dsi_ctrl->hw.ops.get_interrupt_status)
1770 status = dsi_ctrl->hw.ops.get_interrupt_status(&dsi_ctrl->hw);
1771 else
1772 status = 0x0;
1773
1774 if (dsi_ctrl->hw.ops.clear_interrupt_status)
1775 dsi_ctrl->hw.ops.clear_interrupt_status(&dsi_ctrl->hw, status);
1776
1777 spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags);
1778 cell_index = dsi_ctrl->cell_index;
1779 spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags);
1780
1781 /* clear error interrupts */
1782 if (dsi_ctrl->hw.ops.get_error_status)
1783 errors = dsi_ctrl->hw.ops.get_error_status(&dsi_ctrl->hw);
1784 else
1785 errors = 0x0;
1786
1787 if (errors) {
1788 /* handle DSI error recovery */
1789 dsi_ctrl_handle_error_status(dsi_ctrl, errors);
1790 if (dsi_ctrl->hw.ops.clear_error_status)
1791 dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
1792 errors);
1793 }
1794
1795 if (status & DSI_CMD_MODE_DMA_DONE) {
1796 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
1797 DSI_SINT_CMD_MODE_DMA_DONE);
1798 complete_all(&dsi_ctrl->irq_info.cmd_dma_done);
1799 }
1800
1801 if (status & DSI_CMD_FRAME_DONE) {
1802 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
1803 DSI_SINT_CMD_FRAME_DONE);
1804 complete_all(&dsi_ctrl->irq_info.cmd_frame_done);
1805 }
1806
1807 if (status & DSI_VIDEO_MODE_FRAME_DONE) {
1808 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
1809 DSI_SINT_VIDEO_MODE_FRAME_DONE);
1810 complete_all(&dsi_ctrl->irq_info.vid_frame_done);
1811 }
1812
1813 if (status & DSI_BTA_DONE) {
1814 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
1815 DSI_SINT_BTA_DONE);
1816 complete_all(&dsi_ctrl->irq_info.bta_done);
1817 }
1818
1819 for (i = 0; status && i < DSI_STATUS_INTERRUPT_COUNT; ++i) {
1820 if (status & 0x1) {
1821 spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags);
1822 cb_info = dsi_ctrl->irq_info.irq_stat_cb[i];
1823 spin_unlock_irqrestore(
1824 &dsi_ctrl->irq_info.irq_lock, flags);
1825
1826 if (cb_info.event_cb)
1827 (void)cb_info.event_cb(cb_info.event_usr_ptr,
1828 cb_info.event_idx,
1829 cell_index, irq, 0, 0, 0);
1830 }
1831 status >>= 1;
1832 }
1833
1834 return IRQ_HANDLED;
1835}
1836
1837/**
1838 * _dsi_ctrl_setup_isr - register ISR handler
1839 * @dsi_ctrl: Pointer to associated dsi_ctrl structure
1840 * Returns: Zero on success
1841 */
1842static int dsi_ctrl_setup_isr(struct dsi_ctrl *dsi_ctrl)
1843{
1844 int irq_num, rc;
1845
1846 if (!dsi_ctrl)
1847 return -EINVAL;
1848 if (dsi_ctrl->irq_info.irq_num != -1)
1849 return 0;
1850
1851 init_completion(&dsi_ctrl->irq_info.cmd_dma_done);
1852 init_completion(&dsi_ctrl->irq_info.vid_frame_done);
1853 init_completion(&dsi_ctrl->irq_info.cmd_frame_done);
1854 init_completion(&dsi_ctrl->irq_info.bta_done);
1855
1856 irq_num = platform_get_irq(dsi_ctrl->pdev, 0);
1857 if (irq_num < 0) {
1858 pr_err("[DSI_%d] Failed to get IRQ number, %d\n",
1859 dsi_ctrl->cell_index, irq_num);
1860 rc = irq_num;
1861 } else {
1862 rc = devm_request_threaded_irq(&dsi_ctrl->pdev->dev, irq_num,
1863 dsi_ctrl_isr, NULL, 0, "dsi_ctrl", dsi_ctrl);
1864 if (rc) {
1865 pr_err("[DSI_%d] Failed to request IRQ, %d\n",
1866 dsi_ctrl->cell_index, rc);
1867 } else {
1868 dsi_ctrl->irq_info.irq_num = irq_num;
1869 disable_irq_nosync(irq_num);
1870
1871 pr_info("[DSI_%d] IRQ %d registered\n",
1872 dsi_ctrl->cell_index, irq_num);
1873 }
1874 }
1875 return rc;
1876}
1877
1878/**
1879 * _dsi_ctrl_destroy_isr - unregister ISR handler
1880 * @dsi_ctrl: Pointer to associated dsi_ctrl structure
1881 */
1882static void _dsi_ctrl_destroy_isr(struct dsi_ctrl *dsi_ctrl)
1883{
1884 if (!dsi_ctrl || !dsi_ctrl->pdev || dsi_ctrl->irq_info.irq_num < 0)
1885 return;
1886
1887 if (dsi_ctrl->irq_info.irq_num != -1) {
1888 devm_free_irq(&dsi_ctrl->pdev->dev,
1889 dsi_ctrl->irq_info.irq_num, dsi_ctrl);
1890 dsi_ctrl->irq_info.irq_num = -1;
1891 }
1892}
1893
1894void dsi_ctrl_enable_status_interrupt(struct dsi_ctrl *dsi_ctrl,
1895 uint32_t intr_idx, struct dsi_event_cb_info *event_info)
1896{
1897 unsigned long flags;
1898
1899 if (!dsi_ctrl || dsi_ctrl->irq_info.irq_num == -1 ||
1900 intr_idx >= DSI_STATUS_INTERRUPT_COUNT)
1901 return;
1902
1903 spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags);
1904
1905 if (dsi_ctrl->irq_info.irq_stat_refcount[intr_idx] == 0) {
1906 /* enable irq on first request */
1907 if (dsi_ctrl->irq_info.irq_stat_mask == 0)
1908 enable_irq(dsi_ctrl->irq_info.irq_num);
1909
1910 /* update hardware mask */
1911 dsi_ctrl->irq_info.irq_stat_mask |= BIT(intr_idx);
1912 dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw,
1913 dsi_ctrl->irq_info.irq_stat_mask);
1914 }
1915 ++(dsi_ctrl->irq_info.irq_stat_refcount[intr_idx]);
1916
1917 if (event_info)
1918 dsi_ctrl->irq_info.irq_stat_cb[intr_idx] = *event_info;
1919
1920 spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags);
1921}
1922
1923void dsi_ctrl_disable_status_interrupt(struct dsi_ctrl *dsi_ctrl,
1924 uint32_t intr_idx)
1925{
1926 unsigned long flags;
1927
1928 if (!dsi_ctrl || dsi_ctrl->irq_info.irq_num == -1 ||
1929 intr_idx >= DSI_STATUS_INTERRUPT_COUNT)
1930 return;
1931
1932 spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags);
1933
1934 if (dsi_ctrl->irq_info.irq_stat_refcount[intr_idx])
1935 if (--(dsi_ctrl->irq_info.irq_stat_refcount[intr_idx]) == 0) {
1936 dsi_ctrl->irq_info.irq_stat_mask &= ~BIT(intr_idx);
1937 dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw,
1938 dsi_ctrl->irq_info.irq_stat_mask);
1939
1940 /* don't need irq if no lines are enabled */
1941 if (dsi_ctrl->irq_info.irq_stat_mask == 0)
1942 disable_irq_nosync(dsi_ctrl->irq_info.irq_num);
1943 }
1944
1945 spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags);
1946}
1947
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301948/**
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001949 * dsi_ctrl_host_init() - Initialize DSI host hardware.
1950 * @dsi_ctrl: DSI controller handle.
1951 *
1952 * Initializes DSI controller hardware with host configuration provided by
1953 * dsi_ctrl_update_host_config(). Initialization can be performed only during
1954 * DSI_CTRL_POWER_CORE_CLK_ON state and after the PHY SW reset has been
1955 * performed.
1956 *
1957 * Return: error code.
1958 */
1959int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl)
1960{
1961 int rc = 0;
1962
1963 if (!dsi_ctrl) {
1964 pr_err("Invalid params\n");
1965 return -EINVAL;
1966 }
1967
1968 mutex_lock(&dsi_ctrl->ctrl_lock);
1969 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x1);
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 Parmar5c6b4862016-06-22 17:31:21 -07001973 goto error;
1974 }
1975
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001976 dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw,
1977 &dsi_ctrl->host_config.lane_map);
1978
1979 dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
1980 &dsi_ctrl->host_config.common_config);
1981
Ajay Singh Parmaraa9152d2016-05-16 18:02:07 -07001982 if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001983 dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
1984 &dsi_ctrl->host_config.common_config,
1985 &dsi_ctrl->host_config.u.cmd_engine);
Ajay Singh Parmaraa9152d2016-05-16 18:02:07 -07001986
1987 dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
Alexander Beykunac182352017-02-27 17:46:51 -05001988 &dsi_ctrl->host_config.video_timing,
Ajay Singh Parmaraa9152d2016-05-16 18:02:07 -07001989 dsi_ctrl->host_config.video_timing.h_active * 3,
Lloyd Atkinson16e96de2017-04-19 11:18:14 -04001990 0x0,
1991 NULL);
Ajay Singh Parmaraa9152d2016-05-16 18:02:07 -07001992 } else {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07001993 dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw,
1994 &dsi_ctrl->host_config.common_config,
1995 &dsi_ctrl->host_config.u.video_engine);
Ajay Singh Parmaraa9152d2016-05-16 18:02:07 -07001996 dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw,
1997 &dsi_ctrl->host_config.video_timing);
1998 }
1999
Clarence Ip80ada7f2017-05-04 09:55:21 -07002000 dsi_ctrl_setup_isr(dsi_ctrl);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002001
2002 dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
2003 dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0x0);
2004
Alexander Beykun32a6a182017-02-27 17:46:51 -05002005 pr_debug("[DSI_%d]Host initialization complete\n",
2006 dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002007 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x1);
2008error:
2009 mutex_unlock(&dsi_ctrl->ctrl_lock);
2010 return rc;
2011}
2012
Lloyd Atkinson8c49c582016-11-18 14:23:54 -05002013int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl)
2014{
2015 if (!dsi_ctrl)
2016 return -EINVAL;
2017
2018 mutex_lock(&dsi_ctrl->ctrl_lock);
2019 dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
2020 mutex_unlock(&dsi_ctrl->ctrl_lock);
2021
Alexander Beykun32a6a182017-02-27 17:46:51 -05002022 pr_debug("[DSI_%d]Soft reset complete\n", dsi_ctrl->cell_index);
Lloyd Atkinson8c49c582016-11-18 14:23:54 -05002023 return 0;
2024}
2025
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002026/**
2027 * dsi_ctrl_host_deinit() - De-Initialize DSI host hardware.
2028 * @dsi_ctrl: DSI controller handle.
2029 *
2030 * De-initializes DSI controller hardware. It can be performed only during
2031 * DSI_CTRL_POWER_CORE_CLK_ON state after LINK clocks have been turned off.
2032 *
2033 * Return: error code.
2034 */
2035int dsi_ctrl_host_deinit(struct dsi_ctrl *dsi_ctrl)
2036{
2037 int rc = 0;
2038
2039 if (!dsi_ctrl) {
2040 pr_err("Invalid params\n");
2041 return -EINVAL;
2042 }
2043
2044 mutex_lock(&dsi_ctrl->ctrl_lock);
2045
Clarence Ip80ada7f2017-05-04 09:55:21 -07002046 _dsi_ctrl_destroy_isr(dsi_ctrl);
2047
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002048 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x0);
2049 if (rc) {
2050 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002051 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002052 pr_err("driver state check failed, rc=%d\n", rc);
2053 goto error;
2054 }
2055
Alexander Beykun32a6a182017-02-27 17:46:51 -05002056 pr_debug("[DSI_%d] Host deinitization complete\n",
2057 dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002058 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x0);
2059error:
2060 mutex_unlock(&dsi_ctrl->ctrl_lock);
2061 return rc;
2062}
2063
2064/**
2065 * dsi_ctrl_update_host_config() - update dsi host configuration
2066 * @dsi_ctrl: DSI controller handle.
2067 * @config: DSI host configuration.
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002068 * @flags: dsi_mode_flags modifying the behavior
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002069 *
2070 * Updates driver with new Host configuration to use for host initialization.
2071 * This function call will only update the software context. The stored
2072 * configuration information will be used when the host is initialized.
2073 *
2074 * Return: error code.
2075 */
2076int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl,
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002077 struct dsi_host_config *config,
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302078 int flags, void *clk_handle)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002079{
2080 int rc = 0;
2081
2082 if (!ctrl || !config) {
2083 pr_err("Invalid params\n");
2084 return -EINVAL;
2085 }
2086
2087 mutex_lock(&ctrl->ctrl_lock);
2088
2089 rc = dsi_ctrl_validate_panel_info(ctrl, config);
2090 if (rc) {
2091 pr_err("panel validation failed, rc=%d\n", rc);
2092 goto error;
2093 }
2094
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002095 if (!(flags & DSI_MODE_FLAG_SEAMLESS)) {
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302096 rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle);
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002097 if (rc) {
2098 pr_err("[%s] failed to update link frequencies, rc=%d\n",
2099 ctrl->name, rc);
2100 goto error;
2101 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002102 }
2103
Alexander Beykun32a6a182017-02-27 17:46:51 -05002104 pr_debug("[DSI_%d]Host config updated\n", ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002105 memcpy(&ctrl->host_config, config, sizeof(ctrl->host_config));
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002106 ctrl->mode_bounds.x = ctrl->host_config.video_timing.h_active *
2107 ctrl->horiz_index;
2108 ctrl->mode_bounds.y = 0;
2109 ctrl->mode_bounds.w = ctrl->host_config.video_timing.h_active;
2110 ctrl->mode_bounds.h = ctrl->host_config.video_timing.v_active;
2111 memcpy(&ctrl->roi, &ctrl->mode_bounds, sizeof(ctrl->mode_bounds));
2112 ctrl->roi.x = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002113error:
2114 mutex_unlock(&ctrl->ctrl_lock);
2115 return rc;
2116}
2117
2118/**
2119 * dsi_ctrl_validate_timing() - validate a video timing configuration
2120 * @dsi_ctrl: DSI controller handle.
2121 * @timing: Pointer to timing data.
2122 *
2123 * Driver will validate if the timing configuration is supported on the
2124 * controller hardware.
2125 *
2126 * Return: error code if timing is not supported.
2127 */
2128int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl,
2129 struct dsi_mode_info *mode)
2130{
2131 int rc = 0;
2132
2133 if (!dsi_ctrl || !mode) {
2134 pr_err("Invalid params\n");
2135 return -EINVAL;
2136 }
2137
2138 mutex_lock(&dsi_ctrl->ctrl_lock);
2139 mutex_unlock(&dsi_ctrl->ctrl_lock);
2140
2141 return rc;
2142}
2143
2144/**
2145 * dsi_ctrl_cmd_transfer() - Transfer commands on DSI link
2146 * @dsi_ctrl: DSI controller handle.
2147 * @msg: Message to transfer on DSI link.
2148 * @flags: Modifiers for message transfer.
2149 *
2150 * Command transfer can be done only when command engine is enabled. The
2151 * transfer API will block until either the command transfer finishes or
2152 * the timeout value is reached. If the trigger is deferred, it will return
2153 * without triggering the transfer. Command parameters are programmed to
2154 * hardware.
2155 *
2156 * Return: error code.
2157 */
2158int dsi_ctrl_cmd_transfer(struct dsi_ctrl *dsi_ctrl,
2159 const struct mipi_dsi_msg *msg,
2160 u32 flags)
2161{
2162 int rc = 0;
2163
2164 if (!dsi_ctrl || !msg) {
2165 pr_err("Invalid params\n");
2166 return -EINVAL;
2167 }
2168
2169 mutex_lock(&dsi_ctrl->ctrl_lock);
2170
2171 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_CMD_TX, 0x0);
2172 if (rc) {
2173 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002174 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002175 goto error;
2176 }
2177
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002178 if (flags & DSI_CTRL_CMD_READ) {
2179 rc = dsi_message_rx(dsi_ctrl, msg, flags);
2180 if (rc)
2181 pr_err("read message failed, rc=%d\n", rc);
2182 } else {
2183 rc = dsi_message_tx(dsi_ctrl, msg, flags);
2184 if (rc)
2185 pr_err("command msg transfer failed, rc = %d\n", rc);
2186 }
2187
2188 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_CMD_TX, 0x0);
Ajay Singh Parmar651406a2016-07-20 17:17:49 -07002189
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002190error:
2191 mutex_unlock(&dsi_ctrl->ctrl_lock);
2192 return rc;
2193}
2194
2195/**
2196 * dsi_ctrl_cmd_tx_trigger() - Trigger a deferred command.
2197 * @dsi_ctrl: DSI controller handle.
2198 * @flags: Modifiers.
2199 *
2200 * Return: error code.
2201 */
2202int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
2203{
Clarence Ip80ada7f2017-05-04 09:55:21 -07002204 int rc = 0, ret = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002205 u32 status = 0;
2206 u32 mask = (DSI_CMD_MODE_DMA_DONE);
2207
2208 if (!dsi_ctrl) {
2209 pr_err("Invalid params\n");
2210 return -EINVAL;
2211 }
2212
2213 mutex_lock(&dsi_ctrl->ctrl_lock);
2214
Clarence Ip80ada7f2017-05-04 09:55:21 -07002215 if (!(flags & DSI_CTRL_CMD_BROADCAST_MASTER))
2216 dsi_ctrl->hw.ops.trigger_command_dma(&dsi_ctrl->hw);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002217
2218 if ((flags & DSI_CTRL_CMD_BROADCAST) &&
Clarence Ip80ada7f2017-05-04 09:55:21 -07002219 (flags & DSI_CTRL_CMD_BROADCAST_MASTER)) {
2220 dsi_ctrl_enable_status_interrupt(dsi_ctrl,
2221 DSI_SINT_CMD_MODE_DMA_DONE, NULL);
2222 reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002223
Clarence Ip80ada7f2017-05-04 09:55:21 -07002224 /* trigger command */
2225 dsi_ctrl->hw.ops.trigger_command_dma(&dsi_ctrl->hw);
2226
2227 ret = wait_for_completion_timeout(
2228 &dsi_ctrl->irq_info.cmd_dma_done,
2229 msecs_to_jiffies(DSI_CTRL_TX_TO_MS));
2230
2231 if (ret == 0) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002232 status = dsi_ctrl->hw.ops.get_interrupt_status(
2233 &dsi_ctrl->hw);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002234 if (status & mask) {
2235 status |= (DSI_CMD_MODE_DMA_DONE |
2236 DSI_BTA_DONE);
2237 dsi_ctrl->hw.ops.clear_interrupt_status(
2238 &dsi_ctrl->hw,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002239 status);
Clarence Ip80ada7f2017-05-04 09:55:21 -07002240 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
2241 DSI_SINT_CMD_MODE_DMA_DONE);
2242 complete_all(&dsi_ctrl->irq_info.cmd_dma_done);
2243 pr_warn("dma_tx done but irq not triggered\n");
2244 } else {
2245 rc = -ETIMEDOUT;
2246 dsi_ctrl_disable_status_interrupt(dsi_ctrl,
2247 DSI_SINT_CMD_MODE_DMA_DONE);
2248 pr_err("[DSI_%d]Command transfer failed\n",
2249 dsi_ctrl->cell_index);
2250 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002251 }
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002252 }
2253
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002254 mutex_unlock(&dsi_ctrl->ctrl_lock);
2255 return rc;
2256}
2257
2258/**
Rajkumar Subbiah01e6dd642017-07-05 14:47:47 -04002259 * _dsi_ctrl_cache_misr - Cache frame MISR value
2260 * @dsi_ctrl: Pointer to associated dsi_ctrl structure
2261 */
2262static void _dsi_ctrl_cache_misr(struct dsi_ctrl *dsi_ctrl)
2263{
2264 u32 misr;
2265
2266 if (!dsi_ctrl || !dsi_ctrl->hw.ops.collect_misr)
2267 return;
2268
2269 misr = dsi_ctrl->hw.ops.collect_misr(&dsi_ctrl->hw,
2270 dsi_ctrl->host_config.panel_mode);
2271
2272 if (misr)
2273 dsi_ctrl->misr_cache = misr;
2274
2275 pr_debug("DSI_%d misr_cache = %x\n", dsi_ctrl->cell_index,
2276 dsi_ctrl->misr_cache);
2277
2278}
2279
2280/**
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002281 * dsi_ctrl_set_power_state() - set power state for dsi controller
2282 * @dsi_ctrl: DSI controller handle.
2283 * @state: Power state.
2284 *
2285 * Set power state for DSI controller. Power state can be changed only when
2286 * Controller, Video and Command engines are turned off.
2287 *
2288 * Return: error code.
2289 */
2290int dsi_ctrl_set_power_state(struct dsi_ctrl *dsi_ctrl,
2291 enum dsi_power_state state)
2292{
2293 int rc = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002294
2295 if (!dsi_ctrl || (state >= DSI_CTRL_POWER_MAX)) {
2296 pr_err("Invalid Params\n");
2297 return -EINVAL;
2298 }
2299
2300 mutex_lock(&dsi_ctrl->ctrl_lock);
2301
2302 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_POWER_STATE_CHANGE,
2303 state);
2304 if (rc) {
2305 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002306 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002307 goto error;
2308 }
2309
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302310 if (state == DSI_CTRL_POWER_VREG_ON) {
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002311 rc = dsi_ctrl_enable_supplies(dsi_ctrl, true);
2312 if (rc) {
2313 pr_err("[%d]failed to enable voltage supplies, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002314 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002315 goto error;
2316 }
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302317 } else if (state == DSI_CTRL_POWER_VREG_OFF) {
Rajkumar Subbiah01e6dd642017-07-05 14:47:47 -04002318 if (dsi_ctrl->misr_enable)
2319 _dsi_ctrl_cache_misr(dsi_ctrl);
2320
Dhaval Patel4fc756b62016-08-10 11:25:48 -07002321 rc = dsi_ctrl_enable_supplies(dsi_ctrl, false);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002322 if (rc) {
2323 pr_err("[%d]failed to disable vreg supplies, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002324 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002325 goto error;
2326 }
2327 }
2328
Alexander Beykun32a6a182017-02-27 17:46:51 -05002329 pr_debug("[DSI_%d] Power state updated to %d\n", dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002330 state);
2331 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_POWER_STATE_CHANGE, state);
2332error:
2333 mutex_unlock(&dsi_ctrl->ctrl_lock);
2334 return rc;
2335}
2336
2337/**
2338 * dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller
2339 * @dsi_ctrl: DSI controller handle.
2340 * @on: enable/disable test pattern.
2341 *
2342 * Test pattern can be enabled only after Video engine (for video mode panels)
2343 * or command engine (for cmd mode panels) is enabled.
2344 *
2345 * Return: error code.
2346 */
2347int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on)
2348{
2349 int rc = 0;
2350
2351 if (!dsi_ctrl) {
2352 pr_err("Invalid params\n");
2353 return -EINVAL;
2354 }
2355
2356 mutex_lock(&dsi_ctrl->ctrl_lock);
2357
2358 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_TPG, on);
2359 if (rc) {
2360 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002361 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002362 goto error;
2363 }
2364
2365 if (on) {
2366 if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) {
2367 dsi_ctrl->hw.ops.video_test_pattern_setup(&dsi_ctrl->hw,
2368 DSI_TEST_PATTERN_INC,
2369 0xFFFF);
2370 } else {
2371 dsi_ctrl->hw.ops.cmd_test_pattern_setup(
2372 &dsi_ctrl->hw,
2373 DSI_TEST_PATTERN_INC,
2374 0xFFFF,
2375 0x0);
2376 }
2377 }
2378 dsi_ctrl->hw.ops.test_pattern_enable(&dsi_ctrl->hw, on);
2379
Alexander Beykun32a6a182017-02-27 17:46:51 -05002380 pr_debug("[DSI_%d]Set test pattern state=%d\n",
2381 dsi_ctrl->cell_index, on);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002382 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_TPG, on);
2383error:
2384 mutex_unlock(&dsi_ctrl->ctrl_lock);
2385 return rc;
2386}
2387
2388/**
2389 * dsi_ctrl_set_host_engine_state() - set host engine state
2390 * @dsi_ctrl: DSI Controller handle.
2391 * @state: Engine state.
2392 *
2393 * Host engine state can be modified only when DSI controller power state is
2394 * set to DSI_CTRL_POWER_LINK_CLK_ON and cmd, video engines are disabled.
2395 *
2396 * Return: error code.
2397 */
2398int dsi_ctrl_set_host_engine_state(struct dsi_ctrl *dsi_ctrl,
2399 enum dsi_engine_state state)
2400{
2401 int rc = 0;
2402
2403 if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) {
2404 pr_err("Invalid params\n");
2405 return -EINVAL;
2406 }
2407
2408 mutex_lock(&dsi_ctrl->ctrl_lock);
2409
2410 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_ENGINE, state);
2411 if (rc) {
2412 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002413 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002414 goto error;
2415 }
2416
2417 if (state == DSI_CTRL_ENGINE_ON)
2418 dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true);
2419 else
2420 dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, false);
2421
Alexander Beykun32a6a182017-02-27 17:46:51 -05002422 pr_debug("[DSI_%d] Set host engine state = %d\n", dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002423 state);
2424 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_ENGINE, state);
2425error:
2426 mutex_unlock(&dsi_ctrl->ctrl_lock);
2427 return rc;
2428}
2429
2430/**
2431 * dsi_ctrl_set_cmd_engine_state() - set command engine state
2432 * @dsi_ctrl: DSI Controller handle.
2433 * @state: Engine state.
2434 *
2435 * Command engine state can be modified only when DSI controller power state is
2436 * set to DSI_CTRL_POWER_LINK_CLK_ON.
2437 *
2438 * Return: error code.
2439 */
2440int dsi_ctrl_set_cmd_engine_state(struct dsi_ctrl *dsi_ctrl,
2441 enum dsi_engine_state state)
2442{
2443 int rc = 0;
2444
2445 if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) {
2446 pr_err("Invalid params\n");
2447 return -EINVAL;
2448 }
2449
2450 mutex_lock(&dsi_ctrl->ctrl_lock);
2451
2452 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_CMD_ENGINE, state);
2453 if (rc) {
2454 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002455 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002456 goto error;
2457 }
2458
2459 if (state == DSI_CTRL_ENGINE_ON)
2460 dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, true);
2461 else
2462 dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, false);
2463
Alexander Beykun32a6a182017-02-27 17:46:51 -05002464 pr_debug("[DSI_%d] Set cmd engine state = %d\n", dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002465 state);
2466 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_CMD_ENGINE, state);
2467error:
2468 mutex_unlock(&dsi_ctrl->ctrl_lock);
2469 return rc;
2470}
2471
2472/**
2473 * dsi_ctrl_set_vid_engine_state() - set video engine state
2474 * @dsi_ctrl: DSI Controller handle.
2475 * @state: Engine state.
2476 *
2477 * Video engine state can be modified only when DSI controller power state is
2478 * set to DSI_CTRL_POWER_LINK_CLK_ON.
2479 *
2480 * Return: error code.
2481 */
2482int dsi_ctrl_set_vid_engine_state(struct dsi_ctrl *dsi_ctrl,
2483 enum dsi_engine_state state)
2484{
2485 int rc = 0;
2486 bool on;
2487
2488 if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) {
2489 pr_err("Invalid params\n");
2490 return -EINVAL;
2491 }
2492
2493 mutex_lock(&dsi_ctrl->ctrl_lock);
2494
2495 rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_VID_ENGINE, state);
2496 if (rc) {
2497 pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002498 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002499 goto error;
2500 }
2501
2502 on = (state == DSI_CTRL_ENGINE_ON) ? true : false;
2503 dsi_ctrl->hw.ops.video_engine_en(&dsi_ctrl->hw, on);
2504
2505 /* perform a reset when turning off video engine */
2506 if (!on)
2507 dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
2508
Alexander Beykun32a6a182017-02-27 17:46:51 -05002509 pr_debug("[DSI_%d] Set video engine state = %d\n", dsi_ctrl->cell_index,
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002510 state);
2511 dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_VID_ENGINE, state);
2512error:
2513 mutex_unlock(&dsi_ctrl->ctrl_lock);
2514 return rc;
2515}
2516
2517/**
Shashank Babu Chinta Venkata82109522017-05-09 18:59:21 -07002518 * dsi_ctrl_set_ulps() - set ULPS state for DSI lanes.
2519 * @dsi_ctrl: DSI controller handle.
2520 * @enable: enable/disable ULPS.
2521 *
2522 * ULPS can be enabled/disabled after DSI host engine is turned on.
2523 *
2524 * Return: error code.
2525 */
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002526int dsi_ctrl_set_ulps(struct dsi_ctrl *dsi_ctrl, bool enable)
2527{
2528 int rc = 0;
2529
2530 if (!dsi_ctrl) {
2531 pr_err("Invalid params\n");
2532 return -EINVAL;
2533 }
2534
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302535 mutex_lock(&dsi_ctrl->ctrl_lock);
2536
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002537 if (enable)
2538 rc = dsi_enable_ulps(dsi_ctrl);
2539 else
2540 rc = dsi_disable_ulps(dsi_ctrl);
2541
2542 if (rc) {
2543 pr_err("[DSI_%d] Ulps state change(%d) failed, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002544 dsi_ctrl->cell_index, enable, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002545 goto error;
2546 }
Alexander Beykun32a6a182017-02-27 17:46:51 -05002547 pr_debug("[DSI_%d] ULPS state = %d\n", dsi_ctrl->cell_index, enable);
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302548
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002549error:
2550 mutex_unlock(&dsi_ctrl->ctrl_lock);
2551 return rc;
2552}
2553
2554/**
2555 * dsi_ctrl_set_clamp_state() - set clamp state for DSI phy
2556 * @dsi_ctrl: DSI controller handle.
2557 * @enable: enable/disable clamping.
2558 *
2559 * Clamps can be enabled/disabled while DSI contoller is still turned on.
2560 *
2561 * Return: error code.
2562 */
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302563int dsi_ctrl_set_clamp_state(struct dsi_ctrl *dsi_ctrl,
2564 bool enable, bool ulps_enabled)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002565{
2566 int rc = 0;
2567
2568 if (!dsi_ctrl) {
2569 pr_err("Invalid params\n");
2570 return -EINVAL;
2571 }
2572
Padmanabhan Komanduru8ee8ee52016-12-19 12:10:51 +05302573 if (!dsi_ctrl->hw.ops.clamp_enable ||
2574 !dsi_ctrl->hw.ops.clamp_disable) {
2575 pr_debug("No clamp control for DSI controller\n");
2576 return 0;
2577 }
2578
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002579 mutex_lock(&dsi_ctrl->ctrl_lock);
2580
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302581 rc = dsi_enable_io_clamp(dsi_ctrl, enable, ulps_enabled);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002582 if (rc) {
Alexander Beykun32a6a182017-02-27 17:46:51 -05002583 pr_err("[DSI_%d] Failed to enable IO clamp\n",
2584 dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002585 goto error;
2586 }
2587
Alexander Beykun32a6a182017-02-27 17:46:51 -05002588 pr_debug("[DSI_%d] Clamp state = %d\n", dsi_ctrl->cell_index, enable);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002589error:
2590 mutex_unlock(&dsi_ctrl->ctrl_lock);
2591 return rc;
2592}
2593
2594/**
2595 * dsi_ctrl_set_clock_source() - set clock source fpr dsi link clocks
2596 * @dsi_ctrl: DSI controller handle.
2597 * @source_clks: Source clocks for DSI link clocks.
2598 *
2599 * Clock source should be changed while link clocks are disabled.
2600 *
2601 * Return: error code.
2602 */
2603int dsi_ctrl_set_clock_source(struct dsi_ctrl *dsi_ctrl,
2604 struct dsi_clk_link_set *source_clks)
2605{
2606 int rc = 0;
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002607
2608 if (!dsi_ctrl || !source_clks) {
2609 pr_err("Invalid params\n");
2610 return -EINVAL;
2611 }
2612
2613 mutex_lock(&dsi_ctrl->ctrl_lock);
2614
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002615 rc = dsi_clk_update_parent(source_clks, &dsi_ctrl->clk_info.rcg_clks);
2616 if (rc) {
2617 pr_err("[DSI_%d]Failed to update link clk parent, rc=%d\n",
Alexander Beykun32a6a182017-02-27 17:46:51 -05002618 dsi_ctrl->cell_index, rc);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002619 (void)dsi_clk_update_parent(&dsi_ctrl->clk_info.pll_op_clks,
2620 &dsi_ctrl->clk_info.rcg_clks);
2621 goto error;
2622 }
2623
2624 dsi_ctrl->clk_info.pll_op_clks.byte_clk = source_clks->byte_clk;
2625 dsi_ctrl->clk_info.pll_op_clks.pixel_clk = source_clks->pixel_clk;
2626
Alexander Beykun32a6a182017-02-27 17:46:51 -05002627 pr_debug("[DSI_%d] Source clocks are updated\n", dsi_ctrl->cell_index);
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002628
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002629error:
2630 mutex_unlock(&dsi_ctrl->ctrl_lock);
2631 return rc;
2632}
2633
2634/**
Rajkumar Subbiah01e6dd642017-07-05 14:47:47 -04002635 * dsi_ctrl_setup_misr() - Setup frame MISR
2636 * @dsi_ctrl: DSI controller handle.
2637 * @enable: enable/disable MISR.
2638 * @frame_count: Number of frames to accumulate MISR.
2639 *
2640 * Return: error code.
2641 */
2642int dsi_ctrl_setup_misr(struct dsi_ctrl *dsi_ctrl,
2643 bool enable,
2644 u32 frame_count)
2645{
2646 if (!dsi_ctrl) {
2647 pr_err("Invalid params\n");
2648 return -EINVAL;
2649 }
2650
2651 if (!dsi_ctrl->hw.ops.setup_misr)
2652 return 0;
2653
2654 mutex_lock(&dsi_ctrl->ctrl_lock);
2655 dsi_ctrl->misr_enable = enable;
2656 dsi_ctrl->hw.ops.setup_misr(&dsi_ctrl->hw,
2657 dsi_ctrl->host_config.panel_mode,
2658 enable, frame_count);
2659 mutex_unlock(&dsi_ctrl->ctrl_lock);
2660 return 0;
2661}
2662
2663/**
2664 * dsi_ctrl_collect_misr() - Read frame MISR
2665 * @dsi_ctrl: DSI controller handle.
2666 *
2667 * Return: MISR value.
2668 */
2669u32 dsi_ctrl_collect_misr(struct dsi_ctrl *dsi_ctrl)
2670{
2671 u32 misr;
2672
2673 if (!dsi_ctrl || !dsi_ctrl->hw.ops.collect_misr)
2674 return 0;
2675
2676 misr = dsi_ctrl->hw.ops.collect_misr(&dsi_ctrl->hw,
2677 dsi_ctrl->host_config.panel_mode);
2678 if (!misr)
2679 misr = dsi_ctrl->misr_cache;
2680
2681 pr_debug("DSI_%d cached misr = %x, final = %x\n",
2682 dsi_ctrl->cell_index, dsi_ctrl->misr_cache, misr);
2683
2684 return misr;
2685}
2686
2687/**
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002688 * dsi_ctrl_drv_register() - register platform driver for dsi controller
2689 */
Ajay Singh Parmar64c19192016-06-10 16:44:56 -07002690void dsi_ctrl_drv_register(void)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002691{
2692 platform_driver_register(&dsi_ctrl_driver);
2693}
2694
2695/**
2696 * dsi_ctrl_drv_unregister() - unregister platform driver
2697 */
Ajay Singh Parmar64c19192016-06-10 16:44:56 -07002698void dsi_ctrl_drv_unregister(void)
Ajay Singh Parmar5c6b4862016-06-22 17:31:21 -07002699{
2700 platform_driver_unregister(&dsi_ctrl_driver);
2701}