现成的 ADB 命令为:
wm size 1920x1280 ----> 这个 ADB 修改分辨率
wm density 240 ----> 这个 修改dpi
dpi 计算公式: ( √(x^2 + y^2) ) / 屏幕尺寸
其实 wm 调用的就 是 上层 WindowsManger.java 的方法,最终调用到 Framework 下的 WindowsManagerServices.java 代码。
如果上层想对 分辨率修改,可以重写 WindowsManagerServices.java 下的set 分辨率的方法。
这种方法也是最稳妥的办法。
wm 执行log 如下:
px30_evb:/ # wm size 640x480
logcat 如下:
10-12 08:05:46.995 1727 1727 D AndroidRuntime: Calling main entry com.android.commands.wm.Wm
10-12 08:05:47.001 396 408 I WindowManager: Using new display size: 640x480
如果在驱动中写死的话,一般不建议这样修改,容易出问题:
高通平台:
--- a/kernel/msm-3.18/drivers/video/msm/mdss/mdss_fb.c
+++ b/kernel/msm-3.18/drivers/video/msm/mdss/mdss_fb.c
@@ -2501,8 +2501,8 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd)
else
fix->line_length = var->xres * bpp;
- var->xres_virtual = var->xres;
- var->yres_virtual = panel_info->yres * mfd->fb_page;
+ var->xres_virtual = 1920; //var->xres;
+ var->yres_virtual = 1080 * mfd->fb_page;
var->bits_per_pixel = bpp * 8; /* FrameBuffer color depth */
/*
@@ -3410,8 +3410,8 @@ void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo,
{
u32 frame_rate;
- var->xres = mdss_fb_get_panel_xres(pinfo);
- var->yres = pinfo->yres;
+ var->xres = 1920; //mdss_fb_get_panel_xres(pinfo);
+ var->yres = 1080; //pinfo->yres;
var->lower_margin = pinfo->lcdc.v_front_porch -
pinfo->prg_fet;
var->upper_margin = pinfo->lcdc.v_back_porch +
rockchip 平台
参考:
@ kernel\drivers\video\fbdev\core\modedb.c
/**
* fb_videomode_to_var - convert fb_videomode to fb_var_screeninfo
* @var: pointer to struct fb_var_screeninfo
* @mode: pointer to struct fb_videomode
*/
void fb_videomode_to_var(struct fb_var_screeninfo *var,
const struct fb_videomode *mode)
{
var->xres = mode->xres;
var->yres = mode->yres;
var->xres_virtual = mode->xres;
var->yres_virtual = mode->yres;
var->xoffset = 0;
var->yoffset = 0;
var->pixclock = mode->pixclock;
var->left_margin = mode->left_margin;
var->right_margin = mode->right_margin;
var->upper_margin = mode->upper_margin;
var->lower_margin = mode->lower_margin;
var->hsync_len = mode->hsync_len;
var->vsync_len = mode->vsync_len;
var->sync = mode->sync;
var->vmode = mode->vmode & FB_VMODE_MASK;
}
@ kernel\drivers\video\rockchip\rk_fb.c
int rk_fb_register(struct rk_lcdc_driver *dev_drv,
struct rk_lcdc_win *win, int id)
{
struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
struct fb_info *fbi;
struct rk_fb_par *fb_par = NULL;
int i = 0, ret = 0, index = 0;
unsigned long flags;
char time_line_name[16];
int mirror = 0;
if (rk_fb->num_lcdc == RK30_MAX_LCDC_SUPPORT)
return -ENXIO;
for (i = 0; i < RK30_MAX_LCDC_SUPPORT; i++) {
if (!rk_fb->lcdc_dev_drv[i]) {
rk_fb->lcdc_dev_drv[i] = dev_drv;
rk_fb->lcdc_dev_drv[i]->id = id;
rk_fb->num_lcdc++;
break;
}
}
index = i;
init_lcdc_device_driver(rk_fb, win, index);
dev_drv->fb_index_base = rk_fb->num_fb;
for (i = 0; i < dev_drv->lcdc_win_num; i++) {
fbi = framebuffer_alloc(0, &fb_pdev->dev);
if (!fbi) {
dev_err(&fb_pdev->dev, "fb framebuffer_alloc fail!");
return -ENOMEM;
}
fb_par = devm_kzalloc(&fb_pdev->dev, sizeof(struct rk_fb_par),
GFP_KERNEL);
if (!fb_par) {
dev_err(&fb_pdev->dev, "malloc fb_par for fb%d fail!",
rk_fb->num_fb);
return -ENOMEM;
}
fb_par->id = rk_fb->num_fb;
fb_par->lcdc_drv = dev_drv;
fbi->par = (void *)fb_par;
fbi->var = def_var;
fbi->fix = def_fix;
sprintf(fbi->fix.id, "fb%d", rk_fb->num_fb);
fb_videomode_to_var(&fbi->var, &dev_drv->cur_screen->mode);
if (dev_drv->dsp_mode == ONE_VOP_DUAL_MIPI_VER_SCAN) {
fbi->var.xres /= 2;
fbi->var.yres *= 2;
fbi->var.xres_virtual /= 2;
fbi->var.yres_virtual *= 2;
}
fbi->var.width = dev_drv->cur_screen->width;
fbi->var.height = dev_drv->cur_screen->height;
fbi->var.grayscale |=
((fbi->var.xres & 0xfff) << 8) + (fbi->var.yres << 20);
fbi->var.reserved[0] |= (fbi->var.xres >> 12);
#if defined(CONFIG_LOGO_LINUX_BMP)
fbi->var.bits_per_pixel = 32;
#else
fbi->var.bits_per_pixel = 16;
#endif
fbi->fix.line_length =
(fbi->var.xres_virtual) * (fbi->var.bits_per_pixel >> 3);
if (dev_drv->iommu_enabled)
fb_ops.fb_mmap = rk_fb_mmap;
fbi->fbops = &fb_ops;
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->pseudo_palette = dev_drv->win[i]->pseudo_pal;
ret = register_framebuffer(fbi);
if (ret < 0) {
dev_err(&fb_pdev->dev,
"%s fb%d register_framebuffer fail!\n",
__func__, rk_fb->num_fb);
return ret;
}
rkfb_create_sysfs(fbi);
rk_fb->fb[rk_fb->num_fb] = fbi;
dev_info(fbi->dev, "rockchip framebuffer registerd:%s\n",
fbi->fix.id);
rk_fb->num_fb++;
if (i == 0) {
init_waitqueue_head(&dev_drv->vsync_info.wait);
init_waitqueue_head(&dev_drv->update_regs_wait);
ret = device_create_file(fbi->dev, &dev_attr_vsync);
if (ret)
dev_err(fbi->dev,
"failed to create vsync file\n");
dev_drv->vsync_info.thread =
kthread_run(rk_fb_wait_for_vsync_thread, dev_drv,
"fb-vsync");
if (dev_drv->vsync_info.thread == ERR_PTR(-ENOMEM)) {
dev_err(fbi->dev,
"failed to run vsync thread\n");
dev_drv->vsync_info.thread = NULL;
}
dev_drv->vsync_info.active = 1;
mutex_init(&dev_drv->output_lock);
INIT_LIST_HEAD(&dev_drv->update_regs_list);
INIT_LIST_HEAD(&dev_drv->saved_list);
mutex_init(&dev_drv->update_regs_list_lock);
init_kthread_worker(&dev_drv->update_regs_worker);
dev_drv->update_regs_thread =
kthread_run(kthread_worker_fn,
&dev_drv->update_regs_worker, "rk-fb");
if (IS_ERR(dev_drv->update_regs_thread)) {
int err = PTR_ERR(dev_drv->update_regs_thread);
dev_drv->update_regs_thread = NULL;
pr_info("failed to run update_regs thread\n");
return err;
}
init_kthread_work(&dev_drv->update_regs_work,
rk_fb_update_regs_handler);
snprintf(time_line_name, sizeof(time_line_name),
"vop%d-timeline", id);
dev_drv->timeline =
sw_sync_timeline_create(time_line_name);
dev_drv->timeline_max = 1;
}
}
/* 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);
main_fbi->var.pixclock = dev_drv->pixclock;
if (dev_drv->iommu_enabled) {
if (dev_drv->mmu_dev)
rockchip_iovmm_set_fault_handler(dev_drv->dev,
rk_fb_sysmmu_fault_handler);
}
rk_fb_alloc_buffer(main_fbi); /* only alloc memory for main fb */
dev_drv->uboot_logo = support_uboot_display();
if (dev_drv->uboot_logo &&
uboot_logo_offset && uboot_logo_base) {
int width, height, bits, xvir;
phys_addr_t start = uboot_logo_base + uboot_logo_offset;
unsigned int size = uboot_logo_size - uboot_logo_offset;
unsigned int nr_pages;
int ymirror = 0;
struct page **pages;
char *vaddr;
int logo_len, i = 0;
if (dev_drv->ops->get_dspbuf_info)
dev_drv->ops->get_dspbuf_info(dev_drv, &xact,
&yact, &format, &dsp_addr, &ymirror);
logo_len = rk_fb_pixel_width(format) * xact * yact >> 3;
nr_pages = size >> PAGE_SHIFT;
pages = kzalloc(sizeof(struct page) * nr_pages,
GFP_KERNEL);
if (!pages)
return -ENOMEM;
while (i < nr_pages) {
pages[i] = phys_to_page(start);
start += PAGE_SIZE;
i++;
}
vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
if (!vaddr) {
pr_err("failed to vmap phy addr 0x%lx\n",
(long)(uboot_logo_base +
uboot_logo_offset));
kfree(pages);
return -1;
}
if (bmpdecoder(vaddr, main_fbi->screen_base, &width,
&height, &bits)) {
kfree(pages);
vunmap(vaddr);
return 0;
}
kfree(pages);
vunmap(vaddr);
if (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;
}
xvir = ALIGN(width * bits, 1 << 5) >> 5;
ymirror = 0;
local_irq_save(flags);
if (dev_drv->ops->wait_frame_start)
dev_drv->ops->wait_frame_start(dev_drv, 0);
mirror = ymirror || dev_drv->cur_screen->y_mirror;
if (dev_drv->ops->post_dspbuf) {
dev_drv->ops->post_dspbuf(dev_drv,
main_fbi->fix.smem_start +
(mirror ? logo_len : 0),
rk_fb_data_fmt(0, bits),
width, height, xvir,
ymirror);
}
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;
}
local_irq_restore(flags);
return 0;
} else if (dev_drv->uboot_logo && uboot_logo_base) {
u32 start = uboot_logo_base;
int logo_len, i = 0;
int y_mirror = 0;
unsigned int nr_pages;
struct page **pages;
char *vaddr;
int align = 0, xvir;
dev_drv->ops->get_dspbuf_info(dev_drv, &xact,
&yact, &format,
&start,
&y_mirror);
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;
}
if (y_mirror)
start -= logo_len;
align = start % PAGE_SIZE;
start -= align;
nr_pages = PAGE_ALIGN(logo_len + align) >> PAGE_SHIFT;
pages = kzalloc(sizeof(struct page) * nr_pages,
GFP_KERNEL);
if (!pages)
return -ENOMEM;
while (i < nr_pages) {
pages[i] = phys_to_page(start);
start += PAGE_SIZE;
i++;
}
vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
if (!vaddr) {
pr_err("failed to vmap phy addr 0x%x\n",
start);
kfree(pages);
return -1;
}
memcpy(main_fbi->screen_base, vaddr + align, logo_len);
kfree(pages);
vunmap(vaddr);
xvir = ALIGN(xact * rk_fb_pixel_width(format),
1 << 5) >> 5;
local_irq_save(flags);
if (dev_drv->ops->wait_frame_start)
dev_drv->ops->wait_frame_start(dev_drv, 0);
mirror = y_mirror || dev_drv->cur_screen->y_mirror;
dev_drv->ops->post_dspbuf(dev_drv,
main_fbi->fix.smem_start +
(mirror ? logo_len : 0),
format, xact, yact,
xvir,
y_mirror);
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;
}
local_irq_restore(flags);
return 0;
} else {
if (dev_drv->iommu_enabled) {
if (dev_drv->ops->mmu_en)
dev_drv->ops->mmu_en(dev_drv);
freed_index = 0;
}
}
#if defined(CONFIG_LOGO)
main_fbi->fbops->fb_set_par(main_fbi);
#if defined(CONFIG_LOGO_LINUX_BMP)
if (fb_prewine_bmp_logo(main_fbi, FB_ROTATE_UR)) {
fb_set_cmap(&main_fbi->cmap, main_fbi);
fb_show_bmp_logo(main_fbi, FB_ROTATE_UR);
}
#else
if (fb_prepare_logo(main_fbi, FB_ROTATE_UR)) {
fb_set_cmap(&main_fbi->cmap, main_fbi);
fb_show_logo(main_fbi, FB_ROTATE_UR);
}
#endif
main_fbi->fbops->fb_pan_display(&main_fbi->var, main_fbi);
#endif
} else {
struct fb_info *extend_fbi = rk_fb->fb[dev_drv->fb_index_base];
extend_fbi->var.pixclock = rk_fb->fb[0]->var.pixclock;
if (rk_fb->disp_mode == DUAL_LCD) {
extend_fbi->fbops->fb_open(extend_fbi, 1);
if (dev_drv->iommu_enabled) {
if (dev_drv->mmu_dev)
rockchip_iovmm_set_fault_handler(dev_drv->dev,
rk_fb_sysmmu_fault_handler);
}
rk_fb_alloc_buffer(extend_fbi);
}
}
#endif
return 0;
}