2 * drivers/amlogic/media/vout/lcd/lcd_common.c
4 * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
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.
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
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>
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>
35 #include "lcd_common.h"
38 /* **********************************
40 * **********************************
42 struct lcd_type_match_s {
47 static struct lcd_type_match_s lcd_type_match_table[] = {
50 {"vbyone", LCD_VBYONE},
52 {"minilvds", LCD_MLVDS},
54 {"invalid", LCD_TYPE_MAX},
57 int lcd_type_str_to_type(const char *str)
60 int type = LCD_TYPE_MAX;
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;
71 char *lcd_type_type_to_str(int type)
74 char *str = lcd_type_match_table[LCD_TYPE_MAX].name;
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;
85 static char *lcd_mode_table[] = {
91 unsigned char lcd_mode_str_to_mode(const char *str)
95 for (mode = 0; mode < ARRAY_SIZE(lcd_mode_table); mode++) {
96 if (!strcmp(str, lcd_mode_table[mode]))
102 char *lcd_mode_mode_to_str(int mode)
104 return lcd_mode_table[mode];
107 /* **********************************
109 * **********************************
112 void lcd_cpu_gpio_probe(unsigned int index)
114 struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
115 struct lcd_cpu_gpio_s *cpu_gpio;
119 if (index >= LCD_CPU_GPIO_NUM_MAX) {
120 LCDERR("gpio index %d, exit\n", index);
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);
133 ret = of_property_read_string_index(lcd_drv->dev->of_node,
134 "lcd_cpu_gpio_names", index, &str);
136 LCDERR("failed to get lcd_cpu_gpio_names: %d\n", index);
139 strcpy(cpu_gpio->name, str);
142 cpu_gpio->probe_flag = 1;
143 cpu_gpio->register_flag = 0;
146 static int lcd_cpu_gpio_register(unsigned int index, int init_value)
148 struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
149 struct lcd_cpu_gpio_s *cpu_gpio;
152 if (index >= LCD_CPU_GPIO_NUM_MAX) {
153 LCDERR("%s: gpio index %d, exit\n", __func__, index);
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);
161 if (cpu_gpio->register_flag) {
162 LCDPR("%s: gpio %s[%d] is already registered\n",
163 __func__, cpu_gpio->name, index);
167 switch (init_value) {
168 case LCD_GPIO_OUTPUT_LOW:
169 value = GPIOD_OUT_LOW;
171 case LCD_GPIO_OUTPUT_HIGH:
172 value = GPIOD_OUT_HIGH;
181 cpu_gpio->gpio = devm_gpiod_get_index(lcd_drv->dev,
182 "lcd_cpu", index, value);
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));
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);
199 void lcd_cpu_gpio_set(unsigned int index, int value)
201 struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
202 struct lcd_cpu_gpio_s *cpu_gpio;
204 if (index >= LCD_CPU_GPIO_NUM_MAX) {
205 LCDERR("gpio index %d, exit\n", index);
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);
213 if (cpu_gpio->register_flag == 0) {
214 lcd_cpu_gpio_register(index, value);
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));
226 case LCD_GPIO_OUTPUT_LOW:
227 case LCD_GPIO_OUTPUT_HIGH:
228 gpiod_direction_output(cpu_gpio->gpio, value);
232 gpiod_direction_input(cpu_gpio->gpio);
235 if (lcd_debug_print_flag) {
236 LCDPR("set gpio %s[%d] value: %d\n",
237 cpu_gpio->name, index, value);
241 unsigned int lcd_cpu_gpio_get(unsigned int index)
243 struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
244 struct lcd_cpu_gpio_s *cpu_gpio;
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);
251 if (cpu_gpio->register_flag == 0) {
252 LCDERR("%s: gpio %s[%d] is not registered\n",
253 __func__, cpu_gpio->name, index);
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));
262 return gpiod_get_value(cpu_gpio->gpio);
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 */
276 void lcd_ttl_pinmux_set(int status)
278 struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
279 struct lcd_config_s *pconf;
280 unsigned int base, index;
282 if (lcd_debug_print_flag)
283 LCDPR("%s: %d\n", __func__, status);
285 pconf = lcd_drv->lcd_config;
286 if (pconf->lcd_basic.lcd_bits == 6)
292 switch (pconf->lcd_control.ttl_config->sync_valid) {
300 case 3: /* DE + hvsync */
308 if (pconf->pinmux_flag == index) {
309 LCDPR("pinmux %s is already selected\n",
310 lcd_ttl_pinmux_str[index]);
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]);
320 if (lcd_debug_print_flag) {
321 LCDPR("set ttl pinmux %s: %p\n",
322 lcd_ttl_pinmux_str[index], pconf->pin);
325 pconf->pinmux_flag = index;
328 static char *lcd_vbyone_pinmux_str[] = {
334 /* set VX1_LOCKN && VX1_HTPDN */
335 void lcd_vbyone_pinmux_set(int status)
337 struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
338 struct lcd_config_s *pconf;
341 if (lcd_debug_print_flag)
342 LCDPR("%s: %d\n", __func__, status);
344 pconf = lcd_drv->lcd_config;
345 index = (status) ? 0 : 1;
347 if (pconf->pinmux_flag == index) {
348 LCDPR("pinmux %s is already selected\n",
349 lcd_vbyone_pinmux_str[index]);
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]);
359 if (lcd_debug_print_flag) {
360 LCDPR("set vbyone pinmux %s: %p\n",
361 lcd_vbyone_pinmux_str[index], pconf->pin);
364 pconf->pinmux_flag = index;
367 static char *lcd_tcon_pinmux_str[] = {
373 void lcd_tcon_pinmux_set(int status)
375 struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
376 struct lcd_config_s *pconf;
379 if (lcd_debug_print_flag)
380 LCDPR("%s: %d\n", __func__, status);
382 pconf = lcd_drv->lcd_config;
383 index = (status) ? 0 : 1;
385 if (pconf->pinmux_flag == index) {
386 LCDPR("pinmux %s is already selected\n",
387 lcd_tcon_pinmux_str[index]);
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]);
397 if (lcd_debug_print_flag) {
398 LCDPR("set tcon pinmux %s: %p\n",
399 lcd_tcon_pinmux_str[index], pconf->pin);
402 pconf->pinmux_flag = index;
405 int lcd_power_load_from_dts(struct lcd_config_s *pconf,
406 struct device_node *child)
409 unsigned int para[5];
411 struct lcd_power_ctrl_s *lcd_power = pconf->lcd_power;
415 if (lcd_debug_print_flag)
416 LCDPR("%s\n", __func__);
419 LCDPR("error: failed to get %s\n", pconf->lcd_propname);
423 ret = of_property_read_u32_array(child, "power_on_step", ¶[0], 4);
425 LCDPR("failed to get power_on_step\n");
426 lcd_power->power_on_step[0].type = LCD_POWER_TYPE_MAX;
429 while (i < LCD_PWR_STEP_MAX) {
430 lcd_power->power_on_step_max = i;
432 ret = of_property_read_u32_index(child, "power_on_step",
434 lcd_power->power_on_step[i].type = (unsigned char)val;
435 if (val == 0xff) /* ending */
438 ret = of_property_read_u32_index(child,
439 "power_on_step", j, &val);
440 lcd_power->power_on_step[i].index = val;
442 ret = of_property_read_u32_index(child,
443 "power_on_step", j, &val);
444 lcd_power->power_on_step[i].value = val;
446 ret = of_property_read_u32_index(child,
447 "power_on_step", j, &val);
448 lcd_power->power_on_step[i].delay = val;
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);
459 case LCD_POWER_TYPE_EXTERN:
460 pconf->extern_index = index;
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;
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);
483 ret = of_property_read_u32_array(child, "power_off_step", ¶[0], 4);
485 LCDPR("failed to get power_off_step\n");
486 lcd_power->power_off_step[0].type = LCD_POWER_TYPE_MAX;
489 while (i < LCD_PWR_STEP_MAX) {
490 lcd_power->power_off_step_max = 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 */
498 ret = of_property_read_u32_index(child,
499 "power_off_step", j, &val);
500 lcd_power->power_off_step[i].index = val;
502 ret = of_property_read_u32_index(child,
503 "power_off_step", j, &val);
504 lcd_power->power_off_step[i].value = val;
506 ret = of_property_read_u32_index(child,
507 "power_off_step", j, &val);
508 lcd_power->power_off_step[i].delay = val;
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);
519 case LCD_POWER_TYPE_EXTERN:
520 if (pconf->extern_index == 0xff)
521 pconf->extern_index = index;
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);
540 ret = of_property_read_u32(child, "backlight_index", ¶[0]);
542 LCDPR("failed to get backlight_index\n");
543 pconf->backlight_index = 0xff;
545 pconf->backlight_index = para[0];
551 int lcd_power_load_from_unifykey(struct lcd_config_s *pconf,
552 unsigned char *buf, int key_len, int len)
559 /* power: (5byte * n) */
562 while (i < LCD_PWR_STEP_MAX) {
563 pconf->lcd_power->power_on_step_max = i;
565 ret = lcd_unifykey_len_check(key_len, len);
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");
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));
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);
592 case LCD_POWER_TYPE_EXTERN:
593 pconf->extern_index = index;
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;
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);
609 if (pconf->lcd_power->power_on_step[i].type >=
615 if (lcd_debug_print_flag)
616 LCDPR("power_off step:\n");
619 while (j < LCD_PWR_STEP_MAX) {
620 pconf->lcd_power->power_off_step_max = j;
622 ret = lcd_unifykey_len_check(key_len, len);
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");
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));
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);
649 case LCD_POWER_TYPE_EXTERN:
650 if (pconf->extern_index == 0xff)
651 pconf->extern_index = index;
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);
663 if (pconf->lcd_power->power_off_step[j].type >=
672 int lcd_vlock_param_load_from_dts(struct lcd_config_s *pconf,
673 struct device_node *child)
675 unsigned int para[4];
678 pconf->lcd_control.vlock_param[0] = LCD_VLOCK_PARAM_BIT_UPDATE;
680 ret = of_property_read_u32_array(child, "vlock_attr", ¶[0], 4);
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];
693 int lcd_vlock_param_load_from_unifykey(struct lcd_config_s *pconf,
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;
716 void lcd_optical_vinfo_update(void)
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;
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;
737 lcd_drv->lcd_info->hdr_info.lumi_max = pconf->optical_info.luma_max;
740 void lcd_timing_init_config(struct lcd_config_s *pconf)
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;
748 switch (pconf->lcd_basic.lcd_type) {
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;
766 de_hstart = hsync_bp + hsync_width;
767 de_vstart = vsync_bp + vsync_width;
769 pconf->lcd_timing.video_on_pixel = de_hstart - h_delay;
770 pconf->lcd_timing.video_on_line = de_vstart;
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;
778 hstart = (de_hstart + h_period - hsync_bp - hsync_width) % h_period;
779 hend = (de_hstart + h_period - hsync_bp) % h_period;
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;
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;
794 pconf->lcd_timing.vs_hs_addr = 0;
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;
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);
815 /* change frame_rate for different vmode */
816 int lcd_vmode_change(struct lcd_config_s *pconf)
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;
825 /* frame rate adjust */
827 case 1: /* htotal adjust */
828 h_period = ((pclk / v_period) * sync_duration_den * 10) /
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 *
838 if (pconf->lcd_timing.lcd_clk != pclk)
839 pconf->lcd_timing.lcd_clk = pclk;
842 case 2: /* vtotal adjust */
843 v_period = ((pclk / h_period) * sync_duration_den * 10) /
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 *
853 if (pconf->lcd_timing.lcd_clk != pclk)
854 pconf->lcd_timing.lcd_clk = pclk;
857 case 0: /* pixel clk adjust */
859 pclk = (h_period * v_period) / sync_duration_den *
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;
874 int lcd_vmode_change(struct lcd_config_s *pconf)
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;
888 pconf->lcd_timing.clk_change = 0; /* clear clk flag */
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;
895 case 1: /* htotal adjust */
896 h_period = ((pclk / v_period) * duration_den * 100) /
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 *
903 if (pconf->lcd_timing.lcd_clk != pclk) {
904 pconf->lcd_timing.clk_change =
909 case 2: /* vtotal adjust */
910 v_period = ((pclk / h_period) * duration_den * 100) /
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 *
917 if (pconf->lcd_timing.lcd_clk != pclk) {
918 pconf->lcd_timing.clk_change =
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 =
933 h_period = ((pclk / v_period) * duration_den * 100) /
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 *
940 if (pconf->lcd_timing.lcd_clk != pclk) {
941 pconf->lcd_timing.clk_change =
947 case 3: /* free adjust, use min/max range to calculate */
949 v_period = ((pclk / h_period) * duration_den * 100) /
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) /
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 *
961 if (pconf->lcd_timing.lcd_clk != pclk) {
962 if (pclk > pclk_max) {
964 LCDERR("invalid vmode\n");
967 pconf->lcd_timing.clk_change =
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) /
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 *
980 if (pconf->lcd_timing.lcd_clk != pclk) {
981 if (pclk < pclk_min) {
983 LCDERR("invalid vmode\n");
986 pconf->lcd_timing.clk_change =
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 *
995 if (pconf->lcd_timing.lcd_clk != pclk) {
996 pconf->lcd_timing.clk_change =
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;
1009 if (pconf->lcd_basic.h_period != h_period) {
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;
1017 if (pconf->lcd_timing.lcd_clk != pclk) {
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;
1026 if (lcd_debug_print_flag) {
1028 LCDPR("%s: %s\n", __func__, str);
1035 void lcd_clk_change(struct lcd_config_s *pconf)
1037 switch (pconf->lcd_timing.clk_change) {
1038 case LCD_CLK_PLL_CHANGE:
1039 lcd_clk_generate_parameter(pconf);
1042 case LCD_CLK_FRAC_UPDATE:
1043 lcd_clk_update(pconf);
1050 void lcd_venc_change(struct lcd_config_s *pconf)
1052 unsigned int htotal, vtotal, frame_rate;
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);
1060 if (pconf->lcd_basic.v_period != vtotal) {
1061 lcd_vcbus_write(ENCL_VIDEO_MAX_LNCNT,
1062 pconf->lcd_basic.v_period - 1);
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);
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);
1076 void lcd_if_enable_retry(struct lcd_config_s *pconf)
1078 pconf->retry_enable_cnt = 0;
1079 while (pconf->retry_enable_flag) {
1080 if (pconf->retry_enable_cnt++ >= LCD_ENABLE_RETRY_MAX)
1082 LCDPR("retry enable...%d\n", pconf->retry_enable_cnt);
1083 aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, NULL);
1085 aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_ON, NULL);
1087 pconf->retry_enable_cnt = 0;
1090 void lcd_vout_notify_mode_change_pre(void)
1092 struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
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);
1105 void lcd_vout_notify_mode_change(void)
1107 struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
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);