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