static int mxc_elcdif_fb_blank(int blank, struct fb_info *info) { struct mxc_elcdif_fb_data *data = (struct mxc_elcdif_fb_data *)info->par; int ret = 0; if (data->cur_blank == blank) return ret; data->next_blank = blank; if (!g_elcdif_pix_clk_enable) { clk_enable(g_elcdif_pix_clk); g_elcdif_pix_clk_enable = true; } ret = mxc_elcdif_blank_panel(blank); if (ret == 0) data->cur_blank = blank; else return ret; if (blank == FB_BLANK_UNBLANK) { info->var.activate = (info->var.activate & ~FB_ACTIVATE_MASK) | FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; ret = mxc_elcdif_fb_set_par(info); if (ret) return ret; } if (data->cur_blank != FB_BLANK_UNBLANK) { if (g_elcdif_axi_clk_enable) { clk_disable(g_elcdif_axi_clk); g_elcdif_axi_clk_enable = false; } if (g_elcdif_pix_clk_enable) { clk_disable(g_elcdif_pix_clk); g_elcdif_pix_clk_enable = false; } } else { if (!g_elcdif_axi_clk_enable) { clk_enable(g_elcdif_axi_clk); g_elcdif_axi_clk_enable = true; } if (!g_elcdif_pix_clk_enable) { clk_enable(g_elcdif_pix_clk); g_elcdif_pix_clk_enable = true; } } return ret; }
/* * This routine actually sets the video mode. It's in here where we * the hardware state info->par and fix which can be affected by the * change in par. For this driver it doesn't do much. * */ static int mxc_elcdif_fb_set_par(struct fb_info *fbi) { struct mxc_elcdif_fb_data *data = (struct mxc_elcdif_fb_data *)fbi->par; struct elcdif_signal_cfg sig_cfg; int mem_len; dev_dbg(fbi->device, "Reconfiguring framebuffer\n"); /* If parameter no change, don't reconfigure. */ if (mxc_elcdif_fb_par_equal(fbi, data)) return 0; sema_init(&data->flip_sem, 1); /* release prev panel */ if (!g_elcdif_pix_clk_enable) { clk_enable(g_elcdif_pix_clk); g_elcdif_pix_clk_enable = true; } mxc_elcdif_blank_panel(FB_BLANK_POWERDOWN); mxc_elcdif_stop(); release_dotclk_panel(); mxc_elcdif_dma_release(); mxc_elcdif_fb_set_fix(fbi); if (g_elcdif_pix_clk_enable) { clk_disable(g_elcdif_pix_clk); g_elcdif_pix_clk_enable = false; } mem_len = fbi->var.yres_virtual * fbi->fix.line_length; if (!fbi->fix.smem_start || (mem_len > fbi->fix.smem_len)) { if (fbi->fix.smem_start) mxc_elcdif_fb_unmap_video_memory(fbi); if (mxc_elcdif_fb_map_video_memory(fbi) < 0) return -ENOMEM; } if (data->next_blank != FB_BLANK_UNBLANK) return 0; /* init next panel */ if (!g_elcdif_pix_clk_enable) { clk_enable(g_elcdif_pix_clk); g_elcdif_pix_clk_enable = true; } mxc_init_elcdif(); mxc_elcdif_init_panel(); dev_dbg(fbi->device, "pixclock = %u Hz\n", (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL)); memset(&sig_cfg, 0, sizeof(sig_cfg)); if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT) sig_cfg.Hsync_pol = true; if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) sig_cfg.Vsync_pol = true; if (fbi->var.sync & FB_SYNC_CLK_LAT_FALL) sig_cfg.clk_pol = true; if (!(fbi->var.sync & FB_SYNC_OE_LOW_ACT)) sig_cfg.enable_pol = true; setup_dotclk_panel((PICOS2KHZ(fbi->var.pixclock)) * 1000UL, fbi->var.vsync_len, fbi->var.upper_margin + fbi->var.yres + fbi->var.lower_margin, fbi->var.upper_margin, fbi->var.yres, fbi->var.hsync_len, fbi->var.left_margin + fbi->var.xres + fbi->var.right_margin, fbi->var.left_margin, fbi->var.xres, bpp_to_pixfmt(fbi), data->output_pix_fmt, sig_cfg, 1); mxc_elcdif_frame_addr_setup(fbi->fix.smem_start); mxc_elcdif_run(); mxc_elcdif_blank_panel(FB_BLANK_UNBLANK); fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var, &fbi->modelist); data->var = fbi->var; return 0; }