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; }
/** * 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; }
/** * 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; }
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; }
/** 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; }
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; }
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; }
/** * 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; }