libpayload: cbgfx: Allow rotation of the display
Sometimes the display native orientation does not match the device default orientation, so allow rotation of the framebuffer before it is displayed on screen. set_pixel now take coordinates in the rotated coordinate system, and converts the coordinates before writing to the framebuffer. Also, screen.size now matches the rotated system (_not_ the framebuffer size). BUG=b:132049716 TEST=Boot krane, see that FW screen is orientation properly. Change-Id: If9316c0ce33c17057372ef5995a2c68de4f11f02 Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/34732 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-by: Christian Walter <christian.walter@9elements.com>
This commit is contained in:
parent
87f265b210
commit
564720f2c8
|
@ -129,8 +129,30 @@ static inline void set_pixel(struct vector *coord, uint32_t color)
|
||||||
{
|
{
|
||||||
const int bpp = fbinfo->bits_per_pixel;
|
const int bpp = fbinfo->bits_per_pixel;
|
||||||
const int bpl = fbinfo->bytes_per_line;
|
const int bpl = fbinfo->bytes_per_line;
|
||||||
|
struct vector rcoord;
|
||||||
int i;
|
int i;
|
||||||
uint8_t * const pixel = fbaddr + coord->y * bpl + coord->x * bpp / 8;
|
|
||||||
|
switch (fbinfo->orientation) {
|
||||||
|
case CB_FB_ORIENTATION_NORMAL:
|
||||||
|
default:
|
||||||
|
rcoord.x = coord->x;
|
||||||
|
rcoord.y = coord->y;
|
||||||
|
break;
|
||||||
|
case CB_FB_ORIENTATION_BOTTOM_UP:
|
||||||
|
rcoord.x = screen.size.width - 1 - coord->x;
|
||||||
|
rcoord.y = screen.size.height - 1 - coord->y;
|
||||||
|
break;
|
||||||
|
case CB_FB_ORIENTATION_LEFT_UP:
|
||||||
|
rcoord.x = coord->y;
|
||||||
|
rcoord.y = screen.size.width - 1 - coord->x;
|
||||||
|
break;
|
||||||
|
case CB_FB_ORIENTATION_RIGHT_UP:
|
||||||
|
rcoord.x = screen.size.height - 1 - coord->y;
|
||||||
|
rcoord.y = coord->x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t * const pixel = fbaddr + rcoord.y * bpl + rcoord.x * bpp / 8;
|
||||||
for (i = 0; i < bpp / 8; i++)
|
for (i = 0; i < bpp / 8; i++)
|
||||||
pixel[i] = (color >> (i * 8));
|
pixel[i] = (color >> (i * 8));
|
||||||
}
|
}
|
||||||
|
@ -152,8 +174,17 @@ static int cbgfx_init(void)
|
||||||
if (!fbaddr)
|
if (!fbaddr)
|
||||||
return CBGFX_ERROR_FRAMEBUFFER_ADDR;
|
return CBGFX_ERROR_FRAMEBUFFER_ADDR;
|
||||||
|
|
||||||
screen.size.width = fbinfo->x_resolution;
|
switch (fbinfo->orientation) {
|
||||||
screen.size.height = fbinfo->y_resolution;
|
default: /* Normal or rotated 180 degrees. */
|
||||||
|
screen.size.width = fbinfo->x_resolution;
|
||||||
|
screen.size.height = fbinfo->y_resolution;
|
||||||
|
break;
|
||||||
|
case CB_FB_ORIENTATION_LEFT_UP: /* 90 degree rotation. */
|
||||||
|
case CB_FB_ORIENTATION_RIGHT_UP:
|
||||||
|
screen.size.width = fbinfo->y_resolution;
|
||||||
|
screen.size.height = fbinfo->x_resolution;
|
||||||
|
break;
|
||||||
|
}
|
||||||
screen.offset.x = 0;
|
screen.offset.x = 0;
|
||||||
screen.offset.y = 0;
|
screen.offset.y = 0;
|
||||||
|
|
||||||
|
@ -242,7 +273,7 @@ int clear_screen(const struct rgb_color *rgb)
|
||||||
* We assume that for 32bpp the high byte gets ignored anyway. */
|
* We assume that for 32bpp the high byte gets ignored anyway. */
|
||||||
if ((((color >> 8) & 0xff) == (color & 0xff)) && (bpp == 16 ||
|
if ((((color >> 8) & 0xff) == (color & 0xff)) && (bpp == 16 ||
|
||||||
(((color >> 16) & 0xff) == (color & 0xff)))) {
|
(((color >> 16) & 0xff) == (color & 0xff)))) {
|
||||||
memset(fbaddr, color & 0xff, screen.size.height * bpl);
|
memset(fbaddr, color & 0xff, fbinfo->y_resolution * bpl);
|
||||||
} else {
|
} else {
|
||||||
for (p.y = 0; p.y < screen.size.height; p.y++)
|
for (p.y = 0; p.y < screen.size.height; p.y++)
|
||||||
for (p.x = 0; p.x < screen.size.width; p.x++)
|
for (p.x = 0; p.x < screen.size.width; p.x++)
|
||||||
|
|
|
@ -189,6 +189,14 @@ struct cb_forward {
|
||||||
u64 forward;
|
u64 forward;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Panel orientation, matches drm_connector.h in the Linux kernel. */
|
||||||
|
enum cb_fb_orientation {
|
||||||
|
CB_FB_ORIENTATION_NORMAL = 0,
|
||||||
|
CB_FB_ORIENTATION_BOTTOM_UP = 1,
|
||||||
|
CB_FB_ORIENTATION_LEFT_UP = 2,
|
||||||
|
CB_FB_ORIENTATION_RIGHT_UP = 3,
|
||||||
|
};
|
||||||
|
|
||||||
struct cb_framebuffer {
|
struct cb_framebuffer {
|
||||||
u32 tag;
|
u32 tag;
|
||||||
u32 size;
|
u32 size;
|
||||||
|
@ -206,6 +214,7 @@ struct cb_framebuffer {
|
||||||
u8 blue_mask_size;
|
u8 blue_mask_size;
|
||||||
u8 reserved_mask_pos;
|
u8 reserved_mask_pos;
|
||||||
u8 reserved_mask_size;
|
u8 reserved_mask_size;
|
||||||
|
u8 orientation;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CB_GPIO_ACTIVE_LOW 0
|
#define CB_GPIO_ACTIVE_LOW 0
|
||||||
|
|
Loading…
Reference in New Issue