Exemple #1
0
static irqreturn_t mxcfb_sys1_eof_irq_handler(int irq, void *dev_id)
{
	ipu_disable_irq(IPU_IRQ_ADC_SYS1_EOF);
	ipu_disable_channel(ADC_SYS1, false);

	ipu_enable_channel(ADC_SYS2);
	ipu_enable_irq(IPU_IRQ_ADC_SYS2_EOF);

	return IRQ_HANDLED;
}
Exemple #2
0
/*!
 * CSI EOF callback function.
 *
 * @param irq       int irq line
 * @param dev_id    void * device id
 *
 * @return status   IRQ_HANDLED for handled
 */
static irqreturn_t prp_csi_eof_callback(int irq, void *dev_id)
{
	if (callback_flag == 2) {
		ipu_select_buffer(CSI_MEM, IPU_OUTPUT_BUFFER, 0);
		ipu_enable_channel(CSI_MEM);
	}

	callback_flag++;
	return IRQ_HANDLED;
}
Exemple #3
0
/*!
 * CSI EOF callback function.
 *
 * @param irq       int irq line
 * @param dev_id    void * device id
 *
 * @return status   IRQ_HANDLED for handled
 */
static irqreturn_t prp_csi_eof_callback(int irq, void *dev_id)
{
	cam_data *cam = devid;
	ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
			  callback_flag%2 ? 1 : 0);
	if (callback_flag == 0)
		ipu_enable_channel(cam->ipu, CSI_MEM);

	callback_flag++;
	return IRQ_HANDLED;
}
static irqreturn_t mxcfb_sys1_eof_irq_handler(int irq, void *dev_id)
{
	struct fb_info *fbi = dev_id;
	uint32_t stat[2];

	ipu_disable_irq(IPU_IRQ_ADC_SYS1_EOF);
	ipu_disable_channel(ADC_SYS1, false);

	ipu_adc_get_snooping_status(&stat[0], &stat[1]);
	if (stat[0] || stat[1]) {
		mxcfb_update_region(fbi, stat[0], stat[1]);
	} else {
		ipu_enable_channel(ADC_SYS2);
		ipu_enable_irq(IPU_IRQ_ADC_SYS2_EOF);
	}

	return IRQ_HANDLED;
}
Exemple #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;
}
/*!
 * 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;
}
Exemple #7
0
/*!
 * CSI ENC enable channel setup function
 *
 * @param cam       struct cam_data * mxc capture instance
 *
 * @return  status
 */
static int csi_enc_setup(cam_data *cam)
{
	ipu_channel_params_t params;
	u32 pixel_fmt;
	int err = 0, sensor_protocol = 0;
	dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
#ifdef CONFIG_MXC_MIPI_CSI2
	void *mipi_csi2_info;
	int ipu_id;
	int csi_id;
#endif

	CAMERA_TRACE("In csi_enc_setup\n");
	if (!cam) {
		printk(KERN_ERR "cam private is NULL\n");
		return -ENXIO;
	}

	memset(&params, 0, sizeof(ipu_channel_params_t));
	params.csi_mem.csi = cam->csi;

	sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
	switch (sensor_protocol) {
	case IPU_CSI_CLK_MODE_GATED_CLK:
	case IPU_CSI_CLK_MODE_NONGATED_CLK:
	case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
	case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
	case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
		params.csi_mem.interlaced = false;
		break;
	case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
	case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
	case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
		params.csi_mem.interlaced = true;
		break;
	default:
		printk(KERN_ERR "sensor protocol unsupported\n");
		return -EINVAL;
	}

	if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
		pixel_fmt = IPU_PIX_FMT_YUV420P;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
		pixel_fmt = IPU_PIX_FMT_YUV422P;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
		pixel_fmt = IPU_PIX_FMT_UYVY;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
		pixel_fmt = IPU_PIX_FMT_YUYV;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
		pixel_fmt = IPU_PIX_FMT_NV12;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
		pixel_fmt = IPU_PIX_FMT_BGR24;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
		pixel_fmt = IPU_PIX_FMT_RGB24;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
		pixel_fmt = IPU_PIX_FMT_RGB565;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
		pixel_fmt = IPU_PIX_FMT_BGR32;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
		pixel_fmt = IPU_PIX_FMT_RGB32;
	else {
		printk(KERN_ERR "format not supported\n");
		return -EINVAL;
	}

	ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_ENC, cam->csi, true, true);

#ifdef CONFIG_MXC_MIPI_CSI2
	mipi_csi2_info = mipi_csi2_get_info();
	ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
	csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);

	if (cam->ipu == ipu_get_soc(ipu_id) && cam->csi == csi_id) {
		params.csi_mem.mipi_en = true;
		params.csi_mem.mipi_vc = mipi_csi2_get_virtual_channel(mipi_csi2_info);
		params.csi_mem.mipi_id = mipi_csi2_get_datatype(mipi_csi2_info);

		mipi_csi2_pixelclk_enable(mipi_csi2_info);
	}
#endif

	err = ipu_init_channel(cam->ipu, CSI_MEM, &params);
	if (err != 0) {
		printk(KERN_ERR "ipu_init_channel %d\n", err);
		return err;
	}

	err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
				      pixel_fmt, cam->v2f.fmt.pix.width,
				      cam->v2f.fmt.pix.height,
				      cam->v2f.fmt.pix.width, IPU_ROTATE_NONE,
				      dummy, dummy, 0,
				      cam->offset.u_offset,
				      cam->offset.v_offset);
	if (err != 0) {
		printk(KERN_ERR "CSI_MEM output buffer\n");
		return err;
	}
	err = ipu_enable_channel(cam->ipu, CSI_MEM);
	if (err < 0) {
		printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
		return err;
	}

	return err;
}
Exemple #8
0
int mxcfb_set_refresh_mode(struct fb_info *fbi, int mode,
			   struct mxcfb_rect *update_region)
{
	unsigned long start_addr;
	int ret_mode;
	uint32_t dummy;
	ipu_channel_params_t params;
	struct mxcfb_rect rect;
	struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
	uint32_t stride_pixels = (fbi->fix.line_length * 8) /
	    fbi->var.bits_per_pixel;
	uint32_t memsize = fbi->fix.smem_len;

	if (mxc_fbi->cur_update_mode == mode)
		return mode;

	ret_mode = mxc_fbi->cur_update_mode;

	ipu_disable_irq(IPU_IRQ_ADC_SYS1_EOF);
	ipu_adc_set_update_mode(ADC_SYS1, IPU_ADC_REFRESH_NONE, 0, 0, 0);
#ifdef PARTIAL_REFRESH
	ipu_disable_irq(IPU_IRQ_ADC_SYS2_EOF);
	ipu_adc_set_update_mode(ADC_SYS2, IPU_ADC_REFRESH_NONE, 0, 0, 0);
#endif

	ipu_disable_channel(ADC_SYS1, true);
	ipu_clear_irq(IPU_IRQ_ADC_SYS1_EOF);
#ifdef PARTIAL_REFRESH
	ipu_disable_channel(ADC_SYS2, true);
	ipu_clear_irq(IPU_IRQ_ADC_SYS2_EOF);
#endif
	ipu_adc_get_snooping_status(&dummy, &dummy);

	mxc_fbi->cur_update_mode = mode;

	switch (mode) {
	case MXCFB_REFRESH_OFF:
		if (ipu_adc_set_update_mode(ADC_SYS1, IPU_ADC_REFRESH_NONE,
					    0, 0, 0) < 0)
			dev_err(fbi->device, "Error enabling auto refesh.\n");
		if (ipu_adc_set_update_mode(ADC_SYS2, IPU_ADC_REFRESH_NONE,
					    0, 0, 0) < 0)
			dev_err(fbi->device, "Error enabling auto refesh.\n");
#if 0
		ipu_init_channel_buffer(ADC_SYS2, IPU_INPUT_BUFFER,
					bpp_to_pixfmt(fbi->var.bits_per_pixel),
					1, 1, 4,
					IPU_ROTATE_NONE,
					fbi->fix.smem_start,
					fbi->fix.smem_start, 0, 0);
		ipu_enable_channel(ADC_SYS2);
		ipu_select_buffer(ADC_SYS2, IPU_INPUT_BUFFER, 0);
		ipu_select_buffer(ADC_SYS2, IPU_INPUT_BUFFER, 1);
		msleep(10);
#endif
		ipu_uninit_channel(ADC_SYS1);
#ifdef PARTIAL_REFRESH
		ipu_uninit_channel(ADC_SYS2);
#endif
		break;
	case MXCFB_REFRESH_PARTIAL:
#ifdef PARTIAL_REFRESH
		ipu_adc_get_snooping_status(&dummy, &dummy);

		params.adc_sys2.disp = DISP0;
		params.adc_sys2.ch_mode = WriteTemplateNonSeq;
		params.adc_sys2.out_left = 0;
		params.adc_sys2.out_top = 0;
		ipu_init_channel(ADC_SYS2, &params);

		if (ipu_adc_set_update_mode(ADC_SYS1, IPU_ADC_REFRESH_NONE,
					    0, 0, 0) < 0) {
			dev_err(fbi->device, "Error enabling auto refesh.\n");
		}
		if (ipu_adc_set_update_mode
		    (ADC_SYS2, IPU_ADC_AUTO_REFRESH_SNOOP, 30,
		     fbi->fix.smem_start, &memsize) < 0) {
			dev_err(fbi->device, "Error enabling auto refesh.\n");
		}
		mxc_fbi->snoop_window_size = memsize;

		ipu_init_channel_buffer(ADC_SYS2, IPU_INPUT_BUFFER,
					bpp_to_pixfmt(fbi->var.bits_per_pixel),
					1, 1, 4,
					IPU_ROTATE_NONE,
					fbi->fix.smem_start, 0, 0, 0);

		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);

		ipu_init_channel_buffer(ADC_SYS1, IPU_INPUT_BUFFER,
					bpp_to_pixfmt(fbi->var.bits_per_pixel),
					MXCFB_SCREEN_WIDTH, MXCFB_SCREEN_HEIGHT,
					stride_pixels, IPU_ROTATE_NONE,
					fbi->fix.smem_start, 0, 0, 0);
		ipu_enable_channel(ADC_SYS1);
		ipu_select_buffer(ADC_SYS1, IPU_INPUT_BUFFER, 0);
		ipu_enable_irq(IPU_IRQ_ADC_SYS1_EOF);
		break;
#endif
	case MXCFB_REFRESH_AUTO:
		if (update_region == NULL) {
			update_region = &rect;
			rect.top = 0;
			rect.left = 0;
			rect.height = MXCFB_SCREEN_HEIGHT;
			rect.width = MXCFB_SCREEN_WIDTH;
		}
		params.adc_sys1.disp = mxc_fbi->disp_num;
		params.adc_sys1.ch_mode = WriteTemplateNonSeq;
		params.adc_sys1.out_left = MXCFB_SCREEN_LEFT_OFFSET +
		    update_region->left;
		params.adc_sys1.out_top = MXCFB_SCREEN_TOP_OFFSET +
		    update_region->top;
		ipu_init_channel(ADC_SYS1, &params);

		/* Address aligned to line */
		start_addr = update_region->top * fbi->fix.line_length;
		start_addr += fbi->fix.smem_start;
		start_addr += update_region->left * fbi->var.bits_per_pixel / 8;

		ipu_init_channel_buffer(ADC_SYS1, IPU_INPUT_BUFFER,
					bpp_to_pixfmt(fbi->var.bits_per_pixel),
					update_region->width,
					update_region->height, stride_pixels,
					IPU_ROTATE_NONE, start_addr, 0, 0, 0);
		ipu_enable_channel(ADC_SYS1);
		ipu_select_buffer(ADC_SYS1, IPU_INPUT_BUFFER, 0);

		if (ipu_adc_set_update_mode
		    (ADC_SYS1, IPU_ADC_AUTO_REFRESH_SNOOP, 30,
		     fbi->fix.smem_start, &memsize) < 0)
			dev_err(fbi->device, "Error enabling auto refesh.\n");

		mxc_fbi->snoop_window_size = memsize;

		break;
	}
	return ret_mode;
}
/*!
 * PrpENC enable channel setup function
 *
 * @param cam       struct cam_data * mxc capture instance
 *
 * @return  status
 */
static int prp_enc_setup(cam_data *cam)
{
	ipu_channel_params_t enc;
	int err = 0;
	dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;
#ifdef CONFIG_MXC_MIPI_CSI2
	void *mipi_csi2_info;
	int ipu_id;
	int csi_id;
#endif

	CAMERA_TRACE("In prp_enc_setup\n");
	if (!cam) {
		printk(KERN_ERR "cam private is NULL\n");
		return -ENXIO;
	}
	memset(&enc, 0, sizeof(ipu_channel_params_t));

	ipu_csi_get_window_size(cam->ipu, &enc.csi_prp_enc_mem.in_width,
				&enc.csi_prp_enc_mem.in_height, cam->csi);

	enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
	enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width;
	enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height;
	enc.csi_prp_enc_mem.csi = cam->csi;
	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
		enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height;
		enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width;
	}

	if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P;
		pr_info("YUV420\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YVU420P;
		pr_info("YVU420\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P;
		pr_info("YUV422P\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUYV;
		pr_info("YUYV\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_UYVY;
		pr_info("UYVY\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_NV12;
		pr_info("NV12\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24;
		pr_info("BGR24\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24;
		pr_info("RGB24\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565;
		pr_info("RGB565\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32;
		pr_info("BGR32\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32;
		pr_info("RGB32\n");
	} else {
		printk(KERN_ERR "format not supported\n");
		return -EINVAL;
	}

#ifdef CONFIG_MXC_MIPI_CSI2
	mipi_csi2_info = mipi_csi2_get_info();

	if (mipi_csi2_info) {
		if (mipi_csi2_get_status(mipi_csi2_info)) {
			ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
			csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);

			if (cam->ipu == ipu_get_soc(ipu_id)
				&& cam->csi == csi_id) {
				enc.csi_prp_enc_mem.mipi_en = true;
				enc.csi_prp_enc_mem.mipi_vc =
				mipi_csi2_get_virtual_channel(mipi_csi2_info);
				enc.csi_prp_enc_mem.mipi_id =
				mipi_csi2_get_datatype(mipi_csi2_info);

				mipi_csi2_pixelclk_enable(mipi_csi2_info);
			} else {
				enc.csi_prp_enc_mem.mipi_en = false;
				enc.csi_prp_enc_mem.mipi_vc = 0;
				enc.csi_prp_enc_mem.mipi_id = 0;
			}
		} else {
			enc.csi_prp_enc_mem.mipi_en = false;
			enc.csi_prp_enc_mem.mipi_vc = 0;
			enc.csi_prp_enc_mem.mipi_id = 0;
		}
	}
#endif

	err = ipu_init_channel(cam->ipu, CSI_PRP_ENC_MEM, &enc);
	if (err != 0) {
		printk(KERN_ERR "ipu_init_channel %d\n", err);
		return err;
	}

	grotation = cam->rotation;
	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
		if (cam->rot_enc_bufs_vaddr[0]) {
			dma_free_coherent(0, cam->rot_enc_buf_size[0],
					  cam->rot_enc_bufs_vaddr[0],
					  cam->rot_enc_bufs[0]);
		}
		if (cam->rot_enc_bufs_vaddr[1]) {
			dma_free_coherent(0, cam->rot_enc_buf_size[1],
					  cam->rot_enc_bufs_vaddr[1],
					  cam->rot_enc_bufs[1]);
		}
		cam->rot_enc_buf_size[0] =
		    PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
		cam->rot_enc_bufs_vaddr[0] =
		    (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0],
					       &cam->rot_enc_bufs[0],
					       GFP_DMA | GFP_KERNEL);
		if (!cam->rot_enc_bufs_vaddr[0]) {
			printk(KERN_ERR "alloc enc_bufs0\n");
			return -ENOMEM;
		}
		cam->rot_enc_buf_size[1] =
		    PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
		cam->rot_enc_bufs_vaddr[1] =
		    (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1],
					       &cam->rot_enc_bufs[1],
					       GFP_DMA | GFP_KERNEL);
		if (!cam->rot_enc_bufs_vaddr[1]) {
			dma_free_coherent(0, cam->rot_enc_buf_size[0],
					  cam->rot_enc_bufs_vaddr[0],
					  cam->rot_enc_bufs[0]);
			cam->rot_enc_bufs_vaddr[0] = NULL;
			cam->rot_enc_bufs[0] = 0;
			printk(KERN_ERR "alloc enc_bufs1\n");
			return -ENOMEM;
		}

		err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM,
					      IPU_OUTPUT_BUFFER,
					      enc.csi_prp_enc_mem.out_pixel_fmt,
					      enc.csi_prp_enc_mem.out_width,
					      enc.csi_prp_enc_mem.out_height,
					      enc.csi_prp_enc_mem.out_width,
					      IPU_ROTATE_NONE,
					      cam->rot_enc_bufs[0],
					      cam->rot_enc_bufs[1], 0, 0, 0);
		if (err != 0) {
			printk(KERN_ERR "CSI_PRP_ENC_MEM err\n");
			return err;
		}

		err = ipu_init_channel(cam->ipu, MEM_ROT_ENC_MEM, NULL);
		if (err != 0) {
			printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n");
			return err;
		}

		err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM,
					      IPU_INPUT_BUFFER,
					      enc.csi_prp_enc_mem.out_pixel_fmt,
					      enc.csi_prp_enc_mem.out_width,
					      enc.csi_prp_enc_mem.out_height,
					      enc.csi_prp_enc_mem.out_width,
					      cam->rotation,
					      cam->rot_enc_bufs[0],
					      cam->rot_enc_bufs[1], 0, 0, 0);
		if (err != 0) {
			printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n");
			return err;
		}

		err =
		    ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM,
					    IPU_OUTPUT_BUFFER,
					    enc.csi_prp_enc_mem.out_pixel_fmt,
					    enc.csi_prp_enc_mem.out_height,
					    enc.csi_prp_enc_mem.out_width,
					    cam->v2f.fmt.pix.bytesperline /
					    bytes_per_pixel(enc.csi_prp_enc_mem.
							    out_pixel_fmt),
					    IPU_ROTATE_NONE,
					    dummy, dummy, 0,
					    cam->offset.u_offset,
					    cam->offset.v_offset);
		if (err != 0) {
			printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n");
			return err;
		}

		err = ipu_link_channels(cam->ipu,
					CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);
		if (err < 0) {
			printk(KERN_ERR
			       "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n");
			return err;
		}

		err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM);
		if (err < 0) {
			printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
			return err;
		}
		err = ipu_enable_channel(cam->ipu, MEM_ROT_ENC_MEM);
		if (err < 0) {
			printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n");
			return err;
		}

		ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM,
				  IPU_OUTPUT_BUFFER, 0);
		ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM,
				  IPU_OUTPUT_BUFFER, 1);
	} else {
		err =
		    ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM,
					    IPU_OUTPUT_BUFFER,
					    enc.csi_prp_enc_mem.out_pixel_fmt,
					    enc.csi_prp_enc_mem.out_width,
					    enc.csi_prp_enc_mem.out_height,
					    cam->v2f.fmt.pix.bytesperline /
					    bytes_per_pixel(enc.csi_prp_enc_mem.
							    out_pixel_fmt),
					    cam->rotation,
					    dummy, dummy, 0,
					    cam->offset.u_offset,
					    cam->offset.v_offset);
		if (err != 0) {
			printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n");
			return err;
		}
		err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM);
		if (err < 0) {
			printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
			return err;
		}
	}

	return err;
}
static int csi_enc_setup(cam_data *cam)
{
	ipu_channel_params_t params;
	int err = 0, sensor_protocol = 0;
#ifdef CONFIG_MXC_MIPI_CSI2
	void *mipi_csi2_info;
	int ipu_id;
	int csi_id;
#endif

	CAMERA_TRACE("In csi_enc_setup\n");
	if (!cam) {
		printk(KERN_ERR "cam private is NULL\n");
		return -ENXIO;
	}

	memset(&params, 0, sizeof(ipu_channel_params_t));
	params.csi_mem.csi = cam->csi;

	sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
	switch (sensor_protocol) {
	case IPU_CSI_CLK_MODE_GATED_CLK:
	case IPU_CSI_CLK_MODE_NONGATED_CLK:
	case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
	case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
	case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
		params.csi_mem.interlaced = false;
		break;
	case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
	case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
	case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
		params.csi_mem.interlaced = true;
		break;
	default:
		printk(KERN_ERR "sensor protocol unsupported\n");
		return -EINVAL;
	}

#ifdef CONFIG_MXC_MIPI_CSI2
	mipi_csi2_info = mipi_csi2_get_info();

	if (mipi_csi2_info) {
		if (mipi_csi2_get_status(mipi_csi2_info)) {
			ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info);
			csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info);

			if (cam->ipu == ipu_get_soc(ipu_id)
				&& cam->csi == csi_id) {
				params.csi_mem.mipi_en = true;
				params.csi_mem.mipi_vc =
				mipi_csi2_get_virtual_channel(mipi_csi2_info);
				params.csi_mem.mipi_id =
				mipi_csi2_get_datatype(mipi_csi2_info);

				mipi_csi2_pixelclk_enable(mipi_csi2_info);
			} else {
				params.csi_mem.mipi_en = false;
				params.csi_mem.mipi_vc = 0;
				params.csi_mem.mipi_id = 0;
			}
		} else {
			params.csi_mem.mipi_en = false;
			params.csi_mem.mipi_vc = 0;
			params.csi_mem.mipi_id = 0;
		}
	}
#endif

	if (cam->vf_bufs_vaddr[0]) {
		dma_free_coherent(0, cam->vf_bufs_size[0],
				  cam->vf_bufs_vaddr[0],
				  (dma_addr_t) cam->vf_bufs[0]);
	}
	if (cam->vf_bufs_vaddr[1]) {
		dma_free_coherent(0, cam->vf_bufs_size[1],
				  cam->vf_bufs_vaddr[1],
				  (dma_addr_t) cam->vf_bufs[1]);
	}
	csi_mem_bufsize = cam->crop_current.width *
			  cam->crop_current.height * 3/2;
	cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize);
	cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0,
							   cam->vf_bufs_size[0],
							   (dma_addr_t *) &
							   cam->vf_bufs[0],
							   GFP_DMA |
							   GFP_KERNEL);
	if (cam->vf_bufs_vaddr[0] == NULL) {
		printk(KERN_ERR "Error to allocate vf buffer\n");
		err = -ENOMEM;
		goto out_2;
	}
	cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize);
	cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0,
							   cam->vf_bufs_size[1],
							   (dma_addr_t *) &
							   cam->vf_bufs[1],
							   GFP_DMA |
							   GFP_KERNEL);
	if (cam->vf_bufs_vaddr[1] == NULL) {
		printk(KERN_ERR "Error to allocate vf buffer\n");
		err = -ENOMEM;
		goto out_1;
	}
	pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]);

	err = ipu_init_channel(cam->ipu, CSI_MEM, &params);
	if (err != 0) {
		printk(KERN_ERR "ipu_init_channel %d\n", err);
		goto out_1;
	}

	if ((cam->crop_current.width == cam->win.w.width) &&
		(cam->crop_current.height == cam->win.w.height) &&
		(vf_out_format == IPU_PIX_FMT_NV12) &&
		(cam->rotation < IPU_ROTATE_VERT_FLIP)) {
		err = ipu_init_channel_buffer(cam->ipu, CSI_MEM,
			IPU_OUTPUT_BUFFER,
			IPU_PIX_FMT_NV12,
			cam->crop_current.width,
			cam->crop_current.height,
			cam->crop_current.width, IPU_ROTATE_NONE,
			fbi->fix.smem_start +
			(fbi->fix.line_length * fbvar.yres),
			fbi->fix.smem_start, 0,
			cam->offset.u_offset, cam->offset.u_offset);
	} else {
		err = ipu_init_channel_buffer(cam->ipu, CSI_MEM,
			IPU_OUTPUT_BUFFER,
			IPU_PIX_FMT_NV12,
			cam->crop_current.width,
			cam->crop_current.height,
			cam->crop_current.width, IPU_ROTATE_NONE,
			cam->vf_bufs[0], cam->vf_bufs[1], 0,
			cam->offset.u_offset, cam->offset.u_offset);
	}
	if (err != 0) {
		printk(KERN_ERR "CSI_MEM output buffer\n");
		goto out_1;
	}
	err = ipu_enable_channel(cam->ipu, CSI_MEM);
	if (err < 0) {
		printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
		goto out_1;
	}

	csi_buffer_num = 0;

	ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0);
	ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 1);
	return err;
out_1:
	if (cam->vf_bufs_vaddr[0]) {
		dma_free_coherent(0, cam->vf_bufs_size[0],
				  cam->vf_bufs_vaddr[0],
				  (dma_addr_t) cam->vf_bufs[0]);
		cam->vf_bufs_vaddr[0] = NULL;
		cam->vf_bufs[0] = 0;
	}
	if (cam->vf_bufs_vaddr[1]) {
		dma_free_coherent(0, cam->vf_bufs_size[1],
				  cam->vf_bufs_vaddr[1],
				  (dma_addr_t) cam->vf_bufs[1]);
		cam->vf_bufs_vaddr[1] = NULL;
		cam->vf_bufs[1] = 0;
	}
out_2:
	return err;
}
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;
}
Exemple #12
0
/*!
 * CSI ENC enable channel setup function
 *
 * @param cam       struct cam_data * mxc capture instance
 *
 * @return  status
 */
static int csi_enc_setup(cam_data *cam)
{
	ipu_channel_params_t params;
	u32 pixel_fmt;
	int err = 0, sensor_protocol = 0;
	dma_addr_t dummy = cam->dummy_frame.buffer.m.offset;

	CAMERA_TRACE("In csi_enc_setup\n");
	if (!cam) {
		printk(KERN_ERR "cam private is NULL\n");
		return -ENXIO;
	}

	memset(&params, 0, sizeof(ipu_channel_params_t));
	params.csi_mem.csi = cam->csi;

	sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi);
	switch (sensor_protocol) {
	case IPU_CSI_CLK_MODE_GATED_CLK:
	case IPU_CSI_CLK_MODE_NONGATED_CLK:
	case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
	case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
	case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
		params.csi_mem.interlaced = false;
		break;
	case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
	case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
	case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
		params.csi_mem.interlaced = true;
		break;
	default:
		printk(KERN_ERR "sensor protocol unsupported\n");
		return -EINVAL;
	}

	if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
		pixel_fmt = IPU_PIX_FMT_YUV420P;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420)
		pixel_fmt = IPU_PIX_FMT_YVU420P;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
		pixel_fmt = IPU_PIX_FMT_YUV422P;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
		pixel_fmt = IPU_PIX_FMT_UYVY;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
		pixel_fmt = IPU_PIX_FMT_YUYV;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
		pixel_fmt = IPU_PIX_FMT_NV12;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
		pixel_fmt = IPU_PIX_FMT_BGR24;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
		pixel_fmt = IPU_PIX_FMT_RGB24;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
		pixel_fmt = IPU_PIX_FMT_RGB565;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
		pixel_fmt = IPU_PIX_FMT_BGR32;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
		pixel_fmt = IPU_PIX_FMT_RGB32;
	else {
		printk(KERN_ERR "format not supported\n");
		return -EINVAL;
	}
	err = cam_mipi_csi2_enable(cam, &params.csi_mem.mipi);
	if (err)
		return err;

	err = ipu_init_channel(cam->ipu, CSI_MEM, &params);
	if (err != 0) {
		printk(KERN_ERR "ipu_init_channel %d\n", err);
		return err;
	}

	err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,
				      pixel_fmt, cam->v2f.fmt.pix.width,
				      cam->v2f.fmt.pix.height,
				      cam->v2f.fmt.pix.bytesperline,
				      cam->rotation,
				      dummy, dummy, 0,
				      cam->offset.u_offset,
				      cam->offset.v_offset);
	if (err != 0) {
		printk(KERN_ERR "CSI_MEM output buffer\n");
		return err;
	}
	err = ipu_enable_channel(cam->ipu, CSI_MEM);
	if (err < 0) {
		printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
		return err;
	}

	return err;
}
Exemple #13
0
/*!
 * CSI ENC enable channel setup function
 *
 * @param cam       struct cam_data * mxc capture instance
 *
 * @return  status
 */
static int csi_enc_setup(cam_data *cam)
{
	ipu_channel_params_t params;
	u32 pixel_fmt;
	int err = 0, sensor_protocol = 0;
	dma_addr_t dummy0 = 0x97BBB800;
	dma_addr_t dummy1 = 0x97B00000;	

	if (!cam) {
		printf("cam private is NULL\n");
		return -ENXIO;
	}
	//printf("csi_enc_setup\n");
	memset(&params, 0, sizeof(ipu_channel_params_t));
	params.csi_mem.csi = cam->csi;

	sensor_protocol = ipu_csi_get_sensor_protocol(cam->csi);
//	printf("csi_enc_setup: sensor_protocol: %d, pixelformat: 0x%x\n", sensor_protocol, cam->v2f.fmt.pix.pixelformat);	
	switch (sensor_protocol) {
	case IPU_CSI_CLK_MODE_GATED_CLK:
	case IPU_CSI_CLK_MODE_NONGATED_CLK:
	case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
	case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
	case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
		params.csi_mem.interlaced = 0;
		break;
	case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
	case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
	case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
		params.csi_mem.interlaced = 1;
		break;
	default:
		printf("sensor protocol unsupported\n");
		return -EINVAL;
	}
	if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
		pixel_fmt = IPU_PIX_FMT_YUV420P;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
		pixel_fmt = IPU_PIX_FMT_YUV422P;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
		pixel_fmt = IPU_PIX_FMT_UYVY;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
		pixel_fmt = IPU_PIX_FMT_YUYV;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
		pixel_fmt = IPU_PIX_FMT_NV12;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
		pixel_fmt = IPU_PIX_FMT_BGR24;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
		pixel_fmt = IPU_PIX_FMT_RGB24;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
		pixel_fmt = IPU_PIX_FMT_RGB565;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
		pixel_fmt = IPU_PIX_FMT_BGR32;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
		pixel_fmt = IPU_PIX_FMT_RGB32;
	else if(cam->v2f.fmt.pix.pixelformat == IPU_PIX_FMT_GENERIC)
		pixel_fmt = IPU_PIX_FMT_GENERIC;
	else {
		printf("format not supported\n");
		return -EINVAL;
	}

	ipu_csi_enable_mclk(cam->csi, 1, 1);

	err = ipu_init_channel(CSI_MEM, &params);
	if (err != 0) {
		printf("ipu_init_channel %d\n", err);
		return err;
	}
//	printf("csi_enc_setup -> ipu_init_channel_buffer \n");
	err = ipu_init_channel_buffer(CSI_MEM, IPU_OUTPUT_BUFFER,
				      pixel_fmt, cam->v2f.fmt.pix.width,
				      cam->v2f.fmt.pix.height,
				      cam->v2f.fmt.pix.width,
				      dummy1, 0,
				      cam->offset.u_offset,
				      cam->offset.v_offset);
	if (err != 0) {
		printf("CSI_MEM output buffer\n");
		return err;
	}
	err = ipu_enable_channel(CSI_MEM);
	if (err < 0) {
		printf("ipu_enable_channel CSI_MEM\n");
		return err;
	}

	return err;
}
static void mxcfb_update_region(struct fb_info *fbi, uint32_t statl,
				uint32_t stath)
{
	ipu_channel_params_t params;
	struct mxcfb_info *mxc_fbi = fbi->par;
	uint32_t seg_size;
	uint32_t lsb, msb;
	uint32_t update_height, start_line, start_addr, end_line, end_addr;
	uint32_t stride_pixels = (fbi->fix.line_length * 8) /
	    fbi->var.bits_per_pixel;

	lsb = ffs(statl);
	if (lsb) {
		lsb--;
	} else {
		lsb = ffs(stath);
		lsb += 32 - 1;
	}
	msb = fls(stath);
	if (msb) {
		msb += 32;
	} else {
		msb = fls(statl);
	}

	seg_size = mxc_fbi->snoop_window_size / 64;

	start_addr = lsb * seg_size;	// starting address offset
	start_line = start_addr / fbi->fix.line_length;
	start_addr = start_line * fbi->fix.line_length;	// Addr aligned to line
	start_addr += fbi->fix.smem_start;

	end_addr = msb * seg_size;	// ending address offset
	end_line = end_addr / fbi->fix.line_length;
	end_line++;

	if (end_line > fbi->var.yres) {
		end_line = fbi->var.yres;
	}

	update_height = end_line - start_line;
	dev_dbg(fbi->device, "updating rows %d to %d, start addr = 0x%08X\n",
		start_line, end_line, start_addr);

	ipu_uninit_channel(ADC_SYS1);
	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 = start_line;
	ipu_init_channel(ADC_SYS1, &params);

	ipu_init_channel_buffer(ADC_SYS1, IPU_INPUT_BUFFER,
				bpp_to_pixfmt(fbi->var.bits_per_pixel),
				MXCFB_SCREEN_WIDTH,
				update_height,
				stride_pixels,
				IPU_ROTATE_NONE, (dma_addr_t) start_addr, 0, 0,
				0);
	ipu_enable_channel(ADC_SYS1);
	ipu_select_buffer(ADC_SYS1, IPU_INPUT_BUFFER, 0);
	ipu_enable_irq(IPU_IRQ_ADC_SYS1_EOF);
}
Exemple #15
0
/*!
 * CSI ENC enable channel setup function
 *
 * @param cam       struct cam_data * mxc capture instance
 *
 * @return  status
 */
static int csi_enc_setup(cam_data *cam)
{
	ipu_channel_params_t params;
	u32 pixel_fmt;
	int err = 0;
	dma_addr_t dummy = 0xdeadbeaf;

	CAMERA_TRACE("In csi_enc_setup\n");
	if (!cam) {
		printk(KERN_ERR "cam private is NULL\n");
		return -ENXIO;
	}

	memset(&params, 0, sizeof(ipu_channel_params_t));
	params.csi_mem.csi = cam->csi;

	if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
		pixel_fmt = IPU_PIX_FMT_YUV420P;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
		pixel_fmt = IPU_PIX_FMT_YUV422P;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
		pixel_fmt = IPU_PIX_FMT_UYVY;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12)
		pixel_fmt = IPU_PIX_FMT_NV12;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
		pixel_fmt = IPU_PIX_FMT_BGR24;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
		pixel_fmt = IPU_PIX_FMT_RGB24;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565)
		pixel_fmt = IPU_PIX_FMT_RGB565;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32)
		pixel_fmt = IPU_PIX_FMT_BGR32;
	else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32)
		pixel_fmt = IPU_PIX_FMT_RGB32;
	else {
		printk(KERN_ERR "format not supported\n");
		return -EINVAL;
	}

	ipu_csi_enable_mclk_if(CSI_MCLK_ENC, cam->csi, true, true);

	err = ipu_init_channel(CSI_MEM, &params);
	if (err != 0) {
		printk(KERN_ERR "ipu_init_channel %d\n", err);
		return err;
	}

	err = ipu_init_channel_buffer(CSI_MEM, IPU_OUTPUT_BUFFER,
				      pixel_fmt, cam->v2f.fmt.pix.width,
				      cam->v2f.fmt.pix.height,
				      cam->v2f.fmt.pix.width, IPU_ROTATE_NONE,
				      dummy, dummy,
				      cam->offset.u_offset,
				      cam->offset.v_offset);
	if (err != 0) {
		printk(KERN_ERR "CSI_MEM output buffer\n");
		return err;
	}
	err = ipu_enable_channel(CSI_MEM);
	if (err < 0) {
		printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");
		return err;
	}

	return err;
}
/*!
 * PrpENC enable channel setup function
 *
 * @param cam       struct cam_data * mxc capture instance
 *
 * @return  status
 */
static int prp_enc_setup(cam_data *cam)
{
	ipu_channel_params_t enc;
	int err = 0;
	dma_addr_t dummy = 0xdeadbeaf;

	CAMERA_TRACE("In prp_enc_setup\n");
	if (!cam) {
		printk(KERN_ERR "cam private is NULL\n");
		return -ENXIO;
	}
	memset(&enc, 0, sizeof(ipu_channel_params_t));

	ipu_csi_get_window_size(&enc.csi_prp_enc_mem.in_width,
				&enc.csi_prp_enc_mem.in_height, cam->csi);

	enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY;
	enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width;
	enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height;
	enc.csi_prp_enc_mem.csi = cam->csi;
	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
		enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height;
		enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width;
	}

	if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P;
		pr_info("YUV420\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P;
		pr_info("YUV422P\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUYV;
		pr_info("YUYV\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_UYVY;
		pr_info("UYVY\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_NV12;
		pr_info("NV12\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24;
		pr_info("BGR24\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24;
		pr_info("RGB24\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565;
		pr_info("RGB565\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32;
		pr_info("BGR32\n");
	} else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) {
		enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32;
		pr_info("RGB32\n");
	} else {
		printk(KERN_ERR "format not supported\n");
		return -EINVAL;
	}

	err = ipu_init_channel(CSI_PRP_ENC_MEM, &enc);
	if (err != 0) {
		printk(KERN_ERR "ipu_init_channel %d\n", err);
		return err;
	}

	ipu_csi_enable_mclk_if(CSI_MCLK_ENC, cam->csi, true, true);

	grotation = cam->rotation;
	if (cam->rotation >= IPU_ROTATE_90_RIGHT) {
		if (cam->rot_enc_bufs_vaddr[0]) {
			dma_free_coherent(0, cam->rot_enc_buf_size[0],
					  cam->rot_enc_bufs_vaddr[0],
					  cam->rot_enc_bufs[0]);
		}
		if (cam->rot_enc_bufs_vaddr[1]) {
			dma_free_coherent(0, cam->rot_enc_buf_size[1],
					  cam->rot_enc_bufs_vaddr[1],
					  cam->rot_enc_bufs[1]);
		}
		cam->rot_enc_buf_size[0] =
		    PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
		cam->rot_enc_bufs_vaddr[0] =
		    (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0],
					       &cam->rot_enc_bufs[0],
					       GFP_DMA | GFP_KERNEL);
		if (!cam->rot_enc_bufs_vaddr[0]) {
			printk(KERN_ERR "alloc enc_bufs0\n");
			return -ENOMEM;
		}
		cam->rot_enc_buf_size[1] =
		    PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);
		cam->rot_enc_bufs_vaddr[1] =
		    (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1],
					       &cam->rot_enc_bufs[1],
					       GFP_DMA | GFP_KERNEL);
		if (!cam->rot_enc_bufs_vaddr[1]) {
			dma_free_coherent(0, cam->rot_enc_buf_size[0],
					  cam->rot_enc_bufs_vaddr[0],
					  cam->rot_enc_bufs[0]);
			cam->rot_enc_bufs_vaddr[0] = NULL;
			cam->rot_enc_bufs[0] = 0;
			printk(KERN_ERR "alloc enc_bufs1\n");
			return -ENOMEM;
		}

		err = ipu_init_channel_buffer(CSI_PRP_ENC_MEM,
					      IPU_OUTPUT_BUFFER,
					      enc.csi_prp_enc_mem.out_pixel_fmt,
					      enc.csi_prp_enc_mem.out_width,
					      enc.csi_prp_enc_mem.out_height,
					      enc.csi_prp_enc_mem.out_width,
					      IPU_ROTATE_NONE,
					      cam->rot_enc_bufs[0],
					      cam->rot_enc_bufs[1], 0, 0, 0);
		if (err != 0) {
			printk(KERN_ERR "CSI_PRP_ENC_MEM err\n");
			return err;
		}

		err = ipu_init_channel(MEM_ROT_ENC_MEM, NULL);
		if (err != 0) {
			printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n");
			return err;
		}

		err = ipu_init_channel_buffer(MEM_ROT_ENC_MEM, IPU_INPUT_BUFFER,
					      enc.csi_prp_enc_mem.out_pixel_fmt,
					      enc.csi_prp_enc_mem.out_width,
					      enc.csi_prp_enc_mem.out_height,
					      enc.csi_prp_enc_mem.out_width,
					      cam->rotation,
					      cam->rot_enc_bufs[0],
					      cam->rot_enc_bufs[1], 0, 0, 0);
		if (err != 0) {
			printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n");
			return err;
		}

		err =
		    ipu_init_channel_buffer(MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER,
					    enc.csi_prp_enc_mem.out_pixel_fmt,
					    enc.csi_prp_enc_mem.out_height,
					    enc.csi_prp_enc_mem.out_width,
					    cam->v2f.fmt.pix.bytesperline /
					    bytes_per_pixel(enc.csi_prp_enc_mem.
							    out_pixel_fmt),
					    IPU_ROTATE_NONE,
					    dummy, dummy, 0,
					    cam->offset.u_offset,
					    cam->offset.v_offset);
		if (err != 0) {
			printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n");
			return err;
		}

		err = ipu_link_channels(CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM);
		if (err < 0) {
			printk(KERN_ERR
			       "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n");
			return err;
		}

		err = ipu_enable_channel(CSI_PRP_ENC_MEM);
		if (err < 0) {
			printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
			return err;
		}
		err = ipu_enable_channel(MEM_ROT_ENC_MEM);
		if (err < 0) {
			printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n");
			return err;
		}

		ipu_select_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, 0);
		ipu_select_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, 1);
	} else {
		err =
		    ipu_init_channel_buffer(CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER,
					    enc.csi_prp_enc_mem.out_pixel_fmt,
					    enc.csi_prp_enc_mem.out_width,
					    enc.csi_prp_enc_mem.out_height,
					    cam->v2f.fmt.pix.bytesperline /
					    bytes_per_pixel(enc.csi_prp_enc_mem.
							    out_pixel_fmt),
					    cam->rotation,
					    dummy, dummy, 0,
					    cam->offset.u_offset,
					    cam->offset.v_offset);
		if (err != 0) {
			printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n");
			return err;
		}
		err = ipu_enable_channel(CSI_PRP_ENC_MEM);
		if (err < 0) {
			printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n");
			return err;
		}
	}

	return err;
}
/*
 * 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;
}
Exemple #18
0
static irqreturn_t mxcfb_sys2_eof_irq_handler(int irq, void *dev_id)
{
	ipu_channel_params_t params;
	struct fb_info *fbi = dev_id;
	struct mxcfb_info *mxc_fbi = fbi->par;
	uint32_t stat[2], seg_size;
	uint32_t lsb, msb;
	uint32_t update_height, start_line, start_addr, end_line, end_addr;
	uint32_t stride_pixels = (fbi->fix.line_length * 8) /
	    fbi->var.bits_per_pixel;

	ipu_adc_get_snooping_status(&stat[0], &stat[1]);

	if (!stat[0] && !stat[1]) {
		dev_err(fbi->device, "error no bus snooping bits set\n");
		return IRQ_HANDLED;
	}
	ipu_disable_irq(IPU_IRQ_ADC_SYS2_EOF);

	lsb = ffs(stat[0]);
	if (lsb) {
		lsb--;
	} else {
		lsb = ffs(stat[1]);
		lsb += 32 - 1;
	}
	msb = fls(stat[1]);
	if (msb) {
		msb += 32;
	} else {
		msb = fls(stat[0]);
	}

	seg_size = mxc_fbi->snoop_window_size / 64;

	start_addr = lsb * seg_size;	/* starting address offset */
	start_line = start_addr / fbi->fix.line_length;
	start_addr = start_line * fbi->fix.line_length;	/* Addr aligned to line */
	start_addr += fbi->fix.smem_start;

	end_addr = msb * seg_size;	/* ending address offset */
	end_line = end_addr / fbi->fix.line_length;
	end_line++;

	if (end_line > fbi->var.yres) {
		end_line = fbi->var.yres;
	}

	update_height = end_line - start_line;
	dev_dbg(fbi->device, "updating rows %d to %d, start addr = 0x%08X\n",
		start_line, end_line, start_addr);

	ipu_uninit_channel(ADC_SYS1);
	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 = start_line;
	ipu_init_channel(ADC_SYS1, &params);

	ipu_init_channel_buffer(ADC_SYS1, IPU_INPUT_BUFFER,
				bpp_to_pixfmt(fbi->var.bits_per_pixel),
				MXCFB_SCREEN_WIDTH,
				update_height,
				stride_pixels,
				IPU_ROTATE_NONE, (dma_addr_t) start_addr, 0,
				0, 0);
	ipu_enable_channel(ADC_SYS1);
	ipu_select_buffer(ADC_SYS1, IPU_INPUT_BUFFER, 0);
	ipu_enable_irq(IPU_IRQ_ADC_SYS1_EOF);

	return IRQ_HANDLED;
}
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;
}
Exemple #20
0
/*!
 * This function handles PP_IOCTL_START calls. It sets the PP channel buffers
 * addresses and starts the channels
 *
 * @return      This function returns 0 on success or negative error code on 
 *              error.
 */
static int mxc_pp_start(pp_buf * in, pp_buf * in_comb, pp_buf * mid, pp_buf * out)
{
  int err = 0;

  FUNC_START;

  pp_data.done_flag = 0;

  if(pp_data.mode >= PP_PP_ROT)
    ipu_enable_irq(IPU_IRQ_PP_OUT_EOF);
  if(pp_data.mode <= PP_PP_ROT)
    ipu_enable_irq(IPU_IRQ_PP_ROT_OUT_EOF);

  if(pp_data.mode == PP_PP) {
    err = ipu_update_channel_buffer(MEM_PP_MEM, IPU_INPUT_BUFFER, 0, (void*)in->addr);
    if(err < 0) {
      printk("mxc_ipu_pp: error PP_PP input buffer\n");
      goto err0;
    }
    err = ipu_update_channel_buffer(MEM_PP_MEM, IPU_OUTPUT_BUFFER, 0, (void*)out->addr);
    if(err < 0) {
      printk("mxc_ipu_pp: error PP_PP output buffer\n");
      goto err0;
    }
    if(pp_data.ic_combine_en != 0) {
      err = ipu_update_channel_buffer(MEM_PP_MEM, IPU_SEC_INPUT_BUFFER, 0, (void*)in_comb->addr);
      if(err < 0) {
        printk("mxc_ipu_pp: error PP_PP second input buffer\n");
        goto err0;
      }
      ipu_select_buffer(MEM_PP_MEM, IPU_SEC_INPUT_BUFFER, 0);
    }
    ipu_select_buffer(MEM_PP_MEM, IPU_INPUT_BUFFER, 0);
    ipu_select_buffer(MEM_PP_MEM, IPU_OUTPUT_BUFFER, 0);
  }
  else if(pp_data.mode == PP_PP_ROT) {
    err = ipu_update_channel_buffer(MEM_PP_MEM, IPU_INPUT_BUFFER, 0, (void*)in->addr);
    if(err < 0) {
      printk("mxc_ipu_pp: error PP_PP_ROT input buffer\n");
      goto err0;
    }
    err = ipu_update_channel_buffer(MEM_PP_MEM, IPU_OUTPUT_BUFFER, 0, (void*)mid->addr);
    if(err < 0) {
      printk("mxc_ipu_pp: error setting PP_PP_ROT middle output buffer\n");
      goto err0;
    }
    err = ipu_update_channel_buffer(MEM_ROT_PP_MEM, IPU_INPUT_BUFFER, 0, (void*)mid->addr);
    if(err < 0) {
      printk("mxc_ipu_pp: error setting PP_PP_ROT middle input buffer\n");
      goto err0;
    }
    err = ipu_update_channel_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 0, (void*)out->addr);
    if(err < 0) {
      printk("mxc_ipu_pp: error setting PP_PP_ROT output buffer\n");
      goto err0;
    }
    if(pp_data.ic_combine_en != 0) {
      err = ipu_update_channel_buffer(MEM_PP_MEM, IPU_SEC_INPUT_BUFFER, 0, (void*)in_comb->addr);
      if(err < 0) {
        printk("mxc_ipu_pp: error PP_PP_ROT second input buffer\n");
        goto err0;
      }
      ipu_select_buffer(MEM_PP_MEM, IPU_SEC_INPUT_BUFFER, 0);
    }
    ipu_select_buffer(MEM_PP_MEM, IPU_INPUT_BUFFER, 0);
    ipu_select_buffer(MEM_PP_MEM, IPU_OUTPUT_BUFFER, 0);
    ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 0);
  }
  else if(pp_data.mode == PP_ROT) {
    err = ipu_update_channel_buffer(MEM_ROT_PP_MEM, IPU_INPUT_BUFFER, 0, (void*)in->addr);
    if(err < 0) {
      printk("mxc_ipu_pp: error setting PP_ROT input buffer\n");
      goto err0;
    }
    err = ipu_update_channel_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 0, (void*)out->addr);
    if(err < 0) {
      printk("mxc_ipu_pp: error setting PP_ROT output buffer\n");
      goto err0;
    }
    ipu_select_buffer(MEM_ROT_PP_MEM, IPU_INPUT_BUFFER, 0);
    ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 0);
  }

  if(!pp_data.pp_enabled) {
    pp_data.pp_enabled = 1;
    if(pp_data.mode == PP_PP)
      ipu_enable_channel(MEM_PP_MEM);
    else if(pp_data.mode == PP_PP_ROT) {
      ipu_enable_channel(MEM_PP_MEM);
      ipu_enable_channel(MEM_ROT_PP_MEM);
    }
    else if(pp_data.mode == PP_ROT) {
      ipu_enable_channel(MEM_ROT_PP_MEM);
    }
  }

  FUNC_END;
  return 0;
err0:
  return err;
}