blob: 76714965e556a71ff2d47708b89919a44b8cd9c3 [file] [log] [blame]
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001/*
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05302 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
Lloyd Atkinsone53b7372017-03-22 17:16:47 -040015#define pr_fmt(fmt) "msm-dsi-panel:[%s:%d] " fmt, __func__, __LINE__
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -070016#include <linux/delay.h>
17#include <linux/slab.h>
18#include <linux/gpio.h>
19#include <linux/of_gpio.h>
Lloyd Atkinsone53b7372017-03-22 17:16:47 -040020#include <video/mipi_display.h>
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -070021
22#include "dsi_panel.h"
23#include "dsi_ctrl_hw.h"
24
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -070025/**
26 * topology is currently defined by a set of following 3 values:
27 * 1. num of layer mixers
28 * 2. num of compression encoders
29 * 3. num of interfaces
30 */
31#define TOPOLOGY_SET_LEN 3
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -070032#define MAX_TOPOLOGY 5
33
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -070034#define DSI_PANEL_DEFAULT_LABEL "Default dsi panel"
35
Alan Kwong9aa061c2016-11-06 21:17:12 -050036#define DEFAULT_MDP_TRANSFER_TIME 14000
37
Dhaval Patelf5cc5a32017-07-10 17:33:23 -070038#define DEFAULT_PANEL_JITTER_NUMERATOR 2
39#define DEFAULT_PANEL_JITTER_DENOMINATOR 1
40#define DEFAULT_PANEL_JITTER_ARRAY_SIZE 2
41#define MAX_PANEL_JITTER 10
42#define DEFAULT_PANEL_PREFILL_LINES 25
Dhaval Patel60e1ff52017-02-18 21:03:40 -080043
Rajkumar Subbiahc70dfab2017-06-16 10:46:32 -040044enum dsi_dsc_ratio_type {
45 DSC_8BPC_8BPP,
46 DSC_10BPC_8BPP,
47 DSC_12BPC_8BPP,
48 DSC_RATIO_TYPE_MAX
49};
50
Alexander Beykunac182352017-02-27 17:46:51 -050051static u32 dsi_dsc_rc_buf_thresh[] = {0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54,
52 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e};
Rajkumar Subbiahc70dfab2017-06-16 10:46:32 -040053
54/*
55 * DSC 1.1
56 * Rate control - Min QP values for each ratio type in dsi_dsc_ratio_type
57 */
58static char dsi_dsc_rc_range_min_qp_1_1[][15] = {
59 {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13},
60 {0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 17},
61 {0, 4, 9, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 21},
62 };
63
64/*
65 * DSC 1.1 SCR
66 * Rate control - Min QP values for each ratio type in dsi_dsc_ratio_type
67 */
68static char dsi_dsc_rc_range_min_qp_1_1_scr1[][15] = {
69 {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 12},
70 {0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 16},
71 {0, 4, 9, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 17, 20},
72 };
73
74/*
75 * DSC 1.1
76 * Rate control - Max QP values for each ratio type in dsi_dsc_ratio_type
77 */
78static char dsi_dsc_rc_range_max_qp_1_1[][15] = {
79 {4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15},
80 {8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 15, 16, 17, 17, 19},
81 {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 19, 20, 21, 21, 23},
82 };
83
84/*
85 * DSC 1.1 SCR
86 * Rate control - Max QP values for each ratio type in dsi_dsc_ratio_type
87 */
88static char dsi_dsc_rc_range_max_qp_1_1_scr1[][15] = {
89 {4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13},
90 {8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17},
91 {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21},
92 };
93
94/*
95 * DSC 1.1 and DSC 1.1 SCR
96 * Rate control - bpg offset values
97 */
Alexander Beykunac182352017-02-27 17:46:51 -050098static char dsi_dsc_rc_range_bpg_offset[] = {2, 0, 0, -2, -4, -6, -8, -8,
99 -8, -10, -10, -12, -12, -12, -12};
100
101int dsi_dsc_create_pps_buf_cmd(struct msm_display_dsc_info *dsc, char *buf,
102 int pps_id)
103{
104 char *bp;
105 char data;
106 int i, bpp;
107 char *dbgbp;
108
109 dbgbp = buf;
110 bp = buf;
111 /* First 7 bytes are cmd header */
112 *bp++ = 0x0A;
113 *bp++ = 1;
114 *bp++ = 0;
115 *bp++ = 0;
116 *bp++ = 10;
117 *bp++ = 0;
118 *bp++ = 128;
119
120 *bp++ = (dsc->version & 0xff); /* pps0 */
121 *bp++ = (pps_id & 0xff); /* pps1 */
122 bp++; /* pps2, reserved */
123
124 data = dsc->line_buf_depth & 0x0f;
125 data |= ((dsc->bpc & 0xf) << 4);
126 *bp++ = data; /* pps3 */
127
128 bpp = dsc->bpp;
129 bpp <<= 4; /* 4 fraction bits */
130 data = (bpp >> 8);
131 data &= 0x03; /* upper two bits */
132 data |= ((dsc->block_pred_enable & 0x1) << 5);
133 data |= ((dsc->convert_rgb & 0x1) << 4);
134 data |= ((dsc->enable_422 & 0x1) << 3);
135 data |= ((dsc->vbr_enable & 0x1) << 2);
136 *bp++ = data; /* pps4 */
137 *bp++ = (bpp & 0xff); /* pps5 */
138
139 *bp++ = ((dsc->pic_height >> 8) & 0xff); /* pps6 */
140 *bp++ = (dsc->pic_height & 0x0ff); /* pps7 */
141 *bp++ = ((dsc->pic_width >> 8) & 0xff); /* pps8 */
142 *bp++ = (dsc->pic_width & 0x0ff); /* pps9 */
143
144 *bp++ = ((dsc->slice_height >> 8) & 0xff);/* pps10 */
145 *bp++ = (dsc->slice_height & 0x0ff); /* pps11 */
146 *bp++ = ((dsc->slice_width >> 8) & 0xff); /* pps12 */
147 *bp++ = (dsc->slice_width & 0x0ff); /* pps13 */
148
149 *bp++ = ((dsc->chunk_size >> 8) & 0xff);/* pps14 */
150 *bp++ = (dsc->chunk_size & 0x0ff); /* pps15 */
151
152 *bp++ = (dsc->initial_xmit_delay >> 8) & 0x3; /* pps16, bit 0, 1 */
153 *bp++ = (dsc->initial_xmit_delay & 0xff);/* pps17 */
154
155 *bp++ = ((dsc->initial_dec_delay >> 8) & 0xff); /* pps18 */
156 *bp++ = (dsc->initial_dec_delay & 0xff);/* pps19 */
157
158 bp++; /* pps20, reserved */
159
160 *bp++ = (dsc->initial_scale_value & 0x3f); /* pps21 */
161
162 *bp++ = ((dsc->scale_increment_interval >> 8) & 0xff); /* pps22 */
163 *bp++ = (dsc->scale_increment_interval & 0xff); /* pps23 */
164
165 *bp++ = ((dsc->scale_decrement_interval >> 8) & 0xf); /* pps24 */
166 *bp++ = (dsc->scale_decrement_interval & 0x0ff);/* pps25 */
167
168 bp++; /* pps26, reserved */
169
170 *bp++ = (dsc->first_line_bpg_offset & 0x1f);/* pps27 */
171
172 *bp++ = ((dsc->nfl_bpg_offset >> 8) & 0xff);/* pps28 */
173 *bp++ = (dsc->nfl_bpg_offset & 0x0ff); /* pps29 */
174 *bp++ = ((dsc->slice_bpg_offset >> 8) & 0xff);/* pps30 */
175 *bp++ = (dsc->slice_bpg_offset & 0x0ff);/* pps31 */
176
177 *bp++ = ((dsc->initial_offset >> 8) & 0xff);/* pps32 */
178 *bp++ = (dsc->initial_offset & 0x0ff); /* pps33 */
179
180 *bp++ = ((dsc->final_offset >> 8) & 0xff);/* pps34 */
181 *bp++ = (dsc->final_offset & 0x0ff); /* pps35 */
182
183 *bp++ = (dsc->min_qp_flatness & 0x1f); /* pps36 */
184 *bp++ = (dsc->max_qp_flatness & 0x1f); /* pps37 */
185
186 *bp++ = ((dsc->rc_model_size >> 8) & 0xff);/* pps38 */
187 *bp++ = (dsc->rc_model_size & 0x0ff); /* pps39 */
188
189 *bp++ = (dsc->edge_factor & 0x0f); /* pps40 */
190
191 *bp++ = (dsc->quant_incr_limit0 & 0x1f); /* pps41 */
192 *bp++ = (dsc->quant_incr_limit1 & 0x1f); /* pps42 */
193
194 data = ((dsc->tgt_offset_hi & 0xf) << 4);
195 data |= (dsc->tgt_offset_lo & 0x0f);
196 *bp++ = data; /* pps43 */
197
198 for (i = 0; i < 14; i++)
199 *bp++ = (dsc->buf_thresh[i] & 0xff); /* pps44 - pps57 */
200
201 for (i = 0; i < 15; i++) { /* pps58 - pps87 */
202 data = (dsc->range_min_qp[i] & 0x1f);
203 data <<= 3;
204 data |= ((dsc->range_max_qp[i] >> 2) & 0x07);
205 *bp++ = data;
206 data = (dsc->range_max_qp[i] & 0x03);
207 data <<= 6;
208 data |= (dsc->range_bpg_offset[i] & 0x3f);
209 *bp++ = data;
210 }
211
212 return 128;
213}
214
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700215static int dsi_panel_vreg_get(struct dsi_panel *panel)
216{
217 int rc = 0;
218 int i;
219 struct regulator *vreg = NULL;
220
221 for (i = 0; i < panel->power_info.count; i++) {
222 vreg = devm_regulator_get(panel->parent,
223 panel->power_info.vregs[i].vreg_name);
224 rc = PTR_RET(vreg);
225 if (rc) {
226 pr_err("failed to get %s regulator\n",
227 panel->power_info.vregs[i].vreg_name);
228 goto error_put;
229 }
230 panel->power_info.vregs[i].vreg = vreg;
231 }
232
233 return rc;
234error_put:
235 for (i = i - 1; i >= 0; i--) {
236 devm_regulator_put(panel->power_info.vregs[i].vreg);
237 panel->power_info.vregs[i].vreg = NULL;
238 }
239 return rc;
240}
241
242static int dsi_panel_vreg_put(struct dsi_panel *panel)
243{
244 int rc = 0;
245 int i;
246
247 for (i = panel->power_info.count - 1; i >= 0; i--)
248 devm_regulator_put(panel->power_info.vregs[i].vreg);
249
250 return rc;
251}
252
253static int dsi_panel_gpio_request(struct dsi_panel *panel)
254{
255 int rc = 0;
256 struct dsi_panel_reset_config *r_config = &panel->reset_config;
257
258 if (gpio_is_valid(r_config->reset_gpio)) {
259 rc = gpio_request(r_config->reset_gpio, "reset_gpio");
260 if (rc) {
261 pr_err("request for reset_gpio failed, rc=%d\n", rc);
262 goto error;
263 }
264 }
265
266 if (gpio_is_valid(r_config->disp_en_gpio)) {
267 rc = gpio_request(r_config->disp_en_gpio, "disp_en_gpio");
268 if (rc) {
269 pr_err("request for disp_en_gpio failed, rc=%d\n", rc);
270 goto error_release_reset;
271 }
272 }
273
274 if (gpio_is_valid(panel->bl_config.en_gpio)) {
275 rc = gpio_request(panel->bl_config.en_gpio, "bklt_en_gpio");
276 if (rc) {
277 pr_err("request for bklt_en_gpio failed, rc=%d\n", rc);
278 goto error_release_disp_en;
279 }
280 }
281
Padmanabhan Komanduruedfe6ff2016-12-19 12:37:04 +0530282 if (gpio_is_valid(r_config->lcd_mode_sel_gpio)) {
283 rc = gpio_request(r_config->lcd_mode_sel_gpio, "mode_gpio");
284 if (rc) {
285 pr_err("request for mode_gpio failed, rc=%d\n", rc);
286 goto error_release_mode_sel;
287 }
288 }
289
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700290 goto error;
Padmanabhan Komanduruedfe6ff2016-12-19 12:37:04 +0530291error_release_mode_sel:
292 if (gpio_is_valid(panel->bl_config.en_gpio))
293 gpio_free(panel->bl_config.en_gpio);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700294error_release_disp_en:
295 if (gpio_is_valid(r_config->disp_en_gpio))
296 gpio_free(r_config->disp_en_gpio);
297error_release_reset:
298 if (gpio_is_valid(r_config->reset_gpio))
299 gpio_free(r_config->reset_gpio);
300error:
301 return rc;
302}
303
304static int dsi_panel_gpio_release(struct dsi_panel *panel)
305{
306 int rc = 0;
307 struct dsi_panel_reset_config *r_config = &panel->reset_config;
308
309 if (gpio_is_valid(r_config->reset_gpio))
310 gpio_free(r_config->reset_gpio);
311
312 if (gpio_is_valid(r_config->disp_en_gpio))
313 gpio_free(r_config->disp_en_gpio);
314
Ajay Singh Parmard687e092016-06-27 11:46:54 -0700315 if (gpio_is_valid(panel->bl_config.en_gpio))
316 gpio_free(panel->bl_config.en_gpio);
317
Padmanabhan Komanduruedfe6ff2016-12-19 12:37:04 +0530318 if (gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio))
319 gpio_free(panel->reset_config.lcd_mode_sel_gpio);
320
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700321 return rc;
322}
323
324static int dsi_panel_reset(struct dsi_panel *panel)
325{
326 int rc = 0;
327 struct dsi_panel_reset_config *r_config = &panel->reset_config;
328 int i;
329
Ajay Singh Parmar4c4cade2016-07-21 15:50:50 -0700330 if (gpio_is_valid(panel->reset_config.disp_en_gpio)) {
Clarence Ip9de0bbc2017-03-02 09:56:06 -0500331 rc = gpio_direction_output(panel->reset_config.disp_en_gpio, 1);
Ajay Singh Parmar4c4cade2016-07-21 15:50:50 -0700332 if (rc) {
333 pr_err("unable to set dir for disp gpio rc=%d\n", rc);
334 goto exit;
335 }
336 }
337
338 if (r_config->count) {
339 rc = gpio_direction_output(r_config->reset_gpio,
340 r_config->sequence[0].level);
341 if (rc) {
342 pr_err("unable to set dir for rst gpio rc=%d\n", rc);
343 goto exit;
344 }
345 }
346
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700347 for (i = 0; i < r_config->count; i++) {
348 gpio_set_value(r_config->reset_gpio,
349 r_config->sequence[i].level);
350
351
352 if (r_config->sequence[i].sleep_ms)
353 usleep_range(r_config->sequence[i].sleep_ms * 1000,
354 r_config->sequence[i].sleep_ms * 1000);
355 }
356
Ajay Singh Parmar4c4cade2016-07-21 15:50:50 -0700357 if (gpio_is_valid(panel->bl_config.en_gpio)) {
358 rc = gpio_direction_output(panel->bl_config.en_gpio, 1);
359 if (rc)
360 pr_err("unable to set dir for bklt gpio rc=%d\n", rc);
361 }
Padmanabhan Komanduruedfe6ff2016-12-19 12:37:04 +0530362
363 if (gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio)) {
364 bool out = true;
365
366 if ((panel->reset_config.mode_sel_state == MODE_SEL_DUAL_PORT)
367 || (panel->reset_config.mode_sel_state
368 == MODE_GPIO_LOW))
369 out = false;
370 else if ((panel->reset_config.mode_sel_state
371 == MODE_SEL_SINGLE_PORT) ||
372 (panel->reset_config.mode_sel_state
373 == MODE_GPIO_HIGH))
374 out = true;
375
376 rc = gpio_direction_output(
377 panel->reset_config.lcd_mode_sel_gpio, out);
378 if (rc)
379 pr_err("unable to set dir for mode gpio rc=%d\n", rc);
380 }
Ajay Singh Parmar4c4cade2016-07-21 15:50:50 -0700381exit:
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700382 return rc;
383}
384
385static int dsi_panel_set_pinctrl_state(struct dsi_panel *panel, bool enable)
386{
387 int rc = 0;
388 struct pinctrl_state *state;
389
390 if (enable)
391 state = panel->pinctrl.active;
392 else
393 state = panel->pinctrl.suspend;
394
395 rc = pinctrl_select_state(panel->pinctrl.pinctrl, state);
396 if (rc)
397 pr_err("[%s] failed to set pin state, rc=%d\n", panel->name,
398 rc);
399
400 return rc;
401}
402
403
404static int dsi_panel_power_on(struct dsi_panel *panel)
405{
406 int rc = 0;
407
408 rc = dsi_pwr_enable_regulator(&panel->power_info, true);
409 if (rc) {
410 pr_err("[%s] failed to enable vregs, rc=%d\n", panel->name, rc);
Lloyd Atkinsone1762542016-07-13 17:27:14 -0400411 goto exit;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700412 }
413
414 rc = dsi_panel_set_pinctrl_state(panel, true);
415 if (rc) {
416 pr_err("[%s] failed to set pinctrl, rc=%d\n", panel->name, rc);
417 goto error_disable_vregs;
418 }
419
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700420 rc = dsi_panel_reset(panel);
421 if (rc) {
422 pr_err("[%s] failed to reset panel, rc=%d\n", panel->name, rc);
Lloyd Atkinsone1762542016-07-13 17:27:14 -0400423 goto error_disable_gpio;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700424 }
425
Lloyd Atkinsone1762542016-07-13 17:27:14 -0400426 goto exit;
427
428error_disable_gpio:
429 if (gpio_is_valid(panel->reset_config.disp_en_gpio))
430 gpio_set_value(panel->reset_config.disp_en_gpio, 0);
431
432 if (gpio_is_valid(panel->bl_config.en_gpio))
433 gpio_set_value(panel->bl_config.en_gpio, 0);
434
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700435 (void)dsi_panel_set_pinctrl_state(panel, false);
Lloyd Atkinsone1762542016-07-13 17:27:14 -0400436
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700437error_disable_vregs:
438 (void)dsi_pwr_enable_regulator(&panel->power_info, false);
Lloyd Atkinsone1762542016-07-13 17:27:14 -0400439
440exit:
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700441 return rc;
442}
443
444static int dsi_panel_power_off(struct dsi_panel *panel)
445{
446 int rc = 0;
447
448 if (gpio_is_valid(panel->reset_config.disp_en_gpio))
449 gpio_set_value(panel->reset_config.disp_en_gpio, 0);
450
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700451 if (gpio_is_valid(panel->reset_config.reset_gpio))
452 gpio_set_value(panel->reset_config.reset_gpio, 0);
453
Padmanabhan Komanduruedfe6ff2016-12-19 12:37:04 +0530454 if (gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio))
455 gpio_set_value(panel->reset_config.lcd_mode_sel_gpio, 0);
456
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700457 rc = dsi_panel_set_pinctrl_state(panel, false);
458 if (rc) {
459 pr_err("[%s] failed set pinctrl state, rc=%d\n", panel->name,
460 rc);
461 }
462
463 rc = dsi_pwr_enable_regulator(&panel->power_info, false);
464 if (rc)
465 pr_err("[%s] failed to enable vregs, rc=%d\n", panel->name, rc);
466
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700467 return rc;
468}
469static int dsi_panel_tx_cmd_set(struct dsi_panel *panel,
470 enum dsi_cmd_set_type type)
471{
472 int rc = 0, i = 0;
473 ssize_t len;
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -0700474 struct dsi_cmd_desc *cmds;
475 u32 count;
476 enum dsi_cmd_set_state state;
477 struct dsi_display_mode *mode;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700478 const struct mipi_dsi_host_ops *ops = panel->host->ops;
479
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -0700480 if (!panel || !panel->cur_mode)
481 return -EINVAL;
482
483 mode = panel->cur_mode;
484
485 cmds = mode->priv_info->cmd_sets[type].cmds;
486 count = mode->priv_info->cmd_sets[type].count;
487 state = mode->priv_info->cmd_sets[type].state;
488
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700489 if (count == 0) {
490 pr_debug("[%s] No commands to be sent for state(%d)\n",
491 panel->name, type);
492 goto error;
493 }
494
495 for (i = 0; i < count; i++) {
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700496 if (state == DSI_CMD_SET_STATE_LP)
497 cmds->msg.flags |= MIPI_DSI_MSG_USE_LPM;
498
Vara Reddy326612b2017-09-20 04:41:10 -0700499 if (cmds->last_command)
500 cmds->msg.flags |= MIPI_DSI_MSG_LASTCOMMAND;
501
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700502 len = ops->transfer(panel->host, &cmds->msg);
503 if (len < 0) {
504 rc = len;
505 pr_err("failed to set cmds(%d), rc=%d\n", type, rc);
506 goto error;
507 }
508 if (cmds->post_wait_ms)
Shashank Babu Chinta Venkatafd4d7032017-11-16 16:24:23 -0800509 usleep_range(cmds->post_wait_ms*1000,
510 ((cmds->post_wait_ms*1000)+10));
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700511 cmds++;
512 }
513error:
514 return rc;
515}
516
517static int dsi_panel_pinctrl_deinit(struct dsi_panel *panel)
518{
519 int rc = 0;
520
521 devm_pinctrl_put(panel->pinctrl.pinctrl);
522
523 return rc;
524}
525
526static int dsi_panel_pinctrl_init(struct dsi_panel *panel)
527{
528 int rc = 0;
529
530 /* TODO: pinctrl is defined in dsi dt node */
531 panel->pinctrl.pinctrl = devm_pinctrl_get(panel->parent);
532 if (IS_ERR_OR_NULL(panel->pinctrl.pinctrl)) {
533 rc = PTR_ERR(panel->pinctrl.pinctrl);
534 pr_err("failed to get pinctrl, rc=%d\n", rc);
535 goto error;
536 }
537
538 panel->pinctrl.active = pinctrl_lookup_state(panel->pinctrl.pinctrl,
539 "panel_active");
540 if (IS_ERR_OR_NULL(panel->pinctrl.active)) {
541 rc = PTR_ERR(panel->pinctrl.active);
542 pr_err("failed to get pinctrl active state, rc=%d\n", rc);
543 goto error;
544 }
545
546 panel->pinctrl.suspend =
547 pinctrl_lookup_state(panel->pinctrl.pinctrl, "panel_suspend");
548
549 if (IS_ERR_OR_NULL(panel->pinctrl.suspend)) {
550 rc = PTR_ERR(panel->pinctrl.suspend);
551 pr_err("failed to get pinctrl suspend state, rc=%d\n", rc);
552 goto error;
553 }
554
555error:
556 return rc;
557}
558
Dhaval Patel6a529532016-09-27 16:33:24 -0700559#ifdef CONFIG_LEDS_TRIGGERS
560static int dsi_panel_led_bl_register(struct dsi_panel *panel,
561 struct dsi_backlight_config *bl)
562{
563 int rc = 0;
564
565 led_trigger_register_simple("bkl-trigger", &bl->wled);
566
567 /* LED APIs don't tell us directly whether a classdev has yet
568 * been registered to service this trigger. Until classdev is
569 * registered, calling led_trigger has no effect, and doesn't
570 * fail. Classdevs are associated with any registered triggers
571 * when they do register, but that is too late for FBCon.
572 * Check the cdev list directly and defer if appropriate.
573 */
574 if (!bl->wled) {
575 pr_err("[%s] backlight registration failed\n", panel->name);
576 rc = -EINVAL;
577 } else {
578 read_lock(&bl->wled->leddev_list_lock);
579 if (list_empty(&bl->wled->led_cdevs))
580 rc = -EPROBE_DEFER;
581 read_unlock(&bl->wled->leddev_list_lock);
582
583 if (rc) {
584 pr_info("[%s] backlight %s not ready, defer probe\n",
585 panel->name, bl->wled->name);
586 led_trigger_unregister_simple(bl->wled);
587 }
588 }
589
590 return rc;
591}
592#else
593static int dsi_panel_led_bl_register(struct dsi_panel *panel,
594 struct dsi_backlight_config *bl)
595{
596 return 0;
597}
598#endif
599
Ingrid Gallardo354c1172017-04-21 15:40:16 -0700600static int dsi_panel_update_backlight(struct dsi_panel *panel,
601 u32 bl_lvl)
602{
603 int rc = 0;
604 struct mipi_dsi_device *dsi;
605
606 if (!panel || (bl_lvl > 0xffff)) {
607 pr_err("invalid params\n");
608 return -EINVAL;
609 }
610
611 dsi = &panel->mipi_device;
612
613 mutex_lock(&panel->panel_lock);
614
615 rc = mipi_dsi_dcs_set_display_brightness(dsi, bl_lvl);
616 if (rc < 0)
617 pr_err("failed to update dcs backlight:%d\n", bl_lvl);
618
619 mutex_unlock(&panel->panel_lock);
620 return rc;
621}
622
Vishnuvardhan Prodduturi75b96802016-10-17 18:45:55 +0530623int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl)
624{
625 int rc = 0;
626 struct dsi_backlight_config *bl = &panel->bl_config;
627
Ingrid Gallardo354c1172017-04-21 15:40:16 -0700628 pr_debug("backlight type:%d lvl:%d\n", bl->type, bl_lvl);
Vishnuvardhan Prodduturi75b96802016-10-17 18:45:55 +0530629 switch (bl->type) {
630 case DSI_BACKLIGHT_WLED:
631 led_trigger_event(bl->wled, bl_lvl);
632 break;
Ingrid Gallardo354c1172017-04-21 15:40:16 -0700633 case DSI_BACKLIGHT_DCS:
634 dsi_panel_update_backlight(panel, bl_lvl);
635 break;
Vishnuvardhan Prodduturi75b96802016-10-17 18:45:55 +0530636 default:
637 pr_err("Backlight type(%d) not supported\n", bl->type);
638 rc = -ENOTSUPP;
639 }
640
641 return rc;
642}
643
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700644static int dsi_panel_bl_register(struct dsi_panel *panel)
645{
646 int rc = 0;
647 struct dsi_backlight_config *bl = &panel->bl_config;
648
649 switch (bl->type) {
650 case DSI_BACKLIGHT_WLED:
Dhaval Patel6a529532016-09-27 16:33:24 -0700651 rc = dsi_panel_led_bl_register(panel, bl);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700652 break;
Ingrid Gallardo354c1172017-04-21 15:40:16 -0700653 case DSI_BACKLIGHT_DCS:
654 break;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700655 default:
656 pr_err("Backlight type(%d) not supported\n", bl->type);
657 rc = -ENOTSUPP;
658 goto error;
659 }
660
661error:
662 return rc;
663}
664
665static int dsi_panel_bl_unregister(struct dsi_panel *panel)
666{
667 int rc = 0;
668 struct dsi_backlight_config *bl = &panel->bl_config;
669
670 switch (bl->type) {
671 case DSI_BACKLIGHT_WLED:
672 led_trigger_unregister_simple(bl->wled);
673 break;
Ingrid Gallardo354c1172017-04-21 15:40:16 -0700674 case DSI_BACKLIGHT_DCS:
675 break;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700676 default:
677 pr_err("Backlight type(%d) not supported\n", bl->type);
678 rc = -ENOTSUPP;
679 goto error;
680 }
681
682error:
683 return rc;
684}
685static int dsi_panel_parse_timing(struct dsi_mode_info *mode,
686 struct device_node *of_node)
687{
688 int rc = 0;
Vara Reddy812bd722017-09-20 07:19:19 -0700689 u64 tmp64;
690 struct dsi_display_mode *display_mode;
691
692 display_mode = container_of(mode, struct dsi_display_mode, timing);
693
694 rc = of_property_read_u64(of_node,
695 "qcom,mdss-dsi-panel-clockrate", &tmp64);
696 if (rc == -EOVERFLOW) {
697 tmp64 = 0;
698 rc = of_property_read_u32(of_node,
699 "qcom,mdss-dsi-panel-clockrate", (u32 *)&tmp64);
700 }
701
702 mode->clk_rate_hz = !rc ? tmp64 : 0;
703 display_mode->priv_info->clk_rate_hz = mode->clk_rate_hz;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700704
705 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-framerate",
706 &mode->refresh_rate);
707 if (rc) {
708 pr_err("failed to read qcom,mdss-dsi-panel-framerate, rc=%d\n",
709 rc);
710 goto error;
711 }
712
713 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-width",
714 &mode->h_active);
715 if (rc) {
716 pr_err("failed to read qcom,mdss-dsi-panel-width, rc=%d\n", rc);
717 goto error;
718 }
719
720 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-front-porch",
721 &mode->h_front_porch);
722 if (rc) {
723 pr_err("failed to read qcom,mdss-dsi-h-front-porch, rc=%d\n",
724 rc);
725 goto error;
726 }
727
728 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-back-porch",
729 &mode->h_back_porch);
730 if (rc) {
731 pr_err("failed to read qcom,mdss-dsi-h-back-porch, rc=%d\n",
732 rc);
733 goto error;
734 }
735
736 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-pulse-width",
737 &mode->h_sync_width);
738 if (rc) {
739 pr_err("failed to read qcom,mdss-dsi-h-pulse-width, rc=%d\n",
740 rc);
741 goto error;
742 }
743
744 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-sync-skew",
745 &mode->h_skew);
746 if (rc)
747 pr_err("qcom,mdss-dsi-h-sync-skew is not defined, rc=%d\n", rc);
748
Dhaval Patel35ec17e2017-10-17 22:20:37 -0700749 pr_debug("panel horz active:%d front_portch:%d back_porch:%d sync_skew:%d\n",
750 mode->h_active, mode->h_front_porch, mode->h_back_porch,
751 mode->h_sync_width);
752
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700753 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-height",
754 &mode->v_active);
755 if (rc) {
756 pr_err("failed to read qcom,mdss-dsi-panel-height, rc=%d\n",
757 rc);
758 goto error;
759 }
760
761 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-v-back-porch",
762 &mode->v_back_porch);
763 if (rc) {
764 pr_err("failed to read qcom,mdss-dsi-v-back-porch, rc=%d\n",
765 rc);
766 goto error;
767 }
768
769 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-v-front-porch",
770 &mode->v_front_porch);
771 if (rc) {
772 pr_err("failed to read qcom,mdss-dsi-v-back-porch, rc=%d\n",
773 rc);
774 goto error;
775 }
776
777 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-v-pulse-width",
778 &mode->v_sync_width);
779 if (rc) {
780 pr_err("failed to read qcom,mdss-dsi-v-pulse-width, rc=%d\n",
781 rc);
782 goto error;
783 }
Dhaval Patel35ec17e2017-10-17 22:20:37 -0700784 pr_debug("panel vert active:%d front_portch:%d back_porch:%d pulse_width:%d\n",
785 mode->v_active, mode->v_front_porch, mode->v_back_porch,
786 mode->v_sync_width);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700787
788error:
789 return rc;
790}
791
792static int dsi_panel_parse_pixel_format(struct dsi_host_common_cfg *host,
793 struct device_node *of_node,
794 const char *name)
795{
796 int rc = 0;
797 u32 bpp = 0;
798 enum dsi_pixel_format fmt;
799 const char *packing;
800
801 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-bpp", &bpp);
802 if (rc) {
803 pr_err("[%s] failed to read qcom,mdss-dsi-bpp, rc=%d\n",
804 name, rc);
805 return rc;
806 }
807
808 switch (bpp) {
809 case 3:
810 fmt = DSI_PIXEL_FORMAT_RGB111;
811 break;
812 case 8:
813 fmt = DSI_PIXEL_FORMAT_RGB332;
814 break;
815 case 12:
816 fmt = DSI_PIXEL_FORMAT_RGB444;
817 break;
818 case 16:
819 fmt = DSI_PIXEL_FORMAT_RGB565;
820 break;
821 case 18:
822 fmt = DSI_PIXEL_FORMAT_RGB666;
823 break;
824 case 24:
825 default:
826 fmt = DSI_PIXEL_FORMAT_RGB888;
827 break;
828 }
829
830 if (fmt == DSI_PIXEL_FORMAT_RGB666) {
831 packing = of_get_property(of_node,
832 "qcom,mdss-dsi-pixel-packing",
833 NULL);
834 if (packing && !strcmp(packing, "loose"))
835 fmt = DSI_PIXEL_FORMAT_RGB666_LOOSE;
836 }
837
838 host->dst_format = fmt;
839 return rc;
840}
841
842static int dsi_panel_parse_lane_states(struct dsi_host_common_cfg *host,
843 struct device_node *of_node,
844 const char *name)
845{
846 int rc = 0;
847 bool lane_enabled;
848
849 lane_enabled = of_property_read_bool(of_node,
850 "qcom,mdss-dsi-lane-0-state");
851 host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_0 : 0);
852
853 lane_enabled = of_property_read_bool(of_node,
854 "qcom,mdss-dsi-lane-1-state");
855 host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_1 : 0);
856
857 lane_enabled = of_property_read_bool(of_node,
858 "qcom,mdss-dsi-lane-2-state");
859 host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_2 : 0);
860
861 lane_enabled = of_property_read_bool(of_node,
862 "qcom,mdss-dsi-lane-3-state");
863 host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_3 : 0);
864
865 if (host->data_lanes == 0) {
866 pr_err("[%s] No data lanes are enabled, rc=%d\n", name, rc);
867 rc = -EINVAL;
868 }
869
870 return rc;
871}
872
873static int dsi_panel_parse_color_swap(struct dsi_host_common_cfg *host,
874 struct device_node *of_node,
875 const char *name)
876{
877 int rc = 0;
878 const char *swap_mode;
879
880 swap_mode = of_get_property(of_node, "qcom,mdss-dsi-color-order", NULL);
881 if (swap_mode) {
882 if (!strcmp(swap_mode, "rgb_swap_rgb")) {
883 host->swap_mode = DSI_COLOR_SWAP_RGB;
884 } else if (!strcmp(swap_mode, "rgb_swap_rbg")) {
885 host->swap_mode = DSI_COLOR_SWAP_RBG;
886 } else if (!strcmp(swap_mode, "rgb_swap_brg")) {
887 host->swap_mode = DSI_COLOR_SWAP_BRG;
888 } else if (!strcmp(swap_mode, "rgb_swap_grb")) {
889 host->swap_mode = DSI_COLOR_SWAP_GRB;
890 } else if (!strcmp(swap_mode, "rgb_swap_gbr")) {
891 host->swap_mode = DSI_COLOR_SWAP_GBR;
892 } else {
893 pr_err("[%s] Unrecognized color order-%s\n",
894 name, swap_mode);
895 rc = -EINVAL;
896 }
897 } else {
898 pr_debug("[%s] Falling back to default color order\n", name);
899 host->swap_mode = DSI_COLOR_SWAP_RGB;
900 }
901
902 /* bit swap on color channel is not defined in dt */
903 host->bit_swap_red = false;
904 host->bit_swap_green = false;
905 host->bit_swap_blue = false;
906 return rc;
907}
908
909static int dsi_panel_parse_triggers(struct dsi_host_common_cfg *host,
910 struct device_node *of_node,
911 const char *name)
912{
913 const char *trig;
914 int rc = 0;
915
916 trig = of_get_property(of_node, "qcom,mdss-dsi-mdp-trigger", NULL);
917 if (trig) {
918 if (!strcmp(trig, "none")) {
919 host->mdp_cmd_trigger = DSI_TRIGGER_NONE;
920 } else if (!strcmp(trig, "trigger_te")) {
921 host->mdp_cmd_trigger = DSI_TRIGGER_TE;
922 } else if (!strcmp(trig, "trigger_sw")) {
923 host->mdp_cmd_trigger = DSI_TRIGGER_SW;
924 } else if (!strcmp(trig, "trigger_sw_te")) {
925 host->mdp_cmd_trigger = DSI_TRIGGER_SW_TE;
926 } else {
927 pr_err("[%s] Unrecognized mdp trigger type (%s)\n",
928 name, trig);
929 rc = -EINVAL;
930 }
931
932 } else {
933 pr_debug("[%s] Falling back to default MDP trigger\n",
934 name);
935 host->mdp_cmd_trigger = DSI_TRIGGER_SW;
936 }
937
938 trig = of_get_property(of_node, "qcom,mdss-dsi-dma-trigger", NULL);
939 if (trig) {
940 if (!strcmp(trig, "none")) {
941 host->dma_cmd_trigger = DSI_TRIGGER_NONE;
942 } else if (!strcmp(trig, "trigger_te")) {
943 host->dma_cmd_trigger = DSI_TRIGGER_TE;
944 } else if (!strcmp(trig, "trigger_sw")) {
945 host->dma_cmd_trigger = DSI_TRIGGER_SW;
946 } else if (!strcmp(trig, "trigger_sw_seof")) {
947 host->dma_cmd_trigger = DSI_TRIGGER_SW_SEOF;
948 } else if (!strcmp(trig, "trigger_sw_te")) {
949 host->dma_cmd_trigger = DSI_TRIGGER_SW_TE;
950 } else {
951 pr_err("[%s] Unrecognized mdp trigger type (%s)\n",
952 name, trig);
953 rc = -EINVAL;
954 }
955
956 } else {
957 pr_debug("[%s] Falling back to default MDP trigger\n", name);
958 host->dma_cmd_trigger = DSI_TRIGGER_SW;
959 }
960
Benjamin Chanfb7c9a62017-08-18 16:43:00 -0400961 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-te-pin-select",
962 &host->te_mode);
963 if (rc) {
964 pr_warn("[%s] fallback to default te-pin-select\n", name);
965 host->te_mode = 1;
966 rc = 0;
967 }
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -0700968
969 return rc;
970}
971
972static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host,
973 struct device_node *of_node,
974 const char *name)
975{
976 u32 val = 0;
977 int rc = 0;
978
979 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-t-clk-post", &val);
980 if (rc) {
981 pr_debug("[%s] Fallback to default t_clk_post value\n", name);
982 host->t_clk_post = 0x03;
983 } else {
984 host->t_clk_post = val;
985 pr_debug("[%s] t_clk_post = %d\n", name, val);
986 }
987
988 val = 0;
989 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-t-clk-pre", &val);
990 if (rc) {
991 pr_debug("[%s] Fallback to default t_clk_pre value\n", name);
992 host->t_clk_pre = 0x24;
993 } else {
994 host->t_clk_pre = val;
995 pr_debug("[%s] t_clk_pre = %d\n", name, val);
996 }
997
998 host->ignore_rx_eot = of_property_read_bool(of_node,
999 "qcom,mdss-dsi-rx-eot-ignore");
1000
1001 host->append_tx_eot = of_property_read_bool(of_node,
1002 "qcom,mdss-dsi-tx-eot-append");
1003
1004 return 0;
1005}
1006
1007static int dsi_panel_parse_host_config(struct dsi_panel *panel,
1008 struct device_node *of_node)
1009{
1010 int rc = 0;
1011
1012 rc = dsi_panel_parse_pixel_format(&panel->host_config, of_node,
1013 panel->name);
1014 if (rc) {
1015 pr_err("[%s] failed to get pixel format, rc=%d\n",
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001016 panel->name, rc);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001017 goto error;
1018 }
1019
1020 rc = dsi_panel_parse_lane_states(&panel->host_config, of_node,
1021 panel->name);
1022 if (rc) {
1023 pr_err("[%s] failed to parse lane states, rc=%d\n",
1024 panel->name, rc);
1025 goto error;
1026 }
1027
1028 rc = dsi_panel_parse_color_swap(&panel->host_config, of_node,
1029 panel->name);
1030 if (rc) {
1031 pr_err("[%s] failed to parse color swap config, rc=%d\n",
1032 panel->name, rc);
1033 goto error;
1034 }
1035
1036 rc = dsi_panel_parse_triggers(&panel->host_config, of_node,
1037 panel->name);
1038 if (rc) {
1039 pr_err("[%s] failed to parse triggers, rc=%d\n",
1040 panel->name, rc);
1041 goto error;
1042 }
1043
1044 rc = dsi_panel_parse_misc_host_config(&panel->host_config, of_node,
1045 panel->name);
1046 if (rc) {
1047 pr_err("[%s] failed to parse misc host config, rc=%d\n",
1048 panel->name, rc);
1049 goto error;
1050 }
1051
1052error:
1053 return rc;
1054}
1055
1056static int dsi_panel_parse_dfps_caps(struct dsi_dfps_capabilities *dfps_caps,
1057 struct device_node *of_node,
1058 const char *name)
1059{
1060 int rc = 0;
1061 bool supported = false;
1062 const char *type;
1063 u32 val = 0;
1064
1065 supported = of_property_read_bool(of_node,
1066 "qcom,mdss-dsi-pan-enable-dynamic-fps");
1067
1068 if (!supported) {
1069 pr_debug("[%s] DFPS is not supported\n", name);
1070 dfps_caps->dfps_support = false;
1071 } else {
1072
1073 type = of_get_property(of_node,
1074 "qcom,mdss-dsi-pan-fps-update",
1075 NULL);
1076 if (!type) {
1077 pr_err("[%s] dfps type not defined\n", name);
1078 rc = -EINVAL;
1079 goto error;
1080 } else if (!strcmp(type, "dfps_suspend_resume_mode")) {
1081 dfps_caps->type = DSI_DFPS_SUSPEND_RESUME;
1082 } else if (!strcmp(type, "dfps_immediate_clk_mode")) {
1083 dfps_caps->type = DSI_DFPS_IMMEDIATE_CLK;
1084 } else if (!strcmp(type, "dfps_immediate_porch_mode_hfp")) {
1085 dfps_caps->type = DSI_DFPS_IMMEDIATE_HFP;
1086 } else if (!strcmp(type, "dfps_immediate_porch_mode_vfp")) {
1087 dfps_caps->type = DSI_DFPS_IMMEDIATE_VFP;
1088 } else {
1089 pr_err("[%s] dfps type is not recognized\n", name);
1090 rc = -EINVAL;
1091 goto error;
1092 }
1093
1094 rc = of_property_read_u32(of_node,
1095 "qcom,mdss-dsi-min-refresh-rate",
1096 &val);
1097 if (rc) {
1098 pr_err("[%s] Min refresh rate is not defined\n", name);
1099 rc = -EINVAL;
1100 goto error;
1101 }
1102 dfps_caps->min_refresh_rate = val;
1103
1104 rc = of_property_read_u32(of_node,
1105 "qcom,mdss-dsi-max-refresh-rate",
1106 &val);
1107 if (rc) {
1108 pr_debug("[%s] Using default refresh rate\n", name);
1109 rc = of_property_read_u32(of_node,
1110 "qcom,mdss-dsi-panel-framerate",
1111 &val);
1112 if (rc) {
1113 pr_err("[%s] max refresh rate is not defined\n",
1114 name);
1115 rc = -EINVAL;
1116 goto error;
1117 }
1118 }
1119 dfps_caps->max_refresh_rate = val;
1120
1121 if (dfps_caps->min_refresh_rate > dfps_caps->max_refresh_rate) {
1122 pr_err("[%s] min rate > max rate\n", name);
1123 rc = -EINVAL;
1124 }
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07001125
1126 pr_debug("[%s] DFPS is supported %d-%d, mode %d\n", name,
1127 dfps_caps->min_refresh_rate,
1128 dfps_caps->max_refresh_rate,
1129 dfps_caps->type);
1130 dfps_caps->dfps_support = true;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001131 }
1132
1133error:
1134 return rc;
1135}
1136
1137static int dsi_panel_parse_video_host_config(struct dsi_video_engine_cfg *cfg,
1138 struct device_node *of_node,
1139 const char *name)
1140{
1141 int rc = 0;
1142 const char *traffic_mode;
1143 u32 vc_id = 0;
1144 u32 val = 0;
1145
1146 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-sync-pulse", &val);
1147 if (rc) {
1148 pr_debug("[%s] fallback to default h-sync-pulse\n", name);
1149 cfg->pulse_mode_hsa_he = false;
1150 } else if (val == 1) {
1151 cfg->pulse_mode_hsa_he = true;
1152 } else if (val == 0) {
1153 cfg->pulse_mode_hsa_he = false;
1154 } else {
1155 pr_err("[%s] Unrecognized value for mdss-dsi-h-sync-pulse\n",
1156 name);
1157 rc = -EINVAL;
1158 goto error;
1159 }
1160
1161 cfg->hfp_lp11_en = of_property_read_bool(of_node,
1162 "qcom,mdss-dsi-hfp-power-mode");
1163
1164 cfg->hbp_lp11_en = of_property_read_bool(of_node,
1165 "qcom,mdss-dsi-hbp-power-mode");
1166
1167 cfg->hsa_lp11_en = of_property_read_bool(of_node,
1168 "qcom,mdss-dsi-hsa-power-mode");
1169
1170 cfg->last_line_interleave_en = of_property_read_bool(of_node,
1171 "qcom,mdss-dsi-last-line-interleave");
1172
1173 cfg->eof_bllp_lp11_en = of_property_read_bool(of_node,
1174 "qcom,mdss-dsi-bllp-eof-power-mode");
1175
1176 cfg->bllp_lp11_en = of_property_read_bool(of_node,
1177 "qcom,mdss-dsi-bllp-power-mode");
1178
1179 traffic_mode = of_get_property(of_node,
1180 "qcom,mdss-dsi-traffic-mode",
1181 NULL);
1182 if (!traffic_mode) {
1183 pr_debug("[%s] Falling back to default traffic mode\n", name);
1184 cfg->traffic_mode = DSI_VIDEO_TRAFFIC_SYNC_PULSES;
1185 } else if (!strcmp(traffic_mode, "non_burst_sync_pulse")) {
1186 cfg->traffic_mode = DSI_VIDEO_TRAFFIC_SYNC_PULSES;
1187 } else if (!strcmp(traffic_mode, "non_burst_sync_event")) {
1188 cfg->traffic_mode = DSI_VIDEO_TRAFFIC_SYNC_START_EVENTS;
1189 } else if (!strcmp(traffic_mode, "burst_mode")) {
1190 cfg->traffic_mode = DSI_VIDEO_TRAFFIC_BURST_MODE;
1191 } else {
1192 pr_err("[%s] Unrecognized traffic mode-%s\n", name,
1193 traffic_mode);
1194 rc = -EINVAL;
1195 goto error;
1196 }
1197
1198 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-virtual-channel-id",
1199 &vc_id);
1200 if (rc) {
1201 pr_debug("[%s] Fallback to default vc id\n", name);
1202 cfg->vc_id = 0;
1203 } else {
1204 cfg->vc_id = vc_id;
1205 }
1206
1207error:
1208 return rc;
1209}
1210
1211static int dsi_panel_parse_cmd_host_config(struct dsi_cmd_engine_cfg *cfg,
1212 struct device_node *of_node,
1213 const char *name)
1214{
1215 u32 val = 0;
1216 int rc = 0;
1217
1218 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-wr-mem-start", &val);
1219 if (rc) {
1220 pr_debug("[%s] Fallback to default wr-mem-start\n", name);
1221 cfg->wr_mem_start = 0x2C;
1222 } else {
1223 cfg->wr_mem_start = val;
1224 }
1225
1226 val = 0;
1227 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-wr-mem-continue",
1228 &val);
1229 if (rc) {
1230 pr_debug("[%s] Fallback to default wr-mem-continue\n", name);
1231 cfg->wr_mem_continue = 0x3C;
1232 } else {
1233 cfg->wr_mem_continue = val;
1234 }
1235
1236 /* TODO: fix following */
1237 cfg->max_cmd_packets_interleave = 0;
1238
1239 val = 0;
1240 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-te-dcs-command",
1241 &val);
1242 if (rc) {
1243 pr_debug("[%s] fallback to default te-dcs-cmd\n", name);
1244 cfg->insert_dcs_command = true;
1245 } else if (val == 1) {
1246 cfg->insert_dcs_command = true;
1247 } else if (val == 0) {
1248 cfg->insert_dcs_command = false;
1249 } else {
1250 pr_err("[%s] Unrecognized value for mdss-dsi-te-dcs-command\n",
1251 name);
1252 rc = -EINVAL;
1253 goto error;
1254 }
1255
Alan Kwong9aa061c2016-11-06 21:17:12 -05001256 if (of_property_read_u32(of_node, "qcom,mdss-mdp-transfer-time-us",
1257 &val)) {
1258 pr_debug("[%s] Fallback to default transfer-time-us\n", name);
1259 cfg->mdp_transfer_time_us = DEFAULT_MDP_TRANSFER_TIME;
1260 } else {
1261 cfg->mdp_transfer_time_us = val;
1262 }
1263
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001264error:
1265 return rc;
1266}
1267
1268static int dsi_panel_parse_panel_mode(struct dsi_panel *panel,
1269 struct device_node *of_node)
1270{
1271 int rc = 0;
1272 enum dsi_op_mode panel_mode;
1273 const char *mode;
1274
1275 mode = of_get_property(of_node, "qcom,mdss-dsi-panel-type", NULL);
1276 if (!mode) {
1277 pr_debug("[%s] Fallback to default panel mode\n", panel->name);
1278 panel_mode = DSI_OP_VIDEO_MODE;
1279 } else if (!strcmp(mode, "dsi_video_mode")) {
1280 panel_mode = DSI_OP_VIDEO_MODE;
1281 } else if (!strcmp(mode, "dsi_cmd_mode")) {
1282 panel_mode = DSI_OP_CMD_MODE;
1283 } else {
1284 pr_err("[%s] Unrecognized panel type-%s\n", panel->name, mode);
1285 rc = -EINVAL;
1286 goto error;
1287 }
1288
1289 if (panel_mode == DSI_OP_VIDEO_MODE) {
1290 rc = dsi_panel_parse_video_host_config(&panel->video_config,
1291 of_node,
1292 panel->name);
1293 if (rc) {
1294 pr_err("[%s] Failed to parse video host cfg, rc=%d\n",
1295 panel->name, rc);
1296 goto error;
1297 }
1298 }
1299
1300 if (panel_mode == DSI_OP_CMD_MODE) {
1301 rc = dsi_panel_parse_cmd_host_config(&panel->cmd_config,
1302 of_node,
1303 panel->name);
1304 if (rc) {
1305 pr_err("[%s] Failed to parse cmd host config, rc=%d\n",
1306 panel->name, rc);
1307 goto error;
1308 }
1309 }
1310
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001311 panel->panel_mode = panel_mode;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001312error:
1313 return rc;
1314}
1315
1316static int dsi_panel_parse_phy_props(struct dsi_panel_phy_props *props,
1317 struct device_node *of_node,
1318 const char *name)
1319{
1320 int rc = 0;
1321 u32 val = 0;
1322 const char *str;
1323
1324 rc = of_property_read_u32(of_node,
1325 "qcom,mdss-pan-physical-width-dimension",
1326 &val);
1327 if (rc) {
1328 pr_debug("[%s] Physical panel width is not defined\n", name);
1329 props->panel_width_mm = 0;
1330 rc = 0;
1331 } else {
1332 props->panel_width_mm = val;
1333 }
1334
1335 rc = of_property_read_u32(of_node,
1336 "qcom,mdss-pan-physical-height-dimension",
1337 &val);
1338 if (rc) {
1339 pr_debug("[%s] Physical panel height is not defined\n", name);
1340 props->panel_height_mm = 0;
1341 rc = 0;
1342 } else {
1343 props->panel_height_mm = val;
1344 }
1345
1346 str = of_get_property(of_node, "qcom,mdss-dsi-panel-orientation", NULL);
1347 if (!str) {
1348 props->rotation = DSI_PANEL_ROTATE_NONE;
1349 } else if (!strcmp(str, "180")) {
1350 props->rotation = DSI_PANEL_ROTATE_HV_FLIP;
1351 } else if (!strcmp(str, "hflip")) {
1352 props->rotation = DSI_PANEL_ROTATE_H_FLIP;
1353 } else if (!strcmp(str, "vflip")) {
1354 props->rotation = DSI_PANEL_ROTATE_V_FLIP;
1355 } else {
1356 pr_err("[%s] Unrecognized panel rotation-%s\n", name, str);
1357 rc = -EINVAL;
1358 goto error;
1359 }
1360error:
1361 return rc;
1362}
1363const char *cmd_set_prop_map[DSI_CMD_SET_MAX] = {
1364 "qcom,mdss-dsi-pre-on-command",
1365 "qcom,mdss-dsi-on-command",
1366 "qcom,mdss-dsi-post-panel-on-command",
1367 "qcom,mdss-dsi-pre-off-command",
1368 "qcom,mdss-dsi-off-command",
1369 "qcom,mdss-dsi-post-off-command",
1370 "qcom,mdss-dsi-pre-res-switch",
1371 "qcom,mdss-dsi-res-switch",
1372 "qcom,mdss-dsi-post-res-switch",
1373 "qcom,cmd-to-video-mode-switch-commands",
1374 "qcom,cmd-to-video-mode-post-switch-commands",
1375 "qcom,video-to-cmd-mode-switch-commands",
1376 "qcom,video-to-cmd-mode-post-switch-commands",
1377 "qcom,mdss-dsi-panel-status-command",
Clarence Ip5f00c0602017-08-02 14:26:31 -04001378 "qcom,mdss-dsi-lp1-command",
1379 "qcom,mdss-dsi-lp2-command",
1380 "qcom,mdss-dsi-nolp-command",
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04001381 "PPS not parsed from DTSI, generated dynamically",
1382 "ROI not parsed from DTSI, generated dynamically",
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001383 "qcom,mdss-dsi-timing-switch-command",
1384 "qcom,mdss-dsi-post-mode-switch-on-command",
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001385};
1386
1387const char *cmd_set_state_map[DSI_CMD_SET_MAX] = {
1388 "qcom,mdss-dsi-pre-on-command-state",
1389 "qcom,mdss-dsi-on-command-state",
1390 "qcom,mdss-dsi-post-on-command-state",
1391 "qcom,mdss-dsi-pre-off-command-state",
1392 "qcom,mdss-dsi-off-command-state",
1393 "qcom,mdss-dsi-post-off-command-state",
1394 "qcom,mdss-dsi-pre-res-switch-state",
1395 "qcom,mdss-dsi-res-switch-state",
1396 "qcom,mdss-dsi-post-res-switch-state",
1397 "qcom,cmd-to-video-mode-switch-commands-state",
1398 "qcom,cmd-to-video-mode-post-switch-commands-state",
1399 "qcom,video-to-cmd-mode-switch-commands-state",
1400 "qcom,video-to-cmd-mode-post-switch-commands-state",
1401 "qcom,mdss-dsi-panel-status-command-state",
Clarence Ip5f00c0602017-08-02 14:26:31 -04001402 "qcom,mdss-dsi-lp1-command-state",
1403 "qcom,mdss-dsi-lp2-command-state",
1404 "qcom,mdss-dsi-nolp-command-state",
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04001405 "PPS not parsed from DTSI, generated dynamically",
1406 "ROI not parsed from DTSI, generated dynamically",
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001407 "qcom,mdss-dsi-timing-switch-command-state",
1408 "qcom,mdss-dsi-post-mode-switch-on-command-state",
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001409};
1410
1411static int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt)
1412{
1413 const u32 cmd_set_min_size = 7;
1414 u32 count = 0;
1415 u32 packet_length;
1416 u32 tmp;
1417
1418 while (length >= cmd_set_min_size) {
1419 packet_length = cmd_set_min_size;
1420 tmp = ((data[5] << 8) | (data[6]));
1421 packet_length += tmp;
1422 if (packet_length > length) {
Alexander Beykunac182352017-02-27 17:46:51 -05001423 pr_err("format error\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001424 return -EINVAL;
1425 }
1426 length -= packet_length;
1427 data += packet_length;
1428 count++;
1429 };
1430
1431 *cnt = count;
1432 return 0;
1433}
1434
1435static int dsi_panel_create_cmd_packets(const char *data,
1436 u32 length,
1437 u32 count,
1438 struct dsi_cmd_desc *cmd)
1439{
1440 int rc = 0;
1441 int i, j;
1442 u8 *payload;
1443
1444 for (i = 0; i < count; i++) {
1445 u32 size;
1446
1447 cmd[i].msg.type = data[0];
1448 cmd[i].last_command = (data[1] == 1 ? true : false);
1449 cmd[i].msg.channel = data[2];
1450 cmd[i].msg.flags |= (data[3] == 1 ? MIPI_DSI_MSG_REQ_ACK : 0);
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04001451 cmd[i].msg.ctrl = 0;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001452 cmd[i].post_wait_ms = data[4];
1453 cmd[i].msg.tx_len = ((data[5] << 8) | (data[6]));
1454
1455 size = cmd[i].msg.tx_len * sizeof(u8);
1456
1457 payload = kzalloc(size, GFP_KERNEL);
1458 if (!payload) {
1459 rc = -ENOMEM;
1460 goto error_free_payloads;
1461 }
1462
1463 for (j = 0; j < cmd[i].msg.tx_len; j++)
1464 payload[j] = data[7 + j];
1465
1466 cmd[i].msg.tx_buf = payload;
1467 data += (7 + cmd[i].msg.tx_len);
1468 }
1469
1470 return rc;
1471error_free_payloads:
1472 for (i = i - 1; i >= 0; i--) {
1473 cmd--;
1474 kfree(cmd->msg.tx_buf);
1475 }
1476
1477 return rc;
1478}
1479
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04001480void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001481{
1482 u32 i = 0;
1483 struct dsi_cmd_desc *cmd;
1484
1485 for (i = 0; i < set->count; i++) {
1486 cmd = &set->cmds[i];
1487 kfree(cmd->msg.tx_buf);
1488 }
1489
1490 kfree(set->cmds);
1491}
1492
Alexander Beykunac182352017-02-27 17:46:51 -05001493static int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd,
1494 u32 packet_count)
1495{
1496 u32 size;
1497
1498 size = packet_count * sizeof(*cmd->cmds);
1499 cmd->cmds = kzalloc(size, GFP_KERNEL);
1500 if (!cmd->cmds)
1501 return -ENOMEM;
1502
1503 cmd->count = packet_count;
1504 return 0;
1505}
1506
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001507static int dsi_panel_parse_cmd_sets_sub(struct dsi_panel_cmd_set *cmd,
1508 enum dsi_cmd_set_type type,
1509 struct device_node *of_node)
1510{
1511 int rc = 0;
1512 u32 length = 0;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001513 const char *data;
1514 const char *state;
1515 u32 packet_count = 0;
1516
1517 data = of_get_property(of_node, cmd_set_prop_map[type], &length);
1518 if (!data) {
Shashank Babu Chinta Venkatacf411332017-05-10 17:30:08 -07001519 pr_debug("%s commands not defined\n", cmd_set_prop_map[type]);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001520 rc = -ENOTSUPP;
1521 goto error;
1522 }
1523
1524 rc = dsi_panel_get_cmd_pkt_count(data, length, &packet_count);
1525 if (rc) {
1526 pr_err("commands failed, rc=%d\n", rc);
1527 goto error;
1528 }
1529 pr_debug("[%s] packet-count=%d, %d\n", cmd_set_prop_map[type],
Alexander Beykunac182352017-02-27 17:46:51 -05001530 packet_count, length);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001531
Alexander Beykunac182352017-02-27 17:46:51 -05001532 rc = dsi_panel_alloc_cmd_packets(cmd, packet_count);
1533 if (rc) {
1534 pr_err("failed to allocate cmd packets, rc=%d\n", rc);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001535 goto error;
1536 }
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001537
1538 rc = dsi_panel_create_cmd_packets(data, length, packet_count,
1539 cmd->cmds);
1540 if (rc) {
Alexander Beykunac182352017-02-27 17:46:51 -05001541 pr_err("failed to create cmd packets, rc=%d\n", rc);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001542 goto error_free_mem;
1543 }
1544
1545 state = of_get_property(of_node, cmd_set_state_map[type], NULL);
1546 if (!state || !strcmp(state, "dsi_lp_mode")) {
1547 cmd->state = DSI_CMD_SET_STATE_LP;
1548 } else if (!strcmp(state, "dsi_hs_mode")) {
1549 cmd->state = DSI_CMD_SET_STATE_HS;
1550 } else {
Alexander Beykunac182352017-02-27 17:46:51 -05001551 pr_err("[%s] command state unrecognized-%s\n",
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001552 cmd_set_state_map[type], state);
1553 goto error_free_mem;
1554 }
1555
1556 return rc;
1557error_free_mem:
1558 kfree(cmd->cmds);
1559 cmd->cmds = NULL;
1560error:
1561 return rc;
1562
1563}
1564
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001565static int dsi_panel_parse_cmd_sets(
1566 struct dsi_display_mode_priv_info *priv_info,
1567 struct device_node *of_node)
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001568{
1569 int rc = 0;
1570 struct dsi_panel_cmd_set *set;
1571 u32 i;
1572
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001573 if (!priv_info) {
1574 pr_err("invalid mode priv info\n");
1575 return -EINVAL;
1576 }
1577
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001578 for (i = DSI_CMD_SET_PRE_ON; i < DSI_CMD_SET_MAX; i++) {
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001579 set = &priv_info->cmd_sets[i];
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001580 set->type = i;
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04001581 set->count = 0;
1582
Alexander Beykunac182352017-02-27 17:46:51 -05001583 if (i == DSI_CMD_SET_PPS) {
1584 rc = dsi_panel_alloc_cmd_packets(set, 1);
1585 if (rc)
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001586 pr_err("failed to allocate cmd set %d, rc = %d\n",
1587 i, rc);
Alexander Beykunac182352017-02-27 17:46:51 -05001588 set->state = DSI_CMD_SET_STATE_LP;
1589 } else {
1590 rc = dsi_panel_parse_cmd_sets_sub(set, i, of_node);
1591 if (rc)
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001592 pr_debug("failed to parse set %d\n", i);
Alexander Beykunac182352017-02-27 17:46:51 -05001593 }
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001594 }
1595
1596 rc = 0;
1597 return rc;
1598}
1599
1600static int dsi_panel_parse_reset_sequence(struct dsi_panel *panel,
1601 struct device_node *of_node)
1602{
1603 int rc = 0;
1604 int i;
1605 u32 length = 0;
1606 u32 count = 0;
1607 u32 size = 0;
1608 u32 *arr_32 = NULL;
1609 const u32 *arr;
1610 struct dsi_reset_seq *seq;
1611
1612 arr = of_get_property(of_node, "qcom,mdss-dsi-reset-sequence", &length);
1613 if (!arr) {
1614 pr_err("[%s] dsi-reset-sequence not found\n", panel->name);
1615 rc = -EINVAL;
1616 goto error;
1617 }
1618 if (length & 0x1) {
1619 pr_err("[%s] syntax error for dsi-reset-sequence\n",
1620 panel->name);
1621 rc = -EINVAL;
1622 goto error;
1623 }
1624
1625 pr_err("RESET SEQ LENGTH = %d\n", length);
1626 length = length / sizeof(u32);
1627
1628 size = length * sizeof(u32);
1629
1630 arr_32 = kzalloc(size, GFP_KERNEL);
1631 if (!arr_32) {
1632 rc = -ENOMEM;
1633 goto error;
1634 }
1635
1636 rc = of_property_read_u32_array(of_node, "qcom,mdss-dsi-reset-sequence",
1637 arr_32, length);
1638 if (rc) {
1639 pr_err("[%s] cannot read dso-reset-seqience\n", panel->name);
1640 goto error_free_arr_32;
1641 }
1642
1643 count = length / 2;
1644 size = count * sizeof(*seq);
1645 seq = kzalloc(size, GFP_KERNEL);
1646 if (!seq) {
1647 rc = -ENOMEM;
1648 goto error_free_arr_32;
1649 }
1650
1651 panel->reset_config.sequence = seq;
1652 panel->reset_config.count = count;
1653
1654 for (i = 0; i < length; i += 2) {
1655 seq->level = arr_32[i];
1656 seq->sleep_ms = arr_32[i + 1];
1657 seq++;
1658 }
1659
1660
1661error_free_arr_32:
1662 kfree(arr_32);
1663error:
1664 return rc;
1665}
1666
Narendra Muppallad4081e12017-04-20 19:24:08 -07001667static int dsi_panel_parse_misc_features(struct dsi_panel *panel,
Veera Sundaram Sankaranc4a90032017-04-21 13:54:14 -07001668 struct device_node *of_node)
1669{
1670 panel->ulps_enabled =
1671 of_property_read_bool(of_node, "qcom,ulps-enabled");
1672
Lei Chen529da982017-10-24 16:23:42 +08001673 pr_info("%s: ulps feature %s\n", __func__,
1674 (panel->ulps_enabled ? "enabled" : "disabled"));
1675
1676 panel->ulps_suspend_enabled =
1677 of_property_read_bool(of_node, "qcom,suspend-ulps-enabled");
1678
1679 pr_info("%s: ulps during suspend feature %s", __func__,
1680 (panel->ulps_suspend_enabled ? "enabled" : "disabled"));
Veera Sundaram Sankaranc4a90032017-04-21 13:54:14 -07001681
Narendra Muppallad4081e12017-04-20 19:24:08 -07001682 panel->te_using_watchdog_timer = of_property_read_bool(of_node,
1683 "qcom,mdss-dsi-te-using-wd");
Sandeep Panda14666d12017-05-08 17:11:03 +05301684
1685 panel->sync_broadcast_en = of_property_read_bool(of_node,
1686 "qcom,cmd-sync-wait-broadcast");
Veera Sundaram Sankaranc4a90032017-04-21 13:54:14 -07001687 return 0;
1688}
1689
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001690static int dsi_panel_parse_jitter_config(
1691 struct dsi_display_mode *mode,
1692 struct device_node *of_node)
Dhaval Patel60e1ff52017-02-18 21:03:40 -08001693{
1694 int rc;
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001695 struct dsi_display_mode_priv_info *priv_info;
Dhaval Patelf5cc5a32017-07-10 17:33:23 -07001696 u32 jitter[DEFAULT_PANEL_JITTER_ARRAY_SIZE] = {0, 0};
1697 u64 jitter_val = 0;
Dhaval Patel60e1ff52017-02-18 21:03:40 -08001698
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001699 priv_info = mode->priv_info;
1700
Dhaval Patelf5cc5a32017-07-10 17:33:23 -07001701 rc = of_property_read_u32_array(of_node, "qcom,mdss-dsi-panel-jitter",
1702 jitter, DEFAULT_PANEL_JITTER_ARRAY_SIZE);
Dhaval Patel60e1ff52017-02-18 21:03:40 -08001703 if (rc) {
Dhaval Patelf5cc5a32017-07-10 17:33:23 -07001704 pr_debug("panel jitter not defined rc=%d\n", rc);
1705 } else {
1706 jitter_val = jitter[0];
1707 jitter_val = div_u64(jitter_val, jitter[1]);
1708 }
1709
1710 if (rc || !jitter_val || (jitter_val > MAX_PANEL_JITTER)) {
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001711 priv_info->panel_jitter_numer = DEFAULT_PANEL_JITTER_NUMERATOR;
1712 priv_info->panel_jitter_denom =
1713 DEFAULT_PANEL_JITTER_DENOMINATOR;
Dhaval Patelf5cc5a32017-07-10 17:33:23 -07001714 } else {
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001715 priv_info->panel_jitter_numer = jitter[0];
1716 priv_info->panel_jitter_denom = jitter[1];
Dhaval Patel60e1ff52017-02-18 21:03:40 -08001717 }
1718
1719 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-prefill-lines",
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001720 &priv_info->panel_prefill_lines);
Dhaval Patel60e1ff52017-02-18 21:03:40 -08001721 if (rc) {
1722 pr_debug("panel prefill lines are not defined rc=%d\n", rc);
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001723 priv_info->panel_prefill_lines = DEFAULT_PANEL_PREFILL_LINES;
1724 } else if (priv_info->panel_prefill_lines >=
1725 DSI_V_TOTAL(&mode->timing)) {
Dhaval Patel60e1ff52017-02-18 21:03:40 -08001726 pr_debug("invalid prefill lines config=%d setting to:%d\n",
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07001727 priv_info->panel_prefill_lines, DEFAULT_PANEL_PREFILL_LINES);
1728
1729 priv_info->panel_prefill_lines = DEFAULT_PANEL_PREFILL_LINES;
Dhaval Patel60e1ff52017-02-18 21:03:40 -08001730 }
1731
1732 return 0;
1733}
1734
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001735static int dsi_panel_parse_power_cfg(struct device *parent,
1736 struct dsi_panel *panel,
1737 struct device_node *of_node)
1738{
1739 int rc = 0;
1740
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05301741 rc = dsi_pwr_of_get_vreg_data(of_node,
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001742 &panel->power_info,
1743 "qcom,panel-supply-entries");
1744 if (rc) {
1745 pr_err("[%s] failed to parse vregs\n", panel->name);
1746 goto error;
1747 }
1748
1749error:
1750 return rc;
1751}
1752
1753static int dsi_panel_parse_gpios(struct dsi_panel *panel,
1754 struct device_node *of_node)
1755{
1756 int rc = 0;
Padmanabhan Komanduruedfe6ff2016-12-19 12:37:04 +05301757 const char *data;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001758
1759 panel->reset_config.reset_gpio = of_get_named_gpio(of_node,
1760 "qcom,platform-reset-gpio",
1761 0);
1762 if (!gpio_is_valid(panel->reset_config.reset_gpio)) {
1763 pr_err("[%s] failed get reset gpio, rc=%d\n", panel->name, rc);
1764 rc = -EINVAL;
1765 goto error;
1766 }
1767
1768 panel->reset_config.disp_en_gpio = of_get_named_gpio(of_node,
1769 "qcom,5v-boost-gpio",
1770 0);
1771 if (!gpio_is_valid(panel->reset_config.disp_en_gpio)) {
1772 pr_debug("[%s] 5v-boot-gpio is not set, rc=%d\n",
1773 panel->name, rc);
1774 panel->reset_config.disp_en_gpio = of_get_named_gpio(of_node,
1775 "qcom,platform-en-gpio",
1776 0);
1777 if (!gpio_is_valid(panel->reset_config.disp_en_gpio)) {
1778 pr_debug("[%s] platform-en-gpio is not set, rc=%d\n",
1779 panel->name, rc);
1780 }
1781 }
1782
Padmanabhan Komanduruedfe6ff2016-12-19 12:37:04 +05301783 panel->reset_config.lcd_mode_sel_gpio = of_get_named_gpio(of_node,
1784 "qcom,panel-mode-gpio", 0);
1785 if (!gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio))
1786 pr_debug("%s:%d mode gpio not specified\n", __func__, __LINE__);
1787
1788 data = of_get_property(of_node,
1789 "qcom,mdss-dsi-mode-sel-gpio-state", NULL);
1790 if (data) {
1791 if (!strcmp(data, "single_port"))
1792 panel->reset_config.mode_sel_state =
1793 MODE_SEL_SINGLE_PORT;
1794 else if (!strcmp(data, "dual_port"))
1795 panel->reset_config.mode_sel_state =
1796 MODE_SEL_DUAL_PORT;
1797 else if (!strcmp(data, "high"))
1798 panel->reset_config.mode_sel_state =
1799 MODE_GPIO_HIGH;
1800 else if (!strcmp(data, "low"))
1801 panel->reset_config.mode_sel_state =
1802 MODE_GPIO_LOW;
1803 } else {
1804 /* Set default mode as SPLIT mode */
1805 panel->reset_config.mode_sel_state = MODE_SEL_DUAL_PORT;
1806 }
1807
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001808 /* TODO: release memory */
1809 rc = dsi_panel_parse_reset_sequence(panel, of_node);
1810 if (rc) {
1811 pr_err("[%s] failed to parse reset sequence, rc=%d\n",
1812 panel->name, rc);
1813 goto error;
1814 }
1815
1816error:
1817 return rc;
1818}
1819
1820static int dsi_panel_parse_bl_pwm_config(struct dsi_backlight_config *config,
1821 struct device_node *of_node)
1822{
1823 int rc = 0;
1824 u32 val;
1825
1826 rc = of_property_read_u32(of_node, "qcom,dsi-bl-pmic-bank-select",
1827 &val);
1828 if (rc) {
1829 pr_err("bl-pmic-bank-select is not defined, rc=%d\n", rc);
1830 goto error;
1831 }
1832 config->pwm_pmic_bank = val;
1833
1834 rc = of_property_read_u32(of_node, "qcom,dsi-bl-pmic-pwm-frequency",
1835 &val);
1836 if (rc) {
1837 pr_err("bl-pmic-bank-select is not defined, rc=%d\n", rc);
1838 goto error;
1839 }
1840 config->pwm_period_usecs = val;
1841
1842 config->pwm_pmi_control = of_property_read_bool(of_node,
1843 "qcom,mdss-dsi-bl-pwm-pmi");
1844
1845 config->pwm_gpio = of_get_named_gpio(of_node,
1846 "qcom,mdss-dsi-pwm-gpio",
1847 0);
1848 if (!gpio_is_valid(config->pwm_gpio)) {
1849 pr_err("pwm gpio is invalid\n");
1850 rc = -EINVAL;
1851 goto error;
1852 }
1853
1854error:
1855 return rc;
1856}
1857
1858static int dsi_panel_parse_bl_config(struct dsi_panel *panel,
1859 struct device_node *of_node)
1860{
1861 int rc = 0;
1862 const char *bl_type;
1863 u32 val = 0;
1864
1865 bl_type = of_get_property(of_node,
1866 "qcom,mdss-dsi-bl-pmic-control-type",
1867 NULL);
1868 if (!bl_type) {
1869 panel->bl_config.type = DSI_BACKLIGHT_UNKNOWN;
1870 } else if (!strcmp(bl_type, "bl_ctrl_pwm")) {
1871 panel->bl_config.type = DSI_BACKLIGHT_PWM;
1872 } else if (!strcmp(bl_type, "bl_ctrl_wled")) {
1873 panel->bl_config.type = DSI_BACKLIGHT_WLED;
1874 } else if (!strcmp(bl_type, "bl_ctrl_dcs")) {
1875 panel->bl_config.type = DSI_BACKLIGHT_DCS;
1876 } else {
1877 pr_debug("[%s] bl-pmic-control-type unknown-%s\n",
1878 panel->name, bl_type);
1879 panel->bl_config.type = DSI_BACKLIGHT_UNKNOWN;
1880 }
1881
Xu Yangd566d222017-05-19 17:18:12 +08001882 panel->bl_config.bl_scale = MAX_BL_SCALE_LEVEL;
1883 panel->bl_config.bl_scale_ad = MAX_AD_BL_SCALE_LEVEL;
1884
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001885 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-bl-min-level", &val);
1886 if (rc) {
1887 pr_debug("[%s] bl-min-level unspecified, defaulting to zero\n",
1888 panel->name);
Vishnuvardhan Prodduturi75b96802016-10-17 18:45:55 +05301889 panel->bl_config.bl_min_level = 0;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001890 } else {
Vishnuvardhan Prodduturi75b96802016-10-17 18:45:55 +05301891 panel->bl_config.bl_min_level = val;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001892 }
1893
1894 rc = of_property_read_u32(of_node, "qcom,mdss-dsi-bl-max-level", &val);
1895 if (rc) {
Vishnuvardhan Prodduturi75b96802016-10-17 18:45:55 +05301896 pr_debug("[%s] bl-max-level unspecified, defaulting to max level\n",
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001897 panel->name);
Vishnuvardhan Prodduturi75b96802016-10-17 18:45:55 +05301898 panel->bl_config.bl_max_level = MAX_BL_LEVEL;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001899 } else {
Vishnuvardhan Prodduturi75b96802016-10-17 18:45:55 +05301900 panel->bl_config.bl_max_level = val;
1901 }
1902
1903 rc = of_property_read_u32(of_node, "qcom,mdss-brightness-max-level",
1904 &val);
1905 if (rc) {
1906 pr_debug("[%s] brigheness-max-level unspecified, defaulting to 255\n",
1907 panel->name);
1908 panel->bl_config.brightness_max_level = 255;
1909 } else {
1910 panel->bl_config.brightness_max_level = val;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001911 }
1912
1913 if (panel->bl_config.type == DSI_BACKLIGHT_PWM) {
1914 rc = dsi_panel_parse_bl_pwm_config(&panel->bl_config, of_node);
1915 if (rc) {
1916 pr_err("[%s] failed to parse pwm config, rc=%d\n",
1917 panel->name, rc);
1918 goto error;
1919 }
1920 }
1921
1922 panel->bl_config.en_gpio = of_get_named_gpio(of_node,
1923 "qcom,platform-bklight-en-gpio",
1924 0);
1925 if (!gpio_is_valid(panel->bl_config.en_gpio)) {
Shashank Babu Chinta Venkatacf411332017-05-10 17:30:08 -07001926 pr_debug("[%s] failed get bklt gpio, rc=%d\n", panel->name, rc);
1927 rc = 0;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07001928 goto error;
1929 }
1930
1931error:
1932 return rc;
1933}
1934
Alexander Beykunac182352017-02-27 17:46:51 -05001935void dsi_dsc_pclk_param_calc(struct msm_display_dsc_info *dsc, int intf_width)
1936{
1937 int slice_per_pkt, slice_per_intf;
1938 int bytes_in_slice, total_bytes_per_intf;
1939
1940 if (!dsc || !dsc->slice_width || !dsc->slice_per_pkt ||
1941 (intf_width < dsc->slice_width)) {
1942 pr_err("invalid input, intf_width=%d slice_width=%d\n",
1943 intf_width, dsc ? dsc->slice_width : -1);
1944 return;
1945 }
1946
1947 slice_per_pkt = dsc->slice_per_pkt;
1948 slice_per_intf = DIV_ROUND_UP(intf_width, dsc->slice_width);
1949
1950 /*
1951 * If slice_per_pkt is greater than slice_per_intf then default to 1.
1952 * This can happen during partial update.
1953 */
1954 if (slice_per_pkt > slice_per_intf)
1955 slice_per_pkt = 1;
1956
1957 bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bpp, 8);
1958 total_bytes_per_intf = bytes_in_slice * slice_per_intf;
1959
1960 dsc->eol_byte_num = total_bytes_per_intf % 3;
1961 dsc->pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf, 3);
1962 dsc->bytes_in_slice = bytes_in_slice;
1963 dsc->bytes_per_pkt = bytes_in_slice * slice_per_pkt;
1964 dsc->pkt_per_line = slice_per_intf / slice_per_pkt;
1965}
1966
1967
1968int dsi_dsc_populate_static_param(struct msm_display_dsc_info *dsc)
1969{
1970 int bpp, bpc;
1971 int mux_words_size;
1972 int groups_per_line, groups_total;
1973 int min_rate_buffer_size;
1974 int hrd_delay;
1975 int pre_num_extra_mux_bits, num_extra_mux_bits;
1976 int slice_bits;
1977 int target_bpp_x16;
1978 int data;
1979 int final_value, final_scale;
Rajkumar Subbiahc70dfab2017-06-16 10:46:32 -04001980 int ratio_index;
Alexander Beykunac182352017-02-27 17:46:51 -05001981
1982 dsc->version = 0x11;
1983 dsc->scr_rev = 0;
1984 dsc->rc_model_size = 8192;
1985 if (dsc->version == 0x11 && dsc->scr_rev == 0x1)
1986 dsc->first_line_bpg_offset = 15;
1987 else
1988 dsc->first_line_bpg_offset = 12;
1989
Alexander Beykunac182352017-02-27 17:46:51 -05001990 dsc->edge_factor = 6;
Alexander Beykunac182352017-02-27 17:46:51 -05001991 dsc->tgt_offset_hi = 3;
1992 dsc->tgt_offset_lo = 3;
1993 dsc->enable_422 = 0;
1994 dsc->convert_rgb = 1;
1995 dsc->vbr_enable = 0;
1996
1997 dsc->buf_thresh = dsi_dsc_rc_buf_thresh;
Alexander Beykunac182352017-02-27 17:46:51 -05001998
1999 bpp = dsc->bpp;
2000 bpc = dsc->bpc;
2001
Rajkumar Subbiahc70dfab2017-06-16 10:46:32 -04002002 if (bpc == 12)
2003 ratio_index = DSC_12BPC_8BPP;
2004 else if (bpc == 10)
2005 ratio_index = DSC_10BPC_8BPP;
2006 else
2007 ratio_index = DSC_8BPC_8BPP;
2008
2009 if (dsc->version == 0x11 && dsc->scr_rev == 0x1) {
2010 dsc->range_min_qp =
2011 dsi_dsc_rc_range_min_qp_1_1_scr1[ratio_index];
2012 dsc->range_max_qp =
2013 dsi_dsc_rc_range_max_qp_1_1_scr1[ratio_index];
2014 } else {
2015 dsc->range_min_qp = dsi_dsc_rc_range_min_qp_1_1[ratio_index];
2016 dsc->range_max_qp = dsi_dsc_rc_range_max_qp_1_1[ratio_index];
2017 }
2018 dsc->range_bpg_offset = dsi_dsc_rc_range_bpg_offset;
2019
Alexander Beykunac182352017-02-27 17:46:51 -05002020 if (bpp == 8)
2021 dsc->initial_offset = 6144;
2022 else
2023 dsc->initial_offset = 2048; /* bpp = 12 */
2024
Rajkumar Subbiahc70dfab2017-06-16 10:46:32 -04002025 if (bpc == 12)
2026 mux_words_size = 64;
Alexander Beykunac182352017-02-27 17:46:51 -05002027 else
Rajkumar Subbiahc70dfab2017-06-16 10:46:32 -04002028 mux_words_size = 48; /* bpc == 8/10 */
2029
2030 if (bpc == 8) {
2031 dsc->line_buf_depth = 9;
2032 dsc->input_10_bits = 0;
2033 dsc->min_qp_flatness = 3;
2034 dsc->max_qp_flatness = 12;
2035 dsc->quant_incr_limit0 = 11;
2036 dsc->quant_incr_limit1 = 11;
2037 } else if (bpc == 10) { /* 10bpc */
2038 dsc->line_buf_depth = 11;
2039 dsc->input_10_bits = 1;
2040 dsc->min_qp_flatness = 7;
2041 dsc->max_qp_flatness = 16;
2042 dsc->quant_incr_limit0 = 15;
2043 dsc->quant_incr_limit1 = 15;
2044 } else { /* 12 bpc */
2045 dsc->line_buf_depth = 9;
2046 dsc->input_10_bits = 0;
2047 dsc->min_qp_flatness = 11;
2048 dsc->max_qp_flatness = 20;
2049 dsc->quant_incr_limit0 = 19;
2050 dsc->quant_incr_limit1 = 19;
2051 }
Alexander Beykunac182352017-02-27 17:46:51 -05002052
2053 dsc->slice_last_group_size = 3 - (dsc->slice_width % 3);
2054
2055 dsc->det_thresh_flatness = 7 + 2*(bpc - 8);
2056
2057 dsc->initial_xmit_delay = dsc->rc_model_size / (2 * bpp);
2058
2059 groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3);
2060
2061 dsc->chunk_size = dsc->slice_width * bpp / 8;
2062 if ((dsc->slice_width * bpp) % 8)
2063 dsc->chunk_size++;
2064
2065 /* rbs-min */
2066 min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset +
2067 dsc->initial_xmit_delay * bpp +
2068 groups_per_line * dsc->first_line_bpg_offset;
2069
2070 hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, bpp);
2071
2072 dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay;
2073
2074 dsc->initial_scale_value = 8 * dsc->rc_model_size /
2075 (dsc->rc_model_size - dsc->initial_offset);
2076
2077 slice_bits = 8 * dsc->chunk_size * dsc->slice_height;
2078
2079 groups_total = groups_per_line * dsc->slice_height;
2080
2081 data = dsc->first_line_bpg_offset * 2048;
2082
2083 dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1));
2084
2085 pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * bpc + 4) - 2);
2086
2087 num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size -
2088 ((slice_bits - pre_num_extra_mux_bits) % mux_words_size));
2089
2090 data = 2048 * (dsc->rc_model_size - dsc->initial_offset
2091 + num_extra_mux_bits);
2092 dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total);
2093
2094 /* bpp * 16 + 0.5 */
2095 data = bpp * 16;
2096 data *= 2;
2097 data++;
2098 data /= 2;
2099 target_bpp_x16 = data;
2100
2101 data = (dsc->initial_xmit_delay * target_bpp_x16) / 16;
2102 final_value = dsc->rc_model_size - data + num_extra_mux_bits;
2103
2104 final_scale = 8 * dsc->rc_model_size /
2105 (dsc->rc_model_size - final_value);
2106
2107 dsc->final_offset = final_value;
2108
2109 data = (final_scale - 9) * (dsc->nfl_bpg_offset +
2110 dsc->slice_bpg_offset);
2111 dsc->scale_increment_interval = (2048 * dsc->final_offset) / data;
2112
2113 dsc->scale_decrement_interval = groups_per_line /
2114 (dsc->initial_scale_value - 8);
2115
2116 return 0;
2117}
2118
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002119
2120static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode,
2121 struct device_node *of_node)
2122{
2123 const char *data;
2124 u32 len, i;
2125 int rc = 0;
2126 struct dsi_display_mode_priv_info *priv_info;
2127
2128 priv_info = mode->priv_info;
2129
2130 data = of_get_property(of_node,
2131 "qcom,mdss-dsi-panel-phy-timings", &len);
2132 if (!data) {
2133 pr_debug("Unable to read Phy timing settings");
2134 } else {
2135 priv_info->phy_timing_val =
2136 kzalloc((sizeof(u32) * len), GFP_KERNEL);
2137 if (!priv_info->phy_timing_val)
2138 return -EINVAL;
2139
2140 for (i = 0; i < len; i++)
2141 priv_info->phy_timing_val[i] = data[i];
2142
2143 priv_info->phy_timing_len = len;
2144 };
2145
2146 mode->pixel_clk_khz = (DSI_H_TOTAL(&mode->timing) *
2147 DSI_V_TOTAL(&mode->timing) *
2148 mode->timing.refresh_rate) / 1000;
2149 return rc;
2150}
2151
2152static int dsi_panel_parse_dsc_params(struct dsi_display_mode *mode,
Alexander Beykunac182352017-02-27 17:46:51 -05002153 struct device_node *of_node)
2154{
2155 u32 data;
2156 int rc = -EINVAL;
2157 int intf_width;
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002158 const char *compression;
2159 struct dsi_display_mode_priv_info *priv_info;
Alexander Beykunac182352017-02-27 17:46:51 -05002160
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002161 if (!mode || !mode->priv_info)
2162 return -EINVAL;
2163
2164 priv_info = mode->priv_info;
2165
2166 priv_info->dsc_enabled = false;
2167 compression = of_get_property(of_node, "qcom,compression-mode", NULL);
2168 if (compression && !strcmp(compression, "dsc"))
2169 priv_info->dsc_enabled = true;
2170
2171 if (!priv_info->dsc_enabled) {
2172 pr_debug("dsc compression is not enabled for the mode");
Alexander Beykunac182352017-02-27 17:46:51 -05002173 return 0;
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002174 }
Alexander Beykunac182352017-02-27 17:46:51 -05002175
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -07002176 rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-height", &data);
Alexander Beykunac182352017-02-27 17:46:51 -05002177 if (rc) {
2178 pr_err("failed to parse qcom,mdss-dsc-slice-height\n");
2179 goto error;
2180 }
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002181 priv_info->dsc.slice_height = data;
Alexander Beykunac182352017-02-27 17:46:51 -05002182
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -07002183 rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-width", &data);
Alexander Beykunac182352017-02-27 17:46:51 -05002184 if (rc) {
2185 pr_err("failed to parse qcom,mdss-dsc-slice-width\n");
2186 goto error;
2187 }
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002188 priv_info->dsc.slice_width = data;
Alexander Beykunac182352017-02-27 17:46:51 -05002189
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002190 intf_width = mode->timing.h_active;
2191 if (intf_width % priv_info->dsc.slice_width) {
Dhaval Patel35ec17e2017-10-17 22:20:37 -07002192 pr_err("invalid slice width for the intf width:%d slice width:%d\n",
2193 intf_width, priv_info->dsc.slice_width);
2194 rc = -EINVAL;
Alexander Beykunac182352017-02-27 17:46:51 -05002195 goto error;
2196 }
2197
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002198 priv_info->dsc.pic_width = mode->timing.h_active;
2199 priv_info->dsc.pic_height = mode->timing.v_active;
Alexander Beykunac182352017-02-27 17:46:51 -05002200
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -07002201 rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-per-pkt",
2202 &data);
Alexander Beykunac182352017-02-27 17:46:51 -05002203 if (rc) {
2204 pr_err("failed to parse qcom,mdss-dsc-slice-per-pkt\n");
2205 goto error;
2206 }
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002207 priv_info->dsc.slice_per_pkt = data;
Alexander Beykunac182352017-02-27 17:46:51 -05002208
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -07002209 rc = of_property_read_u32(of_node, "qcom,mdss-dsc-bit-per-component",
Alexander Beykunac182352017-02-27 17:46:51 -05002210 &data);
2211 if (rc) {
2212 pr_err("failed to parse qcom,mdss-dsc-bit-per-component\n");
2213 goto error;
2214 }
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002215 priv_info->dsc.bpc = data;
Alexander Beykunac182352017-02-27 17:46:51 -05002216
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -07002217 rc = of_property_read_u32(of_node, "qcom,mdss-dsc-bit-per-pixel",
2218 &data);
Alexander Beykunac182352017-02-27 17:46:51 -05002219 if (rc) {
2220 pr_err("failed to parse qcom,mdss-dsc-bit-per-pixel\n");
2221 goto error;
2222 }
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002223 priv_info->dsc.bpp = data;
Alexander Beykunac182352017-02-27 17:46:51 -05002224
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002225 priv_info->dsc.block_pred_enable = of_property_read_bool(of_node,
Alexander Beykunac182352017-02-27 17:46:51 -05002226 "qcom,mdss-dsc-block-prediction-enable");
2227
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002228 priv_info->dsc.full_frame_slices = DIV_ROUND_UP(intf_width,
2229 priv_info->dsc.slice_width);
Alexander Beykunac182352017-02-27 17:46:51 -05002230
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002231 dsi_dsc_populate_static_param(&priv_info->dsc);
2232 dsi_dsc_pclk_param_calc(&priv_info->dsc, intf_width);
Alexander Beykunac182352017-02-27 17:46:51 -05002233
2234error:
2235 return rc;
2236}
2237
Ping Li898b1bf2017-02-09 18:03:28 -08002238static int dsi_panel_parse_hdr_config(struct dsi_panel *panel,
2239 struct device_node *of_node)
2240{
2241
2242 int rc = 0;
2243 struct drm_panel_hdr_properties *hdr_prop;
2244
2245 hdr_prop = &panel->hdr_props;
2246 hdr_prop->hdr_enabled = of_property_read_bool(of_node,
2247 "qcom,mdss-dsi-panel-hdr-enabled");
2248
2249 if (hdr_prop->hdr_enabled) {
2250 rc = of_property_read_u32_array(of_node,
2251 "qcom,mdss-dsi-panel-hdr-color-primaries",
2252 hdr_prop->display_primaries,
2253 DISPLAY_PRIMARIES_MAX);
2254 if (rc) {
2255 pr_err("%s:%d, Unable to read color primaries,rc:%u",
2256 __func__, __LINE__, rc);
2257 hdr_prop->hdr_enabled = false;
2258 return rc;
2259 }
2260
2261 rc = of_property_read_u32(of_node,
2262 "qcom,mdss-dsi-panel-peak-brightness",
2263 &(hdr_prop->peak_brightness));
2264 if (rc) {
2265 pr_err("%s:%d, Unable to read hdr brightness, rc:%u",
2266 __func__, __LINE__, rc);
2267 hdr_prop->hdr_enabled = false;
2268 return rc;
2269 }
2270
2271 rc = of_property_read_u32(of_node,
2272 "qcom,mdss-dsi-panel-blackness-level",
2273 &(hdr_prop->blackness_level));
2274 if (rc) {
2275 pr_err("%s:%d, Unable to read hdr brightness, rc:%u",
2276 __func__, __LINE__, rc);
2277 hdr_prop->hdr_enabled = false;
2278 return rc;
2279 }
2280 }
2281 return 0;
2282}
2283
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002284static int dsi_panel_parse_topology(
2285 struct dsi_display_mode_priv_info *priv_info,
2286 struct device_node *of_node, int topology_override)
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -07002287{
2288 struct msm_display_topology *topology;
2289 u32 top_count, top_sel, *array = NULL;
2290 int i, len = 0;
2291 int rc = -EINVAL;
2292
2293 len = of_property_count_u32_elems(of_node, "qcom,display-topology");
2294 if (len <= 0 || len % TOPOLOGY_SET_LEN ||
2295 len > (TOPOLOGY_SET_LEN * MAX_TOPOLOGY)) {
2296 pr_err("invalid topology list for the panel, rc = %d\n", rc);
2297 return rc;
2298 }
2299
2300 top_count = len / TOPOLOGY_SET_LEN;
2301
2302 array = kcalloc(len, sizeof(u32), GFP_KERNEL);
2303 if (!array)
2304 return -ENOMEM;
2305
2306 rc = of_property_read_u32_array(of_node,
2307 "qcom,display-topology", array, len);
2308 if (rc) {
2309 pr_err("unable to read the display topologies, rc = %d\n", rc);
2310 goto read_fail;
2311 }
2312
2313 topology = kcalloc(top_count, sizeof(*topology), GFP_KERNEL);
2314 if (!topology) {
2315 rc = -ENOMEM;
2316 goto read_fail;
2317 }
2318
2319 for (i = 0; i < top_count; i++) {
2320 struct msm_display_topology *top = &topology[i];
2321
2322 top->num_lm = array[i * TOPOLOGY_SET_LEN];
2323 top->num_enc = array[i * TOPOLOGY_SET_LEN + 1];
2324 top->num_intf = array[i * TOPOLOGY_SET_LEN + 2];
2325 };
2326
Chandan Uddaraju7e9613a2017-06-01 13:10:55 -07002327 if (topology_override >= 0 && topology_override < top_count) {
2328 pr_info("override topology: cfg:%d lm:%d comp_enc:%d intf:%d\n",
2329 topology_override,
2330 topology[topology_override].num_lm,
2331 topology[topology_override].num_enc,
2332 topology[topology_override].num_intf);
2333 top_sel = topology_override;
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -07002334 goto parse_done;
2335 }
2336
2337 rc = of_property_read_u32(of_node,
2338 "qcom,default-topology-index", &top_sel);
2339 if (rc) {
2340 pr_err("no default topology selected, rc = %d\n", rc);
2341 goto parse_fail;
2342 }
2343
2344 if (top_sel >= top_count) {
2345 rc = -EINVAL;
2346 pr_err("default topology is specified is not valid, rc = %d\n",
2347 rc);
2348 goto parse_fail;
2349 }
2350
2351 pr_info("default topology: lm: %d comp_enc:%d intf: %d\n",
2352 topology[top_sel].num_lm,
2353 topology[top_sel].num_enc,
2354 topology[top_sel].num_intf);
2355
2356parse_done:
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002357 memcpy(&priv_info->topology, &topology[top_sel],
Jeykumar Sankaran6b345ac2017-03-15 19:17:19 -07002358 sizeof(struct msm_display_topology));
2359parse_fail:
2360 kfree(topology);
2361read_fail:
2362 kfree(array);
2363
2364 return rc;
2365}
2366
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002367static int dsi_panel_parse_roi_alignment(struct device_node *of_node,
2368 struct msm_roi_alignment *align)
2369{
2370 int len = 0, rc = 0;
2371 u32 value[6];
2372 struct property *data;
2373
2374 if (!align || !of_node)
2375 return -EINVAL;
2376
2377 memset(align, 0, sizeof(*align));
2378
2379 data = of_find_property(of_node, "qcom,panel-roi-alignment", &len);
2380 len /= sizeof(u32);
2381 if (!data) {
2382 pr_err("panel roi alignment not found\n");
2383 rc = -EINVAL;
2384 } else if (len != 6) {
2385 pr_err("incorrect roi alignment len %d\n", len);
2386 rc = -EINVAL;
2387 } else {
2388 rc = of_property_read_u32_array(of_node,
2389 "qcom,panel-roi-alignment", value, len);
2390 if (rc)
2391 pr_debug("error reading panel roi alignment values\n");
2392 else {
2393 align->xstart_pix_align = value[0];
2394 align->ystart_pix_align = value[1];
2395 align->width_pix_align = value[2];
2396 align->height_pix_align = value[3];
2397 align->min_width = value[4];
2398 align->min_height = value[5];
2399 }
2400
2401 pr_info("roi alignment: [%d, %d, %d, %d, %d, %d]\n",
2402 align->xstart_pix_align,
2403 align->width_pix_align,
2404 align->ystart_pix_align,
2405 align->height_pix_align,
2406 align->min_width,
2407 align->min_height);
2408 }
2409
2410 return rc;
2411}
2412
Jeykumar Sankaran736d79d2017-10-05 17:44:24 -07002413static int dsi_panel_parse_partial_update_caps(struct dsi_display_mode *mode,
2414 struct device_node *of_node)
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002415{
Jeykumar Sankaran736d79d2017-10-05 17:44:24 -07002416 struct msm_roi_caps *roi_caps = NULL;
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002417 const char *data;
2418 int rc = 0;
2419
Jeykumar Sankaran736d79d2017-10-05 17:44:24 -07002420 if (!mode || !mode->priv_info) {
2421 pr_err("invalid arguments\n");
2422 return -EINVAL;
2423 }
2424
2425 roi_caps = &mode->priv_info->roi_caps;
2426
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002427 memset(roi_caps, 0, sizeof(*roi_caps));
2428
2429 data = of_get_property(of_node, "qcom,partial-update-enabled", NULL);
2430 if (data) {
2431 if (!strcmp(data, "dual_roi"))
2432 roi_caps->num_roi = 2;
Jeykumar Sankaran736d79d2017-10-05 17:44:24 -07002433 else if (!strcmp(data, "single_roi"))
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002434 roi_caps->num_roi = 1;
Jeykumar Sankaran736d79d2017-10-05 17:44:24 -07002435 else {
2436 pr_info(
2437 "invalid value for qcom,partial-update-enabled: %s\n",
2438 data);
2439 return 0;
2440 }
2441 } else {
2442 pr_info("partial update disabled as the property is not set\n");
2443 return 0;
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002444 }
2445
2446 roi_caps->merge_rois = of_property_read_bool(of_node,
2447 "qcom,partial-update-roi-merge");
2448
2449 roi_caps->enabled = roi_caps->num_roi > 0;
2450
2451 pr_info("partial update num_rois=%d enabled=%d\n", roi_caps->num_roi,
2452 roi_caps->enabled);
2453
2454 if (roi_caps->enabled)
2455 rc = dsi_panel_parse_roi_alignment(of_node,
Jeykumar Sankaran736d79d2017-10-05 17:44:24 -07002456 &roi_caps->align);
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04002457
2458 if (rc)
2459 memset(roi_caps, 0, sizeof(*roi_caps));
2460
2461 return rc;
2462}
2463
Jeykumar Sankarana7c7bbe2017-05-31 18:12:05 -07002464static int dsi_panel_parse_dms_info(struct dsi_panel *panel,
2465 struct device_node *of_node)
2466{
2467 int dms_enabled;
2468 const char *data;
2469
2470 if (!of_node || !panel) {
2471 pr_err("invalid params\n");
2472 return -EINVAL;
2473 }
2474
2475 panel->dms_mode = DSI_DMS_MODE_DISABLED;
2476 dms_enabled = of_property_read_bool(of_node,
2477 "qcom,dynamic-mode-switch-enabled");
2478 if (!dms_enabled)
2479 return 0;
2480
2481 data = of_get_property(of_node, "qcom,dynamic-mode-switch-type", NULL);
2482 if (data && !strcmp(data, "dynamic-resolution-switch-immediate")) {
2483 panel->dms_mode = DSI_DMS_MODE_RES_SWITCH_IMMEDIATE;
2484 } else {
2485 pr_err("[%s] unsupported dynamic switch mode: %s\n",
2486 panel->name, data);
2487 return -EINVAL;
2488 }
2489
2490 return 0;
2491};
2492
Sandeep Panda14666d12017-05-08 17:11:03 +05302493/*
2494 * The length of all the valid values to be checked should not be greater
2495 * than the length of returned data from read command.
2496 */
2497static bool
2498dsi_panel_parse_esd_check_valid_params(struct dsi_panel *panel, u32 count)
2499{
2500 int i;
2501 struct drm_panel_esd_config *config = &panel->esd_config;
2502
2503 for (i = 0; i < count; ++i) {
2504 if (config->status_valid_params[i] >
2505 config->status_cmds_rlen[i]) {
2506 pr_debug("ignore valid params\n");
2507 return false;
2508 }
2509 }
2510
2511 return true;
2512}
2513
2514static bool dsi_panel_parse_esd_status_len(struct device_node *np,
2515 char *prop_key, u32 **target, u32 cmd_cnt)
2516{
2517 int tmp;
2518
2519 if (!of_find_property(np, prop_key, &tmp))
2520 return false;
2521
2522 tmp /= sizeof(u32);
2523 if (tmp != cmd_cnt) {
2524 pr_err("request property(%d) do not match cmd count(%d)\n",
2525 tmp, cmd_cnt);
2526 return false;
2527 }
2528
2529 *target = kcalloc(tmp, sizeof(u32), GFP_KERNEL);
2530 if (IS_ERR_OR_NULL(*target)) {
2531 pr_err("Error allocating memory for property\n");
2532 return false;
2533 }
2534
2535 if (of_property_read_u32_array(np, prop_key, *target, tmp)) {
2536 pr_err("cannot get values from dts\n");
2537 kfree(*target);
2538 *target = NULL;
2539 return false;
2540 }
2541
2542 return true;
2543}
2544
2545static void dsi_panel_esd_config_deinit(struct drm_panel_esd_config *esd_config)
2546{
Sandeep Panda79450002017-05-08 17:14:24 +05302547 kfree(esd_config->status_buf);
Sandeep Panda14666d12017-05-08 17:11:03 +05302548 kfree(esd_config->return_buf);
2549 kfree(esd_config->status_value);
2550 kfree(esd_config->status_valid_params);
2551 kfree(esd_config->status_cmds_rlen);
2552 kfree(esd_config->status_cmd.cmds);
2553}
2554
2555static int dsi_panel_parse_esd_config(struct dsi_panel *panel,
2556 struct device_node *of_node)
2557{
2558 int rc = 0;
2559 u32 tmp;
2560 u32 i, status_len, *lenp;
2561 struct property *data;
2562 const char *string;
2563 struct drm_panel_esd_config *esd_config;
Sandeep Panda5a91e482017-10-10 10:04:00 +05302564 u8 *esd_mode = NULL;
Sandeep Panda14666d12017-05-08 17:11:03 +05302565
2566 esd_config = &panel->esd_config;
Sandeep Panda5a91e482017-10-10 10:04:00 +05302567 esd_config->status_mode = ESD_MODE_MAX;
Sandeep Panda14666d12017-05-08 17:11:03 +05302568 esd_config->esd_enabled = of_property_read_bool(of_node,
2569 "qcom,esd-check-enabled");
2570
2571 if (!esd_config->esd_enabled)
2572 return 0;
2573
2574 rc = of_property_read_string(of_node,
2575 "qcom,mdss-dsi-panel-status-check-mode", &string);
2576 if (!rc) {
2577 if (!strcmp(string, "bta_check")) {
2578 esd_config->status_mode = ESD_MODE_SW_BTA;
2579 } else if (!strcmp(string, "reg_read")) {
2580 esd_config->status_mode = ESD_MODE_REG_READ;
2581 } else if (!strcmp(string, "te_signal_check")) {
2582 if (panel->panel_mode == DSI_OP_CMD_MODE) {
2583 esd_config->status_mode = ESD_MODE_PANEL_TE;
2584 } else {
2585 pr_err("TE-ESD not valid for video mode\n");
2586 rc = -EINVAL;
2587 goto error;
2588 }
2589 } else {
2590 pr_err("No valid panel-status-check-mode string\n");
2591 rc = -EINVAL;
2592 goto error;
2593 }
2594 } else {
2595 pr_debug("status check method not defined!\n");
2596 rc = -EINVAL;
2597 goto error;
2598 }
2599
2600 if ((esd_config->status_mode == ESD_MODE_SW_BTA) ||
2601 (esd_config->status_mode == ESD_MODE_PANEL_TE))
2602 return 0;
2603
2604 dsi_panel_parse_cmd_sets_sub(&esd_config->status_cmd,
2605 DSI_CMD_SET_PANEL_STATUS, of_node);
2606 if (!esd_config->status_cmd.count) {
2607 pr_err("panel status command parsing failed\n");
2608 rc = -EINVAL;
2609 goto error;
2610 }
2611
2612 if (!dsi_panel_parse_esd_status_len(of_node,
2613 "qcom,mdss-dsi-panel-status-read-length",
2614 &panel->esd_config.status_cmds_rlen,
2615 esd_config->status_cmd.count)) {
2616 pr_err("Invalid status read length\n");
2617 rc = -EINVAL;
2618 goto error1;
2619 }
2620
2621 if (dsi_panel_parse_esd_status_len(of_node,
2622 "qcom,mdss-dsi-panel-status-valid-params",
2623 &panel->esd_config.status_valid_params,
2624 esd_config->status_cmd.count)) {
2625 if (!dsi_panel_parse_esd_check_valid_params(panel,
2626 esd_config->status_cmd.count)) {
2627 rc = -EINVAL;
2628 goto error2;
2629 }
2630 }
2631
2632 status_len = 0;
2633 lenp = esd_config->status_valid_params ?: esd_config->status_cmds_rlen;
2634 for (i = 0; i < esd_config->status_cmd.count; ++i)
2635 status_len += lenp[i];
2636
2637 if (!status_len) {
2638 rc = -EINVAL;
2639 goto error2;
2640 }
2641
2642 /*
2643 * Some panel may need multiple read commands to properly
2644 * check panel status. Do a sanity check for proper status
2645 * value which will be compared with the value read by dsi
2646 * controller during ESD check. Also check if multiple read
2647 * commands are there then, there should be corresponding
2648 * status check values for each read command.
2649 */
2650 data = of_find_property(of_node,
2651 "qcom,mdss-dsi-panel-status-value", &tmp);
2652 tmp /= sizeof(u32);
2653 if (!IS_ERR_OR_NULL(data) && tmp != 0 && (tmp % status_len) == 0) {
2654 esd_config->groups = tmp / status_len;
2655 } else {
2656 pr_err("error parse panel-status-value\n");
2657 rc = -EINVAL;
2658 goto error2;
2659 }
2660
2661 esd_config->status_value =
2662 kzalloc(sizeof(u32) * status_len * esd_config->groups,
2663 GFP_KERNEL);
2664 if (!esd_config->status_value) {
2665 rc = -ENOMEM;
2666 goto error2;
2667 }
2668
2669 esd_config->return_buf = kcalloc(status_len * esd_config->groups,
2670 sizeof(unsigned char), GFP_KERNEL);
2671 if (!esd_config->return_buf) {
2672 rc = -ENOMEM;
2673 goto error3;
2674 }
2675
Sandeep Panda79450002017-05-08 17:14:24 +05302676 esd_config->status_buf = kzalloc(SZ_4K, GFP_KERNEL);
2677 if (!esd_config->status_buf)
2678 goto error4;
2679
Sandeep Panda14666d12017-05-08 17:11:03 +05302680 rc = of_property_read_u32_array(of_node,
2681 "qcom,mdss-dsi-panel-status-value",
2682 esd_config->status_value, esd_config->groups * status_len);
2683 if (rc) {
2684 pr_debug("error reading panel status values\n");
2685 memset(esd_config->status_value, 0,
2686 esd_config->groups * status_len);
2687 }
2688
Sandeep Panda5a91e482017-10-10 10:04:00 +05302689 if (panel->esd_config.status_mode == ESD_MODE_REG_READ)
2690 esd_mode = "register_read";
2691 else if (panel->esd_config.status_mode == ESD_MODE_SW_BTA)
2692 esd_mode = "bta_trigger";
2693 else if (panel->esd_config.status_mode == ESD_MODE_PANEL_TE)
2694 esd_mode = "te_check";
2695
2696 pr_info("ESD enabled with mode: %s\n", esd_mode);
2697
Sandeep Panda14666d12017-05-08 17:11:03 +05302698 return 0;
2699
Sandeep Panda79450002017-05-08 17:14:24 +05302700error4:
2701 kfree(esd_config->return_buf);
Sandeep Panda14666d12017-05-08 17:11:03 +05302702error3:
2703 kfree(esd_config->status_value);
2704error2:
2705 kfree(esd_config->status_valid_params);
2706 kfree(esd_config->status_cmds_rlen);
2707error1:
2708 kfree(esd_config->status_cmd.cmds);
2709error:
2710 panel->esd_config.esd_enabled = false;
2711 return rc;
2712}
2713
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002714struct dsi_panel *dsi_panel_get(struct device *parent,
Chandan Uddaraju7e9613a2017-06-01 13:10:55 -07002715 struct device_node *of_node,
2716 int topology_override)
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002717{
2718 struct dsi_panel *panel;
2719 int rc = 0;
2720
2721 panel = kzalloc(sizeof(*panel), GFP_KERNEL);
2722 if (!panel)
2723 return ERR_PTR(-ENOMEM);
2724
2725 panel->name = of_get_property(of_node, "qcom,mdss-dsi-panel-name",
2726 NULL);
2727 if (!panel->name)
2728 panel->name = DSI_PANEL_DEFAULT_LABEL;
2729
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002730 rc = dsi_panel_parse_host_config(panel, of_node);
2731 if (rc) {
2732 pr_err("failed to parse host configuration, rc=%d\n", rc);
2733 goto error;
2734 }
2735
2736 rc = dsi_panel_parse_panel_mode(panel, of_node);
2737 if (rc) {
2738 pr_err("failed to parse panel mode configuration, rc=%d\n", rc);
2739 goto error;
2740 }
2741
2742 rc = dsi_panel_parse_dfps_caps(&panel->dfps_caps, of_node, panel->name);
2743 if (rc)
2744 pr_err("failed to parse dfps configuration, rc=%d\n", rc);
2745
2746 rc = dsi_panel_parse_phy_props(&panel->phy_props, of_node, panel->name);
2747 if (rc) {
2748 pr_err("failed to parse panel physical dimension, rc=%d\n", rc);
2749 goto error;
2750 }
2751
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002752 rc = dsi_panel_parse_power_cfg(parent, panel, of_node);
2753 if (rc)
2754 pr_err("failed to parse power config, rc=%d\n", rc);
2755
2756 rc = dsi_panel_parse_gpios(panel, of_node);
2757 if (rc)
2758 pr_err("failed to parse panel gpios, rc=%d\n", rc);
2759
2760 rc = dsi_panel_parse_bl_config(panel, of_node);
2761 if (rc)
2762 pr_err("failed to parse backlight config, rc=%d\n", rc);
2763
Dhaval Patel60e1ff52017-02-18 21:03:40 -08002764
Narendra Muppallad4081e12017-04-20 19:24:08 -07002765 rc = dsi_panel_parse_misc_features(panel, of_node);
Veera Sundaram Sankaranc4a90032017-04-21 13:54:14 -07002766 if (rc)
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002767 pr_err("failed to parse misc features, rc=%d\n", rc);
Veera Sundaram Sankaranc4a90032017-04-21 13:54:14 -07002768
Ping Li898b1bf2017-02-09 18:03:28 -08002769 rc = dsi_panel_parse_hdr_config(panel, of_node);
2770 if (rc)
2771 pr_err("failed to parse hdr config, rc=%d\n", rc);
2772
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002773 rc = dsi_panel_get_mode_count(panel, of_node);
2774 if (rc) {
2775 pr_err("failed to get mode count, rc=%d\n", rc);
2776 goto error;
2777 }
2778
Jeykumar Sankarana7c7bbe2017-05-31 18:12:05 -07002779 rc = dsi_panel_parse_dms_info(panel, of_node);
2780 if (rc)
2781 pr_debug("failed to get dms info, rc=%d\n", rc);
2782
Sandeep Panda14666d12017-05-08 17:11:03 +05302783 rc = dsi_panel_parse_esd_config(panel, of_node);
Sandeep Panda5a91e482017-10-10 10:04:00 +05302784 if (rc)
Sandeep Panda14666d12017-05-08 17:11:03 +05302785 pr_debug("failed to parse esd config, rc=%d\n", rc);
Sandeep Panda14666d12017-05-08 17:11:03 +05302786
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002787 panel->panel_of_node = of_node;
2788 drm_panel_init(&panel->drm_panel);
2789 mutex_init(&panel->panel_lock);
2790 panel->parent = parent;
2791 return panel;
2792error:
2793 kfree(panel);
2794 return ERR_PTR(rc);
2795}
2796
2797void dsi_panel_put(struct dsi_panel *panel)
2798{
Sandeep Panda14666d12017-05-08 17:11:03 +05302799 /* free resources allocated for ESD check */
2800 dsi_panel_esd_config_deinit(&panel->esd_config);
2801
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002802 kfree(panel);
2803}
2804
2805int dsi_panel_drv_init(struct dsi_panel *panel,
2806 struct mipi_dsi_host *host)
2807{
2808 int rc = 0;
2809 struct mipi_dsi_device *dev;
2810
2811 if (!panel || !host) {
Alexander Beykunac182352017-02-27 17:46:51 -05002812 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002813 return -EINVAL;
2814 }
2815
2816 mutex_lock(&panel->panel_lock);
2817
2818 dev = &panel->mipi_device;
2819
2820 dev->host = host;
2821 /*
2822 * We dont have device structure since panel is not a device node.
2823 * When using drm panel framework, the device is probed when the host is
2824 * create.
2825 */
2826 dev->channel = 0;
2827 dev->lanes = 4;
2828
2829 panel->host = host;
2830 rc = dsi_panel_vreg_get(panel);
2831 if (rc) {
Alexander Beykunac182352017-02-27 17:46:51 -05002832 pr_err("[%s] failed to get panel regulators, rc=%d\n",
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002833 panel->name, rc);
Ajay Singh Parmard687e092016-06-27 11:46:54 -07002834 goto exit;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002835 }
2836
2837 rc = dsi_panel_pinctrl_init(panel);
2838 if (rc) {
2839 pr_err("[%s] failed to init pinctrl, rc=%d\n", panel->name, rc);
2840 goto error_vreg_put;
2841 }
2842
2843 rc = dsi_panel_gpio_request(panel);
2844 if (rc) {
2845 pr_err("[%s] failed to request gpios, rc=%d\n", panel->name,
2846 rc);
2847 goto error_pinctrl_deinit;
2848 }
2849
2850 rc = dsi_panel_bl_register(panel);
2851 if (rc) {
Ajay Singh Parmard687e092016-06-27 11:46:54 -07002852 if (rc != -EPROBE_DEFER)
2853 pr_err("[%s] failed to register backlight, rc=%d\n",
2854 panel->name, rc);
2855 goto error_gpio_release;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002856 }
Ajay Singh Parmard687e092016-06-27 11:46:54 -07002857
2858 goto exit;
2859
2860error_gpio_release:
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002861 (void)dsi_panel_gpio_release(panel);
2862error_pinctrl_deinit:
2863 (void)dsi_panel_pinctrl_deinit(panel);
2864error_vreg_put:
2865 (void)dsi_panel_vreg_put(panel);
Ajay Singh Parmard687e092016-06-27 11:46:54 -07002866exit:
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002867 mutex_unlock(&panel->panel_lock);
2868 return rc;
2869}
2870
2871int dsi_panel_drv_deinit(struct dsi_panel *panel)
2872{
2873 int rc = 0;
2874
2875 if (!panel) {
Alexander Beykunac182352017-02-27 17:46:51 -05002876 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002877 return -EINVAL;
2878 }
2879
2880 mutex_lock(&panel->panel_lock);
2881
2882 rc = dsi_panel_bl_unregister(panel);
2883 if (rc)
2884 pr_err("[%s] failed to unregister backlight, rc=%d\n",
2885 panel->name, rc);
2886
2887 rc = dsi_panel_gpio_release(panel);
2888 if (rc)
2889 pr_err("[%s] failed to release gpios, rc=%d\n", panel->name,
2890 rc);
2891
2892 rc = dsi_panel_pinctrl_deinit(panel);
2893 if (rc)
2894 pr_err("[%s] failed to deinit gpios, rc=%d\n", panel->name,
2895 rc);
2896
2897 rc = dsi_panel_vreg_put(panel);
2898 if (rc)
2899 pr_err("[%s] failed to put regs, rc=%d\n", panel->name, rc);
2900
2901 panel->host = NULL;
2902 memset(&panel->mipi_device, 0x0, sizeof(panel->mipi_device));
2903
2904 mutex_unlock(&panel->panel_lock);
2905 return rc;
2906}
2907
2908int dsi_panel_validate_mode(struct dsi_panel *panel,
2909 struct dsi_display_mode *mode)
2910{
2911 return 0;
2912}
2913
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002914int dsi_panel_get_mode_count(struct dsi_panel *panel,
2915 struct device_node *of_node)
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002916{
Jeykumar Sankarana7c7bbe2017-05-31 18:12:05 -07002917 const u32 SINGLE_MODE_SUPPORT = 1;
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002918 struct device_node *timings_np;
2919 int count, rc = 0;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002920
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002921 if (!of_node || !panel) {
Alexander Beykunac182352017-02-27 17:46:51 -05002922 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002923 return -EINVAL;
2924 }
2925
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002926 panel->num_timing_nodes = 0;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002927
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002928 timings_np = of_get_child_by_name(of_node,
2929 "qcom,mdss-dsi-display-timings");
2930 if (!timings_np) {
2931 pr_err("no display timing nodes defined\n");
2932 rc = -EINVAL;
2933 goto error;
2934 }
2935
2936 count = of_get_child_count(timings_np);
2937 if (!count || count > DSI_MODE_MAX) {
2938 pr_err("invalid count of timing nodes: %d\n", count);
2939 rc = -EINVAL;
2940 goto error;
2941 }
Jeykumar Sankarana7c7bbe2017-05-31 18:12:05 -07002942
2943 /* No multiresolution support is available for video mode panels */
2944 if (panel->panel_mode != DSI_OP_CMD_MODE)
2945 count = SINGLE_MODE_SUPPORT;
2946
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002947 panel->num_timing_nodes = count;
2948
2949error:
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002950 return rc;
2951}
2952
2953int dsi_panel_get_phy_props(struct dsi_panel *panel,
2954 struct dsi_panel_phy_props *phy_props)
2955{
2956 int rc = 0;
2957
2958 if (!panel || !phy_props) {
Alexander Beykunac182352017-02-27 17:46:51 -05002959 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002960 return -EINVAL;
2961 }
2962
2963 mutex_lock(&panel->panel_lock);
2964
2965 memcpy(phy_props, &panel->phy_props, sizeof(*phy_props));
2966
2967 mutex_unlock(&panel->panel_lock);
2968 return rc;
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002969}
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002970
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002971int dsi_panel_get_dfps_caps(struct dsi_panel *panel,
2972 struct dsi_dfps_capabilities *dfps_caps)
2973{
2974 int rc = 0;
2975
2976 if (!panel || !dfps_caps) {
Alexander Beykunac182352017-02-27 17:46:51 -05002977 pr_err("invalid params\n");
Ajay Singh Parmar62f795b2016-06-10 23:20:23 -07002978 return -EINVAL;
2979 }
2980
2981 mutex_lock(&panel->panel_lock);
2982
2983 memcpy(dfps_caps, &panel->dfps_caps, sizeof(*dfps_caps));
2984
2985 mutex_unlock(&panel->panel_lock);
2986 return rc;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002987}
2988
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002989void dsi_panel_put_mode(struct dsi_display_mode *mode)
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07002990{
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07002991 int i;
2992
2993 if (!mode->priv_info)
2994 return;
2995
2996 for (i = 0; i < DSI_CMD_SET_MAX; i++)
2997 dsi_panel_destroy_cmd_packets(&mode->priv_info->cmd_sets[i]);
2998
2999 kfree(mode->priv_info);
3000}
3001
3002int dsi_panel_get_mode(struct dsi_panel *panel,
3003 u32 index, struct dsi_display_mode *mode,
3004 int topology_override)
3005{
3006 struct device_node *timings_np, *child_np;
3007 struct dsi_display_mode_priv_info *prv_info;
3008 u32 child_idx = 0;
3009 int rc = 0, num_timings;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003010
3011 if (!panel || !mode) {
Alexander Beykunac182352017-02-27 17:46:51 -05003012 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003013 return -EINVAL;
3014 }
3015
3016 mutex_lock(&panel->panel_lock);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003017
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003018 mode->priv_info = kzalloc(sizeof(*mode->priv_info), GFP_KERNEL);
3019 if (!mode->priv_info) {
3020 rc = -ENOMEM;
3021 goto done;
3022 }
3023
3024 prv_info = mode->priv_info;
3025
3026 timings_np = of_get_child_by_name(panel->panel_of_node,
3027 "qcom,mdss-dsi-display-timings");
3028 if (!timings_np) {
3029 pr_err("no display timing nodes defined\n");
3030 rc = -EINVAL;
3031 goto parse_fail;
3032 }
3033
3034 num_timings = of_get_child_count(timings_np);
3035 if (!num_timings || num_timings > DSI_MODE_MAX) {
3036 pr_err("invalid count of timing nodes: %d\n", num_timings);
3037 rc = -EINVAL;
3038 goto parse_fail;
3039 }
3040
3041 for_each_child_of_node(timings_np, child_np) {
3042 if (index != child_idx++)
3043 continue;
3044
3045 rc = dsi_panel_parse_timing(&mode->timing, child_np);
3046 if (rc) {
3047 pr_err("failed to parse panel timing, rc=%d\n", rc);
3048 goto parse_fail;
3049 }
3050
3051 rc = dsi_panel_parse_dsc_params(mode, child_np);
3052 if (rc) {
3053 pr_err("failed to parse dsc params, rc=%d\n", rc);
3054 goto parse_fail;
3055 }
3056
3057 rc = dsi_panel_parse_topology(prv_info, child_np,
3058 topology_override);
3059 if (rc) {
3060 pr_err("failed to parse panel topology, rc=%d\n", rc);
3061 goto parse_fail;
3062 }
3063
3064 rc = dsi_panel_parse_cmd_sets(prv_info, child_np);
3065 if (rc) {
3066 pr_err("failed to parse command sets, rc=%d\n", rc);
3067 goto parse_fail;
3068 }
3069
3070 rc = dsi_panel_parse_jitter_config(mode, child_np);
3071 if (rc)
3072 pr_err(
3073 "failed to parse panel jitter config, rc=%d\n", rc);
3074
3075 rc = dsi_panel_parse_phy_timing(mode, child_np);
3076 if (rc) {
3077 pr_err(
3078 "failed to parse panel phy timings, rc=%d\n", rc);
3079 goto parse_fail;
3080 }
Jeykumar Sankaran736d79d2017-10-05 17:44:24 -07003081
3082 rc = dsi_panel_parse_partial_update_caps(mode, child_np);
3083 if (rc)
3084 pr_err("failed to partial update caps, rc=%d\n", rc);
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003085 }
3086 goto done;
3087
3088parse_fail:
3089 kfree(mode->priv_info);
3090 mode->priv_info = NULL;
3091done:
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003092 mutex_unlock(&panel->panel_lock);
3093 return rc;
3094}
3095
3096int dsi_panel_get_host_cfg_for_mode(struct dsi_panel *panel,
3097 struct dsi_display_mode *mode,
3098 struct dsi_host_config *config)
3099{
3100 int rc = 0;
3101
3102 if (!panel || !mode || !config) {
Alexander Beykunac182352017-02-27 17:46:51 -05003103 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003104 return -EINVAL;
3105 }
3106
3107 mutex_lock(&panel->panel_lock);
3108
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003109 config->panel_mode = panel->panel_mode;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003110 memcpy(&config->common_config, &panel->host_config,
3111 sizeof(config->common_config));
3112
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003113 if (panel->panel_mode == DSI_OP_VIDEO_MODE) {
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003114 memcpy(&config->u.video_engine, &panel->video_config,
3115 sizeof(config->u.video_engine));
3116 } else {
3117 memcpy(&config->u.cmd_engine, &panel->cmd_config,
3118 sizeof(config->u.cmd_engine));
3119 }
3120
3121 memcpy(&config->video_timing, &mode->timing,
3122 sizeof(config->video_timing));
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003123 config->video_timing.dsc_enabled = mode->priv_info->dsc_enabled;
3124 config->video_timing.dsc = &mode->priv_info->dsc;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003125
Vara Reddy812bd722017-09-20 07:19:19 -07003126 config->bit_clk_rate_hz = mode->priv_info->clk_rate_hz;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003127 config->esc_clk_rate_hz = 19200000;
3128 mutex_unlock(&panel->panel_lock);
3129 return rc;
3130}
3131
3132int dsi_panel_pre_prepare(struct dsi_panel *panel)
3133{
3134 int rc = 0;
3135
3136 if (!panel) {
Alexander Beykunac182352017-02-27 17:46:51 -05003137 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003138 return -EINVAL;
3139 }
3140
3141 mutex_lock(&panel->panel_lock);
3142
3143 /* If LP11_INIT is set, panel will be powered up during prepare() */
3144 if (panel->lp11_init)
3145 goto error;
3146
3147 rc = dsi_panel_power_on(panel);
3148 if (rc) {
Alexander Beykunac182352017-02-27 17:46:51 -05003149 pr_err("[%s] panel power on failed, rc=%d\n", panel->name, rc);
3150 goto error;
3151 }
3152
3153error:
3154 mutex_unlock(&panel->panel_lock);
3155 return rc;
3156}
3157
3158int dsi_panel_update_pps(struct dsi_panel *panel)
3159{
3160 int rc = 0;
3161 struct dsi_panel_cmd_set *set = NULL;
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003162 struct dsi_display_mode_priv_info *priv_info = NULL;
Alexander Beykunac182352017-02-27 17:46:51 -05003163
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003164 if (!panel || !panel->cur_mode) {
Alexander Beykunac182352017-02-27 17:46:51 -05003165 pr_err("invalid params\n");
3166 return -EINVAL;
3167 }
3168
3169 mutex_lock(&panel->panel_lock);
3170
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003171 priv_info = panel->cur_mode->priv_info;
Alexander Beykunac182352017-02-27 17:46:51 -05003172
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003173 set = &priv_info->cmd_sets[DSI_CMD_SET_PPS];
3174
3175 dsi_dsc_create_pps_buf_cmd(&priv_info->dsc, panel->dsc_pps_cmd, 0);
Alexander Beykunac182352017-02-27 17:46:51 -05003176 rc = dsi_panel_create_cmd_packets(panel->dsc_pps_cmd,
3177 DSI_CMD_PPS_SIZE, 1, set->cmds);
3178 if (rc) {
3179 pr_err("failed to create cmd packets, rc=%d\n", rc);
3180 goto error;
3181 }
3182
3183 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_PPS);
3184 if (rc) {
3185 pr_err("[%s] failed to send DSI_CMD_SET_PPS cmds, rc=%d\n",
3186 panel->name, rc);
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003187 goto error;
3188 }
3189
3190error:
3191 mutex_unlock(&panel->panel_lock);
3192 return rc;
3193}
3194
Clarence Ip5f00c0602017-08-02 14:26:31 -04003195int dsi_panel_set_lp1(struct dsi_panel *panel)
3196{
3197 int rc = 0;
3198
3199 if (!panel) {
3200 pr_err("invalid params\n");
3201 return -EINVAL;
3202 }
3203
3204 mutex_lock(&panel->panel_lock);
3205 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP1);
3206 if (rc)
3207 pr_err("[%s] failed to send DSI_CMD_SET_LP1 cmd, rc=%d\n",
3208 panel->name, rc);
3209 mutex_unlock(&panel->panel_lock);
3210 return rc;
3211}
3212
3213int dsi_panel_set_lp2(struct dsi_panel *panel)
3214{
3215 int rc = 0;
3216
3217 if (!panel) {
3218 pr_err("invalid params\n");
3219 return -EINVAL;
3220 }
3221
3222 mutex_lock(&panel->panel_lock);
3223 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP2);
3224 if (rc)
3225 pr_err("[%s] failed to send DSI_CMD_SET_LP2 cmd, rc=%d\n",
3226 panel->name, rc);
3227 mutex_unlock(&panel->panel_lock);
3228 return rc;
3229}
3230
3231int dsi_panel_set_nolp(struct dsi_panel *panel)
3232{
3233 int rc = 0;
3234
3235 if (!panel) {
3236 pr_err("invalid params\n");
3237 return -EINVAL;
3238 }
3239
3240 mutex_lock(&panel->panel_lock);
3241 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_NOLP);
3242 if (rc)
3243 pr_err("[%s] failed to send DSI_CMD_SET_NOLP cmd, rc=%d\n",
3244 panel->name, rc);
3245 mutex_unlock(&panel->panel_lock);
3246 return rc;
3247}
3248
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003249int dsi_panel_prepare(struct dsi_panel *panel)
3250{
3251 int rc = 0;
3252
3253 if (!panel) {
Alexander Beykunac182352017-02-27 17:46:51 -05003254 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003255 return -EINVAL;
3256 }
3257
3258 mutex_lock(&panel->panel_lock);
3259
3260 if (panel->lp11_init) {
3261 rc = dsi_panel_power_on(panel);
3262 if (rc) {
3263 pr_err("[%s] panel power on failed, rc=%d\n",
3264 panel->name, rc);
3265 goto error;
3266 }
3267 }
3268
3269 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_PRE_ON);
3270 if (rc) {
3271 pr_err("[%s] failed to send DSI_CMD_SET_PRE_ON cmds, rc=%d\n",
3272 panel->name, rc);
3273 goto error;
3274 }
3275
3276error:
3277 mutex_unlock(&panel->panel_lock);
3278 return rc;
3279}
3280
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003281static int dsi_panel_roi_prepare_dcs_cmds(struct dsi_panel_cmd_set *set,
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04003282 struct dsi_rect *roi, int ctrl_idx, int unicast)
3283{
3284 static const int ROI_CMD_LEN = 5;
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003285
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04003286 int rc = 0;
3287
3288 /* DTYPE_DCS_LWRITE */
3289 static char *caset, *paset;
3290
3291 set->cmds = NULL;
3292
3293 caset = kzalloc(ROI_CMD_LEN, GFP_KERNEL);
3294 if (!caset) {
3295 rc = -ENOMEM;
3296 goto exit;
3297 }
3298 caset[0] = 0x2a;
3299 caset[1] = (roi->x & 0xFF00) >> 8;
3300 caset[2] = roi->x & 0xFF;
3301 caset[3] = ((roi->x - 1 + roi->w) & 0xFF00) >> 8;
3302 caset[4] = (roi->x - 1 + roi->w) & 0xFF;
3303
3304 paset = kzalloc(ROI_CMD_LEN, GFP_KERNEL);
3305 if (!paset) {
3306 rc = -ENOMEM;
3307 goto error_free_mem;
3308 }
3309 paset[0] = 0x2b;
3310 paset[1] = (roi->y & 0xFF00) >> 8;
3311 paset[2] = roi->y & 0xFF;
3312 paset[3] = ((roi->y - 1 + roi->h) & 0xFF00) >> 8;
3313 paset[4] = (roi->y - 1 + roi->h) & 0xFF;
3314
3315 set->type = DSI_CMD_SET_ROI;
3316 set->state = DSI_CMD_SET_STATE_LP;
3317 set->count = 2; /* send caset + paset together */
3318 set->cmds = kcalloc(set->count, sizeof(*set->cmds), GFP_KERNEL);
3319 if (!set->cmds) {
3320 rc = -ENOMEM;
3321 goto error_free_mem;
3322 }
3323 set->cmds[0].msg.channel = 0;
3324 set->cmds[0].msg.type = MIPI_DSI_DCS_LONG_WRITE;
3325 set->cmds[0].msg.flags = unicast ? MIPI_DSI_MSG_UNICAST : 0;
3326 set->cmds[0].msg.ctrl = unicast ? ctrl_idx : 0;
3327 set->cmds[0].msg.tx_len = ROI_CMD_LEN;
3328 set->cmds[0].msg.tx_buf = caset;
3329 set->cmds[0].msg.rx_len = 0;
3330 set->cmds[0].msg.rx_buf = 0;
3331 set->cmds[0].last_command = 0;
3332 set->cmds[0].post_wait_ms = 1;
3333
3334 set->cmds[1].msg.channel = 0;
3335 set->cmds[1].msg.type = MIPI_DSI_DCS_LONG_WRITE;
3336 set->cmds[1].msg.flags = unicast ? MIPI_DSI_MSG_UNICAST : 0;
3337 set->cmds[1].msg.ctrl = unicast ? ctrl_idx : 0;
3338 set->cmds[1].msg.tx_len = ROI_CMD_LEN;
3339 set->cmds[1].msg.tx_buf = paset;
3340 set->cmds[1].msg.rx_len = 0;
3341 set->cmds[1].msg.rx_buf = 0;
3342 set->cmds[1].last_command = 1;
3343 set->cmds[1].post_wait_ms = 1;
3344
3345 goto exit;
3346
3347error_free_mem:
3348 kfree(caset);
3349 kfree(paset);
3350 kfree(set->cmds);
3351
3352exit:
3353 return rc;
3354}
3355
3356int dsi_panel_send_roi_dcs(struct dsi_panel *panel, int ctrl_idx,
3357 struct dsi_rect *roi)
3358{
3359 int rc = 0;
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003360 struct dsi_panel_cmd_set *set;
3361 struct dsi_display_mode_priv_info *priv_info;
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04003362
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003363 if (!panel || !panel->cur_mode) {
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04003364 pr_err("Invalid params\n");
3365 return -EINVAL;
3366 }
3367
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003368 priv_info = panel->cur_mode->priv_info;
3369 set = &priv_info->cmd_sets[DSI_CMD_SET_ROI];
3370
3371 rc = dsi_panel_roi_prepare_dcs_cmds(set, roi, ctrl_idx, true);
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04003372 if (rc) {
3373 pr_err("[%s] failed to prepare DSI_CMD_SET_ROI cmds, rc=%d\n",
3374 panel->name, rc);
3375 return rc;
3376 }
3377 pr_debug("[%s] send roi x %d y %d w %d h %d\n", panel->name,
3378 roi->x, roi->y, roi->w, roi->h);
3379
3380 mutex_lock(&panel->panel_lock);
3381
3382 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_ROI);
3383 if (rc)
3384 pr_err("[%s] failed to send DSI_CMD_SET_ROI cmds, rc=%d\n",
3385 panel->name, rc);
3386
3387 mutex_unlock(&panel->panel_lock);
3388
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -07003389 dsi_panel_destroy_cmd_packets(set);
Lloyd Atkinsone53b7372017-03-22 17:16:47 -04003390
3391 return rc;
3392}
3393
Jeykumar Sankarana7c7bbe2017-05-31 18:12:05 -07003394int dsi_panel_switch(struct dsi_panel *panel)
3395{
3396 int rc = 0;
3397
3398 if (!panel) {
3399 pr_err("Invalid params\n");
3400 return -EINVAL;
3401 }
3402
3403 mutex_lock(&panel->panel_lock);
3404
3405 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_TIMING_SWITCH);
3406 if (rc)
3407 pr_err("[%s] failed to send DSI_CMD_SET_TIMING_SWITCH cmds, rc=%d\n",
3408 panel->name, rc);
3409
3410 mutex_unlock(&panel->panel_lock);
3411 return rc;
3412}
3413
3414int dsi_panel_post_switch(struct dsi_panel *panel)
3415{
3416 int rc = 0;
3417
3418 if (!panel) {
3419 pr_err("Invalid params\n");
3420 return -EINVAL;
3421 }
3422
3423 mutex_lock(&panel->panel_lock);
3424
3425 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_TIMING_SWITCH);
3426 if (rc)
3427 pr_err("[%s] failed to send DSI_CMD_SET_POST_TIMING_SWITCH cmds, rc=%d\n",
3428 panel->name, rc);
3429
3430 mutex_unlock(&panel->panel_lock);
3431 return rc;
3432}
3433
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003434int dsi_panel_enable(struct dsi_panel *panel)
3435{
3436 int rc = 0;
3437
3438 if (!panel) {
3439 pr_err("Invalid params\n");
3440 return -EINVAL;
3441 }
3442
3443 mutex_lock(&panel->panel_lock);
3444
3445 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_ON);
3446 if (rc) {
3447 pr_err("[%s] failed to send DSI_CMD_SET_ON cmds, rc=%d\n",
3448 panel->name, rc);
3449 }
Padmanabhan Komandurudbd2fb02016-12-02 15:18:49 +05303450 panel->panel_initialized = true;
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003451 mutex_unlock(&panel->panel_lock);
3452 return rc;
3453}
3454
3455int dsi_panel_post_enable(struct dsi_panel *panel)
3456{
3457 int rc = 0;
3458
3459 if (!panel) {
Alexander Beykunac182352017-02-27 17:46:51 -05003460 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003461 return -EINVAL;
3462 }
3463
3464 mutex_lock(&panel->panel_lock);
3465
3466 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_ON);
3467 if (rc) {
3468 pr_err("[%s] failed to send DSI_CMD_SET_POST_ON cmds, rc=%d\n",
3469 panel->name, rc);
3470 goto error;
3471 }
3472error:
3473 mutex_unlock(&panel->panel_lock);
3474 return rc;
3475}
3476
3477int dsi_panel_pre_disable(struct dsi_panel *panel)
3478{
3479 int rc = 0;
3480
3481 if (!panel) {
Alexander Beykunac182352017-02-27 17:46:51 -05003482 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003483 return -EINVAL;
3484 }
3485
3486 mutex_lock(&panel->panel_lock);
3487
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003488 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_PRE_OFF);
3489 if (rc) {
3490 pr_err("[%s] failed to send DSI_CMD_SET_PRE_OFF cmds, rc=%d\n",
3491 panel->name, rc);
3492 goto error;
3493 }
3494
3495error:
3496 mutex_unlock(&panel->panel_lock);
3497 return rc;
3498}
3499
3500int dsi_panel_disable(struct dsi_panel *panel)
3501{
3502 int rc = 0;
3503
3504 if (!panel) {
Alexander Beykunac182352017-02-27 17:46:51 -05003505 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003506 return -EINVAL;
3507 }
3508
3509 mutex_lock(&panel->panel_lock);
3510
3511 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_OFF);
3512 if (rc) {
3513 pr_err("[%s] failed to send DSI_CMD_SET_OFF cmds, rc=%d\n",
3514 panel->name, rc);
3515 goto error;
3516 }
Veera Sundaram Sankaranbb3680f2017-04-21 13:20:46 -07003517 panel->panel_initialized = false;
3518
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003519error:
3520 mutex_unlock(&panel->panel_lock);
3521 return rc;
3522}
3523
3524int dsi_panel_unprepare(struct dsi_panel *panel)
3525{
3526 int rc = 0;
3527
3528 if (!panel) {
Alexander Beykunac182352017-02-27 17:46:51 -05003529 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003530 return -EINVAL;
3531 }
3532
3533 mutex_lock(&panel->panel_lock);
3534
3535 rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_OFF);
3536 if (rc) {
3537 pr_err("[%s] failed to send DSI_CMD_SET_POST_OFF cmds, rc=%d\n",
3538 panel->name, rc);
3539 goto error;
3540 }
3541
3542 if (panel->lp11_init) {
3543 rc = dsi_panel_power_off(panel);
3544 if (rc) {
3545 pr_err("[%s] panel power_Off failed, rc=%d\n",
3546 panel->name, rc);
3547 goto error;
3548 }
3549 }
3550error:
3551 mutex_unlock(&panel->panel_lock);
3552 return rc;
3553}
3554
3555int dsi_panel_post_unprepare(struct dsi_panel *panel)
3556{
3557 int rc = 0;
3558
3559 if (!panel) {
Alexander Beykunac182352017-02-27 17:46:51 -05003560 pr_err("invalid params\n");
Ajay Singh Parmar4fa53172016-05-16 17:54:30 -07003561 return -EINVAL;
3562 }
3563
3564 mutex_lock(&panel->panel_lock);
3565
3566 if (!panel->lp11_init) {
3567 rc = dsi_panel_power_off(panel);
3568 if (rc) {
3569 pr_err("[%s] panel power_Off failed, rc=%d\n",
3570 panel->name, rc);
3571 goto error;
3572 }
3573 }
3574error:
3575 mutex_unlock(&panel->panel_lock);
3576 return rc;
3577}