Skip to content

Commit

Permalink
rk_fb: update uboot & kernel logo parse
Browse files Browse the repository at this point in the history
Sometimes we want to display logo at hdmi screen. but hdmi uboot
resolution maybe different with framebuffer size, so we need read
logo config from regs and decide how to display logo at kernel.

now only support uboot logo size = kernel logo size

Signed-off-by: Mark Yao <[email protected]>
  • Loading branch information
Mark Yao committed Dec 29, 2014
1 parent bef88e8 commit 2fddf40
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 26 deletions.
48 changes: 48 additions & 0 deletions drivers/video/rockchip/lcdc/rk312x_lcdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,52 @@ static void rk312x_lcdc_select_bcsh(struct rk_lcdc_driver *dev_drv,
}
}

static int rk312x_get_dspbuf_info(struct rk_lcdc_driver *dev_drv, u16 *xact,
u16 *yact, int *format, u32 *dsp_addr)
{
struct lcdc_device *lcdc_dev = container_of(dev_drv,
struct lcdc_device, driver);
u32 val;

spin_lock(&lcdc_dev->reg_lock);

val = lcdc_readl(lcdc_dev, WIN0_ACT_INFO);
*xact = (val & m_ACT_WIDTH)+1;
*yact = ((val & m_ACT_HEIGHT)>>16)+1;

val = lcdc_readl(lcdc_dev, SYS_CTRL);

*format = (val & m_WIN0_FORMAT) >> 3;
*dsp_addr = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);

spin_unlock(&lcdc_dev->reg_lock);

return 0;
}

static int rk312x_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
int format, u16 xact, u16 yact, u16 xvir)
{
struct lcdc_device *lcdc_dev = container_of(dev_drv,
struct lcdc_device, driver);
u32 val, mask;

mask = m_WIN0_FORMAT;
val = v_WIN0_FORMAT(format);
lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);

lcdc_msk_reg(lcdc_dev, WIN0_VIR, m_YRGB_VIR,
v_YRGB_VIR(xvir));
lcdc_writel(lcdc_dev, WIN0_ACT_INFO, v_ACT_WIDTH(xact) |
v_ACT_HEIGHT(yact));

lcdc_writel(lcdc_dev, WIN0_YRGB_MST, rgb_mst);

lcdc_cfg_done(lcdc_dev);

return 0;
}

static int rk312x_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
{
u16 face = 0;
Expand Down Expand Up @@ -2395,6 +2441,8 @@ static int rk312x_lcdc_dsp_black(struct rk_lcdc_driver *dev_drv, int enable)
static struct rk_lcdc_drv_ops lcdc_drv_ops = {
.open = rk312x_lcdc_open,
.load_screen = rk312x_load_screen,
.get_dspbuf_info = rk312x_get_dspbuf_info,
.post_dspbuf = rk312x_post_dspbuf,
.set_par = rk312x_lcdc_set_par,
.pan_display = rk312x_lcdc_pan_display,
.direct_set_addr = rk312x_lcdc_direct_set_win_addr,
Expand Down
48 changes: 48 additions & 0 deletions drivers/video/rockchip/lcdc/rk3288_lcdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,52 @@ static int rk3288_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)

}

static int rk3288_get_dspbuf_info(struct rk_lcdc_driver *dev_drv, u16 *xact,
u16 *yact, int *format, u32 *dsp_addr)
{
struct lcdc_device *lcdc_dev = container_of(dev_drv,
struct lcdc_device, driver);
u32 val;

spin_lock(&lcdc_dev->reg_lock);

val = lcdc_readl(lcdc_dev, WIN0_ACT_INFO);
*xact = (val & m_WIN0_ACT_WIDTH) + 1;
*yact = ((val & m_WIN0_ACT_HEIGHT)>>16) + 1;

val = lcdc_readl(lcdc_dev, WIN0_CTRL0);
*format = (val & m_WIN0_DATA_FMT) >> 1;
*dsp_addr = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);

spin_unlock(&lcdc_dev->reg_lock);

return 0;
}

static int rk3288_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
int format, u16 xact, u16 yact, u16 xvir)
{
struct lcdc_device *lcdc_dev = container_of(dev_drv,
struct lcdc_device, driver);
u32 val, mask;
int swap = (format == RGB888) ? 1 : 0;

mask = m_WIN0_DATA_FMT | m_WIN0_RB_SWAP;
val = v_WIN0_DATA_FMT(format) | v_WIN0_RB_SWAP(swap);
lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask, val);

lcdc_msk_reg(lcdc_dev, WIN0_VIR, m_WIN0_VIR_STRIDE,
v_WIN0_VIR_STRIDE(xvir));
lcdc_writel(lcdc_dev, WIN0_ACT_INFO, v_WIN0_ACT_WIDTH(xact) |
v_WIN0_ACT_HEIGHT(yact));

lcdc_writel(lcdc_dev, WIN0_YRGB_MST, rgb_mst);

lcdc_cfg_done(lcdc_dev);

return 0;
}

static int rk3288_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
{
u16 face = 0;
Expand Down Expand Up @@ -3535,6 +3581,8 @@ static struct rk_lcdc_drv_ops lcdc_drv_ops = {
.open = rk3288_lcdc_open,
.win_direct_en = rk3288_lcdc_win_direct_en,
.load_screen = rk3288_load_screen,
.get_dspbuf_info = rk3288_get_dspbuf_info,
.post_dspbuf = rk3288_post_dspbuf,
.set_par = rk3288_lcdc_set_par,
.pan_display = rk3288_lcdc_pan_display,
.direct_set_addr = rk3288_lcdc_direct_set_win_addr,
Expand Down
98 changes: 72 additions & 26 deletions drivers/video/rockchip/rk_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -4151,6 +4151,9 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
/* show logo for primary display device */
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE)
if (dev_drv->prop == PRMRY) {
u16 xact, yact;
int format;
u32 dsp_addr;
struct fb_info *main_fbi = rk_fb->fb[0];
main_fbi->fbops->fb_open(main_fbi, 1);

Expand All @@ -4165,8 +4168,8 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
rk_fb_alloc_buffer(main_fbi, 0); /* only alloc memory for main fb */
dev_drv->uboot_logo = support_uboot_display();

if (uboot_logo_offset && uboot_logo_base) {
struct rk_lcdc_win *win = dev_drv->win[0];
if (dev_drv->uboot_logo &&
uboot_logo_offset && uboot_logo_base) {
int width, height, bits;
phys_addr_t start = uboot_logo_base + uboot_logo_offset;
unsigned int size = uboot_logo_size - uboot_logo_offset;
Expand All @@ -4175,6 +4178,9 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
char *vaddr;
int i = 0;

if (dev_drv->ops->get_dspbuf_info)
dev_drv->ops->get_dspbuf_info(dev_drv, &xact,
&yact, &format, &dsp_addr);
nr_pages = size >> PAGE_SHIFT;
pages = kzalloc(sizeof(struct page) * nr_pages,
GFP_KERNEL);
Expand All @@ -4199,35 +4205,75 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
}
kfree(pages);
vunmap(vaddr);
if (width > main_fbi->var.xres ||
height > main_fbi->var.yres) {
pr_err("ERROR: logo size out of screen range");
if (dev_drv->uboot_logo &&
(width != xact || height != yact)) {
pr_err("can't support uboot kernel logo use different size [%dx%d] != [%dx%d]\n",
xact, yact, width, height);
return 0;
}

win->area[0].format = rk_fb_data_fmt(0, bits);
win->area[0].y_vir_stride = width * bits >> 5;
win->area[0].xpos = (main_fbi->var.xres - width) >> 1;
win->area[0].ypos = (main_fbi->var.yres - height) >> 1;
win->area[0].xsize = width;
win->area[0].ysize = height;
win->area[0].xact = width;
win->area[0].yact = height;
win->area[0].xvir = win->area[0].y_vir_stride;
win->area[0].yvir = height;
win->area[0].smem_start = main_fbi->fix.smem_start;
win->area[0].y_offset = 0;

win->area_num = 1;
win->alpha_mode = 4;
win->alpha_en = 0;
win->g_alpha_val = 0;
if (dev_drv->ops->post_dspbuf) {
dev_drv->ops->post_dspbuf(dev_drv,
main_fbi->fix.smem_start,
rk_fb_data_fmt(0, bits),
width, height, width * bits >> 5);
}
if (dev_drv->iommu_enabled) {
rk_fb_poll_wait_frame_complete();
if (dev_drv->ops->mmu_en)
dev_drv->ops->mmu_en(dev_drv);
freed_index = 0;
}

win->state = 1;
dev_drv->ops->set_par(dev_drv, 0);
dev_drv->ops->pan_display(dev_drv, 0);
dev_drv->ops->cfg_done(dev_drv);
return 0;
} else if (dev_drv->uboot_logo && uboot_logo_base) {
phys_addr_t start = uboot_logo_base;
int logo_len, i=0;
unsigned int nr_pages;
struct page **pages;
char *vaddr;

dev_drv->ops->get_dspbuf_info(dev_drv, &xact,
&yact, &format,
&start);
logo_len = rk_fb_pixel_width(format) * xact * yact >> 3;
if (logo_len > uboot_logo_size ||
logo_len > main_fbi->fix.smem_len) {
pr_err("logo size > uboot reserve buffer size\n");
return -1;
}

nr_pages = uboot_logo_size >> PAGE_SHIFT;
pages = kzalloc(sizeof(struct page) * nr_pages,
GFP_KERNEL);
while (i < nr_pages) {
pages[i] = phys_to_page(start);
start += PAGE_SIZE;
i++;
}
vaddr = vmap(pages, nr_pages, VM_MAP,
pgprot_writecombine(PAGE_KERNEL));
if (!vaddr) {
pr_err("failed to vmap phy addr %x\n",
uboot_logo_base);
return -1;
}

memcpy(main_fbi->screen_base, vaddr, logo_len);

kfree(pages);
vunmap(vaddr);

dev_drv->ops->post_dspbuf(dev_drv,
main_fbi->fix.smem_start,
format, xact, yact,
xact * rk_fb_pixel_width(format) >> 5);
if (dev_drv->iommu_enabled) {
rk_fb_poll_wait_frame_complete();
if (dev_drv->ops->mmu_en)
dev_drv->ops->mmu_en(dev_drv);
freed_index = 0;
}
return 0;
}
#if defined(CONFIG_LOGO)
Expand Down
6 changes: 6 additions & 0 deletions include/linux/rk_fb.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,12 @@ struct rk_lcdc_drv_ops {
ssize_t(*get_disp_info) (struct rk_lcdc_driver *dev_drv, char *buf,
int layer_id);
int (*load_screen) (struct rk_lcdc_driver *dev_drv, bool initscreen);
int (*get_dspbuf_info) (struct rk_lcdc_driver *dev_drv,
u16 *xact, u16 *yact, int *format,
u32 *dsp_addr);
int (*post_dspbuf)(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
int format, u16 xact, u16 yact, u16 xvir);

int (*get_win_state) (struct rk_lcdc_driver *dev_drv, int layer_id);
int (*ovl_mgr) (struct rk_lcdc_driver *dev_drv, int swap, bool set); /*overlay manager*/
int (*fps_mgr) (struct rk_lcdc_driver *dev_drv, int fps, bool set);
Expand Down
Binary file modified logo.bmp
Binary file not shown.

0 comments on commit 2fddf40

Please sign in to comment.