Esempio n. 1
0
/*!
 * Probe routine for the framebuffer driver. It is called during the
 * driver binding process.      The following functions are performed in
 * this routine: Framebuffer initialization, Memory allocation and
 * mapping, Framebuffer registration, IPU initialization.
 *
 * @return      Appropriate error code to the kernel common code
 */
static int mxcfb_probe(struct platform_device *pdev)
{
	struct fb_info *fbi;
	struct mxcfb_info *mxc_fbi;
	int ret;

	platform_set_drvdata(pdev, &mxcfb_drv_data);

	/*
	 * Initialize FB structures
	 */
	fbi = mxcfb_init_fbinfo(&pdev->dev, &mxcfb_ops);
	if (!fbi) {
		ret = -ENOMEM;
		goto err0;
	}
	mxcfb_drv_data.fbi = fbi;
	mxc_fbi = fbi->par;

	mxcfb_drv_data.suspended = false;
	init_waitqueue_head(&mxcfb_drv_data.suspend_wq);

	/*
	 * Allocate memory
	 */
	ret = mxcfb_map_video_memory(fbi);
	if (ret < 0) {
		goto err1;
	}

	mxcfb_init_panel(fbi);

	/*
	 * Register framebuffer
	 */
	ret = register_framebuffer(fbi);
	if (ret < 0) {
		goto err2;
	}

	dev_info(&pdev->dev, "%s registered\n", MXCFB_NAME);

	return 0;

      err2:
	mxcfb_unmap_video_memory(fbi);
      err1:
	if (&fbi->cmap)
		fb_dealloc_cmap(&fbi->cmap);
	framebuffer_release(fbi);
      err0:
	return ret;
}
Esempio n. 2
0
static void mxcfb_exit(void)
{
	struct fb_info *fbi = dev_get_drvdata(&mxcfb_device.dev);

	if (fbi) {
		mxcfb_unmap_video_memory(fbi);

		if (&fbi->cmap)
			fb_dealloc_cmap(&fbi->cmap);

		unregister_framebuffer(fbi);
		framebuffer_release(fbi);
	}

	platform_device_unregister(&mxcfb_device);
	platform_driver_unregister(&mxcfb_driver);
}
/*
 * Set framebuffer parameters and change the operating mode.
 *
 * @param       info     framebuffer information pointer
 */
static int mxcfb_set_par(struct fb_info *fbi)
{
	int retval = 0;
	u32 mem_len;
	ipu_di_signal_cfg_t sig_cfg;
	struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
	uint32_t out_pixel_fmt;

	ipu_disable_channel(mxc_fbi->ipu_ch);
	ipu_uninit_channel(mxc_fbi->ipu_ch);
	mxcfb_set_fix(fbi);

	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)
			mxcfb_unmap_video_memory(fbi);

		if (mxcfb_map_video_memory(fbi) < 0)
			return -ENOMEM;
	}

	setup_disp_channel1(fbi);

	memset(&sig_cfg, 0, sizeof(sig_cfg));
	if (fbi->var.vmode & FB_VMODE_INTERLACED) {
		sig_cfg.interlaced = 1;
		out_pixel_fmt = IPU_PIX_FMT_YUV444;
	} else {
		if (mxc_fbi->ipu_di_pix_fmt)
			out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
		else
			out_pixel_fmt = IPU_PIX_FMT_RGB666;
	}
	if (fbi->var.vmode & FB_VMODE_ODD_FLD_FIRST) /* PAL */
		sig_cfg.odd_field_first = 1;
	if ((fbi->var.sync & FB_SYNC_EXT) || ext_clk_used)
		sig_cfg.ext_clk = 1;
	if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
		sig_cfg.Hsync_pol = 1;
	if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
		sig_cfg.Vsync_pol = 1;
	if (!(fbi->var.sync & FB_SYNC_CLK_LAT_FALL))
		sig_cfg.clk_pol = 1;
	if (fbi->var.sync & FB_SYNC_DATA_INVERT)
		sig_cfg.data_pol = 1;
	if (!(fbi->var.sync & FB_SYNC_OE_LOW_ACT))
		sig_cfg.enable_pol = 1;
	if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
		sig_cfg.clkidle_en = 1;

	debug("pixclock = %lu Hz\n", PICOS2KHZ(fbi->var.pixclock) * 1000UL);

	if (ipu_init_sync_panel(mxc_fbi->ipu_di,
				(PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
				fbi->var.xres, fbi->var.yres,
				out_pixel_fmt,
				fbi->var.left_margin,
				fbi->var.hsync_len,
				fbi->var.right_margin,
				fbi->var.upper_margin,
				fbi->var.vsync_len,
				fbi->var.lower_margin,
				0, sig_cfg) != 0) {
		puts("mxcfb: Error initializing panel.\n");
		return -EINVAL;
	}

	retval = setup_disp_channel2(fbi);
	if (retval)
		return retval;

	if (mxc_fbi->blank == FB_BLANK_UNBLANK)
		ipu_enable_channel(mxc_fbi->ipu_ch);

	return retval;
}