rk3288: Auto-detect display.
We currently select either HDMI or EDP (default). This patch allows us to use HDMI as a fallback for devices that may have a display connected on either interface. It also renames the enums to sound a little more sensible in other contexts (more on that in the follow-up patches). VOP_MODE_AUTO is added to the mode enum which will make it explicit that a board can support either. In AUTO_MODE we will try EDP first and then fallback to HDMI. Other modes can be set to force a certain behavior such as HDMI-only on Mickey where it doesn't make sense to try EDP. A follow-up patch will add logic for when we explicitly don't want to probe for any display (headless devices). BUG=none BRANCH=none TEST=On veyron_danger, connected EDP and HDMI displays and saw dev mode screen appear on EDP display. Unplugged EDP and then dev mode screen showed up on HDMI. Change-Id: I22b38031c4ab3d79fbb182f7a906da1197f35543 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 3f57ed3758c4e516d9fd226ad9499b102b81b423 Original-Change-Id: I352dcde16f7f3ebbf5796852b685685e541eb794 Original-Signed-off-by: David Hendricks <dhendrix@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/281076 Original-Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-on: http://review.coreboot.org/10775 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
aa33609d28
commit
af42f069ea
|
@ -21,6 +21,7 @@
|
|||
#define __SOC_ROCKCHIP_RK3288_CHIP_H__
|
||||
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/vop.h> /* for vop_modes enum used in devicetree.cb */
|
||||
|
||||
struct soc_rockchip_rk3288_config {
|
||||
u32 vop_id;
|
||||
|
|
|
@ -46,6 +46,7 @@ void rk_display_init(device_t dev, u32 lcdbase,
|
|||
struct soc_rockchip_rk3288_config *conf = dev->chip_info;
|
||||
uint32_t lower = ALIGN_DOWN(lcdbase, MiB);
|
||||
uint32_t upper = ALIGN_UP(lcdbase + fb_size, MiB);
|
||||
enum vop_modes detected_mode = VOP_MODE_UNKNOWN;
|
||||
|
||||
printk(BIOS_SPEW, "LCD framebuffer @%p\n", (void *)(lcdbase));
|
||||
memset((void *)lcdbase, 0, fb_size); /* clear the framebuffer */
|
||||
|
@ -53,26 +54,41 @@ void rk_display_init(device_t dev, u32 lcdbase,
|
|||
mmu_config_range(lower / MiB, (upper - lower) / MiB, DCACHE_OFF);
|
||||
|
||||
switch (conf->vop_mode) {
|
||||
case HDMI_MODE:
|
||||
rkclk_configure_hdmi();
|
||||
rkclk_configure_vop_aclk(conf->vop_id, 384 * MHz);
|
||||
rk_hdmi_init(conf->vop_id);
|
||||
if (rk_hdmi_get_edid(&edid)) {
|
||||
printk(BIOS_WARNING, "can not get edid\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case EDP_MODE:
|
||||
default:
|
||||
case VOP_MODE_AUTO_DETECT:
|
||||
/* try EDP first, then HDMI */
|
||||
case VOP_MODE_EDP:
|
||||
printk(BIOS_DEBUG, "Attempting to setup EDP display.\n");
|
||||
rkclk_configure_edp();
|
||||
rkclk_configure_vop_aclk(conf->vop_id, 192 * MHz);
|
||||
rk_edp_init(conf->vop_id);
|
||||
if (rk_edp_get_edid(&edid)) {
|
||||
printk(BIOS_WARNING, "can not get edid\n");
|
||||
return;
|
||||
|
||||
if (rk_edp_get_edid(&edid) == 0) {
|
||||
detected_mode = VOP_MODE_EDP;
|
||||
break;
|
||||
} else {
|
||||
printk(BIOS_WARNING, "Cannot get EDID from EDP.\n");
|
||||
if (conf->vop_mode == VOP_MODE_EDP)
|
||||
return;
|
||||
}
|
||||
break;
|
||||
/* fall thru */
|
||||
case VOP_MODE_HDMI:
|
||||
printk(BIOS_DEBUG, "Attempting to setup HDMI display.\n");
|
||||
rkclk_configure_hdmi();
|
||||
rkclk_configure_vop_aclk(conf->vop_id, 384 * MHz);
|
||||
rk_hdmi_init(conf->vop_id);
|
||||
|
||||
if (rk_hdmi_get_edid(&edid) == 0) {
|
||||
detected_mode = VOP_MODE_HDMI;
|
||||
break;
|
||||
} else {
|
||||
printk(BIOS_WARNING, "Cannot get EDID from HDMI.\n");
|
||||
if (conf->vop_mode == VOP_MODE_HDMI)
|
||||
return;
|
||||
}
|
||||
/* fall thru */
|
||||
default:
|
||||
printk(BIOS_WARNING, "Cannot read any edid info, aborting.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rkclk_configure_vop_dclk(conf->vop_id, edid.pixel_clock * KHz)) {
|
||||
|
@ -84,12 +100,12 @@ void rk_display_init(device_t dev, u32 lcdbase,
|
|||
edid.bytes_per_line = edid.ha * conf->framebuffer_bits_per_pixel / 8;
|
||||
edid.x_resolution = edid.ha;
|
||||
edid.y_resolution = edid.va;
|
||||
rkvop_mode_set(conf->vop_id, &edid, conf->vop_mode);
|
||||
rkvop_mode_set(conf->vop_id, &edid, detected_mode);
|
||||
|
||||
rkvop_enable(conf->vop_id, lcdbase, &edid);
|
||||
|
||||
switch (conf->vop_mode) {
|
||||
case HDMI_MODE:
|
||||
switch (detected_mode) {
|
||||
case VOP_MODE_HDMI:
|
||||
if (rk_hdmi_enable(&edid)) {
|
||||
printk(BIOS_WARNING, "hdmi enable err\n");
|
||||
return;
|
||||
|
@ -103,7 +119,7 @@ void rk_display_init(device_t dev, u32 lcdbase,
|
|||
mdelay(2000);
|
||||
break;
|
||||
|
||||
case EDP_MODE:
|
||||
case VOP_MODE_EDP:
|
||||
default:
|
||||
if (rk_edp_enable()) {
|
||||
printk(BIOS_WARNING, "edp enable err\n");
|
||||
|
|
|
@ -100,9 +100,15 @@ enum {
|
|||
LB_RGB_1280X8 = 0x5
|
||||
};
|
||||
|
||||
enum {
|
||||
EDP_MODE,
|
||||
HDMI_MODE,
|
||||
enum vop_modes {
|
||||
/* EDP == 0 is used for early RK3288 products and is the most likely
|
||||
* use case, so keep it as the default. Other desired modes should
|
||||
* be set explicitly in the board's devicetree.cb.
|
||||
*/
|
||||
VOP_MODE_EDP = 0,
|
||||
VOP_MODE_HDMI,
|
||||
VOP_MODE_AUTO_DETECT,
|
||||
VOP_MODE_UNKNOWN,
|
||||
};
|
||||
|
||||
/* VOP_VERSION_INFO */
|
||||
|
|
|
@ -110,12 +110,12 @@ void rkvop_mode_set(u32 vop_id, const struct edid *edid, u32 mode)
|
|||
|
||||
switch (mode) {
|
||||
|
||||
case HDMI_MODE:
|
||||
case VOP_MODE_HDMI:
|
||||
clrsetbits_le32(&preg->sys_ctrl,
|
||||
M_ALL_OUT_EN, V_HDMI_OUT_EN(1));
|
||||
break;
|
||||
|
||||
case EDP_MODE:
|
||||
case VOP_MODE_EDP:
|
||||
default:
|
||||
clrsetbits_le32(&preg->sys_ctrl,
|
||||
M_ALL_OUT_EN, V_EDP_OUT_EN(1));
|
||||
|
|
Loading…
Reference in New Issue