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