Exemplo n.º 1
0
/*!
 * Post-processing driver open function. This function implements the Linux
 * file_operations.open() API function. 
 *
 * @param       inode           struct inode *
 *
 * @param       filp            struct file * 
 *
 * @return      This function returns 0 on success or negative error code on 
 *              error.
 */
static int mxc_pp_open(struct inode *inode, struct file *filp)
{
  int i;

  FUNC_START;

  if(open_count++ == 0) {
    memset(&pp_data, 0, sizeof(pp_data));
    for(i = 0; i < PP_MAX_BUFFER_CNT; i++) {
      pp_data.buf[i].index = -1;
    }
    init_waitqueue_head(&pp_data.pp_wait);
    init_MUTEX(&pp_data.busy_lock);

    pp_data.busy_flag = 1;

    ipu_request_irq(IPU_IRQ_PP_ROT_OUT_EOF, mxc_pp_irq_handler, 0, "mxc_ipu_pp", &pp_data);
    ipu_request_irq(IPU_IRQ_PP_OUT_EOF, mxc_pp_irq_handler, 0, "mxc_ipu_pp", &pp_data);

    ipu_disable_irq(IPU_IRQ_PP_ROT_OUT_EOF);
    ipu_disable_irq(IPU_IRQ_PP_OUT_EOF);
  }

  FUNC_END;
  return 0;
}
/*!
 * Function to initialize Asynchronous Display Controller. It also initilizes
 * the ADC System 1 channel. Configure ADC display 0 parallel interface for
 * the panel.
 *
 * @param       fbi     framebuffer information pointer
 */
static void mxcfb_init_panel(struct fb_info *fbi)
{
	int msb;
	int panel_stride;
	struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;

#ifdef CONFIG_FB_MXC_ASYNC_PANEL_IFC_16_BIT
	uint32_t pix_fmt = IPU_PIX_FMT_RGB666;
	ipu_adc_sig_cfg_t sig = { 0, 0, 0, 0, 0, 0, 0, 0,
		IPU_ADC_BURST_WCS,
		IPU_ADC_IFC_MODE_SYS80_TYPE2,
		16, 0, 0, IPU_ADC_SER_NO_RW
	};
	mxc_fbi->disp_num = DISP0;
#elif defined(CONFIG_FB_MXC_ASYNC_PANEL_IFC_8_BIT)
	uint32_t pix_fmt = IPU_PIX_FMT_RGB666;
	ipu_adc_sig_cfg_t sig = { 0, 0, 0, 0, 0, 0, 0, 0,
		IPU_ADC_BURST_WCS,
		IPU_ADC_IFC_MODE_SYS80_TYPE2,
		8, 0, 0, IPU_ADC_SER_NO_RW
	};
	mxc_fbi->disp_num = DISP0;
#endif

#ifdef PARTIAL_REFRESH
	if (ipu_request_irq(IPU_IRQ_ADC_SYS2_EOF, mxcfb_sys2_eof_irq_handler, 0,
			    MXCFB_NAME, fbi) != 0) {
		dev_err(fbi->device, "Error registering SYS2 irq handler.\n");
		return;
	}

	if (ipu_request_irq(IPU_IRQ_ADC_SYS1_EOF, mxcfb_sys1_eof_irq_handler, 0,
			    MXCFB_NAME, fbi) != 0) {
		dev_err(fbi->device, "Error registering SYS1 irq handler.\n");
		return;
	}
	ipu_disable_irq(IPU_IRQ_ADC_SYS1_EOF);
	ipu_disable_irq(IPU_IRQ_ADC_SYS2_EOF);
#endif
	// Init DI interface
	msb = fls(MXCFB_SCREEN_WIDTH);
	if (!(MXCFB_SCREEN_WIDTH & ((1UL << msb) - 1)))
		msb--;		// Already aligned to power 2
	panel_stride = 1UL << msb;
	ipu_adc_init_panel(mxc_fbi->disp_num,
			   MXCFB_SCREEN_WIDTH + MXCFB_SCREEN_LEFT_OFFSET,
			   MXCFB_SCREEN_HEIGHT,
			   pix_fmt, panel_stride, sig, XY, 0, VsyncInternal);

	ipu_adc_init_ifc_timing(mxc_fbi->disp_num, true,
				190, 17, 104, 190, 5000000);
	ipu_adc_init_ifc_timing(mxc_fbi->disp_num, false, 90, 10, 60, 0, 0);

	_init_panel(mxc_fbi->disp_num);

	init_channel_template(mxc_fbi->disp_num);
}
Exemplo n.º 3
0
/*!
 * V4L2 interface - open function
 *
 * @param inode        structure inode *
 *
 * @param file         structure file *
 *
 * @return  status    0 success, ENODEV invalid device instance,
 *                    ENODEV timeout, ERESTARTSYS interrupted by user
 */
static int mxc_v4l2out_open(struct inode *inode, struct file *file)
{
	struct video_device *dev = video_devdata(file);
	vout_data *vout = video_get_drvdata(dev);
	int err;

	FUNC_START;

	if (!vout) {
		DPRINTK("Internal error, vout_data not found!\n");
		return -ENODEV;
	}

	down(&vout->busy_lock);

	err = -EINTR;
	if (signal_pending(current))
		goto oops;

	if (vout->open_count++ == 0) {
		ipu_request_irq(IPU_IRQ_PP_IN_EOF,
				mxc_v4l2out_pp_in_irq_handler,
				0, dev->name, vout);

		init_waitqueue_head(&vout->v4l_bufq);

		init_timer(&vout->output_timer);
		vout->output_timer.function = mxc_v4l2out_timer_handler;
		vout->output_timer.data = (unsigned long)vout;

		vout->state = STATE_STREAM_OFF;
		g_irq_cnt = g_buf_output_cnt = g_buf_q_cnt = g_buf_dq_cnt = 0;

	}

	file->private_data = dev;

	up(&vout->busy_lock);

	FUNC_END;
	return 0;

      oops:
	up(&vout->busy_lock);
	return err;
}
Exemplo n.º 4
0
static int mxc_ipu_ioctl(struct inode *inode, struct file *file,
			 unsigned int cmd, unsigned long arg)
{
	int ret = 0;

	switch (cmd) {

	case IPU_INIT_CHANNEL:
		{
			ipu_channel_parm parm;
			if (copy_from_user
			    (&parm, (ipu_channel_parm *) arg,
			     sizeof(ipu_channel_parm))) {
				return -EFAULT;
			}
			if (!parm.flag) {
				ret =
				    ipu_init_channel(parm.channel,
						     &parm.params);
			} else {
				ret = ipu_init_channel(parm.channel, NULL);
			}
		}
		break;

	case IPU_UNINIT_CHANNEL:
		{
			ipu_channel_t ch;
			int __user *argp = (void __user *)arg;
			if (get_user(ch, argp))
				return -EFAULT;
			ipu_uninit_channel(ch);
		}
		break;

	case IPU_INIT_CHANNEL_BUFFER:
		{
			ipu_channel_buf_parm parm;
			if (copy_from_user
			    (&parm, (ipu_channel_buf_parm *) arg,
			     sizeof(ipu_channel_buf_parm))) {
				return -EFAULT;
			}
			ret =
			    ipu_init_channel_buffer(parm.channel, parm.type,
						    parm.pixel_fmt,
						    parm.width, parm.height,
						    parm.stride,
						    parm.rot_mode,
						    parm.phyaddr_0,
						    parm.phyaddr_1,
						    parm.u_offset,
						    parm.v_offset);

		}
		break;

	case IPU_UPDATE_CHANNEL_BUFFER:
		{
			ipu_channel_buf_parm parm;
			if (copy_from_user
			    (&parm, (ipu_channel_buf_parm *) arg,
			     sizeof(ipu_channel_buf_parm))) {
				return -EFAULT;
			}
			if ((parm.phyaddr_0 != (dma_addr_t) NULL)
			    && (parm.phyaddr_1 == (dma_addr_t) NULL)) {
				ret =
				    ipu_update_channel_buffer(parm.channel,
							      parm.type,
							      parm.bufNum,
							      parm.phyaddr_0);
			} else if ((parm.phyaddr_0 == (dma_addr_t) NULL)
				   && (parm.phyaddr_1 != (dma_addr_t) NULL)) {
				ret =
				    ipu_update_channel_buffer(parm.channel,
							      parm.type,
							      parm.bufNum,
							      parm.phyaddr_1);
			} else {
				ret = -1;
			}

		}
		break;
	case IPU_SELECT_CHANNEL_BUFFER:
		{
			ipu_channel_buf_parm parm;
			if (copy_from_user
			    (&parm, (ipu_channel_buf_parm *) arg,
			     sizeof(ipu_channel_buf_parm))) {
				return -EFAULT;
			}
			ret =
			    ipu_select_buffer(parm.channel, parm.type,
					      parm.bufNum);

		}
		break;
	case IPU_LINK_CHANNELS:
		{
			ipu_channel_link link;
			if (copy_from_user
			    (&link, (ipu_channel_link *) arg,
			     sizeof(ipu_channel_link))) {
				return -EFAULT;
			}
			ret = ipu_link_channels(link.src_ch, link.dest_ch);

		}
		break;
	case IPU_UNLINK_CHANNELS:
		{
			ipu_channel_link link;
			if (copy_from_user
			    (&link, (ipu_channel_link *) arg,
			     sizeof(ipu_channel_link))) {
				return -EFAULT;
			}
			ret = ipu_unlink_channels(link.src_ch, link.dest_ch);

		}
		break;
	case IPU_ENABLE_CHANNEL:
		{
			ipu_channel_t ch;
			int __user *argp = (void __user *)arg;
			if (get_user(ch, argp))
				return -EFAULT;
			ipu_enable_channel(ch);
		}
		break;
	case IPU_DISABLE_CHANNEL:
		{
			ipu_channel_info info;
			if (copy_from_user
			    (&info, (ipu_channel_info *) arg,
			     sizeof(ipu_channel_info))) {
				return -EFAULT;
			}
			ret = ipu_disable_channel(info.channel, info.stop);
		}
		break;
	case IPU_ENABLE_IRQ:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ipu_enable_irq(irq);
		}
		break;
	case IPU_DISABLE_IRQ:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ipu_disable_irq(irq);
		}
		break;
	case IPU_CLEAR_IRQ:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ipu_clear_irq(irq);
		}
		break;
	case IPU_FREE_IRQ:
		{
			ipu_irq_info info;
			if (copy_from_user
			    (&info, (ipu_irq_info *) arg,
			     sizeof(ipu_irq_info))) {
				return -EFAULT;
			}
			ipu_free_irq(info.irq, info.dev_id);
		}
		break;
	case IPU_REQUEST_IRQ_STATUS:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ret = ipu_get_irq_status(irq);
		}
		break;
	case IPU_SDC_INIT_PANEL:
		{
			ipu_sdc_panel_info sinfo;
			if (copy_from_user
			    (&sinfo, (ipu_sdc_panel_info *) arg,
			     sizeof(ipu_sdc_panel_info))) {
				return -EFAULT;
			}
			ret =
			    ipu_sdc_init_panel(sinfo.panel, sinfo.pixel_clk,
					       sinfo.width, sinfo.height,
					       sinfo.pixel_fmt,
					       sinfo.hStartWidth,
					       sinfo.hSyncWidth,
					       sinfo.hEndWidth,
					       sinfo.vStartWidth,
					       sinfo.vSyncWidth,
					       sinfo.vEndWidth, sinfo.signal);
		}
		break;
	case IPU_SDC_SET_WIN_POS:
		{
			ipu_sdc_window_pos pos;
			if (copy_from_user
			    (&pos, (ipu_sdc_window_pos *) arg,
			     sizeof(ipu_sdc_window_pos))) {
				return -EFAULT;
			}
			ret =
			    ipu_sdc_set_window_pos(pos.channel, pos.x_pos,
						   pos.y_pos);

		}
		break;
	case IPU_SDC_SET_GLOBAL_ALPHA:
		{
			ipu_sdc_global_alpha g;
			if (copy_from_user
			    (&g, (ipu_sdc_global_alpha *) arg,
			     sizeof(ipu_sdc_global_alpha))) {
				return -EFAULT;
			}
			ret = ipu_sdc_set_global_alpha(g.enable, g.alpha);
		}
		break;
	case IPU_SDC_SET_COLOR_KEY:
		{
			ipu_sdc_color_key c;
			if (copy_from_user
			    (&c, (ipu_sdc_color_key *) arg,
			     sizeof(ipu_sdc_color_key))) {
				return -EFAULT;
			}
			ret =
			    ipu_sdc_set_color_key(c.channel, c.enable,
						  c.colorKey);
		}
		break;
	case IPU_SDC_SET_BRIGHTNESS:
		{
			uint8_t b;
			int __user *argp = (void __user *)arg;
			if (get_user(b, argp))
				return -EFAULT;
			ret = ipu_sdc_set_brightness(b);

		}
		break;
	case IPU_REGISTER_GENERIC_ISR:
		{
			ipu_event_info info;
			if (copy_from_user
			    (&info, (ipu_event_info *) arg,
			     sizeof(ipu_event_info))) {
				return -EFAULT;
			}
			ret =
			    ipu_request_irq(info.irq, mxc_ipu_generic_handler,
					    0, "video_sink", info.dev);
		}
		break;
	case IPU_GET_EVENT:
		/* User will have to allocate event_type structure and pass the pointer in arg */
		{
			event_type ev;
			int r = -1;
			r = get_events(&ev);
			if (r == -1) {
				wait_event_interruptible(waitq,
							 (pending_events != 0));
				r = get_events(&ev);
			}
			ret = -1;
			if (r == 0) {
				if (!copy_to_user((event_type *) arg, &ev,
						  sizeof(event_type))) {
					ret = 0;
				}
			}
		}
		break;
	case IPU_ADC_WRITE_TEMPLATE:
		{
			ipu_adc_template temp;
			if (copy_from_user
			    (&temp, (ipu_adc_template *) arg, sizeof(temp))) {
				return -EFAULT;
			}
			ret =
			    ipu_adc_write_template(temp.disp, temp.pCmd,
						   temp.write);
		}
		break;
	case IPU_ADC_UPDATE:
		{
			ipu_adc_update update;
			if (copy_from_user
			    (&update, (ipu_adc_update *) arg, sizeof(update))) {
				return -EFAULT;
			}
			ret =
			    ipu_adc_set_update_mode(update.channel, update.mode,
						    update.refresh_rate,
						    update.addr, update.size);
		}
		break;
	case IPU_ADC_SNOOP:
		{
			ipu_adc_snoop snoop;
			if (copy_from_user
			    (&snoop, (ipu_adc_snoop *) arg, sizeof(snoop))) {
				return -EFAULT;
			}
			ret =
			    ipu_adc_get_snooping_status(snoop.statl,
							snoop.stath);
		}
		break;
	case IPU_ADC_CMD:
		{
			ipu_adc_cmd cmd;
			if (copy_from_user
			    (&cmd, (ipu_adc_cmd *) arg, sizeof(cmd))) {
				return -EFAULT;
			}
			ret =
			    ipu_adc_write_cmd(cmd.disp, cmd.type, cmd.cmd,
					      cmd.params, cmd.numParams);
		}
		break;
	case IPU_ADC_INIT_PANEL:
		{
			ipu_adc_panel panel;
			if (copy_from_user
			    (&panel, (ipu_adc_panel *) arg, sizeof(panel))) {
				return -EFAULT;
			}
			ret =
			    ipu_adc_init_panel(panel.disp, panel.width,
					       panel.height, panel.pixel_fmt,
					       panel.stride, panel.signal,
					       panel.addr, panel.vsync_width,
					       panel.mode);
		}
		break;
	case IPU_ADC_IFC_TIMING:
		{
			ipu_adc_ifc_timing t;
			if (copy_from_user
			    (&t, (ipu_adc_ifc_timing *) arg, sizeof(t))) {
				return -EFAULT;
			}
			ret =
			    ipu_adc_init_ifc_timing(t.disp, t.read,
						    t.cycle_time, t.up_time,
						    t.down_time,
						    t.read_latch_time,
						    t.pixel_clk);
		}
		break;
	case IPU_CSI_INIT_INTERFACE:
		{
			ipu_csi_interface c;
			if (copy_from_user
			    (&c, (ipu_csi_interface *) arg, sizeof(c)))
				return -EFAULT;
			ret =
			    ipu_csi_init_interface(c.width, c.height,
						   c.pixel_fmt, c.signal);
		}
		break;
	case IPU_CSI_ENABLE_MCLK:
		{
			ipu_csi_mclk m;
			if (copy_from_user(&m, (ipu_csi_mclk *) arg, sizeof(m)))
				return -EFAULT;
			ret = ipu_csi_enable_mclk(m.src, m.flag, m.wait);
		}
		break;
	case IPU_CSI_READ_MCLK_FLAG:
		{
			ret = ipu_csi_read_mclk_flag();
		}
		break;
	case IPU_CSI_FLASH_STROBE:
		{
			bool strobe;
			int __user *argp = (void __user *)arg;
			if (get_user(strobe, argp))
				return -EFAULT;
			ipu_csi_flash_strobe(strobe);
		}
		break;
	case IPU_CSI_GET_WIN_SIZE:
		{
			ipu_csi_window_size w;
			ipu_csi_get_window_size(&w.width, &w.height);
			if (copy_to_user
			    ((ipu_csi_window_size *) arg, &w, sizeof(w)))
				return -EFAULT;
		}
		break;
	case IPU_CSI_SET_WIN_SIZE:
		{
			ipu_csi_window_size w;
			if (copy_from_user
			    (&w, (ipu_csi_window_size *) arg, sizeof(w)))
				return -EFAULT;
			ipu_csi_set_window_size(w.width, w.height);
		}
		break;
	case IPU_CSI_SET_WINDOW:
		{
			ipu_csi_window p;
			if (copy_from_user
			    (&p, (ipu_csi_window *) arg, sizeof(p)))
				return -EFAULT;
			ipu_csi_set_window_pos(p.left, p.top);
		}
		break;
	case IPU_PF_SET_PAUSE_ROW:
		{
			uint32_t p;
			int __user *argp = (void __user *)arg;
			if (get_user(p, argp))
				return -EFAULT;
			ret = ipu_pf_set_pause_row(p);
		}
		break;
	default:
		break;

	}
	return ret;
}
Exemplo n.º 5
0
static long mxc_ipu_ioctl(struct file *file,
		unsigned int cmd, unsigned long arg)
{
	int ret = 0;

	switch (cmd) {
	case IPU_INIT_CHANNEL:
		{
			ipu_channel_parm parm;

			if (copy_from_user
					(&parm, (ipu_channel_parm *) arg,
					 sizeof(ipu_channel_parm)))
				return -EFAULT;

			if (!parm.flag) {
				ret =
					ipu_init_channel(parm.channel,
							&parm.params);
			} else {
				ret = ipu_init_channel(parm.channel, NULL);
			}
		}
		break;
	case IPU_UNINIT_CHANNEL:
		{
		ipu_channel_t ch;
		int __user *argp = (void __user *)arg;
		if (get_user(ch, argp))
				return -EFAULT;
			ipu_uninit_channel(ch);
		}
		break;
	case IPU_INIT_CHANNEL_BUFFER:
		{
			ipu_channel_buf_parm parm;
			if (copy_from_user
				(&parm, (ipu_channel_buf_parm *) arg,
				sizeof(ipu_channel_buf_parm)))
				return -EFAULT;

			ret =
				ipu_init_channel_buffer(
						parm.channel, parm.type,
						parm.pixel_fmt,
						parm.width, parm.height,
						parm.stride,
						parm.rot_mode,
						parm.phyaddr_0,
						parm.phyaddr_1,
						parm.u_offset,
						parm.v_offset);

		}
		break;
	case IPU_UPDATE_CHANNEL_BUFFER:
		{
			ipu_channel_buf_parm parm;
			if (copy_from_user
				(&parm, (ipu_channel_buf_parm *) arg,
				sizeof(ipu_channel_buf_parm)))
				return -EFAULT;

			if ((parm.phyaddr_0 != (dma_addr_t) NULL)
				&& (parm.phyaddr_1 == (dma_addr_t) NULL)) {
				ret =
					ipu_update_channel_buffer(
							parm.channel,
							parm.type,
							parm.bufNum,
							parm.phyaddr_0);
			} else if ((parm.phyaddr_0 == (dma_addr_t) NULL)
				&& (parm.phyaddr_1 != (dma_addr_t) NULL)) {
				ret =
					ipu_update_channel_buffer(
							parm.channel,
							parm.type,
							parm.bufNum,
							parm.phyaddr_1);
			} else {
				ret = -1;
			}

		}
		break;
	case IPU_SELECT_CHANNEL_BUFFER:
		{
			ipu_channel_buf_parm parm;
			if (copy_from_user
				(&parm, (ipu_channel_buf_parm *) arg,
				sizeof(ipu_channel_buf_parm)))
				return -EFAULT;

			ret =
				ipu_select_buffer(parm.channel,
					parm.type, parm.bufNum);

		}
		break;
	case IPU_SELECT_MULTI_VDI_BUFFER:
		{
			uint32_t parm;
			if (copy_from_user
				(&parm, (uint32_t *) arg,
				sizeof(uint32_t)))
				return -EFAULT;

			ret = ipu_select_multi_vdi_buffer(parm);
		}
		break;
	case IPU_LINK_CHANNELS:
		{
			ipu_channel_link link;
			if (copy_from_user
				(&link, (ipu_channel_link *) arg,
				sizeof(ipu_channel_link)))
				return -EFAULT;

			ret = ipu_link_channels(link.src_ch,
				link.dest_ch);

		}
		break;
	case IPU_UNLINK_CHANNELS:
		{
			ipu_channel_link link;
			if (copy_from_user
				(&link, (ipu_channel_link *) arg,
				sizeof(ipu_channel_link)))
				return -EFAULT;

			ret = ipu_unlink_channels(link.src_ch,
				link.dest_ch);

		}
		break;
	case IPU_ENABLE_CHANNEL:
		{
			ipu_channel_t ch;
			int __user *argp = (void __user *)arg;
			if (get_user(ch, argp))
				return -EFAULT;
			ipu_enable_channel(ch);
		}
		break;
	case IPU_DISABLE_CHANNEL:
		{
			ipu_channel_info info;
			if (copy_from_user
				(&info, (ipu_channel_info *) arg,
				 sizeof(ipu_channel_info)))
				return -EFAULT;

			ret = ipu_disable_channel(info.channel,
				info.stop);
		}
		break;
	case IPU_ENABLE_IRQ:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ipu_enable_irq(irq);
		}
		break;
	case IPU_DISABLE_IRQ:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ipu_disable_irq(irq);
		}
		break;
	case IPU_CLEAR_IRQ:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ipu_clear_irq(irq);
		}
		break;
	case IPU_FREE_IRQ:
		{
			ipu_irq_info info;

			if (copy_from_user
					(&info, (ipu_irq_info *) arg,
					 sizeof(ipu_irq_info)))
				return -EFAULT;

			ipu_free_irq(info.irq, info.dev_id);
			irq_info[info.irq].irq_pending = 0;
		}
		break;
	case IPU_REQUEST_IRQ_STATUS:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ret = ipu_get_irq_status(irq);
		}
		break;
	case IPU_REGISTER_GENERIC_ISR:
		{
			ipu_event_info info;
			if (copy_from_user
					(&info, (ipu_event_info *) arg,
					 sizeof(ipu_event_info)))
				return -EFAULT;

			ret =
				ipu_request_irq(info.irq,
					mxc_ipu_generic_handler,
					0, "video_sink", info.dev);
			if (ret == 0)
				init_waitqueue_head(&(irq_info[info.irq].waitq));
		}
		break;
	case IPU_GET_EVENT:
		/* User will have to allocate event_type
		structure and pass the pointer in arg */
		{
			ipu_event_info info;
			int r = -1;

			if (copy_from_user
					(&info, (ipu_event_info *) arg,
					 sizeof(ipu_event_info)))
				return -EFAULT;

			r = get_events(&info);
			if (r == -1) {
				if ((file->f_flags & O_NONBLOCK) &&
					(irq_info[info.irq].irq_pending == 0))
					return -EAGAIN;
				wait_event_interruptible_timeout(irq_info[info.irq].waitq,
						(irq_info[info.irq].irq_pending != 0), 2 * HZ);
				r = get_events(&info);
			}
			ret = -1;
			if (r == 0) {
				if (!copy_to_user((ipu_event_info *) arg,
					&info, sizeof(ipu_event_info)))
					ret = 0;
			}
		}
		break;
	case IPU_ALOC_MEM:
		{
			ipu_mem_info info;
			if (copy_from_user
					(&info, (ipu_mem_info *) arg,
					 sizeof(ipu_mem_info)))
				return -EFAULT;

			info.vaddr = dma_alloc_coherent(0,
					PAGE_ALIGN(info.size),
					&info.paddr,
					GFP_DMA | GFP_KERNEL);
			if (info.vaddr == 0) {
				printk(KERN_ERR "dma alloc failed!\n");
				return -ENOBUFS;
			}
			if (copy_to_user((ipu_mem_info *) arg, &info,
					sizeof(ipu_mem_info)) > 0)
				return -EFAULT;
		}
		break;
	case IPU_FREE_MEM:
		{
			ipu_mem_info info;
			if (copy_from_user
					(&info, (ipu_mem_info *) arg,
					 sizeof(ipu_mem_info)))
				return -EFAULT;

			if (info.vaddr)
				dma_free_coherent(0, PAGE_ALIGN(info.size),
					info.vaddr, info.paddr);
			else
				return -EFAULT;
		}
		break;
	case IPU_IS_CHAN_BUSY:
		{
			ipu_channel_t chan;
			if (copy_from_user
					(&chan, (ipu_channel_t *)arg,
					 sizeof(ipu_channel_t)))
				return -EFAULT;

			if (ipu_is_channel_busy(chan))
				ret = 1;
			else
				ret = 0;
		}
		break;
	case IPU_CALC_STRIPES_SIZE:
		{
			ipu_stripe_parm stripe_parm;

			if (copy_from_user (&stripe_parm, (ipu_stripe_parm *)arg,
					 sizeof(ipu_stripe_parm)))
				return -EFAULT;
			ipu_calc_stripes_sizes(stripe_parm.input_width,
						stripe_parm.output_width,
						stripe_parm.maximal_stripe_width,
						stripe_parm.cirr,
						stripe_parm.equal_stripes,
						stripe_parm.input_pixelformat,
						stripe_parm.output_pixelformat,
						&stripe_parm.left,
						&stripe_parm.right);
			if (copy_to_user((ipu_stripe_parm *) arg, &stripe_parm,
					sizeof(ipu_stripe_parm)) > 0)
				return -EFAULT;
		}
		break;
	case IPU_UPDATE_BUF_OFFSET:
		{
			ipu_buf_offset_parm offset_parm;

			if (copy_from_user (&offset_parm, (ipu_buf_offset_parm *)arg,
					 sizeof(ipu_buf_offset_parm)))
				return -EFAULT;
			ret = ipu_update_channel_offset(offset_parm.channel,
							offset_parm.type,
							offset_parm.pixel_fmt,
							offset_parm.width,
							offset_parm.height,
							offset_parm.stride,
							offset_parm.u_offset,
							offset_parm.v_offset,
							offset_parm.vertical_offset,
							offset_parm.horizontal_offset);
		}
		break;
	case IPU_CSC_UPDATE:
		{
			int param[5][3];
			ipu_csc_update csc;
			if (copy_from_user(&csc, (void *) arg,
					   sizeof(ipu_csc_update)))
				return -EFAULT;
			if (copy_from_user(&param[0][0], (void *) csc.param,
					   sizeof(param)))
				return -EFAULT;
			ipu_set_csc_coefficients(csc.channel, param);
		}
		break;
	default:
		break;
	}
	return ret;
}
Exemplo n.º 6
0
/*!
 * Function to initialize Asynchronous Display Controller. It also initilizes
 * the ADC System 1 channel. Configure ADC display 0 parallel interface for
 * the panel.
 *
 * @param       fbi     framebuffer information pointer
 */
static void mxcfb_init_panel(struct fb_info *fbi)
{
	int msb;
	int panel_stride;
	ipu_channel_params_t params;
	struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;

#ifdef CONFIG_FB_MXC_ASYNC_PANEL_IFC_16_BIT
	uint32_t pix_fmt = IPU_PIX_FMT_RGB565;
	ipu_adc_sig_cfg_t sig = { 0, 0, 0, 0, 0, 0, 0, 0,
		IPU_ADC_BURST_WCS,
		IPU_ADC_IFC_MODE_SYS80_TYPE2,
		16, 0, 0, IPU_ADC_SER_NO_RW
	};
	mxc_fbi->disp_num = DISP0;
#elif defined(CONFIG_FB_MXC_ASYNC_PANEL_IFC_8_BIT)
	uint32_t pix_fmt = IPU_PIX_FMT_RGB666;
	ipu_adc_sig_cfg_t sig = { 0, 0, 0, 0, 0, 0, 0, 0,
		IPU_ADC_BURST_WCS,
		IPU_ADC_IFC_MODE_SYS80_TYPE2,
		8, 0, 0, IPU_ADC_SER_NO_RW
	};
	mxc_fbi->disp_num = DISP0;
#else
	uint32_t pix_fmt = IPU_PIX_FMT_RGB565;
	ipu_adc_sig_cfg_t sig = { 0, 1, 0, 0, 0, 0, 0, 0,
		IPU_ADC_BURST_SERIAL,
		IPU_ADC_IFC_MODE_5WIRE_SERIAL_CLK,
		16, 0, 0, IPU_ADC_SER_NO_RW
	};
	fbi->disp_num = DISP1;
#endif

#ifdef PARTIAL_REFRESH
	if (ipu_request_irq(IPU_IRQ_ADC_SYS2_EOF, mxcfb_sys2_eof_irq_handler, 0,
			    MXCFB_NAME, fbi) != 0) {
		dev_err(fbi->device, "Error registering SYS2 irq handler.\n");
		return;
	}

	if (ipu_request_irq(IPU_IRQ_ADC_SYS1_EOF, mxcfb_sys1_eof_irq_handler, 0,
			    MXCFB_NAME, fbi) != 0) {
		dev_err(fbi->device, "Error registering SYS1 irq handler.\n");
		return;
	}
	ipu_disable_irq(IPU_IRQ_ADC_SYS1_EOF);
	ipu_disable_irq(IPU_IRQ_ADC_SYS2_EOF);
#endif
	/* Init DI interface */
	msb = fls(MXCFB_SCREEN_WIDTH);
	if (!(MXCFB_SCREEN_WIDTH & ((1UL << msb) - 1)))
		msb--;	/* Already aligned to power 2 */
	panel_stride = 1UL << msb;
	ipu_adc_init_panel(mxc_fbi->disp_num,
			   MXCFB_SCREEN_WIDTH + MXCFB_SCREEN_LEFT_OFFSET,
			   MXCFB_SCREEN_HEIGHT,
			   pix_fmt, panel_stride, sig, XY, 0, VsyncInternal);

	ipu_adc_init_ifc_timing(mxc_fbi->disp_num, true,
				190, 17, 104, 190, 5000000);
	ipu_adc_init_ifc_timing(mxc_fbi->disp_num, false, 123, 17, 68, 0, 0);

	/* Needed to turn on ADC clock for panel init */
	memset(&params, 0, sizeof(params));
	params.adc_sys1.disp = mxc_fbi->disp_num;
	params.adc_sys1.ch_mode = WriteTemplateNonSeq;
	params.adc_sys1.out_left = MXCFB_SCREEN_LEFT_OFFSET;
	params.adc_sys1.out_top = MXCFB_SCREEN_TOP_OFFSET;
	ipu_init_channel(ADC_SYS1, &params);

	_init_panel(mxc_fbi->disp_num);
	init_channel_template(mxc_fbi->disp_num);
}
}

/*!
 * Enable encoder task
 * @param private       struct cam_data * mxc capture instance
 *
 * @return  status
 */
static int csi_enc_enabling_tasks(void *private)
{
	cam_data *cam = (cam_data *) private;
	int err = 0;
	CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");

	ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF);
	err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF,
			      csi_enc_callback, 0, "Mxc Camera", cam);
	if (err != 0) {
		printk(KERN_ERR "Error registering CSI0_OUT_EOF irq\n");
		return err;
	}

	INIT_WORK(&cam->csi_work_struct, csi_buf_work_func);

	err = csi_enc_setup(cam);
	if (err != 0) {
		printk(KERN_ERR "csi_enc_setup %d\n", err);
		goto out1;
	}

	return err;
out1:
static int mxc_ipu_ioctl(struct inode *inode, struct file *file,
		unsigned int cmd, unsigned long arg)
{
	int ret = 0;

	switch (cmd) {
	case IPU_INIT_CHANNEL:
		{
			ipu_channel_parm parm;

			if (copy_from_user
					(&parm, (ipu_channel_parm *) arg,
					 sizeof(ipu_channel_parm)))
				return -EFAULT;

			if (!parm.flag) {
				ret =
					ipu_init_channel(parm.channel,
							&parm.params);
			} else {
				ret = ipu_init_channel(parm.channel, NULL);
			}
		}
		break;
	case IPU_UNINIT_CHANNEL:
		{
		ipu_channel_t ch;
		int __user *argp = (void __user *)arg;
		if (get_user(ch, argp))
				return -EFAULT;
			ipu_uninit_channel(ch);
		}
		break;
	case IPU_INIT_CHANNEL_BUFFER:
		{
			ipu_channel_buf_parm parm;
			if (copy_from_user
				(&parm, (ipu_channel_buf_parm *) arg,
				sizeof(ipu_channel_buf_parm)))
				return -EFAULT;

			ret =
				ipu_init_channel_buffer(
						parm.channel, parm.type,
						parm.pixel_fmt,
						parm.width, parm.height,
						parm.stride,
						parm.rot_mode,
						parm.phyaddr_0,
						parm.phyaddr_1,
						parm.u_offset,
						parm.v_offset);

		}
		break;
	case IPU_UPDATE_CHANNEL_BUFFER:
		{
			ipu_channel_buf_parm parm;
			if (copy_from_user
				(&parm, (ipu_channel_buf_parm *) arg,
				sizeof(ipu_channel_buf_parm)))
				return -EFAULT;

			if ((parm.phyaddr_0 != (dma_addr_t) NULL)
				&& (parm.phyaddr_1 == (dma_addr_t) NULL)) {
				ret =
					ipu_update_channel_buffer(
							parm.channel,
							parm.type,
							parm.bufNum,
							parm.phyaddr_0);
			} else if ((parm.phyaddr_0 == (dma_addr_t) NULL)
				&& (parm.phyaddr_1 != (dma_addr_t) NULL)) {
				ret =
					ipu_update_channel_buffer(
							parm.channel,
							parm.type,
							parm.bufNum,
							parm.phyaddr_1);
			} else {
				ret = -1;
			}

		}
		break;
	case IPU_SELECT_CHANNEL_BUFFER:
		{
			ipu_channel_buf_parm parm;
			if (copy_from_user
				(&parm, (ipu_channel_buf_parm *) arg,
				sizeof(ipu_channel_buf_parm)))
				return -EFAULT;

			ret =
				ipu_select_buffer(parm.channel,
					parm.type, parm.bufNum);

		}
		break;
	case IPU_LINK_CHANNELS:
		{
			ipu_channel_link link;
			if (copy_from_user
				(&link, (ipu_channel_link *) arg,
				sizeof(ipu_channel_link)))
				return -EFAULT;

			ret = ipu_link_channels(link.src_ch,
				link.dest_ch);

		}
		break;
	case IPU_UNLINK_CHANNELS:
		{
			ipu_channel_link link;
			if (copy_from_user
				(&link, (ipu_channel_link *) arg,
				sizeof(ipu_channel_link)))
				return -EFAULT;

			ret = ipu_unlink_channels(link.src_ch,
				link.dest_ch);

		}
		break;
	case IPU_ENABLE_CHANNEL:
		{
			ipu_channel_t ch;
			int __user *argp = (void __user *)arg;
			if (get_user(ch, argp))
				return -EFAULT;
			ipu_enable_channel(ch);
		}
		break;
	case IPU_DISABLE_CHANNEL:
		{
			ipu_channel_info info;
			if (copy_from_user
				(&info, (ipu_channel_info *) arg,
				 sizeof(ipu_channel_info)))
				return -EFAULT;

			ret = ipu_disable_channel(info.channel,
				info.stop);
		}
		break;
	case IPU_ENABLE_IRQ:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ipu_enable_irq(irq);
		}
		break;
	case IPU_DISABLE_IRQ:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ipu_disable_irq(irq);
		}
		break;
	case IPU_CLEAR_IRQ:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ipu_clear_irq(irq);
		}
		break;
	case IPU_FREE_IRQ:
		{
			ipu_irq_info info;
			int i;

			if (copy_from_user
					(&info, (ipu_irq_info *) arg,
					 sizeof(ipu_irq_info)))
				return -EFAULT;

			ipu_free_irq(info.irq, info.dev_id);
			for (i = 0; i < MAX_Q_SIZE; i++) {
				if (events[i].irq == info.irq)
					events[i].irq = 0;
			}
		}
		break;
	case IPU_REQUEST_IRQ_STATUS:
		{
			uint32_t irq;
			int __user *argp = (void __user *)arg;
			if (get_user(irq, argp))
				return -EFAULT;
			ret = ipu_get_irq_status(irq);
		}
		break;
	case IPU_REGISTER_GENERIC_ISR:
		{
			ipu_event_info info;
			if (copy_from_user
					(&info, (ipu_event_info *) arg,
					 sizeof(ipu_event_info)))
				return -EFAULT;

			ret =
				ipu_request_irq(info.irq,
					mxc_ipu_generic_handler,
					0, "video_sink", info.dev);
		}
		break;
	case IPU_GET_EVENT:
		/* User will have to allocate event_type
		structure and pass the pointer in arg */
		{
			ipu_event_info info;
			int r = -1;

			if (copy_from_user
					(&info, (ipu_event_info *) arg,
					 sizeof(ipu_event_info)))
				return -EFAULT;

			r = get_events(&info);
			if (r == -1) {
				wait_event_interruptible_timeout(waitq,
						(pending_events != 0), HZ/10);
				r = get_events(&info);
			}
			ret = -1;
			if (r == 0) {
				if (!copy_to_user((ipu_event_info *) arg,
					&info, sizeof(ipu_event_info)))
					ret = 0;
			}
		}
		break;
	case IPU_ALOC_MEM:
		{
			ipu_mem_info info;
			if (copy_from_user
					(&info, (ipu_mem_info *) arg,
					 sizeof(ipu_mem_info)))
				return -EFAULT;

			info.vaddr = dma_alloc_coherent(0,
					PAGE_ALIGN(info.size),
					&info.paddr,
					GFP_DMA | GFP_KERNEL);
			if (info.vaddr == 0) {
				printk(KERN_ERR "dma alloc failed!\n");
				return -ENOBUFS;
			}
			if (copy_to_user((ipu_mem_info *) arg, &info,
					sizeof(ipu_mem_info)) > 0)
				return -EFAULT;
		}
		break;
	case IPU_FREE_MEM:
		{
			ipu_mem_info info;
			if (copy_from_user
					(&info, (ipu_mem_info *) arg,
					 sizeof(ipu_mem_info)))
				return -EFAULT;

			if (info.vaddr)
				dma_free_coherent(0, PAGE_ALIGN(info.size),
					info.vaddr, info.paddr);
			else
				return -EFAULT;
		}
		break;
	case IPU_IS_CHAN_BUSY:
		{
			ipu_channel_t chan;
			if (copy_from_user
					(&chan, (ipu_channel_t *)arg,
					 sizeof(ipu_channel_t)))
				return -EFAULT;

			if (ipu_is_channel_busy(chan))
				ret = 1;
			else
				ret = 0;
		}
		break;
	default:
		break;
	}
	return ret;
}