blob: b94280ddcd153d4c1e94de46620febeefb3e9d29 [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
1067static void mdss_dsi_parse_trigger(struct device_node *np, char *trigger,
1068 char *trigger_key)
1069{
1070 const char *data;
1071
1072 *trigger = DSI_CMD_TRIGGER_SW;
1073 data = of_get_property(np, trigger_key, NULL);
1074 if (data) {
1075 if (!strcmp(data, "none"))
1076 *trigger = DSI_CMD_TRIGGER_NONE;
1077 else if (!strcmp(data, "trigger_te"))
1078 *trigger = DSI_CMD_TRIGGER_TE;
1079 else if (!strcmp(data, "trigger_sw_seof"))
1080 *trigger = DSI_CMD_TRIGGER_SW_SEOF;
1081 else if (!strcmp(data, "trigger_sw_te"))
1082 *trigger = DSI_CMD_TRIGGER_SW_TE;
1083 }
1084}
1085
1086
1087static int mdss_dsi_parse_dcs_cmds(struct device_node *np,
1088 struct dsi_panel_cmds *pcmds, char *cmd_key, char *link_key)
1089{
1090 const char *data;
1091 int blen = 0, len;
1092 char *buf, *bp;
1093 struct dsi_ctrl_hdr *dchdr;
1094 int i, cnt;
1095
1096 data = of_get_property(np, cmd_key, &blen);
1097 if (!data) {
1098 pr_err("%s: failed, key=%s\n", __func__, cmd_key);
1099 return -ENOMEM;
1100 }
1101
1102 buf = kcalloc(blen, sizeof(char), GFP_KERNEL);
1103 if (!buf)
1104 return -ENOMEM;
1105
1106 memcpy(buf, data, blen);
1107
1108 /* scan dcs commands */
1109 bp = buf;
1110 len = blen;
1111 cnt = 0;
1112 while (len >= sizeof(*dchdr)) {
1113 dchdr = (struct dsi_ctrl_hdr *)bp;
1114 dchdr->dlen = ntohs(dchdr->dlen);
1115 if (dchdr->dlen > len) {
1116 pr_err("%s: dtsi cmd=%x error, len=%d",
1117 __func__, dchdr->dtype, dchdr->dlen);
1118 goto exit_free;
1119 }
1120 bp += sizeof(*dchdr);
1121 len -= sizeof(*dchdr);
1122 bp += dchdr->dlen;
1123 len -= dchdr->dlen;
1124 cnt++;
1125 }
1126
1127 if (len != 0) {
1128 pr_err("%s: dcs_cmd=%x len=%d error!",
1129 __func__, buf[0], blen);
1130 goto exit_free;
1131 }
1132
1133 pcmds->cmds = kcalloc(cnt, sizeof(struct dsi_cmd_desc),
1134 GFP_KERNEL);
1135 if (!pcmds->cmds)
1136 goto exit_free;
1137
1138 pcmds->cmd_cnt = cnt;
1139 pcmds->buf = buf;
1140 pcmds->blen = blen;
1141
1142 bp = buf;
1143 len = blen;
1144 for (i = 0; i < cnt; i++) {
1145 dchdr = (struct dsi_ctrl_hdr *)bp;
1146 len -= sizeof(*dchdr);
1147 bp += sizeof(*dchdr);
1148 pcmds->cmds[i].dchdr = *dchdr;
1149 pcmds->cmds[i].payload = bp;
1150 bp += dchdr->dlen;
1151 len -= dchdr->dlen;
1152 }
1153
1154 /*Set default link state to LP Mode*/
1155 pcmds->link_state = DSI_LP_MODE;
1156
1157 if (link_key) {
1158 data = of_get_property(np, link_key, NULL);
1159 if (data && !strcmp(data, "dsi_hs_mode"))
1160 pcmds->link_state = DSI_HS_MODE;
1161 else
1162 pcmds->link_state = DSI_LP_MODE;
1163 }
1164
1165 pr_debug("%s: dcs_cmd=%x len=%d, cmd_cnt=%d link_state=%d\n", __func__,
1166 pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt, pcmds->link_state);
1167
1168 return 0;
1169
1170exit_free:
1171 kfree(buf);
1172 return -ENOMEM;
1173}
1174
1175
1176int mdss_panel_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing,
1177 char *dst_format)
1178{
1179 int rc = 0;
1180
1181 switch (bpp) {
1182 case 3:
1183 *dst_format = DSI_CMD_DST_FORMAT_RGB111;
1184 break;
1185 case 8:
1186 *dst_format = DSI_CMD_DST_FORMAT_RGB332;
1187 break;
1188 case 12:
1189 *dst_format = DSI_CMD_DST_FORMAT_RGB444;
1190 break;
1191 case 16:
1192 switch (mipi_mode) {
1193 case DSI_VIDEO_MODE:
1194 *dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
1195 break;
1196 case DSI_CMD_MODE:
1197 *dst_format = DSI_CMD_DST_FORMAT_RGB565;
1198 break;
1199 default:
1200 *dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
1201 break;
1202 }
1203 break;
1204 case 18:
1205 switch (mipi_mode) {
1206 case DSI_VIDEO_MODE:
1207 if (pixel_packing == 0)
1208 *dst_format = DSI_VIDEO_DST_FORMAT_RGB666;
1209 else
1210 *dst_format = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE;
1211 break;
1212 case DSI_CMD_MODE:
1213 *dst_format = DSI_CMD_DST_FORMAT_RGB666;
1214 break;
1215 default:
1216 if (pixel_packing == 0)
1217 *dst_format = DSI_VIDEO_DST_FORMAT_RGB666;
1218 else
1219 *dst_format = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE;
1220 break;
1221 }
1222 break;
1223 case 24:
1224 switch (mipi_mode) {
1225 case DSI_VIDEO_MODE:
1226 *dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
1227 break;
1228 case DSI_CMD_MODE:
1229 *dst_format = DSI_CMD_DST_FORMAT_RGB888;
1230 break;
1231 default:
1232 *dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
1233 break;
1234 }
1235 break;
1236 default:
1237 rc = -EINVAL;
1238 break;
1239 }
1240 return rc;
1241}
1242
1243static int mdss_dsi_parse_fbc_params(struct device_node *np,
1244 struct mdss_panel_timing *timing)
1245{
1246 int rc, fbc_enabled = 0;
1247 u32 tmp;
1248 struct fbc_panel_info *fbc = &timing->fbc;
1249
1250 fbc_enabled = of_property_read_bool(np, "qcom,mdss-dsi-fbc-enable");
1251 if (fbc_enabled) {
1252 pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__);
1253 fbc->enabled = 1;
1254 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bpp", &tmp);
1255 fbc->target_bpp = (!rc ? tmp : 24);
1256 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-packing",
1257 &tmp);
1258 fbc->comp_mode = (!rc ? tmp : 0);
1259 fbc->qerr_enable = of_property_read_bool(np,
1260 "qcom,mdss-dsi-fbc-quant-error");
1261 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bias", &tmp);
1262 fbc->cd_bias = (!rc ? tmp : 0);
1263 fbc->pat_enable = of_property_read_bool(np,
1264 "qcom,mdss-dsi-fbc-pat-mode");
1265 fbc->vlc_enable = of_property_read_bool(np,
1266 "qcom,mdss-dsi-fbc-vlc-mode");
1267 fbc->bflc_enable = of_property_read_bool(np,
1268 "qcom,mdss-dsi-fbc-bflc-mode");
1269 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-h-line-budget",
1270 &tmp);
1271 fbc->line_x_budget = (!rc ? tmp : 0);
1272 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-budget-ctrl",
1273 &tmp);
1274 fbc->block_x_budget = (!rc ? tmp : 0);
1275 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-block-budget",
1276 &tmp);
1277 fbc->block_budget = (!rc ? tmp : 0);
1278 rc = of_property_read_u32(np,
1279 "qcom,mdss-dsi-fbc-lossless-threshold", &tmp);
1280 fbc->lossless_mode_thd = (!rc ? tmp : 0);
1281 rc = of_property_read_u32(np,
1282 "qcom,mdss-dsi-fbc-lossy-threshold", &tmp);
1283 fbc->lossy_mode_thd = (!rc ? tmp : 0);
1284 rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-rgb-threshold",
1285 &tmp);
1286 fbc->lossy_rgb_thd = (!rc ? tmp : 0);
1287 rc = of_property_read_u32(np,
1288 "qcom,mdss-dsi-fbc-lossy-mode-idx", &tmp);
1289 fbc->lossy_mode_idx = (!rc ? tmp : 0);
1290 rc = of_property_read_u32(np,
1291 "qcom,mdss-dsi-fbc-slice-height", &tmp);
1292 fbc->slice_height = (!rc ? tmp : 0);
1293 fbc->pred_mode = of_property_read_bool(np,
1294 "qcom,mdss-dsi-fbc-2d-pred-mode");
1295 fbc->enc_mode = of_property_read_bool(np,
1296 "qcom,mdss-dsi-fbc-ver2-mode");
1297 rc = of_property_read_u32(np,
1298 "qcom,mdss-dsi-fbc-max-pred-err", &tmp);
1299 fbc->max_pred_err = (!rc ? tmp : 0);
1300
1301 timing->compression_mode = COMPRESSION_FBC;
1302 } else {
1303 pr_debug("%s:%d Panel does not support FBC.\n",
1304 __func__, __LINE__);
1305 fbc->enabled = 0;
1306 fbc->target_bpp = 24;
1307 }
1308 return 0;
1309}
1310
1311void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl,
1312 struct mdss_panel_info *pinfo)
1313{
1314 struct dsi_panel_cmds pcmds;
1315 struct dsi_cmd_desc cmd;
1316
1317 if (!pinfo || (pinfo->compression_mode != COMPRESSION_DSC))
1318 return;
1319
1320 memset(&pcmds, 0, sizeof(pcmds));
1321 memset(&cmd, 0, sizeof(cmd));
1322
1323 cmd.dchdr.dlen = mdss_panel_dsc_prepare_pps_buf(&pinfo->dsc,
1324 ctrl->pps_buf, 0);
1325 cmd.dchdr.dtype = DTYPE_PPS;
1326 cmd.dchdr.last = 1;
1327 cmd.dchdr.wait = 10;
1328 cmd.dchdr.vc = 0;
1329 cmd.dchdr.ack = 0;
1330 cmd.payload = ctrl->pps_buf;
1331
1332 pcmds.cmd_cnt = 1;
1333 pcmds.cmds = &cmd;
1334 pcmds.link_state = DSI_LP_MODE;
1335
1336 mdss_dsi_panel_cmds_send(ctrl, &pcmds, CMD_REQ_COMMIT);
1337}
1338
1339static int mdss_dsi_parse_hdr_settings(struct device_node *np,
1340 struct mdss_panel_info *pinfo)
1341{
1342 int rc = 0;
1343 struct mdss_panel_hdr_properties *hdr_prop;
1344
1345 if (!np) {
1346 pr_err("%s: device node pointer is NULL\n", __func__);
1347 return -EINVAL;
1348 }
1349
1350 if (!pinfo) {
1351 pr_err("%s: panel info is NULL\n", __func__);
1352 return -EINVAL;
1353 }
1354
1355 hdr_prop = &pinfo->hdr_properties;
1356 hdr_prop->hdr_enabled = of_property_read_bool(np,
1357 "qcom,mdss-dsi-panel-hdr-enabled");
1358
1359 if (hdr_prop->hdr_enabled) {
1360 rc = of_property_read_u32_array(np,
1361 "qcom,mdss-dsi-panel-hdr-color-primaries",
1362 hdr_prop->display_primaries,
1363 DISPLAY_PRIMARIES_COUNT);
1364 if (rc) {
1365 pr_info("%s:%d, Unable to read color primaries,rc:%u",
1366 __func__, __LINE__,
1367 hdr_prop->hdr_enabled = false);
1368 }
1369
1370 rc = of_property_read_u32(np,
1371 "qcom,mdss-dsi-panel-peak-brightness",
1372 &(hdr_prop->peak_brightness));
1373 if (rc) {
1374 pr_info("%s:%d, Unable to read hdr brightness, rc:%u",
1375 __func__, __LINE__, rc);
1376 hdr_prop->hdr_enabled = false;
1377 }
1378
1379 rc = of_property_read_u32(np,
1380 "qcom,mdss-dsi-panel-blackness-level",
1381 &(hdr_prop->blackness_level));
1382 if (rc) {
1383 pr_info("%s:%d, Unable to read hdr brightness, rc:%u",
1384 __func__, __LINE__, rc);
1385 hdr_prop->hdr_enabled = false;
1386 }
1387 }
1388 return 0;
1389}
1390
1391static int mdss_dsi_parse_dsc_version(struct device_node *np,
1392 struct mdss_panel_timing *timing)
1393{
1394 u32 data;
1395 int rc = 0;
1396 struct dsc_desc *dsc = &timing->dsc;
1397
1398 rc = of_property_read_u32(np, "qcom,mdss-dsc-version", &data);
1399 if (rc) {
1400 dsc->version = 0x11;
1401 rc = 0;
1402 } else {
1403 dsc->version = data & 0xff;
1404 /* only support DSC 1.1 rev */
1405 if (dsc->version != 0x11) {
1406 pr_err("%s: DSC version:%d not supported\n", __func__,
1407 dsc->version);
1408 rc = -EINVAL;
1409 goto end;
1410 }
1411 }
1412
1413 rc = of_property_read_u32(np, "qcom,mdss-dsc-scr-version", &data);
1414 if (rc) {
1415 dsc->scr_rev = 0x0;
1416 rc = 0;
1417 } else {
1418 dsc->scr_rev = data & 0xff;
1419 /* only one scr rev supported */
1420 if (dsc->scr_rev > 0x1) {
1421 pr_err("%s: DSC scr version:%d not supported\n",
1422 __func__, dsc->scr_rev);
1423 rc = -EINVAL;
1424 goto end;
1425 }
1426 }
1427
1428end:
1429 return rc;
1430}
1431
1432static int mdss_dsi_parse_dsc_params(struct device_node *np,
1433 struct mdss_panel_timing *timing, bool is_split_display)
1434{
1435 u32 data, intf_width;
1436 int rc = 0;
1437 struct dsc_desc *dsc = &timing->dsc;
1438
1439 if (!np) {
1440 pr_err("%s: device node pointer is NULL\n", __func__);
1441 return -EINVAL;
1442 }
1443
1444 rc = of_property_read_u32(np, "qcom,mdss-dsc-encoders", &data);
1445 if (rc) {
1446 if (!of_find_property(np, "qcom,mdss-dsc-encoders", NULL)) {
1447 /* property is not defined, default to 1 */
1448 data = 1;
1449 } else {
1450 pr_err("%s: Error parsing qcom,mdss-dsc-encoders\n",
1451 __func__);
1452 goto end;
1453 }
1454 }
1455
1456 timing->dsc_enc_total = data;
1457
1458 if (is_split_display && (timing->dsc_enc_total > 1)) {
1459 pr_err("%s: Error: for split displays, more than 1 dsc encoder per panel is not allowed.\n",
1460 __func__);
1461 goto end;
1462 }
1463
1464 rc = of_property_read_u32(np, "qcom,mdss-dsc-slice-height", &data);
1465 if (rc)
1466 goto end;
1467 dsc->slice_height = data;
1468
1469 rc = of_property_read_u32(np, "qcom,mdss-dsc-slice-width", &data);
1470 if (rc)
1471 goto end;
1472 dsc->slice_width = data;
1473 intf_width = timing->xres;
1474
1475 if (intf_width % dsc->slice_width) {
1476 pr_err("%s: Error: multiple of slice-width:%d should match panel-width:%d\n",
1477 __func__, dsc->slice_width, intf_width);
1478 goto end;
1479 }
1480
1481 data = intf_width / dsc->slice_width;
1482 if (((timing->dsc_enc_total > 1) && ((data != 2) && (data != 4))) ||
1483 ((timing->dsc_enc_total == 1) && (data > 2))) {
1484 pr_err("%s: Error: max 2 slice per encoder. slice-width:%d should match panel-width:%d dsc_enc_total:%d\n",
1485 __func__, dsc->slice_width,
1486 intf_width, timing->dsc_enc_total);
1487 goto end;
1488 }
1489
1490 rc = of_property_read_u32(np, "qcom,mdss-dsc-slice-per-pkt", &data);
1491 if (rc)
1492 goto end;
1493 dsc->slice_per_pkt = data;
1494
1495 /*
1496 * slice_per_pkt can be either 1 or all slices_per_intf
1497 */
1498 if ((dsc->slice_per_pkt > 1) && (dsc->slice_per_pkt !=
1499 DIV_ROUND_UP(intf_width, dsc->slice_width))) {
1500 pr_err("Error: slice_per_pkt can be either 1 or all slices_per_intf\n");
1501 pr_err("%s: slice_per_pkt=%d, slice_width=%d intf_width=%d\n",
1502 __func__,
1503 dsc->slice_per_pkt, dsc->slice_width, intf_width);
1504 rc = -EINVAL;
1505 goto end;
1506 }
1507
1508 pr_debug("%s: num_enc:%d :slice h=%d w=%d s_pkt=%d\n", __func__,
1509 timing->dsc_enc_total, dsc->slice_height,
1510 dsc->slice_width, dsc->slice_per_pkt);
1511
1512 rc = of_property_read_u32(np, "qcom,mdss-dsc-bit-per-component", &data);
1513 if (rc)
1514 goto end;
1515 dsc->bpc = data;
1516
1517 rc = of_property_read_u32(np, "qcom,mdss-dsc-bit-per-pixel", &data);
1518 if (rc)
1519 goto end;
1520 dsc->bpp = data;
1521
1522 pr_debug("%s: bpc=%d bpp=%d\n", __func__,
1523 dsc->bpc, dsc->bpp);
1524
1525 dsc->block_pred_enable = of_property_read_bool(np,
1526 "qcom,mdss-dsc-block-prediction-enable");
1527
1528 dsc->enable_422 = 0;
1529 dsc->convert_rgb = 1;
1530 dsc->vbr_enable = 0;
1531
1532 dsc->config_by_manufacture_cmd = of_property_read_bool(np,
1533 "qcom,mdss-dsc-config-by-manufacture-cmd");
1534
1535 mdss_panel_dsc_parameters_calc(&timing->dsc);
1536 mdss_panel_dsc_pclk_param_calc(&timing->dsc, intf_width);
1537
1538 timing->dsc.full_frame_slices =
1539 DIV_ROUND_UP(intf_width, timing->dsc.slice_width);
1540
1541 timing->compression_mode = COMPRESSION_DSC;
1542
1543end:
1544 return rc;
1545}
1546
1547static struct device_node *mdss_dsi_panel_get_dsc_cfg_np(
1548 struct device_node *np, struct mdss_panel_data *panel_data,
1549 bool default_timing)
1550{
1551 struct device_node *dsc_cfg_np = NULL;
1552
1553
1554 /* Read the dsc config node specified by command line */
1555 if (default_timing) {
1556 dsc_cfg_np = of_get_child_by_name(np,
1557 panel_data->dsc_cfg_np_name);
1558 if (!dsc_cfg_np)
1559 pr_warn_once("%s: cannot find dsc config node:%s\n",
1560 __func__, panel_data->dsc_cfg_np_name);
1561 }
1562
1563 /*
1564 * Fall back to default from DT as nothing is specified
1565 * in command line.
1566 */
1567 if (!dsc_cfg_np && of_find_property(np, "qcom,config-select", NULL)) {
1568 dsc_cfg_np = of_parse_phandle(np, "qcom,config-select", 0);
1569 if (!dsc_cfg_np)
1570 pr_warn_once("%s:err parsing qcom,config-select\n",
1571 __func__);
1572 }
1573
1574 return dsc_cfg_np;
1575}
1576
1577static int mdss_dsi_parse_topology_config(struct device_node *np,
1578 struct dsi_panel_timing *pt, struct mdss_panel_data *panel_data,
1579 bool default_timing)
1580{
1581 int rc = 0;
1582 bool is_split_display = panel_data->panel_info.is_split_display;
1583 const char *data;
1584 struct mdss_panel_timing *timing = &pt->timing;
1585 struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
1586 struct mdss_panel_info *pinfo;
1587 struct device_node *cfg_np = NULL;
1588
1589 ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata,
1590 panel_data);
1591 pinfo = &ctrl_pdata->panel_data.panel_info;
1592
1593 cfg_np = mdss_dsi_panel_get_dsc_cfg_np(np,
1594 &ctrl_pdata->panel_data, default_timing);
1595
1596 if (cfg_np) {
1597 if (!of_property_read_u32_array(cfg_np, "qcom,lm-split",
1598 timing->lm_widths, 2)) {
1599 if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)
1600 && (timing->lm_widths[1] != 0)) {
1601 pr_err("%s: lm-split not allowed with split display\n",
1602 __func__);
1603 rc = -EINVAL;
1604 goto end;
1605 }
1606 }
Naseer Ahmed143b89b2016-12-22 16:19:10 -05001607
1608 if (!of_property_read_string(cfg_np, "qcom,split-mode",
1609 &data) && !strcmp(data, "pingpong-split"))
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301610 pinfo->use_pingpong_split = true;
1611
1612 if (((timing->lm_widths[0]) || (timing->lm_widths[1])) &&
1613 pinfo->use_pingpong_split) {
1614 pr_err("%s: pingpong_split cannot be used when lm-split[%d,%d] is specified\n",
1615 __func__,
1616 timing->lm_widths[0], timing->lm_widths[1]);
1617 return -EINVAL;
1618 }
1619
1620 pr_info("%s: cfg_node name %s lm_split:%dx%d pp_split:%s\n",
1621 __func__, cfg_np->name,
1622 timing->lm_widths[0], timing->lm_widths[1],
1623 pinfo->use_pingpong_split ? "yes" : "no");
1624 }
1625
1626 if (!pinfo->use_pingpong_split &&
1627 (timing->lm_widths[0] == 0) && (timing->lm_widths[1] == 0))
1628 timing->lm_widths[0] = pt->timing.xres;
1629
1630 data = of_get_property(np, "qcom,compression-mode", NULL);
1631 if (data) {
1632 if (cfg_np && !strcmp(data, "dsc")) {
1633 rc = mdss_dsi_parse_dsc_version(np, &pt->timing);
1634 if (rc)
1635 goto end;
1636
1637 pinfo->send_pps_before_switch =
1638 of_property_read_bool(np,
1639 "qcom,mdss-dsi-send-pps-before-switch");
1640
1641 rc = mdss_dsi_parse_dsc_params(cfg_np, &pt->timing,
1642 is_split_display);
1643 } else if (!strcmp(data, "fbc")) {
1644 rc = mdss_dsi_parse_fbc_params(np, &pt->timing);
1645 }
1646 }
1647
1648end:
1649 of_node_put(cfg_np);
1650 return rc;
1651}
1652
1653static void mdss_panel_parse_te_params(struct device_node *np,
1654 struct mdss_panel_timing *timing)
1655{
1656 struct mdss_mdp_pp_tear_check *te = &timing->te;
1657 u32 tmp;
1658 int rc = 0;
1659 /*
1660 * TE default: dsi byte clock calculated base on 70 fps;
1661 * around 14 ms to complete a kickoff cycle if te disabled;
1662 * vclk_line base on 60 fps; write is faster than read;
1663 * init == start == rdptr;
1664 */
1665 te->tear_check_en =
1666 !of_property_read_bool(np, "qcom,mdss-tear-check-disable");
1667 rc = of_property_read_u32
1668 (np, "qcom,mdss-tear-check-sync-cfg-height", &tmp);
1669 te->sync_cfg_height = (!rc ? tmp : 0xfff0);
1670 rc = of_property_read_u32
1671 (np, "qcom,mdss-tear-check-sync-init-val", &tmp);
1672 te->vsync_init_val = (!rc ? tmp : timing->yres);
1673 rc = of_property_read_u32
1674 (np, "qcom,mdss-tear-check-sync-threshold-start", &tmp);
1675 te->sync_threshold_start = (!rc ? tmp : 4);
1676 rc = of_property_read_u32
1677 (np, "qcom,mdss-tear-check-sync-threshold-continue", &tmp);
1678 te->sync_threshold_continue = (!rc ? tmp : 4);
1679 rc = of_property_read_u32(np, "qcom,mdss-tear-check-frame-rate", &tmp);
1680 te->refx100 = (!rc ? tmp : 6000);
1681 rc = of_property_read_u32
1682 (np, "qcom,mdss-tear-check-start-pos", &tmp);
1683 te->start_pos = (!rc ? tmp : timing->yres);
1684 rc = of_property_read_u32
1685 (np, "qcom,mdss-tear-check-rd-ptr-trigger-intr", &tmp);
1686 te->rd_ptr_irq = (!rc ? tmp : timing->yres + 1);
1687 te->wr_ptr_irq = 0;
1688}
1689
1690
1691static int mdss_dsi_parse_reset_seq(struct device_node *np,
1692 u32 rst_seq[MDSS_DSI_RST_SEQ_LEN], u32 *rst_len,
1693 const char *name)
1694{
1695 int num = 0, i;
1696 int rc;
1697 struct property *data;
1698 u32 tmp[MDSS_DSI_RST_SEQ_LEN];
1699 *rst_len = 0;
1700 data = of_find_property(np, name, &num);
1701 num /= sizeof(u32);
1702 if (!data || !num || num > MDSS_DSI_RST_SEQ_LEN || num % 2) {
1703 pr_debug("%s:%d, error reading %s, length found = %d\n",
1704 __func__, __LINE__, name, num);
1705 } else {
1706 rc = of_property_read_u32_array(np, name, tmp, num);
1707 if (rc)
1708 pr_debug("%s:%d, error reading %s, rc = %d\n",
1709 __func__, __LINE__, name, rc);
1710 else {
1711 for (i = 0; i < num; ++i)
1712 rst_seq[i] = tmp[i];
1713 *rst_len = num;
1714 }
1715 }
1716 return 0;
1717}
1718
1719static bool mdss_dsi_cmp_panel_reg_v2(struct mdss_dsi_ctrl_pdata *ctrl)
1720{
Ingrid Gallardo53795e72016-10-12 18:38:48 -07001721 int i, j = 0;
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301722 int len = 0, *lenp;
1723 int group = 0;
1724
1725 lenp = ctrl->status_valid_params ?: ctrl->status_cmds_rlen;
1726
1727 for (i = 0; i < ctrl->status_cmds.cmd_cnt; i++)
1728 len += lenp[i];
1729
Ingrid Gallardo53795e72016-10-12 18:38:48 -07001730 for (i = 0; i < len; i++) {
1731 pr_debug("[%i] return:0x%x status:0x%x\n",
1732 i, (unsigned int)ctrl->return_buf[i],
1733 (unsigned int)ctrl->status_value[j + i]);
1734 MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i],
1735 ctrl->status_value[j + i]);
1736 j += len;
1737 }
1738
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301739 for (j = 0; j < ctrl->groups; ++j) {
1740 for (i = 0; i < len; ++i) {
1741 if (ctrl->return_buf[i] !=
1742 ctrl->status_value[group + i])
1743 break;
1744 }
1745
1746 if (i == len)
1747 return true;
1748 group += len;
1749 }
1750
1751 return false;
1752}
1753
1754static int mdss_dsi_gen_read_status(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
1755{
1756 if (!mdss_dsi_cmp_panel_reg_v2(ctrl_pdata)) {
1757 pr_err("%s: Read back value from panel is incorrect\n",
1758 __func__);
1759 return -EINVAL;
1760 } else {
1761 return 1;
1762 }
1763}
1764
1765static int mdss_dsi_nt35596_read_status(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
1766{
1767 if (!mdss_dsi_cmp_panel_reg(ctrl_pdata->status_buf,
1768 ctrl_pdata->status_value, 0)) {
1769 ctrl_pdata->status_error_count = 0;
1770 pr_err("%s: Read back value from panel is incorrect\n",
1771 __func__);
1772 return -EINVAL;
1773 }
1774 {
1775 if (!mdss_dsi_cmp_panel_reg(ctrl_pdata->status_buf,
1776 ctrl_pdata->status_value, 3)) {
1777 ctrl_pdata->status_error_count = 0;
1778 } else {
1779 if (mdss_dsi_cmp_panel_reg(ctrl_pdata->status_buf,
1780 ctrl_pdata->status_value, 4) ||
1781 mdss_dsi_cmp_panel_reg(ctrl_pdata->status_buf,
1782 ctrl_pdata->status_value, 5))
1783 ctrl_pdata->status_error_count = 0;
1784 else
1785 ctrl_pdata->status_error_count++;
1786 if (ctrl_pdata->status_error_count >=
1787 ctrl_pdata->max_status_error_count) {
1788 ctrl_pdata->status_error_count = 0;
1789 pr_err("%s: Read value bad. Error_cnt = %i\n",
1790 __func__,
1791 ctrl_pdata->status_error_count);
1792 return -EINVAL;
1793 }
1794 }
1795 return 1;
1796 }
1797}
1798
1799static void mdss_dsi_parse_roi_alignment(struct device_node *np,
1800 struct dsi_panel_timing *pt)
1801{
1802 int len = 0;
1803 u32 value[6];
1804 struct property *data;
1805 struct mdss_panel_timing *timing = &pt->timing;
1806
1807 data = of_find_property(np, "qcom,panel-roi-alignment", &len);
1808 len /= sizeof(u32);
1809 if (!data || (len != 6)) {
1810 pr_debug("%s: Panel roi alignment not found", __func__);
1811 } else {
1812 int rc = of_property_read_u32_array(np,
1813 "qcom,panel-roi-alignment", value, len);
1814 if (rc)
1815 pr_debug("%s: Error reading panel roi alignment values",
1816 __func__);
1817 else {
1818 timing->roi_alignment.xstart_pix_align = value[0];
1819 timing->roi_alignment.ystart_pix_align = value[1];
1820 timing->roi_alignment.width_pix_align = value[2];
1821 timing->roi_alignment.height_pix_align = value[3];
1822 timing->roi_alignment.min_width = value[4];
1823 timing->roi_alignment.min_height = value[5];
1824 }
1825
1826 pr_debug("%s: ROI alignment: [%d, %d, %d, %d, %d, %d]",
1827 __func__, timing->roi_alignment.xstart_pix_align,
1828 timing->roi_alignment.width_pix_align,
1829 timing->roi_alignment.ystart_pix_align,
1830 timing->roi_alignment.height_pix_align,
1831 timing->roi_alignment.min_width,
1832 timing->roi_alignment.min_height);
1833 }
1834}
1835
1836static void mdss_dsi_parse_dms_config(struct device_node *np,
1837 struct mdss_dsi_ctrl_pdata *ctrl)
1838{
1839 struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
1840 const char *data;
1841 bool dms_enabled;
1842
1843 dms_enabled = of_property_read_bool(np,
1844 "qcom,dynamic-mode-switch-enabled");
1845
1846 if (!dms_enabled) {
1847 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_DISABLED;
1848 goto exit;
1849 }
1850
1851 /* default mode is suspend_resume */
1852 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_SUSPEND_RESUME;
1853 data = of_get_property(np, "qcom,dynamic-mode-switch-type", NULL);
1854 if (data && !strcmp(data, "dynamic-resolution-switch-immediate")) {
1855 if (!list_empty(&ctrl->panel_data.timings_list))
1856 pinfo->mipi.dms_mode =
1857 DYNAMIC_MODE_RESOLUTION_SWITCH_IMMEDIATE;
1858 else
1859 pinfo->mipi.dms_mode =
1860 DYNAMIC_MODE_SWITCH_DISABLED;
1861 goto exit;
1862 }
1863
1864 if (data && !strcmp(data, "dynamic-switch-immediate"))
1865 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_IMMEDIATE;
1866 else
1867 pr_debug("%s: default dms suspend/resume\n", __func__);
1868
1869 mdss_dsi_parse_dcs_cmds(np, &ctrl->video2cmd,
Ingrid Gallardo259c4b02016-11-16 09:24:32 -08001870 "qcom,video-to-cmd-mode-switch-commands",
1871 "qcom,mode-switch-commands-state");
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301872
1873 mdss_dsi_parse_dcs_cmds(np, &ctrl->cmd2video,
Ingrid Gallardo259c4b02016-11-16 09:24:32 -08001874 "qcom,cmd-to-video-mode-switch-commands",
1875 "qcom,mode-switch-commands-state");
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301876
1877 mdss_dsi_parse_dcs_cmds(np, &ctrl->post_dms_on_cmds,
1878 "qcom,mdss-dsi-post-mode-switch-on-command",
1879 "qcom,mdss-dsi-post-mode-switch-on-command-state");
1880
1881 if (pinfo->mipi.dms_mode == DYNAMIC_MODE_SWITCH_IMMEDIATE &&
1882 !ctrl->post_dms_on_cmds.cmd_cnt) {
1883 pr_warn("%s: No post dms on cmd specified\n", __func__);
1884 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_DISABLED;
1885 }
1886
1887 if (!ctrl->video2cmd.cmd_cnt || !ctrl->cmd2video.cmd_cnt) {
1888 pr_warn("%s: No commands specified for dynamic switch\n",
1889 __func__);
1890 pinfo->mipi.dms_mode = DYNAMIC_MODE_SWITCH_DISABLED;
1891 }
1892exit:
1893 pr_info("%s: dynamic switch feature enabled: %d\n", __func__,
1894 pinfo->mipi.dms_mode);
1895}
1896
1897/* the length of all the valid values to be checked should not be great
1898 * than the length of returned data from read command.
1899 */
1900static bool
1901mdss_dsi_parse_esd_check_valid_params(struct mdss_dsi_ctrl_pdata *ctrl)
1902{
1903 int i;
1904
1905 for (i = 0; i < ctrl->status_cmds.cmd_cnt; ++i) {
1906 if (ctrl->status_valid_params[i] > ctrl->status_cmds_rlen[i]) {
1907 pr_debug("%s: ignore valid params!\n", __func__);
1908 return false;
1909 }
1910 }
1911
1912 return true;
1913}
1914
1915static bool mdss_dsi_parse_esd_status_len(struct device_node *np,
1916 char *prop_key, u32 **target, u32 cmd_cnt)
1917{
1918 int tmp;
1919
1920 if (!of_find_property(np, prop_key, &tmp))
1921 return false;
1922
1923 tmp /= sizeof(u32);
1924 if (tmp != cmd_cnt) {
1925 pr_err("%s: request property number(%d) not match command count(%d)\n",
1926 __func__, tmp, cmd_cnt);
1927 return false;
1928 }
1929
1930 *target = kcalloc(tmp, sizeof(u32), GFP_KERNEL);
1931 if (IS_ERR_OR_NULL(*target)) {
1932 pr_err("%s: Error allocating memory for property\n",
1933 __func__);
1934 return false;
1935 }
1936
1937 if (of_property_read_u32_array(np, prop_key, *target, tmp)) {
1938 pr_err("%s: cannot get values from dts\n", __func__);
1939 kfree(*target);
1940 *target = NULL;
1941 return false;
1942 }
1943
1944 return true;
1945}
1946
1947static void mdss_dsi_parse_esd_params(struct device_node *np,
1948 struct mdss_dsi_ctrl_pdata *ctrl)
1949{
1950 u32 tmp;
1951 u32 i, status_len, *lenp;
1952 int rc;
1953 struct property *data;
1954 const char *string;
1955 struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
1956
1957 pinfo->esd_check_enabled = of_property_read_bool(np,
1958 "qcom,esd-check-enabled");
1959
1960 if (!pinfo->esd_check_enabled)
1961 return;
1962
1963 ctrl->status_mode = ESD_MAX;
1964 rc = of_property_read_string(np,
1965 "qcom,mdss-dsi-panel-status-check-mode", &string);
1966 if (!rc) {
1967 if (!strcmp(string, "bta_check")) {
1968 ctrl->status_mode = ESD_BTA;
1969 } else if (!strcmp(string, "reg_read")) {
1970 ctrl->status_mode = ESD_REG;
1971 ctrl->check_read_status =
1972 mdss_dsi_gen_read_status;
1973 } else if (!strcmp(string, "reg_read_nt35596")) {
1974 ctrl->status_mode = ESD_REG_NT35596;
1975 ctrl->status_error_count = 0;
1976 ctrl->check_read_status =
1977 mdss_dsi_nt35596_read_status;
1978 } else if (!strcmp(string, "te_signal_check")) {
1979 if (pinfo->mipi.mode == DSI_CMD_MODE) {
1980 ctrl->status_mode = ESD_TE;
1981 } else {
1982 pr_err("TE-ESD not valid for video mode\n");
1983 goto error;
1984 }
1985 } else {
1986 pr_err("No valid panel-status-check-mode string\n");
1987 goto error;
1988 }
1989 }
1990
1991 if ((ctrl->status_mode == ESD_BTA) || (ctrl->status_mode == ESD_TE) ||
1992 (ctrl->status_mode == ESD_MAX))
1993 return;
1994
1995 mdss_dsi_parse_dcs_cmds(np, &ctrl->status_cmds,
1996 "qcom,mdss-dsi-panel-status-command",
1997 "qcom,mdss-dsi-panel-status-command-state");
1998
1999 rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-max-error-count",
2000 &tmp);
2001 ctrl->max_status_error_count = (!rc ? tmp : 0);
2002
2003 if (!mdss_dsi_parse_esd_status_len(np,
2004 "qcom,mdss-dsi-panel-status-read-length",
2005 &ctrl->status_cmds_rlen, ctrl->status_cmds.cmd_cnt)) {
2006 pinfo->esd_check_enabled = false;
2007 return;
2008 }
2009
2010 if (mdss_dsi_parse_esd_status_len(np,
2011 "qcom,mdss-dsi-panel-status-valid-params",
2012 &ctrl->status_valid_params, ctrl->status_cmds.cmd_cnt)) {
2013 if (!mdss_dsi_parse_esd_check_valid_params(ctrl))
2014 goto error1;
2015 }
2016
2017 status_len = 0;
2018 lenp = ctrl->status_valid_params ?: ctrl->status_cmds_rlen;
2019 for (i = 0; i < ctrl->status_cmds.cmd_cnt; ++i)
2020 status_len += lenp[i];
2021
2022 data = of_find_property(np, "qcom,mdss-dsi-panel-status-value", &tmp);
2023 tmp /= sizeof(u32);
2024 if (!IS_ERR_OR_NULL(data) && tmp != 0 && (tmp % status_len) == 0) {
2025 ctrl->groups = tmp / status_len;
2026 } else {
2027 pr_err("%s: Error parse panel-status-value\n", __func__);
2028 goto error1;
2029 }
2030
2031 ctrl->status_value = kcalloc(status_len * ctrl->groups, sizeof(u32),
2032 GFP_KERNEL);
2033 if (!ctrl->status_value)
2034 goto error1;
2035
2036 ctrl->return_buf = kcalloc(status_len * ctrl->groups,
2037 sizeof(unsigned char), GFP_KERNEL);
2038 if (!ctrl->return_buf)
2039 goto error2;
2040
2041 rc = of_property_read_u32_array(np,
2042 "qcom,mdss-dsi-panel-status-value",
2043 ctrl->status_value, ctrl->groups * status_len);
2044 if (rc) {
2045 pr_debug("%s: Error reading panel status values\n",
2046 __func__);
2047 memset(ctrl->status_value, 0, ctrl->groups * status_len);
2048 }
2049
2050 return;
2051
2052error2:
2053 kfree(ctrl->status_value);
2054error1:
2055 kfree(ctrl->status_valid_params);
2056 kfree(ctrl->status_cmds_rlen);
2057error:
2058 pinfo->esd_check_enabled = false;
2059}
2060
2061static int mdss_dsi_parse_panel_features(struct device_node *np,
2062 struct mdss_dsi_ctrl_pdata *ctrl)
2063{
2064 struct mdss_panel_info *pinfo;
2065
2066 if (!np || !ctrl) {
2067 pr_err("%s: Invalid arguments\n", __func__);
2068 return -ENODEV;
2069 }
2070
2071 pinfo = &ctrl->panel_data.panel_info;
2072
2073 pinfo->partial_update_supported = of_property_read_bool(np,
2074 "qcom,partial-update-enabled");
2075 if (pinfo->mipi.mode == DSI_CMD_MODE) {
2076 pinfo->partial_update_enabled = pinfo->partial_update_supported;
2077 pr_info("%s: partial_update_enabled=%d\n", __func__,
2078 pinfo->partial_update_enabled);
2079 ctrl->set_col_page_addr = mdss_dsi_set_col_page_addr;
2080 if (pinfo->partial_update_enabled) {
2081 pinfo->partial_update_roi_merge =
2082 of_property_read_bool(np,
2083 "qcom,partial-update-roi-merge");
2084 }
2085 }
2086
2087 pinfo->dcs_cmd_by_left = of_property_read_bool(np,
2088 "qcom,dcs-cmd-by-left");
2089
2090 pinfo->ulps_feature_enabled = of_property_read_bool(np,
2091 "qcom,ulps-enabled");
2092 pr_info("%s: ulps feature %s\n", __func__,
2093 (pinfo->ulps_feature_enabled ? "enabled" : "disabled"));
2094
2095 pinfo->ulps_suspend_enabled = of_property_read_bool(np,
2096 "qcom,suspend-ulps-enabled");
2097 pr_info("%s: ulps during suspend feature %s", __func__,
2098 (pinfo->ulps_suspend_enabled ? "enabled" : "disabled"));
2099
2100 mdss_dsi_parse_dms_config(np, ctrl);
2101
2102 pinfo->panel_ack_disabled = pinfo->sim_panel_mode ?
2103 1 : of_property_read_bool(np, "qcom,panel-ack-disabled");
2104
2105 pinfo->allow_phy_power_off = of_property_read_bool(np,
2106 "qcom,panel-allow-phy-poweroff");
2107
2108 mdss_dsi_parse_esd_params(np, ctrl);
2109
2110 if (pinfo->panel_ack_disabled && pinfo->esd_check_enabled) {
2111 pr_warn("ESD should not be enabled if panel ACK is disabled\n");
2112 pinfo->esd_check_enabled = false;
2113 }
2114
2115 if (ctrl->disp_en_gpio <= 0) {
2116 ctrl->disp_en_gpio = of_get_named_gpio(
2117 np,
2118 "qcom,5v-boost-gpio", 0);
2119
2120 if (!gpio_is_valid(ctrl->disp_en_gpio))
2121 pr_debug("%s:%d, Disp_en gpio not specified\n",
2122 __func__, __LINE__);
2123 }
2124
2125 mdss_dsi_parse_dcs_cmds(np, &ctrl->lp_on_cmds,
2126 "qcom,mdss-dsi-lp-mode-on", NULL);
2127
2128 mdss_dsi_parse_dcs_cmds(np, &ctrl->lp_off_cmds,
2129 "qcom,mdss-dsi-lp-mode-off", NULL);
2130
2131 return 0;
2132}
2133
2134static void mdss_dsi_parse_panel_horizintal_line_idle(struct device_node *np,
2135 struct mdss_dsi_ctrl_pdata *ctrl)
2136{
2137 const u32 *src;
2138 int i, len, cnt;
2139 struct panel_horizontal_idle *kp;
2140
2141 if (!np || !ctrl) {
2142 pr_err("%s: Invalid arguments\n", __func__);
2143 return;
2144 }
2145
2146 src = of_get_property(np, "qcom,mdss-dsi-hor-line-idle", &len);
2147 if (!src || len == 0)
2148 return;
2149
2150 cnt = len % 3; /* 3 fields per entry */
2151 if (cnt) {
2152 pr_err("%s: invalid horizontal idle len=%d\n", __func__, len);
2153 return;
2154 }
2155
2156 cnt = len / sizeof(u32);
2157
2158 kp = kcalloc((cnt / 3), sizeof(*kp), GFP_KERNEL);
2159 if (kp == NULL)
2160 return;
2161
2162 ctrl->line_idle = kp;
2163 for (i = 0; i < cnt; i += 3) {
2164 kp->min = be32_to_cpu(src[i]);
2165 kp->max = be32_to_cpu(src[i+1]);
2166 kp->idle = be32_to_cpu(src[i+2]);
2167 kp++;
2168 ctrl->horizontal_idle_cnt++;
2169 }
2170
2171 /*
2172 * idle is enabled for this controller, this will be used to
2173 * enable/disable burst mode since both features are mutually
2174 * exclusive.
2175 */
2176 ctrl->idle_enabled = true;
2177
2178 pr_debug("%s: horizontal_idle_cnt=%d\n", __func__,
2179 ctrl->horizontal_idle_cnt);
2180}
2181
2182static int mdss_dsi_set_refresh_rate_range(struct device_node *pan_node,
2183 struct mdss_panel_info *pinfo)
2184{
2185 int rc = 0;
2186
2187 rc = of_property_read_u32(pan_node,
2188 "qcom,mdss-dsi-min-refresh-rate",
2189 &pinfo->min_fps);
2190 if (rc) {
2191 pr_warn("%s:%d, Unable to read min refresh rate\n",
2192 __func__, __LINE__);
2193
2194 /*
Aravind Venkateswaranefd2e782016-08-24 16:43:13 -07002195 * If min refresh rate is not specified, set it to the
2196 * default panel refresh rate.
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302197 */
Aravind Venkateswaranefd2e782016-08-24 16:43:13 -07002198 pinfo->min_fps = pinfo->mipi.frame_rate;
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302199 rc = 0;
2200 }
2201
2202 rc = of_property_read_u32(pan_node,
2203 "qcom,mdss-dsi-max-refresh-rate",
2204 &pinfo->max_fps);
2205 if (rc) {
2206 pr_warn("%s:%d, Unable to read max refresh rate\n",
2207 __func__, __LINE__);
2208
2209 /*
2210 * Since max refresh rate was not specified when dynamic
2211 * fps is enabled, using the default panel refresh rate
2212 * as max refresh rate supported.
2213 */
2214 pinfo->max_fps = pinfo->mipi.frame_rate;
2215 rc = 0;
2216 }
2217
2218 pr_info("dyn_fps: min = %d, max = %d\n",
2219 pinfo->min_fps, pinfo->max_fps);
2220 return rc;
2221}
2222
2223static void mdss_dsi_parse_dfps_config(struct device_node *pan_node,
2224 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2225{
2226 const char *data;
2227 bool dynamic_fps;
2228 struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
2229
2230 dynamic_fps = of_property_read_bool(pan_node,
2231 "qcom,mdss-dsi-pan-enable-dynamic-fps");
2232
2233 if (!dynamic_fps)
2234 return;
2235
2236 pinfo->dynamic_fps = true;
2237 data = of_get_property(pan_node, "qcom,mdss-dsi-pan-fps-update", NULL);
2238 if (data) {
2239 if (!strcmp(data, "dfps_suspend_resume_mode")) {
2240 pinfo->dfps_update = DFPS_SUSPEND_RESUME_MODE;
2241 pr_debug("dfps mode: suspend/resume\n");
2242 } else if (!strcmp(data, "dfps_immediate_clk_mode")) {
2243 pinfo->dfps_update = DFPS_IMMEDIATE_CLK_UPDATE_MODE;
2244 pr_debug("dfps mode: Immediate clk\n");
2245 } else if (!strcmp(data, "dfps_immediate_porch_mode_hfp")) {
2246 pinfo->dfps_update =
2247 DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP;
2248 pr_debug("dfps mode: Immediate porch HFP\n");
2249 } else if (!strcmp(data, "dfps_immediate_porch_mode_vfp")) {
2250 pinfo->dfps_update =
2251 DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP;
2252 pr_debug("dfps mode: Immediate porch VFP\n");
2253 } else {
2254 pinfo->dfps_update = DFPS_SUSPEND_RESUME_MODE;
2255 pr_debug("default dfps mode: suspend/resume\n");
2256 }
2257 mdss_dsi_set_refresh_rate_range(pan_node, pinfo);
2258 } else {
2259 pinfo->dynamic_fps = false;
2260 pr_debug("dfps update mode not configured: disable\n");
2261 }
2262 pinfo->new_fps = pinfo->mipi.frame_rate;
2263 pinfo->current_fps = pinfo->mipi.frame_rate;
2264}
2265
2266int mdss_panel_parse_bl_settings(struct device_node *np,
2267 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2268{
2269 const char *data;
2270 int rc = 0;
2271 u32 tmp;
2272
2273 ctrl_pdata->bklt_ctrl = UNKNOWN_CTRL;
2274 data = of_get_property(np, "qcom,mdss-dsi-bl-pmic-control-type", NULL);
2275 if (data) {
2276 if (!strcmp(data, "bl_ctrl_wled")) {
2277 led_trigger_register_simple("bkl-trigger",
2278 &bl_led_trigger);
2279 pr_debug("%s: SUCCESS-> WLED TRIGGER register\n",
2280 __func__);
2281 ctrl_pdata->bklt_ctrl = BL_WLED;
2282 } else if (!strcmp(data, "bl_ctrl_pwm")) {
2283 ctrl_pdata->bklt_ctrl = BL_PWM;
2284 ctrl_pdata->pwm_pmi = of_property_read_bool(np,
2285 "qcom,mdss-dsi-bl-pwm-pmi");
2286 rc = of_property_read_u32(np,
2287 "qcom,mdss-dsi-bl-pmic-pwm-frequency", &tmp);
2288 if (rc) {
2289 pr_err("%s:%d, Error, panel pwm_period\n",
2290 __func__, __LINE__);
2291 return -EINVAL;
2292 }
2293 ctrl_pdata->pwm_period = tmp;
2294 if (ctrl_pdata->pwm_pmi) {
2295 ctrl_pdata->pwm_bl = of_pwm_get(np, NULL);
2296 if (IS_ERR(ctrl_pdata->pwm_bl)) {
2297 pr_err("%s: Error, pwm device\n",
2298 __func__);
2299 ctrl_pdata->pwm_bl = NULL;
2300 return -EINVAL;
2301 }
2302 } else {
2303 rc = of_property_read_u32(np,
2304 "qcom,mdss-dsi-bl-pmic-bank-select",
2305 &tmp);
2306 if (rc) {
2307 pr_err("%s:%d, Error, lpg channel\n",
2308 __func__, __LINE__);
2309 return -EINVAL;
2310 }
2311 ctrl_pdata->pwm_lpg_chan = tmp;
2312 tmp = of_get_named_gpio(np,
2313 "qcom,mdss-dsi-pwm-gpio", 0);
2314 ctrl_pdata->pwm_pmic_gpio = tmp;
2315 pr_debug("%s: Configured PWM bklt ctrl\n",
2316 __func__);
2317 }
2318 } else if (!strcmp(data, "bl_ctrl_dcs")) {
2319 ctrl_pdata->bklt_ctrl = BL_DCS_CMD;
Yahui Wang0c1acb02017-06-07 09:40:03 +08002320 data = of_get_property(np,
2321 "qcom,mdss-dsi-bl-dcs-command-state", NULL);
2322 if (data && !strcmp(data, "dsi_hs_mode"))
2323 ctrl_pdata->bklt_dcs_op_mode = DSI_HS_MODE;
2324 else
2325 ctrl_pdata->bklt_dcs_op_mode = DSI_LP_MODE;
2326
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302327 pr_debug("%s: Configured DCS_CMD bklt ctrl\n",
2328 __func__);
2329 }
2330 }
2331 return 0;
2332}
2333
2334int mdss_dsi_panel_timing_switch(struct mdss_dsi_ctrl_pdata *ctrl,
2335 struct mdss_panel_timing *timing)
2336{
2337 struct dsi_panel_timing *pt;
2338 struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
2339 int i;
2340
2341 if (!timing)
2342 return -EINVAL;
2343
2344 if (timing == ctrl->panel_data.current_timing) {
2345 pr_warn("%s: panel timing \"%s\" already set\n", __func__,
2346 timing->name);
2347 return 0; /* nothing to do */
2348 }
2349
2350 pr_debug("%s: ndx=%d switching to panel timing \"%s\"\n", __func__,
2351 ctrl->ndx, timing->name);
2352
2353 mdss_panel_info_from_timing(timing, pinfo);
2354
2355 pt = container_of(timing, struct dsi_panel_timing, timing);
2356 pinfo->mipi.t_clk_pre = pt->t_clk_pre;
2357 pinfo->mipi.t_clk_post = pt->t_clk_post;
2358
2359 for (i = 0; i < ARRAY_SIZE(pt->phy_timing); i++)
2360 pinfo->mipi.dsi_phy_db.timing[i] = pt->phy_timing[i];
2361
2362 for (i = 0; i < ARRAY_SIZE(pt->phy_timing_8996); i++)
2363 pinfo->mipi.dsi_phy_db.timing_8996[i] = pt->phy_timing_8996[i];
2364
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +05302365 for (i = 0; i < ARRAY_SIZE(pt->phy_timing_12nm); i++)
2366 pinfo->mipi.dsi_phy_db.timing_12nm[i] = pt->phy_timing_12nm[i];
2367
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302368 ctrl->on_cmds = pt->on_cmds;
2369 ctrl->post_panel_on_cmds = pt->post_panel_on_cmds;
2370
2371 ctrl->panel_data.current_timing = timing;
2372 if (!timing->clk_rate)
2373 ctrl->refresh_clk_rate = true;
2374 mdss_dsi_clk_refresh(&ctrl->panel_data, ctrl->update_phy_timing);
2375
2376 return 0;
2377}
2378
2379void mdss_dsi_unregister_bl_settings(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2380{
2381 if (ctrl_pdata->bklt_ctrl == BL_WLED)
2382 led_trigger_unregister_simple(bl_led_trigger);
2383}
2384
2385static int mdss_dsi_panel_timing_from_dt(struct device_node *np,
2386 struct dsi_panel_timing *pt,
2387 struct mdss_panel_data *panel_data)
2388{
2389 u32 tmp;
2390 u64 tmp64;
2391 int rc, i, len;
2392 const char *data;
2393 struct mdss_dsi_ctrl_pdata *ctrl_pdata;
2394 struct mdss_panel_info *pinfo;
2395 bool phy_timings_present = false;
2396
2397 pinfo = &panel_data->panel_info;
2398
2399 ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata,
2400 panel_data);
2401
2402 rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-width", &tmp);
2403 if (rc) {
2404 pr_err("%s:%d, panel width not specified\n",
2405 __func__, __LINE__);
2406 return -EINVAL;
2407 }
2408 pt->timing.xres = tmp;
2409
2410 rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-height", &tmp);
2411 if (rc) {
2412 pr_err("%s:%d, panel height not specified\n",
2413 __func__, __LINE__);
2414 return -EINVAL;
2415 }
2416 pt->timing.yres = tmp;
2417
2418 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-front-porch", &tmp);
2419 pt->timing.h_front_porch = (!rc ? tmp : 6);
2420 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-back-porch", &tmp);
2421 pt->timing.h_back_porch = (!rc ? tmp : 6);
2422 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-pulse-width", &tmp);
2423 pt->timing.h_pulse_width = (!rc ? tmp : 2);
2424 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-sync-skew", &tmp);
2425 pt->timing.hsync_skew = (!rc ? tmp : 0);
2426 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-back-porch", &tmp);
2427 pt->timing.v_back_porch = (!rc ? tmp : 6);
2428 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-front-porch", &tmp);
2429 pt->timing.v_front_porch = (!rc ? tmp : 6);
2430 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-pulse-width", &tmp);
2431 pt->timing.v_pulse_width = (!rc ? tmp : 2);
2432
2433 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-left-border", &tmp);
2434 pt->timing.border_left = !rc ? tmp : 0;
2435 rc = of_property_read_u32(np, "qcom,mdss-dsi-h-right-border", &tmp);
2436 pt->timing.border_right = !rc ? tmp : 0;
2437
2438 /* overriding left/right borders for split display cases */
2439 if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) {
2440 if (panel_data->next)
2441 pt->timing.border_right = 0;
2442 else
2443 pt->timing.border_left = 0;
2444 }
2445
2446 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-top-border", &tmp);
2447 pt->timing.border_top = !rc ? tmp : 0;
2448 rc = of_property_read_u32(np, "qcom,mdss-dsi-v-bottom-border", &tmp);
2449 pt->timing.border_bottom = !rc ? tmp : 0;
2450
2451 rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-framerate", &tmp);
2452 pt->timing.frame_rate = !rc ? tmp : DEFAULT_FRAME_RATE;
2453 rc = of_property_read_u64(np, "qcom,mdss-dsi-panel-clockrate", &tmp64);
2454 if (rc == -EOVERFLOW) {
2455 tmp64 = 0;
2456 rc = of_property_read_u32(np,
2457 "qcom,mdss-dsi-panel-clockrate", (u32 *)&tmp64);
2458 }
2459 pt->timing.clk_rate = !rc ? tmp64 : 0;
2460
2461 data = of_get_property(np, "qcom,mdss-dsi-panel-timings", &len);
2462 if ((!data) || (len != 12)) {
2463 pr_debug("%s:%d, Unable to read Phy timing settings",
2464 __func__, __LINE__);
2465 } else {
2466 for (i = 0; i < len; i++)
2467 pt->phy_timing[i] = data[i];
2468 phy_timings_present = true;
2469 }
2470
2471 data = of_get_property(np, "qcom,mdss-dsi-panel-timings-phy-v2", &len);
2472 if ((!data) || (len != 40)) {
2473 pr_debug("%s:%d, Unable to read 8996 Phy lane timing settings",
2474 __func__, __LINE__);
2475 } else {
2476 for (i = 0; i < len; i++)
2477 pt->phy_timing_8996[i] = data[i];
2478 phy_timings_present = true;
2479 }
Padmanabhan Komanduru81d8dc522018-03-22 20:00:58 +05302480
2481 data = of_get_property(np,
2482 "qcom,mdss-dsi-panel-timings-phy-12nm", &len);
2483 if ((!data) || (len != 8)) {
2484 pr_debug("%s:%d, Unable to read 12nm Phy lane timing settings",
2485 __func__, __LINE__);
2486 } else {
2487 for (i = 0; i < len; i++)
2488 pt->phy_timing_12nm[i] = data[i];
2489 phy_timings_present = true;
2490 }
2491
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302492 if (!phy_timings_present) {
2493 pr_err("%s: phy timing settings not present\n", __func__);
2494 return -EINVAL;
2495 }
2496
2497 rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-pre", &tmp);
2498 pt->t_clk_pre = (!rc ? tmp : 0x24);
2499 rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-post", &tmp);
2500 pt->t_clk_post = (!rc ? tmp : 0x03);
2501
2502 if (np->name) {
2503 pt->timing.name = kstrdup(np->name, GFP_KERNEL);
2504 pr_info("%s: found new timing \"%s\" (%pK)\n", __func__,
2505 np->name, &pt->timing);
2506 }
2507
2508 return 0;
2509}
2510
2511static int mdss_dsi_panel_config_res_properties(struct device_node *np,
2512 struct dsi_panel_timing *pt,
2513 struct mdss_panel_data *panel_data,
2514 bool default_timing)
2515{
2516 int rc = 0;
2517
2518 mdss_dsi_parse_roi_alignment(np, pt);
2519
2520 mdss_dsi_parse_dcs_cmds(np, &pt->on_cmds,
2521 "qcom,mdss-dsi-on-command",
2522 "qcom,mdss-dsi-on-command-state");
2523
2524 mdss_dsi_parse_dcs_cmds(np, &pt->post_panel_on_cmds,
2525 "qcom,mdss-dsi-post-panel-on-command", NULL);
2526
2527 mdss_dsi_parse_dcs_cmds(np, &pt->switch_cmds,
2528 "qcom,mdss-dsi-timing-switch-command",
2529 "qcom,mdss-dsi-timing-switch-command-state");
2530
2531 rc = mdss_dsi_parse_topology_config(np, pt, panel_data, default_timing);
2532 if (rc) {
2533 pr_err("%s: parsing compression params failed. rc:%d\n",
2534 __func__, rc);
2535 return rc;
2536 }
2537
2538 mdss_panel_parse_te_params(np, &pt->timing);
2539 return rc;
2540}
2541
2542static int mdss_panel_parse_display_timings(struct device_node *np,
2543 struct mdss_panel_data *panel_data)
2544{
2545 struct mdss_dsi_ctrl_pdata *ctrl;
2546 struct dsi_panel_timing *modedb;
2547 struct device_node *timings_np;
2548 struct device_node *entry;
2549 int num_timings, rc;
2550 int i = 0, active_ndx = 0;
2551 bool default_timing = false;
2552
2553 ctrl = container_of(panel_data, struct mdss_dsi_ctrl_pdata, panel_data);
2554
2555 INIT_LIST_HEAD(&panel_data->timings_list);
2556
2557 timings_np = of_get_child_by_name(np, "qcom,mdss-dsi-display-timings");
2558 if (!timings_np) {
2559 struct dsi_panel_timing pt;
2560
2561 memset(&pt, 0, sizeof(struct dsi_panel_timing));
2562
2563 /*
2564 * display timings node is not available, fallback to reading
2565 * timings directly from root node instead
2566 */
2567 pr_debug("reading display-timings from panel node\n");
2568 rc = mdss_dsi_panel_timing_from_dt(np, &pt, panel_data);
2569 if (!rc) {
2570 mdss_dsi_panel_config_res_properties(np, &pt,
2571 panel_data, true);
2572 rc = mdss_dsi_panel_timing_switch(ctrl, &pt.timing);
2573 }
2574 return rc;
2575 }
2576
2577 num_timings = of_get_child_count(timings_np);
2578 if (num_timings == 0) {
2579 pr_err("no timings found within display-timings\n");
2580 rc = -EINVAL;
2581 goto exit;
2582 }
2583
2584 modedb = kcalloc(num_timings, sizeof(*modedb), GFP_KERNEL);
2585 if (!modedb) {
2586 rc = -ENOMEM;
2587 goto exit;
2588 }
2589
2590 for_each_child_of_node(timings_np, entry) {
2591 rc = mdss_dsi_panel_timing_from_dt(entry, (modedb + i),
2592 panel_data);
2593 if (rc) {
2594 kfree(modedb);
2595 goto exit;
2596 }
2597
2598 default_timing = of_property_read_bool(entry,
2599 "qcom,mdss-dsi-timing-default");
2600 if (default_timing)
2601 active_ndx = i;
2602
2603 mdss_dsi_panel_config_res_properties(entry, (modedb + i),
2604 panel_data, default_timing);
2605
2606 list_add(&modedb[i].timing.list,
2607 &panel_data->timings_list);
2608 i++;
2609 }
2610
2611 /* Configure default timing settings */
2612 rc = mdss_dsi_panel_timing_switch(ctrl, &modedb[active_ndx].timing);
2613 if (rc)
2614 pr_err("unable to configure default timing settings\n");
2615
2616exit:
2617 of_node_put(timings_np);
2618
2619 return rc;
2620}
2621
2622#ifdef TARGET_HW_MDSS_HDMI
2623static int mdss_panel_parse_dt_hdmi(struct device_node *np,
2624 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2625{
2626 int len = 0;
2627 const char *bridge_chip_name;
2628 struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
2629
2630 pinfo->is_dba_panel = of_property_read_bool(np,
2631 "qcom,dba-panel");
2632
2633 if (pinfo->is_dba_panel) {
2634 bridge_chip_name = of_get_property(np,
2635 "qcom,bridge-name", &len);
2636 if (!bridge_chip_name || len <= 0) {
2637 pr_err("%s:%d Unable to read qcom,bridge_name, data=%pK,len=%d\n",
2638 __func__, __LINE__, bridge_chip_name, len);
2639 return -EINVAL;
2640 }
2641 strlcpy(ctrl_pdata->bridge_name, bridge_chip_name,
2642 MSM_DBA_CHIP_NAME_MAX_LEN);
2643 }
2644 return 0;
2645}
2646#else
2647static int mdss_panel_parse_dt_hdmi(struct device_node *np,
2648 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2649{
2650 (void)(*np);
2651 (void)(*ctrl_pdata);
2652 return 0;
2653}
2654#endif
2655static int mdss_panel_parse_dt(struct device_node *np,
2656 struct mdss_dsi_ctrl_pdata *ctrl_pdata)
2657{
2658 u32 tmp;
2659 u8 lanes = 0;
2660 int rc = 0;
2661 const char *data;
2662 static const char *pdest;
2663 struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
2664
2665 if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data))
2666 pinfo->is_split_display = true;
2667
2668 rc = of_property_read_u32(np,
2669 "qcom,mdss-pan-physical-width-dimension", &tmp);
2670 pinfo->physical_width = (!rc ? tmp : 0);
2671 rc = of_property_read_u32(np,
2672 "qcom,mdss-pan-physical-height-dimension", &tmp);
2673 pinfo->physical_height = (!rc ? tmp : 0);
2674
2675 rc = of_property_read_u32(np, "qcom,mdss-dsi-bpp", &tmp);
2676 if (rc) {
2677 pr_err("%s:%d, bpp not specified\n", __func__, __LINE__);
2678 return -EINVAL;
2679 }
2680 pinfo->bpp = (!rc ? tmp : 24);
2681 pinfo->mipi.mode = DSI_VIDEO_MODE;
2682 data = of_get_property(np, "qcom,mdss-dsi-panel-type", NULL);
2683 if (data && !strcmp(data, "dsi_cmd_mode"))
2684 pinfo->mipi.mode = DSI_CMD_MODE;
2685 pinfo->mipi.boot_mode = pinfo->mipi.mode;
2686 tmp = 0;
2687 data = of_get_property(np, "qcom,mdss-dsi-pixel-packing", NULL);
2688 if (data && !strcmp(data, "loose"))
2689 pinfo->mipi.pixel_packing = 1;
2690 else
2691 pinfo->mipi.pixel_packing = 0;
2692 rc = mdss_panel_get_dst_fmt(pinfo->bpp,
2693 pinfo->mipi.mode, pinfo->mipi.pixel_packing,
2694 &(pinfo->mipi.dst_format));
2695 if (rc) {
2696 pr_debug("%s: problem determining dst format. Set Default\n",
2697 __func__);
2698 pinfo->mipi.dst_format =
2699 DSI_VIDEO_DST_FORMAT_RGB888;
2700 }
2701 pdest = of_get_property(np,
2702 "qcom,mdss-dsi-panel-destination", NULL);
2703
2704 rc = of_property_read_u32(np,
2705 "qcom,mdss-dsi-underflow-color", &tmp);
2706 pinfo->lcdc.underflow_clr = (!rc ? tmp : 0xff);
2707 rc = of_property_read_u32(np,
2708 "qcom,mdss-dsi-border-color", &tmp);
2709 pinfo->lcdc.border_clr = (!rc ? tmp : 0);
2710 data = of_get_property(np, "qcom,mdss-dsi-panel-orientation", NULL);
2711 if (data) {
2712 pr_debug("panel orientation is %s\n", data);
2713 if (!strcmp(data, "180"))
2714 pinfo->panel_orientation = MDP_ROT_180;
2715 else if (!strcmp(data, "hflip"))
2716 pinfo->panel_orientation = MDP_FLIP_LR;
2717 else if (!strcmp(data, "vflip"))
2718 pinfo->panel_orientation = MDP_FLIP_UD;
2719 }
2720
2721 rc = of_property_read_u32(np, "qcom,mdss-brightness-max-level", &tmp);
2722 pinfo->brightness_max = (!rc ? tmp : MDSS_MAX_BL_BRIGHTNESS);
2723 rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-min-level", &tmp);
2724 pinfo->bl_min = (!rc ? tmp : 0);
2725 rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-max-level", &tmp);
2726 pinfo->bl_max = (!rc ? tmp : 255);
2727 ctrl_pdata->bklt_max = pinfo->bl_max;
2728
2729 rc = of_property_read_u32(np, "qcom,mdss-dsi-interleave-mode", &tmp);
2730 pinfo->mipi.interleave_mode = (!rc ? tmp : 0);
2731
2732 pinfo->mipi.vsync_enable = of_property_read_bool(np,
2733 "qcom,mdss-dsi-te-check-enable");
2734
2735 if (pinfo->sim_panel_mode == SIM_SW_TE_MODE)
2736 pinfo->mipi.hw_vsync_mode = false;
2737 else
2738 pinfo->mipi.hw_vsync_mode = of_property_read_bool(np,
2739 "qcom,mdss-dsi-te-using-te-pin");
2740
2741 rc = of_property_read_u32(np,
2742 "qcom,mdss-dsi-h-sync-pulse", &tmp);
2743 pinfo->mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
2744
2745 pinfo->mipi.hfp_power_stop = of_property_read_bool(np,
2746 "qcom,mdss-dsi-hfp-power-mode");
2747 pinfo->mipi.hsa_power_stop = of_property_read_bool(np,
2748 "qcom,mdss-dsi-hsa-power-mode");
2749 pinfo->mipi.hbp_power_stop = of_property_read_bool(np,
2750 "qcom,mdss-dsi-hbp-power-mode");
2751 pinfo->mipi.last_line_interleave_en = of_property_read_bool(np,
2752 "qcom,mdss-dsi-last-line-interleave");
2753 pinfo->mipi.bllp_power_stop = of_property_read_bool(np,
2754 "qcom,mdss-dsi-bllp-power-mode");
2755 pinfo->mipi.eof_bllp_power_stop = of_property_read_bool(
2756 np, "qcom,mdss-dsi-bllp-eof-power-mode");
2757 pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
2758 data = of_get_property(np, "qcom,mdss-dsi-traffic-mode", NULL);
2759 if (data) {
2760 if (!strcmp(data, "non_burst_sync_event"))
2761 pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
2762 else if (!strcmp(data, "burst_mode"))
2763 pinfo->mipi.traffic_mode = DSI_BURST_MODE;
2764 }
2765 rc = of_property_read_u32(np,
2766 "qcom,mdss-dsi-te-dcs-command", &tmp);
2767 pinfo->mipi.insert_dcs_cmd =
2768 (!rc ? tmp : 1);
2769 rc = of_property_read_u32(np,
2770 "qcom,mdss-dsi-wr-mem-continue", &tmp);
2771 pinfo->mipi.wr_mem_continue =
2772 (!rc ? tmp : 0x3c);
2773 rc = of_property_read_u32(np,
2774 "qcom,mdss-dsi-wr-mem-start", &tmp);
2775 pinfo->mipi.wr_mem_start =
2776 (!rc ? tmp : 0x2c);
2777 rc = of_property_read_u32(np,
2778 "qcom,mdss-dsi-te-pin-select", &tmp);
2779 pinfo->mipi.te_sel =
2780 (!rc ? tmp : 1);
2781 rc = of_property_read_u32(np, "qcom,mdss-dsi-virtual-channel-id", &tmp);
2782 pinfo->mipi.vc = (!rc ? tmp : 0);
2783 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
2784 data = of_get_property(np, "qcom,mdss-dsi-color-order", NULL);
2785 if (data) {
2786 if (!strcmp(data, "rgb_swap_rbg"))
2787 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RBG;
2788 else if (!strcmp(data, "rgb_swap_bgr"))
2789 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_BGR;
2790 else if (!strcmp(data, "rgb_swap_brg"))
2791 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_BRG;
2792 else if (!strcmp(data, "rgb_swap_grb"))
2793 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_GRB;
2794 else if (!strcmp(data, "rgb_swap_gbr"))
2795 pinfo->mipi.rgb_swap = DSI_RGB_SWAP_GBR;
2796 }
2797 pinfo->mipi.data_lane0 = of_property_read_bool(np,
2798 "qcom,mdss-dsi-lane-0-state");
2799 pinfo->mipi.data_lane1 = of_property_read_bool(np,
2800 "qcom,mdss-dsi-lane-1-state");
2801 pinfo->mipi.data_lane2 = of_property_read_bool(np,
2802 "qcom,mdss-dsi-lane-2-state");
2803 pinfo->mipi.data_lane3 = of_property_read_bool(np,
2804 "qcom,mdss-dsi-lane-3-state");
2805
2806 if (pinfo->mipi.data_lane0)
2807 lanes++;
2808 if (pinfo->mipi.data_lane1)
2809 lanes++;
2810 if (pinfo->mipi.data_lane2)
2811 lanes++;
2812 if (pinfo->mipi.data_lane3)
2813 lanes++;
2814 /*
2815 * needed to set default lanes during
2816 * resolution switch for bridge chips
2817 */
2818 pinfo->mipi.default_lanes = lanes;
2819
2820 rc = mdss_panel_parse_display_timings(np, &ctrl_pdata->panel_data);
2821 if (rc)
2822 return rc;
2823 rc = mdss_dsi_parse_hdr_settings(np, pinfo);
2824 if (rc)
2825 return rc;
2826
2827 pinfo->mipi.rx_eot_ignore = of_property_read_bool(np,
2828 "qcom,mdss-dsi-rx-eot-ignore");
2829 pinfo->mipi.tx_eot_append = of_property_read_bool(np,
2830 "qcom,mdss-dsi-tx-eot-append");
2831
2832 rc = of_property_read_u32(np, "qcom,mdss-dsi-stream", &tmp);
2833 pinfo->mipi.stream = (!rc ? tmp : 0);
2834
2835 data = of_get_property(np, "qcom,mdss-dsi-panel-mode-gpio-state", NULL);
2836 if (data) {
2837 if (!strcmp(data, "high"))
2838 pinfo->mode_gpio_state = MODE_GPIO_HIGH;
2839 else if (!strcmp(data, "low"))
2840 pinfo->mode_gpio_state = MODE_GPIO_LOW;
2841 } else {
2842 pinfo->mode_gpio_state = MODE_GPIO_NOT_VALID;
2843 }
2844
2845 rc = of_property_read_u32(np, "qcom,mdss-mdp-transfer-time-us", &tmp);
2846 pinfo->mdp_transfer_time_us = (!rc ? tmp : DEFAULT_MDP_TRANSFER_TIME);
2847
2848 pinfo->mipi.lp11_init = of_property_read_bool(np,
2849 "qcom,mdss-dsi-lp11-init");
2850 rc = of_property_read_u32(np, "qcom,mdss-dsi-init-delay-us", &tmp);
2851 pinfo->mipi.init_delay = (!rc ? tmp : 0);
2852
2853 rc = of_property_read_u32(np, "qcom,mdss-dsi-post-init-delay", &tmp);
2854 pinfo->mipi.post_init_delay = (!rc ? tmp : 0);
2855
2856 mdss_dsi_parse_trigger(np, &(pinfo->mipi.mdp_trigger),
2857 "qcom,mdss-dsi-mdp-trigger");
2858
2859 mdss_dsi_parse_trigger(np, &(pinfo->mipi.dma_trigger),
2860 "qcom,mdss-dsi-dma-trigger");
2861
2862 mdss_dsi_parse_reset_seq(np, pinfo->rst_seq, &(pinfo->rst_seq_len),
2863 "qcom,mdss-dsi-reset-sequence");
2864
2865 mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->off_cmds,
2866 "qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state");
2867
2868 mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->idle_on_cmds,
2869 "qcom,mdss-dsi-idle-on-command",
2870 "qcom,mdss-dsi-idle-on-command-state");
2871
2872 mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->idle_off_cmds,
2873 "qcom,mdss-dsi-idle-off-command",
2874 "qcom,mdss-dsi-idle-off-command-state");
2875
2876 rc = of_property_read_u32(np, "qcom,mdss-dsi-idle-fps", &tmp);
2877 pinfo->mipi.frame_rate_idle = (!rc ? tmp : 60);
2878
2879 rc = of_property_read_u32(np, "qcom,adjust-timer-wakeup-ms", &tmp);
2880 pinfo->adjust_timer_delay_ms = (!rc ? tmp : 0);
2881
2882 pinfo->mipi.force_clk_lane_hs = of_property_read_bool(np,
2883 "qcom,mdss-dsi-force-clock-lane-hs");
2884
2885 rc = mdss_dsi_parse_panel_features(np, ctrl_pdata);
2886 if (rc) {
2887 pr_err("%s: failed to parse panel features\n", __func__);
2888 goto error;
2889 }
2890
2891 mdss_dsi_parse_panel_horizintal_line_idle(np, ctrl_pdata);
2892
2893 mdss_dsi_parse_dfps_config(np, ctrl_pdata);
2894
2895 rc = mdss_panel_parse_dt_hdmi(np, ctrl_pdata);
2896 if (rc)
2897 goto error;
2898
2899 return 0;
2900
2901error:
2902 return -EINVAL;
2903}
2904
2905int mdss_dsi_panel_init(struct device_node *node,
2906 struct mdss_dsi_ctrl_pdata *ctrl_pdata,
2907 int ndx)
2908{
2909 int rc = 0;
2910 static const char *panel_name;
2911 struct mdss_panel_info *pinfo;
2912
2913 if (!node || !ctrl_pdata) {
2914 pr_err("%s: Invalid arguments\n", __func__);
2915 return -ENODEV;
2916 }
2917
2918 pinfo = &ctrl_pdata->panel_data.panel_info;
2919
2920 pr_debug("%s:%d\n", __func__, __LINE__);
2921 pinfo->panel_name[0] = '\0';
2922 panel_name = of_get_property(node, "qcom,mdss-dsi-panel-name", NULL);
2923 if (!panel_name) {
2924 pr_info("%s:%d, Panel name not specified\n",
2925 __func__, __LINE__);
2926 } else {
2927 pr_info("%s: Panel Name = %s\n", __func__, panel_name);
2928 strlcpy(&pinfo->panel_name[0], panel_name, MDSS_MAX_PANEL_LEN);
2929 }
2930 rc = mdss_panel_parse_dt(node, ctrl_pdata);
2931 if (rc) {
2932 pr_err("%s:%d panel dt parse failed\n", __func__, __LINE__);
2933 return rc;
2934 }
2935
2936 pinfo->dynamic_switch_pending = false;
2937 pinfo->is_lpm_mode = false;
2938 pinfo->esd_rdy = false;
2939 pinfo->persist_mode = false;
2940
2941 ctrl_pdata->on = mdss_dsi_panel_on;
2942 ctrl_pdata->post_panel_on = mdss_dsi_post_panel_on;
2943 ctrl_pdata->off = mdss_dsi_panel_off;
2944 ctrl_pdata->low_power_config = mdss_dsi_panel_low_power_config;
2945 ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
2946 ctrl_pdata->panel_data.apply_display_setting =
2947 mdss_dsi_panel_apply_display_setting;
2948 ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode;
2949 ctrl_pdata->panel_data.get_idle = mdss_dsi_panel_get_idle_mode;
2950 return 0;
2951}