amlogic/media: lcd: Fix division by zero
[platform/kernel/linux-amlogic.git] / drivers / amlogic / media / vout / lcd / lcd_common.c
1 /*
2  * drivers/amlogic/media/vout/lcd/lcd_common.c
3  *
4  * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  */
17
18 #include <linux/init.h>
19 #include <linux/version.h>
20 #include <linux/types.h>
21 #include <linux/slab.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/platform_device.h>
25 #include <linux/delay.h>
26 #include <linux/io.h>
27 #include <linux/of.h>
28 #include <linux/reset.h>
29 #include <linux/clk.h>
30 #include <linux/amlogic/media/vout/lcd/lcd_vout.h>
31 #include <linux/amlogic/media/vout/lcd/lcd_notify.h>
32 #include <linux/amlogic/media/vout/lcd/lcd_unifykey.h>
33 #include <linux/amlogic/media/vout/vinfo.h>
34
35 #include "lcd_common.h"
36 #include "lcd_reg.h"
37
38 /* **********************************
39  * lcd type
40  * **********************************
41  */
42 struct lcd_type_match_s {
43         char *name;
44         enum lcd_type_e type;
45 };
46
47 static struct lcd_type_match_s lcd_type_match_table[] = {
48         {"ttl",      LCD_TTL},
49         {"lvds",     LCD_LVDS},
50         {"vbyone",   LCD_VBYONE},
51         {"mipi",     LCD_MIPI},
52         {"minilvds", LCD_MLVDS},
53         {"p2p",      LCD_P2P},
54         {"invalid",  LCD_TYPE_MAX},
55 };
56
57 int lcd_type_str_to_type(const char *str)
58 {
59         int i;
60         int type = LCD_TYPE_MAX;
61
62         for (i = 0; i < LCD_TYPE_MAX; i++) {
63                 if (!strcmp(str, lcd_type_match_table[i].name)) {
64                         type = lcd_type_match_table[i].type;
65                         break;
66                 }
67         }
68         return type;
69 }
70
71 char *lcd_type_type_to_str(int type)
72 {
73         int i;
74         char *str = lcd_type_match_table[LCD_TYPE_MAX].name;
75
76         for (i = 0; i < LCD_TYPE_MAX; i++) {
77                 if (type == lcd_type_match_table[i].type) {
78                         str = lcd_type_match_table[i].name;
79                         break;
80                 }
81         }
82         return str;
83 }
84
85 static char *lcd_mode_table[] = {
86         "tv",
87         "tablet",
88         "invalid",
89 };
90
91 unsigned char lcd_mode_str_to_mode(const char *str)
92 {
93         unsigned char mode;
94
95         for (mode = 0; mode < ARRAY_SIZE(lcd_mode_table); mode++) {
96                 if (!strcmp(str, lcd_mode_table[mode]))
97                         break;
98         }
99         return mode;
100 }
101
102 char *lcd_mode_mode_to_str(int mode)
103 {
104         return lcd_mode_table[mode];
105 }
106
107 /* **********************************
108  * lcd gpio
109  * **********************************
110  */
111
112 void lcd_cpu_gpio_probe(unsigned int index)
113 {
114         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
115         struct lcd_cpu_gpio_s *cpu_gpio;
116         const char *str;
117         int ret;
118
119         if (index >= LCD_CPU_GPIO_NUM_MAX) {
120                 LCDERR("gpio index %d, exit\n", index);
121                 return;
122         }
123         cpu_gpio = &lcd_drv->lcd_config->lcd_power->cpu_gpio[index];
124         if (cpu_gpio->probe_flag) {
125                 if (lcd_debug_print_flag) {
126                         LCDPR("gpio %s[%d] is already registered\n",
127                                 cpu_gpio->name, index);
128                 }
129                 return;
130         }
131
132         /* get gpio name */
133         ret = of_property_read_string_index(lcd_drv->dev->of_node,
134                 "lcd_cpu_gpio_names", index, &str);
135         if (ret) {
136                 LCDERR("failed to get lcd_cpu_gpio_names: %d\n", index);
137                 str = "unknown";
138         }
139         strcpy(cpu_gpio->name, str);
140
141         /* init gpio flag */
142         cpu_gpio->probe_flag = 1;
143         cpu_gpio->register_flag = 0;
144 }
145
146 static int lcd_cpu_gpio_register(unsigned int index, int init_value)
147 {
148         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
149         struct lcd_cpu_gpio_s *cpu_gpio;
150         int value;
151
152         if (index >= LCD_CPU_GPIO_NUM_MAX) {
153                 LCDERR("%s: gpio index %d, exit\n", __func__, index);
154                 return -1;
155         }
156         cpu_gpio = &lcd_drv->lcd_config->lcd_power->cpu_gpio[index];
157         if (cpu_gpio->probe_flag == 0) {
158                 LCDERR("%s: gpio [%d] is not probed, exit\n", __func__, index);
159                 return -1;
160         }
161         if (cpu_gpio->register_flag) {
162                 LCDPR("%s: gpio %s[%d] is already registered\n",
163                         __func__, cpu_gpio->name, index);
164                 return 0;
165         }
166
167         switch (init_value) {
168         case LCD_GPIO_OUTPUT_LOW:
169                 value = GPIOD_OUT_LOW;
170                 break;
171         case LCD_GPIO_OUTPUT_HIGH:
172                 value = GPIOD_OUT_HIGH;
173                 break;
174         case LCD_GPIO_INPUT:
175         default:
176                 value = GPIOD_IN;
177                 break;
178         }
179
180         /* request gpio */
181         cpu_gpio->gpio = devm_gpiod_get_index(lcd_drv->dev,
182                 "lcd_cpu", index, value);
183
184         if (IS_ERR(cpu_gpio->gpio)) {
185                 LCDERR("register gpio %s[%d]: %p, err: %d\n",
186                         cpu_gpio->name, index, cpu_gpio->gpio,
187                         IS_ERR(cpu_gpio->gpio));
188                 return -1;
189         }
190         cpu_gpio->register_flag = 1;
191         if (lcd_debug_print_flag) {
192                 LCDPR("register gpio %s[%d]: %p, init value: %d\n",
193                         cpu_gpio->name, index, cpu_gpio->gpio, init_value);
194         }
195
196         return 0;
197 }
198
199 void lcd_cpu_gpio_set(unsigned int index, int value)
200 {
201         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
202         struct lcd_cpu_gpio_s *cpu_gpio;
203
204         if (index >= LCD_CPU_GPIO_NUM_MAX) {
205                 LCDERR("gpio index %d, exit\n", index);
206                 return;
207         }
208         cpu_gpio = &lcd_drv->lcd_config->lcd_power->cpu_gpio[index];
209         if (cpu_gpio->probe_flag == 0) {
210                 LCDERR("%s: gpio [%d] is not probed, exit\n", __func__, index);
211                 return;
212         }
213         if (cpu_gpio->register_flag == 0) {
214                 lcd_cpu_gpio_register(index, value);
215                 return;
216         }
217
218         if (IS_ERR_OR_NULL(cpu_gpio->gpio)) {
219                 LCDERR("gpio %s[%d]: %p, err: %ld\n",
220                         cpu_gpio->name, index, cpu_gpio->gpio,
221                         PTR_ERR(cpu_gpio->gpio));
222                 return;
223         }
224
225         switch (value) {
226         case LCD_GPIO_OUTPUT_LOW:
227         case LCD_GPIO_OUTPUT_HIGH:
228                 gpiod_direction_output(cpu_gpio->gpio, value);
229                 break;
230         case LCD_GPIO_INPUT:
231         default:
232                 gpiod_direction_input(cpu_gpio->gpio);
233                 break;
234         }
235         if (lcd_debug_print_flag) {
236                 LCDPR("set gpio %s[%d] value: %d\n",
237                         cpu_gpio->name, index, value);
238         }
239 }
240
241 unsigned int lcd_cpu_gpio_get(unsigned int index)
242 {
243         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
244         struct lcd_cpu_gpio_s *cpu_gpio;
245
246         cpu_gpio = &lcd_drv->lcd_config->lcd_power->cpu_gpio[index];
247         if (cpu_gpio->probe_flag == 0) {
248                 LCDERR("%s: gpio [%d] is not probed\n", __func__, index);
249                 return -1;
250         }
251         if (cpu_gpio->register_flag == 0) {
252                 LCDERR("%s: gpio %s[%d] is not registered\n",
253                         __func__, cpu_gpio->name, index);
254                 return -1;
255         }
256         if (IS_ERR_OR_NULL(cpu_gpio->gpio)) {
257                 LCDERR("gpio[%d]: %p, err: %ld\n",
258                         index, cpu_gpio->gpio, PTR_ERR(cpu_gpio->gpio));
259                 return -1;
260         }
261
262         return gpiod_get_value(cpu_gpio->gpio);
263 }
264
265 static char *lcd_ttl_pinmux_str[] = {
266         "ttl_6bit_hvsync_on",      /* 0 */
267         "ttl_6bit_de_on",          /* 1 */
268         "ttl_6bit_hvsync_de_on",   /* 2 */
269         "ttl_6bit_hvsync_de_off",  /* 3 */
270         "ttl_8bit_hvsync_on",      /* 4 */
271         "ttl_8bit_de_on",          /* 5 */
272         "ttl_8bit_hvsync_de_on",   /* 6 */
273         "ttl_8bit_hvsync_de_off",  /* 7 */
274 };
275
276 void lcd_ttl_pinmux_set(int status)
277 {
278         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
279         struct lcd_config_s *pconf;
280         unsigned int base, index;
281
282         if (lcd_debug_print_flag)
283                 LCDPR("%s: %d\n", __func__, status);
284
285         pconf = lcd_drv->lcd_config;
286         if (pconf->lcd_basic.lcd_bits == 6)
287                 base = 0;
288         else
289                 base = 4;
290
291         if (status) {
292                 switch (pconf->lcd_control.ttl_config->sync_valid) {
293                 case 1: /* hvsync */
294                         index = base + 0;
295                         break;
296                 case 2: /* DE */
297                         index = base + 1;
298                         break;
299                 default:
300                 case 3: /* DE + hvsync */
301                         index = base + 2;
302                         break;
303                 }
304         } else {
305                 index = base + 3;
306         }
307
308         if (pconf->pinmux_flag == index) {
309                 LCDPR("pinmux %s is already selected\n",
310                         lcd_ttl_pinmux_str[index]);
311                 return;
312         }
313
314         /* request pinmux */
315         pconf->pin = devm_pinctrl_get_select(lcd_drv->dev,
316                 lcd_ttl_pinmux_str[index]);
317         if (IS_ERR(pconf->pin))
318                 LCDERR("set ttl pinmux %s error\n", lcd_ttl_pinmux_str[index]);
319         else {
320                 if (lcd_debug_print_flag) {
321                         LCDPR("set ttl pinmux %s: %p\n",
322                                 lcd_ttl_pinmux_str[index], pconf->pin);
323                 }
324         }
325         pconf->pinmux_flag = index;
326 }
327
328 static char *lcd_vbyone_pinmux_str[] = {
329         "vbyone",
330         "vbyone_off",
331         "none",
332 };
333
334 /* set VX1_LOCKN && VX1_HTPDN */
335 void lcd_vbyone_pinmux_set(int status)
336 {
337         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
338         struct lcd_config_s *pconf;
339         unsigned int index;
340
341         if (lcd_debug_print_flag)
342                 LCDPR("%s: %d\n", __func__, status);
343
344         pconf = lcd_drv->lcd_config;
345         index = (status) ? 0 : 1;
346
347         if (pconf->pinmux_flag == index) {
348                 LCDPR("pinmux %s is already selected\n",
349                         lcd_vbyone_pinmux_str[index]);
350                 return;
351         }
352
353         pconf->pin = devm_pinctrl_get_select(lcd_drv->dev,
354                 lcd_vbyone_pinmux_str[index]);
355         if (IS_ERR(pconf->pin)) {
356                 LCDERR("set vbyone pinmux %s error\n",
357                         lcd_vbyone_pinmux_str[index]);
358         } else {
359                 if (lcd_debug_print_flag) {
360                         LCDPR("set vbyone pinmux %s: %p\n",
361                                 lcd_vbyone_pinmux_str[index], pconf->pin);
362                 }
363         }
364         pconf->pinmux_flag = index;
365 }
366
367 static char *lcd_tcon_pinmux_str[] = {
368         "tcon",
369         "tcon_off",
370         "none",
371 };
372
373 void lcd_tcon_pinmux_set(int status)
374 {
375         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
376         struct lcd_config_s *pconf;
377         unsigned int index;
378
379         if (lcd_debug_print_flag)
380                 LCDPR("%s: %d\n", __func__, status);
381
382         pconf = lcd_drv->lcd_config;
383         index = (status) ? 0 : 1;
384
385         if (pconf->pinmux_flag == index) {
386                 LCDPR("pinmux %s is already selected\n",
387                         lcd_tcon_pinmux_str[index]);
388                 return;
389         }
390
391         pconf->pin = devm_pinctrl_get_select(lcd_drv->dev,
392                 lcd_tcon_pinmux_str[index]);
393         if (IS_ERR(pconf->pin)) {
394                 LCDERR("set tcon pinmux %s error\n",
395                         lcd_tcon_pinmux_str[index]);
396         } else {
397                 if (lcd_debug_print_flag) {
398                         LCDPR("set tcon pinmux %s: %p\n",
399                                 lcd_tcon_pinmux_str[index], pconf->pin);
400                 }
401         }
402         pconf->pinmux_flag = index;
403 }
404
405 int lcd_power_load_from_dts(struct lcd_config_s *pconf,
406                 struct device_node *child)
407 {
408         int ret = 0;
409         unsigned int para[5];
410         unsigned int val;
411         struct lcd_power_ctrl_s *lcd_power = pconf->lcd_power;
412         int i, j, temp;
413         unsigned int index;
414
415         if (lcd_debug_print_flag)
416                 LCDPR("%s\n", __func__);
417
418         if (child == NULL) {
419                 LCDPR("error: failed to get %s\n", pconf->lcd_propname);
420                 return -1;
421         }
422
423         ret = of_property_read_u32_array(child, "power_on_step", &para[0], 4);
424         if (ret) {
425                 LCDPR("failed to get power_on_step\n");
426                 lcd_power->power_on_step[0].type = LCD_POWER_TYPE_MAX;
427         } else {
428                 i = 0;
429                 while (i < LCD_PWR_STEP_MAX) {
430                         lcd_power->power_on_step_max = i;
431                         j = 4 * i;
432                         ret = of_property_read_u32_index(child, "power_on_step",
433                                 j, &val);
434                         lcd_power->power_on_step[i].type = (unsigned char)val;
435                         if (val == 0xff) /* ending */
436                                 break;
437                         j = 4 * i + 1;
438                         ret = of_property_read_u32_index(child,
439                                 "power_on_step", j, &val);
440                         lcd_power->power_on_step[i].index = val;
441                         j = 4 * i + 2;
442                         ret = of_property_read_u32_index(child,
443                                 "power_on_step", j, &val);
444                         lcd_power->power_on_step[i].value = val;
445                         j = 4 * i + 3;
446                         ret = of_property_read_u32_index(child,
447                                 "power_on_step", j, &val);
448                         lcd_power->power_on_step[i].delay = val;
449
450                         /* gpio/extern probe */
451                         index = lcd_power->power_on_step[i].index;
452                         switch (lcd_power->power_on_step[i].type) {
453                         case LCD_POWER_TYPE_CPU:
454                         case LCD_POWER_TYPE_EXPANDER_IO:
455                         case LCD_POWER_TYPE_WAIT_GPIO:
456                                 if (index < LCD_CPU_GPIO_NUM_MAX)
457                                         lcd_cpu_gpio_probe(index);
458                                 break;
459                         case LCD_POWER_TYPE_EXTERN:
460                                 pconf->extern_index = index;
461                                 break;
462                         case LCD_POWER_TYPE_CLK_SS:
463                                 temp = pconf->lcd_power->power_on_step[i].value;
464                                 pconf->lcd_timing.ss_level |= temp << 8;
465                         break;
466                         default:
467                                 break;
468                         }
469                         if (lcd_debug_print_flag) {
470                                 LCDPR("power_on %d type: %d\n", i,
471                                         lcd_power->power_on_step[i].type);
472                                 LCDPR("power_on %d index: %d\n", i,
473                                         lcd_power->power_on_step[i].index);
474                                 LCDPR("power_on %d value: %d\n", i,
475                                         lcd_power->power_on_step[i].value);
476                                 LCDPR("power_on %d delay: %d\n", i,
477                                         lcd_power->power_on_step[i].delay);
478                         }
479                         i++;
480                 }
481         }
482
483         ret = of_property_read_u32_array(child, "power_off_step", &para[0], 4);
484         if (ret) {
485                 LCDPR("failed to get power_off_step\n");
486                 lcd_power->power_off_step[0].type = LCD_POWER_TYPE_MAX;
487         } else {
488                 i = 0;
489                 while (i < LCD_PWR_STEP_MAX) {
490                         lcd_power->power_off_step_max = i;
491                         j = 4 * i;
492                         ret = of_property_read_u32_index(child,
493                                 "power_off_step", j, &val);
494                         lcd_power->power_off_step[i].type = (unsigned char)val;
495                         if (val == 0xff) /* ending */
496                                 break;
497                         j = 4 * i + 1;
498                         ret = of_property_read_u32_index(child,
499                                 "power_off_step", j, &val);
500                         lcd_power->power_off_step[i].index = val;
501                         j = 4 * i + 2;
502                         ret = of_property_read_u32_index(child,
503                                 "power_off_step", j, &val);
504                         lcd_power->power_off_step[i].value = val;
505                         j = 4 * i + 3;
506                         ret = of_property_read_u32_index(child,
507                                 "power_off_step", j, &val);
508                         lcd_power->power_off_step[i].delay = val;
509
510                         /* gpio/extern probe */
511                         index = lcd_power->power_off_step[i].index;
512                         switch (lcd_power->power_off_step[i].type) {
513                         case LCD_POWER_TYPE_CPU:
514                         case LCD_POWER_TYPE_EXPANDER_IO:
515                         case LCD_POWER_TYPE_WAIT_GPIO:
516                                 if (index < LCD_CPU_GPIO_NUM_MAX)
517                                         lcd_cpu_gpio_probe(index);
518                                 break;
519                         case LCD_POWER_TYPE_EXTERN:
520                                 if (pconf->extern_index == 0xff)
521                                         pconf->extern_index = index;
522                                 break;
523                         default:
524                                 break;
525                         }
526                         if (lcd_debug_print_flag) {
527                                 LCDPR("power_off %d type: %d\n", i,
528                                         lcd_power->power_off_step[i].type);
529                                 LCDPR("power_off %d index: %d\n", i,
530                                         lcd_power->power_off_step[i].index);
531                                 LCDPR("power_off %d value: %d\n", i,
532                                         lcd_power->power_off_step[i].value);
533                                 LCDPR("power_off %d delay: %d\n", i,
534                                         lcd_power->power_off_step[i].delay);
535                         }
536                         i++;
537                 }
538         }
539
540         ret = of_property_read_u32(child, "backlight_index", &para[0]);
541         if (ret) {
542                 LCDPR("failed to get backlight_index\n");
543                 pconf->backlight_index = 0xff;
544         } else {
545                 pconf->backlight_index = para[0];
546         }
547
548         return ret;
549 }
550
551 int lcd_power_load_from_unifykey(struct lcd_config_s *pconf,
552                 unsigned char *buf, int key_len, int len)
553 {
554         int i, j, temp;
555         unsigned char *p;
556         unsigned int index;
557         int ret;
558
559         /* power: (5byte * n) */
560         p = buf + len;
561         i = 0;
562         while (i < LCD_PWR_STEP_MAX) {
563                 pconf->lcd_power->power_on_step_max = i;
564                 len += 5;
565                 ret = lcd_unifykey_len_check(key_len, len);
566                 if (ret < 0) {
567                         pconf->lcd_power->power_on_step[i].type = 0xff;
568                         pconf->lcd_power->power_on_step[i].index = 0;
569                         pconf->lcd_power->power_on_step[i].value = 0;
570                         pconf->lcd_power->power_on_step[i].delay = 0;
571                         LCDERR("unifykey power_on length is incorrect\n");
572                         return -1;
573                 }
574                 pconf->lcd_power->power_on_step[i].type =
575                         *(p + LCD_UKEY_PWR_TYPE + 5*i);
576                 pconf->lcd_power->power_on_step[i].index =
577                         *(p + LCD_UKEY_PWR_INDEX + 5*i);
578                 pconf->lcd_power->power_on_step[i].value =
579                         *(p + LCD_UKEY_PWR_VAL + 5*i);
580                 pconf->lcd_power->power_on_step[i].delay =
581                         (*(p + LCD_UKEY_PWR_DELAY + 5*i) |
582                         ((*(p + LCD_UKEY_PWR_DELAY + 5*i + 1)) << 8));
583
584                 /* gpio/extern probe */
585                 index = pconf->lcd_power->power_on_step[i].index;
586                 switch (pconf->lcd_power->power_on_step[i].type) {
587                 case LCD_POWER_TYPE_CPU:
588                 case LCD_POWER_TYPE_WAIT_GPIO:
589                         if (index < LCD_CPU_GPIO_NUM_MAX)
590                                 lcd_cpu_gpio_probe(index);
591                         break;
592                 case LCD_POWER_TYPE_EXTERN:
593                         pconf->extern_index = index;
594                         break;
595                 case LCD_POWER_TYPE_CLK_SS:
596                         temp = pconf->lcd_power->power_on_step[i].value;
597                         pconf->lcd_timing.ss_level |= temp << 8;
598                         break;
599                 default:
600                         break;
601                 }
602                 if (lcd_debug_print_flag) {
603                         LCDPR("%d: type=%d, index=%d, value=%d, delay=%d\n",
604                                 i, pconf->lcd_power->power_on_step[i].type,
605                                 pconf->lcd_power->power_on_step[i].index,
606                                 pconf->lcd_power->power_on_step[i].value,
607                                 pconf->lcd_power->power_on_step[i].delay);
608                 }
609                 if (pconf->lcd_power->power_on_step[i].type >=
610                         LCD_POWER_TYPE_MAX)
611                         break;
612                 i++;
613         }
614
615         if (lcd_debug_print_flag)
616                 LCDPR("power_off step:\n");
617         p += (5*(i + 1));
618         j = 0;
619         while (j < LCD_PWR_STEP_MAX) {
620                 pconf->lcd_power->power_off_step_max = j;
621                 len += 5;
622                 ret = lcd_unifykey_len_check(key_len, len);
623                 if (ret < 0) {
624                         pconf->lcd_power->power_off_step[j].type = 0xff;
625                         pconf->lcd_power->power_off_step[j].index = 0;
626                         pconf->lcd_power->power_off_step[j].value = 0;
627                         pconf->lcd_power->power_off_step[j].delay = 0;
628                         LCDERR("unifykey power_off length is incorrect\n");
629                         return -1;
630                 }
631                 pconf->lcd_power->power_off_step[j].type =
632                         *(p + LCD_UKEY_PWR_TYPE + 5*j);
633                 pconf->lcd_power->power_off_step[j].index =
634                         *(p + LCD_UKEY_PWR_INDEX + 5*j);
635                 pconf->lcd_power->power_off_step[j].value =
636                         *(p + LCD_UKEY_PWR_VAL + 5*j);
637                 pconf->lcd_power->power_off_step[j].delay =
638                                 (*(p + LCD_UKEY_PWR_DELAY + 5*j) |
639                                 ((*(p + LCD_UKEY_PWR_DELAY + 5*j + 1)) << 8));
640
641                 /* gpio/extern probe */
642                 index = pconf->lcd_power->power_off_step[j].index;
643                 switch (pconf->lcd_power->power_off_step[j].type) {
644                 case LCD_POWER_TYPE_CPU:
645                 case LCD_POWER_TYPE_WAIT_GPIO:
646                         if (index < LCD_CPU_GPIO_NUM_MAX)
647                                 lcd_cpu_gpio_probe(index);
648                         break;
649                 case LCD_POWER_TYPE_EXTERN:
650                         if (pconf->extern_index == 0xff)
651                                 pconf->extern_index = index;
652                         break;
653                 default:
654                         break;
655                 }
656                 if (lcd_debug_print_flag) {
657                         LCDPR("%d: type=%d, index=%d, value=%d, delay=%d\n",
658                                 j, pconf->lcd_power->power_off_step[j].type,
659                                 pconf->lcd_power->power_off_step[j].index,
660                                 pconf->lcd_power->power_off_step[j].value,
661                                 pconf->lcd_power->power_off_step[j].delay);
662                 }
663                 if (pconf->lcd_power->power_off_step[j].type >=
664                         LCD_POWER_TYPE_MAX)
665                         break;
666                 j++;
667         }
668
669         return 0;
670 }
671
672 int lcd_vlock_param_load_from_dts(struct lcd_config_s *pconf,
673                 struct device_node *child)
674 {
675         unsigned int para[4];
676         int ret;
677
678         pconf->lcd_control.vlock_param[0] = LCD_VLOCK_PARAM_BIT_UPDATE;
679
680         ret = of_property_read_u32_array(child, "vlock_attr", &para[0], 4);
681         if (ret == 0) {
682                 LCDPR("find vlock_attr\n");
683                 pconf->lcd_control.vlock_param[0] |= LCD_VLOCK_PARAM_BIT_VALID;
684                 pconf->lcd_control.vlock_param[1] = para[0];
685                 pconf->lcd_control.vlock_param[2] = para[1];
686                 pconf->lcd_control.vlock_param[3] = para[2];
687                 pconf->lcd_control.vlock_param[4] = para[3];
688         }
689
690         return 0;
691 }
692
693 int lcd_vlock_param_load_from_unifykey(struct lcd_config_s *pconf,
694                 unsigned char *buf)
695 {
696         unsigned char *p;
697
698         p = buf;
699
700         pconf->lcd_control.vlock_param[0] = LCD_VLOCK_PARAM_BIT_UPDATE;
701         pconf->lcd_control.vlock_param[1] = *(p + LCD_UKEY_VLOCK_VAL_0);
702         pconf->lcd_control.vlock_param[2] = *(p + LCD_UKEY_VLOCK_VAL_1);
703         pconf->lcd_control.vlock_param[3] = *(p + LCD_UKEY_VLOCK_VAL_2);
704         pconf->lcd_control.vlock_param[4] = *(p + LCD_UKEY_VLOCK_VAL_3);
705         if (pconf->lcd_control.vlock_param[1] ||
706                 pconf->lcd_control.vlock_param[2] ||
707                 pconf->lcd_control.vlock_param[3] ||
708                 pconf->lcd_control.vlock_param[4]) {
709                 LCDPR("find vlock_attr\n");
710                 pconf->lcd_control.vlock_param[0] |= LCD_VLOCK_PARAM_BIT_VALID;
711         }
712
713         return 0;
714 }
715
716 void lcd_optical_vinfo_update(void)
717 {
718         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
719         struct lcd_config_s *pconf;
720         struct master_display_info_s *disp_vinfo;
721
722         pconf = lcd_drv->lcd_config;
723         disp_vinfo = &lcd_drv->lcd_info->master_display_info;
724         disp_vinfo->present_flag = pconf->optical_info.hdr_support;
725         disp_vinfo->features = pconf->optical_info.features;
726         disp_vinfo->primaries[0][0] = pconf->optical_info.primaries_g_x;
727         disp_vinfo->primaries[0][1] = pconf->optical_info.primaries_g_y;
728         disp_vinfo->primaries[1][0] = pconf->optical_info.primaries_b_x;
729         disp_vinfo->primaries[1][1] = pconf->optical_info.primaries_b_y;
730         disp_vinfo->primaries[2][0] = pconf->optical_info.primaries_r_x;
731         disp_vinfo->primaries[2][1] = pconf->optical_info.primaries_r_y;
732         disp_vinfo->white_point[0] = pconf->optical_info.white_point_x;
733         disp_vinfo->white_point[1] = pconf->optical_info.white_point_y;
734         disp_vinfo->luminance[0] = pconf->optical_info.luma_max;
735         disp_vinfo->luminance[1] = pconf->optical_info.luma_min;
736
737         lcd_drv->lcd_info->hdr_info.lumi_max = pconf->optical_info.luma_max;
738 }
739
740 void lcd_timing_init_config(struct lcd_config_s *pconf)
741 {
742         unsigned short h_period, v_period, h_active, v_active;
743         unsigned short hsync_bp, hsync_width, vsync_bp, vsync_width;
744         unsigned short de_hstart, de_vstart;
745         unsigned short hstart, hend, vstart, vend;
746         unsigned short h_delay;
747
748         switch (pconf->lcd_basic.lcd_type) {
749         case LCD_TTL:
750                 h_delay = TTL_DELAY;
751                 break;
752         default:
753                 h_delay = 0;
754                 break;
755         }
756         /* use period_dft to avoid period changing offset */
757         h_period = pconf->lcd_timing.h_period_dft;
758         v_period = pconf->lcd_timing.v_period_dft;
759         h_active = pconf->lcd_basic.h_active;
760         v_active = pconf->lcd_basic.v_active;
761         hsync_bp = pconf->lcd_timing.hsync_bp;
762         hsync_width = pconf->lcd_timing.hsync_width;
763         vsync_bp = pconf->lcd_timing.vsync_bp;
764         vsync_width = pconf->lcd_timing.vsync_width;
765
766         de_hstart = hsync_bp + hsync_width;
767         de_vstart = vsync_bp + vsync_width;
768
769         pconf->lcd_timing.video_on_pixel = de_hstart - h_delay;
770         pconf->lcd_timing.video_on_line = de_vstart;
771
772         pconf->lcd_timing.de_hs_addr = de_hstart;
773         pconf->lcd_timing.de_he_addr = de_hstart + h_active;
774         pconf->lcd_timing.de_vs_addr = de_vstart;
775         pconf->lcd_timing.de_ve_addr = de_vstart + v_active - 1;
776
777         if (h_period) {
778                 hstart = (de_hstart + h_period - hsync_bp - hsync_width) % h_period;
779                 hend = (de_hstart + h_period - hsync_bp) % h_period;
780         } else {
781                 hstart = 0;
782                 hend = 0;
783         }
784         pconf->lcd_timing.hs_hs_addr = hstart;
785         pconf->lcd_timing.hs_he_addr = hend;
786         pconf->lcd_timing.hs_vs_addr = 0;
787         pconf->lcd_timing.hs_ve_addr = v_period - 1;
788
789         if (h_period) {
790                 pconf->lcd_timing.vs_hs_addr = (hstart + h_period) % h_period;
791                 vstart = (de_vstart + v_period - vsync_bp - vsync_width) % v_period;
792                 vend = (de_vstart + v_period - vsync_bp) % v_period;
793         } else {
794                 pconf->lcd_timing.vs_hs_addr = 0;
795                 vstart = 0;
796                 vend = 0;
797         }
798         pconf->lcd_timing.vs_he_addr = pconf->lcd_timing.vs_hs_addr;
799         pconf->lcd_timing.vs_vs_addr = vstart;
800         pconf->lcd_timing.vs_ve_addr = vend;
801
802         if (lcd_debug_print_flag) {
803                 LCDPR("hs_hs_addr=%d, hs_he_addr=%d\n"
804                 "hs_vs_addr=%d, hs_ve_addr=%d\n"
805                 "vs_hs_addr=%d, vs_he_addr=%d\n"
806                 "vs_vs_addr=%d, vs_ve_addr=%d\n",
807                 pconf->lcd_timing.hs_hs_addr, pconf->lcd_timing.hs_he_addr,
808                 pconf->lcd_timing.hs_vs_addr, pconf->lcd_timing.hs_ve_addr,
809                 pconf->lcd_timing.vs_hs_addr, pconf->lcd_timing.vs_he_addr,
810                 pconf->lcd_timing.vs_vs_addr, pconf->lcd_timing.vs_ve_addr);
811         }
812 }
813
814 #if 0
815 /* change frame_rate for different vmode */
816 int lcd_vmode_change(struct lcd_config_s *pconf)
817 {
818         unsigned int pclk = pconf->lcd_timing.lcd_clk_dft; /* avoid offset */
819         unsigned char type = pconf->lcd_timing.fr_adjust_type;
820         unsigned int h_period = pconf->lcd_basic.h_period;
821         unsigned int v_period = pconf->lcd_basic.v_period;
822         unsigned int sync_duration_num = pconf->lcd_timing.sync_duration_num;
823         unsigned int sync_duration_den = pconf->lcd_timing.sync_duration_den;
824
825         /* frame rate adjust */
826         switch (type) {
827         case 1: /* htotal adjust */
828                 h_period = ((pclk / v_period) * sync_duration_den * 10) /
829                                 sync_duration_num;
830                 h_period = (h_period + 5) / 10; /* round off */
831                 if (pconf->lcd_basic.h_period != h_period) {
832                         LCDPR("%s: adjust h_period %u -> %u\n",
833                                 __func__, pconf->lcd_basic.h_period, h_period);
834                         pconf->lcd_basic.h_period = h_period;
835                         /* check clk frac update */
836                         pclk = (h_period * v_period) / sync_duration_den *
837                                 sync_duration_num;
838                         if (pconf->lcd_timing.lcd_clk != pclk)
839                                 pconf->lcd_timing.lcd_clk = pclk;
840                 }
841                 break;
842         case 2: /* vtotal adjust */
843                 v_period = ((pclk / h_period) * sync_duration_den * 10) /
844                                 sync_duration_num;
845                 v_period = (v_period + 5) / 10; /* round off */
846                 if (pconf->lcd_basic.v_period != v_period) {
847                         LCDPR("%s: adjust v_period %u -> %u\n",
848                                 __func__, pconf->lcd_basic.v_period, v_period);
849                         pconf->lcd_basic.v_period = v_period;
850                         /* check clk frac update */
851                         pclk = (h_period * v_period) / sync_duration_den *
852                                 sync_duration_num;
853                         if (pconf->lcd_timing.lcd_clk != pclk)
854                                 pconf->lcd_timing.lcd_clk = pclk;
855                 }
856                 break;
857         case 0: /* pixel clk adjust */
858         default:
859                 pclk = (h_period * v_period) / sync_duration_den *
860                         sync_duration_num;
861                 if (pconf->lcd_timing.lcd_clk != pclk) {
862                         LCDPR("%s: adjust pclk %u.%03uMHz -> %u.%03uMHz\n",
863                                 __func__, (pconf->lcd_timing.lcd_clk / 1000000),
864                                 ((pconf->lcd_timing.lcd_clk / 1000) % 1000),
865                                 (pclk / 1000000), ((pclk / 1000) % 1000));
866                         pconf->lcd_timing.lcd_clk = pclk;
867                 }
868                 break;
869         }
870
871         return 0;
872 }
873 #else
874 int lcd_vmode_change(struct lcd_config_s *pconf)
875 {
876         unsigned char type = pconf->lcd_timing.fr_adjust_type;
877          /* use default value to avoid offset */
878         unsigned int pclk = pconf->lcd_timing.lcd_clk_dft;
879         unsigned int h_period = pconf->lcd_timing.h_period_dft;
880         unsigned int v_period = pconf->lcd_timing.v_period_dft;
881         unsigned int pclk_min = pconf->lcd_basic.lcd_clk_min;
882         unsigned int pclk_max = pconf->lcd_basic.lcd_clk_max;
883         unsigned int duration_num = pconf->lcd_timing.sync_duration_num;
884         unsigned int duration_den = pconf->lcd_timing.sync_duration_den;
885         char str[100];
886         int len = 0;
887
888         pconf->lcd_timing.clk_change = 0; /* clear clk flag */
889         switch (type) {
890         case 0: /* pixel clk adjust */
891                 pclk = (h_period * v_period) / duration_den * duration_num;
892                 if (pconf->lcd_timing.lcd_clk != pclk)
893                         pconf->lcd_timing.clk_change = LCD_CLK_PLL_CHANGE;
894                 break;
895         case 1: /* htotal adjust */
896                 h_period = ((pclk / v_period) * duration_den * 100) /
897                                 duration_num;
898                 h_period = (h_period + 99) / 100; /* round off */
899                 if (pconf->lcd_basic.h_period != h_period) {
900                         /* check clk frac update */
901                         pclk = (h_period * v_period) / duration_den *
902                                 duration_num;
903                         if (pconf->lcd_timing.lcd_clk != pclk) {
904                                 pconf->lcd_timing.clk_change =
905                                         LCD_CLK_FRAC_UPDATE;
906                         }
907                 }
908                 break;
909         case 2: /* vtotal adjust */
910                 v_period = ((pclk / h_period) * duration_den * 100) /
911                                 duration_num;
912                 v_period = (v_period + 99) / 100; /* round off */
913                 if (pconf->lcd_basic.v_period != v_period) {
914                         /* check clk frac update */
915                         pclk = (h_period * v_period) / duration_den *
916                                 duration_num;
917                         if (pconf->lcd_timing.lcd_clk != pclk) {
918                                 pconf->lcd_timing.clk_change =
919                                         LCD_CLK_FRAC_UPDATE;
920                         }
921                 }
922                 break;
923         case 4: /* hdmi mode */
924                 if ((duration_num / duration_den) == 59) {
925                         /* pixel clk adjust */
926                         pclk = (h_period * v_period) /
927                                 duration_den * duration_num;
928                         if (pconf->lcd_timing.lcd_clk != pclk)
929                                 pconf->lcd_timing.clk_change =
930                                         LCD_CLK_PLL_CHANGE;
931                 } else {
932                         /* htotal adjust */
933                         h_period = ((pclk / v_period) * duration_den * 100) /
934                                         duration_num;
935                         h_period = (h_period + 99) / 100; /* round off */
936                         if (pconf->lcd_basic.h_period != h_period) {
937                                 /* check clk frac update */
938                                 pclk = (h_period * v_period) / duration_den *
939                                         duration_num;
940                                 if (pconf->lcd_timing.lcd_clk != pclk) {
941                                         pconf->lcd_timing.clk_change =
942                                                 LCD_CLK_FRAC_UPDATE;
943                                 }
944                         }
945                 }
946                 break;
947         case 3: /* free adjust, use min/max range to calculate */
948         default:
949                 v_period = ((pclk / h_period) * duration_den * 100) /
950                         duration_num;
951                 v_period = (v_period + 99) / 100; /* round off */
952                 if (v_period > pconf->lcd_basic.v_period_max) {
953                         v_period = pconf->lcd_basic.v_period_max;
954                         h_period = ((pclk / v_period) * duration_den * 100) /
955                                 duration_num;
956                         h_period = (h_period + 99) / 100; /* round off */
957                         if (h_period > pconf->lcd_basic.h_period_max) {
958                                 h_period = pconf->lcd_basic.h_period_max;
959                                 pclk = (h_period * v_period) / duration_den *
960                                         duration_num;
961                                 if (pconf->lcd_timing.lcd_clk != pclk) {
962                                         if (pclk > pclk_max) {
963                                                 pclk = pclk_max;
964                                                 LCDERR("invalid vmode\n");
965                                                 return -1;
966                                         }
967                                         pconf->lcd_timing.clk_change =
968                                                 LCD_CLK_PLL_CHANGE;
969                                 }
970                         }
971                 } else if (v_period < pconf->lcd_basic.v_period_min) {
972                         v_period = pconf->lcd_basic.v_period_min;
973                         h_period = ((pclk / v_period) * duration_den * 100) /
974                                 duration_num;
975                         h_period = (h_period + 99) / 100; /* round off */
976                         if (h_period < pconf->lcd_basic.h_period_min) {
977                                 h_period = pconf->lcd_basic.h_period_min;
978                                 pclk = (h_period * v_period) / duration_den *
979                                         duration_num;
980                                 if (pconf->lcd_timing.lcd_clk != pclk) {
981                                         if (pclk < pclk_min) {
982                                                 pclk = pclk_min;
983                                                 LCDERR("invalid vmode\n");
984                                                 return -1;
985                                         }
986                                         pconf->lcd_timing.clk_change =
987                                                 LCD_CLK_PLL_CHANGE;
988                                 }
989                         }
990                 }
991                 /* check clk frac update */
992                 if ((pconf->lcd_timing.clk_change & LCD_CLK_PLL_CHANGE) == 0) {
993                         pclk = (h_period * v_period) / duration_den *
994                                 duration_num;
995                         if (pconf->lcd_timing.lcd_clk != pclk) {
996                                 pconf->lcd_timing.clk_change =
997                                         LCD_CLK_FRAC_UPDATE;
998                         }
999                 }
1000                 break;
1001         }
1002
1003         if (pconf->lcd_basic.v_period != v_period) {
1004                 len += sprintf(str+len, "v_period %u->%u",
1005                         pconf->lcd_basic.v_period, v_period);
1006                 /* update v_period */
1007                 pconf->lcd_basic.v_period = v_period;
1008         }
1009         if (pconf->lcd_basic.h_period != h_period) {
1010                 if (len > 0)
1011                         len += sprintf(str+len, ", ");
1012                 len += sprintf(str+len, "h_period %u->%u",
1013                         pconf->lcd_basic.h_period, h_period);
1014                 /* update h_period */
1015                 pconf->lcd_basic.h_period = h_period;
1016         }
1017         if (pconf->lcd_timing.lcd_clk != pclk) {
1018                 if (len > 0)
1019                         len += sprintf(str+len, ", ");
1020                 len += sprintf(str+len, "pclk %u.%03uMHz->%u.%03uMHz",
1021                         (pconf->lcd_timing.lcd_clk / 1000000),
1022                         ((pconf->lcd_timing.lcd_clk / 1000) % 1000),
1023                         (pclk / 1000000), ((pclk / 1000) % 1000));
1024                 pconf->lcd_timing.lcd_clk = pclk;
1025         }
1026         if (lcd_debug_print_flag) {
1027                 if (len > 0)
1028                         LCDPR("%s: %s\n", __func__, str);
1029         }
1030
1031         return 0;
1032 }
1033 #endif
1034
1035 void lcd_clk_change(struct lcd_config_s *pconf)
1036 {
1037         switch (pconf->lcd_timing.clk_change) {
1038         case LCD_CLK_PLL_CHANGE:
1039                 lcd_clk_generate_parameter(pconf);
1040                 lcd_clk_set(pconf);
1041                 break;
1042         case LCD_CLK_FRAC_UPDATE:
1043                 lcd_clk_update(pconf);
1044                 break;
1045         default:
1046                 break;
1047         }
1048 }
1049
1050 void lcd_venc_change(struct lcd_config_s *pconf)
1051 {
1052         unsigned int htotal, vtotal, frame_rate;
1053
1054         htotal = lcd_vcbus_read(ENCL_VIDEO_MAX_PXCNT) + 1;
1055         vtotal = lcd_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1;
1056         if (pconf->lcd_basic.h_period != htotal) {
1057                 lcd_vcbus_write(ENCL_VIDEO_MAX_PXCNT,
1058                         pconf->lcd_basic.h_period - 1);
1059         }
1060         if (pconf->lcd_basic.v_period != vtotal) {
1061                 lcd_vcbus_write(ENCL_VIDEO_MAX_LNCNT,
1062                         pconf->lcd_basic.v_period - 1);
1063         }
1064         if (lcd_debug_print_flag) {
1065                 LCDPR("venc changed: %d,%d\n",
1066                         pconf->lcd_basic.h_period,
1067                         pconf->lcd_basic.v_period);
1068         }
1069
1070         frame_rate = (pconf->lcd_timing.sync_duration_num * 100) /
1071                 pconf->lcd_timing.sync_duration_den;
1072         frame_rate = (frame_rate + 50) / 100;
1073         aml_lcd_notifier_call_chain(LCD_EVENT_BACKLIGHT_UPDATE, &frame_rate);
1074 }
1075
1076 void lcd_if_enable_retry(struct lcd_config_s *pconf)
1077 {
1078         pconf->retry_enable_cnt = 0;
1079         while (pconf->retry_enable_flag) {
1080                 if (pconf->retry_enable_cnt++ >= LCD_ENABLE_RETRY_MAX)
1081                         break;
1082                 LCDPR("retry enable...%d\n", pconf->retry_enable_cnt);
1083                 aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, NULL);
1084                 msleep(1000);
1085                 aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_ON, NULL);
1086         }
1087         pconf->retry_enable_cnt = 0;
1088 }
1089
1090 void lcd_vout_notify_mode_change_pre(void)
1091 {
1092         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
1093
1094         if (lcd_drv->viu_sel == 1) {
1095                 vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE,
1096                         &lcd_drv->lcd_info->mode);
1097         } else if (lcd_drv->viu_sel == 2) {
1098 #ifdef CONFIG_AMLOGIC_VOUT2_SERVE
1099                 vout2_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE,
1100                         &lcd_drv->lcd_info->mode);
1101 #endif
1102         }
1103 }
1104
1105 void lcd_vout_notify_mode_change(void)
1106 {
1107         struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
1108
1109         if (lcd_drv->viu_sel == 1) {
1110                 vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
1111                         &lcd_drv->lcd_info->mode);
1112         } else if (lcd_drv->viu_sel == 2) {
1113 #ifdef CONFIG_AMLOGIC_VOUT2_SERVE
1114                 vout2_notifier_call_chain(VOUT_EVENT_MODE_CHANGE,
1115                         &lcd_drv->lcd_info->mode);
1116 #endif
1117         }
1118 }