Lines Matching +full:imx7 +full:- +full:mipi +full:- +full:csi2
1 // SPDX-License-Identifier: GPL-2.0
3 * NXP i.MX8MQ SoC series MIPI-CSI2 receiver driver
10 #include <linux/clk-provider.h>
28 #include <media/v4l2-common.h>
29 #include <media/v4l2-device.h>
30 #include <media/v4l2-fwnode.h>
31 #include <media/v4l2-mc.h>
32 #include <media/v4l2-subdev.h>
34 #define MIPI_CSI2_DRIVER_NAME "imx8mq-mipi-csi2"
46 /* i.MX8MQ CSI-2 controller CSR */
99 * which the sensor transfers data to the CSI-2 Controller and the user
102 * The calculation is the classical rate-in rate-out type of problem: If the
103 * video bandwidth is 10% faster than the incoming mipi data and the video
135 /* -----------------------------------------------------------------------------
144 /* -----------------------------------------------------------------------------
156 regmap_update_bits(state->phy_gpr,
157 state->phy_gpr_reg,
172 /* -----------------------------------------------------------------------------
208 regmap_clear_bits(state->phy_gpr, CSI2SS_DATA_TYPE_DISABLE_BF,
211 regmap_write(state->phy_gpr, CSI2SS_PLM_CTRL, 0x0);
213 regmap_write(state->phy_gpr, CSI2SS_PHY_CTRL,
219 ret = regmap_read_poll_timeout(state->phy_gpr, CSI2SS_PLM_CTRL,
225 dev_err(state->dev, "Timeout waiting for Pixel-Link clock\n");
230 regmap_set_bits(state->phy_gpr, CSI2SS_PLM_CTRL,
234 regmap_clear_bits(state->phy_gpr, CSI2SS_PHY_CTRL,
238 regmap_set_bits(state->phy_gpr, CSI2SS_CTRL_CLK_RESET, CSI2SS_CTRL_CLK_RESET_EN);
246 regmap_write(state->phy_gpr, CSI2SS_PLM_CTRL, 0x0);
249 regmap_write(state->phy_gpr, CSI2SS_PHY_CTRL, 0x0);
251 regmap_clear_bits(state->phy_gpr, CSI2SS_CTRL_CLK_RESET,
341 /* -----------------------------------------------------------------------------
347 writel(val, state->regs + reg);
355 * these are most likely self-clearing reset bits. to make it
356 * more clear, the reset-imx7 driver should implement the
359 ret = reset_control_assert(state->rst);
361 dev_err(state->dev, "Failed to assert resets: %d\n", ret);
370 int lanes = state->bus.num_data_lanes;
372 imx8mq_mipi_csi_write(state, CSI2RX_CFG_NUM_LANES, lanes - 1);
389 return clk_bulk_prepare_enable(CSI2_NUM_CLKS, state->clks);
394 clk_bulk_disable_unprepare(CSI2_NUM_CLKS, state->clks);
402 state->clks[i].id = imx8mq_mipi_csi_clk_id[i];
404 return devm_clk_bulk_get(state->dev, CSI2_NUM_CLKS, state->clks);
419 src_pad = media_entity_remote_source_pad_unique(&sd_state->sd->entity);
421 dev_err(state->dev, "can't get source pad of %s (%ld)\n",
422 sd_state->sd->name, PTR_ERR(src_pad));
429 csi2_fmt = find_csi2_format(fmt->code);
431 link_freq = v4l2_get_link_freq(src_pad, csi2_fmt->width,
432 state->bus.num_data_lanes * 2);
434 dev_err(state->dev, "Unable to obtain link frequency: %d\n",
441 dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate);
442 return -EINVAL;
446 * The D-PHY specification requires Ths-settle to be in the range
450 * The Ths-settle value is expressed in the hardware as a multiple of
453 * Ths-settle = (PRG_RXHS_SETTLE + 1) * Tperiod of RxClkInEsc
459 esc_clk_rate = clk_get_rate(state->clks[CSI2_CLK_ESC].clk);
461 dev_err(state->dev, "Could not get esc clock rate.\n");
462 return -EINVAL;
465 dev_dbg(state->dev, "esc clk rate: %lu\n", esc_clk_rate);
472 *hs_settle = ths_settle_ns / esc_clk_period_ns - 1;
474 dev_dbg(state->dev, "lane rate %u Ths_settle %u hs_settle %u\n",
495 ret = state->pdata->enable(state, hs_settle);
506 if (state->pdata->disable)
507 state->pdata->disable(state);
510 /* -----------------------------------------------------------------------------
526 ret = pm_runtime_resume_and_get(state->dev);
531 mutex_lock(&state->lock);
534 if (state->state & ST_SUSPENDED) {
535 ret = -EBUSY;
546 ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1);
550 state->state |= ST_STREAMING;
552 v4l2_subdev_call(state->src_sd, video, s_stream, 0);
554 state->state &= ~ST_STREAMING;
558 mutex_unlock(&state->lock);
561 pm_runtime_put(state->dev);
576 fmt_sink->code = MEDIA_BUS_FMT_SGBRG10_1X10;
577 fmt_sink->width = MIPI_CSI2_DEF_PIX_WIDTH;
578 fmt_sink->height = MIPI_CSI2_DEF_PIX_HEIGHT;
579 fmt_sink->field = V4L2_FIELD_NONE;
581 fmt_sink->colorspace = V4L2_COLORSPACE_RAW;
582 fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
583 fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
584 fmt_sink->quantization =
585 V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
586 fmt_sink->ycbcr_enc);
601 if (code->pad == MIPI_CSI2_PAD_SOURCE) {
604 if (code->index > 0)
605 return -EINVAL;
607 fmt = v4l2_subdev_state_get_format(sd_state, code->pad);
608 code->code = fmt->code;
612 if (code->pad != MIPI_CSI2_PAD_SINK)
613 return -EINVAL;
615 if (code->index >= ARRAY_SIZE(imx8mq_mipi_csi_formats))
616 return -EINVAL;
618 code->code = imx8mq_mipi_csi_formats[code->index].code;
634 if (sdformat->pad == MIPI_CSI2_PAD_SOURCE)
637 if (sdformat->pad != MIPI_CSI2_PAD_SINK)
638 return -EINVAL;
640 csi2_fmt = find_csi2_format(sdformat->format.code);
644 fmt = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
646 fmt->code = csi2_fmt->code;
647 fmt->width = sdformat->format.width;
648 fmt->height = sdformat->format.height;
650 sdformat->format = *fmt;
654 *fmt = sdformat->format;
678 /* -----------------------------------------------------------------------------
687 /* -----------------------------------------------------------------------------
702 struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK];
704 state->src_sd = sd;
724 v4l2_async_subdev_nf_init(&state->notifier, &state->sd);
726 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
729 return -ENOTCONN;
737 dev_err(state->dev,
739 ret = -EINVAL;
744 state->bus = vep.bus.mipi_csi2;
746 dev_dbg(state->dev, "data lanes: %d flags: 0x%08x\n",
747 state->bus.num_data_lanes,
748 state->bus.flags);
750 asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
759 state->notifier.ops = &imx8mq_mipi_csi_notify_ops;
761 ret = v4l2_async_nf_register(&state->notifier);
765 return v4l2_async_register_subdev(&state->sd);
773 /* -----------------------------------------------------------------------------
782 mutex_lock(&state->lock);
784 if (state->state & ST_POWERED) {
787 state->state &= ~ST_POWERED;
790 mutex_unlock(&state->lock);
800 mutex_lock(&state->lock);
802 if (!(state->state & ST_POWERED)) {
803 state->state |= ST_POWERED;
806 if (state->state & ST_STREAMING) {
814 state->state &= ~ST_SUSPENDED;
817 mutex_unlock(&state->lock);
819 return ret ? -EAGAIN : 0;
829 state->state |= ST_SUSPENDED;
839 if (!(state->state & ST_SUSPENDED))
853 ret = icc_set_bw(state->icc_path, 0, 0);
866 ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw);
881 /* -----------------------------------------------------------------------------
887 struct v4l2_subdev *sd = &state->sd;
891 sd->internal_ops = &imx8mq_mipi_csi_internal_ops;
892 sd->owner = THIS_MODULE;
893 snprintf(sd->name, sizeof(sd->name), "%s %s",
894 MIPI_CSI2_SUBDEV_NAME, dev_name(state->dev));
896 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
898 sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
899 sd->entity.ops = &imx8mq_mipi_csi_entity_ops;
901 sd->dev = state->dev;
903 state->pads[MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK
905 state->pads[MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
907 ret = media_entity_pads_init(&sd->entity, MIPI_CSI2_PADS_NUM,
908 state->pads);
914 media_entity_cleanup(&sd->entity);
923 struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
926 icc_put(state->icc_path);
931 struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
935 state->icc_path = of_icc_get(&pdev->dev, "dram");
936 if (IS_ERR_OR_NULL(state->icc_path))
937 return PTR_ERR_OR_ZERO(state->icc_path);
939 state->icc_path_bw = MBps_to_icc(700);
946 struct device *dev = state->dev;
947 struct device_node *np = state->dev->of_node;
953 state->rst = devm_reset_control_array_get_exclusive(dev);
954 if (IS_ERR(state->rst)) {
955 dev_err(dev, "Failed to get reset: %pe\n", state->rst);
956 return PTR_ERR(state->rst);
959 if (state->pdata->use_reg_csr) {
971 state->phy_gpr = devm_regmap_init_mmio(dev, base, ®map_config);
972 if (IS_ERR(state->phy_gpr))
973 return dev_err_probe(dev, PTR_ERR(state->phy_gpr),
978 ret = of_property_read_u32_array(np, "fsl,mipi-phy-gpr", out_val,
981 dev_err(dev, "no fsl,mipi-phy-gpr property found: %d\n", ret);
990 return -ENODEV;
992 state->phy_gpr = syscon_node_to_regmap(node);
994 if (IS_ERR(state->phy_gpr)) {
995 dev_err(dev, "failed to get gpr regmap: %pe\n", state->phy_gpr);
996 return PTR_ERR(state->phy_gpr);
999 state->phy_gpr_reg = out_val[1];
1000 dev_dbg(dev, "phy gpr register set to 0x%x\n", state->phy_gpr_reg);
1007 struct device *dev = &pdev->dev;
1013 return -ENOMEM;
1015 state->dev = dev;
1017 state->pdata = of_device_get_match_data(dev);
1026 state->regs = devm_platform_ioremap_resource(pdev, 0);
1027 if (IS_ERR(state->regs))
1028 return PTR_ERR(state->regs);
1034 platform_set_drvdata(pdev, &state->sd);
1036 mutex_init(&state->lock);
1061 pm_runtime_disable(&pdev->dev);
1062 imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
1064 media_entity_cleanup(&state->sd.entity);
1065 v4l2_subdev_cleanup(&state->sd);
1066 v4l2_async_nf_unregister(&state->notifier);
1067 v4l2_async_nf_cleanup(&state->notifier);
1068 v4l2_async_unregister_subdev(&state->sd);
1072 mutex_destroy(&state->lock);
1082 v4l2_async_nf_unregister(&state->notifier);
1083 v4l2_async_nf_cleanup(&state->notifier);
1084 v4l2_async_unregister_subdev(&state->sd);
1086 pm_runtime_disable(&pdev->dev);
1087 imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
1088 media_entity_cleanup(&state->sd.entity);
1089 v4l2_subdev_cleanup(&state->sd);
1090 mutex_destroy(&state->lock);
1091 pm_runtime_set_suspended(&pdev->dev);
1096 { .compatible = "fsl,imx8mq-mipi-csi2", .data = &imx8mq_data },
1097 { .compatible = "fsl,imx8qxp-mipi-csi2", .data = &imx8qxp_data },
1114 MODULE_DESCRIPTION("i.MX8MQ MIPI CSI-2 receiver driver");
1117 MODULE_ALIAS("platform:imx8mq-mipi-csi2");