示例#1
0
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;
}
示例#2
0
/*
 * 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;
}