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