Lines Matching +full:csi +full:- +full:bridge

1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for ST MIPID02 CSI-2 to PARALLEL bridge
19 #include <media/mipi-csi2.h>
20 #include <media/v4l2-async.h>
21 #include <media/v4l2-cci.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-device.h>
24 #include <media/v4l2-fwnode.h>
25 #include <media/v4l2-subdev.h>
229 static int mipid02_get_regulators(struct mipid02_dev *bridge) in mipid02_get_regulators() argument
234 bridge->supplies[i].supply = mipid02_supply_name[i]; in mipid02_get_regulators()
236 return devm_regulator_bulk_get(&bridge->i2c_client->dev, in mipid02_get_regulators()
238 bridge->supplies); in mipid02_get_regulators()
241 static void mipid02_apply_reset(struct mipid02_dev *bridge) in mipid02_apply_reset() argument
243 gpiod_set_value_cansleep(bridge->reset_gpio, 0); in mipid02_apply_reset()
245 gpiod_set_value_cansleep(bridge->reset_gpio, 1); in mipid02_apply_reset()
247 gpiod_set_value_cansleep(bridge->reset_gpio, 0); in mipid02_apply_reset()
251 static int mipid02_set_power_on(struct mipid02_dev *bridge) in mipid02_set_power_on() argument
253 struct i2c_client *client = bridge->i2c_client; in mipid02_set_power_on()
256 ret = clk_prepare_enable(bridge->xclk); in mipid02_set_power_on()
258 dev_err(&client->dev, "%s: failed to enable clock\n", __func__); in mipid02_set_power_on()
263 bridge->supplies); in mipid02_set_power_on()
265 dev_err(&client->dev, "%s: failed to enable regulators\n", in mipid02_set_power_on()
270 if (bridge->reset_gpio) { in mipid02_set_power_on()
271 dev_dbg(&client->dev, "apply reset"); in mipid02_set_power_on()
272 mipid02_apply_reset(bridge); in mipid02_set_power_on()
274 dev_dbg(&client->dev, "don't apply reset"); in mipid02_set_power_on()
281 clk_disable_unprepare(bridge->xclk); in mipid02_set_power_on()
285 static void mipid02_set_power_off(struct mipid02_dev *bridge) in mipid02_set_power_off() argument
287 regulator_bulk_disable(MIPID02_NUM_SUPPLIES, bridge->supplies); in mipid02_set_power_off()
288 clk_disable_unprepare(bridge->xclk); in mipid02_set_power_off()
291 static int mipid02_detect(struct mipid02_dev *bridge) in mipid02_detect() argument
299 return cci_read(bridge->regmap, MIPID02_CLK_LANE_WR_REG1, &reg, NULL); in mipid02_detect()
307 static int mipid02_configure_from_rx_speed(struct mipid02_dev *bridge, in mipid02_configure_from_rx_speed() argument
310 struct i2c_client *client = bridge->i2c_client; in mipid02_configure_from_rx_speed()
311 struct v4l2_subdev *subdev = bridge->s_subdev; in mipid02_configure_from_rx_speed()
312 struct v4l2_fwnode_endpoint *ep = &bridge->rx; in mipid02_configure_from_rx_speed()
313 u32 bpp = bpp_from_code(fmt->code); in mipid02_configure_from_rx_speed()
321 link_freq = v4l2_get_link_freq(subdev->ctrl_handler, bpp, in mipid02_configure_from_rx_speed()
322 2 * ep->bus.mipi_csi2.num_data_lanes); in mipid02_configure_from_rx_speed()
324 dev_err(&client->dev, "Failed to get link frequency"); in mipid02_configure_from_rx_speed()
325 return -EINVAL; in mipid02_configure_from_rx_speed()
328 dev_dbg(&client->dev, "detect link_freq = %lld Hz", link_freq); in mipid02_configure_from_rx_speed()
330 bridge->r.clk_lane_reg1 |= ui_4 << 2; in mipid02_configure_from_rx_speed()
335 static int mipid02_configure_clk_lane(struct mipid02_dev *bridge) in mipid02_configure_clk_lane() argument
337 struct i2c_client *client = bridge->i2c_client; in mipid02_configure_clk_lane()
338 struct v4l2_fwnode_endpoint *ep = &bridge->rx; in mipid02_configure_clk_lane()
339 bool *polarities = ep->bus.mipi_csi2.lane_polarities; in mipid02_configure_clk_lane()
342 if (ep->bus.mipi_csi2.clock_lane != 0) { in mipid02_configure_clk_lane()
343 dev_err(&client->dev, "clk lane must be map to lane 0\n"); in mipid02_configure_clk_lane()
344 return -EINVAL; in mipid02_configure_clk_lane()
346 bridge->r.clk_lane_reg1 |= (polarities[0] << 1) | CLK_ENABLE; in mipid02_configure_clk_lane()
351 static int mipid02_configure_data0_lane(struct mipid02_dev *bridge, int nb, in mipid02_configure_data0_lane() argument
364 bridge->r.data_lane0_reg1 = 1 << 1; in mipid02_configure_data0_lane()
365 bridge->r.data_lane0_reg1 |= DATA_ENABLE; in mipid02_configure_data0_lane()
370 static int mipid02_configure_data1_lane(struct mipid02_dev *bridge, int nb, in mipid02_configure_data1_lane() argument
379 bridge->r.data_lane1_reg1 = 1 << 1; in mipid02_configure_data1_lane()
380 bridge->r.data_lane1_reg1 |= DATA_ENABLE; in mipid02_configure_data1_lane()
385 static int mipid02_configure_from_rx(struct mipid02_dev *bridge, in mipid02_configure_from_rx() argument
388 struct v4l2_fwnode_endpoint *ep = &bridge->rx; in mipid02_configure_from_rx()
389 bool are_lanes_swap = ep->bus.mipi_csi2.data_lanes[0] == 2; in mipid02_configure_from_rx()
390 bool *polarities = ep->bus.mipi_csi2.lane_polarities; in mipid02_configure_from_rx()
391 int nb = ep->bus.mipi_csi2.num_data_lanes; in mipid02_configure_from_rx()
394 ret = mipid02_configure_clk_lane(bridge); in mipid02_configure_from_rx()
398 ret = mipid02_configure_data0_lane(bridge, nb, are_lanes_swap, in mipid02_configure_from_rx()
403 ret = mipid02_configure_data1_lane(bridge, nb, are_lanes_swap, in mipid02_configure_from_rx()
408 bridge->r.mode_reg1 |= are_lanes_swap ? MODE_DATA_SWAP : 0; in mipid02_configure_from_rx()
409 bridge->r.mode_reg1 |= (nb - 1) << 1; in mipid02_configure_from_rx()
411 return mipid02_configure_from_rx_speed(bridge, fmt); in mipid02_configure_from_rx()
414 static int mipid02_configure_from_tx(struct mipid02_dev *bridge) in mipid02_configure_from_tx() argument
416 struct v4l2_fwnode_endpoint *ep = &bridge->tx; in mipid02_configure_from_tx()
418 bridge->r.data_selection_ctrl = SELECTION_MANUAL_WIDTH; in mipid02_configure_from_tx()
419 bridge->r.pix_width_ctrl = ep->bus.parallel.bus_width; in mipid02_configure_from_tx()
420 bridge->r.pix_width_ctrl_emb = ep->bus.parallel.bus_width; in mipid02_configure_from_tx()
421 if (ep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) in mipid02_configure_from_tx()
422 bridge->r.mode_reg2 |= MODE_HSYNC_ACTIVE_HIGH; in mipid02_configure_from_tx()
423 if (ep->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) in mipid02_configure_from_tx()
424 bridge->r.mode_reg2 |= MODE_VSYNC_ACTIVE_HIGH; in mipid02_configure_from_tx()
425 if (ep->bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_RISING) in mipid02_configure_from_tx()
426 bridge->r.mode_reg2 |= MODE_PCLK_SAMPLE_RISING; in mipid02_configure_from_tx()
431 static int mipid02_configure_from_code(struct mipid02_dev *bridge, in mipid02_configure_from_code() argument
436 bridge->r.data_id_rreg = 0; in mipid02_configure_from_code()
438 if (fmt->code != MEDIA_BUS_FMT_JPEG_1X8) { in mipid02_configure_from_code()
439 bridge->r.data_selection_ctrl |= SELECTION_MANUAL_DATA; in mipid02_configure_from_code()
441 data_type = data_type_from_code(fmt->code); in mipid02_configure_from_code()
443 return -EINVAL; in mipid02_configure_from_code()
444 bridge->r.data_id_rreg = data_type; in mipid02_configure_from_code()
450 static int mipid02_stream_disable(struct mipid02_dev *bridge) in mipid02_stream_disable() argument
452 struct i2c_client *client = bridge->i2c_client; in mipid02_stream_disable()
453 int ret = -EINVAL; in mipid02_stream_disable()
455 if (!bridge->s_subdev) in mipid02_stream_disable()
458 ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 0); in mipid02_stream_disable()
463 cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, 0, &ret); in mipid02_stream_disable()
464 cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, 0, &ret); in mipid02_stream_disable()
465 cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret); in mipid02_stream_disable()
470 dev_err(&client->dev, "failed to stream off %d", ret); in mipid02_stream_disable()
475 static int mipid02_stream_enable(struct mipid02_dev *bridge) in mipid02_stream_enable() argument
477 struct i2c_client *client = bridge->i2c_client; in mipid02_stream_enable()
480 int ret = -EINVAL; in mipid02_stream_enable()
482 if (!bridge->s_subdev) in mipid02_stream_enable()
485 memset(&bridge->r, 0, sizeof(bridge->r)); in mipid02_stream_enable()
487 state = v4l2_subdev_lock_and_get_active_state(&bridge->sd); in mipid02_stream_enable()
491 ret = mipid02_configure_from_rx(bridge, fmt); in mipid02_stream_enable()
494 ret = mipid02_configure_from_tx(bridge); in mipid02_stream_enable()
497 ret = mipid02_configure_from_code(bridge, fmt); in mipid02_stream_enable()
504 cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, in mipid02_stream_enable()
505 bridge->r.clk_lane_reg1, &ret); in mipid02_stream_enable()
506 cci_write(bridge->regmap, MIPID02_CLK_LANE_REG3, CLK_MIPI_CSI, &ret); in mipid02_stream_enable()
507 cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, in mipid02_stream_enable()
508 bridge->r.data_lane0_reg1, &ret); in mipid02_stream_enable()
509 cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG2, DATA_MIPI_CSI, &ret); in mipid02_stream_enable()
510 cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, in mipid02_stream_enable()
511 bridge->r.data_lane1_reg1, &ret); in mipid02_stream_enable()
512 cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG2, DATA_MIPI_CSI, &ret); in mipid02_stream_enable()
513 cci_write(bridge->regmap, MIPID02_MODE_REG1, in mipid02_stream_enable()
514 MODE_NO_BYPASS | bridge->r.mode_reg1, &ret); in mipid02_stream_enable()
515 cci_write(bridge->regmap, MIPID02_MODE_REG2, bridge->r.mode_reg2, &ret); in mipid02_stream_enable()
516 cci_write(bridge->regmap, MIPID02_DATA_ID_RREG, bridge->r.data_id_rreg, in mipid02_stream_enable()
518 cci_write(bridge->regmap, MIPID02_DATA_SELECTION_CTRL, in mipid02_stream_enable()
519 bridge->r.data_selection_ctrl, &ret); in mipid02_stream_enable()
520 cci_write(bridge->regmap, MIPID02_PIX_WIDTH_CTRL, in mipid02_stream_enable()
521 bridge->r.pix_width_ctrl, &ret); in mipid02_stream_enable()
522 cci_write(bridge->regmap, MIPID02_PIX_WIDTH_CTRL_EMB, in mipid02_stream_enable()
523 bridge->r.pix_width_ctrl_emb, &ret); in mipid02_stream_enable()
527 ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 1); in mipid02_stream_enable()
534 dev_err(&client->dev, "failed to stream on %d", ret); in mipid02_stream_enable()
535 mipid02_stream_disable(bridge); in mipid02_stream_enable()
542 struct mipid02_dev *bridge = to_mipid02_dev(sd); in mipid02_s_stream() local
543 struct i2c_client *client = bridge->i2c_client; in mipid02_s_stream()
546 dev_dbg(&client->dev, "%s : requested %d\n", __func__, enable); in mipid02_s_stream()
548 ret = enable ? mipid02_stream_enable(bridge) : in mipid02_s_stream()
549 mipid02_stream_disable(bridge); in mipid02_s_stream()
551 dev_err(&client->dev, "failed to stream %s (%d)\n", in mipid02_s_stream()
585 switch (code->pad) { in mipid02_enum_mbus_code()
587 if (code->index >= ARRAY_SIZE(mipid02_supported_fmt_codes)) in mipid02_enum_mbus_code()
588 ret = -EINVAL; in mipid02_enum_mbus_code()
590 code->code = mipid02_supported_fmt_codes[code->index]; in mipid02_enum_mbus_code()
593 if (code->index == 0) { in mipid02_enum_mbus_code()
596 code->code = serial_to_parallel_code(sink_fmt->code); in mipid02_enum_mbus_code()
598 ret = -EINVAL; in mipid02_enum_mbus_code()
602 ret = -EINVAL; in mipid02_enum_mbus_code()
612 struct mipid02_dev *bridge = to_mipid02_dev(sd); in mipid02_set_fmt() local
613 struct i2c_client *client = bridge->i2c_client; in mipid02_set_fmt()
616 dev_dbg(&client->dev, "%s for %d", __func__, fmt->pad); in mipid02_set_fmt()
618 /* second CSI-2 pad not yet supported */ in mipid02_set_fmt()
619 if (fmt->pad == MIPID02_SINK_1) in mipid02_set_fmt()
620 return -EINVAL; in mipid02_set_fmt()
622 pad_fmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); in mipid02_set_fmt()
623 fmt->format.code = get_fmt_code(fmt->format.code); in mipid02_set_fmt()
626 if (fmt->pad == MIPID02_SOURCE) in mipid02_set_fmt()
627 fmt->format.code = serial_to_parallel_code(fmt->format.code); in mipid02_set_fmt()
629 *pad_fmt = fmt->format; in mipid02_set_fmt()
632 if (fmt->pad == MIPID02_SINK_0) { in mipid02_set_fmt()
635 *pad_fmt = fmt->format; in mipid02_set_fmt()
636 pad_fmt->code = serial_to_parallel_code(fmt->format.code); in mipid02_set_fmt()
669 struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); in mipid02_async_bound() local
670 struct i2c_client *client = bridge->i2c_client; in mipid02_async_bound()
674 dev_dbg(&client->dev, "sensor_async_bound call %p", s_subdev); in mipid02_async_bound()
676 source_pad = media_entity_get_fwnode_pad(&s_subdev->entity, in mipid02_async_bound()
677 s_subdev->fwnode, in mipid02_async_bound()
680 dev_err(&client->dev, "Couldn't find output pad for subdev %s\n", in mipid02_async_bound()
681 s_subdev->name); in mipid02_async_bound()
685 ret = media_create_pad_link(&s_subdev->entity, source_pad, in mipid02_async_bound()
686 &bridge->sd.entity, 0, in mipid02_async_bound()
690 dev_err(&client->dev, "Couldn't create media link %d", ret); in mipid02_async_bound()
694 bridge->s_subdev = s_subdev; in mipid02_async_bound()
703 struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); in mipid02_async_unbind() local
705 bridge->s_subdev = NULL; in mipid02_async_unbind()
713 static int mipid02_parse_rx_ep(struct mipid02_dev *bridge) in mipid02_parse_rx_ep() argument
716 struct i2c_client *client = bridge->i2c_client; in mipid02_parse_rx_ep()
722 ep_node = of_graph_get_endpoint_by_regs(bridge->i2c_client->dev.of_node, in mipid02_parse_rx_ep()
725 dev_err(&client->dev, "unable to find port0 ep"); in mipid02_parse_rx_ep()
726 ret = -EINVAL; in mipid02_parse_rx_ep()
732 dev_err(&client->dev, "Could not parse v4l2 endpoint %d\n", in mipid02_parse_rx_ep()
739 dev_err(&client->dev, "max supported data lanes is 2 / got %d", in mipid02_parse_rx_ep()
741 ret = -EINVAL; in mipid02_parse_rx_ep()
746 bridge->rx = ep; in mipid02_parse_rx_ep()
749 v4l2_async_subdev_nf_init(&bridge->notifier, &bridge->sd); in mipid02_parse_rx_ep()
750 asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier, in mipid02_parse_rx_ep()
756 dev_err(&client->dev, "fail to register asd to notifier %ld", in mipid02_parse_rx_ep()
760 bridge->notifier.ops = &mipid02_notifier_ops; in mipid02_parse_rx_ep()
762 ret = v4l2_async_nf_register(&bridge->notifier); in mipid02_parse_rx_ep()
764 v4l2_async_nf_cleanup(&bridge->notifier); in mipid02_parse_rx_ep()
775 static int mipid02_parse_tx_ep(struct mipid02_dev *bridge) in mipid02_parse_tx_ep() argument
778 struct i2c_client *client = bridge->i2c_client; in mipid02_parse_tx_ep()
783 ep_node = of_graph_get_endpoint_by_regs(bridge->i2c_client->dev.of_node, in mipid02_parse_tx_ep()
786 dev_err(&client->dev, "unable to find port1 ep"); in mipid02_parse_tx_ep()
787 ret = -EINVAL; in mipid02_parse_tx_ep()
793 dev_err(&client->dev, "Could not parse v4l2 endpoint\n"); in mipid02_parse_tx_ep()
798 bridge->tx = ep; in mipid02_parse_tx_ep()
806 return -EINVAL; in mipid02_parse_tx_ep()
811 struct device *dev = &client->dev; in mipid02_probe()
812 struct mipid02_dev *bridge; in mipid02_probe() local
816 bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); in mipid02_probe()
817 if (!bridge) in mipid02_probe()
818 return -ENOMEM; in mipid02_probe()
820 bridge->i2c_client = client; in mipid02_probe()
821 v4l2_i2c_subdev_init(&bridge->sd, client, &mipid02_subdev_ops); in mipid02_probe()
824 bridge->xclk = devm_clk_get(dev, "xclk"); in mipid02_probe()
825 if (IS_ERR(bridge->xclk)) { in mipid02_probe()
827 return PTR_ERR(bridge->xclk); in mipid02_probe()
830 clk_freq = clk_get_rate(bridge->xclk); in mipid02_probe()
832 dev_err(dev, "xclk freq must be in 6-27 Mhz range. got %d Hz\n", in mipid02_probe()
834 return -EINVAL; in mipid02_probe()
837 bridge->reset_gpio = devm_gpiod_get_optional(dev, "reset", in mipid02_probe()
840 if (IS_ERR(bridge->reset_gpio)) { in mipid02_probe()
842 return PTR_ERR(bridge->reset_gpio); in mipid02_probe()
845 ret = mipid02_get_regulators(bridge); in mipid02_probe()
852 bridge->regmap = devm_cci_regmap_init_i2c(client, 16); in mipid02_probe()
853 if (IS_ERR(bridge->regmap)) in mipid02_probe()
854 return dev_err_probe(dev, PTR_ERR(bridge->regmap), in mipid02_probe()
857 bridge->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in mipid02_probe()
858 bridge->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; in mipid02_probe()
859 bridge->sd.internal_ops = &mipid02_subdev_internal_ops; in mipid02_probe()
860 bridge->sd.entity.ops = &mipid02_subdev_entity_ops; in mipid02_probe()
861 bridge->pad[0].flags = MEDIA_PAD_FL_SINK; in mipid02_probe()
862 bridge->pad[1].flags = MEDIA_PAD_FL_SINK; in mipid02_probe()
863 bridge->pad[2].flags = MEDIA_PAD_FL_SOURCE; in mipid02_probe()
864 ret = media_entity_pads_init(&bridge->sd.entity, MIPID02_PAD_NB, in mipid02_probe()
865 bridge->pad); in mipid02_probe()
867 dev_err(&client->dev, "pads init failed %d", ret); in mipid02_probe()
871 ret = v4l2_subdev_init_finalize(&bridge->sd); in mipid02_probe()
878 ret = mipid02_set_power_on(bridge); in mipid02_probe()
882 ret = mipid02_detect(bridge); in mipid02_probe()
884 dev_err(&client->dev, "failed to detect mipid02 %d", ret); in mipid02_probe()
888 ret = mipid02_parse_tx_ep(bridge); in mipid02_probe()
890 dev_err(&client->dev, "failed to parse tx %d", ret); in mipid02_probe()
894 ret = mipid02_parse_rx_ep(bridge); in mipid02_probe()
896 dev_err(&client->dev, "failed to parse rx %d", ret); in mipid02_probe()
900 ret = v4l2_async_register_subdev(&bridge->sd); in mipid02_probe()
902 dev_err(&client->dev, "v4l2_async_register_subdev failed %d", in mipid02_probe()
907 dev_info(&client->dev, "mipid02 device probe successfully"); in mipid02_probe()
912 v4l2_async_nf_unregister(&bridge->notifier); in mipid02_probe()
913 v4l2_async_nf_cleanup(&bridge->notifier); in mipid02_probe()
915 mipid02_set_power_off(bridge); in mipid02_probe()
917 media_entity_cleanup(&bridge->sd.entity); in mipid02_probe()
925 struct mipid02_dev *bridge = to_mipid02_dev(sd); in mipid02_remove() local
927 v4l2_async_nf_unregister(&bridge->notifier); in mipid02_remove()
928 v4l2_async_nf_cleanup(&bridge->notifier); in mipid02_remove()
929 v4l2_async_unregister_subdev(&bridge->sd); in mipid02_remove()
930 mipid02_set_power_off(bridge); in mipid02_remove()
931 media_entity_cleanup(&bridge->sd.entity); in mipid02_remove()
935 { .compatible = "st,st-mipid02" },
942 .name = "st-mipid02",
952 MODULE_DESCRIPTION("STMicroelectronics MIPID02 CSI-2 bridge driver");