blob: 19de5dabdd3d6e663732c4f89dc8b541545e53c7 [file] [log] [blame]
Xipeng Gu4ef53f92019-08-19 22:01:42 +08001/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/of.h>
16#include <linux/of_gpio.h>
17#include <linux/gpio.h>
18#include <linux/qpnp/pin.h>
19#include <linux/delay.h>
20#include <linux/slab.h>
21#include <linux/leds.h>
22#include <linux/qpnp/pwm.h>
23#include <linux/err.h>
24#include <linux/string.h>
25
26#include "mdss_dsi.h"
Arun kumar83b8d522018-05-23 16:57:26 +053027#include "mdss_debug.h"
Sachin Bhayareeeb88892018-01-02 16:36:01 +053028#ifdef TARGET_HW_MDSS_HDMI
29#include "mdss_dba_utils.h"
30#endif
Ingrid Gallardo53795e72016-10-12 18:38:48 -070031#include "mdss_debug.h"
32
Sachin Bhayareeeb88892018-01-02 16:36:01 +053033#define DT_CMD_HDR 6
Sachin Bhayareeeb88892018-01-02 16:36:01 +053034#define DEFAULT_MDP_TRANSFER_TIME 14000
35
36#define VSYNC_DELAY msecs_to_jiffies(17)
37
38DEFINE_LED_TRIGGER(bl_led_trigger);
39
40void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl)
41{
42 if (ctrl->pwm_pmi)
43 return;
44
45 ctrl->pwm_bl = pwm_request(ctrl->pwm_lpg_chan, "lcd-bklt");
46 if (ctrl->pwm_bl == NULL || IS_ERR(ctrl->pwm_bl)) {
47 pr_err("%s: Error: lpg_chan=%d pwm request failed",
48 __func__, ctrl->pwm_lpg_chan);
49 }
50 ctrl->pwm_enabled = 0;
51}
52
53bool mdss_dsi_panel_pwm_enable(struct mdss_dsi_ctrl_pdata *ctrl)
54{
55 bool status = true;
56
57 if (!ctrl->pwm_enabled)
58 goto end;
59
60 if (pwm_enable(ctrl->pwm_bl)) {
61 pr_err("%s: pwm_enable() failed\n", __func__);
62 status = false;
63 }
64
65 ctrl->pwm_enabled = 1;
66
67end:
68 return status;
69}
70
71static void mdss_dsi_panel_bklt_pwm(struct mdss_dsi_ctrl_pdata *ctrl, int level)
72{
73 int ret;
74 u32 duty;
75 u32 period_ns;
76
77 if (ctrl->pwm_bl == NULL) {
78 pr_err("%s: no PWM\n", __func__);
79 return;
80 }
81
82 if (level == 0) {
83 if (ctrl->pwm_enabled) {
Vishnuvardhan Prodduturia814fd92018-02-13 11:38:43 +053084 ret = pwm_config(ctrl->pwm_bl, 0,
85 ctrl->pwm_period * NSEC_PER_USEC);
Sachin Bhayareeeb88892018-01-02 16:36:01 +053086 if (ret)
Vishnuvardhan Prodduturia814fd92018-02-13 11:38:43 +053087 pr_err("%s: pwm_config() failed err=%d.\n",
Sachin Bhayareeeb88892018-01-02 16:36:01 +053088 __func__, ret);
89 pwm_disable(ctrl->pwm_bl);
90 }
91 ctrl->pwm_enabled = 0;
92 return;
93 }
94
95 duty = level * ctrl->pwm_period;
96 duty /= ctrl->bklt_max;
97
98 pr_debug("%s: bklt_ctrl=%d pwm_period=%d pwm_gpio=%d pwm_lpg_chan=%d\n",
99 __func__, ctrl->bklt_ctrl, ctrl->pwm_period,
100 ctrl->pwm_pmic_gpio, ctrl->pwm_lpg_chan);
101
102 pr_debug("%s: ndx=%d level=%d duty=%d\n", __func__,
103 ctrl->ndx, level, duty);
104
105 if (ctrl->pwm_period >= USEC_PER_SEC) {
106 ret = pwm_config_us(ctrl->pwm_bl, duty, ctrl->pwm_period);
107 if (ret) {
108 pr_err("%s: pwm_config_us() failed err=%d.\n",
109 __func__, ret);
110 return;
111 }
112 } else {
113 period_ns = ctrl->pwm_period * NSEC_PER_USEC;
114 ret = pwm_config(ctrl->pwm_bl,
115 level * period_ns / ctrl->bklt_max,
116 period_ns);
117 if (ret) {
118 pr_err("%s: pwm_config() failed err=%d.\n",
119 __func__, ret);
120 return;
121 }
122 }
123
124 if (!ctrl->pwm_enabled) {
125 ret = pwm_enable(ctrl->pwm_bl);
126 if (ret)
127 pr_err("%s: pwm_enable() failed err=%d\n", __func__,
128 ret);
129 ctrl->pwm_enabled = 1;
130 }
131}
132
133static char dcs_cmd[2] = {0x54, 0x00}; /* DTYPE_DCS_READ */
134static struct dsi_cmd_desc dcs_read_cmd = {
135 {DTYPE_DCS_READ, 1, 0, 1, 5, sizeof(dcs_cmd)},
136 dcs_cmd
137};
138
139int mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0,
140 char cmd1, void (*fxn)(int), char *rbuf, int len)
141{
142 struct dcs_cmd_req cmdreq;
143 struct mdss_panel_info *pinfo;
144
145 pinfo = &(ctrl->panel_data.panel_info);
146 if (pinfo->dcs_cmd_by_left) {
147 if (ctrl->ndx != DSI_CTRL_LEFT)
148 return -EINVAL;
149 }
150
151 dcs_cmd[0] = cmd0;
152 dcs_cmd[1] = cmd1;
153 memset(&cmdreq, 0, sizeof(cmdreq));
154 cmdreq.cmds = &dcs_read_cmd;
155 cmdreq.cmds_cnt = 1;
156 cmdreq.flags = CMD_REQ_RX | CMD_REQ_COMMIT;
157 cmdreq.rlen = len;
158 cmdreq.rbuf = rbuf;
159 cmdreq.cb = fxn; /* call back */
160 /*
161 * blocked here, until call back called
162 */
163
164 return mdss_dsi_cmdlist_put(ctrl, &cmdreq);
165}
166
167static void mdss_dsi_panel_apply_settings(struct mdss_dsi_ctrl_pdata *ctrl,
168 struct dsi_panel_cmds *pcmds)
169{
170 struct dcs_cmd_req cmdreq;
171 struct mdss_panel_info *pinfo;
172
173 pinfo = &(ctrl->panel_data.panel_info);
174 if ((pinfo->dcs_cmd_by_left) && (ctrl->ndx != DSI_CTRL_LEFT))
175 return;
176
177 memset(&cmdreq, 0, sizeof(cmdreq));
178 cmdreq.cmds = pcmds->cmds;
179 cmdreq.cmds_cnt = pcmds->cmd_cnt;
180 cmdreq.flags = CMD_REQ_COMMIT;
181 cmdreq.rlen = 0;
182 cmdreq.cb = NULL;
183 mdss_dsi_cmdlist_put(ctrl, &cmdreq);
184}
185
186static void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl,
187 struct dsi_panel_cmds *pcmds, u32 flags)
188{
189 struct dcs_cmd_req cmdreq;
190 struct mdss_panel_info *pinfo;
191
192 pinfo = &(ctrl->panel_data.panel_info);
193 if (pinfo->dcs_cmd_by_left) {
194 if (ctrl->ndx != DSI_CTRL_LEFT)
195 return;
196 }
197
198 memset(&cmdreq, 0, sizeof(cmdreq));
199 cmdreq.cmds = pcmds->cmds;
200 cmdreq.cmds_cnt = pcmds->cmd_cnt;
201 cmdreq.flags = flags;
202
203 /*Panel ON/Off commands should be sent in DSI Low Power Mode*/
204 if (pcmds->link_state == DSI_LP_MODE)
205 cmdreq.flags |= CMD_REQ_LP_MODE;
206 else if (pcmds->link_state == DSI_HS_MODE)
207 cmdreq.flags |= CMD_REQ_HS_MODE;
208
209 cmdreq.rlen = 0;
210 cmdreq.cb = NULL;
211
212 mdss_dsi_cmdlist_put(ctrl, &cmdreq);
213}
214
215static char led_pwm1[2] = {0x51, 0x0}; /* DTYPE_DCS_WRITE1 */
216static struct dsi_cmd_desc backlight_cmd = {
217 {DTYPE_DCS_WRITE1, 1, 0, 0, 1, sizeof(led_pwm1)},
218 led_pwm1
219};
220
221static void mdss_dsi_panel_bklt_dcs(struct mdss_dsi_ctrl_pdata *ctrl, int level)
222{
223 struct dcs_cmd_req cmdreq;
224 struct mdss_panel_info *pinfo;
225
226 pinfo = &(ctrl->panel_data.panel_info);
227 if (pinfo->dcs_cmd_by_left) {
228 if (ctrl->ndx != DSI_CTRL_LEFT)
229 return;
230 }
231
232 pr_debug("%s: level=%d\n", __func__, level);
233
234 led_pwm1[1] = (unsigned char)level;
235
236 memset(&cmdreq, 0, sizeof(cmdreq));
237 cmdreq.cmds = &backlight_cmd;
238 cmdreq.cmds_cnt = 1;
239 cmdreq.flags = CMD_REQ_COMMIT;
240 cmdreq.rlen = 0;
241 cmdreq.cb = NULL;
242
Yahui Wang0c1acb02017-06-07 09:40:03 +0800243 if (ctrl->bklt_dcs_op_mode == DSI_HS_MODE)
244 cmdreq.flags |= CMD_REQ_HS_MODE;
245 else
246 cmdreq.flags |= CMD_REQ_LP_MODE;
247
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530248 mdss_dsi_cmdlist_put(ctrl, &cmdreq);
249}
250
251static void mdss_dsi_panel_set_idle_mode(struct mdss_panel_data *pdata,
252 bool enable)
253{
254 struct mdss_dsi_ctrl_pdata *ctrl = NULL;
255
256 if (pdata == NULL) {
257 pr_err("%s: Invalid input data\n", __func__);
258 return;
259 }
260
261 ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
262 panel_data);
263
Arun kumar83b8d522018-05-23 16:57:26 +0530264 pr_info("%s: Idle (%d->%d)\n", __func__, ctrl->idle, enable);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530265
266 if (ctrl->idle == enable)
267 return;
268
Arun kumar83b8d522018-05-23 16:57:26 +0530269 MDSS_XLOG(ctrl->idle, enable);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530270 if (enable) {
271 if (ctrl->idle_on_cmds.cmd_cnt) {
272 mdss_dsi_panel_cmds_send(ctrl, &ctrl->idle_on_cmds,
273 CMD_REQ_COMMIT);
274 ctrl->idle = true;
275 pr_debug("Idle on\n");
276 }
277 } else {
278 if (ctrl->idle_off_cmds.cmd_cnt) {
279 mdss_dsi_panel_cmds_send(ctrl, &ctrl->idle_off_cmds,
280 CMD_REQ_COMMIT);
281 ctrl->idle = false;
282 pr_debug("Idle off\n");
283 }
284 }
285}
286
287static bool mdss_dsi_panel_get_idle_mode(struct mdss_panel_data *pdata)
288
289{
290 struct mdss_dsi_ctrl_pdata *ctrl = NULL;
291
292 if (pdata == NULL) {
293 pr_err("%s: Invalid input data\n", __func__);
294 return 0;
295 }
296 ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
297 panel_data);
298 return ctrl->idle;
299}
300
301static int mdss_dsi_request_gpios(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
302{
303 int rc = 0;
304
305 if (gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
306 rc = gpio_request(ctrl_pdata->disp_en_gpio,
307 "disp_enable");
308 if (rc) {
309 pr_err("request disp_en gpio failed, rc=%d\n",
310 rc);
311 goto disp_en_gpio_err;
312 }
313 }
314 rc = gpio_request(ctrl_pdata->rst_gpio, "disp_rst_n");
315 if (rc) {
316 pr_err("request reset gpio failed, rc=%d\n",
317 rc);
318 goto rst_gpio_err;
319 }
320 if (gpio_is_valid(ctrl_pdata->bklt_en_gpio)) {
321 rc = gpio_request(ctrl_pdata->bklt_en_gpio,
322 "bklt_enable");
323 if (rc) {
324 pr_err("request bklt gpio failed, rc=%d\n",
325 rc);
326 goto bklt_en_gpio_err;
327 }
328 }
Narender Ankam4fcd6892018-06-11 13:09:00 +0530329 if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio)) {
330 rc = gpio_request(ctrl_pdata->vdd_ext_gpio,
331 "vdd_enable");
332 if (rc) {
333 pr_err("request vdd enable gpio failed, rc=%d\n",
334 rc);
335 goto vdd_en_gpio_err;
336 }
337 }
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530338 if (gpio_is_valid(ctrl_pdata->mode_gpio)) {
339 rc = gpio_request(ctrl_pdata->mode_gpio, "panel_mode");
340 if (rc) {
341 pr_err("request panel mode gpio failed,rc=%d\n",
342 rc);
343 goto mode_gpio_err;
344 }
345 }
346 return rc;
347
348mode_gpio_err:
Narender Ankam4fcd6892018-06-11 13:09:00 +0530349 if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio))
350 gpio_free(ctrl_pdata->vdd_ext_gpio);
351vdd_en_gpio_err:
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530352 if (gpio_is_valid(ctrl_pdata->bklt_en_gpio))
353 gpio_free(ctrl_pdata->bklt_en_gpio);
354bklt_en_gpio_err:
355 gpio_free(ctrl_pdata->rst_gpio);
356rst_gpio_err:
357 if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
358 gpio_free(ctrl_pdata->disp_en_gpio);
359disp_en_gpio_err:
360 return rc;
361}
362
363int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
364{
365 struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
366 struct mdss_panel_info *pinfo = NULL;
367 int i, rc = 0;
368
369 if (pdata == NULL) {
370 pr_err("%s: Invalid input data\n", __func__);
371 return -EINVAL;
372 }
373
374 ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
375 panel_data);
376
377 pinfo = &(ctrl_pdata->panel_data.panel_info);
378
379 /* need to configure intf mux only for external interface */
380 if (pinfo->is_dba_panel) {
381 if (enable) {
382 if (gpio_is_valid(ctrl_pdata->intf_mux_gpio)) {
383 rc = gpio_request(ctrl_pdata->intf_mux_gpio,
384 "intf_mux");
385 if (rc) {
386 pr_err("request mux gpio failed, rc=%d\n",
387 rc);
388 return rc;
389 }
390 rc = gpio_direction_output(
391 ctrl_pdata->intf_mux_gpio, 0);
392 if (rc) {
393 pr_err("%s: unable to set dir for intf mux gpio\n",
394 __func__);
395 goto exit;
396 }
397 gpio_set_value(ctrl_pdata->intf_mux_gpio, 0);
398 } else {
399 pr_debug("%s:%d, intf mux gpio not specified\n",
400 __func__, __LINE__);
401 }
402 } else {
403 if (gpio_is_valid(ctrl_pdata->intf_mux_gpio))
404 gpio_free(ctrl_pdata->intf_mux_gpio);
405 }
406 }
407
408 if ((mdss_dsi_is_right_ctrl(ctrl_pdata) &&
409 mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) ||
410 pinfo->is_dba_panel) {
411 pr_debug("%s:%d, right ctrl gpio configuration not needed\n",
412 __func__, __LINE__);
413 return rc;
414 }
415
416 if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
417 pr_debug("%s:%d, reset line not configured\n",
418 __func__, __LINE__);
419 }
420
421 if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
422 pr_debug("%s:%d, reset line not configured\n",
423 __func__, __LINE__);
424 return rc;
425 }
426
427 pr_debug("%s: enable = %d\n", __func__, enable);
428
429 if (enable) {
430 rc = mdss_dsi_request_gpios(ctrl_pdata);
431 if (rc) {
432 pr_err("gpio request failed\n");
433 return rc;
434 }
435 if (!pinfo->cont_splash_enabled) {
436 if (gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
437 rc = gpio_direction_output(
438 ctrl_pdata->disp_en_gpio, 1);
439 if (rc) {
440 pr_err("%s: unable to set dir for en gpio\n",
441 __func__);
442 goto exit;
443 }
Arun kumarec570b72018-05-09 20:23:38 +0530444 gpio_set_value((ctrl_pdata->disp_en_gpio), 1);
445 usleep_range(100, 110);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530446 }
447
448 if (pdata->panel_info.rst_seq_len) {
449 rc = gpio_direction_output(ctrl_pdata->rst_gpio,
450 pdata->panel_info.rst_seq[0]);
451 if (rc) {
452 pr_err("%s: unable to set dir for rst gpio\n",
453 __func__);
454 goto exit;
455 }
456 }
457
458 for (i = 0; i < pdata->panel_info.rst_seq_len; ++i) {
459 gpio_set_value((ctrl_pdata->rst_gpio),
460 pdata->panel_info.rst_seq[i]);
461 if (pdata->panel_info.rst_seq[++i])
Vishnuvardhan Prodduturicc3789e2018-05-09 17:58:00 +0530462 usleep_range((pinfo->rst_seq[i] * 1000),
463 (pinfo->rst_seq[i] * 1000) + 10);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530464 }
465
466 if (gpio_is_valid(ctrl_pdata->bklt_en_gpio)) {
Yahui Wang12a6d372016-12-12 22:43:20 +0800467
468 if (ctrl_pdata->bklt_en_gpio_invert)
469 rc = gpio_direction_output(
470 ctrl_pdata->bklt_en_gpio, 0);
471 else
472 rc = gpio_direction_output(
473 ctrl_pdata->bklt_en_gpio, 1);
474
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530475 if (rc) {
476 pr_err("%s: unable to set dir for bklt gpio\n",
477 __func__);
478 goto exit;
479 }
480 }
481 }
482
483 if (gpio_is_valid(ctrl_pdata->mode_gpio)) {
484 bool out = false;
485
486 if (pinfo->mode_gpio_state == MODE_GPIO_HIGH)
487 out = true;
488 else if (pinfo->mode_gpio_state == MODE_GPIO_LOW)
489 out = false;
490
491 rc = gpio_direction_output(ctrl_pdata->mode_gpio, out);
492 if (rc) {
493 pr_err("%s: unable to set dir for mode gpio\n",
494 __func__);
495 goto exit;
496 }
497 }
498 if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
499 pr_debug("%s: Panel Not properly turned OFF\n",
500 __func__);
501 ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT;
502 pr_debug("%s: Reset panel done\n", __func__);
503 }
504 } else {
505 if (gpio_is_valid(ctrl_pdata->bklt_en_gpio)) {
Yahui Wang12a6d372016-12-12 22:43:20 +0800506
507 if (ctrl_pdata->bklt_en_gpio_invert)
508 gpio_set_value((ctrl_pdata->bklt_en_gpio), 1);
509 else
510 gpio_set_value((ctrl_pdata->bklt_en_gpio), 0);
511
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530512 gpio_free(ctrl_pdata->bklt_en_gpio);
513 }
514 if (gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
515 gpio_set_value((ctrl_pdata->disp_en_gpio), 0);
Arun kumarec570b72018-05-09 20:23:38 +0530516 usleep_range(100, 110);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530517 gpio_free(ctrl_pdata->disp_en_gpio);
518 }
519 gpio_set_value((ctrl_pdata->rst_gpio), 0);
520 gpio_free(ctrl_pdata->rst_gpio);
521 if (gpio_is_valid(ctrl_pdata->mode_gpio))
522 gpio_free(ctrl_pdata->mode_gpio);
523 }
524
525exit:
526 return rc;
527}
528
529/**
530 * mdss_dsi_roi_merge() - merge two roi into single roi
531 *
532 * Function used by partial update with only one dsi intf take 2A/2B
533 * (column/page) dcs commands.
534 */
535static int mdss_dsi_roi_merge(struct mdss_dsi_ctrl_pdata *ctrl,
536 struct mdss_rect *roi)
537{
538 struct mdss_panel_info *l_pinfo;
539 struct mdss_rect *l_roi;
540 struct mdss_rect *r_roi;
541 struct mdss_dsi_ctrl_pdata *other = NULL;
542 int ans = 0;
543
544 if (ctrl->ndx == DSI_CTRL_LEFT) {
545 other = mdss_dsi_get_ctrl_by_index(DSI_CTRL_RIGHT);
546 if (!other)
547 return ans;
548 l_pinfo = &(ctrl->panel_data.panel_info);
549 l_roi = &(ctrl->panel_data.panel_info.roi);
550 r_roi = &(other->panel_data.panel_info.roi);
551 } else {
552 other = mdss_dsi_get_ctrl_by_index(DSI_CTRL_LEFT);
553 if (!other)
554 return ans;
555 l_pinfo = &(other->panel_data.panel_info);
556 l_roi = &(other->panel_data.panel_info.roi);
557 r_roi = &(ctrl->panel_data.panel_info.roi);
558 }
559
560 if (l_roi->w == 0 && l_roi->h == 0) {
561 /* right only */
562 *roi = *r_roi;
563 roi->x += l_pinfo->xres;/* add left full width to x-offset */
564 } else {
565 /* left only and left+righ */
566 *roi = *l_roi;
567 roi->w += r_roi->w; /* add right width */
568 ans = 1;
569 }
570
571 return ans;
572}
573
574static char caset[] = {0x2a, 0x00, 0x00, 0x03, 0x00}; /* DTYPE_DCS_LWRITE */
575static char paset[] = {0x2b, 0x00, 0x00, 0x05, 0x00}; /* DTYPE_DCS_LWRITE */
576
577/* pack into one frame before sent */
578static struct dsi_cmd_desc set_col_page_addr_cmd[] = {
579 {{DTYPE_DCS_LWRITE, 0, 0, 0, 1, sizeof(caset)}, caset}, /* packed */
580 {{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(paset)}, paset},
581};
582
583static void mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl,
584 struct mdss_rect *roi, int unicast)
585{
586 struct dcs_cmd_req cmdreq;
587
588 caset[1] = (((roi->x) & 0xFF00) >> 8);
589 caset[2] = (((roi->x) & 0xFF));
590 caset[3] = (((roi->x - 1 + roi->w) & 0xFF00) >> 8);
591 caset[4] = (((roi->x - 1 + roi->w) & 0xFF));
592 set_col_page_addr_cmd[0].payload = caset;
593
594 paset[1] = (((roi->y) & 0xFF00) >> 8);
595 paset[2] = (((roi->y) & 0xFF));
596 paset[3] = (((roi->y - 1 + roi->h) & 0xFF00) >> 8);
597 paset[4] = (((roi->y - 1 + roi->h) & 0xFF));
598 set_col_page_addr_cmd[1].payload = paset;
599
600 memset(&cmdreq, 0, sizeof(cmdreq));
601 cmdreq.cmds_cnt = 2;
602 cmdreq.flags = CMD_REQ_COMMIT;
603 if (unicast)
604 cmdreq.flags |= CMD_REQ_UNICAST;
605 cmdreq.rlen = 0;
606 cmdreq.cb = NULL;
607
608 cmdreq.cmds = set_col_page_addr_cmd;
609 mdss_dsi_cmdlist_put(ctrl, &cmdreq);
610}
611
612static int mdss_dsi_set_col_page_addr(struct mdss_panel_data *pdata,
613 bool force_send)
614{
615 struct mdss_panel_info *pinfo;
616 struct mdss_rect roi = {0};
617 struct mdss_rect *p_roi;
618 struct mdss_rect *c_roi;
619 struct mdss_dsi_ctrl_pdata *ctrl = NULL;
620 struct mdss_dsi_ctrl_pdata *other = NULL;
621 int left_or_both = 0;
622
623 if (pdata == NULL) {
624 pr_err("%s: Invalid input data\n", __func__);
625 return -EINVAL;
626 }
627
628 ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
629 panel_data);
630
631 pinfo = &pdata->panel_info;
632 p_roi = &pinfo->roi;
633
634 /*
635 * to avoid keep sending same col_page info to panel,
636 * if roi_merge enabled, the roi of left ctrl is used
637 * to compare against new merged roi and saved new
638 * merged roi to it after comparing.
639 * if roi_merge disabled, then the calling ctrl's roi
640 * and pinfo's roi are used to compare.
641 */
642 if (pinfo->partial_update_roi_merge) {
643 left_or_both = mdss_dsi_roi_merge(ctrl, &roi);
644 other = mdss_dsi_get_ctrl_by_index(DSI_CTRL_LEFT);
645 c_roi = &other->roi;
646 } else {
647 c_roi = &ctrl->roi;
648 roi = *p_roi;
649 }
650
651 /* roi had changed, do col_page update */
652 if (force_send || !mdss_rect_cmp(c_roi, &roi)) {
653 pr_debug("%s: ndx=%d x=%d y=%d w=%d h=%d\n",
654 __func__, ctrl->ndx, p_roi->x,
655 p_roi->y, p_roi->w, p_roi->h);
656
657 *c_roi = roi; /* keep to ctrl */
658 if (c_roi->w == 0 || c_roi->h == 0) {
659 /* no new frame update */
660 pr_debug("%s: ctrl=%d, no partial roi set\n",
661 __func__, ctrl->ndx);
662 return 0;
663 }
664
Xipeng Gu4ef53f92019-08-19 22:01:42 +0800665 if (pinfo->partial_update_col_addr_offset)
666 roi.x += pinfo->partial_update_col_addr_offset;
667
668 if (pinfo->partial_update_row_addr_offset)
669 roi.y += pinfo->partial_update_row_addr_offset;
670
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530671 if (pinfo->dcs_cmd_by_left) {
672 if (left_or_both && ctrl->ndx == DSI_CTRL_RIGHT) {
673 /* 2A/2B sent by left already */
674 return 0;
675 }
676 }
677
678 if (!mdss_dsi_sync_wait_enable(ctrl)) {
679 if (pinfo->dcs_cmd_by_left)
680 ctrl = mdss_dsi_get_ctrl_by_index(
681 DSI_CTRL_LEFT);
682 mdss_dsi_send_col_page_addr(ctrl, &roi, 0);
683 } else {
684 /*
685 * when sync_wait_broadcast enabled,
686 * need trigger at right ctrl to
687 * start both dcs cmd transmission
688 */
689 other = mdss_dsi_get_other_ctrl(ctrl);
690 if (!other)
691 goto end;
692
693 if (mdss_dsi_is_left_ctrl(ctrl)) {
694 if (pinfo->partial_update_roi_merge) {
695 /*
696 * roi is the one after merged
697 * to dsi-1 only
698 */
699 mdss_dsi_send_col_page_addr(other,
700 &roi, 0);
701 } else {
702 mdss_dsi_send_col_page_addr(ctrl,
703 &ctrl->roi, 1);
704 mdss_dsi_send_col_page_addr(other,
705 &other->roi, 1);
706 }
707 } else {
708 if (pinfo->partial_update_roi_merge) {
709 /*
710 * roi is the one after merged
711 * to dsi-1 only
712 */
713 mdss_dsi_send_col_page_addr(ctrl,
714 &roi, 0);
715 } else {
716 mdss_dsi_send_col_page_addr(other,
717 &other->roi, 1);
718 mdss_dsi_send_col_page_addr(ctrl,
719 &ctrl->roi, 1);
720 }
721 }
722 }
723 }
724
725end:
726 return 0;
727}
728
729static int mdss_dsi_panel_apply_display_setting(struct mdss_panel_data *pdata,
730 u32 mode)
731{
732 struct mdss_dsi_ctrl_pdata *ctrl = NULL;
733 struct dsi_panel_cmds *lp_on_cmds;
734 struct dsi_panel_cmds *lp_off_cmds;
735
736 if (pdata == NULL) {
737 pr_err("%s: Invalid input data\n", __func__);
738 return -EINVAL;
739 }
740
741 ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
742 panel_data);
743
744 lp_on_cmds = &ctrl->lp_on_cmds;
745 lp_off_cmds = &ctrl->lp_off_cmds;
746
747 /* Apply display settings for low-persistence mode */
748 if ((mode == MDSS_PANEL_LOW_PERSIST_MODE_ON) &&
749 (lp_on_cmds->cmd_cnt))
750 mdss_dsi_panel_apply_settings(ctrl, lp_on_cmds);
751 else if ((mode == MDSS_PANEL_LOW_PERSIST_MODE_OFF) &&
752 (lp_off_cmds->cmd_cnt))
753 mdss_dsi_panel_apply_settings(ctrl, lp_off_cmds);
754 else
755 return -EINVAL;
756
757 pr_debug("%s: Persistence mode %d applied\n", __func__, mode);
758 return 0;
759}
760
761static void mdss_dsi_panel_switch_mode(struct mdss_panel_data *pdata,
762 int mode)
763{
764 struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
765 struct mipi_panel_info *mipi;
766 struct dsi_panel_cmds *pcmds;
767 u32 flags = 0;
768
769 if (pdata == NULL) {
770 pr_err("%s: Invalid input data\n", __func__);
771 return;
772 }
773
774 mipi = &pdata->panel_info.mipi;
775
776 if (!mipi->dms_mode)
777 return;
778
779 ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
780 panel_data);
781
782 if (mipi->dms_mode != DYNAMIC_MODE_RESOLUTION_SWITCH_IMMEDIATE) {
783 flags |= CMD_REQ_COMMIT;
784 if (mode == SWITCH_TO_CMD_MODE)
785 pcmds = &ctrl_pdata->video2cmd;
786 else
787 pcmds = &ctrl_pdata->cmd2video;
788 } else if ((mipi->dms_mode ==
789 DYNAMIC_MODE_RESOLUTION_SWITCH_IMMEDIATE)
790 && pdata->current_timing
791 && !list_empty(&pdata->timings_list)) {
792 struct dsi_panel_timing *pt;
793
794 pt = container_of(pdata->current_timing,
795 struct dsi_panel_timing, timing);
796
797 pr_debug("%s: sending switch commands\n", __func__);
798 pcmds = &pt->switch_cmds;
799 flags |= CMD_REQ_DMA_TPG;
800 flags |= CMD_REQ_COMMIT;
801 } else {
802 pr_warn("%s: Invalid mode switch attempted\n", __func__);
803 return;
804 }
805
806 if ((pdata->panel_info.compression_mode == COMPRESSION_DSC) &&
807 (pdata->panel_info.send_pps_before_switch))
808 mdss_dsi_panel_dsc_pps_send(ctrl_pdata, &pdata->panel_info);
809
810 mdss_dsi_panel_cmds_send(ctrl_pdata, pcmds, flags);
811
812 if ((pdata->panel_info.compression_mode == COMPRESSION_DSC) &&
813 (!pdata->panel_info.send_pps_before_switch))
814 mdss_dsi_panel_dsc_pps_send(ctrl_pdata, &pdata->panel_info);
815}
816
817static void mdss_dsi_panel_bl_ctrl(struct mdss_panel_data *pdata,
818 u32 bl_level)
819{
820 struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
821 struct mdss_dsi_ctrl_pdata *sctrl = NULL;
822
823 if (pdata == NULL) {
824 pr_err("%s: Invalid input data\n", __func__);
825 return;
826 }
827
828 ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
829 panel_data);
830
831 /*
832 * Some backlight controllers specify a minimum duty cycle
833 * for the backlight brightness. If the brightness is less
834 * than it, the controller can malfunction.
835 */
836
837 if ((bl_level < pdata->panel_info.bl_min) && (bl_level != 0))
838 bl_level = pdata->panel_info.bl_min;
839
840 switch (ctrl_pdata->bklt_ctrl) {
841 case BL_WLED:
842 led_trigger_event(bl_led_trigger, bl_level);
843 break;
844 case BL_PWM:
845 mdss_dsi_panel_bklt_pwm(ctrl_pdata, bl_level);
846 break;
847 case BL_DCS_CMD:
848 if (!mdss_dsi_sync_wait_enable(ctrl_pdata)) {
849 mdss_dsi_panel_bklt_dcs(ctrl_pdata, bl_level);
850 break;
851 }
852 /*
853 * DCS commands to update backlight are usually sent at
854 * the same time to both the controllers. However, if
855 * sync_wait is enabled, we need to ensure that the
856 * dcs commands are first sent to the non-trigger
857 * controller so that when the commands are triggered,
858 * both controllers receive it at the same time.
859 */
860 sctrl = mdss_dsi_get_other_ctrl(ctrl_pdata);
861 if (mdss_dsi_sync_wait_trigger(ctrl_pdata)) {
862 if (sctrl)
863 mdss_dsi_panel_bklt_dcs(sctrl, bl_level);
864 mdss_dsi_panel_bklt_dcs(ctrl_pdata, bl_level);
865 } else {
866 mdss_dsi_panel_bklt_dcs(ctrl_pdata, bl_level);
867 if (sctrl)
868 mdss_dsi_panel_bklt_dcs(sctrl, bl_level);
869 }
870 break;
871 default:
872 pr_err("%s: Unknown bl_ctrl configuration\n",
873 __func__);
874 break;
875 }
876}
877
878#ifdef TARGET_HW_MDSS_HDMI
879static void mdss_dsi_panel_on_hdmi(struct mdss_dsi_ctrl_pdata *ctrl,
880 struct mdss_panel_info *pinfo)
881{
882 if (ctrl->ds_registered)
883 mdss_dba_utils_video_on(pinfo->dba_data, pinfo);
884}
885#else
886static void mdss_dsi_panel_on_hdmi(struct mdss_dsi_ctrl_pdata *ctrl,
887 struct mdss_panel_info *pinfo)
888{
889 (void)(*ctrl);
890 (void)(*pinfo);
891}
892#endif
893
894static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
895{
896 struct mdss_dsi_ctrl_pdata *ctrl = NULL;
897 struct mdss_panel_info *pinfo;
898 struct dsi_panel_cmds *on_cmds;
899 int ret = 0;
900
901 if (pdata == NULL) {
902 pr_err("%s: Invalid input data\n", __func__);
903 return -EINVAL;
904 }
905
906 pinfo = &pdata->panel_info;
907 ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
908 panel_data);
909
910 pr_debug("%s: ndx=%d\n", __func__, ctrl->ndx);
911
912 if (pinfo->dcs_cmd_by_left) {
913 if (ctrl->ndx != DSI_CTRL_LEFT)
914 goto end;
915 }
916
917 on_cmds = &ctrl->on_cmds;
918
919 if ((pinfo->mipi.dms_mode == DYNAMIC_MODE_SWITCH_IMMEDIATE) &&
920 (pinfo->mipi.boot_mode != pinfo->mipi.mode))
921 on_cmds = &ctrl->post_dms_on_cmds;
922
923 pr_debug("%s: ndx=%d cmd_cnt=%d\n", __func__,
924 ctrl->ndx, on_cmds->cmd_cnt);
925
926 if (on_cmds->cmd_cnt)
927 mdss_dsi_panel_cmds_send(ctrl, on_cmds, CMD_REQ_COMMIT);
928
929 if (pinfo->compression_mode == COMPRESSION_DSC)
930 mdss_dsi_panel_dsc_pps_send(ctrl, pinfo);
931
932 mdss_dsi_panel_on_hdmi(ctrl, pinfo);
933
934 /* Ensure low persistence mode is set as before */
935 mdss_dsi_panel_apply_display_setting(pdata, pinfo->persist_mode);
936
937end:
938 pr_debug("%s:-\n", __func__);
939 return ret;
940}
941
942#ifdef TARGET_HW_MDSS_HDMI
943static void mdss_dsi_post_panel_on_hdmi(struct mdss_panel_info *pinfo)
944{
945 u32 vsync_period = 0;
946
947 if (pinfo->is_dba_panel && pinfo->is_pluggable) {
948 /* ensure at least 1 frame transfers to down stream device */
949 vsync_period = (MSEC_PER_SEC / pinfo->mipi.frame_rate) + 1;
950 msleep(vsync_period);
951 mdss_dba_utils_hdcp_enable(pinfo->dba_data, true);
952 }
953}
954#else
955static void mdss_dsi_post_panel_on_hdmi(struct mdss_panel_info *pinfo)
956{
957 (void)(*pinfo);
958}
959#endif
960
961static int mdss_dsi_post_panel_on(struct mdss_panel_data *pdata)
962{
963 struct mdss_dsi_ctrl_pdata *ctrl = NULL;
964 struct mdss_panel_info *pinfo;
965 struct dsi_panel_cmds *cmds;
966
967 if (pdata == NULL) {
968 pr_err("%s: Invalid input data\n", __func__);
969 return -EINVAL;
970 }
971
972 ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
973 panel_data);
974
975 pr_debug("%s: ctrl=%pK ndx=%d\n", __func__, ctrl, ctrl->ndx);
976
977 pinfo = &pdata->panel_info;
978 if (pinfo->dcs_cmd_by_left && ctrl->ndx != DSI_CTRL_LEFT)
979 goto end;
980
981 cmds = &ctrl->post_panel_on_cmds;
982 if (cmds->cmd_cnt) {
983 msleep(VSYNC_DELAY); /* wait for a vsync passed */
984 mdss_dsi_panel_cmds_send(ctrl, cmds, CMD_REQ_COMMIT);
985 }
986
987 mdss_dsi_post_panel_on_hdmi(pinfo);
988
989end:
990 pr_debug("%s:-\n", __func__);
991 return 0;
992}
993
994#ifdef TARGET_HW_MDSS_HDMI
995static void mdss_dsi_panel_off_hdmi(struct mdss_dsi_ctrl_pdata *ctrl,
996 struct mdss_panel_info *pinfo)
997{
998 if (ctrl->ds_registered && pinfo->is_pluggable) {
999 mdss_dba_utils_video_off(pinfo->dba_data);
1000 mdss_dba_utils_hdcp_enable(pinfo->dba_data, false);
1001 }
1002}
1003#else
1004static void mdss_dsi_panel_off_hdmi(struct mdss_dsi_ctrl_pdata *ctrl,
1005 struct mdss_panel_info *pinfo)
1006{
1007 (void)(*ctrl);
1008 (void)(*pinfo);
1009}
1010#endif
1011
1012static int mdss_dsi_panel_off(struct mdss_panel_data *pdata)
1013{
1014 struct mdss_dsi_ctrl_pdata *ctrl = NULL;
1015 struct mdss_panel_info *pinfo;
1016
1017 if (pdata == NULL) {
1018 pr_err("%s: Invalid input data\n", __func__);
1019 return -EINVAL;
1020 }
1021
1022 pinfo = &pdata->panel_info;
1023 ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
1024 panel_data);
1025
1026 pr_debug("%s: ctrl=%pK ndx=%d\n", __func__, ctrl, ctrl->ndx);
1027
1028 if (pinfo->dcs_cmd_by_left) {
1029 if (ctrl->ndx != DSI_CTRL_LEFT)
1030 goto end;
1031 }
1032
1033 if (ctrl->off_cmds.cmd_cnt)
1034 mdss_dsi_panel_cmds_send(ctrl, &ctrl->off_cmds, CMD_REQ_COMMIT);
1035
1036 mdss_dsi_panel_off_hdmi(ctrl, pinfo);
1037
1038end:
1039 /* clear idle state */
1040 ctrl->idle = false;
1041 pr_debug("%s:-\n", __func__);
1042 return 0;
1043}
1044
1045static int mdss_dsi_panel_low_power_config(struct mdss_panel_data *pdata,
1046 int enable)
1047{
1048 struct mdss_dsi_ctrl_pdata *ctrl = NULL;
1049 struct mdss_panel_info *pinfo;
1050
1051 if (pdata == NULL) {
1052 pr_err("%s: Invalid input data\n", __func__);
1053 return -EINVAL;
1054 }
1055
1056 pinfo = &pdata->panel_info;
1057 ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
1058 panel_data);
1059
1060 pr_debug("%s: ctrl=%pK ndx=%d enable=%d\n", __func__, ctrl, ctrl->ndx,
1061 enable);
1062
1063 /* Any panel specific low power commands/config */
1064 /* Control idle mode for panel */
1065 if (enable)
1066 mdss_dsi_panel_set_idle_mode(pdata, true);
1067 else
1068 mdss_dsi_panel_set_idle_mode(pdata, false);
1069 pr_debug("%s:-\n", __func__);
1070 return 0;
1071}
1072
Ingrid Gallardoc9053a42016-09-22 21:20:08 -07001073static void mdss_dsi_parse_mdp_kickoff_threshold(struct device_node *np,
1074 struct mdss_panel_info *pinfo)
1075{
1076 int len, rc;
1077 const u32 *src;
1078 u32 tmp;
1079 u32 max_delay_us;
1080
1081 pinfo->mdp_koff_thshold = false;
1082 src = of_get_property(np, "qcom,mdss-mdp-kickoff-threshold", &len);
1083 if (!src || (len == 0))
1084 return;
1085
1086 rc = of_property_read_u32(np, "qcom,mdss-mdp-kickoff-delay", &tmp);
1087 if (!rc)
1088 pinfo->mdp_koff_delay = tmp;
1089 else
1090 return;
1091
1092 if (pinfo->mipi.frame_rate == 0) {
1093 pr_err("cannot enable guard window, unexpected panel fps\n");
1094 return;
1095 }
1096
1097 pinfo->mdp_koff_thshold_low = be32_to_cpu(src[0]);
1098 pinfo->mdp_koff_thshold_high = be32_to_cpu(src[1]);
1099 max_delay_us = 1000000 / pinfo->mipi.frame_rate;
1100
1101 /* enable the feature if threshold is valid */
1102 if ((pinfo->mdp_koff_thshold_low < pinfo->mdp_koff_thshold_high) &&
1103 ((pinfo->mdp_koff_delay > 0) ||
1104 (pinfo->mdp_koff_delay < max_delay_us)))
1105 pinfo->mdp_koff_thshold = true;
1106
1107 pr_debug("panel kickoff thshold:[%d, %d] delay:%d (max:%d) enable:%d\n",
1108 pinfo->mdp_koff_thshold_low,
1109 pinfo->mdp_koff_thshold_high,
1110 pinfo->mdp_koff_delay,
1111 max_delay_us,
1112 pinfo->mdp_koff_thshold);
1113}
1114
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301115static void mdss_dsi_parse_trigger(struct device_node *np, char *trigger,
1116 char *trigger_key)
1117{
1118 const char *data;
1119
1120 *trigger = DSI_CMD_TRIGGER_SW;
1121 data = of_get_property(np, trigger_key, NULL);
1122 if (data) {
1123 if (!strcmp(data, "none"))
1124 *trigger = DSI_CMD_TRIGGER_NONE;
1125 else if (!strcmp(data, "trigger_te"))
1126 *trigger = DSI_CMD_TRIGGER_TE;
1127 else if (!strcmp(data, "trigger_sw_seof"))
1128 *trigger = DSI_CMD_TRIGGER_SW_SEOF;
1129 else if (!strcmp(data, "trigger_sw_te"))
1130 *trigger = DSI_CMD_TRIGGER_SW_TE;
1131 }
1132}
1133
1134
1135static int mdss_dsi_parse_dcs_cmds(struct device_node *np,
1136 struct dsi_panel_cmds *pcmds, char *cmd_key, char *link_key)
1137{
1138 const char *data;
1139 int blen = 0, len;
1140 char *buf, *bp;
1141 struct dsi_ctrl_hdr *dchdr;
1142 int i, cnt;
1143
1144 data = of_get_property(np, cmd_key, &blen);
1145 if (!data) {
1146 pr_err("%s: failed, key=%s\n", __func__, cmd_key);
1147 return -ENOMEM;
1148 }
1149
1150 buf = kcalloc(blen, sizeof(char), GFP_KERNEL);
1151 if (!buf)
1152 return -ENOMEM;
1153
1154 memcpy(buf, data, blen);
1155
1156 /* scan dcs commands */
1157 bp = buf;
1158 len = blen;
1159 cnt = 0;
1160 while (len >= sizeof(*dchdr)) {
1161 dchdr = (struct dsi_ctrl_hdr *)bp;
1162 dchdr->dlen = ntohs(dchdr->dlen);
1163 if (dchdr->dlen > len) {
1164 pr_err("%s: dtsi cmd=%x error, len=%d",
1165 __func__, dchdr->dtype, dchdr->dlen);
1166 goto exit_free;
1167 }
1168 bp += sizeof(*dchdr);
1169 len -= sizeof(*dchdr);
1170 bp += dchdr->dlen;
1171 len -= dchdr->dlen;
1172 cnt++;
1173 }
1174
1175 if (len != 0) {
1176 pr_err("%s: dcs_cmd=%x len=%d error!",
1177 __func__, buf[0], blen);
1178 goto exit_free;
1179 }
1180
1181 pcmds->cmds = kcalloc(cnt, sizeof(struct dsi_cmd_desc),
1182 GFP_KERNEL);
1183 if (!pcmds->cmds)
1184 goto exit_free;
1185
1186 pcmds->cmd_cnt = cnt;
1187 pcmds->buf = buf;
1188 pcmds->blen = blen;
1189
1190 bp = buf;
1191 len = blen;
1192 for (i = 0; i < cnt; i++) {
1193 dchdr = (struct dsi_ctrl_hdr *)bp;
1194 len -= sizeof(*dchdr);
1195 bp += sizeof(*dchdr);
1196 pcmds->cmds[i].dchdr = *dchdr;
1197 pcmds->cmds[i].payload = bp;
1198 bp += dchdr->dlen;
1199 len -= dchdr->dlen;
1200 }
1201
1202 /*Set default link state to LP Mode*/
1203 pcmds->link_state = DSI_LP_MODE;
1204
1205 if (link_key) {
1206 data = of_get_property(np, link_key, NULL);
1207 if (data && !strcmp(data, "dsi_hs_mode"))
1208 pcmds->link_state = DSI_HS_MODE;
1209 else
1210 pcmds->link_state = DSI_LP_MODE;
1211 }
1212
1213 pr_debug("%s: dcs_cmd=%x len=%d, cmd_cnt=%d link_state=%d\n", __func__,
1214 pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt, pcmds->link_state);
1215
1216 return 0;
1217
1218exit_free:
1219 kfree(buf);
1220 return -ENOMEM;
1221}
1222
1223
1224int mdss_panel_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing,
1225 char *dst_format)
1226{
1227 int rc = 0;
1228
1229 switch (bpp) {
1230 case 3:
1231 *dst_format = DSI_CMD_DST_FORMAT_RGB111;
1232 break;
1233 case 8:
1234 *dst_format = DSI_CMD_DST_FORMAT_RGB332;
1235 break;
1236 case 12:
1237 *dst_format = DSI_CMD_DST_FORMAT_RGB444;
1238 break;
1239 case 16:
1240 switch (mipi_mode) {
1241 case DSI_VIDEO_MODE:
1242 *dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
1243 break;
1244 case DSI_CMD_MODE:
1245 *dst_format = DSI_CMD_DST_FORMAT_RGB565;
1246 break;
1247 default:
1248 *dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
1249 break;
1250 }
1251 break;
1252 case 18:
1253 switch (mipi_mode) {
1254 case DSI_VIDEO_MODE:
1255 if (pixel_packing == 0)
1256 *dst_format = DSI_VIDEO_DST_FORMAT_RGB666;
1257 else
1258 *dst_format = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE;
1259 break;
1260 case DSI_CMD_MODE:
1261 *dst_format = DSI_CMD_DST_FORMAT_RGB666;
1262 break;
1263 default:
1264 if (pixel_packing == 0)
1265 *dst_format = DSI_VIDEO_DST_FORMAT_RGB666;
1266 else
1267 *dst_format = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE;
1268 break;
1269 }
1270 break;
1271 case 24:
1272 switch (mipi_mode) {
1273 case DSI_VIDEO_MODE:
1274 *dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
1275 break;
1276 case DSI_CMD_MODE:
1277 *dst_format = DSI_CMD_DST_FORMAT_RGB888;
1278 break;
1279 default:
1280 *dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
1281 break;
1282 }
1283 break;
1284 default:
1285 rc = -EINVAL;
1286 break;
1287 }
1288 return rc;
1289}
1290
1291static int mdss_dsi_parse_fbc_params(struct device_node *np,
1292 struct mdss_panel_timing *timing)
1293{
1294 int rc, fbc_enabled = 0;
1295 u32 tmp;
1296 struct fbc_panel_info *fbc = &timing->fbc;
1297
1298 fbc_enabled = of_property_read_bool(np, "qcom,mdss-dsi-fbc-enable");
1299 if (fbc_enabled) {
1300 pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__);
1301 fbc->enabled = 1;
1302 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bpp", &tmp);
1303 fbc->target_bpp = (!rc ? tmp : 24);
1304 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-packing",
1305 &tmp);
1306 fbc->comp_mode = (!rc ? tmp : 0);
1307 fbc->qerr_enable = of_property_read_bool(np,
1308 "qcom,mdss-dsi-fbc-quant-error");
1309 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bias", &tmp);
1310 fbc->cd_bias = (!rc ? tmp : 0);
1311 fbc->pat_enable = of_property_read_bool(np,
1312 "qcom,mdss-dsi-fbc-pat-mode");
1313 fbc->vlc_enable = of_property_read_bool(np,
1314 "qcom,mdss-dsi-fbc-vlc-mode");
1315 fbc->bflc_enable = of_property_read_bool(np,
1316 "qcom,mdss-dsi-fbc-bflc-mode");
1317 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-h-line-budget",
1318 &tmp);
1319 fbc->line_x_budget = (!rc ? tmp : 0);
1320 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-budget-ctrl",
1321 &tmp);
1322 fbc->block_x_budget = (!rc ? tmp : 0);
1323 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-block-budget",
1324 &tmp);
1325 fbc->block_budget = (!rc ? tmp : 0);
1326 rc = of_property_read_u32(np,
1327 "qcom,mdss-dsi-fbc-lossless-threshold", &tmp);
1328 fbc->lossless_mode_thd = (!rc ? tmp : 0);
1329 rc = of_property_read_u32(np,
1330 "qcom,mdss-dsi-fbc-lossy-threshold", &tmp);
1331 fbc->lossy_mode_thd = (!rc ? tmp : 0);
1332 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-rgb-threshold",
1333 &tmp);
1334 fbc->lossy_rgb_thd = (!rc ? tmp : 0);
1335 rc = of_property_read_u32(np,
1336 "qcom,mdss-dsi-fbc-lossy-mode-idx", &tmp);
1337 fbc->lossy_mode_idx = (!rc ? tmp : 0);
1338 rc = of_property_read_u32(np,
1339 "qcom,mdss-dsi-fbc-slice-height", &tmp);
1340 fbc->slice_height = (!rc ? tmp : 0);
1341 fbc->pred_mode = of_property_read_bool(np,
1342 "qcom,mdss-dsi-fbc-2d-pred-mode");
1343 fbc->enc_mode = of_property_read_bool(np,
1344 "qcom,mdss-dsi-fbc-ver2-mode");
1345 rc = of_property_read_u32(np,
1346 "qcom,mdss-dsi-fbc-max-pred-err", &tmp);
1347 fbc->max_pred_err = (!rc ? tmp : 0);
1348
1349 timing->compression_mode = COMPRESSION_FBC;
1350 } else {
1351 pr_debug("%s:%d Panel does not support FBC.\n",
1352 __func__, __LINE__);
1353 fbc->enabled = 0;
1354 fbc->target_bpp = 24;
1355 }
1356 return 0;
1357}
1358
1359void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl,
1360 struct mdss_panel_info *pinfo)
1361{
1362 struct dsi_panel_cmds pcmds;
1363 struct dsi_cmd_desc cmd;
1364
1365 if (!pinfo || (pinfo->compression_mode != COMPRESSION_DSC))
1366 return;
1367
1368 memset(&pcmds, 0, sizeof(pcmds));
1369 memset(&cmd, 0, sizeof(cmd));
1370
1371 cmd.dchdr.dlen = mdss_panel_dsc_prepare_pps_buf(&pinfo->dsc,
1372 ctrl->pps_buf, 0);
1373 cmd.dchdr.dtype = DTYPE_PPS;
1374 cmd.dchdr.last = 1;
1375 cmd.dchdr.wait = 10;
1376 cmd.dchdr.vc = 0;
1377 cmd.dchdr.ack = 0;
1378 cmd.payload = ctrl->pps_buf;
1379
1380 pcmds.cmd_cnt = 1;
1381 pcmds.cmds = &cmd;
1382 pcmds.link_state = DSI_LP_MODE;
1383
1384 mdss_dsi_panel_cmds_send(ctrl, &pcmds, CMD_REQ_COMMIT);
1385}
1386
1387static int mdss_dsi_parse_hdr_settings(struct device_node *np,
1388 struct mdss_panel_info *pinfo)
1389{
1390 int rc = 0;
1391 struct mdss_panel_hdr_properties *hdr_prop;
1392
1393 if (!np) {
1394 pr_err("%s: device node pointer is NULL\n", __func__);
1395 return -EINVAL;
1396 }
1397
1398 if (!pinfo) {
1399 pr_err("%s: panel info is NULL\n", __func__);
1400 return -EINVAL;
1401 }
1402
1403 hdr_prop = &pinfo->hdr_properties;
1404 hdr_prop->hdr_enabled = of_property_read_bool(np,
1405 "qcom,mdss-dsi-panel-hdr-enabled");
1406
1407 if (hdr_prop->hdr_enabled) {
1408 rc = of_property_read_u32_array(np,
1409 "qcom,mdss-dsi-panel-hdr-color-primaries",
1410 hdr_prop->display_primaries,
1411 DISPLAY_PRIMARIES_COUNT);
1412 if (rc) {
1413 pr_info("%s:%d, Unable to read color primaries,rc:%u",
1414 __func__, __LINE__,
1415 hdr_prop->hdr_enabled = false);
1416 }
1417
1418 rc = of_property_read_u32(np,
1419 "qcom,mdss-dsi-panel-peak-brightness",
1420 &(hdr_prop->peak_brightness));
1421 if (rc) {
1422 pr_info("%s:%d, Unable to read hdr brightness, rc:%u",
1423 __func__, __LINE__, rc);
1424 hdr_prop->hdr_enabled = false;
1425 }
1426
1427 rc = of_property_read_u32(np,
1428 "qcom,mdss-dsi-panel-blackness-level",
1429 &(hdr_prop->blackness_level));
1430 if (rc) {
1431 pr_info("%s:%d, Unable to read hdr brightness, rc:%u",
1432 __func__, __LINE__, rc);
1433 hdr_prop->hdr_enabled = false;
1434 }
1435 }
1436 return 0;
1437}
1438
1439static int mdss_dsi_parse_dsc_version(struct device_node *np,
1440 struct mdss_panel_timing *timing)
1441{
1442 u32 data;
1443 int rc = 0;
1444 struct dsc_desc *dsc = &timing->dsc;
1445
1446 rc = of_property_read_u32(np, "qcom,mdss-dsc-version", &data);
1447 if (rc) {
1448 dsc->version = 0x11;
1449 rc = 0;
1450 } else {
1451 dsc->version = data & 0xff;
1452 /* only support DSC 1.1 rev */
1453 if (dsc->version != 0x11) {
1454 pr_err("%s: DSC version:%d not supported\n", __func__,
1455 dsc->version);
1456 rc = -EINVAL;
1457 goto end;
1458 }
1459 }
1460
1461 rc = of_property_read_u32(np, "qcom,mdss-dsc-scr-version", &data);
1462 if (rc) {
1463 dsc->scr_rev = 0x0;
1464 rc = 0;
1465 } else {
1466 dsc->scr_rev = data & 0xff;
1467 /* only one scr rev supported */
1468 if (dsc->scr_rev > 0x1) {
1469 pr_err("%s: DSC scr version:%d not supported\n",
1470 __func__, dsc->scr_rev);
1471 rc = -EINVAL;
1472 goto end;
1473 }
1474 }
1475
1476end:
1477 return rc;
1478}
1479
1480static int mdss_dsi_parse_dsc_params(struct device_node *np,
1481 struct mdss_panel_timing *timing, bool is_split_display)
1482{
1483 u32 data, intf_width;
1484 int rc = 0;
1485 struct dsc_desc *dsc = &timing->dsc;
1486
1487 if (!np) {
1488 pr_err("%s: device node pointer is NULL\n", __func__);
1489 return -EINVAL;
1490 }
1491
1492 rc = of_property_read_u32(np, "qcom,mdss-dsc-encoders", &data);
1493 if (rc) {
1494 if (!of_find_property(np, "qcom,mdss-dsc-encoders", NULL)) {
1495 /* property is not defined, default to 1 */
1496 data = 1;
1497 } else {
1498 pr_err("%s: Error parsing qcom,mdss-dsc-encoders\n",
1499 __func__);
1500 goto end;
1501 }
1502 }
1503
1504 timing->dsc_enc_total = data;
1505
1506 if (is_split_display && (timing->dsc_enc_total > 1)) {
1507 pr_err("%s: Error: for split displays, more than 1 dsc encoder per panel is not allowed.\n",
1508 __func__);
1509 goto end;
1510 }
1511
1512 rc = of_property_read_u32(np, "qcom,mdss-dsc-slice-height", &data);
1513 if (rc)
1514 goto end;
1515 dsc->slice_height = data;
1516
1517 rc = of_property_read_u32(np, "qcom,mdss-dsc-slice-width", &data);
1518 if (rc)
1519 goto end;
1520 dsc->slice_width = data;
1521 intf_width = timing->xres;
1522
1523 if (intf_width % dsc->slice_width) {
1524 pr_err("%s: Error: multiple of slice-width:%d should match panel-width:%d\n",
1525 __func__, dsc->slice_width, intf_width);
1526 goto end;
1527 }
1528
1529 data = intf_width / dsc->slice_width;
1530 if (((timing->dsc_enc_total > 1) && ((data != 2) && (data != 4))) ||
1531 ((timing->dsc_enc_total == 1) && (data > 2))) {
1532 pr_err("%s: Error: max 2 slice per encoder. slice-width:%d should match panel-width:%d dsc_enc_total:%d\n",
1533 __func__, dsc->slice_width,
1534 intf_width, timing->dsc_enc_total);
1535 goto end;
1536 }
1537
1538 rc = of_property_read_u32(np, "qcom,mdss-dsc-slice-per-pkt", &data);
1539 if (rc)
1540 goto end;
1541 dsc->slice_per_pkt = data;
1542
1543 /*
1544 * slice_per_pkt can be either 1 or all slices_per_intf
1545 */
1546 if ((dsc->slice_per_pkt > 1) && (dsc->slice_per_pkt !=
1547 DIV_ROUND_UP(intf_width, dsc->slice_width))) {
1548 pr_err("Error: slice_per_pkt can be either 1 or all slices_per_intf\n");
1549 pr_err("%s: slice_per_pkt=%d, slice_width=%d intf_width=%d\n",
1550 __func__,
1551 dsc->slice_per_pkt, dsc->slice_width, intf_width);
1552 rc = -EINVAL;
1553 goto end;
1554 }
1555
1556 pr_debug("%s: num_enc:%d :slice h=%d w=%d s_pkt=%d\n", __func__,
1557 timing->dsc_enc_total, dsc->slice_height,
1558 dsc->slice_width, dsc->slice_per_pkt);
1559
1560 rc = of_property_read_u32(np, "qcom,mdss-dsc-bit-per-component", &data);
1561 if (rc)
1562 goto end;
1563 dsc->bpc = data;
1564
1565 rc = of_property_read_u32(np, "qcom,mdss-dsc-bit-per-pixel", &data);
1566 if (rc)
1567 goto end;
1568 dsc->bpp = data;
1569
1570 pr_debug("%s: bpc=%d bpp=%d\n", __func__,
1571 dsc->bpc, dsc->bpp);
1572
1573 dsc->block_pred_enable = of_property_read_bool(np,
1574 "qcom,mdss-dsc-block-prediction-enable");
1575
1576 dsc->enable_422 = 0;
1577 dsc->convert_rgb = 1;
1578 dsc->vbr_enable = 0;
1579
1580 dsc->config_by_manufacture_cmd = of_property_read_bool(np,
1581 "qcom,mdss-dsc-config-by-manufacture-cmd");
1582
1583 mdss_panel_dsc_parameters_calc(&timing->dsc);
1584 mdss_panel_dsc_pclk_param_calc(&timing->dsc, intf_width);
1585
1586 timing->dsc.full_frame_slices =
1587 DIV_ROUND_UP(intf_width, timing->dsc.slice_width);
1588
1589 timing->compression_mode = COMPRESSION_DSC;
1590
1591end:
1592 return rc;
1593}
1594
1595static struct device_node *mdss_dsi_panel_get_dsc_cfg_np(
1596 struct device_node *np, struct mdss_panel_data *panel_data,
1597 bool default_timing)
1598{
1599 struct device_node *dsc_cfg_np = NULL;
1600
1601
1602 /* Read the dsc config node specified by command line */
1603 if (default_timing) {
1604 dsc_cfg_np = of_get_child_by_name(np,
1605 panel_data->dsc_cfg_np_name);
1606 if (!dsc_cfg_np)
1607 pr_warn_once("%s: cannot find dsc config node:%s\n",
1608 __func__, panel_data->dsc_cfg_np_name);
1609 }
1610
1611 /*
1612 * Fall back to default from DT as nothing is specified
1613 * in command line.
1614 */
1615 if (!dsc_cfg_np && of_find_property(np, "qcom,config-select", NULL)) {
1616 dsc_cfg_np = of_parse_phandle(np, "qcom,config-select", 0);
1617 if (!dsc_cfg_np)
1618 pr_warn_once("%s:err parsing qcom,config-select\n",
1619 __func__);
1620 }
1621
1622 return dsc_cfg_np;
1623}
1624
1625static int mdss_dsi_parse_topology_config(struct device_node *np,
1626 struct dsi_panel_timing *pt, struct mdss_panel_data *panel_data,
1627 bool default_timing)
1628{
1629 int rc = 0;
1630 bool is_split_display = panel_data->panel_info.is_split_display;
1631 const char *data;
1632 struct mdss_panel_timing *timing = &pt->timing;
1633 struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
1634 struct mdss_panel_info *pinfo;
1635 struct device_node *cfg_np = NULL;
1636
1637 ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata,
1638 panel_data);
1639 pinfo = &ctrl_pdata->panel_data.panel_info;
1640
1641 cfg_np = mdss_dsi_panel_get_dsc_cfg_np(np,
1642 &ctrl_pdata->panel_data, default_timing);
1643
1644 if (cfg_np) {
1645 if (!of_property_read_u32_array(cfg_np, "qcom,lm-split",
1646 timing->lm_widths, 2)) {
1647 if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)
1648 && (timing->lm_widths[1] != 0)) {
1649 pr_err("%s: lm-split not allowed with split display\n",
1650 __func__);
1651 rc = -EINVAL;
1652 goto end;
1653 }
1654 }
Naseer Ahmed143b89b2016-12-22 16:19:10 -05001655
1656 if (!of_property_read_string(cfg_np, "qcom,split-mode",
1657 &data) && !strcmp(data, "pingpong-split"))
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301658 pinfo->use_pingpong_split = true;
1659
1660 if (((timing->lm_widths[0]) || (timing->lm_widths[1])) &&
1661 pinfo->use_pingpong_split) {
1662 pr_err("%s: pingpong_split cannot be used when lm-split[%d,%d] is specified\n",
1663 __func__,
1664 timing->lm_widths[0], timing->lm_widths[1]);
1665 return -EINVAL;
1666 }
1667
1668 pr_info("%s: cfg_node name %s lm_split:%dx%d pp_split:%s\n",
1669 __func__, cfg_np->name,
1670 timing->lm_widths[0], timing->lm_widths[1],
1671 pinfo->use_pingpong_split ? "yes" : "no");
1672 }
1673
1674 if (!pinfo->use_pingpong_split &&
1675 (timing->lm_widths[0] == 0) && (timing->lm_widths[1] == 0))
1676 timing->lm_widths[0] = pt->timing.xres;
1677
1678 data = of_get_property(np, "qcom,compression-mode", NULL);
1679 if (data) {
1680 if (cfg_np && !strcmp(data, "dsc")) {
1681 rc = mdss_dsi_parse_dsc_version(np, &pt->timing);
1682 if (rc)
1683 goto end;
1684
1685 pinfo->send_pps_before_switch =
1686 of_property_read_bool(np,
1687 "qcom,mdss-dsi-send-pps-before-switch");
1688
1689 rc = mdss_dsi_parse_dsc_params(cfg_np, &pt->timing,
1690 is_split_display);
1691 } else if (!strcmp(data, "fbc")) {
1692 rc = mdss_dsi_parse_fbc_params(np, &pt->timing);
1693 }
1694 }
1695
1696end:
1697 of_node_put(cfg_np);
1698 return rc;
1699}
1700
1701static void mdss_panel_parse_te_params(struct device_node *np,
1702 struct mdss_panel_timing *timing)
1703{
1704 struct mdss_mdp_pp_tear_check *te = &timing->te;
1705 u32 tmp;
1706 int rc = 0;
1707 /*
1708 * TE default: dsi byte clock calculated base on 70 fps;
1709 * around 14 ms to complete a kickoff cycle if te disabled;
1710 * vclk_line base on 60 fps; write is faster than read;
1711 * init == start == rdptr;
1712 */
1713 te->tear_check_en =
1714 !of_property_read_bool(np, "qcom,mdss-tear-check-disable");
1715 rc = of_property_read_u32
1716 (np, "qcom,mdss-tear-check-sync-cfg-height", &tmp);
1717 te->sync_cfg_height = (!rc ? tmp : 0xfff0);
1718 rc = of_property_read_u32
1719 (np, "qcom,mdss-tear-check-sync-init-val", &tmp);
1720 te->vsync_init_val = (!rc ? tmp : timing->yres);
1721 rc = of_property_read_u32
1722 (np, "qcom,mdss-tear-check-sync-threshold-start", &tmp);
1723 te->sync_threshold_start = (!rc ? tmp : 4);
1724 rc = of_property_read_u32
1725 (np, "qcom,mdss-tear-check-sync-threshold-continue", &tmp);
1726 te->sync_threshold_continue = (!rc ? tmp : 4);
1727 rc = of_property_read_u32(np, "qcom,mdss-tear-check-frame-rate", &tmp);
1728 te->refx100 = (!rc ? tmp : 6000);
1729 rc = of_property_read_u32
1730 (np, "qcom,mdss-tear-check-start-pos", &tmp);
1731 te->start_pos = (!rc ? tmp : timing->yres);
1732 rc = of_property_read_u32
1733 (np, "qcom,mdss-tear-check-rd-ptr-trigger-intr", &tmp);
1734 te->rd_ptr_irq = (!rc ? tmp : timing->yres + 1);
1735 te->wr_ptr_irq = 0;
1736}
1737
1738
1739static int mdss_dsi_parse_reset_seq(struct device_node *np,
1740 u32 rst_seq[MDSS_DSI_RST_SEQ_LEN], u32 *rst_len,
1741 const char *name)
1742{
1743 int num = 0, i;
1744 int rc;
1745 struct property *data;
1746 u32 tmp[MDSS_DSI_RST_SEQ_LEN];
1747 *rst_len = 0;
1748 data = of_find_property(np, name, &num);
1749 num /= sizeof(u32);
1750 if (!data || !num || num > MDSS_DSI_RST_SEQ_LEN || num % 2) {
1751 pr_debug("%s:%d, error reading %s, length found = %d\n",
1752 __func__, __LINE__, name, num);
1753 } else {
1754 rc = of_property_read_u32_array(np, name, tmp, num);
1755 if (rc)
1756 pr_debug("%s:%d, error reading %s, rc = %d\n",
1757 __func__, __LINE__, name, rc);
1758 else {
1759 for (i = 0; i < num; ++i)
1760 rst_seq[i] = tmp[i];
1761 *rst_len = num;
1762 }
1763 }
1764 return 0;
1765}
1766
1767static bool mdss_dsi_cmp_panel_reg_v2(struct mdss_dsi_ctrl_pdata *ctrl)
1768{
Ingrid Gallardo53795e72016-10-12 18:38:48 -07001769 int i, j = 0;
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301770 int len = 0, *lenp;
1771 int group = 0;
1772
1773 lenp = ctrl->status_valid_params ?: ctrl->status_cmds_rlen;
1774
1775 for (i = 0; i < ctrl->status_cmds.cmd_cnt; i++)
1776 len += lenp[i];
1777
1778 for (j = 0; j < ctrl->groups; ++j) {
1779 for (i = 0; i < len; ++i) {
Narender Ankamedf4f602018-08-30 21:45:59 +05301780 pr_debug("[%i] return:0x%x status:0x%x\n",
1781 i, ctrl->return_buf[i],
1782 (unsigned int)ctrl->status_value[group + i]);
1783 MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i],
1784 ctrl->status_value[group + i]);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301785 if (ctrl->return_buf[i] !=
1786 ctrl->status_value[group + i])
1787 break;
1788 }
1789
1790 if (i == len)
1791 return true;
1792 group += len;
1793 }
1794
1795 return false;
1796}
1797
1798static int mdss_dsi_gen_read_status(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
1799{
1800 if (!mdss_dsi_cmp_panel_reg_v2(ctrl_pdata)) {
1801 pr_err("%s: Read back value from panel is incorrect\n",
1802 __func__);
1803 return -EINVAL;
1804 } else {
1805 return 1;
1806 }
1807}
1808
1809static int mdss_dsi_nt35596_read_status(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
1810{
1811 if (!mdss_dsi_cmp_panel_reg(ctrl_pdata->status_buf,
1812 ctrl_pdata->status_value, 0)) {
1813 ctrl_pdata->status_error_count = 0;
1814 pr_err("%s: Read back value from panel is incorrect\n",
1815 __func__);
1816 return -EINVAL;
1817 }
1818 {
1819 if (!mdss_dsi_cmp_panel_reg(ctrl_pdata->status_buf,
1820 ctrl_pdata->status_value, 3)) {
1821 ctrl_pdata->status_error_count = 0;
1822 } else {
1823 if (mdss_dsi_cmp_panel_reg(ctrl_pdata->status_buf,
1824 ctrl_pdata->status_value, 4) ||
1825 mdss_dsi_cmp_panel_reg(ctrl_pdata->status_buf,
1826 ctrl_pdata->status_value, 5))
1827 ctrl_pdata->status_error_count = 0;
1828 else
1829 ctrl_pdata->status_error_count++;
1830 if (ctrl_pdata->status_error_count >=
1831 ctrl_pdata->max_status_error_count) {
1832 ctrl_pdata->status_error_count = 0;
1833 pr_err("%s: Read value bad. Error_cnt = %i\n",
1834 __func__,
1835 ctrl_pdata->status_error_count);
1836 return -EINVAL;
1837 }
1838 }
1839 return 1;
1840 }
1841}
1842
1843static void mdss_dsi_parse_roi_alignment(struct device_node *np,
1844 struct dsi_panel_timing *pt)
1845{
1846 int len = 0;
1847 u32 value[6];
1848 struct property *data;
1849 struct mdss_panel_timing *timing = &pt->timing;
1850
1851 data = of_find_property(np, "qcom,panel-roi-alignment", &len);
1852 len /= sizeof(u32);
1853 if (!data || (len != 6)) {
1854 pr_debug("%s: Panel roi alignment not found", __func__);
1855 } else {
1856 int rc = of_property_read_u32_array(np,
1857 "qcom,panel-roi-alignment", value, len);
1858 if (rc)
1859 pr_debug("%s: Error reading panel roi alignment values",
1860 __func__);
1861 else {
1862 timing->roi_alignment.xstart_pix_align = value[0];
1863 timing->roi_alignment.ystart_pix_align = value[1];
1864 timing->roi_alignment.width_pix_align = value[2];
1865 timing->roi_alignment.height_pix_align = value[3];
1866 timing->roi_alignment.min_width = value[4];
1867 timing->roi_alignment.min_height = value[5];
1868 }
1869
1870 pr_debug("%s: ROI alignment: [%d, %d, %d, %d, %d, %d]",
1871 __func__, timing->roi_alignment.xstart_pix_align,
1872 timing->roi_alignment.width_pix_align,
1873 timing->roi_alignment.ystart_pix_align,
1874 timing->roi_alignment.height_pix_align,
1875 timing->roi_alignment.min_width,
1876 timing->roi_alignment.min_height);
1877 }
1878}
1879
1880static void mdss_dsi_parse_dms_config(struct device_node *np,
1881 struct mdss_dsi_ctrl_pdata *ctrl)
1882{
1883 struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
1884 const char *data;
1885 bool dms_enabled;
1886
1887 dms_enabled = of_property_read_bool(np,
1888 "qcom,dynamic-mode-switch-enabled");
1889
1890 if (!dms_enabled) {
1891 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_DISABLED;
1892 goto exit;
1893 }
1894
1895 /* default mode is suspend_resume */
1896 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_SUSPEND_RESUME;
1897 data = of_get_property(np, "qcom,dynamic-mode-switch-type", NULL);
1898 if (data && !strcmp(data, "dynamic-resolution-switch-immediate")) {
1899 if (!list_empty(&ctrl->panel_data.timings_list))
1900 pinfo->mipi.dms_mode =
1901 DYNAMIC_MODE_RESOLUTION_SWITCH_IMMEDIATE;
1902 else
1903 pinfo->mipi.dms_mode =
1904 DYNAMIC_MODE_SWITCH_DISABLED;
1905 goto exit;
1906 }
1907
1908 if (data && !strcmp(data, "dynamic-switch-immediate"))
1909 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_IMMEDIATE;
1910 else
1911 pr_debug("%s: default dms suspend/resume\n", __func__);
1912
1913 mdss_dsi_parse_dcs_cmds(np, &ctrl->video2cmd,
Ingrid Gallardo259c4b02016-11-16 09:24:32 -08001914 "qcom,video-to-cmd-mode-switch-commands",
1915 "qcom,mode-switch-commands-state");
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301916
1917 mdss_dsi_parse_dcs_cmds(np, &ctrl->cmd2video,
Ingrid Gallardo259c4b02016-11-16 09:24:32 -08001918 "qcom,cmd-to-video-mode-switch-commands",
1919 "qcom,mode-switch-commands-state");
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301920
1921 mdss_dsi_parse_dcs_cmds(np, &ctrl->post_dms_on_cmds,
1922 "qcom,mdss-dsi-post-mode-switch-on-command",
1923 "qcom,mdss-dsi-post-mode-switch-on-command-state");
1924
1925 if (pinfo->mipi.dms_mode == DYNAMIC_MODE_SWITCH_IMMEDIATE &&
1926 !ctrl->post_dms_on_cmds.cmd_cnt) {
1927 pr_warn("%s: No post dms on cmd specified\n", __func__);
1928 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_DISABLED;
1929 }
1930
1931 if (!ctrl->video2cmd.cmd_cnt || !ctrl->cmd2video.cmd_cnt) {
1932 pr_warn("%s: No commands specified for dynamic switch\n",
1933 __func__);
1934 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_DISABLED;
1935 }
1936exit:
1937 pr_info("%s: dynamic switch feature enabled: %d\n", __func__,
1938 pinfo->mipi.dms_mode);
1939}
1940
1941/* the length of all the valid values to be checked should not be great
1942 * than the length of returned data from read command.
1943 */
1944static bool
1945mdss_dsi_parse_esd_check_valid_params(struct mdss_dsi_ctrl_pdata *ctrl)
1946{
1947 int i;
1948
1949 for (i = 0; i < ctrl->status_cmds.cmd_cnt; ++i) {
1950 if (ctrl->status_valid_params[i] > ctrl->status_cmds_rlen[i]) {
1951 pr_debug("%s: ignore valid params!\n", __func__);
1952 return false;
1953 }
1954 }
1955
1956 return true;
1957}
1958
1959static bool mdss_dsi_parse_esd_status_len(struct device_node *np,
1960 char *prop_key, u32 **target, u32 cmd_cnt)
1961{
1962 int tmp;
1963
1964 if (!of_find_property(np, prop_key, &tmp))
1965 return false;
1966
1967 tmp /= sizeof(u32);
1968 if (tmp != cmd_cnt) {
1969 pr_err("%s: request property number(%d) not match command count(%d)\n",
1970 __func__, tmp, cmd_cnt);
1971 return false;
1972 }
1973
1974 *target = kcalloc(tmp, sizeof(u32), GFP_KERNEL);
1975 if (IS_ERR_OR_NULL(*target)) {
1976 pr_err("%s: Error allocating memory for property\n",
1977 __func__);
1978 return false;
1979 }
1980
1981 if (of_property_read_u32_array(np, prop_key, *target, tmp)) {
1982 pr_err("%s: cannot get values from dts\n", __func__);
1983 kfree(*target);
1984 *target = NULL;
1985 return false;
1986 }
1987
1988 return true;
1989}
1990
1991static void mdss_dsi_parse_esd_params(struct device_node *np,
1992 struct mdss_dsi_ctrl_pdata *ctrl)
1993{
1994 u32 tmp;
1995 u32 i, status_len, *lenp;
1996 int rc;
1997 struct property *data;
1998 const char *string;
1999 struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
2000
2001 pinfo->esd_check_enabled = of_property_read_bool(np,
2002 "qcom,esd-check-enabled");
2003
2004 if (!pinfo->esd_check_enabled)
2005 return;
2006
2007 ctrl->status_mode = ESD_MAX;
2008 rc = of_property_read_string(np,
2009 "qcom,mdss-dsi-panel-status-check-mode", &string);
2010 if (!rc) {
2011 if (!strcmp(string, "bta_check")) {
2012 ctrl->status_mode = ESD_BTA;
2013 } else if (!strcmp(string, "reg_read")) {
2014 ctrl->status_mode = ESD_REG;
2015 ctrl->check_read_status =
2016 mdss_dsi_gen_read_status;
2017 } else if (!strcmp(string, "reg_read_nt35596")) {
2018 ctrl->status_mode = ESD_REG_NT35596;
2019 ctrl->status_error_count = 0;
2020 ctrl->check_read_status =
2021 mdss_dsi_nt35596_read_status;
2022 } else if (!strcmp(string, "te_signal_check")) {
2023 if (pinfo->mipi.mode == DSI_CMD_MODE) {
2024 ctrl->status_mode = ESD_TE;
2025 } else {
2026 pr_err("TE-ESD not valid for video mode\n");
2027 goto error;
2028 }
2029 } else {
2030 pr_err("No valid panel-status-check-mode string\n");
2031 goto error;
2032 }
2033 }
2034
2035 if ((ctrl->status_mode == ESD_BTA) || (ctrl->status_mode == ESD_TE) ||
2036 (ctrl->status_mode == ESD_MAX))
2037 return;
2038
2039 mdss_dsi_parse_dcs_cmds(np, &ctrl->status_cmds,
2040 "qcom,mdss-dsi-panel-status-command",
2041 "qcom,mdss-dsi-panel-status-command-state");
2042
2043 rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-max-error-count",
2044 &tmp);
2045 ctrl->max_status_error_count = (!rc ? tmp : 0);
2046
2047 if (!mdss_dsi_parse_esd_status_len(np,
2048 "qcom,mdss-dsi-panel-status-read-length",
2049 &ctrl->status_cmds_rlen, ctrl->status_cmds.cmd_cnt)) {
2050 pinfo->esd_check_enabled = false;
2051 return;
2052 }
2053
2054 if (mdss_dsi_parse_esd_status_len(np,
2055 "qcom,mdss-dsi-panel-status-valid-params",
2056 &ctrl->status_valid_params, ctrl->status_cmds.cmd_cnt)) {
2057 if (!mdss_dsi_parse_esd_check_valid_params(ctrl))
2058 goto error1;
2059 }
2060
2061 status_len = 0;
2062 lenp = ctrl->status_valid_params ?: ctrl->status_cmds_rlen;
2063 for (i = 0; i < ctrl->status_cmds.cmd_cnt; ++i)
2064 status_len += lenp[i];
2065
2066 data = of_find_property(np, "qcom,mdss-dsi-panel-status-value", &tmp);
2067 tmp /= sizeof(u32);
2068 if (!IS_ERR_OR_NULL(data) && tmp != 0 && (tmp % status_len) == 0) {
2069 ctrl->groups = tmp / status_len;
2070 } else {
2071 pr_err("%s: Error parse panel-status-value\n", __func__);
2072 goto error1;
2073 }
2074
2075 ctrl->status_value = kcalloc(status_len * ctrl->groups, sizeof(u32),
2076 GFP_KERNEL);
2077 if (!ctrl->status_value)
2078 goto error1;
2079
2080 ctrl->return_buf = kcalloc(status_len * ctrl->groups,
2081 sizeof(unsigned char), GFP_KERNEL);
2082 if (!ctrl->return_buf)
2083 goto error2;
2084
2085 rc = of_property_read_u32_array(np,
2086 "qcom,mdss-dsi-panel-status-value",
2087 ctrl->status_value, ctrl->groups * status_len);
2088 if (rc) {
2089 pr_debug("%s: Error reading panel status values\n",
2090 __func__);
2091 memset(ctrl->status_value, 0, ctrl->groups * status_len);
2092 }
2093
2094 return;
2095
2096error2:
2097 kfree(ctrl->status_value);
2098error1:
2099 kfree(ctrl->status_valid_params);
2100 kfree(ctrl->status_cmds_rlen);
2101error:
2102 pinfo->esd_check_enabled = false;
2103}
2104
2105static int mdss_dsi_parse_panel_features(struct device_node *np,
2106 struct mdss_dsi_ctrl_pdata *ctrl)
2107{
Xipeng Gu4ef53f92019-08-19 22:01:42 +08002108 u32 value[2];
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302109 struct mdss_panel_info *pinfo;
2110
2111 if (!np || !ctrl) {
2112 pr_err("%s: Invalid arguments\n", __func__);
2113 return -ENODEV;
2114 }
2115
2116 pinfo = &ctrl->panel_data.panel_info;
2117
2118 pinfo->partial_update_supported = of_property_read_bool(np,
2119 "qcom,partial-update-enabled");
2120 if (pinfo->mipi.mode == DSI_CMD_MODE) {
2121 pinfo->partial_update_enabled = pinfo->partial_update_supported;
2122 pr_info("%s: partial_update_enabled=%d\n", __func__,
2123 pinfo->partial_update_enabled);
2124 ctrl->set_col_page_addr = mdss_dsi_set_col_page_addr;
2125 if (pinfo->partial_update_enabled) {
Xipeng Gu4ef53f92019-08-19 22:01:42 +08002126 int rc = of_property_read_u32_array(np,
2127 "qcom,partial-update-addr-offset",
2128 value, 2);
2129 pinfo->partial_update_col_addr_offset =
2130 (!rc ? value[0] : 0);
2131 pinfo->partial_update_row_addr_offset =
2132 (!rc ? value[1] : 0);
2133
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302134 pinfo->partial_update_roi_merge =
2135 of_property_read_bool(np,
2136 "qcom,partial-update-roi-merge");
2137 }
2138 }
2139
2140 pinfo->dcs_cmd_by_left = of_property_read_bool(np,
2141 "qcom,dcs-cmd-by-left");
2142
2143 pinfo->ulps_feature_enabled = of_property_read_bool(np,
2144 "qcom,ulps-enabled");
2145 pr_info("%s: ulps feature %s\n", __func__,
2146 (pinfo->ulps_feature_enabled ? "enabled" : "disabled"));
2147
2148 pinfo->ulps_suspend_enabled = of_property_read_bool(np,
2149 "qcom,suspend-ulps-enabled");
2150 pr_info("%s: ulps during suspend feature %s", __func__,
2151 (pinfo->ulps_suspend_enabled ? "enabled" : "disabled"));
2152
2153 mdss_dsi_parse_dms_config(np, ctrl);
2154
2155 pinfo->panel_ack_disabled = pinfo->sim_panel_mode ?
2156 1 : of_property_read_bool(np, "qcom,panel-ack-disabled");
2157
2158 pinfo->allow_phy_power_off = of_property_read_bool(np,
2159 "qcom,panel-allow-phy-poweroff");
2160
2161 mdss_dsi_parse_esd_params(np, ctrl);
2162
2163 if (pinfo->panel_ack_disabled && pinfo->esd_check_enabled) {
2164 pr_warn("ESD should not be enabled if panel ACK is disabled\n");
2165 pinfo->esd_check_enabled = false;
2166 }
2167
2168 if (ctrl->disp_en_gpio <= 0) {
2169 ctrl->disp_en_gpio = of_get_named_gpio(
2170 np,
2171 "qcom,5v-boost-gpio", 0);
2172
2173 if (!gpio_is_valid(ctrl->disp_en_gpio))
2174 pr_debug("%s:%d, Disp_en gpio not specified\n",
2175 __func__, __LINE__);
2176 }
2177
2178 mdss_dsi_parse_dcs_cmds(np, &ctrl->lp_on_cmds,
2179 "qcom,mdss-dsi-lp-mode-on", NULL);
2180
2181 mdss_dsi_parse_dcs_cmds(np, &ctrl->lp_off_cmds,
2182 "qcom,mdss-dsi-lp-mode-off", NULL);
2183
2184 return 0;
2185}
2186
2187static void mdss_dsi_parse_panel_horizintal_line_idle(struct device_node *np,
2188 struct mdss_dsi_ctrl_pdata *ctrl)
2189{
2190 const u32 *src;
2191 int i, len, cnt;
2192 struct panel_horizontal_idle *kp;
2193
2194 if (!np || !ctrl) {
2195 pr_err("%s: Invalid arguments\n", __func__);
2196 return;
2197 }
2198
2199 src = of_get_property(np, "qcom,mdss-dsi-hor-line-idle", &len);
2200 if (!src || len == 0)
2201 return;
2202
2203 cnt = len % 3; /* 3 fields per entry */
2204 if (cnt) {
2205 pr_err("%s: invalid horizontal idle len=%d\n", __func__, len);
2206 return;
2207 }
2208
2209 cnt = len / sizeof(u32);
2210
2211 kp = kcalloc((cnt / 3), sizeof(*kp), GFP_KERNEL);
2212 if (kp == NULL)
2213 return;
2214
2215 ctrl->line_idle = kp;
2216 for (i = 0; i < cnt; i += 3) {
2217 kp->min = be32_to_cpu(src[i]);
2218 kp->max = be32_to_cpu(src[i+1]);
2219 kp->idle = be32_to_cpu(src[i+2]);
2220 kp++;
2221 ctrl->horizontal_idle_cnt++;
2222 }
2223
2224 /*
2225 * idle is enabled for this controller, this will be used to
2226 * enable/disable burst mode since both features are mutually
2227 * exclusive.
2228 */
2229 ctrl->idle_enabled = true;
2230
2231 pr_debug("%s: horizontal_idle_cnt=%d\n", __func__,
2232 ctrl->horizontal_idle_cnt);
2233}
2234
2235static int mdss_dsi_set_refresh_rate_range(struct device_node *pan_node,
2236 struct mdss_panel_info *pinfo)
2237{
2238 int rc = 0;
2239
2240 rc = of_property_read_u32(pan_node,
2241 "qcom,mdss-dsi-min-refresh-rate",
2242 &pinfo->min_fps);
2243 if (rc) {
2244 pr_warn("%s:%d, Unable to read min refresh rate\n",
2245 __func__, __LINE__);
2246
2247 /*
Aravind Venkateswaranefd2e782016-08-24 16:43:13 -07002248 * If min refresh rate is not specified, set it to the
2249 * default panel refresh rate.
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302250 */
Aravind Venkateswaranefd2e782016-08-24 16:43:13 -07002251 pinfo->min_fps = pinfo->mipi.frame_rate;
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302252 rc = 0;
2253 }
2254
2255 rc = of_property_read_u32(pan_node,
2256 "qcom,mdss-dsi-max-refresh-rate",
2257 &pinfo->max_fps);
2258 if (rc) {
2259 pr_warn("%s:%d, Unable to read max refresh rate\n",
2260 __func__, __LINE__);
2261
2262 /*
2263 * Since max refresh rate was not specified when dynamic
2264 * fps is enabled, using the default panel refresh rate
2265 * as max refresh rate supported.
2266 */
2267 pinfo->max_fps = pinfo->mipi.frame_rate;
2268 rc = 0;
2269 }
2270
2271 pr_info("dyn_fps: min = %d, max = %d\n",
2272 pinfo->min_fps, pinfo->max_fps);
2273 return rc;
2274}
2275
2276static void mdss_dsi_parse_dfps_config(struct device_node *pan_node,
2277 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2278{
2279 const char *data;
2280 bool dynamic_fps;
2281 struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
2282
2283 dynamic_fps = of_property_read_bool(pan_node,
2284 "qcom,mdss-dsi-pan-enable-dynamic-fps");
2285
2286 if (!dynamic_fps)
2287 return;
2288
2289 pinfo->dynamic_fps = true;
2290 data = of_get_property(pan_node, "qcom,mdss-dsi-pan-fps-update", NULL);
2291 if (data) {
2292 if (!strcmp(data, "dfps_suspend_resume_mode")) {
2293 pinfo->dfps_update = DFPS_SUSPEND_RESUME_MODE;
2294 pr_debug("dfps mode: suspend/resume\n");
2295 } else if (!strcmp(data, "dfps_immediate_clk_mode")) {
2296 pinfo->dfps_update = DFPS_IMMEDIATE_CLK_UPDATE_MODE;
2297 pr_debug("dfps mode: Immediate clk\n");
2298 } else if (!strcmp(data, "dfps_immediate_porch_mode_hfp")) {
2299 pinfo->dfps_update =
2300 DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP;
2301 pr_debug("dfps mode: Immediate porch HFP\n");
2302 } else if (!strcmp(data, "dfps_immediate_porch_mode_vfp")) {
2303 pinfo->dfps_update =
2304 DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP;
2305 pr_debug("dfps mode: Immediate porch VFP\n");
2306 } else {
2307 pinfo->dfps_update = DFPS_SUSPEND_RESUME_MODE;
2308 pr_debug("default dfps mode: suspend/resume\n");
2309 }
2310 mdss_dsi_set_refresh_rate_range(pan_node, pinfo);
2311 } else {
2312 pinfo->dynamic_fps = false;
2313 pr_debug("dfps update mode not configured: disable\n");
2314 }
2315 pinfo->new_fps = pinfo->mipi.frame_rate;
2316 pinfo->current_fps = pinfo->mipi.frame_rate;
2317}
2318
2319int mdss_panel_parse_bl_settings(struct device_node *np,
2320 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2321{
2322 const char *data;
2323 int rc = 0;
2324 u32 tmp;
2325
2326 ctrl_pdata->bklt_ctrl = UNKNOWN_CTRL;
2327 data = of_get_property(np, "qcom,mdss-dsi-bl-pmic-control-type", NULL);
2328 if (data) {
2329 if (!strcmp(data, "bl_ctrl_wled")) {
2330 led_trigger_register_simple("bkl-trigger",
2331 &bl_led_trigger);
2332 pr_debug("%s: SUCCESS-> WLED TRIGGER register\n",
2333 __func__);
2334 ctrl_pdata->bklt_ctrl = BL_WLED;
2335 } else if (!strcmp(data, "bl_ctrl_pwm")) {
2336 ctrl_pdata->bklt_ctrl = BL_PWM;
2337 ctrl_pdata->pwm_pmi = of_property_read_bool(np,
2338 "qcom,mdss-dsi-bl-pwm-pmi");
2339 rc = of_property_read_u32(np,
2340 "qcom,mdss-dsi-bl-pmic-pwm-frequency", &tmp);
2341 if (rc) {
2342 pr_err("%s:%d, Error, panel pwm_period\n",
2343 __func__, __LINE__);
2344 return -EINVAL;
2345 }
2346 ctrl_pdata->pwm_period = tmp;
2347 if (ctrl_pdata->pwm_pmi) {
2348 ctrl_pdata->pwm_bl = of_pwm_get(np, NULL);
2349 if (IS_ERR(ctrl_pdata->pwm_bl)) {
2350 pr_err("%s: Error, pwm device\n",
2351 __func__);
2352 ctrl_pdata->pwm_bl = NULL;
2353 return -EINVAL;
2354 }
2355 } else {
2356 rc = of_property_read_u32(np,
2357 "qcom,mdss-dsi-bl-pmic-bank-select",
2358 &tmp);
2359 if (rc) {
2360 pr_err("%s:%d, Error, lpg channel\n",
2361 __func__, __LINE__);
2362 return -EINVAL;
2363 }
2364 ctrl_pdata->pwm_lpg_chan = tmp;
2365 tmp = of_get_named_gpio(np,
2366 "qcom,mdss-dsi-pwm-gpio", 0);
2367 ctrl_pdata->pwm_pmic_gpio = tmp;
2368 pr_debug("%s: Configured PWM bklt ctrl\n",
2369 __func__);
2370 }
2371 } else if (!strcmp(data, "bl_ctrl_dcs")) {
2372 ctrl_pdata->bklt_ctrl = BL_DCS_CMD;
Yahui Wang0c1acb02017-06-07 09:40:03 +08002373 data = of_get_property(np,
2374 "qcom,mdss-dsi-bl-dcs-command-state", NULL);
2375 if (data && !strcmp(data, "dsi_hs_mode"))
2376 ctrl_pdata->bklt_dcs_op_mode = DSI_HS_MODE;
2377 else
2378 ctrl_pdata->bklt_dcs_op_mode = DSI_LP_MODE;
2379
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302380 pr_debug("%s: Configured DCS_CMD bklt ctrl\n",
2381 __func__);
2382 }
2383 }
2384 return 0;
2385}
2386
2387int mdss_dsi_panel_timing_switch(struct mdss_dsi_ctrl_pdata *ctrl,
2388 struct mdss_panel_timing *timing)
2389{
2390 struct dsi_panel_timing *pt;
2391 struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
2392 int i;
2393
2394 if (!timing)
2395 return -EINVAL;
2396
2397 if (timing == ctrl->panel_data.current_timing) {
2398 pr_warn("%s: panel timing \"%s\" already set\n", __func__,
2399 timing->name);
2400 return 0; /* nothing to do */
2401 }
2402
2403 pr_debug("%s: ndx=%d switching to panel timing \"%s\"\n", __func__,
2404 ctrl->ndx, timing->name);
2405
2406 mdss_panel_info_from_timing(timing, pinfo);
2407
2408 pt = container_of(timing, struct dsi_panel_timing, timing);
2409 pinfo->mipi.t_clk_pre = pt->t_clk_pre;
2410 pinfo->mipi.t_clk_post = pt->t_clk_post;
2411
2412 for (i = 0; i < ARRAY_SIZE(pt->phy_timing); i++)
2413 pinfo->mipi.dsi_phy_db.timing[i] = pt->phy_timing[i];
2414
2415 for (i = 0; i < ARRAY_SIZE(pt->phy_timing_8996); i++)
2416 pinfo->mipi.dsi_phy_db.timing_8996[i] = pt->phy_timing_8996[i];
2417
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +05302418 for (i = 0; i < ARRAY_SIZE(pt->phy_timing_12nm); i++)
2419 pinfo->mipi.dsi_phy_db.timing_12nm[i] = pt->phy_timing_12nm[i];
2420
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302421 ctrl->on_cmds = pt->on_cmds;
2422 ctrl->post_panel_on_cmds = pt->post_panel_on_cmds;
2423
2424 ctrl->panel_data.current_timing = timing;
2425 if (!timing->clk_rate)
2426 ctrl->refresh_clk_rate = true;
2427 mdss_dsi_clk_refresh(&ctrl->panel_data, ctrl->update_phy_timing);
2428
2429 return 0;
2430}
2431
2432void mdss_dsi_unregister_bl_settings(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2433{
2434 if (ctrl_pdata->bklt_ctrl == BL_WLED)
2435 led_trigger_unregister_simple(bl_led_trigger);
2436}
2437
2438static int mdss_dsi_panel_timing_from_dt(struct device_node *np,
2439 struct dsi_panel_timing *pt,
2440 struct mdss_panel_data *panel_data)
2441{
2442 u32 tmp;
2443 u64 tmp64;
2444 int rc, i, len;
2445 const char *data;
2446 struct mdss_dsi_ctrl_pdata *ctrl_pdata;
2447 struct mdss_panel_info *pinfo;
2448 bool phy_timings_present = false;
2449
2450 pinfo = &panel_data->panel_info;
2451
2452 ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata,
2453 panel_data);
2454
2455 rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-width", &tmp);
2456 if (rc) {
2457 pr_err("%s:%d, panel width not specified\n",
2458 __func__, __LINE__);
2459 return -EINVAL;
2460 }
2461 pt->timing.xres = tmp;
2462
2463 rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-height", &tmp);
2464 if (rc) {
2465 pr_err("%s:%d, panel height not specified\n",
2466 __func__, __LINE__);
2467 return -EINVAL;
2468 }
2469 pt->timing.yres = tmp;
2470
2471 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-front-porch", &tmp);
2472 pt->timing.h_front_porch = (!rc ? tmp : 6);
2473 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-back-porch", &tmp);
2474 pt->timing.h_back_porch = (!rc ? tmp : 6);
2475 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-pulse-width", &tmp);
2476 pt->timing.h_pulse_width = (!rc ? tmp : 2);
2477 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-sync-skew", &tmp);
2478 pt->timing.hsync_skew = (!rc ? tmp : 0);
2479 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-back-porch", &tmp);
2480 pt->timing.v_back_porch = (!rc ? tmp : 6);
2481 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-front-porch", &tmp);
2482 pt->timing.v_front_porch = (!rc ? tmp : 6);
2483 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-pulse-width", &tmp);
2484 pt->timing.v_pulse_width = (!rc ? tmp : 2);
2485
2486 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-left-border", &tmp);
2487 pt->timing.border_left = !rc ? tmp : 0;
2488 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-right-border", &tmp);
2489 pt->timing.border_right = !rc ? tmp : 0;
2490
2491 /* overriding left/right borders for split display cases */
2492 if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) {
2493 if (panel_data->next)
2494 pt->timing.border_right = 0;
2495 else
2496 pt->timing.border_left = 0;
2497 }
2498
2499 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-top-border", &tmp);
2500 pt->timing.border_top = !rc ? tmp : 0;
2501 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-bottom-border", &tmp);
2502 pt->timing.border_bottom = !rc ? tmp : 0;
2503
2504 rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-framerate", &tmp);
2505 pt->timing.frame_rate = !rc ? tmp : DEFAULT_FRAME_RATE;
2506 rc = of_property_read_u64(np, "qcom,mdss-dsi-panel-clockrate", &tmp64);
2507 if (rc == -EOVERFLOW) {
2508 tmp64 = 0;
2509 rc = of_property_read_u32(np,
2510 "qcom,mdss-dsi-panel-clockrate", (u32 *)&tmp64);
2511 }
2512 pt->timing.clk_rate = !rc ? tmp64 : 0;
2513
2514 data = of_get_property(np, "qcom,mdss-dsi-panel-timings", &len);
2515 if ((!data) || (len != 12)) {
2516 pr_debug("%s:%d, Unable to read Phy timing settings",
2517 __func__, __LINE__);
2518 } else {
2519 for (i = 0; i < len; i++)
2520 pt->phy_timing[i] = data[i];
2521 phy_timings_present = true;
2522 }
2523
2524 data = of_get_property(np, "qcom,mdss-dsi-panel-timings-phy-v2", &len);
2525 if ((!data) || (len != 40)) {
2526 pr_debug("%s:%d, Unable to read 8996 Phy lane timing settings",
2527 __func__, __LINE__);
2528 } else {
2529 for (i = 0; i < len; i++)
2530 pt->phy_timing_8996[i] = data[i];
2531 phy_timings_present = true;
2532 }
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +05302533
2534 data = of_get_property(np,
2535 "qcom,mdss-dsi-panel-timings-phy-12nm", &len);
2536 if ((!data) || (len != 8)) {
2537 pr_debug("%s:%d, Unable to read 12nm Phy lane timing settings",
2538 __func__, __LINE__);
2539 } else {
2540 for (i = 0; i < len; i++)
2541 pt->phy_timing_12nm[i] = data[i];
2542 phy_timings_present = true;
2543 }
2544
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302545 if (!phy_timings_present) {
2546 pr_err("%s: phy timing settings not present\n", __func__);
2547 return -EINVAL;
2548 }
2549
2550 rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-pre", &tmp);
2551 pt->t_clk_pre = (!rc ? tmp : 0x24);
2552 rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-post", &tmp);
2553 pt->t_clk_post = (!rc ? tmp : 0x03);
2554
2555 if (np->name) {
2556 pt->timing.name = kstrdup(np->name, GFP_KERNEL);
2557 pr_info("%s: found new timing \"%s\" (%pK)\n", __func__,
2558 np->name, &pt->timing);
2559 }
2560
2561 return 0;
2562}
2563
2564static int mdss_dsi_panel_config_res_properties(struct device_node *np,
2565 struct dsi_panel_timing *pt,
2566 struct mdss_panel_data *panel_data,
2567 bool default_timing)
2568{
2569 int rc = 0;
2570
2571 mdss_dsi_parse_roi_alignment(np, pt);
2572
2573 mdss_dsi_parse_dcs_cmds(np, &pt->on_cmds,
2574 "qcom,mdss-dsi-on-command",
2575 "qcom,mdss-dsi-on-command-state");
2576
2577 mdss_dsi_parse_dcs_cmds(np, &pt->post_panel_on_cmds,
2578 "qcom,mdss-dsi-post-panel-on-command", NULL);
2579
2580 mdss_dsi_parse_dcs_cmds(np, &pt->switch_cmds,
2581 "qcom,mdss-dsi-timing-switch-command",
2582 "qcom,mdss-dsi-timing-switch-command-state");
2583
2584 rc = mdss_dsi_parse_topology_config(np, pt, panel_data, default_timing);
2585 if (rc) {
2586 pr_err("%s: parsing compression params failed. rc:%d\n",
2587 __func__, rc);
2588 return rc;
2589 }
2590
2591 mdss_panel_parse_te_params(np, &pt->timing);
2592 return rc;
2593}
2594
2595static int mdss_panel_parse_display_timings(struct device_node *np,
2596 struct mdss_panel_data *panel_data)
2597{
2598 struct mdss_dsi_ctrl_pdata *ctrl;
2599 struct dsi_panel_timing *modedb;
2600 struct device_node *timings_np;
2601 struct device_node *entry;
2602 int num_timings, rc;
2603 int i = 0, active_ndx = 0;
2604 bool default_timing = false;
2605
2606 ctrl = container_of(panel_data, struct mdss_dsi_ctrl_pdata, panel_data);
2607
2608 INIT_LIST_HEAD(&panel_data->timings_list);
2609
2610 timings_np = of_get_child_by_name(np, "qcom,mdss-dsi-display-timings");
2611 if (!timings_np) {
2612 struct dsi_panel_timing pt;
2613
2614 memset(&pt, 0, sizeof(struct dsi_panel_timing));
2615
2616 /*
2617 * display timings node is not available, fallback to reading
2618 * timings directly from root node instead
2619 */
2620 pr_debug("reading display-timings from panel node\n");
2621 rc = mdss_dsi_panel_timing_from_dt(np, &pt, panel_data);
2622 if (!rc) {
2623 mdss_dsi_panel_config_res_properties(np, &pt,
2624 panel_data, true);
2625 rc = mdss_dsi_panel_timing_switch(ctrl, &pt.timing);
2626 }
2627 return rc;
2628 }
2629
2630 num_timings = of_get_child_count(timings_np);
2631 if (num_timings == 0) {
2632 pr_err("no timings found within display-timings\n");
2633 rc = -EINVAL;
2634 goto exit;
2635 }
2636
2637 modedb = kcalloc(num_timings, sizeof(*modedb), GFP_KERNEL);
2638 if (!modedb) {
2639 rc = -ENOMEM;
2640 goto exit;
2641 }
2642
2643 for_each_child_of_node(timings_np, entry) {
2644 rc = mdss_dsi_panel_timing_from_dt(entry, (modedb + i),
2645 panel_data);
2646 if (rc) {
2647 kfree(modedb);
2648 goto exit;
2649 }
2650
2651 default_timing = of_property_read_bool(entry,
2652 "qcom,mdss-dsi-timing-default");
2653 if (default_timing)
2654 active_ndx = i;
2655
2656 mdss_dsi_panel_config_res_properties(entry, (modedb + i),
2657 panel_data, default_timing);
2658
2659 list_add(&modedb[i].timing.list,
2660 &panel_data->timings_list);
2661 i++;
2662 }
2663
2664 /* Configure default timing settings */
2665 rc = mdss_dsi_panel_timing_switch(ctrl, &modedb[active_ndx].timing);
2666 if (rc)
2667 pr_err("unable to configure default timing settings\n");
2668
2669exit:
2670 of_node_put(timings_np);
2671
2672 return rc;
2673}
2674
2675#ifdef TARGET_HW_MDSS_HDMI
2676static int mdss_panel_parse_dt_hdmi(struct device_node *np,
2677 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2678{
2679 int len = 0;
2680 const char *bridge_chip_name;
2681 struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
2682
2683 pinfo->is_dba_panel = of_property_read_bool(np,
2684 "qcom,dba-panel");
2685
2686 if (pinfo->is_dba_panel) {
2687 bridge_chip_name = of_get_property(np,
2688 "qcom,bridge-name", &len);
2689 if (!bridge_chip_name || len <= 0) {
2690 pr_err("%s:%d Unable to read qcom,bridge_name, data=%pK,len=%d\n",
2691 __func__, __LINE__, bridge_chip_name, len);
2692 return -EINVAL;
2693 }
2694 strlcpy(ctrl_pdata->bridge_name, bridge_chip_name,
2695 MSM_DBA_CHIP_NAME_MAX_LEN);
2696 }
2697 return 0;
2698}
2699#else
2700static int mdss_panel_parse_dt_hdmi(struct device_node *np,
2701 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2702{
2703 (void)(*np);
2704 (void)(*ctrl_pdata);
2705 return 0;
2706}
2707#endif
2708static int mdss_panel_parse_dt(struct device_node *np,
2709 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2710{
2711 u32 tmp;
2712 u8 lanes = 0;
2713 int rc = 0;
2714 const char *data;
2715 static const char *pdest;
2716 struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
2717
2718 if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data))
2719 pinfo->is_split_display = true;
2720
2721 rc = of_property_read_u32(np,
2722 "qcom,mdss-pan-physical-width-dimension", &tmp);
2723 pinfo->physical_width = (!rc ? tmp : 0);
2724 rc = of_property_read_u32(np,
2725 "qcom,mdss-pan-physical-height-dimension", &tmp);
2726 pinfo->physical_height = (!rc ? tmp : 0);
2727
2728 rc = of_property_read_u32(np, "qcom,mdss-dsi-bpp", &tmp);
2729 if (rc) {
2730 pr_err("%s:%d, bpp not specified\n", __func__, __LINE__);
2731 return -EINVAL;
2732 }
2733 pinfo->bpp = (!rc ? tmp : 24);
2734 pinfo->mipi.mode = DSI_VIDEO_MODE;
2735 data = of_get_property(np, "qcom,mdss-dsi-panel-type", NULL);
2736 if (data && !strcmp(data, "dsi_cmd_mode"))
2737 pinfo->mipi.mode = DSI_CMD_MODE;
2738 pinfo->mipi.boot_mode = pinfo->mipi.mode;
2739 tmp = 0;
2740 data = of_get_property(np, "qcom,mdss-dsi-pixel-packing", NULL);
2741 if (data && !strcmp(data, "loose"))
2742 pinfo->mipi.pixel_packing = 1;
2743 else
2744 pinfo->mipi.pixel_packing = 0;
2745 rc = mdss_panel_get_dst_fmt(pinfo->bpp,
2746 pinfo->mipi.mode, pinfo->mipi.pixel_packing,
2747 &(pinfo->mipi.dst_format));
2748 if (rc) {
2749 pr_debug("%s: problem determining dst format. Set Default\n",
2750 __func__);
2751 pinfo->mipi.dst_format =
2752 DSI_VIDEO_DST_FORMAT_RGB888;
2753 }
2754 pdest = of_get_property(np,
2755 "qcom,mdss-dsi-panel-destination", NULL);
2756
2757 rc = of_property_read_u32(np,
2758 "qcom,mdss-dsi-underflow-color", &tmp);
2759 pinfo->lcdc.underflow_clr = (!rc ? tmp : 0xff);
2760 rc = of_property_read_u32(np,
2761 "qcom,mdss-dsi-border-color", &tmp);
2762 pinfo->lcdc.border_clr = (!rc ? tmp : 0);
2763 data = of_get_property(np, "qcom,mdss-dsi-panel-orientation", NULL);
2764 if (data) {
2765 pr_debug("panel orientation is %s\n", data);
2766 if (!strcmp(data, "180"))
2767 pinfo->panel_orientation = MDP_ROT_180;
2768 else if (!strcmp(data, "hflip"))
2769 pinfo->panel_orientation = MDP_FLIP_LR;
2770 else if (!strcmp(data, "vflip"))
2771 pinfo->panel_orientation = MDP_FLIP_UD;
2772 }
2773
2774 rc = of_property_read_u32(np, "qcom,mdss-brightness-max-level", &tmp);
2775 pinfo->brightness_max = (!rc ? tmp : MDSS_MAX_BL_BRIGHTNESS);
2776 rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-min-level", &tmp);
2777 pinfo->bl_min = (!rc ? tmp : 0);
2778 rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-max-level", &tmp);
2779 pinfo->bl_max = (!rc ? tmp : 255);
2780 ctrl_pdata->bklt_max = pinfo->bl_max;
2781
2782 rc = of_property_read_u32(np, "qcom,mdss-dsi-interleave-mode", &tmp);
2783 pinfo->mipi.interleave_mode = (!rc ? tmp : 0);
2784
2785 pinfo->mipi.vsync_enable = of_property_read_bool(np,
2786 "qcom,mdss-dsi-te-check-enable");
2787
2788 if (pinfo->sim_panel_mode == SIM_SW_TE_MODE)
2789 pinfo->mipi.hw_vsync_mode = false;
2790 else
2791 pinfo->mipi.hw_vsync_mode = of_property_read_bool(np,
2792 "qcom,mdss-dsi-te-using-te-pin");
2793
2794 rc = of_property_read_u32(np,
2795 "qcom,mdss-dsi-h-sync-pulse", &tmp);
2796 pinfo->mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
2797
2798 pinfo->mipi.hfp_power_stop = of_property_read_bool(np,
2799 "qcom,mdss-dsi-hfp-power-mode");
2800 pinfo->mipi.hsa_power_stop = of_property_read_bool(np,
2801 "qcom,mdss-dsi-hsa-power-mode");
2802 pinfo->mipi.hbp_power_stop = of_property_read_bool(np,
2803 "qcom,mdss-dsi-hbp-power-mode");
2804 pinfo->mipi.last_line_interleave_en = of_property_read_bool(np,
2805 "qcom,mdss-dsi-last-line-interleave");
2806 pinfo->mipi.bllp_power_stop = of_property_read_bool(np,
2807 "qcom,mdss-dsi-bllp-power-mode");
2808 pinfo->mipi.eof_bllp_power_stop = of_property_read_bool(
2809 np, "qcom,mdss-dsi-bllp-eof-power-mode");
2810 pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
2811 data = of_get_property(np, "qcom,mdss-dsi-traffic-mode", NULL);
2812 if (data) {
2813 if (!strcmp(data, "non_burst_sync_event"))
2814 pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
2815 else if (!strcmp(data, "burst_mode"))
2816 pinfo->mipi.traffic_mode = DSI_BURST_MODE;
2817 }
2818 rc = of_property_read_u32(np,
2819 "qcom,mdss-dsi-te-dcs-command", &tmp);
2820 pinfo->mipi.insert_dcs_cmd =
2821 (!rc ? tmp : 1);
2822 rc = of_property_read_u32(np,
2823 "qcom,mdss-dsi-wr-mem-continue", &tmp);
2824 pinfo->mipi.wr_mem_continue =
2825 (!rc ? tmp : 0x3c);
2826 rc = of_property_read_u32(np,
2827 "qcom,mdss-dsi-wr-mem-start", &tmp);
2828 pinfo->mipi.wr_mem_start =
2829 (!rc ? tmp : 0x2c);
2830 rc = of_property_read_u32(np,
2831 "qcom,mdss-dsi-te-pin-select", &tmp);
2832 pinfo->mipi.te_sel =
2833 (!rc ? tmp : 1);
2834 rc = of_property_read_u32(np, "qcom,mdss-dsi-virtual-channel-id", &tmp);
2835 pinfo->mipi.vc = (!rc ? tmp : 0);
2836 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
2837 data = of_get_property(np, "qcom,mdss-dsi-color-order", NULL);
2838 if (data) {
2839 if (!strcmp(data, "rgb_swap_rbg"))
2840 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RBG;
2841 else if (!strcmp(data, "rgb_swap_bgr"))
2842 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_BGR;
2843 else if (!strcmp(data, "rgb_swap_brg"))
2844 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_BRG;
2845 else if (!strcmp(data, "rgb_swap_grb"))
2846 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_GRB;
2847 else if (!strcmp(data, "rgb_swap_gbr"))
2848 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_GBR;
2849 }
2850 pinfo->mipi.data_lane0 = of_property_read_bool(np,
2851 "qcom,mdss-dsi-lane-0-state");
2852 pinfo->mipi.data_lane1 = of_property_read_bool(np,
2853 "qcom,mdss-dsi-lane-1-state");
2854 pinfo->mipi.data_lane2 = of_property_read_bool(np,
2855 "qcom,mdss-dsi-lane-2-state");
2856 pinfo->mipi.data_lane3 = of_property_read_bool(np,
2857 "qcom,mdss-dsi-lane-3-state");
2858
2859 if (pinfo->mipi.data_lane0)
2860 lanes++;
2861 if (pinfo->mipi.data_lane1)
2862 lanes++;
2863 if (pinfo->mipi.data_lane2)
2864 lanes++;
2865 if (pinfo->mipi.data_lane3)
2866 lanes++;
2867 /*
2868 * needed to set default lanes during
2869 * resolution switch for bridge chips
2870 */
2871 pinfo->mipi.default_lanes = lanes;
2872
2873 rc = mdss_panel_parse_display_timings(np, &ctrl_pdata->panel_data);
2874 if (rc)
2875 return rc;
2876 rc = mdss_dsi_parse_hdr_settings(np, pinfo);
2877 if (rc)
2878 return rc;
2879
2880 pinfo->mipi.rx_eot_ignore = of_property_read_bool(np,
2881 "qcom,mdss-dsi-rx-eot-ignore");
2882 pinfo->mipi.tx_eot_append = of_property_read_bool(np,
2883 "qcom,mdss-dsi-tx-eot-append");
2884
2885 rc = of_property_read_u32(np, "qcom,mdss-dsi-stream", &tmp);
2886 pinfo->mipi.stream = (!rc ? tmp : 0);
2887
2888 data = of_get_property(np, "qcom,mdss-dsi-panel-mode-gpio-state", NULL);
2889 if (data) {
2890 if (!strcmp(data, "high"))
2891 pinfo->mode_gpio_state = MODE_GPIO_HIGH;
2892 else if (!strcmp(data, "low"))
2893 pinfo->mode_gpio_state = MODE_GPIO_LOW;
2894 } else {
2895 pinfo->mode_gpio_state = MODE_GPIO_NOT_VALID;
2896 }
2897
2898 rc = of_property_read_u32(np, "qcom,mdss-mdp-transfer-time-us", &tmp);
2899 pinfo->mdp_transfer_time_us = (!rc ? tmp : DEFAULT_MDP_TRANSFER_TIME);
2900
Ingrid Gallardoc9053a42016-09-22 21:20:08 -07002901 mdss_dsi_parse_mdp_kickoff_threshold(np, pinfo);
2902
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302903 pinfo->mipi.lp11_init = of_property_read_bool(np,
2904 "qcom,mdss-dsi-lp11-init");
2905 rc = of_property_read_u32(np, "qcom,mdss-dsi-init-delay-us", &tmp);
2906 pinfo->mipi.init_delay = (!rc ? tmp : 0);
2907
2908 rc = of_property_read_u32(np, "qcom,mdss-dsi-post-init-delay", &tmp);
2909 pinfo->mipi.post_init_delay = (!rc ? tmp : 0);
2910
2911 mdss_dsi_parse_trigger(np, &(pinfo->mipi.mdp_trigger),
2912 "qcom,mdss-dsi-mdp-trigger");
2913
2914 mdss_dsi_parse_trigger(np, &(pinfo->mipi.dma_trigger),
2915 "qcom,mdss-dsi-dma-trigger");
2916
2917 mdss_dsi_parse_reset_seq(np, pinfo->rst_seq, &(pinfo->rst_seq_len),
2918 "qcom,mdss-dsi-reset-sequence");
2919
2920 mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->off_cmds,
2921 "qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state");
2922
2923 mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->idle_on_cmds,
2924 "qcom,mdss-dsi-idle-on-command",
2925 "qcom,mdss-dsi-idle-on-command-state");
2926
2927 mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->idle_off_cmds,
2928 "qcom,mdss-dsi-idle-off-command",
2929 "qcom,mdss-dsi-idle-off-command-state");
2930
2931 rc = of_property_read_u32(np, "qcom,mdss-dsi-idle-fps", &tmp);
2932 pinfo->mipi.frame_rate_idle = (!rc ? tmp : 60);
2933
2934 rc = of_property_read_u32(np, "qcom,adjust-timer-wakeup-ms", &tmp);
2935 pinfo->adjust_timer_delay_ms = (!rc ? tmp : 0);
2936
2937 pinfo->mipi.force_clk_lane_hs = of_property_read_bool(np,
2938 "qcom,mdss-dsi-force-clock-lane-hs");
2939
2940 rc = mdss_dsi_parse_panel_features(np, ctrl_pdata);
2941 if (rc) {
2942 pr_err("%s: failed to parse panel features\n", __func__);
2943 goto error;
2944 }
2945
2946 mdss_dsi_parse_panel_horizintal_line_idle(np, ctrl_pdata);
2947
2948 mdss_dsi_parse_dfps_config(np, ctrl_pdata);
2949
2950 rc = mdss_panel_parse_dt_hdmi(np, ctrl_pdata);
2951 if (rc)
2952 goto error;
2953
2954 return 0;
2955
2956error:
2957 return -EINVAL;
2958}
2959
2960int mdss_dsi_panel_init(struct device_node *node,
2961 struct mdss_dsi_ctrl_pdata *ctrl_pdata,
2962 int ndx)
2963{
2964 int rc = 0;
2965 static const char *panel_name;
2966 struct mdss_panel_info *pinfo;
2967
2968 if (!node || !ctrl_pdata) {
2969 pr_err("%s: Invalid arguments\n", __func__);
2970 return -ENODEV;
2971 }
2972
2973 pinfo = &ctrl_pdata->panel_data.panel_info;
2974
2975 pr_debug("%s:%d\n", __func__, __LINE__);
2976 pinfo->panel_name[0] = '\0';
2977 panel_name = of_get_property(node, "qcom,mdss-dsi-panel-name", NULL);
2978 if (!panel_name) {
2979 pr_info("%s:%d, Panel name not specified\n",
2980 __func__, __LINE__);
2981 } else {
2982 pr_info("%s: Panel Name = %s\n", __func__, panel_name);
2983 strlcpy(&pinfo->panel_name[0], panel_name, MDSS_MAX_PANEL_LEN);
2984 }
2985 rc = mdss_panel_parse_dt(node, ctrl_pdata);
2986 if (rc) {
2987 pr_err("%s:%d panel dt parse failed\n", __func__, __LINE__);
2988 return rc;
2989 }
2990
2991 pinfo->dynamic_switch_pending = false;
2992 pinfo->is_lpm_mode = false;
2993 pinfo->esd_rdy = false;
2994 pinfo->persist_mode = false;
2995
2996 ctrl_pdata->on = mdss_dsi_panel_on;
2997 ctrl_pdata->post_panel_on = mdss_dsi_post_panel_on;
2998 ctrl_pdata->off = mdss_dsi_panel_off;
2999 ctrl_pdata->low_power_config = mdss_dsi_panel_low_power_config;
3000 ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
3001 ctrl_pdata->panel_data.apply_display_setting =
3002 mdss_dsi_panel_apply_display_setting;
3003 ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode;
3004 ctrl_pdata->panel_data.get_idle = mdss_dsi_panel_get_idle_mode;
3005 return 0;
3006}