Commit 2c1bb62e authored by Sylwester Nawrocki's avatar Sylwester Nawrocki Committed by Mauro Carvalho Chehab

[media] s5p-fimc: Fix buffer dequeue order issue

When requested more than 2 buffers the buffer dequeue order was wrong
due to erroneous updating FIMC registers in every interrupt handler
call. This also fixes regression of resetting the output DMA buffer
pointer at wrong time, when some buffers are already queued in hardware.
The hardware is reset in the start_streaming callback in order to align
the H/W state with the software output buffer pointer (buf_index).

Additionally a simple write to S5P_CISCCTRL register is replaced with
a read/modification/write to make sure the scaler is not being disabled
in fimc_hw_set_scaler().
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 7aa9f184
...@@ -98,6 +98,10 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) ...@@ -98,6 +98,10 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
} }
set_bit(ST_CAPT_SUSPENDED, &fimc->state); set_bit(ST_CAPT_SUSPENDED, &fimc->state);
fimc_hw_reset(fimc);
cap->buf_index = 0;
spin_unlock_irqrestore(&fimc->slock, flags); spin_unlock_irqrestore(&fimc->slock, flags);
if (streaming) if (streaming)
...@@ -137,7 +141,7 @@ int fimc_capture_config_update(struct fimc_ctx *ctx) ...@@ -137,7 +141,7 @@ int fimc_capture_config_update(struct fimc_ctx *ctx)
struct fimc_dev *fimc = ctx->fimc_dev; struct fimc_dev *fimc = ctx->fimc_dev;
int ret; int ret;
if (test_bit(ST_CAPT_APPLY_CFG, &fimc->state)) if (!test_bit(ST_CAPT_APPLY_CFG, &fimc->state))
return 0; return 0;
spin_lock(&ctx->slock); spin_lock(&ctx->slock);
...@@ -150,7 +154,7 @@ int fimc_capture_config_update(struct fimc_ctx *ctx) ...@@ -150,7 +154,7 @@ int fimc_capture_config_update(struct fimc_ctx *ctx)
fimc_hw_set_rotation(ctx); fimc_hw_set_rotation(ctx);
fimc_prepare_dma_offset(ctx, &ctx->d_frame); fimc_prepare_dma_offset(ctx, &ctx->d_frame);
fimc_hw_set_out_dma(ctx); fimc_hw_set_out_dma(ctx);
set_bit(ST_CAPT_APPLY_CFG, &fimc->state); clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
} }
spin_unlock(&ctx->slock); spin_unlock(&ctx->slock);
return ret; return ret;
...@@ -164,7 +168,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) ...@@ -164,7 +168,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
int min_bufs; int min_bufs;
int ret; int ret;
fimc_hw_reset(fimc);
vid_cap->frame_count = 0; vid_cap->frame_count = 0;
ret = fimc_init_capture(fimc); ret = fimc_init_capture(fimc);
......
...@@ -1706,8 +1706,6 @@ static int fimc_runtime_resume(struct device *dev) ...@@ -1706,8 +1706,6 @@ static int fimc_runtime_resume(struct device *dev)
/* Enable clocks and perform basic initalization */ /* Enable clocks and perform basic initalization */
clk_enable(fimc->clock[CLK_GATE]); clk_enable(fimc->clock[CLK_GATE]);
fimc_hw_reset(fimc); fimc_hw_reset(fimc);
if (fimc->variant->out_buf_count > 4)
fimc_hw_set_dma_seq(fimc, 0xF);
/* Resume the capture or mem-to-mem device */ /* Resume the capture or mem-to-mem device */
if (fimc_capture_busy(fimc)) if (fimc_capture_busy(fimc))
...@@ -1749,8 +1747,6 @@ static int fimc_resume(struct device *dev) ...@@ -1749,8 +1747,6 @@ static int fimc_resume(struct device *dev)
return 0; return 0;
} }
fimc_hw_reset(fimc); fimc_hw_reset(fimc);
if (fimc->variant->out_buf_count > 4)
fimc_hw_set_dma_seq(fimc, 0xF);
spin_unlock_irqrestore(&fimc->slock, flags); spin_unlock_irqrestore(&fimc->slock, flags);
if (fimc_capture_busy(fimc)) if (fimc_capture_busy(fimc))
......
...@@ -35,6 +35,9 @@ void fimc_hw_reset(struct fimc_dev *dev) ...@@ -35,6 +35,9 @@ void fimc_hw_reset(struct fimc_dev *dev)
cfg = readl(dev->regs + S5P_CIGCTRL); cfg = readl(dev->regs + S5P_CIGCTRL);
cfg &= ~S5P_CIGCTRL_SWRST; cfg &= ~S5P_CIGCTRL_SWRST;
writel(cfg, dev->regs + S5P_CIGCTRL); writel(cfg, dev->regs + S5P_CIGCTRL);
if (dev->variant->out_buf_count > 4)
fimc_hw_set_dma_seq(dev, 0xF);
} }
static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx) static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
...@@ -251,7 +254,14 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx) ...@@ -251,7 +254,14 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
struct fimc_scaler *sc = &ctx->scaler; struct fimc_scaler *sc = &ctx->scaler;
struct fimc_frame *src_frame = &ctx->s_frame; struct fimc_frame *src_frame = &ctx->s_frame;
struct fimc_frame *dst_frame = &ctx->d_frame; struct fimc_frame *dst_frame = &ctx->d_frame;
u32 cfg = 0;
u32 cfg = readl(dev->regs + S5P_CISCCTRL);
cfg &= ~(S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE |
S5P_CISCCTRL_SCALEUP_H | S5P_CISCCTRL_SCALEUP_V |
S5P_CISCCTRL_SCALERBYPASS | S5P_CISCCTRL_ONE2ONE |
S5P_CISCCTRL_INRGB_FMT_MASK | S5P_CISCCTRL_OUTRGB_FMT_MASK |
S5P_CISCCTRL_INTERLACE | S5P_CISCCTRL_RGB_EXT);
if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW)) if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE); cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
...@@ -308,9 +318,9 @@ void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) ...@@ -308,9 +318,9 @@ void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
fimc_hw_set_scaler(ctx); fimc_hw_set_scaler(ctx);
cfg = readl(dev->regs + S5P_CISCCTRL); cfg = readl(dev->regs + S5P_CISCCTRL);
cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK);
if (variant->has_mainscaler_ext) { if (variant->has_mainscaler_ext) {
cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK);
cfg |= S5P_CISCCTRL_MHRATIO_EXT(sc->main_hratio); cfg |= S5P_CISCCTRL_MHRATIO_EXT(sc->main_hratio);
cfg |= S5P_CISCCTRL_MVRATIO_EXT(sc->main_vratio); cfg |= S5P_CISCCTRL_MVRATIO_EXT(sc->main_vratio);
writel(cfg, dev->regs + S5P_CISCCTRL); writel(cfg, dev->regs + S5P_CISCCTRL);
...@@ -323,7 +333,6 @@ void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) ...@@ -323,7 +333,6 @@ void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
cfg |= S5P_CIEXTEN_MVRATIO_EXT(sc->main_vratio); cfg |= S5P_CIEXTEN_MVRATIO_EXT(sc->main_vratio);
writel(cfg, dev->regs + S5P_CIEXTEN); writel(cfg, dev->regs + S5P_CIEXTEN);
} else { } else {
cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK);
cfg |= S5P_CISCCTRL_MHRATIO(sc->main_hratio); cfg |= S5P_CISCCTRL_MHRATIO(sc->main_hratio);
cfg |= S5P_CISCCTRL_MVRATIO(sc->main_vratio); cfg |= S5P_CISCCTRL_MVRATIO(sc->main_vratio);
writel(cfg, dev->regs + S5P_CISCCTRL); writel(cfg, dev->regs + S5P_CISCCTRL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment