Lines Matching +full:isp +full:- +full:0
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>
24 #include "isp.h"
57 * ccdc_print_status - Print current CCDC Module register values.
58 * @ccdc: Pointer to ISP CCDC device.
62 #define CCDC_PRINT_REGISTER(isp, name)\ argument
63 dev_dbg(isp->dev, "###CCDC " #name "=0x%08x\n", \
64 isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_##name))
68 struct isp_device *isp = to_isp_device(ccdc); in ccdc_print_status() local
70 dev_dbg(isp->dev, "-------------CCDC Register dump-------------\n"); in ccdc_print_status()
72 CCDC_PRINT_REGISTER(isp, PCR); in ccdc_print_status()
73 CCDC_PRINT_REGISTER(isp, SYN_MODE); in ccdc_print_status()
74 CCDC_PRINT_REGISTER(isp, HD_VD_WID); in ccdc_print_status()
75 CCDC_PRINT_REGISTER(isp, PIX_LINES); in ccdc_print_status()
76 CCDC_PRINT_REGISTER(isp, HORZ_INFO); in ccdc_print_status()
77 CCDC_PRINT_REGISTER(isp, VERT_START); in ccdc_print_status()
78 CCDC_PRINT_REGISTER(isp, VERT_LINES); in ccdc_print_status()
79 CCDC_PRINT_REGISTER(isp, CULLING); in ccdc_print_status()
80 CCDC_PRINT_REGISTER(isp, HSIZE_OFF); in ccdc_print_status()
81 CCDC_PRINT_REGISTER(isp, SDOFST); in ccdc_print_status()
82 CCDC_PRINT_REGISTER(isp, SDR_ADDR); in ccdc_print_status()
83 CCDC_PRINT_REGISTER(isp, CLAMP); in ccdc_print_status()
84 CCDC_PRINT_REGISTER(isp, DCSUB); in ccdc_print_status()
85 CCDC_PRINT_REGISTER(isp, COLPTN); in ccdc_print_status()
86 CCDC_PRINT_REGISTER(isp, BLKCMP); in ccdc_print_status()
87 CCDC_PRINT_REGISTER(isp, FPC); in ccdc_print_status()
88 CCDC_PRINT_REGISTER(isp, FPC_ADDR); in ccdc_print_status()
89 CCDC_PRINT_REGISTER(isp, VDINT); in ccdc_print_status()
90 CCDC_PRINT_REGISTER(isp, ALAW); in ccdc_print_status()
91 CCDC_PRINT_REGISTER(isp, REC656IF); in ccdc_print_status()
92 CCDC_PRINT_REGISTER(isp, CFG); in ccdc_print_status()
93 CCDC_PRINT_REGISTER(isp, FMTCFG); in ccdc_print_status()
94 CCDC_PRINT_REGISTER(isp, FMT_HORZ); in ccdc_print_status()
95 CCDC_PRINT_REGISTER(isp, FMT_VERT); in ccdc_print_status()
96 CCDC_PRINT_REGISTER(isp, PRGEVEN0); in ccdc_print_status()
97 CCDC_PRINT_REGISTER(isp, PRGEVEN1); in ccdc_print_status()
98 CCDC_PRINT_REGISTER(isp, PRGODD0); in ccdc_print_status()
99 CCDC_PRINT_REGISTER(isp, PRGODD1); in ccdc_print_status()
100 CCDC_PRINT_REGISTER(isp, VP_OUT); in ccdc_print_status()
101 CCDC_PRINT_REGISTER(isp, LSC_CONFIG); in ccdc_print_status()
102 CCDC_PRINT_REGISTER(isp, LSC_INITIAL); in ccdc_print_status()
103 CCDC_PRINT_REGISTER(isp, LSC_TABLE_BASE); in ccdc_print_status()
104 CCDC_PRINT_REGISTER(isp, LSC_TABLE_OFFSET); in ccdc_print_status()
106 dev_dbg(isp->dev, "--------------------------------------------\n"); in ccdc_print_status()
110 * omap3isp_ccdc_busy - Get busy state of the CCDC.
111 * @ccdc: Pointer to ISP CCDC device.
115 struct isp_device *isp = to_isp_device(ccdc); in omap3isp_ccdc_busy() local
117 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) & in omap3isp_ccdc_busy()
121 /* -----------------------------------------------------------------------------
126 * ccdc_lsc_validate_config - Check that LSC configuration is valid.
127 * @ccdc: Pointer to ISP CCDC device.
130 * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
135 struct isp_device *isp = to_isp_device(ccdc); in ccdc_lsc_validate_config() local
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()
189 return 0; in ccdc_lsc_validate_config()
193 * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
194 * @ccdc: Pointer to ISP CCDC device.
204 * ccdc_lsc_setup_regs - Configures the lens shading compensation module
205 * @ccdc: Pointer to ISP CCDC device.
210 struct isp_device *isp = to_isp_device(ccdc); in ccdc_lsc_setup_regs() local
213 isp_reg_writel(isp, cfg->offset, OMAP3_ISP_IOMEM_CCDC, in ccdc_lsc_setup_regs()
216 reg = 0; 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()
220 isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG); in ccdc_lsc_setup_regs()
222 reg = 0; 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()
227 isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC, in ccdc_lsc_setup_regs()
233 struct isp_device *isp = to_isp_device(ccdc); in ccdc_lsc_wait_prefetch() local
236 isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ, in ccdc_lsc_wait_prefetch()
240 for (wait = 0; wait < 1000; wait++) { in ccdc_lsc_wait_prefetch()
241 if (isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS) & in ccdc_lsc_wait_prefetch()
243 isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ, in ccdc_lsc_wait_prefetch()
245 return 0; in ccdc_lsc_wait_prefetch()
252 return -ETIMEDOUT; in ccdc_lsc_wait_prefetch()
256 * __ccdc_lsc_enable - Enables/Disables the Lens Shading Compensation module.
257 * @ccdc: Pointer to ISP CCDC device.
258 * @enable: 0 Disables LSC, 1 Enables LSC.
262 struct isp_device *isp = to_isp_device(ccdc); in __ccdc_lsc_enable() local
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()
274 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_LSC_READ); in __ccdc_lsc_enable()
276 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, in __ccdc_lsc_enable()
277 ISPCCDC_LSC_ENABLE, enable ? ISPCCDC_LSC_ENABLE : 0); in __ccdc_lsc_enable()
280 if (ccdc_lsc_wait_prefetch(ccdc) < 0) { in __ccdc_lsc_enable()
281 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, 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()
292 return 0; in __ccdc_lsc_enable()
297 struct isp_device *isp = to_isp_device(ccdc); in ccdc_lsc_busy() local
299 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG) & in ccdc_lsc_busy()
304 * __ccdc_lsc_configure - Apply a new configuration to the LSC engine
305 * @ccdc: Pointer to ISP CCDC device
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()
324 return 0; in __ccdc_lsc_configure()
328 * ccdc_lsc_error_handler - Handle LSC prefetch error scenario.
329 * @ccdc: Pointer to ISP CCDC device.
335 struct isp_device *isp = to_isp_device(ccdc); in ccdc_lsc_error_handler() local
345 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, in ccdc_lsc_error_handler()
347 ccdc->lsc.state = LSC_STATE_STOPPED; in ccdc_lsc_error_handler()
353 struct isp_device *isp = to_isp_device(ccdc); in ccdc_lsc_free_request() local
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
404 struct isp_device *isp = to_isp_device(ccdc); in ccdc_lsc_config() local
410 update = config->update & in ccdc_lsc_config()
413 return 0; 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()
446 if (ret < 0) 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()
470 ret = 0; in ccdc_lsc_config()
473 if (ret < 0) 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()
519 return 0; in ccdc_lsc_enable()
522 /* -----------------------------------------------------------------------------
527 * ccdc_configure_clamp - Configure optical-black or digital clamping
528 * @ccdc: Pointer to ISP CCDC device.
530 * The CCDC performs either optical-black or digital clamp. Configure and enable
535 struct isp_device *isp = to_isp_device(ccdc); in ccdc_configure_clamp() local
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()
543 isp_reg_writel(isp, clamp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP); in ccdc_configure_clamp()
545 isp_reg_writel(isp, ccdc->clamp.dcsubval, in ccdc_configure_clamp()
549 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP, in ccdc_configure_clamp()
551 ccdc->obclamp ? ISPCCDC_CLAMP_CLAMPEN : 0); in ccdc_configure_clamp()
555 * ccdc_configure_fpc - Configure Faulty Pixel Correction
556 * @ccdc: Pointer to ISP CCDC device.
560 struct isp_device *isp = to_isp_device(ccdc); in ccdc_configure_fpc() local
562 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, ISPCCDC_FPC_FPCEN); in ccdc_configure_fpc()
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.
578 * @ccdc: Pointer to ISP CCDC device.
582 struct isp_device *isp = to_isp_device(ccdc); in ccdc_configure_black_comp() local
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()
590 isp_reg_writel(isp, blcomp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP); in ccdc_configure_black_comp()
594 * ccdc_configure_lpf - Configure Low-Pass Filter (LPF).
595 * @ccdc: Pointer to ISP CCDC device.
599 struct isp_device *isp = to_isp_device(ccdc); in ccdc_configure_lpf() local
601 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE, in ccdc_configure_lpf()
603 ccdc->lpf ? ISPCCDC_SYN_MODE_LPF : 0); in ccdc_configure_lpf()
607 * ccdc_configure_alaw - Configure A-law compression.
608 * @ccdc: Pointer to ISP CCDC device.
612 struct isp_device *isp = to_isp_device(ccdc); in ccdc_configure_alaw() local
614 u32 alaw = 0; in ccdc_configure_alaw()
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()
639 isp_reg_writel(isp, alaw, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW); in ccdc_configure_alaw()
643 * ccdc_config_imgattr - Configure sensor image specific attributes.
644 * @ccdc: Pointer to ISP CCDC device.
649 struct isp_device *isp = to_isp_device(ccdc); in ccdc_config_imgattr() local
651 isp_reg_writel(isp, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN); in ccdc_config_imgattr()
655 * ccdc_config - Set CCDC configuration from userspace
656 * @ccdc: Pointer to ISP CCDC device.
659 * Returns 0 if successful, -EINVAL if the pointer to the configuration
666 struct isp_device *isp = to_isp_device(ccdc); in ccdc_config() local
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
781 * @isp: Pointer to ISP device
783 void omap3isp_ccdc_restore_context(struct isp_device *isp) in omap3isp_ccdc_restore_context() argument
785 struct isp_ccdc_device *ccdc = &isp->isp_ccdc; in omap3isp_ccdc_restore_context()
787 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC); 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.
801 * @ccdc: Pointer to ISP CCDC device.
805 struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); in ccdc_config_vp()
806 struct isp_device *isp = to_isp_device(ccdc); in ccdc_config_vp() local
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()
811 unsigned int div = 0; in ccdc_config_vp()
814 format = &ccdc->formats[CCDC_PAD_SOURCE_VP]; in ccdc_config_vp()
816 if (!format->code) { in ccdc_config_vp()
818 * This is indicated by a pixel code set to 0. in ccdc_config_vp()
820 isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG); in ccdc_config_vp()
824 isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) | in ccdc_config_vp()
825 (format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT), in ccdc_config_vp()
827 isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_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()
861 isp_reg_writel(isp, fmtcfg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG); in ccdc_config_vp()
865 * ccdc_config_outlineoffset - Configure memory saving output line offset
866 * @ccdc: Pointer to ISP CCDC device.
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
888 struct isp_device *isp = to_isp_device(ccdc); in ccdc_config_outlineoffset() local
889 u32 sdofst = 0; in ccdc_config_outlineoffset()
891 isp_reg_writel(isp, bpl & 0xffff, OMAP3_ISP_IOMEM_CCDC, in ccdc_config_outlineoffset()
911 isp_reg_writel(isp, sdofst, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST); in ccdc_config_outlineoffset()
915 * ccdc_set_outaddr - Set memory address to save output image
916 * @ccdc: Pointer to ISP CCDC device.
917 * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
923 struct isp_device *isp = to_isp_device(ccdc); in ccdc_set_outaddr() local
925 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR); in ccdc_set_outaddr()
929 * omap3isp_ccdc_max_rate - Calculate maximum input data rate based on the input
930 * @ccdc: Pointer to ISP CCDC device.
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
958 * @ccdc: Pointer to ISP CCDC device.
966 struct isp_device *isp = to_isp_device(ccdc); in ccdc_config_sync_if() local
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()
1010 if ((parcfg && parcfg->vs_pol) || ccdc->bt656) in ccdc_config_sync_if()
1013 if (parcfg && parcfg->fld_pol) in ccdc_config_sync_if()
1016 isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); in ccdc_config_sync_if()
1021 if (format->code == MEDIA_BUS_FMT_UYVY8_2X8) in ccdc_config_sync_if()
1022 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, in ccdc_config_sync_if()
1025 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, in ccdc_config_sync_if()
1031 if (ccdc->bt656) in ccdc_config_sync_if()
1032 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, in ccdc_config_sync_if()
1035 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, in ccdc_config_sync_if()
1115 struct isp_device *isp = to_isp_device(ccdc); in ccdc_configure() local
1125 unsigned int depth_in = 0; in ccdc_configure()
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()
1183 syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); 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()
1245 isp_reg_writel(isp, (sph << ISPCCDC_HORZ_INFO_SPH_SHIFT) | 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()
1271 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, in ccdc_configure()
1274 isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, in ccdc_configure()
1281 if (omap3isp_video_format_info(format->code)->width <= 8 || ccdc->bt656) in ccdc_configure()
1286 isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); 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()
1319 struct isp_device *isp = to_isp_device(ccdc); in __ccdc_enable() local
1322 if (enable && ccdc->stopping & CCDC_STOP_REQUEST) in __ccdc_enable()
1325 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR, in __ccdc_enable()
1326 ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0); in __ccdc_enable()
1328 ccdc->running = enable; in __ccdc_enable()
1334 int ret = 0; in ccdc_disable()
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()
1346 if (ret == 0) { 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()
1363 return ret > 0 ? 0 : ret; in ccdc_disable()
1373 /* -----------------------------------------------------------------------------
1378 * ccdc_sbl_busy - Poll idle state of CCDC and related SBL memory write bits
1379 * @ccdc: Pointer to ISP CCDC device.
1386 struct isp_device *isp = to_isp_device(ccdc); in ccdc_sbl_busy() local
1389 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) & in ccdc_sbl_busy()
1391 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) & in ccdc_sbl_busy()
1393 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) & in ccdc_sbl_busy()
1395 | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) & in ccdc_sbl_busy()
1400 * ccdc_sbl_wait_idle - Wait until the CCDC and related SBL are idle
1401 * @ccdc: Pointer to ISP CCDC device.
1407 unsigned int wait = 0; in ccdc_sbl_wait_idle()
1409 if (max_wait == 0) in ccdc_sbl_wait_idle()
1412 for (wait = 0; wait <= max_wait; wait++) { in ccdc_sbl_wait_idle()
1414 return 0; in ccdc_sbl_wait_idle()
1420 return -EBUSY; in ccdc_sbl_wait_idle()
1423 /* ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
1424 * @ccdc: Pointer to ISP CCDC device.
1432 int rval = 0; in ccdc_handle_stopping()
1434 switch ((ccdc->stopping & 3) | event) { in ccdc_handle_stopping()
1436 if (ccdc->lsc.state != LSC_STATE_STOPPED) in ccdc_handle_stopping()
1437 __ccdc_lsc_enable(ccdc, 0); in ccdc_handle_stopping()
1438 __ccdc_enable(ccdc, 0); 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()
1475 memset(&event, 0, sizeof(event)); 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
1484 * @ccdc: Pointer to ISP CCDC device.
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()
1547 struct isp_device *isp = to_isp_device(ccdc); in ccdc_has_all_fields() local
1548 enum v4l2_field of_field = ccdc->formats[CCDC_PAD_SOURCE_OF].field; in ccdc_has_all_fields()
1556 field = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE) 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()
1591 struct isp_device *isp = to_isp_device(ccdc); in ccdc_isr_buffer() local
1600 if (list_empty(&ccdc->video_out.dmaqueue)) in ccdc_isr_buffer()
1601 return 0; 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()
1617 return 0; 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()
1623 return 0; 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
1644 * @ccdc: Pointer to ISP CCDC device.
1651 int restart = 0; 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()
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()
1672 __ccdc_lsc_enable(ccdc, 0); in ccdc_vd0_isr()
1673 __ccdc_enable(ccdc, 0); 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
1698 * @ccdc: Pointer to ISP CCDC device.
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()
1736 __ccdc_lsc_enable(ccdc, 0); in ccdc_vd1_isr()
1737 __ccdc_enable(ccdc, 0); 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()
1756 __ccdc_lsc_enable(ccdc, 0); 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.
1771 * @ccdc: Pointer to ISP CCDC device.
1776 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) in omap3isp_ccdc_isr()
1777 return 0; in omap3isp_ccdc_isr()
1790 return 0; in omap3isp_ccdc_isr()
1793 /* -----------------------------------------------------------------------------
1794 * ISP video operations
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()
1825 return 0; in ccdc_video_queue()
1832 /* -----------------------------------------------------------------------------
1837 * ccdc_ioctl - CCDC module private ioctl's
1838 * @sd: ISP CCDC V4L2 subdevice
1842 * Return 0 on success or a negative error code otherwise.
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
1884 * @sd: ISP CCDC V4L2 subdevice
1897 struct isp_device *isp = to_isp_device(ccdc); in ccdc_set_stream() local
1898 int ret = 0; in ccdc_set_stream()
1900 if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) { in ccdc_set_stream()
1902 return 0; in ccdc_set_stream()
1904 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_CCDC); in ccdc_set_stream()
1905 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, in ccdc_set_stream()
1915 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_set_stream()
1916 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE); 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()
1927 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE); in ccdc_set_stream()
1934 if (ccdc->output & CCDC_OUTPUT_MEMORY) in ccdc_set_stream()
1935 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CCDC_WRITE); in ccdc_set_stream()
1936 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_CCDC); 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
1970 * @ccdc: ISP CCDC device
1983 unsigned int width = fmt->width; in ccdc_try_format()
1984 unsigned int height = fmt->height; in ccdc_try_format()
1991 for (i = 0; i < ARRAY_SIZE(ccdc_fmts); i++) { in ccdc_try_format()
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()
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()
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
2085 * @ccdc: ISP CCDC device
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()
2183 /* A pixel code equal to 0 means that the video port doesn't 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()
2196 return 0; 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()
2226 return 0; in ccdc_enum_frame_size()
2230 * ccdc_get_selection - Retrieve a selection rectangle on a pad
2231 * @sd: ISP CCDC V4L2 subdevice
2238 * Return 0 on success or a negative error code otherwise.
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()
2270 return 0; in ccdc_get_selection()
2274 * ccdc_set_selection - Set a selection rectangle on a pad
2275 * @sd: ISP CCDC V4L2 subdevice
2282 * Return 0 on success or a negative error code otherwise.
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()
2305 return 0; 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()
2318 return 0; in ccdc_set_selection()
2322 * ccdc_get_format - Retrieve the video format on a pad
2323 * @sd : ISP CCDC V4L2 subdevice
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()
2342 return 0; in ccdc_get_format()
2346 * ccdc_set_format - Set the video format on a pad
2347 * @sd : ISP CCDC V4L2 subdevice
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()
2394 return 0; in ccdc_set_format()
2402 * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
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()
2451 parallel_shift = 0; 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()
2459 return 0; in ccdc_link_validate()
2463 * ccdc_init_formats - Initialize formats on all pads
2464 * @sd: ISP CCDC V4L2 subdevice
2475 memset(&format, 0, sizeof(format)); in ccdc_init_formats()
2481 ccdc_set_format(sd, fh ? fh->state : NULL, &format); in ccdc_init_formats()
2483 return 0; in ccdc_init_formats()
2521 /* -----------------------------------------------------------------------------
2526 * ccdc_link_setup - Setup CCDC connections
2532 * return -EINVAL or zero on success
2540 struct isp_device *isp = to_isp_device(ccdc); in ccdc_link_setup() local
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()
2572 * The ISP core doesn't support pipelines with multiple video outputs. in ccdc_link_setup()
2573 * Revisit this when it will be implemented, and return -EBUSY for now. 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()
2615 return 0; 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()
2638 if (ret < 0) in omap3isp_ccdc_register_entities()
2641 ret = omap3isp_video_register(&ccdc->video_out, vdev); in omap3isp_ccdc_register_entities()
2642 if (ret < 0) in omap3isp_ccdc_register_entities()
2645 return 0; in omap3isp_ccdc_register_entities()
2652 /* -----------------------------------------------------------------------------
2653 * ISP CCDC initialisation and cleanup
2657 * ccdc_init_entities - Initialize V4L2 subdev and media entity
2658 * @ccdc: ISP CCDC module
2660 * Return 0 on success and a negative error code on failure.
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()
2685 if (ret < 0) 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()
2697 if (ret < 0) in ccdc_init_entities()
2700 return 0; in ccdc_init_entities()
2708 * omap3isp_ccdc_init - CCDC module initialization.
2709 * @isp: Device pointer specific to the OMAP3 ISP.
2713 * Return 0 on success or a negative error code otherwise.
2715 int omap3isp_ccdc_init(struct isp_device *isp) in omap3isp_ccdc_init() argument
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()
2738 if (ret < 0) { in omap3isp_ccdc_init()
2739 mutex_destroy(&ccdc->ioctl_lock); in omap3isp_ccdc_init()
2743 return 0; in omap3isp_ccdc_init()
2747 * omap3isp_ccdc_cleanup - CCDC module cleanup.
2748 * @isp: Device pointer specific to the OMAP3 ISP.
2750 void omap3isp_ccdc_cleanup(struct isp_device *isp) in omap3isp_ccdc_cleanup() argument
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()
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()