mb/google/fatcat: add pre-mem configuration based on fw_config
[coreboot.git] / src / soc / rockchip / rk3288 / display.c
blobf9f41e2f9c0de225359292fb8b8f0a84312ef885
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/cache.h>
4 #include <device/mmio.h>
5 #include <console/console.h>
6 #include <device/device.h>
7 #include <delay.h>
8 #include <edid.h>
9 #include <gpio.h>
10 #include <string.h>
11 #include <soc/addressmap.h>
12 #include <soc/clock.h>
13 #include <soc/display.h>
14 #include <soc/edp.h>
15 #include <soc/hdmi.h>
16 #include <soc/grf.h>
17 #include <soc/soc.h>
18 #include <soc/vop.h>
19 #include <framebuffer_info.h>
21 #include "chip.h"
23 void rk_display_init(struct device *dev, u32 lcdbase, unsigned long fb_size)
25 struct edid edid;
26 uint32_t val;
27 struct soc_rockchip_rk3288_config *conf = dev->chip_info;
28 uint32_t lower = ALIGN_DOWN(lcdbase, MiB);
29 uint32_t upper = ALIGN_UP(lcdbase + fb_size, MiB);
30 enum vop_modes detected_mode = VOP_MODE_UNKNOWN;
32 printk(BIOS_SPEW, "LCD framebuffer @%p\n", (void *)(lcdbase));
33 memset((void *)lcdbase, 0, fb_size); /* clear the framebuffer */
34 dcache_clean_invalidate_by_mva((void *)lower, upper - lower);
35 mmu_config_range(lower / MiB, (upper - lower) / MiB, DCACHE_OFF);
37 switch (conf->vop_mode) {
38 case VOP_MODE_NONE:
39 return;
40 case VOP_MODE_AUTO_DETECT:
41 /* try EDP first, then HDMI */
42 case VOP_MODE_EDP:
43 printk(BIOS_DEBUG, "Attempting to setup EDP display.\n");
44 rkclk_configure_edp();
45 rkclk_configure_vop_aclk(conf->vop_id, 192 * MHz);
47 /* grf_edp_ref_clk_sel: from internal 24MHz or 27MHz clock */
48 write32(&rk3288_grf->soc_con12, RK_SETBITS(1 << 4));
50 /* select epd signal from vop0 or vop1 */
51 val = (conf->vop_id == 1) ? RK_SETBITS(1 << 5) :
52 RK_CLRBITS(1 << 5);
53 write32(&rk3288_grf->soc_con6, val);
55 rk_edp_init();
57 if (rk_edp_get_edid(&edid) == 0) {
58 detected_mode = VOP_MODE_EDP;
59 break;
60 } else {
61 printk(BIOS_WARNING, "Cannot get EDID from EDP.\n");
62 if (conf->vop_mode == VOP_MODE_EDP)
63 return;
65 __fallthrough;
66 case VOP_MODE_HDMI:
67 printk(BIOS_DEBUG, "Attempting to setup HDMI display.\n");
68 rkclk_configure_hdmi();
69 rkclk_configure_vop_aclk(conf->vop_id, 384 * MHz);
70 rk_hdmi_init(conf->vop_id);
72 if (rk_hdmi_get_edid(&edid) == 0) {
73 detected_mode = VOP_MODE_HDMI;
74 break;
75 } else {
76 printk(BIOS_WARNING, "Cannot get EDID from HDMI.\n");
77 if (conf->vop_mode == VOP_MODE_HDMI)
78 return;
80 __fallthrough;
81 default:
82 printk(BIOS_WARNING, "Cannot read any edid info, aborting.\n");
83 return;
86 if (rkclk_configure_vop_dclk(conf->vop_id, edid.mode.pixel_clock * KHz)) {
87 printk(BIOS_WARNING, "config vop err\n");
88 return;
91 edid_set_framebuffer_bits_per_pixel(&edid,
92 conf->framebuffer_bits_per_pixel, 0);
93 rkvop_mode_set(conf->vop_id, &edid, detected_mode);
95 rkvop_prepare(conf->vop_id, &edid);
96 rkvop_enable(conf->vop_id, lcdbase);
98 switch (detected_mode) {
99 case VOP_MODE_HDMI:
100 if (rk_hdmi_enable(&edid)) {
101 printk(BIOS_WARNING, "hdmi enable err\n");
102 return;
106 * HACK: if we do remove this delay, HDMI TV may not show
107 * anythings. So we make an delay here, ensure TV have
108 * enough time to respond.
110 mdelay(2000);
111 break;
113 case VOP_MODE_EDP:
114 default:
115 if (rk_edp_prepare()) {
116 printk(BIOS_WARNING, "edp prepare err\n");
117 return;
119 if (rk_edp_enable()) {
120 printk(BIOS_WARNING, "edp enable err\n");
121 return;
123 mainboard_power_on_backlight();
124 break;
127 fb_new_framebuffer_info_from_edid(&edid, (uintptr_t)lcdbase);