Ejemplo n.º 1
0
/*
 * mxcfb_blank():
 *      Blank the display.
 */
static int mxcfb_blank(int blank, struct fb_info *fbi)
{
	int retval = 0;
	struct mxcfb_info *mxc_fbi = fbi->par;

	dev_dbg(fbi->device, "blank = %d\n", blank);

	retval = wait_event_interruptible(mxcfb_drv_data.suspend_wq,
				 (mxcfb_drv_data.suspended == false));
	if (retval < 0)
		return retval;

	mxc_fbi->blank = blank;

	switch (blank) {
	case FB_BLANK_POWERDOWN:
	case FB_BLANK_VSYNC_SUSPEND:
	case FB_BLANK_HSYNC_SUSPEND:
	case FB_BLANK_NORMAL:
		mxcfb_set_refresh_mode(fbi, MXCFB_REFRESH_OFF, NULL);
		break;
	case FB_BLANK_UNBLANK:
		mxcfb_set_refresh_mode(fbi, MXCFB_REFRESH_DEFAULT, NULL);
		break;
	}
	return 0;
}
Ejemplo n.º 2
0
/*!
 * Shut down the voutera
 *
 * @param vout      structure vout_data *
 *
 * @return status  0 Success
 */
static int mxc_v4l2out_streamoff(vout_data * vout)
{
	int retval = 0;
	u32 lockflag = 0;

	if (!vout)
		return -EINVAL;

	if (vout->state == STATE_STREAM_OFF) {
		return 0;
	}

	spin_lock_irqsave(&g_lock, lockflag);

	del_timer(&vout->output_timer);

	if (vout->state == STATE_STREAM_ON) {
		vout->state = STATE_STREAM_STOPPING;
	}

	ipu_disable_irq(IPU_IRQ_PP_IN_EOF);

	spin_unlock_irqrestore(&g_lock, lockflag);

	if (vout->post_proc_ch == MEM_PP_MEM) {	/* SDC or ADC with Rotation */
		ipu_disable_channel(MEM_PP_MEM, true);
		if (vout->rotate >= IPU_ROTATE_90_RIGHT) {
			ipu_disable_channel(MEM_ROT_PP_MEM, true);
			ipu_unlink_channels(MEM_PP_MEM, MEM_ROT_PP_MEM);
			ipu_unlink_channels(MEM_ROT_PP_MEM, vout->display_ch);
		} else {
			ipu_unlink_channels(MEM_PP_MEM, vout->display_ch);
		}
		ipu_disable_channel(vout->display_ch, true);
		ipu_uninit_channel(vout->display_ch);
		ipu_uninit_channel(MEM_PP_MEM);
		ipu_uninit_channel(MEM_ROT_PP_MEM);
	} else {		/* ADC Direct */
		ipu_disable_channel(MEM_PP_ADC, true);
		ipu_uninit_channel(MEM_PP_ADC);
	}
	vout->ready_q.head = vout->ready_q.tail = 0;

	vout->state = STATE_STREAM_OFF;

#ifdef CONFIG_FB_MXC_ASYNC_PANEL
	if (vout->cur_disp_output != DISP3) {
		mxcfb_set_refresh_mode(registered_fb
				       [vout->
					output_fb_num[vout->cur_disp_output]],
				       MXCFB_REFRESH_PARTIAL, 0);
	}
#endif

	return retval;
}
Ejemplo n.º 3
0
/*
 * 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;
	int mode;

	retval = wait_event_interruptible(mxcfb_drv_data.suspend_wq,
			 (mxcfb_drv_data.suspended == false));
	if (retval < 0)
		return retval;

	mode = mxcfb_set_refresh_mode(fbi, MXCFB_REFRESH_OFF, NULL);

	mxcfb_set_fix(fbi);

	if (mode != MXCFB_REFRESH_OFF) {
#ifdef PARTIAL_REFRESH
		mxcfb_set_refresh_mode(fbi, MXCFB_REFRESH_PARTIAL, NULL);
#else
		mxcfb_set_refresh_mode(fbi, MXCFB_REFRESH_AUTO, NULL);
#endif
	}
	return 0;
}
Ejemplo n.º 4
0
/*!
 * Suspends the framebuffer and blanks the screen. Power management support
 *
 * @param	pdev	pointer to device structure.
 * @param	state	state of the device.
 *
 * @return	success
 */
static int mxcfb_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct mxcfb_data *drv_data = platform_get_drvdata(pdev);
	struct fb_info *fbi = drv_data->fbi;
	struct mxcfb_info *mxc_fbi = fbi->par;

	drv_data->suspended = true;

	if (mxc_fbi->blank == FB_BLANK_UNBLANK)
		mxcfb_set_refresh_mode(fbi, MXCFB_REFRESH_OFF, NULL);
	/* Display OFF */
	ipu_adc_write_cmd(mxc_fbi->disp_num, CMD, DISOFF, 0, 0);

	return 0;
}
Ejemplo n.º 5
0
/*!
 * Resumes the framebuffer and unblanks the screen. Power management support
 *
 * @param       pdev     pointer to device structure.
 *
 * @return      success
 */
static int mxcfb_resume(struct platform_device *pdev)
{
	struct mxcfb_data *drv_data = platform_get_drvdata(pdev);
	struct fb_info *fbi = drv_data->fbi;
	struct mxcfb_info *mxc_fbi = fbi->par;

	/* Display ON */
	ipu_adc_write_cmd(mxc_fbi->disp_num, CMD, DISON, 0, 0);
	drv_data->suspended = false;

	if (mxc_fbi->blank == FB_BLANK_UNBLANK)
		mxcfb_set_refresh_mode(fbi, MXCFB_REFRESH_DEFAULT, NULL);
	wake_up_interruptible(&drv_data->suspend_wq);

	return 0;
}
Ejemplo n.º 6
0
/*!
 * Start the output stream
 *
 * @param vout      structure vout_data *
 *
 * @return status  0 Success
 */
static int mxc_v4l2out_streamon(vout_data * vout)
{
	ipu_channel_params_t params;
	int pp_in_buf[2];
	u16 out_width;
	u16 out_height;
	ipu_channel_t display_input_ch = MEM_PP_MEM;
	bool use_direct_adc = false;

	if (!vout)
		return -EINVAL;

	if (queue_size(&vout->ready_q) < 2) {
		DPRINTK("2 buffers not been queued yet!\n");
		return -EINVAL;
	}

	out_width = vout->crop_current.width;
	out_height = vout->crop_current.height;

	vout->next_done_ipu_buf = vout->next_rdy_ipu_buf = 0;
	vout->ipu_buf[0] = pp_in_buf[0] = dequeue_buf(&vout->ready_q);
	vout->ipu_buf[1] = pp_in_buf[1] = dequeue_buf(&vout->ready_q);

	/* Init Display Channel */
#ifdef CONFIG_FB_MXC_ASYNC_PANEL
	if (vout->cur_disp_output != DISP3) {
		int fbnum = vout->output_fb_num[vout->cur_disp_output];
		mxcfb_set_refresh_mode(registered_fb[fbnum],
				       MXCFB_REFRESH_OFF, 0);
		if (vout->rotate < IPU_ROTATE_90_RIGHT) {
			DPRINTK("Using PP direct to ADC channel\n");
			use_direct_adc = true;
			vout->display_ch = MEM_PP_ADC;
			vout->post_proc_ch = MEM_PP_ADC;

			memset(&params, 0, sizeof(params));
			params.mem_pp_adc.in_width = vout->v2f.fmt.pix.width;
			params.mem_pp_adc.in_height = vout->v2f.fmt.pix.height;
			params.mem_pp_adc.in_pixel_fmt =
			    vout->v2f.fmt.pix.pixelformat;
			params.mem_pp_adc.out_width = out_width;
			params.mem_pp_adc.out_height = out_height;
			params.mem_pp_adc.out_pixel_fmt = SDC_FG_FB_FORMAT;
#ifdef CONFIG_FB_MXC_EPSON_PANEL
			params.mem_pp_adc.out_left = 2 +
			    vout->crop_current.left;
#else
			params.mem_pp_adc.out_left = 12 +
			    vout->crop_current.left;
#endif
			params.mem_pp_adc.out_top = vout->crop_current.top;
			if (ipu_init_channel(vout->post_proc_ch, &params) != 0) {
				DPRINTK(KERN_ERR
					"Error initializing PP chan\n");
				return -EINVAL;
			}

			if (ipu_init_channel_buffer(vout->post_proc_ch,
						    IPU_INPUT_BUFFER,
						    params.mem_pp_adc.
						    in_pixel_fmt,
						    params.mem_pp_adc.in_width,
						    params.mem_pp_adc.in_height,
						    params.mem_pp_adc.in_width,
						    vout->rotate,
						    vout->
						    queue_buf_paddr[pp_in_buf
								    [0]],
						    vout->
						    queue_buf_paddr[pp_in_buf
								    [1]]) !=
			    0) {
				DPRINTK(KERN_ERR "Error initializing PP "
					"in buf\n");
				return -EINVAL;
			}
			if (ipu_init_channel_buffer(vout->post_proc_ch,
						    IPU_OUTPUT_BUFFER,
						    params.mem_pp_adc.
						    out_pixel_fmt, out_width,
						    out_height, out_width,
						    vout->rotate, NULL,
						    NULL) != 0) {
				DPRINTK(KERN_ERR "Error initializing PP "
					"output buffer\n");
				return -EINVAL;
			}

		} else {
			DPRINTK("Using ADC SYS2 channel\n");
			vout->display_ch = ADC_SYS2;
			vout->post_proc_ch = MEM_PP_MEM;
			memset(&params, 0, sizeof(params));
			params.adc_sys2.disp = vout->cur_disp_output;
			params.adc_sys2.ch_mode = WriteTemplateNonSeq;
#ifdef CONFIG_FB_MXC_EPSON_PANEL
			params.adc_sys2.out_left = 2 + vout->crop_current.left;
#else
			params.adc_sys2.out_left = 12 + vout->crop_current.left;
#endif
			params.adc_sys2.out_top = vout->crop_current.top;
			if (ipu_init_channel(ADC_SYS2, &params) < 0)
				return -EINVAL;

			if (ipu_init_channel_buffer(vout->display_ch,
						    IPU_INPUT_BUFFER,
						    SDC_FG_FB_FORMAT,
						    out_width, out_height,
						    out_width,
						    IPU_ROTATE_NONE,
						    vout->display_bufs[0],
						    vout->display_bufs[1]) !=
			    0) {
				DPRINTK(KERN_ERR "Error initializing SDC FG "
					"buffer\n");
				return -EINVAL;
			}
		}
	} else
#endif
	{			/* Use SDC */
		DPRINTK("Using SDC channel\n");
		vout->display_ch = MEM_SDC_FG;
		vout->post_proc_ch = MEM_PP_MEM;
		ipu_init_channel(MEM_SDC_FG, NULL);
		ipu_sdc_set_window_pos(MEM_SDC_FG, vout->crop_current.left,
				       vout->crop_current.top);
		if (ipu_init_channel_buffer(vout->display_ch, IPU_INPUT_BUFFER,
					    SDC_FG_FB_FORMAT,
					    out_width, out_height, out_width,
					    IPU_ROTATE_NONE,
					    vout->display_bufs[0],
					    vout->display_bufs[1]) != 0) {
			DPRINTK(KERN_ERR "Error initializing SDC FG buffer\n");
			return -EINVAL;
		}
	}

	/* Init PP */
	if (use_direct_adc == false) {
		if (vout->rotate >= IPU_ROTATE_90_RIGHT) {
			out_width = vout->crop_current.height;
			out_height = vout->crop_current.width;
		}
		memset(&params, 0, sizeof(params));
		params.mem_pp_mem.in_width = vout->v2f.fmt.pix.width;
		params.mem_pp_mem.in_height = vout->v2f.fmt.pix.height;
		params.mem_pp_mem.in_pixel_fmt = vout->v2f.fmt.pix.pixelformat;
		params.mem_pp_mem.out_width = out_width;
		params.mem_pp_mem.out_height = out_height;
		params.mem_pp_mem.out_pixel_fmt = SDC_FG_FB_FORMAT;
		if (ipu_init_channel(vout->post_proc_ch, &params) != 0) {
			DPRINTK(KERN_ERR "Error initializing PP channel\n");
			return -EINVAL;
		}

		if (ipu_init_channel_buffer(vout->post_proc_ch,
					    IPU_INPUT_BUFFER,
					    params.mem_pp_mem.in_pixel_fmt,
					    params.mem_pp_mem.in_width,
					    params.mem_pp_mem.in_height,
					    params.mem_pp_mem.in_width,
					    IPU_ROTATE_NONE,
					    vout->queue_buf_paddr[pp_in_buf[0]],
					    vout->
					    queue_buf_paddr[pp_in_buf[1]]) !=
		    0) {
			DPRINTK(KERN_ERR
				"Error initializing PP input buffer\n");
			return -EINVAL;
		}

		if (vout->rotate >= IPU_ROTATE_90_RIGHT) {
			if (vout->rot_pp_bufs[0]) {
				mxc_free_buffers(vout->rot_pp_bufs, 2);
			}
			if (mxc_allocate_buffers(vout->rot_pp_bufs, 2,
						 vout->sdc_fg_buf_size) < 0) {
				return -ENOBUFS;
			}

			if (ipu_init_channel_buffer(vout->post_proc_ch,
						    IPU_OUTPUT_BUFFER,
						    params.mem_pp_mem.
						    out_pixel_fmt, out_width,
						    out_height, out_width,
						    IPU_ROTATE_NONE,
						    vout->rot_pp_bufs[0],
						    vout->rot_pp_bufs[1]) !=
			    0) {
				DPRINTK(KERN_ERR "Error initializing PP "
					"output buffer\n");
				return -EINVAL;
			}

			if (ipu_init_channel(MEM_ROT_PP_MEM, NULL) != 0) {
				DPRINTK(KERN_ERR "Error initializing PP ROT "
					"channel\n");
				return -EINVAL;
			}

			if (ipu_init_channel_buffer(MEM_ROT_PP_MEM,
						    IPU_INPUT_BUFFER,
						    params.mem_pp_mem.
						    out_pixel_fmt, out_width,
						    out_height, out_width,
						    vout->rotate,
						    vout->rot_pp_bufs[0],
						    vout->rot_pp_bufs[1]) !=
			    0) {
				DPRINTK(KERN_ERR "Error initializing PP ROT "
					"input buffer\n");
				return -EINVAL;
			}

			/* swap width and height */
			out_width = vout->crop_current.width;
			out_height = vout->crop_current.height;

			if (ipu_init_channel_buffer(MEM_ROT_PP_MEM,
						    IPU_OUTPUT_BUFFER,
						    params.mem_pp_mem.
						    out_pixel_fmt, out_width,
						    out_height, out_width,
						    IPU_ROTATE_NONE,
						    vout->display_bufs[0],
						    vout->display_bufs[1]) !=
			    0) {
				DPRINTK(KERN_ERR "Error initializing PP "
					"output buffer\n");
				return -EINVAL;
			}

			if (ipu_link_channels(vout->post_proc_ch,
					      MEM_ROT_PP_MEM) < 0) {
				return -EINVAL;
			}
			ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 0);
			ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 1);

			ipu_enable_channel(MEM_ROT_PP_MEM);

			display_input_ch = MEM_ROT_PP_MEM;
		} else {
			if (ipu_init_channel_buffer(vout->post_proc_ch,
						    IPU_OUTPUT_BUFFER,
						    params.mem_pp_mem.
						    out_pixel_fmt, out_width,
						    out_height, out_width,
						    vout->rotate,
						    vout->display_bufs[0],
						    vout->display_bufs[1]) !=
			    0) {
				DPRINTK(KERN_ERR "Error initializing PP "
					"output buffer\n");
				return -EINVAL;
			}
		}
		if (ipu_link_channels(display_input_ch, vout->display_ch) < 0) {
			DPRINTK(KERN_ERR "Error linking ipu channels\n");
			return -EINVAL;
		}
	}

	vout->state = STATE_STREAM_PAUSED;

	ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 0);
	ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 1);

	if (use_direct_adc == false) {
		ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 0);
		ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 1);

		ipu_enable_channel(vout->post_proc_ch);
		ipu_enable_channel(vout->display_ch);
	} else {
		ipu_enable_channel(vout->post_proc_ch);
	}

	return 0;
}