Lines Matching +full:656 +full:- +full:4
1 // SPDX-License-Identifier: GPL-2.0-only
5 * TI OMAP3 ISP - CCDC module
7 * Copyright (C) 2009-2010 Nokia Corporation
18 #include <linux/dma-mapping.h>
22 #include <media/v4l2-event.h>
57 * ccdc_print_status - Print current CCDC Module register values.
63 dev_dbg(isp->dev, "###CCDC " #name "=0x%08x\n", \
70 dev_dbg(isp->dev, "-------------CCDC Register dump-------------\n"); in ccdc_print_status()
106 dev_dbg(isp->dev, "--------------------------------------------\n"); in ccdc_print_status()
110 * omap3isp_ccdc_busy - Get busy state of the CCDC.
121 /* -----------------------------------------------------------------------------
126 * ccdc_lsc_validate_config - Check that LSC configuration is valid.
130 * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
142 paxel_shift_x = lsc_cfg->gain_mode_m; in ccdc_lsc_validate_config()
143 paxel_shift_y = lsc_cfg->gain_mode_n; in ccdc_lsc_validate_config()
147 dev_dbg(isp->dev, "CCDC: LSC: Invalid paxel size\n"); in ccdc_lsc_validate_config()
148 return -EINVAL; in ccdc_lsc_validate_config()
151 if (lsc_cfg->offset & 3) { in ccdc_lsc_validate_config()
152 dev_dbg(isp->dev, in ccdc_lsc_validate_config()
153 "CCDC: LSC: Offset must be a multiple of 4\n"); in ccdc_lsc_validate_config()
154 return -EINVAL; in ccdc_lsc_validate_config()
157 if ((lsc_cfg->initial_x & 1) || (lsc_cfg->initial_y & 1)) { in ccdc_lsc_validate_config()
158 dev_dbg(isp->dev, "CCDC: LSC: initial_x and y must be even\n"); in ccdc_lsc_validate_config()
159 return -EINVAL; in ccdc_lsc_validate_config()
164 input_width = format->width; in ccdc_lsc_validate_config()
165 input_height = format->height; in ccdc_lsc_validate_config()
169 min_width = ((input_width + lsc_cfg->initial_x + paxel_width - 1) in ccdc_lsc_validate_config()
173 min_height = ((input_height + lsc_cfg->initial_y + paxel_height - 1) in ccdc_lsc_validate_config()
176 min_size = 4 * min_width * min_height; in ccdc_lsc_validate_config()
177 if (min_size > lsc_cfg->size) { in ccdc_lsc_validate_config()
178 dev_dbg(isp->dev, "CCDC: LSC: too small table\n"); in ccdc_lsc_validate_config()
179 return -EINVAL; in ccdc_lsc_validate_config()
181 if (lsc_cfg->offset < (min_width * 4)) { in ccdc_lsc_validate_config()
182 dev_dbg(isp->dev, "CCDC: LSC: Offset is too small\n"); in ccdc_lsc_validate_config()
183 return -EINVAL; in ccdc_lsc_validate_config()
185 if ((lsc_cfg->size / lsc_cfg->offset) < min_height) { in ccdc_lsc_validate_config()
186 dev_dbg(isp->dev, "CCDC: LSC: Wrong size/offset combination\n"); in ccdc_lsc_validate_config()
187 return -EINVAL; in ccdc_lsc_validate_config()
193 * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
204 * ccdc_lsc_setup_regs - Configures the lens shading compensation module
213 isp_reg_writel(isp, cfg->offset, OMAP3_ISP_IOMEM_CCDC, in ccdc_lsc_setup_regs()
217 reg |= cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT; in ccdc_lsc_setup_regs()
218 reg |= cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT; in ccdc_lsc_setup_regs()
219 reg |= cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT; in ccdc_lsc_setup_regs()
224 reg |= cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT; in ccdc_lsc_setup_regs()
226 reg |= cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT; in ccdc_lsc_setup_regs()
252 return -ETIMEDOUT; in ccdc_lsc_wait_prefetch()
256 * __ccdc_lsc_enable - Enables/Disables the Lens Shading Compensation module.
267 if ((format->code != MEDIA_BUS_FMT_SGRBG10_1X10) && in __ccdc_lsc_enable()
268 (format->code != MEDIA_BUS_FMT_SRGGB10_1X10) && in __ccdc_lsc_enable()
269 (format->code != MEDIA_BUS_FMT_SBGGR10_1X10) && in __ccdc_lsc_enable()
270 (format->code != MEDIA_BUS_FMT_SGBRG10_1X10)) in __ccdc_lsc_enable()
271 return -EINVAL; in __ccdc_lsc_enable()
283 ccdc->lsc.state = LSC_STATE_STOPPED; in __ccdc_lsc_enable()
285 return -ETIMEDOUT; in __ccdc_lsc_enable()
287 ccdc->lsc.state = LSC_STATE_RUNNING; in __ccdc_lsc_enable()
289 ccdc->lsc.state = LSC_STATE_STOPPING; in __ccdc_lsc_enable()
304 * __ccdc_lsc_configure - Apply a new configuration to the LSC engine
311 if (!req->enable) in __ccdc_lsc_configure()
312 return -EINVAL; in __ccdc_lsc_configure()
314 if (ccdc_lsc_validate_config(ccdc, &req->config) < 0) { in __ccdc_lsc_configure()
316 return -EINVAL; in __ccdc_lsc_configure()
320 return -EBUSY; in __ccdc_lsc_configure()
322 ccdc_lsc_setup_regs(ccdc, &req->config); in __ccdc_lsc_configure()
323 ccdc_lsc_program_table(ccdc, req->table.dma); in __ccdc_lsc_configure()
328 * ccdc_lsc_error_handler - Handle LSC prefetch error scenario.
347 ccdc->lsc.state = LSC_STATE_STOPPED; in ccdc_lsc_error_handler()
358 if (req->table.addr) { in ccdc_lsc_free_request()
359 sg_free_table(&req->table.sgt); in ccdc_lsc_free_request()
360 dma_free_coherent(isp->dev, req->config.size, req->table.addr, in ccdc_lsc_free_request()
361 req->table.dma); in ccdc_lsc_free_request()
373 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_lsc_free_queue()
375 list_del(&req->list); in ccdc_lsc_free_queue()
376 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_lsc_free_queue()
378 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_lsc_free_queue()
380 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_lsc_free_queue()
391 ccdc_lsc_free_queue(ccdc, &lsc->free_queue); in ccdc_lsc_free_table_work()
395 * ccdc_lsc_config - Configure the LSC module from a userspace request
410 update = config->update & in ccdc_lsc_config()
419 return -EINVAL; in ccdc_lsc_config()
424 return -ENOMEM; in ccdc_lsc_config()
426 if (config->flag & OMAP3ISP_CCDC_CONFIG_LSC) { in ccdc_lsc_config()
427 if (copy_from_user(&req->config, config->lsc_cfg, in ccdc_lsc_config()
428 sizeof(req->config))) { in ccdc_lsc_config()
429 ret = -EFAULT; in ccdc_lsc_config()
433 req->enable = 1; in ccdc_lsc_config()
435 req->table.addr = dma_alloc_coherent(isp->dev, req->config.size, in ccdc_lsc_config()
436 &req->table.dma, in ccdc_lsc_config()
438 if (req->table.addr == NULL) { in ccdc_lsc_config()
439 ret = -ENOMEM; in ccdc_lsc_config()
443 ret = dma_get_sgtable(isp->dev, &req->table.sgt, in ccdc_lsc_config()
444 req->table.addr, req->table.dma, in ccdc_lsc_config()
445 req->config.size); in ccdc_lsc_config()
449 dma_sync_sg_for_cpu(isp->dev, req->table.sgt.sgl, in ccdc_lsc_config()
450 req->table.sgt.nents, DMA_TO_DEVICE); in ccdc_lsc_config()
452 if (copy_from_user(req->table.addr, config->lsc, in ccdc_lsc_config()
453 req->config.size)) { in ccdc_lsc_config()
454 ret = -EFAULT; in ccdc_lsc_config()
458 dma_sync_sg_for_device(isp->dev, req->table.sgt.sgl, in ccdc_lsc_config()
459 req->table.sgt.nents, DMA_TO_DEVICE); in ccdc_lsc_config()
462 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_lsc_config()
463 if (ccdc->lsc.request) { in ccdc_lsc_config()
464 list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue); in ccdc_lsc_config()
465 schedule_work(&ccdc->lsc.table_work); in ccdc_lsc_config()
467 ccdc->lsc.request = req; in ccdc_lsc_config()
468 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_lsc_config()
484 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_lsc_is_configured()
485 ret = ccdc->lsc.active != NULL; in ccdc_lsc_is_configured()
486 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_lsc_is_configured()
493 struct ispccdc_lsc *lsc = &ccdc->lsc; in ccdc_lsc_enable()
495 if (lsc->state != LSC_STATE_STOPPED) in ccdc_lsc_enable()
496 return -EINVAL; in ccdc_lsc_enable()
498 if (lsc->active) { in ccdc_lsc_enable()
499 list_add_tail(&lsc->active->list, &lsc->free_queue); in ccdc_lsc_enable()
500 lsc->active = NULL; in ccdc_lsc_enable()
503 if (__ccdc_lsc_configure(ccdc, lsc->request) < 0) { in ccdc_lsc_enable()
506 list_add_tail(&lsc->request->list, &lsc->free_queue); in ccdc_lsc_enable()
507 lsc->request = NULL; in ccdc_lsc_enable()
511 lsc->active = lsc->request; in ccdc_lsc_enable()
512 lsc->request = NULL; in ccdc_lsc_enable()
516 if (!list_empty(&lsc->free_queue)) in ccdc_lsc_enable()
517 schedule_work(&lsc->table_work); in ccdc_lsc_enable()
522 /* -----------------------------------------------------------------------------
527 * ccdc_configure_clamp - Configure optical-black or digital clamping
530 * The CCDC performs either optical-black or digital clamp. Configure and enable
538 if (ccdc->obclamp) { in ccdc_configure_clamp()
539 clamp = ccdc->clamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT; in ccdc_configure_clamp()
540 clamp |= ccdc->clamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT; in ccdc_configure_clamp()
541 clamp |= ccdc->clamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT; in ccdc_configure_clamp()
542 clamp |= ccdc->clamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT; in ccdc_configure_clamp()
545 isp_reg_writel(isp, ccdc->clamp.dcsubval, in ccdc_configure_clamp()
551 ccdc->obclamp ? ISPCCDC_CLAMP_CLAMPEN : 0); in ccdc_configure_clamp()
555 * ccdc_configure_fpc - Configure Faulty Pixel Correction
564 if (!ccdc->fpc_en) in ccdc_configure_fpc()
567 isp_reg_writel(isp, ccdc->fpc.dma, OMAP3_ISP_IOMEM_CCDC, in ccdc_configure_fpc()
570 isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT), in ccdc_configure_fpc()
572 isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT) | in ccdc_configure_fpc()
577 * ccdc_configure_black_comp - Configure Black Level Compensation.
585 blcomp = ccdc->blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT; in ccdc_configure_black_comp()
586 blcomp |= ccdc->blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT; in ccdc_configure_black_comp()
587 blcomp |= ccdc->blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT; in ccdc_configure_black_comp()
588 blcomp |= ccdc->blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT; in ccdc_configure_black_comp()
594 * ccdc_configure_lpf - Configure Low-Pass Filter (LPF).
603 ccdc->lpf ? ISPCCDC_SYN_MODE_LPF : 0); in ccdc_configure_lpf()
607 * ccdc_configure_alaw - Configure A-law compression.
616 info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code); in ccdc_configure_alaw()
618 switch (info->width) { in ccdc_configure_alaw()
636 if (ccdc->alaw) in ccdc_configure_alaw()
643 * ccdc_config_imgattr - Configure sensor image specific attributes.
655 * ccdc_config - Set CCDC configuration from userspace
659 * Returns 0 if successful, -EINVAL if the pointer to the configuration
669 spin_lock_irqsave(&ccdc->lock, flags); in ccdc_config()
670 ccdc->shadow_update = 1; in ccdc_config()
671 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_config()
673 if (OMAP3ISP_CCDC_ALAW & ccdc_struct->update) { in ccdc_config()
674 ccdc->alaw = !!(OMAP3ISP_CCDC_ALAW & ccdc_struct->flag); in ccdc_config()
675 ccdc->update |= OMAP3ISP_CCDC_ALAW; in ccdc_config()
678 if (OMAP3ISP_CCDC_LPF & ccdc_struct->update) { in ccdc_config()
679 ccdc->lpf = !!(OMAP3ISP_CCDC_LPF & ccdc_struct->flag); in ccdc_config()
680 ccdc->update |= OMAP3ISP_CCDC_LPF; in ccdc_config()
683 if (OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->update) { in ccdc_config()
684 if (copy_from_user(&ccdc->clamp, ccdc_struct->bclamp, in ccdc_config()
685 sizeof(ccdc->clamp))) { in ccdc_config()
686 ccdc->shadow_update = 0; in ccdc_config()
687 return -EFAULT; in ccdc_config()
690 ccdc->obclamp = !!(OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->flag); in ccdc_config()
691 ccdc->update |= OMAP3ISP_CCDC_BLCLAMP; in ccdc_config()
694 if (OMAP3ISP_CCDC_BCOMP & ccdc_struct->update) { in ccdc_config()
695 if (copy_from_user(&ccdc->blcomp, ccdc_struct->blcomp, in ccdc_config()
696 sizeof(ccdc->blcomp))) { in ccdc_config()
697 ccdc->shadow_update = 0; in ccdc_config()
698 return -EFAULT; in ccdc_config()
701 ccdc->update |= OMAP3ISP_CCDC_BCOMP; in ccdc_config()
704 ccdc->shadow_update = 0; in ccdc_config()
706 if (OMAP3ISP_CCDC_FPC & ccdc_struct->update) { in ccdc_config()
712 if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED) in ccdc_config()
713 return -EBUSY; in ccdc_config()
715 ccdc->fpc_en = !!(OMAP3ISP_CCDC_FPC & ccdc_struct->flag); in ccdc_config()
717 if (ccdc->fpc_en) { in ccdc_config()
718 if (copy_from_user(&fpc, ccdc_struct->fpc, sizeof(fpc))) in ccdc_config()
719 return -EFAULT; in ccdc_config()
721 size = fpc.fpnum * 4; in ccdc_config()
724 * The table address must be 64-bytes aligned, which is in ccdc_config()
728 fpc_new.addr = dma_alloc_coherent(isp->dev, size, in ccdc_config()
732 return -ENOMEM; in ccdc_config()
737 dma_free_coherent(isp->dev, size, fpc_new.addr, in ccdc_config()
739 return -EFAULT; in ccdc_config()
742 fpc_old = ccdc->fpc; in ccdc_config()
743 ccdc->fpc = fpc_new; in ccdc_config()
749 dma_free_coherent(isp->dev, fpc_old.fpnum * 4, in ccdc_config()
758 if (ccdc->update & OMAP3ISP_CCDC_ALAW) { in ccdc_apply_controls()
760 ccdc->update &= ~OMAP3ISP_CCDC_ALAW; in ccdc_apply_controls()
763 if (ccdc->update & OMAP3ISP_CCDC_LPF) { in ccdc_apply_controls()
765 ccdc->update &= ~OMAP3ISP_CCDC_LPF; in ccdc_apply_controls()
768 if (ccdc->update & OMAP3ISP_CCDC_BLCLAMP) { in ccdc_apply_controls()
770 ccdc->update &= ~OMAP3ISP_CCDC_BLCLAMP; in ccdc_apply_controls()
773 if (ccdc->update & OMAP3ISP_CCDC_BCOMP) { in ccdc_apply_controls()
775 ccdc->update &= ~OMAP3ISP_CCDC_BCOMP; in ccdc_apply_controls()
780 * omap3isp_ccdc_restore_context - Restore values of the CCDC module registers
785 struct isp_ccdc_device *ccdc = &isp->isp_ccdc; in omap3isp_ccdc_restore_context()
789 ccdc->update = OMAP3ISP_CCDC_ALAW | OMAP3ISP_CCDC_LPF in omap3isp_ccdc_restore_context()
795 /* -----------------------------------------------------------------------------
796 * Format- and pipeline-related configuration helpers
800 * ccdc_config_vp - Configure the Video Port.
805 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); in ccdc_config_vp()
809 unsigned long l3_ick = pipe->l3_ick; in ccdc_config_vp()
810 unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8; in ccdc_config_vp()
814 format = &ccdc->formats[CCDC_PAD_SOURCE_VP]; in ccdc_config_vp()
816 if (!format->code) { in ccdc_config_vp()
825 (format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT), in ccdc_config_vp()
828 ((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT), in ccdc_config_vp()
831 isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) | in ccdc_config_vp()
832 (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT), in ccdc_config_vp()
835 info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code); in ccdc_config_vp()
837 switch (info->width) { in ccdc_config_vp()
853 if (pipe->input) in ccdc_config_vp()
854 div = DIV_ROUND_UP(l3_ick, pipe->max_rate); in ccdc_config_vp()
855 else if (pipe->external_rate) in ccdc_config_vp()
856 div = l3_ick / pipe->external_rate; in ccdc_config_vp()
859 fmtcfg |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT; in ccdc_config_vp()
865 * ccdc_config_outlineoffset - Configure memory saving output line offset
872 * - The horizontal line offset is defined as the number of bytes between the
876 * - The field offset value is defined as the number of lines to offset the
879 * - The line offset values are defined as the number of lines (as defined by
915 * ccdc_set_outaddr - Set memory address to save output image
917 * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
929 * omap3isp_ccdc_max_rate - Calculate maximum input data rate based on the input
938 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); in omap3isp_ccdc_max_rate()
948 if (ccdc->input == CCDC_INPUT_PARALLEL) in omap3isp_ccdc_max_rate()
949 rate = pipe->l3_ick / 2 * 9 / 10; in omap3isp_ccdc_max_rate()
951 rate = pipe->l3_ick / 2; in omap3isp_ccdc_max_rate()
957 * ccdc_config_sync_if - Set CCDC sync interface configuration
970 format = &ccdc->formats[CCDC_PAD_SINK]; in ccdc_config_sync_if()
972 if (format->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_config_sync_if()
973 format->code == MEDIA_BUS_FMT_UYVY8_2X8) { in ccdc_config_sync_if()
975 * mode, enabling BT.656 mode should take precedence. However, in ccdc_config_sync_if()
977 * seems to be required in BT.656 mode. In SYNC mode set it to in ccdc_config_sync_if()
980 if (ccdc->bt656) in ccdc_config_sync_if()
1001 if (parcfg && parcfg->data_pol) in ccdc_config_sync_if()
1004 if (parcfg && parcfg->hs_pol) in ccdc_config_sync_if()
1007 /* The polarity of the vertical sync signal output by the BT.656 in ccdc_config_sync_if()
1010 if ((parcfg && parcfg->vs_pol) || ccdc->bt656) in ccdc_config_sync_if()
1013 if (parcfg && parcfg->fld_pol) in ccdc_config_sync_if()
1021 if (format->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_config_sync_if()
1028 /* Enable or disable BT.656 mode, including error correction for the in ccdc_config_sync_if()
1031 if (ccdc->bt656) in ccdc_config_sync_if()
1135 ccdc->bt656 = false; in ccdc_configure()
1136 ccdc->fields = 0; in ccdc_configure()
1138 pad = media_pad_remote_pad_first(&ccdc->pads[CCDC_PAD_SINK]); in ccdc_configure()
1139 sensor = media_entity_to_v4l2_subdev(pad->entity); in ccdc_configure()
1140 if (ccdc->input == CCDC_INPUT_PARALLEL) { in ccdc_configure()
1142 to_isp_pipeline(&ccdc->subdev.entity)->external; in ccdc_configure()
1149 parcfg = &bus_cfg->bus.parallel; in ccdc_configure()
1150 ccdc->bt656 = parcfg->bt656; in ccdc_configure()
1154 format = &ccdc->formats[CCDC_PAD_SINK]; in ccdc_configure()
1157 * input format is a non-BT.656 YUV variant. in ccdc_configure()
1159 fmt_src.pad = pad->index; in ccdc_configure()
1162 depth_in = fmt_info->width; in ccdc_configure()
1165 fmt_info = omap3isp_video_format_info(format->code); in ccdc_configure()
1166 depth_out = fmt_info->width; in ccdc_configure()
1167 shift = depth_in - depth_out; in ccdc_configure()
1169 if (ccdc->bt656) in ccdc_configure()
1171 else if (fmt_info->code == MEDIA_BUS_FMT_YUYV8_2X8) in ccdc_configure()
1173 else if (fmt_info->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_configure()
1178 omap3isp_configure_bridge(isp, ccdc->input, parcfg, shift, bridge); in ccdc_configure()
1190 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_configure()
1195 if (ccdc->output & CCDC_OUTPUT_RESIZER) in ccdc_configure()
1201 switch (format->code) { in ccdc_configure()
1224 isp_reg_writel(isp, ((format->height - 2) << ISPCCDC_VDINT_0_SHIFT) | in ccdc_configure()
1225 ((format->height * 2 / 3) << ISPCCDC_VDINT_1_SHIFT), in ccdc_configure()
1229 format = &ccdc->formats[CCDC_PAD_SOURCE_OF]; in ccdc_configure()
1230 crop = &ccdc->crop; in ccdc_configure()
1233 * need two cycles per pixel in BT.656 mode, and one cycle per pixel in in ccdc_configure()
1237 if (ccdc->bt656) { in ccdc_configure()
1238 sph = crop->left * 2; in ccdc_configure()
1239 nph = crop->width * 2 - 1; in ccdc_configure()
1241 sph = crop->left; in ccdc_configure()
1242 nph = crop->width - 1; in ccdc_configure()
1248 isp_reg_writel(isp, (crop->top << ISPCCDC_VERT_START_SLV0_SHIFT) | in ccdc_configure()
1249 (crop->top << ISPCCDC_VERT_START_SLV1_SHIFT), in ccdc_configure()
1251 isp_reg_writel(isp, (crop->height - 1) in ccdc_configure()
1255 ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, in ccdc_configure()
1256 format->field); in ccdc_configure()
1262 if (ccdc->formats[CCDC_PAD_SINK].field == V4L2_FIELD_ALTERNATE && in ccdc_configure()
1263 (format->field == V4L2_FIELD_INTERLACED_TB || in ccdc_configure()
1264 format->field == V4L2_FIELD_INTERLACED_BT)) in ccdc_configure()
1270 if (format->code == MEDIA_BUS_FMT_YUYV8_1X16) in ccdc_configure()
1277 /* Use PACK8 mode for 1byte per pixel formats. Check for BT.656 mode in ccdc_configure()
1281 if (omap3isp_video_format_info(format->code)->width <= 8 || ccdc->bt656) in ccdc_configure()
1292 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_configure()
1293 if (ccdc->lsc.request == NULL) in ccdc_configure()
1296 WARN_ON(ccdc->lsc.active); in ccdc_configure()
1301 if (ccdc->lsc.active == NULL && in ccdc_configure()
1302 __ccdc_lsc_configure(ccdc, ccdc->lsc.request) == 0) { in ccdc_configure()
1303 ccdc->lsc.active = ccdc->lsc.request; in ccdc_configure()
1305 list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue); in ccdc_configure()
1306 schedule_work(&ccdc->lsc.table_work); in ccdc_configure()
1309 ccdc->lsc.request = NULL; in ccdc_configure()
1312 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_configure()
1322 if (enable && ccdc->stopping & CCDC_STOP_REQUEST) in __ccdc_enable()
1328 ccdc->running = enable; in __ccdc_enable()
1336 spin_lock_irqsave(&ccdc->lock, flags); in ccdc_disable()
1337 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS) in ccdc_disable()
1338 ccdc->stopping = CCDC_STOP_REQUEST; in ccdc_disable()
1339 if (!ccdc->running) in ccdc_disable()
1340 ccdc->stopping = CCDC_STOP_FINISHED; in ccdc_disable()
1341 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_disable()
1343 ret = wait_event_timeout(ccdc->wait, in ccdc_disable()
1344 ccdc->stopping == CCDC_STOP_FINISHED, in ccdc_disable()
1347 ret = -ETIMEDOUT; in ccdc_disable()
1353 mutex_lock(&ccdc->ioctl_lock); in ccdc_disable()
1354 ccdc_lsc_free_request(ccdc, ccdc->lsc.request); in ccdc_disable()
1355 ccdc->lsc.request = ccdc->lsc.active; in ccdc_disable()
1356 ccdc->lsc.active = NULL; in ccdc_disable()
1357 cancel_work_sync(&ccdc->lsc.table_work); in ccdc_disable()
1358 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue); in ccdc_disable()
1359 mutex_unlock(&ccdc->ioctl_lock); in ccdc_disable()
1361 ccdc->stopping = CCDC_STOP_NOT_REQUESTED; in ccdc_disable()
1373 /* -----------------------------------------------------------------------------
1378 * ccdc_sbl_busy - Poll idle state of CCDC and related SBL memory write bits
1400 * ccdc_sbl_wait_idle - Wait until the CCDC and related SBL are idle
1420 return -EBUSY; in ccdc_sbl_wait_idle()
1423 /* ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
1434 switch ((ccdc->stopping & 3) | event) { in ccdc_handle_stopping()
1436 if (ccdc->lsc.state != LSC_STATE_STOPPED) in ccdc_handle_stopping()
1439 ccdc->stopping = CCDC_STOP_EXECUTED; in ccdc_handle_stopping()
1443 ccdc->stopping |= CCDC_STOP_CCDC_FINISHED; in ccdc_handle_stopping()
1444 if (ccdc->lsc.state == LSC_STATE_STOPPED) in ccdc_handle_stopping()
1445 ccdc->stopping |= CCDC_STOP_LSC_FINISHED; in ccdc_handle_stopping()
1450 ccdc->stopping |= CCDC_STOP_LSC_FINISHED; in ccdc_handle_stopping()
1458 if (ccdc->stopping == CCDC_STOP_FINISHED) { in ccdc_handle_stopping()
1459 wake_up(&ccdc->wait); in ccdc_handle_stopping()
1468 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); in ccdc_hs_vs_isr()
1469 struct video_device *vdev = ccdc->subdev.devnode; in ccdc_hs_vs_isr()
1473 atomic_inc(&pipe->frame_number); in ccdc_hs_vs_isr()
1477 event.u.frame_sync.frame_sequence = atomic_read(&pipe->frame_number); in ccdc_hs_vs_isr()
1483 * ccdc_lsc_isr - Handle LSC events
1493 to_isp_pipeline(&ccdc->subdev.entity); in ccdc_lsc_isr()
1496 pipe->error = true; in ccdc_lsc_isr()
1507 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_lsc_isr()
1509 if (ccdc->lsc.state == LSC_STATE_STOPPING) in ccdc_lsc_isr()
1510 ccdc->lsc.state = LSC_STATE_STOPPED; in ccdc_lsc_isr()
1515 if (ccdc->lsc.state != LSC_STATE_RECONFIG) in ccdc_lsc_isr()
1519 ccdc->lsc.state = LSC_STATE_STOPPED; in ccdc_lsc_isr()
1531 if (ccdc->lsc.request == NULL) in ccdc_lsc_isr()
1537 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_lsc_isr()
1546 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); in ccdc_has_all_fields()
1548 enum v4l2_field of_field = ccdc->formats[CCDC_PAD_SOURCE_OF].field; in ccdc_has_all_fields()
1564 pipe->field = field; in ccdc_has_all_fields()
1569 ccdc->fields |= field == V4L2_FIELD_BOTTOM in ccdc_has_all_fields()
1572 if (ccdc->fields != CCDC_FIELD_BOTH) in ccdc_has_all_fields()
1583 ccdc->fields = 0; in ccdc_has_all_fields()
1590 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); in ccdc_isr_buffer()
1600 if (list_empty(&ccdc->video_out.dmaqueue)) in ccdc_isr_buffer()
1604 * buffer underrun. Re-enable them now that we have a buffer. The buffer in ccdc_isr_buffer()
1607 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && ccdc->underrun) { in ccdc_isr_buffer()
1608 ccdc->underrun = 0; in ccdc_isr_buffer()
1614 dev_info(isp->dev, "CCDC won't become idle!\n"); in ccdc_isr_buffer()
1615 media_entity_enum_set(&isp->crashed, &ccdc->subdev.entity); in ccdc_isr_buffer()
1621 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && in ccdc_isr_buffer()
1622 ccdc->stopping & CCDC_STOP_REQUEST) in ccdc_isr_buffer()
1628 buffer = omap3isp_video_buffer_next(&ccdc->video_out); in ccdc_isr_buffer()
1630 ccdc_set_outaddr(ccdc, buffer->dma); in ccdc_isr_buffer()
1632 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; in ccdc_isr_buffer()
1634 if (ccdc->state == ISP_PIPELINE_STREAM_SINGLESHOT && in ccdc_isr_buffer()
1643 * ccdc_vd0_isr - Handle VD0 event
1653 /* In BT.656 mode the CCDC doesn't generate an HS/VS interrupt. We thus in ccdc_vd0_isr()
1656 if (ccdc->bt656) { in ccdc_vd0_isr()
1658 to_isp_pipeline(&ccdc->subdev.entity); in ccdc_vd0_isr()
1660 atomic_inc(&pipe->frame_number); in ccdc_vd0_isr()
1663 /* Emulate a VD1 interrupt for BT.656 mode, as we can't stop the CCDC in in ccdc_vd0_isr()
1667 if (ccdc->bt656) { in ccdc_vd0_isr()
1668 spin_lock_irqsave(&ccdc->lock, flags); in ccdc_vd0_isr()
1669 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && in ccdc_vd0_isr()
1670 ccdc->output & CCDC_OUTPUT_MEMORY) { in ccdc_vd0_isr()
1671 if (ccdc->lsc.state != LSC_STATE_STOPPED) in ccdc_vd0_isr()
1676 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_vd0_isr()
1679 spin_lock_irqsave(&ccdc->lock, flags); in ccdc_vd0_isr()
1681 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_vd0_isr()
1685 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_vd0_isr()
1688 if (!ccdc->shadow_update) in ccdc_vd0_isr()
1690 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_vd0_isr()
1697 * ccdc_vd1_isr - Handle VD1 event
1704 /* In BT.656 mode the synchronization signals are generated by the CCDC in ccdc_vd1_isr()
1711 * interrupt handler instead for BT.656. in ccdc_vd1_isr()
1713 if (ccdc->bt656) in ccdc_vd1_isr()
1716 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_vd1_isr()
1728 switch (ccdc->state) { in ccdc_vd1_isr()
1730 ccdc->stopping = CCDC_STOP_REQUEST; in ccdc_vd1_isr()
1734 if (ccdc->output & CCDC_OUTPUT_MEMORY) { in ccdc_vd1_isr()
1735 if (ccdc->lsc.state != LSC_STATE_STOPPED) in ccdc_vd1_isr()
1748 if (ccdc->lsc.request == NULL) in ccdc_vd1_isr()
1755 if (ccdc->lsc.state == LSC_STATE_RUNNING) { in ccdc_vd1_isr()
1757 ccdc->lsc.state = LSC_STATE_RECONFIG; in ccdc_vd1_isr()
1762 if (ccdc->lsc.state == LSC_STATE_STOPPED) in ccdc_vd1_isr()
1766 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_vd1_isr()
1770 * omap3isp_ccdc_isr - Configure CCDC during interframe time.
1776 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) in omap3isp_ccdc_isr()
1793 /* -----------------------------------------------------------------------------
1799 struct isp_ccdc_device *ccdc = &video->isp->isp_ccdc; in ccdc_video_queue()
1803 if (!(ccdc->output & CCDC_OUTPUT_MEMORY)) in ccdc_video_queue()
1804 return -ENODEV; in ccdc_video_queue()
1806 ccdc_set_outaddr(ccdc, buffer->dma); in ccdc_video_queue()
1810 * starting the stream) in external sync mode, or immediately in BT.656 in ccdc_video_queue()
1814 spin_lock_irqsave(&ccdc->lock, flags); in ccdc_video_queue()
1815 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && !ccdc->running && in ccdc_video_queue()
1816 ccdc->bt656) in ccdc_video_queue()
1819 ccdc->underrun = 1; in ccdc_video_queue()
1820 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_video_queue()
1832 /* -----------------------------------------------------------------------------
1837 * ccdc_ioctl - CCDC module private ioctl's
1851 mutex_lock(&ccdc->ioctl_lock); in ccdc_ioctl()
1853 mutex_unlock(&ccdc->ioctl_lock); in ccdc_ioctl()
1857 return -ENOIOCTLCMD; in ccdc_ioctl()
1866 if (sub->type != V4L2_EVENT_FRAME_SYNC) in ccdc_subscribe_event()
1867 return -EINVAL; in ccdc_subscribe_event()
1870 if (sub->id != 0) in ccdc_subscribe_event()
1871 return -EINVAL; in ccdc_subscribe_event()
1883 * ccdc_set_stream - Enable/Disable streaming on the CCDC module
1900 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) { in ccdc_set_stream()
1915 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_set_stream()
1918 if (ccdc->underrun || !(ccdc->output & CCDC_OUTPUT_MEMORY)) in ccdc_set_stream()
1921 ccdc->underrun = 0; in ccdc_set_stream()
1925 if (ccdc->output & CCDC_OUTPUT_MEMORY && in ccdc_set_stream()
1926 ccdc->state != ISP_PIPELINE_STREAM_SINGLESHOT) in ccdc_set_stream()
1934 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_set_stream()
1937 ccdc->underrun = 0; in ccdc_set_stream()
1941 ccdc->state = enable; in ccdc_set_stream()
1951 return v4l2_subdev_get_try_format(&ccdc->subdev, sd_state, in __ccdc_get_format()
1954 return &ccdc->formats[pad]; in __ccdc_get_format()
1963 return v4l2_subdev_get_try_crop(&ccdc->subdev, sd_state, in __ccdc_get_crop()
1966 return &ccdc->crop; in __ccdc_get_crop()
1970 * ccdc_try_format - Try video format on a pad
1984 unsigned int width = fmt->width; in ccdc_try_format()
1985 unsigned int height = fmt->height; in ccdc_try_format()
1993 if (fmt->code == ccdc_fmts[i]) in ccdc_try_format()
1999 fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; in ccdc_try_format()
2002 fmt->width = clamp_t(u32, width, 32, 4096); in ccdc_try_format()
2003 fmt->height = clamp_t(u32, height, 32, 4096); in ccdc_try_format()
2006 if (fmt->field == V4L2_FIELD_ANY) in ccdc_try_format()
2007 fmt->field = V4L2_FIELD_NONE; in ccdc_try_format()
2012 pixelcode = fmt->code; in ccdc_try_format()
2013 field = fmt->field; in ccdc_try_format()
2018 * 1X16. In BT.656 no such conversion occurs. As we don't know in ccdc_try_format()
2019 * at this point whether the source will use SYNC or BT.656 mode in ccdc_try_format()
2021 * configured to pack bytes in BT.656, hiding the inaccuracy. in ccdc_try_format()
2024 if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_try_format()
2025 fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) { in ccdc_try_format()
2031 fmt->code = pixelcode; in ccdc_try_format()
2033 if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8) in ccdc_try_format()
2034 fmt->code = MEDIA_BUS_FMT_YUYV8_1X16; in ccdc_try_format()
2035 else if (fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_try_format()
2036 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; in ccdc_try_format()
2041 fmt->width = crop->width; in ccdc_try_format()
2042 fmt->height = crop->height; in ccdc_try_format()
2047 if (fmt->field == V4L2_FIELD_ALTERNATE && in ccdc_try_format()
2050 fmt->field = field; in ccdc_try_format()
2051 fmt->height *= 2; in ccdc_try_format()
2061 info = omap3isp_video_format_info(fmt->code); in ccdc_try_format()
2062 fmt->code = info->truncated; in ccdc_try_format()
2065 if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_try_format()
2066 fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_try_format()
2067 fmt->code = 0; in ccdc_try_format()
2073 fmt->width = clamp_t(u32, width, 32, fmt->width); in ccdc_try_format()
2074 fmt->height = clamp_t(u32, height, 32, fmt->height - 1); in ccdc_try_format()
2078 /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is in ccdc_try_format()
2081 fmt->colorspace = V4L2_COLORSPACE_SRGB; in ccdc_try_format()
2085 * ccdc_try_crop - Validate a crop rectangle
2100 info = omap3isp_video_format_info(sink->code); in ccdc_try_crop()
2101 if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) { in ccdc_try_crop()
2102 crop->left &= ~1; in ccdc_try_crop()
2103 crop->top &= ~1; in ccdc_try_crop()
2106 crop->left = clamp_t(u32, crop->left, 0, sink->width - CCDC_MIN_WIDTH); in ccdc_try_crop()
2107 crop->top = clamp_t(u32, crop->top, 0, sink->height - CCDC_MIN_HEIGHT); in ccdc_try_crop()
2114 max_width = (sink->width - crop->left + 15) & ~15; in ccdc_try_crop()
2115 crop->width = clamp_t(u32, crop->width, CCDC_MIN_WIDTH, max_width) in ccdc_try_crop()
2117 crop->height = clamp_t(u32, crop->height, CCDC_MIN_HEIGHT, in ccdc_try_crop()
2118 sink->height - crop->top); in ccdc_try_crop()
2121 if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) { in ccdc_try_crop()
2122 crop->width &= ~1; in ccdc_try_crop()
2123 crop->height &= ~1; in ccdc_try_crop()
2128 * ccdc_enum_mbus_code - Handle pixel format enumeration
2132 * return -EINVAL or zero on success
2141 switch (code->pad) { in ccdc_enum_mbus_code()
2143 if (code->index >= ARRAY_SIZE(ccdc_fmts)) in ccdc_enum_mbus_code()
2144 return -EINVAL; in ccdc_enum_mbus_code()
2146 code->code = ccdc_fmts[code->index]; in ccdc_enum_mbus_code()
2150 format = __ccdc_get_format(ccdc, sd_state, code->pad, in ccdc_enum_mbus_code()
2151 code->which); in ccdc_enum_mbus_code()
2153 if (format->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_enum_mbus_code()
2154 format->code == MEDIA_BUS_FMT_UYVY8_2X8) { in ccdc_enum_mbus_code()
2156 if (code->index == 0) in ccdc_enum_mbus_code()
2157 code->code = MEDIA_BUS_FMT_YUYV8_1X16; in ccdc_enum_mbus_code()
2158 else if (code->index == 1) in ccdc_enum_mbus_code()
2159 code->code = MEDIA_BUS_FMT_UYVY8_1X16; in ccdc_enum_mbus_code()
2161 return -EINVAL; in ccdc_enum_mbus_code()
2166 if (code->index == 0) in ccdc_enum_mbus_code()
2167 code->code = format->code; in ccdc_enum_mbus_code()
2169 return -EINVAL; in ccdc_enum_mbus_code()
2178 if (code->index != 0) in ccdc_enum_mbus_code()
2179 return -EINVAL; in ccdc_enum_mbus_code()
2181 format = __ccdc_get_format(ccdc, sd_state, code->pad, in ccdc_enum_mbus_code()
2182 code->which); in ccdc_enum_mbus_code()
2187 if (format->code == 0) in ccdc_enum_mbus_code()
2188 return -EINVAL; in ccdc_enum_mbus_code()
2190 code->code = format->code; in ccdc_enum_mbus_code()
2194 return -EINVAL; in ccdc_enum_mbus_code()
2207 if (fse->index != 0) in ccdc_enum_frame_size()
2208 return -EINVAL; in ccdc_enum_frame_size()
2210 format.code = fse->code; in ccdc_enum_frame_size()
2213 ccdc_try_format(ccdc, sd_state, fse->pad, &format, fse->which); in ccdc_enum_frame_size()
2214 fse->min_width = format.width; in ccdc_enum_frame_size()
2215 fse->min_height = format.height; in ccdc_enum_frame_size()
2217 if (format.code != fse->code) in ccdc_enum_frame_size()
2218 return -EINVAL; in ccdc_enum_frame_size()
2220 format.code = fse->code; in ccdc_enum_frame_size()
2221 format.width = -1; in ccdc_enum_frame_size()
2222 format.height = -1; in ccdc_enum_frame_size()
2223 ccdc_try_format(ccdc, sd_state, fse->pad, &format, fse->which); in ccdc_enum_frame_size()
2224 fse->max_width = format.width; in ccdc_enum_frame_size()
2225 fse->max_height = format.height; in ccdc_enum_frame_size()
2231 * ccdc_get_selection - Retrieve a selection rectangle on a pad
2248 if (sel->pad != CCDC_PAD_SOURCE_OF) in ccdc_get_selection()
2249 return -EINVAL; in ccdc_get_selection()
2251 switch (sel->target) { in ccdc_get_selection()
2253 sel->r.left = 0; in ccdc_get_selection()
2254 sel->r.top = 0; in ccdc_get_selection()
2255 sel->r.width = INT_MAX; in ccdc_get_selection()
2256 sel->r.height = INT_MAX; in ccdc_get_selection()
2259 sel->which); in ccdc_get_selection()
2260 ccdc_try_crop(ccdc, format, &sel->r); in ccdc_get_selection()
2264 sel->r = *__ccdc_get_crop(ccdc, sd_state, sel->which); in ccdc_get_selection()
2268 return -EINVAL; in ccdc_get_selection()
2275 * ccdc_set_selection - Set a selection rectangle on a pad
2292 if (sel->target != V4L2_SEL_TGT_CROP || in ccdc_set_selection()
2293 sel->pad != CCDC_PAD_SOURCE_OF) in ccdc_set_selection()
2294 return -EINVAL; in ccdc_set_selection()
2297 if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED) in ccdc_set_selection()
2298 return -EBUSY; in ccdc_set_selection()
2304 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) { in ccdc_set_selection()
2305 sel->r = *__ccdc_get_crop(ccdc, sd_state, sel->which); in ccdc_set_selection()
2309 format = __ccdc_get_format(ccdc, sd_state, CCDC_PAD_SINK, sel->which); in ccdc_set_selection()
2310 ccdc_try_crop(ccdc, format, &sel->r); in ccdc_set_selection()
2311 *__ccdc_get_crop(ccdc, sd_state, sel->which) = sel->r; in ccdc_set_selection()
2315 sel->which); in ccdc_set_selection()
2317 sel->which); in ccdc_set_selection()
2323 * ccdc_get_format - Retrieve the video format on a pad
2328 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
2338 format = __ccdc_get_format(ccdc, sd_state, fmt->pad, fmt->which); in ccdc_get_format()
2340 return -EINVAL; in ccdc_get_format()
2342 fmt->format = *format; in ccdc_get_format()
2347 * ccdc_set_format - Set the video format on a pad
2352 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
2363 format = __ccdc_get_format(ccdc, sd_state, fmt->pad, fmt->which); in ccdc_set_format()
2365 return -EINVAL; in ccdc_set_format()
2367 ccdc_try_format(ccdc, sd_state, fmt->pad, &fmt->format, fmt->which); in ccdc_set_format()
2368 *format = fmt->format; in ccdc_set_format()
2371 if (fmt->pad == CCDC_PAD_SINK) { in ccdc_set_format()
2373 crop = __ccdc_get_crop(ccdc, sd_state, fmt->which); in ccdc_set_format()
2374 crop->left = 0; in ccdc_set_format()
2375 crop->top = 0; in ccdc_set_format()
2376 crop->width = fmt->format.width; in ccdc_set_format()
2377 crop->height = fmt->format.height; in ccdc_set_format()
2379 ccdc_try_crop(ccdc, &fmt->format, crop); in ccdc_set_format()
2383 fmt->which); in ccdc_set_format()
2384 *format = fmt->format; in ccdc_set_format()
2386 fmt->which); in ccdc_set_format()
2389 fmt->which); in ccdc_set_format()
2390 *format = fmt->format; in ccdc_set_format()
2392 fmt->which); in ccdc_set_format()
2418 if ((in_info->flavor == 0) || (out_info->flavor == 0)) in ccdc_is_shiftable()
2421 if (in_info->flavor != out_info->flavor) in ccdc_is_shiftable()
2424 return in_info->width - out_info->width + additional_shift <= 6; in ccdc_is_shiftable()
2436 if (source_fmt->format.width != sink_fmt->format.width || in ccdc_link_validate()
2437 source_fmt->format.height != sink_fmt->format.height) in ccdc_link_validate()
2438 return -EPIPE; in ccdc_link_validate()
2441 if (ccdc->input == CCDC_INPUT_PARALLEL) { in ccdc_link_validate()
2443 media_entity_to_v4l2_subdev(link->source->entity); in ccdc_link_validate()
2448 return -EPIPE; in ccdc_link_validate()
2450 parallel_shift = bus_cfg->bus.parallel.data_lane_shift; in ccdc_link_validate()
2456 if (!ccdc_is_shiftable(source_fmt->format.code, in ccdc_link_validate()
2457 sink_fmt->format.code, parallel_shift)) in ccdc_link_validate()
2458 return -EPIPE; in ccdc_link_validate()
2464 * ccdc_init_formats - Initialize formats on all pads
2482 ccdc_set_format(sd, fh ? fh->state : NULL, &format); in ccdc_init_formats()
2522 /* -----------------------------------------------------------------------------
2527 * ccdc_link_setup - Setup CCDC connections
2533 * return -EINVAL or zero on success
2542 unsigned int index = local->index; in ccdc_link_setup()
2545 if (is_media_entity_v4l2_subdev(remote->entity)) in ccdc_link_setup()
2554 ccdc->input = CCDC_INPUT_NONE; in ccdc_link_setup()
2558 if (ccdc->input != CCDC_INPUT_NONE) in ccdc_link_setup()
2559 return -EBUSY; in ccdc_link_setup()
2561 if (remote->entity == &isp->isp_ccp2.subdev.entity) in ccdc_link_setup()
2562 ccdc->input = CCDC_INPUT_CCP2B; in ccdc_link_setup()
2563 else if (remote->entity == &isp->isp_csi2a.subdev.entity) in ccdc_link_setup()
2564 ccdc->input = CCDC_INPUT_CSI2A; in ccdc_link_setup()
2565 else if (remote->entity == &isp->isp_csi2c.subdev.entity) in ccdc_link_setup()
2566 ccdc->input = CCDC_INPUT_CSI2C; in ccdc_link_setup()
2568 ccdc->input = CCDC_INPUT_PARALLEL; in ccdc_link_setup()
2574 * Revisit this when it will be implemented, and return -EBUSY for now. in ccdc_link_setup()
2582 if (ccdc->output & ~CCDC_OUTPUT_PREVIEW) in ccdc_link_setup()
2583 return -EBUSY; in ccdc_link_setup()
2584 ccdc->output |= CCDC_OUTPUT_PREVIEW; in ccdc_link_setup()
2586 ccdc->output &= ~CCDC_OUTPUT_PREVIEW; in ccdc_link_setup()
2593 if (ccdc->output & ~CCDC_OUTPUT_MEMORY) in ccdc_link_setup()
2594 return -EBUSY; in ccdc_link_setup()
2595 ccdc->output |= CCDC_OUTPUT_MEMORY; in ccdc_link_setup()
2597 ccdc->output &= ~CCDC_OUTPUT_MEMORY; in ccdc_link_setup()
2604 if (ccdc->output & ~CCDC_OUTPUT_RESIZER) in ccdc_link_setup()
2605 return -EBUSY; in ccdc_link_setup()
2606 ccdc->output |= CCDC_OUTPUT_RESIZER; in ccdc_link_setup()
2608 ccdc->output &= ~CCDC_OUTPUT_RESIZER; in ccdc_link_setup()
2613 return -EINVAL; in ccdc_link_setup()
2627 v4l2_device_unregister_subdev(&ccdc->subdev); in omap3isp_ccdc_unregister_entities()
2628 omap3isp_video_unregister(&ccdc->video_out); in omap3isp_ccdc_unregister_entities()
2637 ccdc->subdev.dev = vdev->mdev->dev; in omap3isp_ccdc_register_entities()
2638 ret = v4l2_device_register_subdev(vdev, &ccdc->subdev); in omap3isp_ccdc_register_entities()
2642 ret = omap3isp_video_register(&ccdc->video_out, vdev); in omap3isp_ccdc_register_entities()
2653 /* -----------------------------------------------------------------------------
2658 * ccdc_init_entities - Initialize V4L2 subdev and media entity
2665 struct v4l2_subdev *sd = &ccdc->subdev; in ccdc_init_entities()
2666 struct media_pad *pads = ccdc->pads; in ccdc_init_entities()
2667 struct media_entity *me = &sd->entity; in ccdc_init_entities()
2670 ccdc->input = CCDC_INPUT_NONE; in ccdc_init_entities()
2673 sd->internal_ops = &ccdc_v4l2_internal_ops; in ccdc_init_entities()
2674 strscpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name)); in ccdc_init_entities()
2675 sd->grp_id = 1 << 16; /* group ID for isp subdevs */ in ccdc_init_entities()
2677 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; in ccdc_init_entities()
2684 me->ops = &ccdc_media_ops; in ccdc_init_entities()
2691 ccdc->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in ccdc_init_entities()
2692 ccdc->video_out.ops = &ccdc_video_ops; in ccdc_init_entities()
2693 ccdc->video_out.isp = to_isp_device(ccdc); in ccdc_init_entities()
2694 ccdc->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; in ccdc_init_entities()
2695 ccdc->video_out.bpl_alignment = 32; in ccdc_init_entities()
2697 ret = omap3isp_video_init(&ccdc->video_out, "CCDC"); in ccdc_init_entities()
2709 * omap3isp_ccdc_init - CCDC module initialization.
2718 struct isp_ccdc_device *ccdc = &isp->isp_ccdc; in omap3isp_ccdc_init()
2721 spin_lock_init(&ccdc->lock); in omap3isp_ccdc_init()
2722 init_waitqueue_head(&ccdc->wait); in omap3isp_ccdc_init()
2723 mutex_init(&ccdc->ioctl_lock); in omap3isp_ccdc_init()
2725 ccdc->stopping = CCDC_STOP_NOT_REQUESTED; in omap3isp_ccdc_init()
2727 INIT_WORK(&ccdc->lsc.table_work, ccdc_lsc_free_table_work); in omap3isp_ccdc_init()
2728 ccdc->lsc.state = LSC_STATE_STOPPED; in omap3isp_ccdc_init()
2729 INIT_LIST_HEAD(&ccdc->lsc.free_queue); in omap3isp_ccdc_init()
2730 spin_lock_init(&ccdc->lsc.req_lock); in omap3isp_ccdc_init()
2732 ccdc->clamp.oblen = 0; in omap3isp_ccdc_init()
2733 ccdc->clamp.dcsubval = 0; in omap3isp_ccdc_init()
2735 ccdc->update = OMAP3ISP_CCDC_BLCLAMP; in omap3isp_ccdc_init()
2740 mutex_destroy(&ccdc->ioctl_lock); in omap3isp_ccdc_init()
2748 * omap3isp_ccdc_cleanup - CCDC module cleanup.
2753 struct isp_ccdc_device *ccdc = &isp->isp_ccdc; in omap3isp_ccdc_cleanup()
2755 omap3isp_video_cleanup(&ccdc->video_out); in omap3isp_ccdc_cleanup()
2756 media_entity_cleanup(&ccdc->subdev.entity); in omap3isp_ccdc_cleanup()
2761 ccdc_lsc_free_request(ccdc, ccdc->lsc.request); in omap3isp_ccdc_cleanup()
2762 cancel_work_sync(&ccdc->lsc.table_work); in omap3isp_ccdc_cleanup()
2763 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue); in omap3isp_ccdc_cleanup()
2765 if (ccdc->fpc.addr != NULL) in omap3isp_ccdc_cleanup()
2766 dma_free_coherent(isp->dev, ccdc->fpc.fpnum * 4, ccdc->fpc.addr, in omap3isp_ccdc_cleanup()
2767 ccdc->fpc.dma); in omap3isp_ccdc_cleanup()
2769 mutex_destroy(&ccdc->ioctl_lock); in omap3isp_ccdc_cleanup()