blob: 9d6cca18b5328fa24832d15961be9565105e8b37 [file] [log] [blame]
Angel Ponsbbc99cf2020-04-04 18:51:23 +02001/* SPDX-License-Identifier: GPL-2.0-only */
huang lin40f558e2014-09-19 14:51:52 +08002
3#include <arch/cache.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
huang lin40f558e2014-09-19 14:51:52 +08005#include <console/console.h>
6#include <device/device.h>
7#include <delay.h>
8#include <edid.h>
9#include <gpio.h>
huang lin40f558e2014-09-19 14:51:52 +080010#include <string.h>
11#include <soc/addressmap.h>
12#include <soc/clock.h>
13#include <soc/display.h>
14#include <soc/edp.h>
Yakir Yang68f42be2015-04-29 10:08:12 -050015#include <soc/hdmi.h>
huang lin40f558e2014-09-19 14:51:52 +080016#include <soc/gpio.h>
17#include <soc/grf.h>
18#include <soc/soc.h>
19#include <soc/vop.h>
Patrick Rudolph8b56c8c2020-02-19 12:57:00 +010020#include <framebuffer_info.h>
huang lin40f558e2014-09-19 14:51:52 +080021
22#include "chip.h"
23
Elyes HAOUASf3ca88b2018-05-25 09:52:45 +020024void rk_display_init(struct device *dev, u32 lcdbase, unsigned long fb_size)
huang lin40f558e2014-09-19 14:51:52 +080025{
26 struct edid edid;
Lin Huangb9a78772016-04-25 18:50:55 +080027 uint32_t val;
huang lin40f558e2014-09-19 14:51:52 +080028 struct soc_rockchip_rk3288_config *conf = dev->chip_info;
29 uint32_t lower = ALIGN_DOWN(lcdbase, MiB);
30 uint32_t upper = ALIGN_UP(lcdbase + fb_size, MiB);
David Hendricksaf42f062015-06-17 13:47:28 -070031 enum vop_modes detected_mode = VOP_MODE_UNKNOWN;
huang lin40f558e2014-09-19 14:51:52 +080032
33 printk(BIOS_SPEW, "LCD framebuffer @%p\n", (void *)(lcdbase));
34 memset((void *)lcdbase, 0, fb_size); /* clear the framebuffer */
35 dcache_clean_invalidate_by_mva((void *)lower, upper - lower);
36 mmu_config_range(lower / MiB, (upper - lower) / MiB, DCACHE_OFF);
37
Yakir Yang68f42be2015-04-29 10:08:12 -050038 switch (conf->vop_mode) {
David Hendrickscc828512015-06-25 18:00:37 -070039 case VOP_MODE_NONE:
40 return;
David Hendricksaf42f062015-06-17 13:47:28 -070041 case VOP_MODE_AUTO_DETECT:
42 /* try EDP first, then HDMI */
43 case VOP_MODE_EDP:
44 printk(BIOS_DEBUG, "Attempting to setup EDP display.\n");
Yakir Yang68f42be2015-04-29 10:08:12 -050045 rkclk_configure_edp();
46 rkclk_configure_vop_aclk(conf->vop_id, 192 * MHz);
Lin Huangb9a78772016-04-25 18:50:55 +080047
48 /* grf_edp_ref_clk_sel: from internal 24MHz or 27MHz clock */
49 write32(&rk3288_grf->soc_con12, RK_SETBITS(1 << 4));
50
51 /* select epd signal from vop0 or vop1 */
52 val = (conf->vop_id == 1) ? RK_SETBITS(1 << 5) :
53 RK_CLRBITS(1 << 5);
54 write32(&rk3288_grf->soc_con6, val);
55
56 rk_edp_init();
David Hendricksaf42f062015-06-17 13:47:28 -070057
58 if (rk_edp_get_edid(&edid) == 0) {
59 detected_mode = VOP_MODE_EDP;
60 break;
61 } else {
62 printk(BIOS_WARNING, "Cannot get EDID from EDP.\n");
63 if (conf->vop_mode == VOP_MODE_EDP)
64 return;
Yakir Yang68f42be2015-04-29 10:08:12 -050065 }
Arthur Heymans507b0742022-03-24 01:16:34 +010066 __fallthrough;
David Hendricksaf42f062015-06-17 13:47:28 -070067 case VOP_MODE_HDMI:
68 printk(BIOS_DEBUG, "Attempting to setup HDMI display.\n");
69 rkclk_configure_hdmi();
70 rkclk_configure_vop_aclk(conf->vop_id, 384 * MHz);
71 rk_hdmi_init(conf->vop_id);
72
73 if (rk_hdmi_get_edid(&edid) == 0) {
74 detected_mode = VOP_MODE_HDMI;
75 break;
76 } else {
77 printk(BIOS_WARNING, "Cannot get EDID from HDMI.\n");
78 if (conf->vop_mode == VOP_MODE_HDMI)
79 return;
80 }
Arthur Heymans507b0742022-03-24 01:16:34 +010081 __fallthrough;
David Hendricksaf42f062015-06-17 13:47:28 -070082 default:
83 printk(BIOS_WARNING, "Cannot read any edid info, aborting.\n");
84 return;
huang lin40f558e2014-09-19 14:51:52 +080085 }
86
David Hendricks7dbf9c62015-07-30 18:49:48 -070087 if (rkclk_configure_vop_dclk(conf->vop_id, edid.mode.pixel_clock * KHz)) {
huang lin40f558e2014-09-19 14:51:52 +080088 printk(BIOS_WARNING, "config vop err\n");
89 return;
90 }
91
Julius Werner69112192016-03-14 17:29:55 -070092 edid_set_framebuffer_bits_per_pixel(&edid,
Julius Werner2b6db972016-04-06 12:50:40 -070093 conf->framebuffer_bits_per_pixel, 0);
David Hendricksaf42f062015-06-17 13:47:28 -070094 rkvop_mode_set(conf->vop_id, &edid, detected_mode);
huang lin40f558e2014-09-19 14:51:52 +080095
Lin Huang152e6752016-10-20 14:22:11 -070096 rkvop_prepare(conf->vop_id, &edid);
97 rkvop_enable(conf->vop_id, lcdbase);
huang lin40f558e2014-09-19 14:51:52 +080098
David Hendricksaf42f062015-06-17 13:47:28 -070099 switch (detected_mode) {
100 case VOP_MODE_HDMI:
Yakir Yang68f42be2015-04-29 10:08:12 -0500101 if (rk_hdmi_enable(&edid)) {
102 printk(BIOS_WARNING, "hdmi enable err\n");
103 return;
104 }
105
106 /*
107 * HACK: if we do remove this delay, HDMI TV may not show
108 * anythings. So we make an delay here, ensure TV have
109 * enough time to respond.
110 */
111 mdelay(2000);
112 break;
113
David Hendricksaf42f062015-06-17 13:47:28 -0700114 case VOP_MODE_EDP:
Yakir Yang68f42be2015-04-29 10:08:12 -0500115 default:
Lin Huanga09b3382016-10-23 14:17:25 -0700116 if (rk_edp_prepare()) {
117 printk(BIOS_WARNING, "edp prepare err\n");
118 return;
119 }
Yakir Yang68f42be2015-04-29 10:08:12 -0500120 if (rk_edp_enable()) {
121 printk(BIOS_WARNING, "edp enable err\n");
122 return;
123 }
124 mainboard_power_on_backlight();
125 break;
huang lin40f558e2014-09-19 14:51:52 +0800126 }
127
Patrick Rudolph8b56c8c2020-02-19 12:57:00 +0100128 fb_new_framebuffer_info_from_edid(&edid, (uintptr_t)lcdbase);
huang lin40f558e2014-09-19 14:51:52 +0800129}