rk3288_lcdc_clk_enable(lcdc_dev);
/*backup reg config at uboot*/
-#ifdef CONFIG_ROCKCHIP_IOMMU
- for (i = 0; i < 0x330;) {
-#else
- for (i = 0; i < 0x1a0;) {
-#endif
+ for (i = 0; i < 0x1a0;) {
lcdc_readl(lcdc_dev,i);
i += 4;
}
static int rk3288_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
{
-#ifdef CONFIG_ROCKCHIP_IOMMU
- memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x330);
-#else
- memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x1fc);
-#endif
+ if (lcdc_dev->driver.iommu_enabled)
+ memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x330);
+ else
+ memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x1fc);
return 0;
}
static int rk3288_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
}
spin_unlock(&lcdc_dev->reg_lock);
+ return 0;
}
static int rk3288_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
static int rk3288_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
{
- int ret = -EINVAL;
- int fps;
u16 face = 0;
u32 v=0;
struct lcdc_device *lcdc_dev =
v_PWM_GEN_INTR_EN(1);
lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
#endif
+ return 0;
}
static int rk3288_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
rk3288_lcdc_pre_init(dev_drv);
rk3288_lcdc_clk_enable(lcdc_dev);
rk3288_lcdc_reg_restore(lcdc_dev);
- #ifdef CONFIG_ROCKCHIP_IOMMU
+ if (dev_drv->iommu_enabled)
rk3288_lcdc_mmu_en(dev_drv);
- #endif
if ((support_uboot_display()&&(lcdc_dev->prop == PRMRY))) {
rk3288_lcdc_set_dclk(dev_drv);
rk3288_lcdc_enable_irq(dev_drv);
struct lcdc_device, driver);
struct rk_lcdc_win *win = NULL;
struct rk_screen *screen = dev_drv->cur_screen;
- u32 mask, val;
+
#if defined(WAIT_FOR_SYNC)
int timeout;
unsigned long flags;
static int rk3288_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
{
+ u32 reg;
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
if (dev_drv->suspend_flag)
dev_drv->suspend_flag = 1;
flush_kthread_worker(&dev_drv->update_regs_worker);
+
+ for (reg = MMU_DTE_ADDR; reg <= MMU_AUTO_GATING; reg +=4)
+ lcdc_readl(lcdc_dev, reg);
if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
dev_drv->trsm_ops->disable();
.set_dsp_hue = rk3288_lcdc_set_hue,
.set_dsp_bcsh_bcs = rk3288_lcdc_set_bcsh_bcs,
.dump_reg = rk3288_lcdc_reg_dump,
- .mmu_en = rk3288_lcdc_mmu_en,
.cfg_done = rk3288_lcdc_config_done,
.set_irq_to_cpu = rk3288_lcdc_set_irq_to_cpu,
};
lcdc_dev->pwr18 = false; /*default set it as 3.xv power supply */
else
lcdc_dev->pwr18 = (val ? true : false);
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+ if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
+ lcdc_dev->driver.iommu_enabled = 0;
+ else
+ lcdc_dev->driver.iommu_enabled = val;
+#else
+ lcdc_dev->driver.iommu_enabled = 0;
+#endif
return 0;
}
lcdc_dev->irq, ret);
return ret;
}
-#ifdef CONFIG_ROCKCHIP_IOMMU
+
+ if (dev_drv->iommu_enabled) {
if(lcdc_dev->id == 0){
strcpy(dev_drv->mmu_dts_name, "iommu,vopb_mmu");
}else{
strcpy(dev_drv->mmu_dts_name, "iommu,vopl_mmu");
}
-#endif
+ }
ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
if (ret < 0) {
}
lcdc_dev->screen = dev_drv->screen0;
- dev_info(dev, "lcdc%d probe ok\n", lcdc_dev->id);
+ dev_info(dev, "lcdc%d probe ok, iommu %s\n",
+ lcdc_dev->id, dev_drv->iommu_enabled ? "enabled" : "disabled");
return 0;
}
#include <linux/rockchip/sysmmu.h>
#include <linux/dma-buf.h>
#endif
+
+
#define H_USE_FENCE 1
static int hdmi_switch_complete;
static struct platform_device *fb_pdev;
#endif
struct rk_fb_reg_win_data g_reg_win_data[4];
+static int g_last_win_num;
static int g_first_buf = 1;
-
static struct rk_fb_trsm_ops *trsm_lvds_ops;
static struct rk_fb_trsm_ops *trsm_edp_ops;
static struct rk_fb_trsm_ops *trsm_mipi_ops;
}
#ifdef CONFIG_ROCKCHIP_IOMMU
+static int g_last_addr[4];
+u32 freed_addr[10];
+u32 freed_index;
+
+#define DUMP_CHUNK 256
+char buf[PAGE_SIZE];
+
int rk_fb_sysmmu_fault_handler(struct device *dev,
enum rk_sysmmu_inttype itype, unsigned long pgtable_base,
unsigned long fault_addr,unsigned int status)
{
- struct fb_info *fbi = dev_get_drvdata(dev);
- struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
-
+ struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
+ int i = 0;
pr_err("PAGE FAULT occurred at 0x%lx (Page table base: 0x%lx),status=%d\n",
fault_addr, pgtable_base,status);
- dev_drv->ops->dump_reg(dev_drv);
- pr_err("Generating Kernel OOPS... because it is unrecoverable.\n");
- BUG();
+ printk("last config addr:\n"
+ "win0:0x%08x\n"
+ "win1:0x%08x\n"
+ "win2:0x%08x\n"
+ "win3:0x%08x\n",
+ g_last_addr[0],
+ g_last_addr[1],
+ g_last_addr[2],
+ g_last_addr[3]);
+ printk("last freed buffer:\n");
+ for (i = 0; freed_addr[i] != 0xfefefefe; i++)
+ printk("%d:0x%08x\n",i, freed_addr[i]);
+ dev_drv->ops->get_disp_info(dev_drv, buf,0) ;
+ for (i = 0; i < PAGE_SIZE; i += DUMP_CHUNK) {
+ if ((PAGE_SIZE - i) > DUMP_CHUNK) {
+ char c = buf[i + DUMP_CHUNK];
+ buf[i + DUMP_CHUNK] = 0;
+ pr_cont("%s", buf + i);
+ buf[i + DUMP_CHUNK] = c;
+ } else {
+ buf[PAGE_SIZE -1] = 0;
+ pr_cont("%s", buf + i);
+ }
+ }
return 0;
}
#endif
-void rk_fb_free_dma_buf(struct device *dev,struct rk_fb_reg_win_data *reg_win_data)
+
+void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv,struct rk_fb_reg_win_data *reg_win_data)
{
int i,index_buf;
struct rk_fb_reg_area_data *area_data;
for(i=0;i<reg_win_data->area_num;i++){
area_data = ®_win_data->reg_area_data[i];
index_buf = area_data->index_buf;
- #ifdef CONFIG_ROCKCHIP_IOMMU
- ion_unmap_iommu(dev, rk_fb->ion_client, area_data->ion_handle);
- #endif
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+ if (dev_drv->iommu_enabled) {
+ ion_unmap_iommu(dev_drv->dev, rk_fb->ion_client,
+ area_data->ion_handle);
+ freed_addr[freed_index++] = area_data->smem_start;
+ }
+#endif
if(area_data->ion_handle != NULL)
ion_free(rk_fb->ion_client, area_data->ion_handle);
- }
+ }
memset(reg_win_data, 0, sizeof(struct rk_fb_reg_win_data));
}
static void rk_fb_update_reg(struct rk_lcdc_driver * dev_drv,struct rk_fb_reg_data *regs)
{
- int i,j,ret=0;
+ int i,j;
struct rk_lcdc_win *win;
ktime_t timestamp = dev_drv->vsync_info.timestamp;
//struct rk_fb_reg_win_data old_reg_win_data[RK30_MAX_LAYER_SUPPORT];
bool wait_for_vsync;
int count = 100;
unsigned int dsp_addr[4];
-
+ long timeout;
for(i=0;i<dev_drv->lcdc_win_num;i++){
//old_reg_win_data[i]= regs->reg_win_data[i];
win = dev_drv->win[i];
rk_fb_update_driver(win,®s->reg_win_data[j]);
win->state = 1;
dev_drv->ops->set_par(dev_drv,i);
- dev_drv->ops->pan_display(dev_drv,i);
+ dev_drv->ops->pan_display(dev_drv,i);
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+ if (dev_drv->iommu_enabled)
+ g_last_addr[i] = win->area[0].smem_start + win->area[0].y_offset;
+#endif
}else{
win->z_order = -1;
win->state = 0;
//ret = wait_event_interruptible_timeout(dev_drv->vsync_info.wait,
// !ktime_equal(timestamp, dev_drv->vsync_info.timestamp),msecs_to_jiffies(dev_drv->cur_screen->ft+5));
do {
- ret = wait_event_interruptible_timeout(dev_drv->vsync_info.wait,
- !ktime_equal(timestamp, dev_drv->vsync_info.timestamp),msecs_to_jiffies(dev_drv->cur_screen->ft+5));
+ timestamp = dev_drv->vsync_info.timestamp;
+ timeout = wait_event_interruptible_timeout(dev_drv->vsync_info.wait,
+ ktime_compare(dev_drv->vsync_info.timestamp, timestamp) > 0,msecs_to_jiffies(25));
dev_drv->ops->get_dsp_addr(dev_drv,dsp_addr);
wait_for_vsync = false;
- for (i = 0; i < dev_drv->lcdc_win_num; i++) {
+ /*for (i = 0; i < dev_drv->lcdc_win_num; i++) {
if(dev_drv->win[i]->state == 1){
u32 new_start = regs->reg_win_data[i].reg_area_data[0].smem_start +
regs->reg_win_data[i].reg_area_data[0].y_offset;
break;
}
}
- }
+ }*/
} while (wait_for_vsync && count--);
#ifdef H_USE_FENCE
sw_sync_timeline_inc(dev_drv->timeline, 1);
#endif
if(!g_first_buf){
- for(i=0;i<regs->win_num;i++){
- rk_fb_free_dma_buf(dev_drv->dev,&g_reg_win_data[i]);
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+ if (dev_drv->iommu_enabled) {
+ freed_index = 0;
+ if (timeout >= 3)
+ msleep(15);
+ }
+#endif
+ for(i=0;i< g_last_win_num;i++){
+ rk_fb_free_dma_buf(dev_drv,&g_reg_win_data[i]);
}
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+ if (dev_drv->iommu_enabled)
+ freed_addr[freed_index] = 0xfefefefe;
+#endif
}
for(i=0;i<regs->win_num;i++){
memcpy(&g_reg_win_data[i], &(regs->reg_win_data[i]), sizeof(struct rk_fb_reg_win_data));
}
+ g_last_win_num = regs->win_num;
g_first_buf = 0;
if (dev_drv->wait_fs == 1)
#ifndef CONFIG_ROCKCHIP_IOMMU
ion_phys(rk_fb->ion_client, hdl, &phy_addr, &len);
#else
- ion_map_iommu(dev_drv->dev, rk_fb->ion_client, hdl,
- (unsigned long *)&phy_addr, (unsigned long *)&len);
+ if (dev_drv->iommu_enabled)
+ ion_map_iommu(dev_drv->dev, rk_fb->ion_client, hdl,
+ (unsigned long *)&phy_addr, (unsigned long *)&len);
+ else
+ ion_phys(rk_fb->ion_client, hdl, &phy_addr, &len);
#endif
reg_win_data->reg_area_data[i].smem_start = phy_addr;
reg_win_data->area_buf_num++;
}
}
return 0;
-#ifdef CONFIG_ROCKCHIP_IOMMU
-err_share_dma_buf:
- ion_free(rk_fb->ion_client, hdl);
- return -ENOMEM;
-#endif
}
static int rk_fb_set_win_config(struct fb_info *info,
}
win->area[0].ion_hdl = handle;
fbi->screen_base = ion_map_kernel(rk_fb->ion_client, handle);
-#ifndef CONFIG_ROCKCHIP_IOMMU
- ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
-#else
- ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
- printk("ion_phys: %x,%x\n", phy_addr, len);
- ion_map_iommu(dev_drv->dev, rk_fb->ion_client, handle,
+#ifdef CONFIG_ROCKCHIP_IOMMU
+ if (dev_drv->iommu_enabled)
+ ion_map_iommu(dev_drv->dev, rk_fb->ion_client, handle,
(unsigned long *)&phy_addr, (unsigned long *)&len);
- printk("%s: ion_map_iommu: %x,%x\n", __func__, phy_addr, len);
+ else
+ ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
+#else
+ ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
#endif
fbi->fix.smem_start = phy_addr;
fbi->fix.smem_len = len;
struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
struct fb_info *fbi;
int i = 0, ret = 0, index = 0;
- #ifdef CONFIG_ROCKCHIP_IOMMU
- struct device *mmu_dev = NULL;
- #endif
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+ struct device *mmu_dev = NULL;
+#endif
if (rk_fb->num_lcdc == RK30_MAX_LCDC_SUPPORT)
return -ENXIO;
fbi->var.width = dev_drv->cur_screen->width;
fbi->var.height = dev_drv->cur_screen->height;
fbi->var.pixclock = dev_drv->pixclock;
-#ifdef CONFIG_ROCKCHIP_IOMMU
- fb_ops.fb_mmap = rk_fb_mmap;
-#endif
+ 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;
- if (i == 0){ /* only alloc memory for main fb*/
- #ifdef CONFIG_ROCKCHIP_IOMMU
- mmu_dev = rockchip_get_sysmmu_device_by_compatible("iommu,vopl_mmu");
- if (mmu_dev) {
- platform_set_sysmmu(mmu_dev, dev_drv->dev);
- rockchip_sysmmu_set_fault_handler(dev_drv->dev, rk_fb_sysmmu_fault_handler);
- iovmm_activate(dev_drv->dev);
- }
- #endif
- rk_fb_alloc_buffer(fbi, rk_fb->num_fb);
- }
ret = register_framebuffer(fbi);
if (ret < 0) {
dev_err(&fb_pdev->dev, "%s fb%d register_framebuffer fail!\n",
main_fbi->fbops->fb_open(main_fbi, 1);
if(support_uboot_display())
return 0;
+
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+ if (dev_drv->iommu_enabled) {/* only alloc memory for main fb*/
+ mmu_dev = rockchip_get_sysmmu_device_by_compatible(dev_drv->mmu_dts_name);
+ if (mmu_dev) {
+ platform_set_sysmmu(mmu_dev, dev_drv->dev);
+ rockchip_sysmmu_set_fault_handler(dev_drv->dev,
+ rk_fb_sysmmu_fault_handler);
+ iovmm_activate(dev_drv->dev);
+ }
+ else
+ dev_err(dev_drv->dev, "failed to get rockchip iommu device\n");
+ }
+#endif
+ rk_fb_alloc_buffer(main_fbi, 0);
main_fbi->fbops->fb_set_par(main_fbi);
#if defined(CONFIG_LOGO_LINUX_BMP)
if (fb_prewine_bmp_logo(main_fbi, FB_ROTATE_UR)) {