Exemplo n.º 1
0
int __isp_af_enable(int enable)
{
	unsigned int pcr;

	pcr = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);

	/* Set AF_EN bit in PCR Register */
	if (enable) {
		if (isp_set_callback(CBK_H3A_AF_DONE, isp_af_isr,
				     (void *)NULL, (void *)NULL)) {
			printk(KERN_ERR "No callback for AF\n");
			return -EINVAL;
		}

		pcr |= AF_EN;
	} else {
		isp_unset_callback(CBK_H3A_AF_DONE);
		pcr &= ~AF_EN;
	}
	isp_reg_writel(pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
	return 0;
}
Exemplo n.º 2
0
/**
 * prev_do_preview - Performs the Preview process
 * @device: Structure containing ISP preview wrapper global information
 * @arg: Currently not used
 *
 * Returns 0 if successful, or -EINVAL if the sent parameters are invalid.
 **/
static int prev_do_preview(struct prev_device *device, int *arg)
{
    int bpp, size;
    int ret = 0;
    u32 out_hsize, out_vsize, out_line_offset;

    dev_dbg(prev_dev, "prev_do_preview E\n");

    if (!device) {
        dev_err(prev_dev, "preview: invalid parameters\n");
        return -EINVAL;
    }

    previewer_set_isp_ctrl();

    if (device->params->size_params.pixsize == PREV_INWIDTH_8BIT)
        bpp = 1;
    else
        bpp = 2;

    size = device->params->size_params.hsize *
           device->params->size_params.vsize * bpp;

    isppreview_config_datapath(PRV_RAW_MEM, PREVIEW_MEM);

    isppreview_try_size(device->params->size_params.hsize,
                        device->params->size_params.vsize,
                        &out_hsize,
                        &out_vsize);


    ret = isppreview_config_inlineoffset(device->params->size_params.hsize
                                         * bpp);
    if (ret)
        goto out;

    out_line_offset = (out_hsize * bpp) & PREV_32BYTES_ALIGN_MASK;

    ret = isppreview_config_outlineoffset(out_line_offset);
    if (ret)
        goto out;

    ret = isppreview_config_size(device->params->size_params.hsize,
                                 device->params->size_params.vsize,
                                 out_hsize, out_vsize);

    device->params->drkf_params.addr = device->isp_addr_lsc;

    prev_hw_setup(device->params);

    ret = isppreview_set_inaddr(device->isp_addr_read);
    if (ret)
        goto out;

    ret = isppreview_set_outaddr(device->isp_addr_read);
    if (ret)
        goto out;

    ret = isp_set_callback(CBK_PREV_DONE, preview_isr, (void *)device,
                           (void *)NULL);
    if (ret) {
        dev_err(prev_dev, "ERROR while setting Previewer callback!\n");
        goto out;
    }
    isppreview_enable(1);

    wait_for_completion_interruptible(&device->wfc);

    ret = isp_unset_callback(CBK_PREV_DONE);

    dev_dbg(prev_dev, "prev_do_preview L\n");
out:
    return ret;
}
Exemplo n.º 3
0
/**
 * prev_do_preview - Performs the Preview process
 * @device: Structure containing ISP preview wrapper global information
 * @arg: Currently not used
 *
 * Returns 0 if successful, or -EINVAL if the sent parameters are invalid.
 **/
static int prev_do_preview(struct prev_device *device, int *arg)
{
	u32 out_hsize, out_vsize, out_line_offset, in_line_offset;
	int ret = 0, bpp;

	dev_dbg(prev_dev, "prev_do_preview E\n");

	if (!device) {
		dev_err(prev_dev, "preview: invalid parameters\n");
		return -EINVAL;
	}

	prev_set_isp_ctrl(device->params->features);

	if (device->params->size_params.pixsize == PREV_INWIDTH_8BIT)
		bpp = 1;
	else
		bpp = 2;

 	out_hsize = device->out_hsize;
	out_vsize = device->out_vsize;

	in_line_offset = device->params->size_params.hsize * bpp;

	ret = isppreview_config_inlineoffset(in_line_offset);
	if (ret)
		goto out;

	dev_dbg(prev_dev, "%s: out_pitch %d, output width %d, out_hsize %d, "
						"out_vsize %d\n", __func__,
		device->params->size_params.out_pitch,
		device->params->size_params.out_pitch / bpp,
		out_hsize, out_vsize);

	out_line_offset = (out_hsize * bpp) & PREV_32BYTES_ALIGN_MASK;

	ret = isppreview_config_outlineoffset(out_line_offset);
	if (ret)
		goto out;

	ret = prev_config_size(device->params->size_params.hsize,
					device->params->size_params.vsize);
	if (ret)
		goto out;

	device->params->drkf_params.addr = device->isp_addr_lsc;

	prev_hw_setup(device->params);

	ret = isppreview_set_inaddr(device->isp_addr_read);
	if (ret)
		goto out;

	ret = isppreview_set_outaddr(device->isp_addr_read);
	if (ret)
		goto out;

	ret = isp_set_callback(CBK_PREV_DONE, prev_isr, (void *) device,
							(void *) NULL);
	if (ret) {
		dev_err(prev_dev, "ERROR while setting Previewer callback!\n");
		goto out;
	}

	isppreview_enable(1);
	wait_for_completion_interruptible(&device->wfc);
	isppreview_enable(0);

	ret = isp_unset_callback(CBK_PREV_DONE);

	prev_unset_isp_ctrl();

	dev_dbg(prev_dev, "prev_do_preview L\n");
out:
	return ret;
}
Exemplo n.º 4
0
static int prev2resz_ioc_run_engine(struct prev2resz_fhdl *fh)
{
	struct isp_freq_devider *fdiv;
	int rval;

	rval = isppreview_s_pipeline(fh->isp_prev, &fh->prev);
	if (rval != 0)
		return rval;

	rval = isppreview_set_inaddr(fh->isp_prev, fh->src_buff_addr);
	if (rval != 0)
		return rval;

	rval = isppreview_config_inlineoffset(fh->isp_prev,
				fh->prev.in.image.bytesperline);
	if (rval != 0)
		return rval;

	rval = isppreview_set_outaddr(fh->isp_prev, fh->dst_buff_addr);
	if (rval != 0)
		return rval;

	rval = isppreview_config_features(fh->isp_prev, &fh->isp_prev->params);
	if (rval != 0)
		return rval;

	isppreview_set_size(fh->isp_prev, fh->prev.in.image.width,
			    fh->prev.in.image.height);

	/* Set resizer input and output size */
	rval = ispresizer_s_pipeline(fh->isp_resz, &fh->resz);
	if (rval != 0)
		return rval;

	rval = ispresizer_set_outaddr(fh->isp_resz, fh->dst_buff_addr);
	if (rval != 0)
		return rval;

	isp_configure_interface(fh->isp, &p2r_interface);
	/*
	 * Through-put requirement:
	 * Set max OCP freq for 3630 is 200 MHz through-put
	 * is in KByte/s so 200000 KHz * 4 = 800000 KByte/s
	 */
	omap_pm_set_min_bus_tput(fh->isp, OCP_INITIATOR_AGENT, 800000);

	/* Reduces memory bandwidth */
	fdiv = isp_get_upscale_ratio(fh->pipe.in.image.width,
				     fh->pipe.in.image.height,
				     fh->pipe.out.image.width,
				     fh->pipe.out.image.height);
	dev_dbg(p2r_device, "Set the REQ_EXP register = %d.\n",
		fdiv->prev_exp);
	isp_reg_and_or(fh->isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
		       ~(ISPSBL_SDR_REQ_PRV_EXP_MASK |
		         ISPSBL_SDR_REQ_RSZ_EXP_MASK),
		         fdiv->prev_exp << ISPSBL_SDR_REQ_PRV_EXP_SHIFT);
	isp_start(fh->isp);

	init_completion(&p2r_ctx.resz_complete);
	rval = isp_set_callback(fh->isp, CBK_RESZ_DONE, prev2resz_resz_callback,
			       (void *) NULL, (void *) NULL);
	if (rval) {
		dev_err(p2r_device, "%s: setting resizer callback failed\n",
			__func__);
		return rval;
	}

	ispresizer_enable(fh->isp_resz, 1);
	isppreview_enable(fh->isp_prev, 1);
	rval = wait_for_completion_interruptible_timeout(
			&p2r_ctx.resz_complete, msecs_to_jiffies(1000));
	if (rval == 0)
		dev_crit(p2r_device, "Resizer interrupt timeout exit\n");

	isp_unset_callback(fh->isp, CBK_RESZ_DONE);

	/* Reset Through-put requirement */
	omap_pm_set_min_bus_tput(fh->isp, OCP_INITIATOR_AGENT, -1);

	/* This will flushes the queue */
	if (&fh->src_vbq)
		videobuf_queue_cancel(&fh->src_vbq);
	if (&fh->dst_vbq)
		videobuf_queue_cancel(&fh->dst_vbq);

	return 0;
}
Exemplo n.º 5
0
/** ispdss_begin - Function to be called by DSS when resizing of the input
  * image buffer is needed
  * @slot: buffer index where the input image is stored
  * @output_buffer_index: output buffer index where output of resizer will
  * be stored
  * @out_off: The line size in bytes for output buffer. as most probably
  * this will be VRFB with YUV422 data, it should come 0x2000 as input
  * @out_phy_add: physical address of the start of output memory area for this
  * @in_phy_add: physical address of the start of input memory area for this
  * @in_off:: The line size in bytes for output buffer.
  * ispdss_begin()  takes the input buffer index and output buffer index
  * to start the process of resizing. after resizing is complete,
  * the callback function will be called with the argument.
  * Indexes of the input and output buffers are used so that it is faster
  * and easier to configure the input and output address for the ISP resizer.
  * As per the current implementation, DSS uses six VRFB contexts for rotation.
  * for both input and output buffers index and physical address has been taken
  * as argument. if this buffer is not already mapped to ISP address space we
  * use physical address to map it, otherwise only the index is used.
  **/
int ispdss_begin(struct isp_node *pipe, u32 input_buffer_index,
		 int output_buffer_index, u32 out_off, u32 out_phy_add,
		 u32 in_phy_add, u32 in_off)
{
	unsigned int output_size;
	struct isp_device *isp = dev_get_drvdata(dev_ctx.isp);
	struct isp_res_device *isp_res = &isp->isp_res;
//LGE_CHANGE_S [[email protected]]  2011_04_22, for improve ISP to get 30fps (OMAPS00236923)
	u32 speed_val = 0;
//LGE_CHANGE_E [[email protected]]  2011_04_22, for improve ISP to get 30fps (OMAPS00236923)	

//LGE_CHANGE_S [[email protected]] 2011_07_19 Froyo_to_GB
	struct device *dev = to_device(isp_res);
//LGE_CHANGE_E [[email protected]] 2011_07_19 Froyo_to_GB

	if (output_buffer_index >= dev_ctx.num_video_buffers) {
		dev_err(dev_ctx.isp,
		"ouput buffer index is out of range %d", output_buffer_index);
		return -EINVAL;
	}

	if (dev_ctx.config_state != STATE_CONFIGURED) {
		dev_err(dev_ctx.isp, "State not configured \n");
		return -EINVAL;
	}

	dev_ctx.tmp_buf_size = PAGE_ALIGN(pipe->out.image.bytesperline *
					  pipe->out.image.height);
	ispdss_tmp_buf_alloc(dev_ctx.tmp_buf_size);

	pipe->in.path = RSZ_MEM_YUV;
	if (ispresizer_s_pipeline(isp_res, pipe) != 0)
		return -EINVAL;

	/* If this output buffer has not been mapped till now then map it */
	if (!dev_ctx.out_buf_virt_addr[output_buffer_index]) {
		output_size = pipe->out.image.height * out_off;
		dev_ctx.out_buf_virt_addr[output_buffer_index] =
			iommu_kmap(isp->iommu, 0, out_phy_add, output_size,
				   IOMMU_FLAG);
		if (IS_ERR_VALUE(
			dev_ctx.out_buf_virt_addr[output_buffer_index])) {
			dev_err(dev_ctx.isp, "Mapping of output buffer failed"
						"for index \n");
			return -ENOMEM;
		}
	}

	if (!dev_ctx.in_buf_virt_addr[input_buffer_index]) {
		dev_ctx.in_buf_virt_addr[input_buffer_index] =
			iommu_kmap(isp->iommu, 0, in_phy_add, in_off,
				   IOMMU_FLAG);
		if (IS_ERR_VALUE(
			dev_ctx.in_buf_virt_addr[input_buffer_index])) {
			dev_err(dev_ctx.isp, "Mapping of input buffer failed"
						"for index \n");
			return -ENOMEM;
		}
	}

	if (ispresizer_set_inaddr(isp_res,
				  dev_ctx.in_buf_virt_addr[input_buffer_index],
				  pipe) != 0)
		return -EINVAL;

	if (ispresizer_set_out_offset(isp_res, out_off) != 0)
		return -EINVAL;

	if (ispresizer_set_outaddr(isp_res,
		(u32)dev_ctx.out_buf_virt_addr[output_buffer_index]) != 0)
		return -EINVAL;

	/* Set ISP callback for the resizing complete even */
	if (isp_set_callback(dev_ctx.isp, CBK_RESZ_DONE, ispdss_isr,
			     (void *) NULL, (void *)NULL)) {
		dev_err(dev_ctx.isp, "No callback for RSZR\n");
		return -1;
	}

	/* All settings are done.Enable the resizer */
	init_completion(&dev_ctx.compl_isr);

//LGE_CHANGE_S [[email protected]]  2011_04_22, for improve ISP to get 30fps (OMAPS00236923)
//	isp_start(dev_ctx.isp);
	/* Only for 720p case*/
	if (use_isp_resizer_decoder){
		/*decoder */
		speed_val = 0;

	}else{
		/* encoder */
		speed_val = 8;

	}
//LGE_CHANGE_S [[email protected]] 2011_07_19 Froyo_to_GB
	
	isp_reg_and_or(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
		       ~ISPSBL_SDR_REQ_RSZ_EXP_MASK,
				speed_val << ISPSBL_SDR_REQ_RSZ_EXP_SHIFT);

	isp_start(dev_ctx.isp);
//LGE_CHANGE_E [[email protected]] 2011_07_19 Froyo_to_GB
	ispresizer_enable(isp_res, 1);

	/* Wait for resizing complete event */
	if (wait_for_completion_interruptible_timeout(
				&dev_ctx.compl_isr, msecs_to_jiffies(500)) == 0)
		dev_crit(dev_ctx.isp, "\nTimeout exit from "
			 "wait_for_completion\n");

	/* Unset the ISP callback function */
	isp_unset_callback(dev_ctx.isp, CBK_RESZ_DONE);

	return 0;
}
Exemplo n.º 6
0
int isp_resize_mem_data(struct isp_mem_resize_data *data)
{
	int i;
	int ret = -1;
	struct isp_mem_resize_data *presizer_user = \
		(struct isp_mem_resize_data *)data;
	u32 input_buffer_size, output_buffer_size;
	u32 input_nr_pages, output_nr_pages;
	struct page **input_pages = NULL;
	struct page **output_pages = NULL;
	unsigned long isp_addr_in = 0;
	unsigned long  isp_addr_out = 0;
	struct isp_mem_resize_data resizer_param;
	unsigned long timeout;

	if (presizer_user == NULL) {
		printk(KERN_ERR "ISP_RESZ_ERR : Invalid user data\n");
		return -EINVAL;
	}

	memcpy(&resizer_param, presizer_user, \
		sizeof(struct isp_mem_resize_data));

	DPRINTK_ISPPROC("\nRSZ input(%d-%d) - output(%d-%d)\n",
		resizer_param.input_width,
		resizer_param.input_height,
		resizer_param.output_width,
		resizer_param.output_height);

	DPRINTK_ISPPROC("RSZ start(%d-%d) - end(%d-%d)\n",
		resizer_param.left,
		resizer_param.top,
		resizer_param.crop_width,
		resizer_param.crop_height);

	if (presizer_user->datain == 0 || presizer_user->dataout == 0)
		return -EINVAL;

	ispresizer_enable(0);
	timeout = jiffies + msecs_to_jiffies(200);
	while (ispresizer_busy()) {
		if (time_after(jiffies, timeout))
			return -EINVAL;
		msleep(1);
	}

	ispresizer_save_context();
	ispresizer_free();
	ispresizer_request();

	/* set data path before configuring modules. */
	ispresizer_config_datapath(RSZ_MEM_YUV, 0);

	input_buffer_size = ALIGN_TO(presizer_user->input_width* \
		presizer_user->input_height*2 , 0x100);
	input_pages = map_user_memory_to_kernel(presizer_user->datain,
		input_buffer_size, &input_nr_pages);
	if (input_pages == NULL) {
		ret = -EINVAL;
		printk(KERN_ERR "ISP_RESZ_ERR: memory allocation failed\n");
		goto exit_cleanup;
	}

	output_buffer_size = ALIGN_TO(presizer_user->output_width* \
		presizer_user->output_height*2, 0x1000);
	output_pages = map_user_memory_to_kernel(presizer_user->dataout,
		output_buffer_size, &output_nr_pages);
	if (output_pages == NULL) {
		ret = -EINVAL;
		printk(KERN_ERR "ISP_RESZ_ERR: memory allocation failed\n");
		goto exit_cleanup;
	}
	for (i = 0; i < output_nr_pages; ++i)
		flush_dcache_page(output_pages[i]);

	isp_addr_in = ispmmu_vmap_pages(input_pages, input_nr_pages);
	if (IS_ERR((void *)isp_addr_in)) {
		isp_addr_in = 0;
		ret = -EINVAL;
		printk(KERN_ERR "ISP_RESZ_ERR: isp mmu map failed\n");
		goto exit_cleanup;
	}
	isp_addr_out = ispmmu_vmap_pages(output_pages, output_nr_pages);
	if (IS_ERR((void *)isp_addr_out)) {
		isp_addr_out = 0;
		ret = -EINVAL;
		printk(KERN_ERR "ISP_RESZ_ERR:  isp mmu map failed\n");
		goto exit_cleanup;
	}

	if ((resizer_param.left == 0) && (resizer_param.top == 0)) {
		ret = ispresizer_try_size(&resizer_param.input_width,
					&resizer_param.input_height,
					&resizer_param.output_width,
					&resizer_param.output_height);

		ret = ispresizer_config_size(resizer_param.input_width,
					resizer_param.input_height,
					resizer_param.output_width,
					resizer_param.output_height);

		ispresizer_set_inaddr(isp_addr_in);
	} else {
		ispresizer_trycrop(resizer_param.left,
					resizer_param.top,
					resizer_param.crop_width,
					resizer_param.crop_height,
					resizer_param.output_width,
					resizer_param.output_height);

		ispresizer_applycrop();

		/*pixel alignment in 32bit space, vertical must be 0 per TRM */
		isp_reg_writel(((resizer_param.left%16) <<
				ISPRSZ_IN_START_HORZ_ST_SHIFT) |
				(0 <<
				ISPRSZ_IN_START_VERT_ST_SHIFT),
				OMAP3_ISP_IOMEM_RESZ,
				ISPRSZ_IN_START);

		/* Align input address for cropping, per TRM  */
		ispresizer_set_inaddr(isp_addr_in +
			(resizer_param.top*resizer_param.input_width*2)
			+ ((resizer_param.left/16)*32));
	}

	ispresizer_set_inaddr(isp_addr_in);
	ispresizer_set_outaddr(isp_addr_out);
	ispresizer_config_ycpos(0);
	ispresizer_config_inlineoffset(
		ALIGN_TO(presizer_user->input_width*2, 32));

	isp_set_callback(CBK_RESZ_DONE, rsz_isr, (void *) NULL, (void *)NULL);
	isp_reg_writel(0xFFFFFFFF, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
	isp_wfc.done = 0;
	/* start resizer engine. */
	ispresizer_enable(1);

	ret = wait_for_completion_timeout(&isp_wfc, msecs_to_jiffies(1000));
	if (!ret)
		ispresizer_enable(0);

	timeout = jiffies + msecs_to_jiffies(50);
	while (ispresizer_busy()) {
		msleep(5);
		if (time_after(jiffies, timeout)) {
			printk(KERN_ERR "ISP_RESZ_ERR: Resizer still busy");
			break;
		}
	}

	isp_reg_writel(0xFFFFFFFF, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
	isp_unset_callback(CBK_RESZ_DONE);
	ret = 0;

exit_cleanup:
	ispresizer_restore_context();

	if (isp_addr_in != 0)
		ispmmu_vunmap(isp_addr_in);
	if (isp_addr_out != 0)
		ispmmu_vunmap(isp_addr_out);
	if (input_pages != NULL) {
		unmap_user_memory_from_kernel(input_pages, input_nr_pages);
		kfree(input_pages);
	}
	if (output_pages != NULL) {
		unmap_user_memory_from_kernel(output_pages, output_nr_pages);
		kfree(output_pages);
	}

	DPRINTK_ISPPROC("resizer exit.\n");

	return ret;
}
Exemplo n.º 7
0
int isp_process_mem_data(struct isp_mem_data *data)
{
	int i;
	int ret = -1;
	struct isp_mem_data *ppreview_user = \
		(struct isp_mem_data *)data;
	struct isp_mem_data preview_param;
	u32 input_buffer_size, output_buffer_size;
	u32 input_nr_pages, output_nr_pages;
	struct page **input_pages = NULL;
	struct page **output_pages = NULL;
	unsigned long isp_addr_in = 0;
	unsigned long  isp_addr_out = 0;
	unsigned long  isp_addr_tmp = 0;
	unsigned long timeout;
	struct isp_mem_resize_data resizer_param;
	u16 cropadjust = 0;

	if (ppreview_user == NULL) {
		printk(KERN_ERR "ISP_PROC_ERR: Invalid user data!\n");
		return -EINVAL;
	}

	memcpy(&preview_param, ppreview_user, \
		sizeof(struct isp_mem_data));

	DPRINTK_ISPPROC("input(%d-%d) - output(%d-%d)\n",
		preview_param.input_width,
		preview_param.input_height,
		preview_param.output_width,
		preview_param.output_height);

	DPRINTK_ISPPROC("start(%d-%d) - end(%d-%d)\n",
		preview_param.left,
		preview_param.top,
		preview_param.crop_width,
		preview_param.crop_height);

	if (ppreview_user->datain == 0 || ppreview_user->dataout == 0)
		return -EINVAL;

	isppreview_enable(0);
	ispresizer_enable(0);
	timeout = jiffies + msecs_to_jiffies(200);
	while (isppreview_busy() ||
			ispresizer_busy()) {
		if (time_after(jiffies, timeout))
			return -EINVAL;
		msleep(1);
	}

	isppreview_save_context();
	ispresizer_save_context();
	isppreview_free();
	ispresizer_free();
	isppreview_request();
	ispresizer_request();

	/* set data path before configuring modules. */
	isppreview_update_datapath(PRV_RAW_MEM, PREVIEW_MEM);
	ispresizer_config_datapath(RSZ_MEM_YUV, 0);

	ret = isppreview_try_size(preview_param.input_width,
		preview_param.input_height,
		&preview_param.output_width,
		&preview_param.output_height);
	if (ret < 0)
		goto exit_cleanup;
	ret = isppreview_config_size(preview_param.input_width,
		preview_param.input_height,
		preview_param.output_width,
		preview_param.output_height);
	if (ret < 0)
		goto exit_cleanup;

	input_buffer_size = ALIGN_TO(ppreview_user->input_width* \
		ppreview_user->input_height*2 , 0x100);
	input_pages = map_user_memory_to_kernel(preview_param.datain,
		input_buffer_size, &input_nr_pages);
	if (input_pages == NULL) {
		ret = -EINVAL;
		printk(KERN_ERR "ISP_PROC_ERR: memory allocation failed\n");
		goto exit_cleanup;
	}

	output_buffer_size = ALIGN_TO(ppreview_user->output_width* \
		ppreview_user->output_height*2, 0x1000);
	output_pages = map_user_memory_to_kernel(preview_param.dataout,
		output_buffer_size, &output_nr_pages);
	if (output_pages == NULL) {
		ret = -EINVAL;
		printk(KERN_ERR "ISP_PROC_ERR: memory allocation failed\n");
		goto exit_cleanup;
	}
	for (i = 0; i < output_nr_pages; ++i)
		flush_dcache_page(output_pages[i]);

	isp_addr_in = ispmmu_vmap_pages(input_pages, input_nr_pages);
	if (IS_ERR((void *)isp_addr_in)) {
		isp_addr_in = 0;
		ret = -EINVAL;
		printk(KERN_ERR "ISP_PROC_ERR: isp mmu map failed\n");
		goto exit_cleanup;
	}
	isp_addr_out = ispmmu_vmap_pages(output_pages, output_nr_pages);
	if (IS_ERR((void *)isp_addr_out)) {
		isp_addr_out = 0;
		ret = -EINVAL;
		printk(KERN_ERR "ISP_PROC_ERR: isp mmu map failed\n");
		goto exit_cleanup;
	}

	/* This buffer must be allocated and mapped to
		the ISP MMU previously. */
	isp_addr_tmp = isp_tmp_buf_addr();
	if (isp_addr_tmp == 0) {
		printk(KERN_ERR "ISP_PROC_ERR: Invalid isp tmp buffer address!\n");
		goto exit_cleanup;
	}

	isppreview_config_inlineoffset(ppreview_user->input_width * 2);
	isppreview_set_inaddr(isp_addr_in);
	isppreview_set_outaddr(isp_addr_tmp);

	resizer_param.input_width = preview_param.output_width;
	resizer_param.input_height = preview_param.output_height;
	resizer_param.output_width = ppreview_user->output_width;
	resizer_param.output_height = ppreview_user->output_height;

	if ((preview_param.left == 0) && (preview_param.top == 0)) {
		ret = ispresizer_try_size(&resizer_param.input_width,
				&resizer_param.input_height,
				&resizer_param.output_width,
				&resizer_param.output_height);
		if (ret < 0)
			goto exit_cleanup;
		ret = ispresizer_config_size(resizer_param.input_width,
				resizer_param.input_height,
				resizer_param.output_width,
				resizer_param.output_height);
		if (ret < 0)
			goto exit_cleanup;
		ispresizer_set_inaddr(isp_addr_tmp);
	} else {
		ispresizer_trycrop(preview_param.left,
				preview_param.top,
				preview_param.crop_width,
				preview_param.crop_height,
				resizer_param.output_width,
				resizer_param.output_height);

		ispresizer_applycrop();

		/* account for pixel loss when using crop*/
		if ((preview_param.input_height > preview_param.output_height)
				&& (preview_param.top > 16))
			cropadjust = 8;
		else
			cropadjust = 0;

		/* pixel alignment in 32bit space, vertical must be 0 per TRM */
		isp_reg_writel(((preview_param.left%16) <<
					ISPRSZ_IN_START_HORZ_ST_SHIFT) |
					(0 <<
					ISPRSZ_IN_START_VERT_ST_SHIFT),
					OMAP3_ISP_IOMEM_RESZ,
					ISPRSZ_IN_START);

		/* Align input address for cropping, per TRM  */
		ispresizer_set_inaddr(isp_addr_tmp -
				(resizer_param.input_width*2*cropadjust) +
				(preview_param.top*resizer_param.input_width*2)
				+ ((preview_param.left/16)*32));
	}

	ispresizer_set_outaddr(isp_addr_out);
	ispresizer_config_inlineoffset(
		ALIGN_TO(resizer_param.input_width*2, 32));

	if (isp_set_callback(CBK_PREV_DONE, prv_isr,
			(void *) NULL, (void *)NULL) != 0) {
		printk(KERN_ERR "ISP_PROC_ERR: Error setting PRV callback.\n");
		goto exit_cleanup;
	}

	if (isp_set_callback(CBK_RESZ_DONE, rsz_isr,
			(void *) NULL, (void *)NULL) != 0) {
		printk(KERN_ERR "ISP_PROC_ERR: Error setting RSZ callback.\n");
		goto exit_cleanup;
	}

	isp_reg_writel(0xFFFFFFFF, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
	isp_wfc.done = 0;

	/* start preview engine. */
	isppreview_enable(1);

	ret = wait_for_completion_timeout(&isp_wfc, msecs_to_jiffies(1000));
	if (!ret) {
		isppreview_enable(0);
		ispresizer_enable(0);
	}

	timeout = jiffies + msecs_to_jiffies(50);
	while (ispresizer_busy()) {
		msleep(5);
		if (time_after(jiffies, timeout)) {
			printk(KERN_ERR "ISP_RESZ_ERR: Resizer still busy");
			break;
		}
	}

	isp_reg_writel(0xFFFFFFFF, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
	isp_unset_callback(CBK_PREV_DONE);
	isp_unset_callback(CBK_RESZ_DONE);

exit_cleanup:
	isppreview_restore_context();
	ispresizer_restore_context();

	if (isp_addr_in != 0)
		ispmmu_vunmap(isp_addr_in);
	if (isp_addr_out != 0)
		ispmmu_vunmap(isp_addr_out);
	if (input_pages != NULL) {
		unmap_user_memory_from_kernel(input_pages, input_nr_pages);
		kfree(input_pages);
	}
	if (output_pages != NULL) {
		unmap_user_memory_from_kernel(output_pages, output_nr_pages);
		kfree(output_pages);
	}

	DPRINTK_ISPPROC("exit.\n");

	return ret;
}
Exemplo n.º 8
0
/**
 * rsz_start - Enables Resizer Wrapper
 * @arg: Currently not used.
 * @device: Structure containing ISP resizer wrapper global information
 *
 * Submits a resizing task specified by the rsz_resize structure. The call can
 * either be blocked until the task is completed or returned immediately based
 * on the value of the blocking argument in the rsz_resize structure. If it is
 * blocking, the status of the task can be checked by calling ioctl
 * RSZ_G_STATUS. Only one task can be outstanding for each logical channel.
 *
 * Returns 0 if successful, or -EINVAL if could not set callback for RSZR IRQ
 * event or the state of the channel is not configured.
 **/
int rsz_start(int *arg, struct rsz_fh *fh)
{
	struct channel_config *rsz_conf_chan = fh->config;
	struct rsz_mult *multipass = fh->multipass;
	struct videobuf_queue *q = &fh->vbq;
	int ret;

	if (rsz_conf_chan->config_state) {
		dev_err(rsz_device, "State not configured \n");
		goto err_einval;
	}

	rsz_conf_chan->status = CHANNEL_BUSY;

	rsz_hardware_setup(rsz_conf_chan);

	if (isp_set_callback(CBK_RESZ_DONE, rsz_isr, (void *) NULL,
							(void *)NULL)) {
		dev_err(rsz_device, "No callback for RSZR\n");
		goto err_einval;
	}
mult:
	device_config->compl_isr.done = 0;

	ispresizer_enable(1);

	ret = wait_for_completion_interruptible(&device_config->compl_isr);
	if (ret != 0) {
		dev_dbg(rsz_device, "Unexpected exit from "
				"wait_for_completion_interruptible\n");
		wait_for_completion(&device_config->compl_isr);
	}

	if (multipass->active) {
		rsz_set_multipass(multipass, rsz_conf_chan);
		goto mult;
	}

	if (fh->isp_addr_read) {
		ispmmu_unmap(fh->isp_addr_read);
		fh->isp_addr_read = 0;
	}
	if (fh->isp_addr_write) {
		ispmmu_unmap(fh->isp_addr_write);
		fh->isp_addr_write = 0;
	}

	rsz_conf_chan->status = CHANNEL_FREE;
	q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
	q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
	rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
	rsz_conf_chan->register_config.rsz_sdr_inadd = 0;

	/* Unmap and free the DMA memory allocated for buffers */
	videobuf_dma_unmap(q, videobuf_to_dma(
				q->bufs[rsz_conf_chan->input_buf_index]));
	videobuf_dma_unmap(q, videobuf_to_dma(
				q->bufs[rsz_conf_chan->output_buf_index]));
	videobuf_dma_free(videobuf_to_dma(
				q->bufs[rsz_conf_chan->input_buf_index]));
	videobuf_dma_free(videobuf_to_dma(
				q->bufs[rsz_conf_chan->output_buf_index]));

	isp_unset_callback(CBK_RESZ_DONE);

	return 0;
err_einval:
	return -EINVAL;
}