diff options
Diffstat (limited to 'drivers/staging/media/imx/imx7-media-csi.c')
-rw-r--r-- | drivers/staging/media/imx/imx7-media-csi.c | 169 |
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); |