From: Shen Zhenyi Date: Mon, 12 Oct 2015 06:27:00 +0000 (+0800) Subject: rk_fb: add extern screen open iommu, when dual screen display using iommu X-Git-Tag: firefly_0821_release~3728 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=firefly-linux-kernel-4.4.55.git;a=commitdiff_plain;h=5f6abdf11d058238fe3fc9c409eaaef7aa811d6d rk_fb: add extern screen open iommu, when dual screen display using iommu Change-Id: Ia216d102df6841d4497144fe3c53aaeea9860178 Signed-off-by: Shen Zhenyi --- diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index d2e74fccacd0..5a30657a10ce 100755 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -3381,7 +3381,9 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) char name[6] = {0}; int i, win_id; static bool load_screen = false; - char *envp[3]; + char *envp[4]; + char envplcdc[32]; + char envpfbdev[32]; int ret, list_is_empty = 0; if (unlikely(!rk_fb) || unlikely(!screen)) @@ -3426,14 +3428,13 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) } envp[0] = "switch screen"; - envp[1] = kmalloc(32, GFP_KERNEL); - if (envp[1] == NULL) { - pr_err("switch screen kmalloc envp[1] fail\n"); - mutex_unlock(&dev_drv->switch_screen); - return 0; - } - sprintf(envp[1], "SCREEN=%d,ENABLE=%d", screen->type, enable); - envp[2] = NULL; + memset(envplcdc, 0, sizeof(envplcdc)); + memset(envpfbdev, 0, sizeof(envpfbdev)); + sprintf(envplcdc, "SCREEN=%d,ENABLE=%d", screen->type, enable); + sprintf(envpfbdev, "FBDEV=%d", dev_drv->fb_index_base); + envp[1] = envplcdc; + envp[2] = envpfbdev; + envp[3] = NULL; if ((rk_fb->disp_mode == ONE_DUAL) || (rk_fb->disp_mode == NO_DUAL)) { @@ -3457,7 +3458,6 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) if (dev_drv->cur_screen->type != screen->type) { dev_drv->hdmi_switch = 0; mutex_unlock(&dev_drv->switch_screen); - kfree(envp[1]); return 0; } @@ -3510,7 +3510,6 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) } } kobject_uevent_env(&dev_drv->dev->kobj, KOBJ_CHANGE, envp); - kfree(envp[1]); hdmi_switch_state = 0; dev_drv->hdmi_switch = 0; @@ -3542,7 +3541,9 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id); win = dev_drv->win[win_id]; if (win && fb_par->state) { + mutex_lock(&dev_drv->win_config); dev_drv->ops->load_screen(dev_drv, 1); + mutex_unlock(&dev_drv->win_config); info->var.activate |= FB_ACTIVATE_FORCE; if (rk_fb->disp_mode == ONE_DUAL) { @@ -3582,7 +3583,6 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) dev_drv->ops->load_screen(dev_drv, 0); } kobject_uevent_env(&dev_drv->dev->kobj, KOBJ_CHANGE, envp); - kfree(envp[1]); hdmi_switch_state = 1; load_screen = true; @@ -3753,6 +3753,8 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi) dma_addr_t fb_mem_phys; void *fb_mem_virt; #endif + ion_phys_addr_t phy_addr; + size_t len; win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id); if (win_id < 0) @@ -3779,9 +3781,64 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi) #endif memset(fbi->screen_base, 0, fbi->fix.smem_len); } else { - fbi->fix.smem_start = rk_fb->fb[0]->fix.smem_start; - fbi->fix.smem_len = rk_fb->fb[0]->fix.smem_len; - fbi->screen_base = rk_fb->fb[0]->screen_base; + if (dev_drv->prop == EXTEND && dev_drv->iommu_enabled) { + struct rk_lcdc_driver *dev_drv_prmry; + int win_id_prmry; + fb_mem_size = get_fb_size(dev_drv->reserved_fb); +#if defined(CONFIG_ION_ROCKCHIP) + dev_drv_prmry = rk_get_prmry_lcdc_drv(); + if (dev_drv_prmry == NULL) + return -ENODEV; + win_id_prmry = + dev_drv_prmry->ops->fb_get_win_id(dev_drv_prmry, + fbi->fix.id); + if (win_id_prmry < 0) + return -ENODEV; + else + fb_par->ion_hdl = + dev_drv_prmry->win[win_id_prmry]->area[0].ion_hdl; + fbi->screen_base = + ion_map_kernel(rk_fb->ion_client, + fb_par->ion_hdl); + dev_drv->win[win_id]->area[0].ion_hdl = + fb_par->ion_hdl; + #ifdef CONFIG_ROCKCHIP_IOMMU + if (dev_drv->mmu_dev) + ret = ion_map_iommu(dev_drv->dev, + rk_fb->ion_client, + fb_par->ion_hdl, + (unsigned long *)&phy_addr, + (unsigned long *)&len); + else + ret = ion_phys(rk_fb->ion_client, + fb_par->ion_hdl, + &phy_addr, &len); + #endif + if (ret < 0) { + dev_err(fbi->dev, "ion map to get phy addr failed\n"); + return -ENOMEM; + } + fbi->fix.smem_start = phy_addr; + fbi->fix.smem_len = len; +#else + fb_mem_virt = dma_alloc_writecombine(fbi->dev, + fb_mem_size, + &fb_mem_phys, + GFP_KERNEL); + if (!fb_mem_virt) { + pr_err("%s: Failed to allocate framebuffer\n", + __func__); + return -ENOMEM; + } + fbi->fix.smem_len = fb_mem_size; + fbi->fix.smem_start = fb_mem_phys; + fbi->screen_base = fb_mem_virt; +#endif + } else { + fbi->fix.smem_start = rk_fb->fb[0]->fix.smem_start; + fbi->fix.smem_len = rk_fb->fb[0]->fix.smem_len; + fbi->screen_base = rk_fb->fb[0]->screen_base; + } } fbi->screen_size = fbi->fix.smem_len; @@ -4217,7 +4274,15 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv, } else { struct fb_info *extend_fbi = rk_fb->fb[rk_fb->num_fb >> 1]; extend_fbi->var.pixclock = rk_fb->fb[0]->var.pixclock; - rk_fb_alloc_buffer(extend_fbi); + extend_fbi->fbops->fb_open(extend_fbi, 1); +#if defined(CONFIG_ROCKCHIP_IOMMU) + if (dev_drv->iommu_enabled) { + if (dev_drv->mmu_dev) + rockchip_iovmm_set_fault_handler(dev_drv->dev, + rk_fb_sysmmu_fault_handler); + } +#endif + rk_fb_alloc_buffer(extend_fbi); } #endif return 0;