From: Wooyeon Kim Date: Mon, 8 Apr 2019 07:44:32 +0000 (+0900) Subject: [COMMON] fimc-is2: move csi dma disable to DMA ISR & modify DMA state. X-Git-Tag: MMI-QSAS30.62-33-3~831 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=bda1c176c3f49a6ff86e3a0e36ca6a3436c5dfcf;p=GitHub%2FMotorolaMobilityLLC%2Fkernel-slsi.git [COMMON] fimc-is2: move csi dma disable to DMA ISR & modify DMA state. - CSIS core start not guerantee CSIS DMA starts. PR JIRA ID: CPR-966 Change-Id: Ifadfe55c34c57c30997e8334b45a19daef5a07c6 Signed-off-by: Wooyeon Kim --- diff --git a/drivers/media/platform/exynos/fimc-is2/fimc-is-device-csi.h b/drivers/media/platform/exynos/fimc-is2/fimc-is-device-csi.h index baa0bebe0ed1..7d8efa2dfd3b 100644 --- a/drivers/media/platform/exynos/fimc-is2/fimc-is-device-csi.h +++ b/drivers/media/platform/exynos/fimc-is2/fimc-is-device-csi.h @@ -96,6 +96,7 @@ struct fimc_is_device_csi { struct work_struct wq_csis_dma[CSI_VIRTUAL_CH_MAX]; struct workqueue_struct *workqueue; int pre_dma_enable[CSI_VIRTUAL_CH_MAX]; + int cur_dma_enable[CSI_VIRTUAL_CH_MAX]; /* subdev slots for dma */ struct fimc_is_subdev *dma_subdev[CSI_VIRTUAL_CH_MAX]; diff --git a/drivers/media/platform/exynos/fimc-is2/fimc-is-device-csi_v4.c b/drivers/media/platform/exynos/fimc-is2/fimc-is-device-csi_v4.c index 0208acaf8447..1db3380db143 100644 --- a/drivers/media/platform/exynos/fimc-is2/fimc-is-device-csi_v4.c +++ b/drivers/media/platform/exynos/fimc-is2/fimc-is-device-csi_v4.c @@ -258,10 +258,9 @@ static void csis_s_vc_dma_multibuf(struct fimc_is_device_csi *csi) } } -static void csis_disable_all_vc_dma_buf(struct fimc_is_device_csi *csi) +static void csis_check_vc_dma_buf(struct fimc_is_device_csi *csi) { u32 vc; - int cur_dma_enable; struct fimc_is_framemgr *framemgr; struct fimc_is_frame *frame; struct fimc_is_subdev *dma_subdev; @@ -276,12 +275,6 @@ static void csis_disable_all_vc_dma_buf(struct fimc_is_device_csi *csi) test_bit(FIMC_IS_SUBDEV_INTERNAL_USE, &dma_subdev->state)) continue; - /* default dma disable */ - csi_s_output_dma(csi, vc, false); - - /* print infomation DMA on/off */ - cur_dma_enable = csi_hw_g_output_cur_dma_enable(csi->vc_reg[csi->scm][vc], vc); - framemgr = GET_SUBDEV_FRAMEMGR(dma_subdev); framemgr_e_barrier(framemgr, 0); if (likely(framemgr)) { @@ -302,22 +295,26 @@ static void csis_disable_all_vc_dma_buf(struct fimc_is_device_csi *csi) * The invalid state indicates that there is process frame at DMA off. */ if (framemgr->queued_count[FS_PROCESS] && - !csi->pre_dma_enable[vc] && !cur_dma_enable) { + !csi->pre_dma_enable[vc] && !csi->cur_dma_enable[vc]) { csi_s_output_dma(csi, vc, true); minfo("[VC%d] DMA on forcely[P(%d)]\n", csi, vc, framemgr->queued_count[FS_PROCESS]); print_frame_queue(framemgr, FS_PROCESS); } + /* print infomation DMA on/off */ if (test_bit(CSIS_START_STREAM, &csi->state) && - csi->pre_dma_enable[vc] != cur_dma_enable) { + csi->pre_dma_enable[vc] != csi->cur_dma_enable[vc]) { minfo("[VC%d][F%d] DMA %s [%d/%d/%d]\n", csi, vc, atomic_read(&csi->fcount), - (cur_dma_enable ? "on" : "off"), + (csi->cur_dma_enable[vc] ? "on" : "off"), framemgr->queued_count[FS_REQUEST], framemgr->queued_count[FS_PROCESS], framemgr->queued_count[FS_COMPLETE]); - csi->pre_dma_enable[vc] = cur_dma_enable; + csi->pre_dma_enable[vc] = csi->cur_dma_enable[vc]; } + + /* after update pre_dma_disable, clear dma enable state */ + csi->cur_dma_enable[vc] = 0; } else { merr("[VC%d] framemgr is NULL", csi, vc); } @@ -533,8 +530,8 @@ void tasklet_csis_str_otf(unsigned long data) } trigger_skip: - /* disable all virtual channel's dma */ - csis_disable_all_vc_dma_buf(csi); + /* check all virtual channel's dma */ + csis_check_vc_dma_buf(csi); /* re-set internal vc dma if flushed */ csis_s_vc_dma_multibuf(csi); @@ -563,8 +560,8 @@ void tasklet_csis_str_m2m(unsigned long data) #ifdef TASKLET_MSG pr_info("S%d\n", fcount); #endif - /* disable all virtual channel's dma */ - csis_disable_all_vc_dma_buf(csi); + /* check all virtual channel's dma */ + csis_check_vc_dma_buf(csi); /* re-set internal vc dma if flushed */ csis_s_vc_dma_multibuf(csi); @@ -1083,6 +1080,7 @@ static inline void csi_wq_func_schedule(struct fimc_is_device_csi *csi, static irqreturn_t fimc_is_isr_csi_dma(int irq, void *data) { struct fimc_is_device_csi *csi; + int dma_frame_str = 0; int dma_frame_end = 0; int dma_err_flag = 0; u32 dma_err_id[CSI_VIRTUAL_CH_MAX]; @@ -1113,14 +1111,16 @@ static irqreturn_t fimc_is_isr_csi_dma(int irq, void *data) dma_err_id[vc] = irq_src.err_id[vc_phys]; dma_err_flag |= dma_err_id[vc]; + if (irq_src.dma_start) + dma_frame_str |= 1 << vc; + if (irq_src.dma_end) dma_frame_end |= 1 << vc; } - dbg_isr("DE %d %X\n", csi, csi->instance, dma_frame_end); - /* DMA End */ if (dma_frame_end) { + dbg_isr("DE %d %X\n", csi, csi->instance, dma_frame_end); #if !defined(SUPPORTED_EARLYBUF_DONE_HW) /* VC0 */ if (csi->dma_subdev[CSI_VIRTUAL_CH_0] && (dma_frame_end & (1 << CSI_VIRTUAL_CH_0))) { @@ -1153,6 +1153,19 @@ static irqreturn_t fimc_is_isr_csi_dma(int irq, void *data) } } + if (dma_frame_str) { + dbg_isr("DS %d %X\n", csi, csi->instance, dma_frame_str); + for (vc = CSI_VIRTUAL_CH_0; vc < CSI_VIRTUAL_CH_MAX; vc++) { + if (!csi->dma_subdev[vc] || + !test_bit(FIMC_IS_SUBDEV_OPEN, &csi->dma_subdev[vc]->state) || + test_bit(FIMC_IS_SUBDEV_INTERNAL_USE, &csi->dma_subdev[vc]->state)) + continue; + + /* dma disable if interrupt occured */ + csi_s_output_dma(csi, vc, false); + } + } + /* Check error */ if (dma_err_flag) csi_err_check(csi, dma_err_id); @@ -1534,6 +1547,7 @@ static int csi_stream_on(struct v4l2_subdev *subdev, csi->overflow_cnt = 0; csi_s_config_dma(csi, sensor_cfg->output); memset(csi->pre_dma_enable, -1, sizeof(csi->pre_dma_enable)); + memset(csi->cur_dma_enable, -1, sizeof(csi->cur_dma_enable)); /* for multi frame buffer setting for internal vc */ csis_s_vc_dma_multibuf(csi); @@ -1885,6 +1899,7 @@ static int csi_s_buffer(struct v4l2_subdev *subdev, void *buf, unsigned int *siz } else { csi_s_buf_addr(csi, frame, 0, vc); csi_s_output_dma(csi, vc, true); + csi->cur_dma_enable[vc] = 1; trans_frame(framemgr, frame, FS_PROCESS); }