Esempio n. 1
0
/**
 * ispresizer_config_datapath - Specifies which input to use in resizer module
 * @input: Indicates the module that gives the image to resizer.
 *
 * Sets up the default resizer configuration according to the arguments.
 *
 * Returns 0 if successful, or -1 if an unsupported input was requested.
 **/
int ispresizer_config_datapath(enum ispresizer_input input)
{
	u32 cnt = 0;
	DPRINTK_ISPRESZ("ispresizer_config_datapath()+\n");
	ispres_obj.resinput = input;
	switch (input) {
	case RSZ_OTFLY_YUV:
		cnt &= ~ISPRSZ_CNT_INPTYP;
		cnt &= ~ISPRSZ_CNT_INPSRC;
		ispresizer_set_inaddr(0);
		ispresizer_config_inlineoffset(0);
		break;
	case RSZ_MEM_YUV:
		cnt |= ISPRSZ_CNT_INPSRC;
		cnt &= ~ISPRSZ_CNT_INPTYP;
		break;
	case RSZ_MEM_COL8:
		cnt |= ISPRSZ_CNT_INPSRC;
		cnt |= ISPRSZ_CNT_INPTYP;
		break;
	default:
		DPRINTK_ISPRESZ( "ISP_ERR : Wrong Input\n");
		return -1;
	}
	isp_reg_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, cnt);
	//ispresizer_config_ycpos(0);
	ispresizer_config_ycpos(1);
	ispresizer_config_filter_coef(&ispreszdefcoef);
	ispresizer_enable_cbilin(0);
	ispresizer_config_luma_enhance(&ispreszdefaultyenh);
	DPRINTK_ISPRESZ("ispresizer_config_datapath()-\n");
	return 0;
}
/**
 * ispresizer_config_datapath - Specifies which input to use in resizer module
 * @input: Indicates the module that gives the image to resizer.
 *
 * Sets up the default resizer configuration according to the arguments.
 *
 * Returns 0 if successful, or -EINVAL if an unsupported input was requested.
 **/
int ispresizer_config_datapath(enum ispresizer_input input)
{
	u32 cnt = 0;
	DPRINTK_ISPRESZ("ispresizer_config_datapath()+\n");
	ispres_obj.resinput = input;
	switch (input) {
	case RSZ_OTFLY_YUV:
		cnt &= ~ISPRSZ_CNT_INPTYP;
		cnt &= ~ISPRSZ_CNT_INPSRC;
		ispresizer_set_inaddr(0);
		ispresizer_config_inlineoffset(0);
		break;
	case RSZ_MEM_YUV:
		cnt |= ISPRSZ_CNT_INPSRC;
		cnt &= ~ISPRSZ_CNT_INPTYP;
		break;
	case RSZ_MEM_COL8:
		cnt |= ISPRSZ_CNT_INPSRC;
		cnt |= ISPRSZ_CNT_INPTYP;
		break;
	default:
		printk(KERN_ERR "ISP_ERR : Wrong Input\n");
		return -EINVAL;
	}
	isp_reg_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, cnt);

	/* Use bilinear interpolation for upsampling per TRM */
	if (ispres_obj.outputwidth > ispres_obj.inputwidth)
		ispresizer_enable_cbilin(1);
	else
		ispresizer_enable_cbilin(0);

	ispresizer_config_ycpos(0);
	ispresizer_config_filter_coef(&ispreszdefcoef);
	ispresizer_config_luma_enhance(&ispreszdefaultyenh);
	DPRINTK_ISPRESZ("ispresizer_config_datapath()-\n");
	return 0;
}
/**
 * ispresizer_config_size - Configures input and output image size.
 * @input_w: input width for the resizer in number of pixels per line.
 * @input_h: input height for the resizer in number of lines.
 * @output_w: output width from the resizer in number of pixels per line.
 * @output_h: output height for the resizer in number of lines.
 *
 * Configures the appropriate values stored in the isp_res structure in the
 * resizer registers.
 *
 * Returns 0 if successful, or -EINVAL if passed values haven't been verified
 * with ispresizer_try_size() previously.
 **/
int ispresizer_config_size(u32 input_w, u32 input_h, u32 output_w,
			   u32 output_h)
{
	int i, j;
	u32 res;
	DPRINTK_ISPRESZ("ispresizer_config_size()+, input_w = %d,input_h ="
			" %d, output_w = %d, output_h"
			" = %d,hresz = %d,vresz = %d,"
			" hcrop = %d, vcrop = %d,"
			" hstph = %d, vstph = %d\n",
			ispres_obj.inputwidth,
			ispres_obj.inputheight,
			ispres_obj.outputwidth,
			ispres_obj.outputheight,
			ispres_obj.h_resz,
			ispres_obj.v_resz,
			ispres_obj.ipwd_crop,
			ispres_obj.ipht_crop,
			ispres_obj.h_startphase,
			ispres_obj.v_startphase);
	if ((output_w != ispres_obj.outputwidth)
	    || (output_h != ispres_obj.outputheight)) {
		printk(KERN_ERR "Output parameters passed do not match the"
		       " values calculated by the"
		       " trysize passed w %d, h %d"
		       " \n", output_w , output_h);
		return -EINVAL;
	}

	/* Set Resizer input address and offset adderss */
	ispresizer_config_inlineoffset(isp_reg_readl(OMAP3_ISP_IOMEM_PREV,
						     ISPPRV_WADD_OFFSET));

	res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
		~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK);
	isp_reg_writel(res |
		       (ispres_obj.h_startphase << ISPRSZ_CNT_HSTPH_SHIFT) |
		       (ispres_obj.v_startphase << ISPRSZ_CNT_VSTPH_SHIFT),
		       OMAP3_ISP_IOMEM_RESZ,
		       ISPRSZ_CNT);

	/* Set start address for cropping */
	isp_reg_writel(ispres_obj.tmp_buf + isp_get_buf_offset(),
		       OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);

	/*
	isp_reg_writel(
		((ispres_obj.ipwd_crop & 15) << ISPRSZ_IN_START_HORZ_ST_SHIFT) |
		(0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT),
		OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START);
	*/

	isp_reg_writel((0x00 << ISPRSZ_IN_START_HORZ_ST_SHIFT) |
		       (0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT),
		       OMAP3_ISP_IOMEM_RESZ,
		       ISPRSZ_IN_START);

	isp_reg_writel((ispres_obj.inputwidth << ISPRSZ_IN_SIZE_HORZ_SHIFT) |
		       (ispres_obj.inputheight <<
			ISPRSZ_IN_SIZE_VERT_SHIFT),
		       OMAP3_ISP_IOMEM_RESZ,
		       ISPRSZ_IN_SIZE);
	if (!ispres_obj.algo) {
		isp_reg_writel((output_w << ISPRSZ_OUT_SIZE_HORZ_SHIFT) |
			       (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT),
			       OMAP3_ISP_IOMEM_RESZ,
			       ISPRSZ_OUT_SIZE);
	} else {
		isp_reg_writel(((output_w - 4) << ISPRSZ_OUT_SIZE_HORZ_SHIFT) |
			       (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT),
			       OMAP3_ISP_IOMEM_RESZ,
			       ISPRSZ_OUT_SIZE);
	}

	res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
		~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK);
	isp_reg_writel(res |
		       ((ispres_obj.h_resz - 1) << ISPRSZ_CNT_HRSZ_SHIFT) |
		       ((ispres_obj.v_resz - 1) << ISPRSZ_CNT_VRSZ_SHIFT),
		       OMAP3_ISP_IOMEM_RESZ,
		       ISPRSZ_CNT);

/* write filter coefficients  */
/* why not call isp_write_filter_coefs() ? */
	if (ispres_obj.h_resz <= MID_RESIZE_VALUE) {
		j = 0;
		for (i = 0; i < 16; i++) {
			isp_reg_writel(
				(ispres_obj.coeflist.h_filter_coef_4tap[j]
				 << ISPRSZ_HFILT10_COEF0_SHIFT) |
				(ispres_obj.coeflist.h_filter_coef_4tap[j + 1]
				 << ISPRSZ_HFILT10_COEF1_SHIFT),
				OMAP3_ISP_IOMEM_RESZ,
				ISPRSZ_HFILT10 + (i * 0x04));
			j += 2;
		}
	} else {
		j = 0;
		for (i = 0; i < 16; i++) {
			if ((i + 1) % 4 == 0) {
				isp_reg_writel((ispres_obj.coeflist.
						h_filter_coef_7tap[j] <<
						ISPRSZ_HFILT10_COEF0_SHIFT),
					       OMAP3_ISP_IOMEM_RESZ,
					       ISPRSZ_HFILT10 + (i * 0x04));
				j += 1;
			} else {
				isp_reg_writel((ispres_obj.coeflist.
						h_filter_coef_7tap[j] <<
						ISPRSZ_HFILT10_COEF0_SHIFT) |
					       (ispres_obj.coeflist.
						h_filter_coef_7tap[j+1] <<
						ISPRSZ_HFILT10_COEF1_SHIFT),
					       OMAP3_ISP_IOMEM_RESZ,
					       ISPRSZ_HFILT10 + (i * 0x04));
				j += 2;
			}
		}
	}
	if (ispres_obj.v_resz <= MID_RESIZE_VALUE) {
		j = 0;
		for (i = 0; i < 16; i++) {
			isp_reg_writel((ispres_obj.coeflist.
					v_filter_coef_4tap[j] <<
					ISPRSZ_VFILT10_COEF0_SHIFT) |
				       (ispres_obj.coeflist.
					v_filter_coef_4tap[j + 1] <<
					ISPRSZ_VFILT10_COEF1_SHIFT),
				       OMAP3_ISP_IOMEM_RESZ,
				       ISPRSZ_VFILT10 + (i * 0x04));
			j += 2;
		}
	} else {
		j = 0;
		for (i = 0; i < 16; i++) {
			if ((i + 1) % 4 == 0) {
				isp_reg_writel((ispres_obj.coeflist.
						v_filter_coef_7tap[j] <<
						ISPRSZ_VFILT10_COEF0_SHIFT),
					       OMAP3_ISP_IOMEM_RESZ,
					       ISPRSZ_VFILT10 + (i * 0x04));
				j += 1;
			} else {
				isp_reg_writel((ispres_obj.coeflist.
						v_filter_coef_7tap[j] <<
						ISPRSZ_VFILT10_COEF0_SHIFT) |
					       (ispres_obj.coeflist.
						v_filter_coef_7tap[j+1] <<
						ISPRSZ_VFILT10_COEF1_SHIFT),
					       OMAP3_ISP_IOMEM_RESZ,
					       ISPRSZ_VFILT10 + (i * 0x04));
				j += 2;
			}
		}
	}

	ispresizer_config_outlineoffset(output_w*2);
	DPRINTK_ISPRESZ("ispresizer_config_size()-\n");
	return 0;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}