Lines Matching +full:field +full:- +full:even +full:- +full:active
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>
56 * ccdc_print_status - Print current CCDC Module register values.
62 dev_dbg(isp->dev, "###CCDC " #name "=0x%08x\n", \
69 dev_dbg(isp->dev, "-------------CCDC Register dump-------------\n"); in ccdc_print_status()
105 dev_dbg(isp->dev, "--------------------------------------------\n"); in ccdc_print_status()
109 * omap3isp_ccdc_busy - Get busy state of the CCDC.
120 /* -----------------------------------------------------------------------------
125 * ccdc_lsc_validate_config - Check that LSC configuration is valid.
129 * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
141 paxel_shift_x = lsc_cfg->gain_mode_m; in ccdc_lsc_validate_config()
142 paxel_shift_y = lsc_cfg->gain_mode_n; in ccdc_lsc_validate_config()
146 dev_dbg(isp->dev, "CCDC: LSC: Invalid paxel size\n"); in ccdc_lsc_validate_config()
147 return -EINVAL; in ccdc_lsc_validate_config()
150 if (lsc_cfg->offset & 3) { in ccdc_lsc_validate_config()
151 dev_dbg(isp->dev, in ccdc_lsc_validate_config()
153 return -EINVAL; in ccdc_lsc_validate_config()
156 if ((lsc_cfg->initial_x & 1) || (lsc_cfg->initial_y & 1)) { in ccdc_lsc_validate_config()
157 dev_dbg(isp->dev, "CCDC: LSC: initial_x and y must be even\n"); in ccdc_lsc_validate_config()
158 return -EINVAL; in ccdc_lsc_validate_config()
163 input_width = format->width; in ccdc_lsc_validate_config()
164 input_height = format->height; in ccdc_lsc_validate_config()
168 min_width = ((input_width + lsc_cfg->initial_x + paxel_width - 1) in ccdc_lsc_validate_config()
172 min_height = ((input_height + lsc_cfg->initial_y + paxel_height - 1) in ccdc_lsc_validate_config()
176 if (min_size > lsc_cfg->size) { in ccdc_lsc_validate_config()
177 dev_dbg(isp->dev, "CCDC: LSC: too small table\n"); in ccdc_lsc_validate_config()
178 return -EINVAL; in ccdc_lsc_validate_config()
180 if (lsc_cfg->offset < (min_width * 4)) { in ccdc_lsc_validate_config()
181 dev_dbg(isp->dev, "CCDC: LSC: Offset is too small\n"); in ccdc_lsc_validate_config()
182 return -EINVAL; in ccdc_lsc_validate_config()
184 if ((lsc_cfg->size / lsc_cfg->offset) < min_height) { in ccdc_lsc_validate_config()
185 dev_dbg(isp->dev, "CCDC: LSC: Wrong size/offset combination\n"); in ccdc_lsc_validate_config()
186 return -EINVAL; in ccdc_lsc_validate_config()
192 * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
203 * ccdc_lsc_setup_regs - Configures the lens shading compensation module
212 isp_reg_writel(isp, cfg->offset, OMAP3_ISP_IOMEM_CCDC, in ccdc_lsc_setup_regs()
216 reg |= cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT; in ccdc_lsc_setup_regs()
217 reg |= cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT; in ccdc_lsc_setup_regs()
218 reg |= cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT; in ccdc_lsc_setup_regs()
223 reg |= cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT; in ccdc_lsc_setup_regs()
225 reg |= cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT; in ccdc_lsc_setup_regs()
251 return -ETIMEDOUT; in ccdc_lsc_wait_prefetch()
255 * __ccdc_lsc_enable - Enables/Disables the Lens Shading Compensation module.
266 if ((format->code != MEDIA_BUS_FMT_SGRBG10_1X10) && in __ccdc_lsc_enable()
267 (format->code != MEDIA_BUS_FMT_SRGGB10_1X10) && in __ccdc_lsc_enable()
268 (format->code != MEDIA_BUS_FMT_SBGGR10_1X10) && in __ccdc_lsc_enable()
269 (format->code != MEDIA_BUS_FMT_SGBRG10_1X10)) in __ccdc_lsc_enable()
270 return -EINVAL; in __ccdc_lsc_enable()
282 ccdc->lsc.state = LSC_STATE_STOPPED; in __ccdc_lsc_enable()
284 return -ETIMEDOUT; in __ccdc_lsc_enable()
286 ccdc->lsc.state = LSC_STATE_RUNNING; in __ccdc_lsc_enable()
288 ccdc->lsc.state = LSC_STATE_STOPPING; in __ccdc_lsc_enable()
302 /* __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()
569 /* The FPNUM field must be set before enabling FPC. */ 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()
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
868 * @field: Field order when storing interlaced formats in memory.
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
877 * start of the field identified by FID = 1. Set it to one.
879 * - The line offset values are defined as the number of lines (as defined by
881 * all combinations of odd/even lines in odd/even fields. When interleaving
886 enum v4l2_field field) in ccdc_config_outlineoffset() argument
894 switch (field) { in ccdc_config_outlineoffset()
897 /* When interleaving fields in memory offset field one by one in ccdc_config_outlineoffset()
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()
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()
1008 * decoder is not documented and seems to be active low. 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()
1031 if (ccdc->bt656) in ccdc_config_sync_if()
1133 ccdc->bt656 = false; in ccdc_configure()
1134 ccdc->fields = 0; in ccdc_configure()
1136 pad = media_entity_remote_pad(&ccdc->pads[CCDC_PAD_SINK]); in ccdc_configure()
1137 sensor = media_entity_to_v4l2_subdev(pad->entity); in ccdc_configure()
1138 if (ccdc->input == CCDC_INPUT_PARALLEL) { in ccdc_configure()
1140 to_isp_pipeline(&ccdc->subdev.entity)->external; in ccdc_configure()
1142 parcfg = &v4l2_subdev_to_bus_cfg(sd)->bus.parallel; in ccdc_configure()
1143 ccdc->bt656 = parcfg->bt656; in ccdc_configure()
1147 format = &ccdc->formats[CCDC_PAD_SINK]; in ccdc_configure()
1150 * input format is a non-BT.656 YUV variant. in ccdc_configure()
1152 fmt_src.pad = pad->index; in ccdc_configure()
1156 depth_in = fmt_info->width; in ccdc_configure()
1159 fmt_info = omap3isp_video_format_info(format->code); in ccdc_configure()
1160 depth_out = fmt_info->width; in ccdc_configure()
1161 shift = depth_in - depth_out; in ccdc_configure()
1163 if (ccdc->bt656) in ccdc_configure()
1165 else if (fmt_info->code == MEDIA_BUS_FMT_YUYV8_2X8) in ccdc_configure()
1167 else if (fmt_info->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_configure()
1172 omap3isp_configure_bridge(isp, ccdc->input, parcfg, shift, bridge); in ccdc_configure()
1184 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_configure()
1189 if (ccdc->output & CCDC_OUTPUT_RESIZER) in ccdc_configure()
1195 switch (format->code) { in ccdc_configure()
1218 isp_reg_writel(isp, ((format->height - 2) << ISPCCDC_VDINT_0_SHIFT) | in ccdc_configure()
1219 ((format->height * 2 / 3) << ISPCCDC_VDINT_1_SHIFT), in ccdc_configure()
1223 format = &ccdc->formats[CCDC_PAD_SOURCE_OF]; in ccdc_configure()
1224 crop = &ccdc->crop; in ccdc_configure()
1231 if (ccdc->bt656) { in ccdc_configure()
1232 sph = crop->left * 2; in ccdc_configure()
1233 nph = crop->width * 2 - 1; in ccdc_configure()
1235 sph = crop->left; in ccdc_configure()
1236 nph = crop->width - 1; in ccdc_configure()
1242 isp_reg_writel(isp, (crop->top << ISPCCDC_VERT_START_SLV0_SHIFT) | in ccdc_configure()
1243 (crop->top << ISPCCDC_VERT_START_SLV1_SHIFT), in ccdc_configure()
1245 isp_reg_writel(isp, (crop->height - 1) in ccdc_configure()
1249 ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, in ccdc_configure()
1250 format->field); in ccdc_configure()
1252 /* When interleaving fields enable processing of the field input signal. in ccdc_configure()
1253 * This will cause the line output control module to apply the field in ccdc_configure()
1254 * offset to field 1. in ccdc_configure()
1256 if (ccdc->formats[CCDC_PAD_SINK].field == V4L2_FIELD_ALTERNATE && in ccdc_configure()
1257 (format->field == V4L2_FIELD_INTERLACED_TB || in ccdc_configure()
1258 format->field == V4L2_FIELD_INTERLACED_BT)) in ccdc_configure()
1264 if (format->code == MEDIA_BUS_FMT_YUYV8_1X16) in ccdc_configure()
1275 if (omap3isp_video_format_info(format->code)->width <= 8 || ccdc->bt656) in ccdc_configure()
1286 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_configure()
1287 if (ccdc->lsc.request == NULL) in ccdc_configure()
1290 WARN_ON(ccdc->lsc.active); in ccdc_configure()
1293 * the current active resolution discard it. in ccdc_configure()
1295 if (ccdc->lsc.active == NULL && in ccdc_configure()
1296 __ccdc_lsc_configure(ccdc, ccdc->lsc.request) == 0) { in ccdc_configure()
1297 ccdc->lsc.active = ccdc->lsc.request; in ccdc_configure()
1299 list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue); in ccdc_configure()
1300 schedule_work(&ccdc->lsc.table_work); in ccdc_configure()
1303 ccdc->lsc.request = NULL; in ccdc_configure()
1306 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_configure()
1316 if (enable && ccdc->stopping & CCDC_STOP_REQUEST) in __ccdc_enable()
1322 ccdc->running = enable; in __ccdc_enable()
1330 spin_lock_irqsave(&ccdc->lock, flags); in ccdc_disable()
1331 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS) in ccdc_disable()
1332 ccdc->stopping = CCDC_STOP_REQUEST; in ccdc_disable()
1333 if (!ccdc->running) in ccdc_disable()
1334 ccdc->stopping = CCDC_STOP_FINISHED; in ccdc_disable()
1335 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_disable()
1337 ret = wait_event_timeout(ccdc->wait, in ccdc_disable()
1338 ccdc->stopping == CCDC_STOP_FINISHED, in ccdc_disable()
1341 ret = -ETIMEDOUT; in ccdc_disable()
1347 mutex_lock(&ccdc->ioctl_lock); in ccdc_disable()
1348 ccdc_lsc_free_request(ccdc, ccdc->lsc.request); in ccdc_disable()
1349 ccdc->lsc.request = ccdc->lsc.active; in ccdc_disable()
1350 ccdc->lsc.active = NULL; in ccdc_disable()
1351 cancel_work_sync(&ccdc->lsc.table_work); in ccdc_disable()
1352 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue); in ccdc_disable()
1353 mutex_unlock(&ccdc->ioctl_lock); in ccdc_disable()
1355 ccdc->stopping = CCDC_STOP_NOT_REQUESTED; in ccdc_disable()
1367 /* -----------------------------------------------------------------------------
1372 * ccdc_sbl_busy - Poll idle state of CCDC and related SBL memory write bits
1394 * ccdc_sbl_wait_idle - Wait until the CCDC and related SBL are idle
1414 return -EBUSY; in ccdc_sbl_wait_idle()
1417 /* ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
1428 switch ((ccdc->stopping & 3) | event) { in ccdc_handle_stopping()
1430 if (ccdc->lsc.state != LSC_STATE_STOPPED) in ccdc_handle_stopping()
1433 ccdc->stopping = CCDC_STOP_EXECUTED; in ccdc_handle_stopping()
1437 ccdc->stopping |= CCDC_STOP_CCDC_FINISHED; in ccdc_handle_stopping()
1438 if (ccdc->lsc.state == LSC_STATE_STOPPED) in ccdc_handle_stopping()
1439 ccdc->stopping |= CCDC_STOP_LSC_FINISHED; in ccdc_handle_stopping()
1444 ccdc->stopping |= CCDC_STOP_LSC_FINISHED; in ccdc_handle_stopping()
1452 if (ccdc->stopping == CCDC_STOP_FINISHED) { in ccdc_handle_stopping()
1453 wake_up(&ccdc->wait); in ccdc_handle_stopping()
1462 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); in ccdc_hs_vs_isr()
1463 struct video_device *vdev = ccdc->subdev.devnode; in ccdc_hs_vs_isr()
1467 atomic_inc(&pipe->frame_number); in ccdc_hs_vs_isr()
1471 event.u.frame_sync.frame_sequence = atomic_read(&pipe->frame_number); in ccdc_hs_vs_isr()
1477 * ccdc_lsc_isr - Handle LSC events
1487 to_isp_pipeline(&ccdc->subdev.entity); in ccdc_lsc_isr()
1490 pipe->error = true; in ccdc_lsc_isr()
1501 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_lsc_isr()
1503 if (ccdc->lsc.state == LSC_STATE_STOPPING) in ccdc_lsc_isr()
1504 ccdc->lsc.state = LSC_STATE_STOPPED; in ccdc_lsc_isr()
1509 if (ccdc->lsc.state != LSC_STATE_RECONFIG) in ccdc_lsc_isr()
1513 ccdc->lsc.state = LSC_STATE_STOPPED; in ccdc_lsc_isr()
1525 if (ccdc->lsc.request == NULL) in ccdc_lsc_isr()
1531 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_lsc_isr()
1540 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); in ccdc_has_all_fields()
1542 enum v4l2_field of_field = ccdc->formats[CCDC_PAD_SOURCE_OF].field; in ccdc_has_all_fields()
1543 enum v4l2_field field; in ccdc_has_all_fields() local
1549 /* Read the current field identifier. */ in ccdc_has_all_fields()
1550 field = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE) in ccdc_has_all_fields()
1554 /* When capturing fields in alternate order just store the current field in ccdc_has_all_fields()
1558 pipe->field = field; in ccdc_has_all_fields()
1563 ccdc->fields |= field == V4L2_FIELD_BOTTOM in ccdc_has_all_fields()
1566 if (ccdc->fields != CCDC_FIELD_BOTH) in ccdc_has_all_fields()
1569 /* Verify that the field just captured corresponds to the last field in ccdc_has_all_fields()
1570 * needed based on the desired field order. in ccdc_has_all_fields()
1572 if ((of_field == V4L2_FIELD_INTERLACED_TB && field == V4L2_FIELD_TOP) || in ccdc_has_all_fields()
1573 (of_field == V4L2_FIELD_INTERLACED_BT && field == V4L2_FIELD_BOTTOM)) in ccdc_has_all_fields()
1577 ccdc->fields = 0; in ccdc_has_all_fields()
1584 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); in ccdc_isr_buffer()
1588 /* The CCDC generates VD0 interrupts even when disabled (the datasheet in ccdc_isr_buffer()
1594 if (list_empty(&ccdc->video_out.dmaqueue)) in ccdc_isr_buffer()
1598 * buffer underrun. Re-enable them now that we have a buffer. The buffer in ccdc_isr_buffer()
1601 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && ccdc->underrun) { in ccdc_isr_buffer()
1602 ccdc->underrun = 0; in ccdc_isr_buffer()
1608 dev_info(isp->dev, "CCDC won't become idle!\n"); in ccdc_isr_buffer()
1609 media_entity_enum_set(&isp->crashed, &ccdc->subdev.entity); in ccdc_isr_buffer()
1615 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && in ccdc_isr_buffer()
1616 ccdc->stopping & CCDC_STOP_REQUEST) in ccdc_isr_buffer()
1622 buffer = omap3isp_video_buffer_next(&ccdc->video_out); in ccdc_isr_buffer()
1624 ccdc_set_outaddr(ccdc, buffer->dma); in ccdc_isr_buffer()
1626 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; in ccdc_isr_buffer()
1628 if (ccdc->state == ISP_PIPELINE_STREAM_SINGLESHOT && in ccdc_isr_buffer()
1637 * ccdc_vd0_isr - Handle VD0 event
1650 if (ccdc->bt656) { in ccdc_vd0_isr()
1652 to_isp_pipeline(&ccdc->subdev.entity); in ccdc_vd0_isr()
1654 atomic_inc(&pipe->frame_number); in ccdc_vd0_isr()
1661 if (ccdc->bt656) { in ccdc_vd0_isr()
1662 spin_lock_irqsave(&ccdc->lock, flags); in ccdc_vd0_isr()
1663 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && in ccdc_vd0_isr()
1664 ccdc->output & CCDC_OUTPUT_MEMORY) { in ccdc_vd0_isr()
1665 if (ccdc->lsc.state != LSC_STATE_STOPPED) in ccdc_vd0_isr()
1670 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_vd0_isr()
1673 spin_lock_irqsave(&ccdc->lock, flags); in ccdc_vd0_isr()
1675 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_vd0_isr()
1679 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_vd0_isr()
1682 if (!ccdc->shadow_update) in ccdc_vd0_isr()
1684 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_vd0_isr()
1691 * ccdc_vd1_isr - Handle VD1 event
1701 * where the line counter runs even when the CCDC is stopped. We can't in ccdc_vd1_isr()
1707 if (ccdc->bt656) in ccdc_vd1_isr()
1710 spin_lock_irqsave(&ccdc->lsc.req_lock, flags); in ccdc_vd1_isr()
1722 switch (ccdc->state) { in ccdc_vd1_isr()
1724 ccdc->stopping = CCDC_STOP_REQUEST; in ccdc_vd1_isr()
1728 if (ccdc->output & CCDC_OUTPUT_MEMORY) { in ccdc_vd1_isr()
1729 if (ccdc->lsc.state != LSC_STATE_STOPPED) in ccdc_vd1_isr()
1742 if (ccdc->lsc.request == NULL) in ccdc_vd1_isr()
1749 if (ccdc->lsc.state == LSC_STATE_RUNNING) { in ccdc_vd1_isr()
1751 ccdc->lsc.state = LSC_STATE_RECONFIG; in ccdc_vd1_isr()
1756 if (ccdc->lsc.state == LSC_STATE_STOPPED) in ccdc_vd1_isr()
1760 spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags); in ccdc_vd1_isr()
1764 * omap3isp_ccdc_isr - Configure CCDC during interframe time.
1770 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) in omap3isp_ccdc_isr()
1787 /* -----------------------------------------------------------------------------
1793 struct isp_ccdc_device *ccdc = &video->isp->isp_ccdc; in ccdc_video_queue()
1797 if (!(ccdc->output & CCDC_OUTPUT_MEMORY)) in ccdc_video_queue()
1798 return -ENODEV; in ccdc_video_queue()
1800 ccdc_set_outaddr(ccdc, buffer->dma); in ccdc_video_queue()
1808 spin_lock_irqsave(&ccdc->lock, flags); in ccdc_video_queue()
1809 if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && !ccdc->running && in ccdc_video_queue()
1810 ccdc->bt656) in ccdc_video_queue()
1813 ccdc->underrun = 1; in ccdc_video_queue()
1814 spin_unlock_irqrestore(&ccdc->lock, flags); in ccdc_video_queue()
1826 /* -----------------------------------------------------------------------------
1831 * ccdc_ioctl - CCDC module private ioctl's
1845 mutex_lock(&ccdc->ioctl_lock); in ccdc_ioctl()
1847 mutex_unlock(&ccdc->ioctl_lock); in ccdc_ioctl()
1851 return -ENOIOCTLCMD; in ccdc_ioctl()
1860 if (sub->type != V4L2_EVENT_FRAME_SYNC) in ccdc_subscribe_event()
1861 return -EINVAL; in ccdc_subscribe_event()
1864 if (sub->id != 0) in ccdc_subscribe_event()
1865 return -EINVAL; in ccdc_subscribe_event()
1877 * ccdc_set_stream - Enable/Disable streaming on the CCDC module
1883 * STREAMON call without any buffer queued yet, just update the enabled field
1894 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) { in ccdc_set_stream()
1909 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_set_stream()
1912 if (ccdc->underrun || !(ccdc->output & CCDC_OUTPUT_MEMORY)) in ccdc_set_stream()
1915 ccdc->underrun = 0; in ccdc_set_stream()
1919 if (ccdc->output & CCDC_OUTPUT_MEMORY && in ccdc_set_stream()
1920 ccdc->state != ISP_PIPELINE_STREAM_SINGLESHOT) in ccdc_set_stream()
1928 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_set_stream()
1931 ccdc->underrun = 0; in ccdc_set_stream()
1935 ccdc->state = enable; in ccdc_set_stream()
1944 return v4l2_subdev_get_try_format(&ccdc->subdev, cfg, pad); in __ccdc_get_format()
1946 return &ccdc->formats[pad]; in __ccdc_get_format()
1954 return v4l2_subdev_get_try_crop(&ccdc->subdev, cfg, CCDC_PAD_SOURCE_OF); in __ccdc_get_crop()
1956 return &ccdc->crop; in __ccdc_get_crop()
1960 * ccdc_try_format - Try video format on a pad
1973 unsigned int width = fmt->width; in ccdc_try_format()
1974 unsigned int height = fmt->height; in ccdc_try_format()
1976 enum v4l2_field field; in ccdc_try_format() local
1982 if (fmt->code == ccdc_fmts[i]) in ccdc_try_format()
1988 fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; in ccdc_try_format()
1991 fmt->width = clamp_t(u32, width, 32, 4096); in ccdc_try_format()
1992 fmt->height = clamp_t(u32, height, 32, 4096); in ccdc_try_format()
1994 /* Default to progressive field order. */ in ccdc_try_format()
1995 if (fmt->field == V4L2_FIELD_ANY) in ccdc_try_format()
1996 fmt->field = V4L2_FIELD_NONE; in ccdc_try_format()
2001 pixelcode = fmt->code; in ccdc_try_format()
2002 field = fmt->field; in ccdc_try_format()
2012 if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_try_format()
2013 fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) { in ccdc_try_format()
2019 fmt->code = pixelcode; in ccdc_try_format()
2021 if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8) in ccdc_try_format()
2022 fmt->code = MEDIA_BUS_FMT_YUYV8_1X16; in ccdc_try_format()
2023 else if (fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_try_format()
2024 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; in ccdc_try_format()
2029 fmt->width = crop->width; in ccdc_try_format()
2030 fmt->height = crop->height; in ccdc_try_format()
2035 if (fmt->field == V4L2_FIELD_ALTERNATE && in ccdc_try_format()
2036 (field == V4L2_FIELD_INTERLACED_TB || in ccdc_try_format()
2037 field == V4L2_FIELD_INTERLACED_BT)) { in ccdc_try_format()
2038 fmt->field = field; in ccdc_try_format()
2039 fmt->height *= 2; in ccdc_try_format()
2048 info = omap3isp_video_format_info(fmt->code); in ccdc_try_format()
2049 fmt->code = info->truncated; in ccdc_try_format()
2052 if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_try_format()
2053 fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_try_format()
2054 fmt->code = 0; in ccdc_try_format()
2060 fmt->width = clamp_t(u32, width, 32, fmt->width); in ccdc_try_format()
2061 fmt->height = clamp_t(u32, height, 32, fmt->height - 1); in ccdc_try_format()
2065 /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is in ccdc_try_format()
2068 fmt->colorspace = V4L2_COLORSPACE_SRGB; in ccdc_try_format()
2072 * ccdc_try_crop - Validate a crop rectangle
2084 /* For Bayer formats, restrict left/top and width/height to even values in ccdc_try_crop()
2087 info = omap3isp_video_format_info(sink->code); in ccdc_try_crop()
2088 if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) { in ccdc_try_crop()
2089 crop->left &= ~1; in ccdc_try_crop()
2090 crop->top &= ~1; in ccdc_try_crop()
2093 crop->left = clamp_t(u32, crop->left, 0, sink->width - CCDC_MIN_WIDTH); in ccdc_try_crop()
2094 crop->top = clamp_t(u32, crop->top, 0, sink->height - CCDC_MIN_HEIGHT); in ccdc_try_crop()
2101 max_width = (sink->width - crop->left + 15) & ~15; in ccdc_try_crop()
2102 crop->width = clamp_t(u32, crop->width, CCDC_MIN_WIDTH, max_width) in ccdc_try_crop()
2104 crop->height = clamp_t(u32, crop->height, CCDC_MIN_HEIGHT, in ccdc_try_crop()
2105 sink->height - crop->top); in ccdc_try_crop()
2108 if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) { in ccdc_try_crop()
2109 crop->width &= ~1; in ccdc_try_crop()
2110 crop->height &= ~1; in ccdc_try_crop()
2115 * ccdc_enum_mbus_code - Handle pixel format enumeration
2119 * return -EINVAL or zero on success
2128 switch (code->pad) { in ccdc_enum_mbus_code()
2130 if (code->index >= ARRAY_SIZE(ccdc_fmts)) in ccdc_enum_mbus_code()
2131 return -EINVAL; in ccdc_enum_mbus_code()
2133 code->code = ccdc_fmts[code->index]; in ccdc_enum_mbus_code()
2137 format = __ccdc_get_format(ccdc, cfg, code->pad, in ccdc_enum_mbus_code()
2138 code->which); in ccdc_enum_mbus_code()
2140 if (format->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_enum_mbus_code()
2141 format->code == MEDIA_BUS_FMT_UYVY8_2X8) { in ccdc_enum_mbus_code()
2143 if (code->index == 0) in ccdc_enum_mbus_code()
2144 code->code = MEDIA_BUS_FMT_YUYV8_1X16; in ccdc_enum_mbus_code()
2145 else if (code->index == 1) in ccdc_enum_mbus_code()
2146 code->code = MEDIA_BUS_FMT_UYVY8_1X16; in ccdc_enum_mbus_code()
2148 return -EINVAL; in ccdc_enum_mbus_code()
2153 if (code->index == 0) in ccdc_enum_mbus_code()
2154 code->code = format->code; in ccdc_enum_mbus_code()
2156 return -EINVAL; in ccdc_enum_mbus_code()
2165 if (code->index != 0) in ccdc_enum_mbus_code()
2166 return -EINVAL; in ccdc_enum_mbus_code()
2168 format = __ccdc_get_format(ccdc, cfg, code->pad, in ccdc_enum_mbus_code()
2169 code->which); in ccdc_enum_mbus_code()
2174 if (format->code == 0) in ccdc_enum_mbus_code()
2175 return -EINVAL; in ccdc_enum_mbus_code()
2177 code->code = format->code; in ccdc_enum_mbus_code()
2181 return -EINVAL; in ccdc_enum_mbus_code()
2194 if (fse->index != 0) in ccdc_enum_frame_size()
2195 return -EINVAL; in ccdc_enum_frame_size()
2197 format.code = fse->code; in ccdc_enum_frame_size()
2200 ccdc_try_format(ccdc, cfg, fse->pad, &format, fse->which); in ccdc_enum_frame_size()
2201 fse->min_width = format.width; in ccdc_enum_frame_size()
2202 fse->min_height = format.height; in ccdc_enum_frame_size()
2204 if (format.code != fse->code) in ccdc_enum_frame_size()
2205 return -EINVAL; in ccdc_enum_frame_size()
2207 format.code = fse->code; in ccdc_enum_frame_size()
2208 format.width = -1; in ccdc_enum_frame_size()
2209 format.height = -1; in ccdc_enum_frame_size()
2210 ccdc_try_format(ccdc, cfg, fse->pad, &format, fse->which); in ccdc_enum_frame_size()
2211 fse->max_width = format.width; in ccdc_enum_frame_size()
2212 fse->max_height = format.height; in ccdc_enum_frame_size()
2218 * ccdc_get_selection - Retrieve a selection rectangle on a pad
2234 if (sel->pad != CCDC_PAD_SOURCE_OF) in ccdc_get_selection()
2235 return -EINVAL; in ccdc_get_selection()
2237 switch (sel->target) { in ccdc_get_selection()
2239 sel->r.left = 0; in ccdc_get_selection()
2240 sel->r.top = 0; in ccdc_get_selection()
2241 sel->r.width = INT_MAX; in ccdc_get_selection()
2242 sel->r.height = INT_MAX; in ccdc_get_selection()
2244 format = __ccdc_get_format(ccdc, cfg, CCDC_PAD_SINK, sel->which); in ccdc_get_selection()
2245 ccdc_try_crop(ccdc, format, &sel->r); in ccdc_get_selection()
2249 sel->r = *__ccdc_get_crop(ccdc, cfg, sel->which); in ccdc_get_selection()
2253 return -EINVAL; in ccdc_get_selection()
2260 * ccdc_set_selection - Set a selection rectangle on a pad
2276 if (sel->target != V4L2_SEL_TGT_CROP || in ccdc_set_selection()
2277 sel->pad != CCDC_PAD_SOURCE_OF) in ccdc_set_selection()
2278 return -EINVAL; in ccdc_set_selection()
2281 if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED) in ccdc_set_selection()
2282 return -EBUSY; in ccdc_set_selection()
2288 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) { in ccdc_set_selection()
2289 sel->r = *__ccdc_get_crop(ccdc, cfg, sel->which); in ccdc_set_selection()
2293 format = __ccdc_get_format(ccdc, cfg, CCDC_PAD_SINK, sel->which); in ccdc_set_selection()
2294 ccdc_try_crop(ccdc, format, &sel->r); in ccdc_set_selection()
2295 *__ccdc_get_crop(ccdc, cfg, sel->which) = sel->r; in ccdc_set_selection()
2298 format = __ccdc_get_format(ccdc, cfg, CCDC_PAD_SOURCE_OF, sel->which); in ccdc_set_selection()
2299 ccdc_try_format(ccdc, cfg, CCDC_PAD_SOURCE_OF, format, sel->which); in ccdc_set_selection()
2305 * ccdc_get_format - Retrieve the video format on a pad
2310 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
2319 format = __ccdc_get_format(ccdc, cfg, fmt->pad, fmt->which); in ccdc_get_format()
2321 return -EINVAL; in ccdc_get_format()
2323 fmt->format = *format; in ccdc_get_format()
2328 * ccdc_set_format - Set the video format on a pad
2333 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
2343 format = __ccdc_get_format(ccdc, cfg, fmt->pad, fmt->which); in ccdc_set_format()
2345 return -EINVAL; in ccdc_set_format()
2347 ccdc_try_format(ccdc, cfg, fmt->pad, &fmt->format, fmt->which); in ccdc_set_format()
2348 *format = fmt->format; in ccdc_set_format()
2351 if (fmt->pad == CCDC_PAD_SINK) { in ccdc_set_format()
2353 crop = __ccdc_get_crop(ccdc, cfg, fmt->which); in ccdc_set_format()
2354 crop->left = 0; in ccdc_set_format()
2355 crop->top = 0; in ccdc_set_format()
2356 crop->width = fmt->format.width; in ccdc_set_format()
2357 crop->height = fmt->format.height; in ccdc_set_format()
2359 ccdc_try_crop(ccdc, &fmt->format, crop); in ccdc_set_format()
2363 fmt->which); in ccdc_set_format()
2364 *format = fmt->format; in ccdc_set_format()
2366 fmt->which); in ccdc_set_format()
2369 fmt->which); in ccdc_set_format()
2370 *format = fmt->format; in ccdc_set_format()
2372 fmt->which); in ccdc_set_format()
2398 if ((in_info->flavor == 0) || (out_info->flavor == 0)) in ccdc_is_shiftable()
2401 if (in_info->flavor != out_info->flavor) in ccdc_is_shiftable()
2404 return in_info->width - out_info->width + additional_shift <= 6; in ccdc_is_shiftable()
2416 if (source_fmt->format.width != sink_fmt->format.width || in ccdc_link_validate()
2417 source_fmt->format.height != sink_fmt->format.height) in ccdc_link_validate()
2418 return -EPIPE; in ccdc_link_validate()
2421 if (ccdc->input == CCDC_INPUT_PARALLEL) { in ccdc_link_validate()
2423 media_entity_to_v4l2_subdev(link->source->entity); in ccdc_link_validate()
2426 parallel_shift = bus_cfg->bus.parallel.data_lane_shift; in ccdc_link_validate()
2432 if (!ccdc_is_shiftable(source_fmt->format.code, in ccdc_link_validate()
2433 sink_fmt->format.code, parallel_shift)) in ccdc_link_validate()
2434 return -EPIPE; in ccdc_link_validate()
2440 * ccdc_init_formats - Initialize formats on all pads
2445 * formats are initialized on the file handle. Otherwise active formats are
2458 ccdc_set_format(sd, fh ? fh->pad : NULL, &format); in ccdc_init_formats()
2498 /* -----------------------------------------------------------------------------
2503 * ccdc_link_setup - Setup CCDC connections
2509 * return -EINVAL or zero on success
2518 unsigned int index = local->index; in ccdc_link_setup()
2521 if (is_media_entity_v4l2_subdev(remote->entity)) in ccdc_link_setup()
2530 ccdc->input = CCDC_INPUT_NONE; in ccdc_link_setup()
2534 if (ccdc->input != CCDC_INPUT_NONE) in ccdc_link_setup()
2535 return -EBUSY; in ccdc_link_setup()
2537 if (remote->entity == &isp->isp_ccp2.subdev.entity) in ccdc_link_setup()
2538 ccdc->input = CCDC_INPUT_CCP2B; in ccdc_link_setup()
2539 else if (remote->entity == &isp->isp_csi2a.subdev.entity) in ccdc_link_setup()
2540 ccdc->input = CCDC_INPUT_CSI2A; in ccdc_link_setup()
2541 else if (remote->entity == &isp->isp_csi2c.subdev.entity) in ccdc_link_setup()
2542 ccdc->input = CCDC_INPUT_CSI2C; in ccdc_link_setup()
2544 ccdc->input = CCDC_INPUT_PARALLEL; in ccdc_link_setup()
2550 * Revisit this when it will be implemented, and return -EBUSY for now. in ccdc_link_setup()
2555 * those links are active, the video port can be disabled. in ccdc_link_setup()
2558 if (ccdc->output & ~CCDC_OUTPUT_PREVIEW) in ccdc_link_setup()
2559 return -EBUSY; in ccdc_link_setup()
2560 ccdc->output |= CCDC_OUTPUT_PREVIEW; in ccdc_link_setup()
2562 ccdc->output &= ~CCDC_OUTPUT_PREVIEW; in ccdc_link_setup()
2569 if (ccdc->output & ~CCDC_OUTPUT_MEMORY) in ccdc_link_setup()
2570 return -EBUSY; in ccdc_link_setup()
2571 ccdc->output |= CCDC_OUTPUT_MEMORY; in ccdc_link_setup()
2573 ccdc->output &= ~CCDC_OUTPUT_MEMORY; in ccdc_link_setup()
2580 if (ccdc->output & ~CCDC_OUTPUT_RESIZER) in ccdc_link_setup()
2581 return -EBUSY; in ccdc_link_setup()
2582 ccdc->output |= CCDC_OUTPUT_RESIZER; in ccdc_link_setup()
2584 ccdc->output &= ~CCDC_OUTPUT_RESIZER; in ccdc_link_setup()
2589 return -EINVAL; in ccdc_link_setup()
2603 v4l2_device_unregister_subdev(&ccdc->subdev); in omap3isp_ccdc_unregister_entities()
2604 omap3isp_video_unregister(&ccdc->video_out); in omap3isp_ccdc_unregister_entities()
2613 ccdc->subdev.dev = vdev->mdev->dev; in omap3isp_ccdc_register_entities()
2614 ret = v4l2_device_register_subdev(vdev, &ccdc->subdev); in omap3isp_ccdc_register_entities()
2618 ret = omap3isp_video_register(&ccdc->video_out, vdev); in omap3isp_ccdc_register_entities()
2629 /* -----------------------------------------------------------------------------
2634 * ccdc_init_entities - Initialize V4L2 subdev and media entity
2641 struct v4l2_subdev *sd = &ccdc->subdev; in ccdc_init_entities()
2642 struct media_pad *pads = ccdc->pads; in ccdc_init_entities()
2643 struct media_entity *me = &sd->entity; in ccdc_init_entities()
2646 ccdc->input = CCDC_INPUT_NONE; in ccdc_init_entities()
2649 sd->internal_ops = &ccdc_v4l2_internal_ops; in ccdc_init_entities()
2650 strscpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name)); in ccdc_init_entities()
2651 sd->grp_id = 1 << 16; /* group ID for isp subdevs */ in ccdc_init_entities()
2653 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; in ccdc_init_entities()
2660 me->ops = &ccdc_media_ops; in ccdc_init_entities()
2667 ccdc->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in ccdc_init_entities()
2668 ccdc->video_out.ops = &ccdc_video_ops; in ccdc_init_entities()
2669 ccdc->video_out.isp = to_isp_device(ccdc); in ccdc_init_entities()
2670 ccdc->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; in ccdc_init_entities()
2671 ccdc->video_out.bpl_alignment = 32; in ccdc_init_entities()
2673 ret = omap3isp_video_init(&ccdc->video_out, "CCDC"); in ccdc_init_entities()
2685 * omap3isp_ccdc_init - CCDC module initialization.
2694 struct isp_ccdc_device *ccdc = &isp->isp_ccdc; in omap3isp_ccdc_init()
2697 spin_lock_init(&ccdc->lock); in omap3isp_ccdc_init()
2698 init_waitqueue_head(&ccdc->wait); in omap3isp_ccdc_init()
2699 mutex_init(&ccdc->ioctl_lock); in omap3isp_ccdc_init()
2701 ccdc->stopping = CCDC_STOP_NOT_REQUESTED; in omap3isp_ccdc_init()
2703 INIT_WORK(&ccdc->lsc.table_work, ccdc_lsc_free_table_work); in omap3isp_ccdc_init()
2704 ccdc->lsc.state = LSC_STATE_STOPPED; in omap3isp_ccdc_init()
2705 INIT_LIST_HEAD(&ccdc->lsc.free_queue); in omap3isp_ccdc_init()
2706 spin_lock_init(&ccdc->lsc.req_lock); in omap3isp_ccdc_init()
2708 ccdc->clamp.oblen = 0; in omap3isp_ccdc_init()
2709 ccdc->clamp.dcsubval = 0; in omap3isp_ccdc_init()
2711 ccdc->update = OMAP3ISP_CCDC_BLCLAMP; in omap3isp_ccdc_init()
2716 mutex_destroy(&ccdc->ioctl_lock); in omap3isp_ccdc_init()
2724 * omap3isp_ccdc_cleanup - CCDC module cleanup.
2729 struct isp_ccdc_device *ccdc = &isp->isp_ccdc; in omap3isp_ccdc_cleanup()
2731 omap3isp_video_cleanup(&ccdc->video_out); in omap3isp_ccdc_cleanup()
2732 media_entity_cleanup(&ccdc->subdev.entity); in omap3isp_ccdc_cleanup()
2734 /* Free LSC requests. As the CCDC is stopped there's no active request, in omap3isp_ccdc_cleanup()
2737 ccdc_lsc_free_request(ccdc, ccdc->lsc.request); in omap3isp_ccdc_cleanup()
2738 cancel_work_sync(&ccdc->lsc.table_work); in omap3isp_ccdc_cleanup()
2739 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue); in omap3isp_ccdc_cleanup()
2741 if (ccdc->fpc.addr != NULL) in omap3isp_ccdc_cleanup()
2742 dma_free_coherent(isp->dev, ccdc->fpc.fpnum * 4, ccdc->fpc.addr, in omap3isp_ccdc_cleanup()
2743 ccdc->fpc.dma); in omap3isp_ccdc_cleanup()
2745 mutex_destroy(&ccdc->ioctl_lock); in omap3isp_ccdc_cleanup()