summaryrefslogtreecommitdiff
path: root/drivers/media/platform/stm32/stm32-dcmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/stm32/stm32-dcmi.c')
-rw-r--r--drivers/media/platform/stm32/stm32-dcmi.c63
1 files changed, 57 insertions, 6 deletions
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index fd1c41cba52f..b745f1342c2e 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -157,6 +157,7 @@ struct stm32_dcmi {
struct vb2_queue queue;
struct v4l2_fwnode_bus_parallel bus;
+ enum v4l2_mbus_type bus_type;
struct completion complete;
struct clk *mclk;
enum state state;
@@ -324,7 +325,7 @@ static int dcmi_start_dma(struct stm32_dcmi *dcmi,
}
/*
- * Avoid call of dmaengine_terminate_all() between
+ * Avoid call of dmaengine_terminate_sync() between
* dmaengine_prep_slave_single() and dmaengine_submit()
* by locking the whole DMA submission sequence
*/
@@ -438,7 +439,7 @@ static void dcmi_process_jpeg(struct stm32_dcmi *dcmi)
}
/* Abort DMA operation */
- dmaengine_terminate_all(dcmi->dma_chan);
+ dmaengine_terminate_sync(dcmi->dma_chan);
/* Restart capture */
if (dcmi_restart_capture(dcmi))
@@ -777,6 +778,23 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
if (dcmi->bus.flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
val |= CR_PCKPOL;
+ /*
+ * BT656 embedded synchronisation bus mode.
+ *
+ * Default SAV/EAV mode is supported here with default codes
+ * SAV=0xff000080 & EAV=0xff00009d.
+ * With DCMI this means LSC=SAV=0x80 & LEC=EAV=0x9d.
+ */
+ if (dcmi->bus_type == V4L2_MBUS_BT656) {
+ val |= CR_ESS;
+
+ /* Unmask all codes */
+ reg_write(dcmi->regs, DCMI_ESUR, 0xffffffff);/* FEC:LEC:LSC:FSC */
+
+ /* Trig on LSC=0x80 & LEC=0x9d codes, ignore FSC and FEC */
+ reg_write(dcmi->regs, DCMI_ESCR, 0xff9d80ff);/* FEC:LEC:LSC:FSC */
+ }
+
reg_write(dcmi->regs, DCMI_CR, val);
/* Set crop */
@@ -882,7 +900,7 @@ static void dcmi_stop_streaming(struct vb2_queue *vq)
/* Stop all pending DMA operations */
mutex_lock(&dcmi->dma_lock);
- dmaengine_terminate_all(dcmi->dma_chan);
+ dmaengine_terminate_sync(dcmi->dma_chan);
mutex_unlock(&dcmi->dma_lock);
pm_runtime_put(dcmi->dev);
@@ -1067,8 +1085,9 @@ static int dcmi_set_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f)
if (ret)
return ret;
- /* Disable crop if JPEG is requested */
- if (pix->pixelformat == V4L2_PIX_FMT_JPEG)
+ /* Disable crop if JPEG is requested or BT656 bus is selected */
+ if (pix->pixelformat == V4L2_PIX_FMT_JPEG &&
+ dcmi->bus_type != V4L2_MBUS_BT656)
dcmi->do_crop = false;
/* pix to mbus format */
@@ -1574,6 +1593,22 @@ static const struct dcmi_format dcmi_formats[] = {
.fourcc = V4L2_PIX_FMT_JPEG,
.mbus_code = MEDIA_BUS_FMT_JPEG_1X8,
.bpp = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SBGGR8,
+ .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .bpp = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGBRG8,
+ .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
+ .bpp = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGRBG8,
+ .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .bpp = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SRGGB8,
+ .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
+ .bpp = 1,
},
};
@@ -1592,6 +1627,11 @@ static int dcmi_formats_init(struct stm32_dcmi *dcmi)
if (dcmi_formats[i].mbus_code != mbus_code.code)
continue;
+ /* Exclude JPEG if BT656 bus is selected */
+ if (dcmi_formats[i].fourcc == V4L2_PIX_FMT_JPEG &&
+ dcmi->bus_type == V4L2_MBUS_BT656)
+ continue;
+
/* Code supported, have we got this fourcc yet? */
for (j = 0; j < num_fmts; j++)
if (sd_fmts[j]->fourcc ==
@@ -1851,7 +1891,9 @@ static int dcmi_probe(struct platform_device *pdev)
dcmi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(dcmi->rstc)) {
- dev_err(&pdev->dev, "Could not get reset control\n");
+ if (PTR_ERR(dcmi->rstc) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Could not get reset control\n");
+
return PTR_ERR(dcmi->rstc);
}
@@ -1873,9 +1915,18 @@ static int dcmi_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "CSI bus not supported\n");
return -ENODEV;
}
+
+ if (ep.bus_type == V4L2_MBUS_BT656 &&
+ ep.bus.parallel.bus_width != 8) {
+ dev_err(&pdev->dev, "BT656 bus conflicts with %u bits bus width (8 bits required)\n",
+ ep.bus.parallel.bus_width);
+ return -ENODEV;
+ }
+
dcmi->bus.flags = ep.bus.parallel.flags;
dcmi->bus.bus_width = ep.bus.parallel.bus_width;
dcmi->bus.data_shift = ep.bus.parallel.data_shift;
+ dcmi->bus_type = ep.bus_type;
irq = platform_get_irq(pdev, 0);
if (irq <= 0)