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>
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()
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()
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()
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()
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()
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()
1258 /* When interleaving fields enable processing of the field input signal. in ccdc_configure()
1259 * This will cause the line output control module to apply the field in ccdc_configure()
1260 * offset to field 1. 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()
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()
1299 * the current active resolution discard it. 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()
1549 enum v4l2_field field; in ccdc_has_all_fields() local
1555 /* Read the current field identifier. */ in ccdc_has_all_fields()
1556 field = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE) in ccdc_has_all_fields()
1560 /* When capturing fields in alternate order just store the current 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()
1575 /* Verify that the field just captured corresponds to the last field in ccdc_has_all_fields()
1576 * needed based on the desired field order. in ccdc_has_all_fields()
1578 if ((of_field == V4L2_FIELD_INTERLACED_TB && field == V4L2_FIELD_TOP) || in ccdc_has_all_fields()
1579 (of_field == V4L2_FIELD_INTERLACED_BT && field == V4L2_FIELD_BOTTOM)) 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()
1594 /* The CCDC generates VD0 interrupts even when disabled (the datasheet 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
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()
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
1707 * where the line counter runs even when the CCDC is stopped. We can't 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()
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
1889 * STREAMON call without any buffer queued yet, just update the enabled field
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()
1953 return &ccdc->formats[pad]; in __ccdc_get_format()
1965 return &ccdc->crop; in __ccdc_get_crop()
1969 * ccdc_try_format - Try video format on a pad
1983 unsigned int width = fmt->width; in ccdc_try_format()
1984 unsigned int height = fmt->height; in ccdc_try_format()
1986 enum v4l2_field field; in ccdc_try_format() local
1992 if (fmt->code == ccdc_fmts[i]) in ccdc_try_format()
1998 fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; in ccdc_try_format()
2001 fmt->width = clamp_t(u32, width, 32, 4096); in ccdc_try_format()
2002 fmt->height = clamp_t(u32, height, 32, 4096); in ccdc_try_format()
2004 /* Default to progressive field order. */ in ccdc_try_format()
2005 if (fmt->field == V4L2_FIELD_ANY) in ccdc_try_format()
2006 fmt->field = V4L2_FIELD_NONE; in ccdc_try_format()
2011 pixelcode = fmt->code; in ccdc_try_format()
2012 field = fmt->field; in ccdc_try_format()
2023 if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_try_format()
2024 fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) { in ccdc_try_format()
2030 fmt->code = pixelcode; in ccdc_try_format()
2032 if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8) in ccdc_try_format()
2033 fmt->code = MEDIA_BUS_FMT_YUYV8_1X16; in ccdc_try_format()
2034 else if (fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_try_format()
2035 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; in ccdc_try_format()
2040 fmt->width = crop->width; in ccdc_try_format()
2041 fmt->height = crop->height; in ccdc_try_format()
2046 if (fmt->field == V4L2_FIELD_ALTERNATE && in ccdc_try_format()
2047 (field == V4L2_FIELD_INTERLACED_TB || in ccdc_try_format()
2048 field == V4L2_FIELD_INTERLACED_BT)) { in ccdc_try_format()
2049 fmt->field = field; in ccdc_try_format()
2050 fmt->height *= 2; in ccdc_try_format()
2060 info = omap3isp_video_format_info(fmt->code); in ccdc_try_format()
2061 fmt->code = info->truncated; in ccdc_try_format()
2064 if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_try_format()
2065 fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_try_format()
2066 fmt->code = 0; in ccdc_try_format()
2072 fmt->width = clamp_t(u32, width, 32, fmt->width); in ccdc_try_format()
2073 fmt->height = clamp_t(u32, height, 32, fmt->height - 1); in ccdc_try_format()
2077 /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is in ccdc_try_format()
2080 fmt->colorspace = V4L2_COLORSPACE_SRGB; in ccdc_try_format()
2084 * ccdc_try_crop - Validate a crop rectangle
2096 /* For Bayer formats, restrict left/top and width/height to even values in ccdc_try_crop()
2099 info = omap3isp_video_format_info(sink->code); in ccdc_try_crop()
2100 if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) { in ccdc_try_crop()
2101 crop->left &= ~1; in ccdc_try_crop()
2102 crop->top &= ~1; in ccdc_try_crop()
2105 crop->left = clamp_t(u32, crop->left, 0, sink->width - CCDC_MIN_WIDTH); in ccdc_try_crop()
2106 crop->top = clamp_t(u32, crop->top, 0, sink->height - CCDC_MIN_HEIGHT); in ccdc_try_crop()
2113 max_width = (sink->width - crop->left + 15) & ~15; in ccdc_try_crop()
2114 crop->width = clamp_t(u32, crop->width, CCDC_MIN_WIDTH, max_width) in ccdc_try_crop()
2116 crop->height = clamp_t(u32, crop->height, CCDC_MIN_HEIGHT, in ccdc_try_crop()
2117 sink->height - crop->top); in ccdc_try_crop()
2120 if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) { in ccdc_try_crop()
2121 crop->width &= ~1; in ccdc_try_crop()
2122 crop->height &= ~1; in ccdc_try_crop()
2127 * ccdc_enum_mbus_code - Handle pixel format enumeration
2131 * return -EINVAL or zero on success
2140 switch (code->pad) { in ccdc_enum_mbus_code()
2142 if (code->index >= ARRAY_SIZE(ccdc_fmts)) in ccdc_enum_mbus_code()
2143 return -EINVAL; in ccdc_enum_mbus_code()
2145 code->code = ccdc_fmts[code->index]; in ccdc_enum_mbus_code()
2149 format = __ccdc_get_format(ccdc, sd_state, code->pad, in ccdc_enum_mbus_code()
2150 code->which); in ccdc_enum_mbus_code()
2152 if (format->code == MEDIA_BUS_FMT_YUYV8_2X8 || in ccdc_enum_mbus_code()
2153 format->code == MEDIA_BUS_FMT_UYVY8_2X8) { in ccdc_enum_mbus_code()
2155 if (code->index == 0) in ccdc_enum_mbus_code()
2156 code->code = MEDIA_BUS_FMT_YUYV8_1X16; in ccdc_enum_mbus_code()
2157 else if (code->index == 1) in ccdc_enum_mbus_code()
2158 code->code = MEDIA_BUS_FMT_UYVY8_1X16; in ccdc_enum_mbus_code()
2160 return -EINVAL; in ccdc_enum_mbus_code()
2165 if (code->index == 0) in ccdc_enum_mbus_code()
2166 code->code = format->code; in ccdc_enum_mbus_code()
2168 return -EINVAL; in ccdc_enum_mbus_code()
2177 if (code->index != 0) in ccdc_enum_mbus_code()
2178 return -EINVAL; in ccdc_enum_mbus_code()
2180 format = __ccdc_get_format(ccdc, sd_state, code->pad, in ccdc_enum_mbus_code()
2181 code->which); in ccdc_enum_mbus_code()
2186 if (format->code == 0) in ccdc_enum_mbus_code()
2187 return -EINVAL; in ccdc_enum_mbus_code()
2189 code->code = format->code; in ccdc_enum_mbus_code()
2193 return -EINVAL; in ccdc_enum_mbus_code()
2206 if (fse->index != 0) in ccdc_enum_frame_size()
2207 return -EINVAL; in ccdc_enum_frame_size()
2209 format.code = fse->code; in ccdc_enum_frame_size()
2212 ccdc_try_format(ccdc, sd_state, fse->pad, &format, fse->which); in ccdc_enum_frame_size()
2213 fse->min_width = format.width; in ccdc_enum_frame_size()
2214 fse->min_height = format.height; in ccdc_enum_frame_size()
2216 if (format.code != fse->code) in ccdc_enum_frame_size()
2217 return -EINVAL; in ccdc_enum_frame_size()
2219 format.code = fse->code; in ccdc_enum_frame_size()
2220 format.width = -1; in ccdc_enum_frame_size()
2221 format.height = -1; in ccdc_enum_frame_size()
2222 ccdc_try_format(ccdc, sd_state, fse->pad, &format, fse->which); in ccdc_enum_frame_size()
2223 fse->max_width = format.width; in ccdc_enum_frame_size()
2224 fse->max_height = format.height; in ccdc_enum_frame_size()
2230 * ccdc_get_selection - Retrieve a selection rectangle on a pad
2247 if (sel->pad != CCDC_PAD_SOURCE_OF) in ccdc_get_selection()
2248 return -EINVAL; in ccdc_get_selection()
2250 switch (sel->target) { in ccdc_get_selection()
2252 sel->r.left = 0; in ccdc_get_selection()
2253 sel->r.top = 0; in ccdc_get_selection()
2254 sel->r.width = INT_MAX; in ccdc_get_selection()
2255 sel->r.height = INT_MAX; in ccdc_get_selection()
2258 sel->which); in ccdc_get_selection()
2259 ccdc_try_crop(ccdc, format, &sel->r); in ccdc_get_selection()
2263 sel->r = *__ccdc_get_crop(ccdc, sd_state, sel->which); in ccdc_get_selection()
2267 return -EINVAL; in ccdc_get_selection()
2274 * ccdc_set_selection - Set a selection rectangle on a pad
2291 if (sel->target != V4L2_SEL_TGT_CROP || in ccdc_set_selection()
2292 sel->pad != CCDC_PAD_SOURCE_OF) in ccdc_set_selection()
2293 return -EINVAL; in ccdc_set_selection()
2296 if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED) in ccdc_set_selection()
2297 return -EBUSY; in ccdc_set_selection()
2303 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) { in ccdc_set_selection()
2304 sel->r = *__ccdc_get_crop(ccdc, sd_state, sel->which); in ccdc_set_selection()
2308 format = __ccdc_get_format(ccdc, sd_state, CCDC_PAD_SINK, sel->which); in ccdc_set_selection()
2309 ccdc_try_crop(ccdc, format, &sel->r); in ccdc_set_selection()
2310 *__ccdc_get_crop(ccdc, sd_state, sel->which) = sel->r; in ccdc_set_selection()
2314 sel->which); in ccdc_set_selection()
2316 sel->which); in ccdc_set_selection()
2322 * ccdc_get_format - Retrieve the video format on a pad
2327 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
2337 format = __ccdc_get_format(ccdc, sd_state, fmt->pad, fmt->which); in ccdc_get_format()
2339 return -EINVAL; in ccdc_get_format()
2341 fmt->format = *format; in ccdc_get_format()
2346 * ccdc_set_format - Set the video format on a pad
2351 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
2362 format = __ccdc_get_format(ccdc, sd_state, fmt->pad, fmt->which); in ccdc_set_format()
2364 return -EINVAL; in ccdc_set_format()
2366 ccdc_try_format(ccdc, sd_state, fmt->pad, &fmt->format, fmt->which); in ccdc_set_format()
2367 *format = fmt->format; in ccdc_set_format()
2370 if (fmt->pad == CCDC_PAD_SINK) { in ccdc_set_format()
2372 crop = __ccdc_get_crop(ccdc, sd_state, fmt->which); in ccdc_set_format()
2373 crop->left = 0; in ccdc_set_format()
2374 crop->top = 0; in ccdc_set_format()
2375 crop->width = fmt->format.width; in ccdc_set_format()
2376 crop->height = fmt->format.height; in ccdc_set_format()
2378 ccdc_try_crop(ccdc, &fmt->format, crop); in ccdc_set_format()
2382 fmt->which); in ccdc_set_format()
2383 *format = fmt->format; in ccdc_set_format()
2385 fmt->which); in ccdc_set_format()
2388 fmt->which); in ccdc_set_format()
2389 *format = fmt->format; in ccdc_set_format()
2391 fmt->which); in ccdc_set_format()
2417 if ((in_info->flavor == 0) || (out_info->flavor == 0)) in ccdc_is_shiftable()
2420 if (in_info->flavor != out_info->flavor) in ccdc_is_shiftable()
2423 return in_info->width - out_info->width + additional_shift <= 6; in ccdc_is_shiftable()
2435 if (source_fmt->format.width != sink_fmt->format.width || in ccdc_link_validate()
2436 source_fmt->format.height != sink_fmt->format.height) in ccdc_link_validate()
2437 return -EPIPE; in ccdc_link_validate()
2440 if (ccdc->input == CCDC_INPUT_PARALLEL) { in ccdc_link_validate()
2442 media_entity_to_v4l2_subdev(link->source->entity); in ccdc_link_validate()
2447 return -EPIPE; in ccdc_link_validate()
2449 parallel_shift = bus_cfg->bus.parallel.data_lane_shift; in ccdc_link_validate()
2455 if (!ccdc_is_shiftable(source_fmt->format.code, in ccdc_link_validate()
2456 sink_fmt->format.code, parallel_shift)) in ccdc_link_validate()
2457 return -EPIPE; in ccdc_link_validate()
2463 * ccdc_init_formats - Initialize formats on all pads
2468 * formats are initialized on the file handle. Otherwise active formats are
2481 ccdc_set_format(sd, fh ? fh->state : NULL, &format); in ccdc_init_formats()
2521 /* -----------------------------------------------------------------------------
2526 * ccdc_link_setup - Setup CCDC connections
2532 * return -EINVAL or zero on success
2541 unsigned int index = local->index; in ccdc_link_setup()
2544 if (is_media_entity_v4l2_subdev(remote->entity)) in ccdc_link_setup()
2553 ccdc->input = CCDC_INPUT_NONE; in ccdc_link_setup()
2557 if (ccdc->input != CCDC_INPUT_NONE) in ccdc_link_setup()
2558 return -EBUSY; in ccdc_link_setup()
2560 if (remote->entity == &isp->isp_ccp2.subdev.entity) in ccdc_link_setup()
2561 ccdc->input = CCDC_INPUT_CCP2B; in ccdc_link_setup()
2562 else if (remote->entity == &isp->isp_csi2a.subdev.entity) in ccdc_link_setup()
2563 ccdc->input = CCDC_INPUT_CSI2A; in ccdc_link_setup()
2564 else if (remote->entity == &isp->isp_csi2c.subdev.entity) in ccdc_link_setup()
2565 ccdc->input = CCDC_INPUT_CSI2C; in ccdc_link_setup()
2567 ccdc->input = CCDC_INPUT_PARALLEL; in ccdc_link_setup()
2573 * Revisit this when it will be implemented, and return -EBUSY for now. in ccdc_link_setup()
2578 * those links are active, the video port can be disabled. in ccdc_link_setup()
2581 if (ccdc->output & ~CCDC_OUTPUT_PREVIEW) in ccdc_link_setup()
2582 return -EBUSY; in ccdc_link_setup()
2583 ccdc->output |= CCDC_OUTPUT_PREVIEW; in ccdc_link_setup()
2585 ccdc->output &= ~CCDC_OUTPUT_PREVIEW; in ccdc_link_setup()
2592 if (ccdc->output & ~CCDC_OUTPUT_MEMORY) in ccdc_link_setup()
2593 return -EBUSY; in ccdc_link_setup()
2594 ccdc->output |= CCDC_OUTPUT_MEMORY; in ccdc_link_setup()
2596 ccdc->output &= ~CCDC_OUTPUT_MEMORY; in ccdc_link_setup()
2603 if (ccdc->output & ~CCDC_OUTPUT_RESIZER) in ccdc_link_setup()
2604 return -EBUSY; in ccdc_link_setup()
2605 ccdc->output |= CCDC_OUTPUT_RESIZER; in ccdc_link_setup()
2607 ccdc->output &= ~CCDC_OUTPUT_RESIZER; in ccdc_link_setup()
2612 return -EINVAL; in ccdc_link_setup()
2626 v4l2_device_unregister_subdev(&ccdc->subdev); in omap3isp_ccdc_unregister_entities()
2627 omap3isp_video_unregister(&ccdc->video_out); in omap3isp_ccdc_unregister_entities()
2636 ccdc->subdev.dev = vdev->mdev->dev; in omap3isp_ccdc_register_entities()
2637 ret = v4l2_device_register_subdev(vdev, &ccdc->subdev); in omap3isp_ccdc_register_entities()
2641 ret = omap3isp_video_register(&ccdc->video_out, vdev); in omap3isp_ccdc_register_entities()
2652 /* -----------------------------------------------------------------------------
2657 * ccdc_init_entities - Initialize V4L2 subdev and media entity
2664 struct v4l2_subdev *sd = &ccdc->subdev; in ccdc_init_entities()
2665 struct media_pad *pads = ccdc->pads; in ccdc_init_entities()
2666 struct media_entity *me = &sd->entity; in ccdc_init_entities()
2669 ccdc->input = CCDC_INPUT_NONE; in ccdc_init_entities()
2672 sd->internal_ops = &ccdc_v4l2_internal_ops; in ccdc_init_entities()
2673 strscpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name)); in ccdc_init_entities()
2674 sd->grp_id = 1 << 16; /* group ID for isp subdevs */ in ccdc_init_entities()
2676 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; in ccdc_init_entities()
2683 me->ops = &ccdc_media_ops; in ccdc_init_entities()
2690 ccdc->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in ccdc_init_entities()
2691 ccdc->video_out.ops = &ccdc_video_ops; in ccdc_init_entities()
2692 ccdc->video_out.isp = to_isp_device(ccdc); in ccdc_init_entities()
2693 ccdc->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3; in ccdc_init_entities()
2694 ccdc->video_out.bpl_alignment = 32; in ccdc_init_entities()
2696 ret = omap3isp_video_init(&ccdc->video_out, "CCDC"); in ccdc_init_entities()
2708 * omap3isp_ccdc_init - CCDC module initialization.
2717 struct isp_ccdc_device *ccdc = &isp->isp_ccdc; in omap3isp_ccdc_init()
2720 spin_lock_init(&ccdc->lock); in omap3isp_ccdc_init()
2721 init_waitqueue_head(&ccdc->wait); in omap3isp_ccdc_init()
2722 mutex_init(&ccdc->ioctl_lock); in omap3isp_ccdc_init()
2724 ccdc->stopping = CCDC_STOP_NOT_REQUESTED; in omap3isp_ccdc_init()
2726 INIT_WORK(&ccdc->lsc.table_work, ccdc_lsc_free_table_work); in omap3isp_ccdc_init()
2727 ccdc->lsc.state = LSC_STATE_STOPPED; in omap3isp_ccdc_init()
2728 INIT_LIST_HEAD(&ccdc->lsc.free_queue); in omap3isp_ccdc_init()
2729 spin_lock_init(&ccdc->lsc.req_lock); in omap3isp_ccdc_init()
2731 ccdc->clamp.oblen = 0; in omap3isp_ccdc_init()
2732 ccdc->clamp.dcsubval = 0; in omap3isp_ccdc_init()
2734 ccdc->update = OMAP3ISP_CCDC_BLCLAMP; in omap3isp_ccdc_init()
2739 mutex_destroy(&ccdc->ioctl_lock); in omap3isp_ccdc_init()
2747 * omap3isp_ccdc_cleanup - CCDC module cleanup.
2752 struct isp_ccdc_device *ccdc = &isp->isp_ccdc; in omap3isp_ccdc_cleanup()
2754 omap3isp_video_cleanup(&ccdc->video_out); in omap3isp_ccdc_cleanup()
2755 media_entity_cleanup(&ccdc->subdev.entity); in omap3isp_ccdc_cleanup()
2757 /* Free LSC requests. As the CCDC is stopped there's no active request, in omap3isp_ccdc_cleanup()
2760 ccdc_lsc_free_request(ccdc, ccdc->lsc.request); in omap3isp_ccdc_cleanup()
2761 cancel_work_sync(&ccdc->lsc.table_work); in omap3isp_ccdc_cleanup()
2762 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue); in omap3isp_ccdc_cleanup()
2764 if (ccdc->fpc.addr != NULL) in omap3isp_ccdc_cleanup()
2765 dma_free_coherent(isp->dev, ccdc->fpc.fpnum * 4, ccdc->fpc.addr, in omap3isp_ccdc_cleanup()
2766 ccdc->fpc.dma); in omap3isp_ccdc_cleanup()
2768 mutex_destroy(&ccdc->ioctl_lock); in omap3isp_ccdc_cleanup()