动态修改屏分辨率

现成的 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;
}

发布了329 篇原创文章 · 获赞 66 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/Ciellee/article/details/102583694
今日推荐