Lines Matching +full:lane +full:- +full:polarities

1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for ST MIPID02 CSI-2 to PARALLEL bridge
20 #include <media/mipi-csi2.h>
21 #include <media/v4l2-async.h>
22 #include <media/v4l2-cci.h>
23 #include <media/v4l2-ctrls.h>
24 #include <media/v4l2-device.h>
25 #include <media/v4l2-fwnode.h>
26 #include <media/v4l2-subdev.h>
221 bridge->supplies[i].supply = mipid02_supply_name[i]; in mipid02_get_regulators()
223 return devm_regulator_bulk_get(&bridge->i2c_client->dev, in mipid02_get_regulators()
225 bridge->supplies); in mipid02_get_regulators()
230 gpiod_set_value_cansleep(bridge->reset_gpio, 0); in mipid02_apply_reset()
232 gpiod_set_value_cansleep(bridge->reset_gpio, 1); in mipid02_apply_reset()
234 gpiod_set_value_cansleep(bridge->reset_gpio, 0); in mipid02_apply_reset()
242 struct i2c_client *client = bridge->i2c_client; in mipid02_set_power_on()
245 ret = clk_prepare_enable(bridge->xclk); in mipid02_set_power_on()
247 dev_err(&client->dev, "%s: failed to enable clock\n", __func__); in mipid02_set_power_on()
252 bridge->supplies); in mipid02_set_power_on()
254 dev_err(&client->dev, "%s: failed to enable regulators\n", in mipid02_set_power_on()
259 if (bridge->reset_gpio) { in mipid02_set_power_on()
260 dev_dbg(&client->dev, "apply reset"); in mipid02_set_power_on()
263 dev_dbg(&client->dev, "don't apply reset"); in mipid02_set_power_on()
270 clk_disable_unprepare(bridge->xclk); in mipid02_set_power_on()
279 regulator_bulk_disable(MIPID02_NUM_SUPPLIES, bridge->supplies); in mipid02_set_power_off()
280 clk_disable_unprepare(bridge->xclk); in mipid02_set_power_off()
293 return cci_read(bridge->regmap, MIPID02_CLK_LANE_WR_REG1, &reg, NULL); in mipid02_detect()
305 &bridge->s_subdev->entity.pads[bridge->s_subdev_pad_id]; in mipid02_configure_from_rx_speed()
306 struct i2c_client *client = bridge->i2c_client; in mipid02_configure_from_rx_speed()
307 struct v4l2_fwnode_endpoint *ep = &bridge->rx; in mipid02_configure_from_rx_speed()
308 u32 bpp = bpp_from_code(fmt->code); in mipid02_configure_from_rx_speed()
317 2 * ep->bus.mipi_csi2.num_data_lanes); in mipid02_configure_from_rx_speed()
319 dev_err(&client->dev, "Failed to get link frequency"); in mipid02_configure_from_rx_speed()
320 return -EINVAL; in mipid02_configure_from_rx_speed()
323 dev_dbg(&client->dev, "detect link_freq = %lld Hz", link_freq); in mipid02_configure_from_rx_speed()
325 bridge->r.clk_lane_reg1 |= ui_4 << 2; in mipid02_configure_from_rx_speed()
332 struct i2c_client *client = bridge->i2c_client; in mipid02_configure_clk_lane()
333 struct v4l2_fwnode_endpoint *ep = &bridge->rx; in mipid02_configure_clk_lane()
334 bool *polarities = ep->bus.mipi_csi2.lane_polarities; in mipid02_configure_clk_lane() local
336 /* midid02 doesn't support clock lane remapping */ in mipid02_configure_clk_lane()
337 if (ep->bus.mipi_csi2.clock_lane != 0) { in mipid02_configure_clk_lane()
338 dev_err(&client->dev, "clk lane must be map to lane 0\n"); in mipid02_configure_clk_lane()
339 return -EINVAL; in mipid02_configure_clk_lane()
341 bridge->r.clk_lane_reg1 |= (polarities[0] << 1) | CLK_ENABLE; in mipid02_configure_clk_lane()
347 bool are_lanes_swap, bool *polarities) in mipid02_configure_data0_lane() argument
349 bool are_pin_swap = are_lanes_swap ? polarities[2] : polarities[1]; in mipid02_configure_data0_lane()
355 * data lane 0 as pin swap polarity reversed compared to clock and in mipid02_configure_data0_lane()
356 * data lane 1 in mipid02_configure_data0_lane()
359 bridge->r.data_lane0_reg1 = 1 << 1; in mipid02_configure_data0_lane()
360 bridge->r.data_lane0_reg1 |= DATA_ENABLE; in mipid02_configure_data0_lane()
366 bool are_lanes_swap, bool *polarities) in mipid02_configure_data1_lane() argument
368 bool are_pin_swap = are_lanes_swap ? polarities[1] : polarities[2]; in mipid02_configure_data1_lane()
374 bridge->r.data_lane1_reg1 = 1 << 1; in mipid02_configure_data1_lane()
375 bridge->r.data_lane1_reg1 |= DATA_ENABLE; in mipid02_configure_data1_lane()
383 struct v4l2_fwnode_endpoint *ep = &bridge->rx; in mipid02_configure_from_rx()
384 bool are_lanes_swap = ep->bus.mipi_csi2.data_lanes[0] == 2; in mipid02_configure_from_rx()
385 bool *polarities = ep->bus.mipi_csi2.lane_polarities; in mipid02_configure_from_rx() local
386 int nb = ep->bus.mipi_csi2.num_data_lanes; in mipid02_configure_from_rx()
394 polarities); in mipid02_configure_from_rx()
399 polarities); in mipid02_configure_from_rx()
403 bridge->r.mode_reg1 |= are_lanes_swap ? MODE_DATA_SWAP : 0; in mipid02_configure_from_rx()
404 bridge->r.mode_reg1 |= (nb - 1) << 1; in mipid02_configure_from_rx()
411 struct v4l2_fwnode_endpoint *ep = &bridge->tx; in mipid02_configure_from_tx()
413 bridge->r.data_selection_ctrl = SELECTION_MANUAL_WIDTH; in mipid02_configure_from_tx()
414 bridge->r.pix_width_ctrl = ep->bus.parallel.bus_width; in mipid02_configure_from_tx()
415 bridge->r.pix_width_ctrl_emb = ep->bus.parallel.bus_width; in mipid02_configure_from_tx()
416 if (ep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) in mipid02_configure_from_tx()
417 bridge->r.mode_reg2 |= MODE_HSYNC_ACTIVE_HIGH; in mipid02_configure_from_tx()
418 if (ep->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) in mipid02_configure_from_tx()
419 bridge->r.mode_reg2 |= MODE_VSYNC_ACTIVE_HIGH; in mipid02_configure_from_tx()
420 if (ep->bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_RISING) in mipid02_configure_from_tx()
421 bridge->r.mode_reg2 |= MODE_PCLK_SAMPLE_RISING; in mipid02_configure_from_tx()
431 bridge->r.data_id_rreg = 0; in mipid02_configure_from_code()
433 if (fmt->code != MEDIA_BUS_FMT_JPEG_1X8) { in mipid02_configure_from_code()
434 bridge->r.data_selection_ctrl |= SELECTION_MANUAL_DATA; in mipid02_configure_from_code()
436 data_type = data_type_from_code(fmt->code); in mipid02_configure_from_code()
438 return -EINVAL; in mipid02_configure_from_code()
439 bridge->r.data_id_rreg = data_type; in mipid02_configure_from_code()
450 struct i2c_client *client = bridge->i2c_client; in mipid02_disable_streams()
451 int ret = -EINVAL; in mipid02_disable_streams()
453 if (!bridge->s_subdev) in mipid02_disable_streams()
456 ret = v4l2_subdev_disable_streams(bridge->s_subdev, in mipid02_disable_streams()
457 bridge->s_subdev_pad_id, BIT(0)); in mipid02_disable_streams()
462 cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, 0, &ret); in mipid02_disable_streams()
463 cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, 0, &ret); in mipid02_disable_streams()
464 cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret); in mipid02_disable_streams()
468 pm_runtime_put_autosuspend(&client->dev); in mipid02_disable_streams()
472 dev_err(&client->dev, "failed to stream off %d", ret); in mipid02_disable_streams()
482 struct i2c_client *client = bridge->i2c_client; in mipid02_enable_streams()
484 int ret = -EINVAL; in mipid02_enable_streams()
486 if (!bridge->s_subdev) in mipid02_enable_streams()
489 memset(&bridge->r, 0, sizeof(bridge->r)); in mipid02_enable_streams()
504 ret = pm_runtime_resume_and_get(&client->dev); in mipid02_enable_streams()
509 cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, in mipid02_enable_streams()
510 bridge->r.clk_lane_reg1, &ret); in mipid02_enable_streams()
511 cci_write(bridge->regmap, MIPID02_CLK_LANE_REG3, CLK_MIPI_CSI, &ret); in mipid02_enable_streams()
512 cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, in mipid02_enable_streams()
513 bridge->r.data_lane0_reg1, &ret); in mipid02_enable_streams()
514 cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG2, DATA_MIPI_CSI, &ret); in mipid02_enable_streams()
515 cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, in mipid02_enable_streams()
516 bridge->r.data_lane1_reg1, &ret); in mipid02_enable_streams()
517 cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG2, DATA_MIPI_CSI, &ret); in mipid02_enable_streams()
518 cci_write(bridge->regmap, MIPID02_MODE_REG1, in mipid02_enable_streams()
519 MODE_NO_BYPASS | bridge->r.mode_reg1, &ret); in mipid02_enable_streams()
520 cci_write(bridge->regmap, MIPID02_MODE_REG2, bridge->r.mode_reg2, &ret); in mipid02_enable_streams()
521 cci_write(bridge->regmap, MIPID02_DATA_ID_RREG, bridge->r.data_id_rreg, in mipid02_enable_streams()
523 cci_write(bridge->regmap, MIPID02_DATA_SELECTION_CTRL, in mipid02_enable_streams()
524 bridge->r.data_selection_ctrl, &ret); in mipid02_enable_streams()
525 cci_write(bridge->regmap, MIPID02_PIX_WIDTH_CTRL, in mipid02_enable_streams()
526 bridge->r.pix_width_ctrl, &ret); in mipid02_enable_streams()
527 cci_write(bridge->regmap, MIPID02_PIX_WIDTH_CTRL_EMB, in mipid02_enable_streams()
528 bridge->r.pix_width_ctrl_emb, &ret); in mipid02_enable_streams()
532 ret = v4l2_subdev_enable_streams(bridge->s_subdev, in mipid02_enable_streams()
533 bridge->s_subdev_pad_id, BIT(0)); in mipid02_enable_streams()
540 cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, 0, &ret); in mipid02_enable_streams()
541 cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, 0, &ret); in mipid02_enable_streams()
542 cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret); in mipid02_enable_streams()
544 pm_runtime_put_autosuspend(&client->dev); in mipid02_enable_streams()
576 switch (code->pad) { in mipid02_enum_mbus_code()
578 if (code->index >= ARRAY_SIZE(mipid02_supported_fmt_codes)) in mipid02_enum_mbus_code()
579 ret = -EINVAL; in mipid02_enum_mbus_code()
581 code->code = mipid02_supported_fmt_codes[code->index]; in mipid02_enum_mbus_code()
584 if (code->index == 0) { in mipid02_enum_mbus_code()
587 code->code = serial_to_parallel_code(sink_fmt->code); in mipid02_enum_mbus_code()
589 ret = -EINVAL; in mipid02_enum_mbus_code()
593 ret = -EINVAL; in mipid02_enum_mbus_code()
604 struct i2c_client *client = bridge->i2c_client; in mipid02_set_fmt()
607 dev_dbg(&client->dev, "%s for %d", __func__, fmt->pad); in mipid02_set_fmt()
609 /* second CSI-2 pad not yet supported */ in mipid02_set_fmt()
610 if (fmt->pad == MIPID02_SINK_1) in mipid02_set_fmt()
611 return -EINVAL; in mipid02_set_fmt()
613 pad_fmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); in mipid02_set_fmt()
614 fmt->format.code = get_fmt_code(fmt->format.code); in mipid02_set_fmt()
617 if (fmt->pad == MIPID02_SOURCE) in mipid02_set_fmt()
618 fmt->format.code = serial_to_parallel_code(fmt->format.code); in mipid02_set_fmt()
620 *pad_fmt = fmt->format; in mipid02_set_fmt()
623 if (fmt->pad == MIPID02_SINK_0) { in mipid02_set_fmt()
626 *pad_fmt = fmt->format; in mipid02_set_fmt()
627 pad_fmt->code = serial_to_parallel_code(fmt->format.code); in mipid02_set_fmt()
662 struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); in mipid02_async_bound()
663 struct i2c_client *client = bridge->i2c_client; in mipid02_async_bound()
667 dev_dbg(&client->dev, "sensor_async_bound call %p", s_subdev); in mipid02_async_bound()
669 source_pad = media_entity_get_fwnode_pad(&s_subdev->entity, in mipid02_async_bound()
670 s_subdev->fwnode, in mipid02_async_bound()
673 dev_err(&client->dev, "Couldn't find output pad for subdev %s\n", in mipid02_async_bound()
674 s_subdev->name); in mipid02_async_bound()
678 ret = media_create_pad_link(&s_subdev->entity, source_pad, in mipid02_async_bound()
679 &bridge->sd.entity, 0, in mipid02_async_bound()
683 dev_err(&client->dev, "Couldn't create media link %d", ret); in mipid02_async_bound()
687 bridge->s_subdev = s_subdev; in mipid02_async_bound()
688 bridge->s_subdev_pad_id = source_pad; in mipid02_async_bound()
697 struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); in mipid02_async_unbind()
699 bridge->s_subdev = NULL; in mipid02_async_unbind()
710 struct i2c_client *client = bridge->i2c_client; in mipid02_parse_rx_ep()
716 ep_node = of_graph_get_endpoint_by_regs(bridge->i2c_client->dev.of_node, in mipid02_parse_rx_ep()
719 dev_err(&client->dev, "unable to find port0 ep"); in mipid02_parse_rx_ep()
720 ret = -EINVAL; in mipid02_parse_rx_ep()
726 dev_err(&client->dev, "Could not parse v4l2 endpoint %d\n", in mipid02_parse_rx_ep()
733 dev_err(&client->dev, "max supported data lanes is 2 / got %d", in mipid02_parse_rx_ep()
735 ret = -EINVAL; in mipid02_parse_rx_ep()
740 bridge->rx = ep; in mipid02_parse_rx_ep()
743 v4l2_async_subdev_nf_init(&bridge->notifier, &bridge->sd); in mipid02_parse_rx_ep()
744 asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier, in mipid02_parse_rx_ep()
750 dev_err(&client->dev, "fail to register asd to notifier %ld", in mipid02_parse_rx_ep()
754 bridge->notifier.ops = &mipid02_notifier_ops; in mipid02_parse_rx_ep()
756 ret = v4l2_async_nf_register(&bridge->notifier); in mipid02_parse_rx_ep()
758 v4l2_async_nf_cleanup(&bridge->notifier); in mipid02_parse_rx_ep()
772 struct i2c_client *client = bridge->i2c_client; in mipid02_parse_tx_ep()
777 ep_node = of_graph_get_endpoint_by_regs(bridge->i2c_client->dev.of_node, in mipid02_parse_tx_ep()
780 dev_err(&client->dev, "unable to find port1 ep"); in mipid02_parse_tx_ep()
781 ret = -EINVAL; in mipid02_parse_tx_ep()
787 dev_err(&client->dev, "Could not parse v4l2 endpoint\n"); in mipid02_parse_tx_ep()
792 bridge->tx = ep; in mipid02_parse_tx_ep()
800 return -EINVAL; in mipid02_parse_tx_ep()
805 struct device *dev = &client->dev; in mipid02_probe()
812 return -ENOMEM; in mipid02_probe()
814 bridge->i2c_client = client; in mipid02_probe()
815 v4l2_i2c_subdev_init(&bridge->sd, client, &mipid02_subdev_ops); in mipid02_probe()
818 bridge->xclk = devm_clk_get(dev, "xclk"); in mipid02_probe()
819 if (IS_ERR(bridge->xclk)) { in mipid02_probe()
821 return PTR_ERR(bridge->xclk); in mipid02_probe()
824 clk_freq = clk_get_rate(bridge->xclk); in mipid02_probe()
826 dev_err(dev, "xclk freq must be in 6-27 Mhz range. got %d Hz\n", in mipid02_probe()
828 return -EINVAL; in mipid02_probe()
831 bridge->reset_gpio = devm_gpiod_get_optional(dev, "reset", in mipid02_probe()
834 if (IS_ERR(bridge->reset_gpio)) { in mipid02_probe()
836 return PTR_ERR(bridge->reset_gpio); in mipid02_probe()
846 bridge->regmap = devm_cci_regmap_init_i2c(client, 16); in mipid02_probe()
847 if (IS_ERR(bridge->regmap)) in mipid02_probe()
848 return dev_err_probe(dev, PTR_ERR(bridge->regmap), in mipid02_probe()
851 bridge->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in mipid02_probe()
852 bridge->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; in mipid02_probe()
853 bridge->sd.internal_ops = &mipid02_subdev_internal_ops; in mipid02_probe()
854 bridge->sd.entity.ops = &mipid02_subdev_entity_ops; in mipid02_probe()
855 bridge->pad[0].flags = MEDIA_PAD_FL_SINK; in mipid02_probe()
856 bridge->pad[1].flags = MEDIA_PAD_FL_SINK; in mipid02_probe()
857 bridge->pad[2].flags = MEDIA_PAD_FL_SOURCE; in mipid02_probe()
858 ret = media_entity_pads_init(&bridge->sd.entity, MIPID02_PAD_NB, in mipid02_probe()
859 bridge->pad); in mipid02_probe()
861 dev_err(&client->dev, "pads init failed %d", ret); in mipid02_probe()
865 ret = v4l2_subdev_init_finalize(&bridge->sd); in mipid02_probe()
872 ret = mipid02_set_power_on(&client->dev); in mipid02_probe()
878 dev_err(&client->dev, "failed to detect mipid02 %d", ret); in mipid02_probe()
884 dev_err(&client->dev, "failed to parse tx %d", ret); in mipid02_probe()
890 dev_err(&client->dev, "failed to parse rx %d", ret); in mipid02_probe()
896 pm_runtime_get_noresume(&client->dev); in mipid02_probe()
899 pm_runtime_set_autosuspend_delay(&client->dev, 1000); in mipid02_probe()
900 pm_runtime_use_autosuspend(&client->dev); in mipid02_probe()
901 pm_runtime_put_autosuspend(&client->dev); in mipid02_probe()
903 ret = v4l2_async_register_subdev(&bridge->sd); in mipid02_probe()
905 dev_err(&client->dev, "v4l2_async_register_subdev failed %d", in mipid02_probe()
910 dev_info(&client->dev, "mipid02 device probe successfully"); in mipid02_probe()
915 v4l2_async_nf_unregister(&bridge->notifier); in mipid02_probe()
916 v4l2_async_nf_cleanup(&bridge->notifier); in mipid02_probe()
917 pm_runtime_disable(&client->dev); in mipid02_probe()
918 pm_runtime_set_suspended(&client->dev); in mipid02_probe()
920 mipid02_set_power_off(&client->dev); in mipid02_probe()
922 media_entity_cleanup(&bridge->sd.entity); in mipid02_probe()
932 v4l2_async_nf_unregister(&bridge->notifier); in mipid02_remove()
933 v4l2_async_nf_cleanup(&bridge->notifier); in mipid02_remove()
934 v4l2_async_unregister_subdev(&bridge->sd); in mipid02_remove()
936 pm_runtime_disable(&client->dev); in mipid02_remove()
937 if (!pm_runtime_status_suspended(&client->dev)) in mipid02_remove()
938 mipid02_set_power_off(&client->dev); in mipid02_remove()
939 pm_runtime_set_suspended(&client->dev); in mipid02_remove()
940 media_entity_cleanup(&bridge->sd.entity); in mipid02_remove()
944 { .compatible = "st,st-mipid02" },
955 .name = "st-mipid02",
966 MODULE_DESCRIPTION("STMicroelectronics MIPID02 CSI-2 bridge driver");