Lines Matching +full:lane +full:- +full:polarities
1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for ST MIPID02 CSI-2 to PARALLEL bridge
19 #include <media/v4l2-async.h>
20 #include <media/v4l2-ctrls.h>
21 #include <media/v4l2-device.h>
22 #include <media/v4l2-fwnode.h>
23 #include <media/v4l2-subdev.h>
196 fmt->code = MEDIA_BUS_FMT_SBGGR8_1X8; in init_format()
197 fmt->field = V4L2_FIELD_NONE; in init_format()
198 fmt->colorspace = V4L2_COLORSPACE_SRGB; in init_format()
199 fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB); in init_format()
200 fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; in init_format()
201 fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB); in init_format()
202 fmt->width = 640; in init_format()
203 fmt->height = 480; in init_format()
243 struct i2c_client *client = bridge->i2c_client; in mipid02_read_reg()
251 msg[0].addr = client->addr; in mipid02_read_reg()
252 msg[0].flags = client->flags; in mipid02_read_reg()
256 msg[1].addr = client->addr; in mipid02_read_reg()
257 msg[1].flags = client->flags | I2C_M_RD; in mipid02_read_reg()
261 ret = i2c_transfer(client->adapter, msg, 2); in mipid02_read_reg()
263 dev_dbg(&client->dev, "%s: %x i2c_transfer, reg: %x => %d\n", in mipid02_read_reg()
264 __func__, client->addr, reg, ret); in mipid02_read_reg()
273 struct i2c_client *client = bridge->i2c_client; in mipid02_write_reg()
282 msg.addr = client->addr; in mipid02_write_reg()
283 msg.flags = client->flags; in mipid02_write_reg()
287 ret = i2c_transfer(client->adapter, &msg, 1); in mipid02_write_reg()
289 dev_dbg(&client->dev, "%s: i2c_transfer, reg: %x => %d\n", in mipid02_write_reg()
302 bridge->supplies[i].supply = mipid02_supply_name[i]; in mipid02_get_regulators()
304 return devm_regulator_bulk_get(&bridge->i2c_client->dev, in mipid02_get_regulators()
306 bridge->supplies); in mipid02_get_regulators()
311 gpiod_set_value_cansleep(bridge->reset_gpio, 0); in mipid02_apply_reset()
313 gpiod_set_value_cansleep(bridge->reset_gpio, 1); in mipid02_apply_reset()
315 gpiod_set_value_cansleep(bridge->reset_gpio, 0); in mipid02_apply_reset()
321 struct i2c_client *client = bridge->i2c_client; in mipid02_set_power_on()
324 ret = clk_prepare_enable(bridge->xclk); in mipid02_set_power_on()
326 dev_err(&client->dev, "%s: failed to enable clock\n", __func__); in mipid02_set_power_on()
331 bridge->supplies); in mipid02_set_power_on()
333 dev_err(&client->dev, "%s: failed to enable regulators\n", in mipid02_set_power_on()
338 if (bridge->reset_gpio) { in mipid02_set_power_on()
339 dev_dbg(&client->dev, "apply reset"); in mipid02_set_power_on()
342 dev_dbg(&client->dev, "don't apply reset"); in mipid02_set_power_on()
349 clk_disable_unprepare(bridge->xclk); in mipid02_set_power_on()
355 regulator_bulk_disable(MIPID02_NUM_SUPPLIES, bridge->supplies); in mipid02_set_power_off()
356 clk_disable_unprepare(bridge->xclk); in mipid02_set_power_off()
377 ctrl = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_LINK_FREQ); in mipid02_get_link_freq_from_cid_link_freq()
382 ret = v4l2_querymenu(subdev->ctrl_handler, &qm); in mipid02_get_link_freq_from_cid_link_freq()
392 struct v4l2_fwnode_endpoint *ep = &bridge->rx; in mipid02_get_link_freq_from_cid_pixel_rate()
395 u32 bpp = bpp_from_code(bridge->fmt.code); in mipid02_get_link_freq_from_cid_pixel_rate()
397 ctrl = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_PIXEL_RATE); in mipid02_get_link_freq_from_cid_pixel_rate()
402 return pixel_clock * bpp / (2 * ep->bus.mipi_csi2.num_data_lanes); in mipid02_get_link_freq_from_cid_pixel_rate()
412 struct i2c_client *client = bridge->i2c_client; in mipid02_configure_from_rx_speed()
413 struct v4l2_subdev *subdev = bridge->s_subdev; in mipid02_configure_from_rx_speed()
421 dev_err(&client->dev, "Failed to get link frequency"); in mipid02_configure_from_rx_speed()
422 return -EINVAL; in mipid02_configure_from_rx_speed()
426 dev_dbg(&client->dev, "detect link_freq = %d Hz", link_freq); in mipid02_configure_from_rx_speed()
427 bridge->r.clk_lane_reg1 |= (2000000000 / link_freq) << 2; in mipid02_configure_from_rx_speed()
434 struct i2c_client *client = bridge->i2c_client; in mipid02_configure_clk_lane()
435 struct v4l2_fwnode_endpoint *ep = &bridge->rx; in mipid02_configure_clk_lane()
436 bool *polarities = ep->bus.mipi_csi2.lane_polarities; in mipid02_configure_clk_lane() local
438 /* midid02 doesn't support clock lane remapping */ in mipid02_configure_clk_lane()
439 if (ep->bus.mipi_csi2.clock_lane != 0) { in mipid02_configure_clk_lane()
440 dev_err(&client->dev, "clk lane must be map to lane 0\n"); in mipid02_configure_clk_lane()
441 return -EINVAL; in mipid02_configure_clk_lane()
443 bridge->r.clk_lane_reg1 |= (polarities[0] << 1) | CLK_ENABLE; in mipid02_configure_clk_lane()
449 bool are_lanes_swap, bool *polarities) in mipid02_configure_data0_lane() argument
451 bool are_pin_swap = are_lanes_swap ? polarities[2] : polarities[1]; in mipid02_configure_data0_lane()
457 * data lane 0 as pin swap polarity reversed compared to clock and in mipid02_configure_data0_lane()
458 * data lane 1 in mipid02_configure_data0_lane()
461 bridge->r.data_lane0_reg1 = 1 << 1; in mipid02_configure_data0_lane()
462 bridge->r.data_lane0_reg1 |= DATA_ENABLE; in mipid02_configure_data0_lane()
468 bool are_lanes_swap, bool *polarities) in mipid02_configure_data1_lane() argument
470 bool are_pin_swap = are_lanes_swap ? polarities[1] : polarities[2]; in mipid02_configure_data1_lane()
476 bridge->r.data_lane1_reg1 = 1 << 1; in mipid02_configure_data1_lane()
477 bridge->r.data_lane1_reg1 |= DATA_ENABLE; in mipid02_configure_data1_lane()
484 struct v4l2_fwnode_endpoint *ep = &bridge->rx; in mipid02_configure_from_rx()
485 bool are_lanes_swap = ep->bus.mipi_csi2.data_lanes[0] == 2; in mipid02_configure_from_rx()
486 bool *polarities = ep->bus.mipi_csi2.lane_polarities; in mipid02_configure_from_rx() local
487 int nb = ep->bus.mipi_csi2.num_data_lanes; in mipid02_configure_from_rx()
495 polarities); in mipid02_configure_from_rx()
500 polarities); in mipid02_configure_from_rx()
504 bridge->r.mode_reg1 |= are_lanes_swap ? MODE_DATA_SWAP : 0; in mipid02_configure_from_rx()
505 bridge->r.mode_reg1 |= (nb - 1) << 1; in mipid02_configure_from_rx()
512 struct v4l2_fwnode_endpoint *ep = &bridge->tx; in mipid02_configure_from_tx()
514 bridge->r.data_selection_ctrl = SELECTION_MANUAL_WIDTH; in mipid02_configure_from_tx()
515 bridge->r.pix_width_ctrl = ep->bus.parallel.bus_width; in mipid02_configure_from_tx()
516 bridge->r.pix_width_ctrl_emb = ep->bus.parallel.bus_width; in mipid02_configure_from_tx()
517 if (ep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) in mipid02_configure_from_tx()
518 bridge->r.mode_reg2 |= MODE_HSYNC_ACTIVE_HIGH; in mipid02_configure_from_tx()
519 if (ep->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) in mipid02_configure_from_tx()
520 bridge->r.mode_reg2 |= MODE_VSYNC_ACTIVE_HIGH; in mipid02_configure_from_tx()
521 if (ep->bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_RISING) in mipid02_configure_from_tx()
522 bridge->r.mode_reg2 |= MODE_PCLK_SAMPLE_RISING; in mipid02_configure_from_tx()
531 bridge->r.data_id_rreg = 0; in mipid02_configure_from_code()
533 if (bridge->fmt.code != MEDIA_BUS_FMT_JPEG_1X8) { in mipid02_configure_from_code()
534 bridge->r.data_selection_ctrl |= SELECTION_MANUAL_DATA; in mipid02_configure_from_code()
536 data_type = data_type_from_code(bridge->fmt.code); in mipid02_configure_from_code()
538 return -EINVAL; in mipid02_configure_from_code()
539 bridge->r.data_id_rreg = data_type; in mipid02_configure_from_code()
547 struct i2c_client *client = bridge->i2c_client; in mipid02_stream_disable()
548 int ret = -EINVAL; in mipid02_stream_disable()
550 if (!bridge->s_subdev) in mipid02_stream_disable()
553 ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 0); in mipid02_stream_disable()
569 dev_err(&client->dev, "failed to stream off %d", ret); in mipid02_stream_disable()
576 struct i2c_client *client = bridge->i2c_client; in mipid02_stream_enable()
577 int ret = -EINVAL; in mipid02_stream_enable()
579 if (!bridge->s_subdev) in mipid02_stream_enable()
582 memset(&bridge->r, 0, sizeof(bridge->r)); in mipid02_stream_enable()
596 bridge->r.clk_lane_reg1); in mipid02_stream_enable()
603 bridge->r.data_lane0_reg1); in mipid02_stream_enable()
611 bridge->r.data_lane1_reg1); in mipid02_stream_enable()
619 MODE_NO_BYPASS | bridge->r.mode_reg1); in mipid02_stream_enable()
623 bridge->r.mode_reg2); in mipid02_stream_enable()
627 bridge->r.data_id_rreg); in mipid02_stream_enable()
631 bridge->r.data_selection_ctrl); in mipid02_stream_enable()
635 bridge->r.pix_width_ctrl); in mipid02_stream_enable()
639 bridge->r.pix_width_ctrl_emb); in mipid02_stream_enable()
643 ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 1); in mipid02_stream_enable()
650 dev_err(&client->dev, "failed to stream on %d", ret); in mipid02_stream_enable()
659 struct i2c_client *client = bridge->i2c_client; in mipid02_s_stream()
662 dev_dbg(&client->dev, "%s : requested %d / current = %d", __func__, in mipid02_s_stream()
663 enable, bridge->streaming); in mipid02_s_stream()
664 mutex_lock(&bridge->lock); in mipid02_s_stream()
666 if (bridge->streaming == enable) in mipid02_s_stream()
672 bridge->streaming = enable; in mipid02_s_stream()
675 dev_dbg(&client->dev, "%s current now = %d / %d", __func__, in mipid02_s_stream()
676 bridge->streaming, ret); in mipid02_s_stream()
677 mutex_unlock(&bridge->lock); in mipid02_s_stream()
689 switch (code->pad) { in mipid02_enum_mbus_code()
691 if (code->index >= ARRAY_SIZE(mipid02_supported_fmt_codes)) in mipid02_enum_mbus_code()
692 ret = -EINVAL; in mipid02_enum_mbus_code()
694 code->code = mipid02_supported_fmt_codes[code->index]; in mipid02_enum_mbus_code()
697 if (code->index == 0) in mipid02_enum_mbus_code()
698 code->code = serial_to_parallel_code(bridge->fmt.code); in mipid02_enum_mbus_code()
700 ret = -EINVAL; in mipid02_enum_mbus_code()
703 ret = -EINVAL; in mipid02_enum_mbus_code()
713 struct v4l2_mbus_framefmt *mbus_fmt = &format->format; in mipid02_get_fmt()
715 struct i2c_client *client = bridge->i2c_client; in mipid02_get_fmt()
718 dev_dbg(&client->dev, "%s probe %d", __func__, format->pad); in mipid02_get_fmt()
720 if (format->pad >= MIPID02_PAD_NB) in mipid02_get_fmt()
721 return -EINVAL; in mipid02_get_fmt()
722 /* second CSI-2 pad not yet supported */ in mipid02_get_fmt()
723 if (format->pad == MIPID02_SINK_1) in mipid02_get_fmt()
724 return -EINVAL; in mipid02_get_fmt()
726 if (format->which == V4L2_SUBDEV_FORMAT_TRY) in mipid02_get_fmt()
727 fmt = v4l2_subdev_get_try_format(&bridge->sd, sd_state, in mipid02_get_fmt()
728 format->pad); in mipid02_get_fmt()
730 fmt = &bridge->fmt; in mipid02_get_fmt()
732 mutex_lock(&bridge->lock); in mipid02_get_fmt()
736 if (format->pad == MIPID02_SOURCE) in mipid02_get_fmt()
737 mbus_fmt->code = serial_to_parallel_code(mbus_fmt->code); in mipid02_get_fmt()
739 mutex_unlock(&bridge->lock); in mipid02_get_fmt()
751 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) in mipid02_set_fmt_source()
752 format->format = bridge->fmt; in mipid02_set_fmt_source()
754 format->format = *v4l2_subdev_get_try_format(sd, sd_state, in mipid02_set_fmt_source()
758 format->format.code = serial_to_parallel_code(format->format.code); in mipid02_set_fmt_source()
761 if (format->which != V4L2_SUBDEV_FORMAT_TRY) in mipid02_set_fmt_source()
765 format->format; in mipid02_set_fmt_source()
776 format->format.code = get_fmt_code(format->format.code); in mipid02_set_fmt_sink()
778 if (format->which == V4L2_SUBDEV_FORMAT_TRY) in mipid02_set_fmt_sink()
779 fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad); in mipid02_set_fmt_sink()
781 fmt = &bridge->fmt; in mipid02_set_fmt_sink()
783 *fmt = format->format; in mipid02_set_fmt_sink()
798 struct i2c_client *client = bridge->i2c_client; in mipid02_set_fmt()
801 dev_dbg(&client->dev, "%s for %d", __func__, format->pad); in mipid02_set_fmt()
803 if (format->pad >= MIPID02_PAD_NB) in mipid02_set_fmt()
804 return -EINVAL; in mipid02_set_fmt()
805 /* second CSI-2 pad not yet supported */ in mipid02_set_fmt()
806 if (format->pad == MIPID02_SINK_1) in mipid02_set_fmt()
807 return -EINVAL; in mipid02_set_fmt()
809 mutex_lock(&bridge->lock); in mipid02_set_fmt()
811 if (bridge->streaming) { in mipid02_set_fmt()
812 ret = -EBUSY; in mipid02_set_fmt()
816 if (format->pad == MIPID02_SOURCE) in mipid02_set_fmt()
822 mutex_unlock(&bridge->lock); in mipid02_set_fmt()
850 struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); in mipid02_async_bound()
851 struct i2c_client *client = bridge->i2c_client; in mipid02_async_bound()
855 dev_dbg(&client->dev, "sensor_async_bound call %p", s_subdev); in mipid02_async_bound()
857 source_pad = media_entity_get_fwnode_pad(&s_subdev->entity, in mipid02_async_bound()
858 s_subdev->fwnode, in mipid02_async_bound()
861 dev_err(&client->dev, "Couldn't find output pad for subdev %s\n", in mipid02_async_bound()
862 s_subdev->name); in mipid02_async_bound()
866 ret = media_create_pad_link(&s_subdev->entity, source_pad, in mipid02_async_bound()
867 &bridge->sd.entity, 0, in mipid02_async_bound()
871 dev_err(&client->dev, "Couldn't create media link %d", ret); in mipid02_async_bound()
875 bridge->s_subdev = s_subdev; in mipid02_async_bound()
884 struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); in mipid02_async_unbind()
886 bridge->s_subdev = NULL; in mipid02_async_unbind()
897 struct i2c_client *client = bridge->i2c_client; in mipid02_parse_rx_ep()
903 ep_node = of_graph_get_endpoint_by_regs(bridge->i2c_client->dev.of_node, in mipid02_parse_rx_ep()
906 dev_err(&client->dev, "unable to find port0 ep"); in mipid02_parse_rx_ep()
907 ret = -EINVAL; in mipid02_parse_rx_ep()
913 dev_err(&client->dev, "Could not parse v4l2 endpoint %d\n", in mipid02_parse_rx_ep()
920 dev_err(&client->dev, "max supported data lanes is 2 / got %d", in mipid02_parse_rx_ep()
922 ret = -EINVAL; in mipid02_parse_rx_ep()
927 bridge->rx = ep; in mipid02_parse_rx_ep()
930 v4l2_async_subdev_nf_init(&bridge->notifier, &bridge->sd); in mipid02_parse_rx_ep()
931 asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier, in mipid02_parse_rx_ep()
937 dev_err(&client->dev, "fail to register asd to notifier %ld", in mipid02_parse_rx_ep()
941 bridge->notifier.ops = &mipid02_notifier_ops; in mipid02_parse_rx_ep()
943 ret = v4l2_async_nf_register(&bridge->notifier); in mipid02_parse_rx_ep()
945 v4l2_async_nf_cleanup(&bridge->notifier); in mipid02_parse_rx_ep()
959 struct i2c_client *client = bridge->i2c_client; in mipid02_parse_tx_ep()
964 ep_node = of_graph_get_endpoint_by_regs(bridge->i2c_client->dev.of_node, in mipid02_parse_tx_ep()
967 dev_err(&client->dev, "unable to find port1 ep"); in mipid02_parse_tx_ep()
968 ret = -EINVAL; in mipid02_parse_tx_ep()
974 dev_err(&client->dev, "Could not parse v4l2 endpoint\n"); in mipid02_parse_tx_ep()
979 bridge->tx = ep; in mipid02_parse_tx_ep()
987 return -EINVAL; in mipid02_parse_tx_ep()
992 struct device *dev = &client->dev; in mipid02_probe()
999 return -ENOMEM; in mipid02_probe()
1001 init_format(&bridge->fmt); in mipid02_probe()
1003 bridge->i2c_client = client; in mipid02_probe()
1004 v4l2_i2c_subdev_init(&bridge->sd, client, &mipid02_subdev_ops); in mipid02_probe()
1007 bridge->xclk = devm_clk_get(dev, "xclk"); in mipid02_probe()
1008 if (IS_ERR(bridge->xclk)) { in mipid02_probe()
1010 return PTR_ERR(bridge->xclk); in mipid02_probe()
1013 clk_freq = clk_get_rate(bridge->xclk); in mipid02_probe()
1015 dev_err(dev, "xclk freq must be in 6-27 Mhz range. got %d Hz\n", in mipid02_probe()
1017 return -EINVAL; in mipid02_probe()
1020 bridge->reset_gpio = devm_gpiod_get_optional(dev, "reset", in mipid02_probe()
1023 if (IS_ERR(bridge->reset_gpio)) { in mipid02_probe()
1025 return PTR_ERR(bridge->reset_gpio); in mipid02_probe()
1034 mutex_init(&bridge->lock); in mipid02_probe()
1035 bridge->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in mipid02_probe()
1036 bridge->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; in mipid02_probe()
1037 bridge->sd.entity.ops = &mipid02_subdev_entity_ops; in mipid02_probe()
1038 bridge->pad[0].flags = MEDIA_PAD_FL_SINK; in mipid02_probe()
1039 bridge->pad[1].flags = MEDIA_PAD_FL_SINK; in mipid02_probe()
1040 bridge->pad[2].flags = MEDIA_PAD_FL_SOURCE; in mipid02_probe()
1041 ret = media_entity_pads_init(&bridge->sd.entity, MIPID02_PAD_NB, in mipid02_probe()
1042 bridge->pad); in mipid02_probe()
1044 dev_err(&client->dev, "pads init failed %d", ret); in mipid02_probe()
1055 dev_err(&client->dev, "failed to detect mipid02 %d", ret); in mipid02_probe()
1061 dev_err(&client->dev, "failed to parse tx %d", ret); in mipid02_probe()
1067 dev_err(&client->dev, "failed to parse rx %d", ret); in mipid02_probe()
1071 ret = v4l2_async_register_subdev(&bridge->sd); in mipid02_probe()
1073 dev_err(&client->dev, "v4l2_async_register_subdev failed %d", in mipid02_probe()
1078 dev_info(&client->dev, "mipid02 device probe successfully"); in mipid02_probe()
1083 v4l2_async_nf_unregister(&bridge->notifier); in mipid02_probe()
1084 v4l2_async_nf_cleanup(&bridge->notifier); in mipid02_probe()
1088 media_entity_cleanup(&bridge->sd.entity); in mipid02_probe()
1090 mutex_destroy(&bridge->lock); in mipid02_probe()
1100 v4l2_async_nf_unregister(&bridge->notifier); in mipid02_remove()
1101 v4l2_async_nf_cleanup(&bridge->notifier); in mipid02_remove()
1102 v4l2_async_unregister_subdev(&bridge->sd); in mipid02_remove()
1104 media_entity_cleanup(&bridge->sd.entity); in mipid02_remove()
1105 mutex_destroy(&bridge->lock); in mipid02_remove()
1109 { .compatible = "st,st-mipid02" },
1116 .name = "st-mipid02",
1126 MODULE_DESCRIPTION("STMicroelectronics MIPID02 CSI-2 bridge driver");