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