aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/staging/media/imx/imx7-media-csi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/imx/imx7-media-csi.c')
-rw-r--r--drivers/staging/media/imx/imx7-media-csi.c169
1 files changed, 61 insertions, 108 deletions
diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c
index a708a0340eb1..f775870df7e0 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -152,8 +152,6 @@
#define CSI_CSICR18 0x48
#define CSI_CSICR19 0x4c
-static const char * const imx7_csi_clk_id[] = {"axi", "dcic", "mclk"};
-
struct imx7_csi {
struct device *dev;
struct v4l2_subdev sd;
@@ -180,9 +178,7 @@ struct imx7_csi {
void __iomem *regbase;
int irq;
-
- int num_clks;
- struct clk_bulk_data *clks;
+ struct clk *mclk;
/* active vb2 buffers to send to video dev sink */
struct imx_media_buffer *active_vb2_buf[2];
@@ -199,23 +195,15 @@ struct imx7_csi {
struct completion last_eof_completion;
};
-#define imx7_csi_reg_read(_csi, _offset) \
- __raw_readl((_csi)->regbase + (_offset))
-#define imx7_csi_reg_write(_csi, _val, _offset) \
- __raw_writel(_val, (_csi)->regbase + (_offset))
-
-static void imx7_csi_clk_enable(struct imx7_csi *csi)
+static u32 imx7_csi_reg_read(struct imx7_csi *csi, unsigned int offset)
{
- int ret;
-
- ret = clk_bulk_prepare_enable(csi->num_clks, csi->clks);
- if (ret < 0)
- dev_err(csi->dev, "failed to enable clocks\n");
+ return readl(csi->regbase + offset);
}
-static void imx7_csi_clk_disable(struct imx7_csi *csi)
+static void imx7_csi_reg_write(struct imx7_csi *csi, unsigned int value,
+ unsigned int offset)
{
- clk_bulk_disable_unprepare(csi->num_clks, csi->clks);
+ writel(value, csi->regbase + offset);
}
static void imx7_csi_hw_reset(struct imx7_csi *csi)
@@ -229,9 +217,9 @@ static void imx7_csi_hw_reset(struct imx7_csi *csi)
imx7_csi_reg_write(csi, CSICR3_RESET_VAL, CSI_CSICR3);
}
-static unsigned long imx7_csi_irq_clear(struct imx7_csi *csi)
+static u32 imx7_csi_irq_clear(struct imx7_csi *csi)
{
- unsigned long isr;
+ u32 isr;
isr = imx7_csi_reg_read(csi, CSI_CSISR);
imx7_csi_reg_write(csi, isr, CSI_CSISR);
@@ -257,7 +245,7 @@ static void imx7_csi_init_interface(struct imx7_csi *csi)
static void imx7_csi_hw_enable_irq(struct imx7_csi *csi)
{
- unsigned long cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
+ u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
cr1 |= BIT_SOF_INTEN;
cr1 |= BIT_RFF_OR_INT;
@@ -273,7 +261,7 @@ static void imx7_csi_hw_enable_irq(struct imx7_csi *csi)
static void imx7_csi_hw_disable_irq(struct imx7_csi *csi)
{
- unsigned long cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
+ u32 cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
cr1 &= ~BIT_SOF_INTEN;
cr1 &= ~BIT_RFF_OR_INT;
@@ -286,7 +274,7 @@ static void imx7_csi_hw_disable_irq(struct imx7_csi *csi)
static void imx7_csi_hw_enable(struct imx7_csi *csi)
{
- unsigned long cr = imx7_csi_reg_read(csi, CSI_CSICR18);
+ u32 cr = imx7_csi_reg_read(csi, CSI_CSICR18);
cr |= BIT_CSI_HW_ENABLE;
@@ -295,7 +283,7 @@ static void imx7_csi_hw_enable(struct imx7_csi *csi)
static void imx7_csi_hw_disable(struct imx7_csi *csi)
{
- unsigned long cr = imx7_csi_reg_read(csi, CSI_CSICR18);
+ u32 cr = imx7_csi_reg_read(csi, CSI_CSICR18);
cr &= ~BIT_CSI_HW_ENABLE;
@@ -304,7 +292,7 @@ static void imx7_csi_hw_disable(struct imx7_csi *csi)
static void imx7_csi_dma_reflash(struct imx7_csi *csi)
{
- unsigned long cr3 = imx7_csi_reg_read(csi, CSI_CSICR18);
+ u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR18);
cr3 = imx7_csi_reg_read(csi, CSI_CSICR3);
cr3 |= BIT_DMA_REFLASH_RFF;
@@ -313,7 +301,7 @@ static void imx7_csi_dma_reflash(struct imx7_csi *csi)
static void imx7_csi_rx_fifo_clear(struct imx7_csi *csi)
{
- unsigned long cr1;
+ u32 cr1;
cr1 = imx7_csi_reg_read(csi, CSI_CSICR1);
imx7_csi_reg_write(csi, cr1 & ~BIT_FCC, CSI_CSICR1);
@@ -331,7 +319,7 @@ static void imx7_csi_buf_stride_set(struct imx7_csi *csi, u32 stride)
static void imx7_csi_deinterlace_enable(struct imx7_csi *csi, bool enable)
{
- unsigned long cr18 = imx7_csi_reg_read(csi, CSI_CSICR18);
+ u32 cr18 = imx7_csi_reg_read(csi, CSI_CSICR18);
if (enable)
cr18 |= BIT_DEINTERLACE_EN;
@@ -343,8 +331,8 @@ static void imx7_csi_deinterlace_enable(struct imx7_csi *csi, bool enable)
static void imx7_csi_dmareq_rff_enable(struct imx7_csi *csi)
{
- unsigned long cr3 = imx7_csi_reg_read(csi, CSI_CSICR3);
- unsigned long cr2 = imx7_csi_reg_read(csi, CSI_CSICR2);
+ u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3);
+ u32 cr2 = imx7_csi_reg_read(csi, CSI_CSICR2);
/* Burst Type of DMA Transfer from RxFIFO. INCR16 */
cr2 |= 0xC0000000;
@@ -360,7 +348,7 @@ static void imx7_csi_dmareq_rff_enable(struct imx7_csi *csi)
static void imx7_csi_dmareq_rff_disable(struct imx7_csi *csi)
{
- unsigned long cr3 = imx7_csi_reg_read(csi, CSI_CSICR3);
+ u32 cr3 = imx7_csi_reg_read(csi, CSI_CSICR3);
cr3 &= ~BIT_DMA_REQ_EN_RFF;
cr3 &= ~BIT_HRESP_ERR_EN;
@@ -408,17 +396,23 @@ static void imx7_csi_error_recovery(struct imx7_csi *csi)
imx7_csi_hw_enable(csi);
}
-static void imx7_csi_init(struct imx7_csi *csi)
+static int imx7_csi_init(struct imx7_csi *csi)
{
+ int ret;
+
if (csi->is_init)
- return;
+ return 0;
- imx7_csi_clk_enable(csi);
+ ret = clk_prepare_enable(csi->mclk);
+ if (ret < 0)
+ return ret;
imx7_csi_hw_reset(csi);
imx7_csi_init_interface(csi);
imx7_csi_dmareq_rff_enable(csi);
csi->is_init = true;
+
+ return 0;
}
static void imx7_csi_deinit(struct imx7_csi *csi)
@@ -429,7 +423,7 @@ static void imx7_csi_deinit(struct imx7_csi *csi)
imx7_csi_hw_reset(csi);
imx7_csi_init_interface(csi);
imx7_csi_dmareq_rff_disable(csi);
- imx7_csi_clk_disable(csi);
+ clk_disable_unprepare(csi->mclk);
csi->is_init = false;
}
@@ -448,11 +442,19 @@ static int imx7_csi_get_upstream_endpoint(struct imx7_csi *csi,
src = &csi->src_sd->entity;
+ /*
+ * if the source is neither a mux or csi2 get the one directly upstream
+ * from this csi
+ */
+ if (src->function != MEDIA_ENT_F_VID_IF_BRIDGE &&
+ src->function != MEDIA_ENT_F_VID_MUX)
+ src = &csi->sd.entity;
+
skip_video_mux:
/* get source pad of entity directly upstream from src */
- pad = imx_media_find_upstream_pad(csi->imxmd, src, 0);
- if (IS_ERR(pad))
- return PTR_ERR(pad);
+ pad = imx_media_pipeline_pad(src, 0, 0, true);
+ if (!pad)
+ return -ENODEV;
sd = media_entity_to_v4l2_subdev(pad->entity);
@@ -531,7 +533,7 @@ static int imx7_csi_link_setup(struct media_entity *entity,
init:
if (csi->sink || csi->src_sd)
- imx7_csi_init(csi);
+ ret = imx7_csi_init(csi);
else
imx7_csi_deinit(csi);
@@ -653,7 +655,7 @@ static void imx7_csi_vb2_buf_done(struct imx7_csi *csi)
static irqreturn_t imx7_csi_irq_handler(int irq, void *data)
{
struct imx7_csi *csi = data;
- unsigned long status;
+ u32 status;
spin_lock(&csi->irqlock);
@@ -714,7 +716,7 @@ static int imx7_csi_dma_start(struct imx7_csi *csi)
struct v4l2_pix_format *out_pix = &vdev->fmt.fmt.pix;
int ret;
- ret = imx_media_alloc_dma_buf(csi->imxmd, &csi->underrun_buf,
+ ret = imx_media_alloc_dma_buf(csi->dev, &csi->underrun_buf,
out_pix->sizeimage);
if (ret < 0) {
v4l2_warn(&csi->sd, "consider increasing the CMA area\n");
@@ -754,7 +756,7 @@ static void imx7_csi_dma_stop(struct imx7_csi *csi)
imx7_csi_dma_unsetup_vb2_buf(csi, VB2_BUF_STATE_ERROR);
- imx_media_free_dma_buf(csi->imxmd, &csi->underrun_buf);
+ imx_media_free_dma_buf(csi->dev, &csi->underrun_buf);
}
static int imx7_csi_configure(struct imx7_csi *csi)
@@ -811,7 +813,7 @@ static int imx7_csi_configure(struct imx7_csi *csi)
return 0;
}
-static int imx7_csi_enable(struct imx7_csi *csi)
+static void imx7_csi_enable(struct imx7_csi *csi)
{
imx7_csi_sw_reset(csi);
@@ -819,10 +821,7 @@ static int imx7_csi_enable(struct imx7_csi *csi)
imx7_csi_dmareq_rff_enable(csi);
imx7_csi_hw_enable_irq(csi);
imx7_csi_hw_enable(csi);
- return 0;
}
-
- return 0;
}
static void imx7_csi_disable(struct imx7_csi *csi)
@@ -1021,7 +1020,6 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi,
break;
default:
return -EINVAL;
- break;
}
return 0;
}
@@ -1031,11 +1029,8 @@ static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_format *sdformat)
{
struct imx7_csi *csi = v4l2_get_subdevdata(sd);
- struct imx_media_video_dev *vdev = csi->vdev;
const struct imx_media_pixfmt *outcc;
struct v4l2_mbus_framefmt *outfmt;
- struct v4l2_pix_format vdev_fmt;
- struct v4l2_rect vdev_compose;
const struct imx_media_pixfmt *cc;
struct v4l2_mbus_framefmt *fmt;
struct v4l2_subdev_format format;
@@ -1080,19 +1075,8 @@ static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
csi->cc[IMX7_CSI_PAD_SRC] = outcc;
}
- if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY)
- goto out_unlock;
-
- csi->cc[sdformat->pad] = cc;
-
- /* propagate output pad format to capture device */
- imx_media_mbus_fmt_to_pix_fmt(&vdev_fmt, &vdev_compose,
- &csi->format_mbus[IMX7_CSI_PAD_SRC],
- csi->cc[IMX7_CSI_PAD_SRC]);
- mutex_unlock(&csi->lock);
- imx_media_capture_device_set_format(vdev, &vdev_fmt, &vdev_compose);
-
- return 0;
+ if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ csi->cc[sdformat->pad] = cc;
out_unlock:
mutex_unlock(&csi->lock);
@@ -1126,17 +1110,7 @@ static int imx7_csi_registered(struct v4l2_subdev *sd)
if (ret < 0)
return ret;
- ret = imx_media_capture_device_register(csi->imxmd, csi->vdev);
- if (ret < 0)
- return ret;
-
- ret = imx_media_add_video_device(csi->imxmd, csi->vdev);
- if (ret < 0) {
- imx_media_capture_device_unregister(csi->vdev);
- return ret;
- }
-
- return 0;
+ return imx_media_capture_device_register(csi->vdev);
}
static void imx7_csi_unregistered(struct v4l2_subdev *sd)
@@ -1200,31 +1174,12 @@ static int imx7_csi_parse_endpoint(struct device *dev,
return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL;
}
-static int imx7_csi_clocks_get(struct imx7_csi *csi)
-{
- struct device *dev = csi->dev;
- int i;
-
- csi->num_clks = ARRAY_SIZE(imx7_csi_clk_id);
- csi->clks = devm_kcalloc(dev, csi->num_clks, sizeof(*csi->clks),
- GFP_KERNEL);
-
- if (!csi->clks)
- return -ENOMEM;
-
- for (i = 0; i < csi->num_clks; i++)
- csi->clks[i].id = imx7_csi_clk_id[i];
-
- return devm_clk_bulk_get(dev, csi->num_clks, csi->clks);
-}
-
static int imx7_csi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct imx_media_dev *imxmd;
struct imx7_csi *csi;
- struct resource *res;
int ret;
csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL);
@@ -1233,24 +1188,22 @@ static int imx7_csi_probe(struct platform_device *pdev)
csi->dev = dev;
- ret = imx7_csi_clocks_get(csi);
- if (ret < 0) {
- dev_err(dev, "Failed to get clocks");
- return -ENODEV;
+ csi->mclk = devm_clk_get(&pdev->dev, "mclk");
+ if (IS_ERR(csi->mclk)) {
+ ret = PTR_ERR(csi->mclk);
+ dev_err(dev, "Failed to get mclk: %d", ret);
+ return ret;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
csi->irq = platform_get_irq(pdev, 0);
- if (!res || csi->irq < 0) {
+ if (csi->irq < 0) {
dev_err(dev, "Missing platform resources data\n");
- return -ENODEV;
+ return csi->irq;
}
- csi->regbase = devm_ioremap_resource(dev, res);
- if (IS_ERR(csi->regbase)) {
- dev_err(dev, "Failed platform resources map\n");
- return -ENODEV;
- }
+ csi->regbase = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(csi->regbase))
+ return PTR_ERR(csi->regbase);
spin_lock_init(&csi->irqlock);
mutex_init(&csi->lock);
@@ -1260,12 +1213,11 @@ static int imx7_csi_probe(struct platform_device *pdev)
(void *)csi);
if (ret < 0) {
dev_err(dev, "Request CSI IRQ failed.\n");
- ret = -ENODEV;
goto destroy_mutex;
}
/* add media device */
- imxmd = imx_media_dev_init(dev);
+ imxmd = imx_media_dev_init(dev, NULL);
if (IS_ERR(imxmd)) {
ret = PTR_ERR(imxmd);
goto destroy_mutex;
@@ -1276,7 +1228,7 @@ static int imx7_csi_probe(struct platform_device *pdev)
if (ret < 0 && ret != -ENODEV && ret != -EEXIST)
goto cleanup;
- ret = imx_media_dev_notifier_register(imxmd);
+ ret = imx_media_dev_notifier_register(imxmd, NULL);
if (ret < 0)
goto cleanup;
@@ -1292,7 +1244,8 @@ static int imx7_csi_probe(struct platform_device *pdev)
csi->sd.grp_id = IMX_MEDIA_GRP_ID_CSI;
snprintf(csi->sd.name, sizeof(csi->sd.name), "csi");
- csi->vdev = imx_media_capture_device_init(&csi->sd, IMX7_CSI_PAD_SRC);
+ csi->vdev = imx_media_capture_device_init(csi->sd.dev, &csi->sd,
+ IMX7_CSI_PAD_SRC);
if (IS_ERR(csi->vdev))
return PTR_ERR(csi->vdev);