Lines Matching +full:csi +full:- +full:pxl +full:- +full:format
1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for Xilinx MIPI CSI-2 Rx Subsystem
5 * Copyright (C) 2016 - 2020 Xilinx, Inc.
19 #include <linux/v4l2-subdev.h>
20 #include <media/media-entity.h>
21 #include <media/mipi-csi2.h>
22 #include <media/v4l2-common.h>
23 #include <media/v4l2-ctrls.h>
24 #include <media/v4l2-fwnode.h>
25 #include <media/v4l2-subdev.h>
26 #include "xilinx-vip.h"
126 #define XCSI_VCX_NUM_EVENTS ((XCSI_MAX_VCX - XCSI_MAX_VC) * 2)
129 * struct xcsi2rxss_event - Event log structure
166 * This table provides a mapping between CSI-2 Data type
200 * struct xcsi2rxss_state - CSI-2 Rx Subsystem device structure
202 * @format: Active V4L2 formats on each pad
203 * @default_format: Default V4L2 format
223 struct v4l2_mbus_framefmt format; member
258 return ioread32(xcsi2rxss->iomem + addr); in xcsi2rxss_read()
264 iowrite32(value, xcsi2rxss->iomem + addr); in xcsi2rxss_write()
290 if (n-- == 0) in xcsi2rxss_get_nth_mbus()
298 /* This returns the data type for a media bus format else 0 */
312 * xcsi2rxss_soft_reset - Does a soft reset of the MIPI CSI-2 Rx Subsystem
313 * @state: Xilinx CSI-2 Rx Subsystem structure pointer
318 * Return: 0 - on success OR -ETIME if reset times out
328 dev_err(state->dev, "soft reset timed out!\n"); in xcsi2rxss_soft_reset()
329 return -ETIME; in xcsi2rxss_soft_reset()
332 timeout--; in xcsi2rxss_soft_reset()
342 if (!state->rst_gpio) in xcsi2rxss_hard_reset()
346 gpiod_set_value_cansleep(state->rst_gpio, 1); in xcsi2rxss_hard_reset()
348 gpiod_set_value_cansleep(state->rst_gpio, 0); in xcsi2rxss_hard_reset()
356 state->events[i] = 0; in xcsi2rxss_reset_event_counters()
359 state->vcx_events[i] = 0; in xcsi2rxss_reset_event_counters()
365 struct device *dev = state->dev; in xcsi2rxss_log_counters()
369 if (state->events[i] > 0) { in xcsi2rxss_log_counters()
372 state->events[i]); in xcsi2rxss_log_counters()
376 if (state->en_vcx) { in xcsi2rxss_log_counters()
378 if (state->vcx_events[i] > 0) { in xcsi2rxss_log_counters()
383 state->vcx_events[i]); in xcsi2rxss_log_counters()
392 struct device *dev = xcsi2rxss->dev; in xcsi2rxss_log_status()
396 mutex_lock(&xcsi2rxss->lock); in xcsi2rxss_log_status()
434 if (xcsi2rxss->en_vcx) in xcsi2rxss_log_status()
461 mutex_unlock(&xcsi2rxss->lock); in xcsi2rxss_log_status()
471 if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) in xcsi2rxss_get_remote_subdev()
474 return media_entity_to_v4l2_subdev(remote->entity); in xcsi2rxss_get_remote_subdev()
486 state->streaming = false; in xcsi2rxss_start_stream()
495 state->streaming = true; in xcsi2rxss_start_stream()
497 state->rsubdev = in xcsi2rxss_start_stream()
498 xcsi2rxss_get_remote_subdev(&state->pads[XVIP_PAD_SINK]); in xcsi2rxss_start_stream()
500 ret = v4l2_subdev_call(state->rsubdev, video, s_stream, 1); in xcsi2rxss_start_stream()
508 state->streaming = false; in xcsi2rxss_start_stream()
516 v4l2_subdev_call(state->rsubdev, video, s_stream, 0); in xcsi2rxss_stop_stream()
524 state->streaming = false; in xcsi2rxss_stop_stream()
528 * xcsi2rxss_irq_handler - Interrupt handler for CSI-2
540 struct device *dev = state->dev; in xcsi2rxss_irq_handler()
603 state->events[i]++; in xcsi2rxss_irq_handler()
606 state->events[i]); in xcsi2rxss_irq_handler()
609 if (status & XCSI_ISR_VCXFE && state->en_vcx) { in xcsi2rxss_irq_handler()
617 state->vcx_events[i]++; in xcsi2rxss_irq_handler()
631 mutex_lock(&xcsi2rxss->lock); in xcsi2rxss_s_stream()
633 if (enable == xcsi2rxss->streaming) in xcsi2rxss_s_stream()
645 mutex_unlock(&xcsi2rxss->lock); in xcsi2rxss_s_stream()
658 return &xcsi2rxss->format; in __xcsi2rxss_get_pad_format()
668 struct v4l2_mbus_framefmt *format; in xcsi2rxss_init_state() local
671 mutex_lock(&xcsi2rxss->lock); in xcsi2rxss_init_state()
673 format = v4l2_subdev_state_get_format(sd_state, i); in xcsi2rxss_init_state()
674 *format = xcsi2rxss->default_format; in xcsi2rxss_init_state()
676 mutex_unlock(&xcsi2rxss->lock); in xcsi2rxss_init_state()
687 mutex_lock(&xcsi2rxss->lock); in xcsi2rxss_get_format()
688 fmt->format = *__xcsi2rxss_get_pad_format(xcsi2rxss, sd_state, in xcsi2rxss_get_format()
689 fmt->pad, in xcsi2rxss_get_format()
690 fmt->which); in xcsi2rxss_get_format()
691 mutex_unlock(&xcsi2rxss->lock); in xcsi2rxss_get_format()
704 mutex_lock(&xcsi2rxss->lock); in xcsi2rxss_set_format()
707 * Only the format->code parameter matters for CSI as the in xcsi2rxss_set_format()
708 * CSI format cannot be changed at runtime. in xcsi2rxss_set_format()
709 * Ensure that format to set is copied to over to CSI pad format in xcsi2rxss_set_format()
712 fmt->pad, fmt->which); in xcsi2rxss_set_format()
714 /* only sink pad format can be updated */ in xcsi2rxss_set_format()
715 if (fmt->pad == XVIP_PAD_SOURCE) { in xcsi2rxss_set_format()
716 fmt->format = *__format; in xcsi2rxss_set_format()
717 mutex_unlock(&xcsi2rxss->lock); in xcsi2rxss_set_format()
722 * RAW8 is supported in all datatypes. So if requested media bus format in xcsi2rxss_set_format()
724 * other RAW, YUV422 8/10 or RGB888, set appropriate media bus format. in xcsi2rxss_set_format()
726 dt = xcsi2rxss_get_dt(fmt->format.code); in xcsi2rxss_set_format()
727 if (dt != xcsi2rxss->datatype && dt != MIPI_CSI2_DT_RAW8) { in xcsi2rxss_set_format()
728 dev_dbg(xcsi2rxss->dev, "Unsupported media bus format"); in xcsi2rxss_set_format()
729 /* set the default format for the data type */ in xcsi2rxss_set_format()
730 fmt->format.code = xcsi2rxss_get_nth_mbus(xcsi2rxss->datatype, in xcsi2rxss_set_format()
734 *__format = fmt->format; in xcsi2rxss_set_format()
735 mutex_unlock(&xcsi2rxss->lock); in xcsi2rxss_set_format()
749 if (code->index < 4) { in xcsi2rxss_enum_mbus_code()
750 n = code->index; in xcsi2rxss_enum_mbus_code()
752 } else if (state->datatype != MIPI_CSI2_DT_RAW8) { in xcsi2rxss_enum_mbus_code()
753 n = code->index - 4; in xcsi2rxss_enum_mbus_code()
754 dt = state->datatype; in xcsi2rxss_enum_mbus_code()
756 return -EINVAL; in xcsi2rxss_enum_mbus_code()
759 code->code = xcsi2rxss_get_nth_mbus(dt, n); in xcsi2rxss_enum_mbus_code()
760 if (!code->code) in xcsi2rxss_enum_mbus_code()
761 ret = -EINVAL; in xcsi2rxss_enum_mbus_code()
766 /* -----------------------------------------------------------------------------
801 struct device *dev = xcsi2rxss->dev; in xcsi2rxss_parse_of()
802 struct device_node *node = dev->of_node; in xcsi2rxss_parse_of()
811 en_csi_v20 = of_property_read_bool(node, "xlnx,en-csi-v2-0"); in xcsi2rxss_parse_of()
813 xcsi2rxss->en_vcx = of_property_read_bool(node, "xlnx,en-vcx"); in xcsi2rxss_parse_of()
815 xcsi2rxss->enable_active_lanes = in xcsi2rxss_parse_of()
816 of_property_read_bool(node, "xlnx,en-active-lanes"); in xcsi2rxss_parse_of()
818 ret = of_property_read_u32(node, "xlnx,csi-pxl-format", in xcsi2rxss_parse_of()
819 &xcsi2rxss->datatype); in xcsi2rxss_parse_of()
821 dev_err(dev, "missing xlnx,csi-pxl-format property\n"); in xcsi2rxss_parse_of()
825 switch (xcsi2rxss->datatype) { in xcsi2rxss_parse_of()
843 ret = -EINVAL; in xcsi2rxss_parse_of()
844 dev_dbg(dev, "enable csi v2 for this pixel format"); in xcsi2rxss_parse_of()
848 ret = -EINVAL; in xcsi2rxss_parse_of()
851 dev_err(dev, "invalid csi-pxl-format property!\n"); in xcsi2rxss_parse_of()
858 return -EINVAL; in xcsi2rxss_parse_of()
866 return -EINVAL; in xcsi2rxss_parse_of()
879 xcsi2rxss->max_num_lanes = vep.bus.mipi_csi2.num_data_lanes; in xcsi2rxss_parse_of()
886 return -EINVAL; in xcsi2rxss_parse_of()
892 xcsi2rxss->en_vcx ? "enabled" : "disabled", in xcsi2rxss_parse_of()
893 xcsi2rxss->max_num_lanes, in xcsi2rxss_parse_of()
894 xcsi2rxss->enable_active_lanes ? "dynamic" : "static", in xcsi2rxss_parse_of()
895 xcsi2rxss->datatype); in xcsi2rxss_parse_of()
905 struct device *dev = &pdev->dev; in xcsi2rxss_probe()
910 return -ENOMEM; in xcsi2rxss_probe()
912 xcsi2rxss->dev = dev; in xcsi2rxss_probe()
914 xcsi2rxss->clks = devm_kmemdup(dev, xcsi2rxss_clks, in xcsi2rxss_probe()
916 if (!xcsi2rxss->clks) in xcsi2rxss_probe()
917 return -ENOMEM; in xcsi2rxss_probe()
920 xcsi2rxss->rst_gpio = devm_gpiod_get_optional(dev, "video-reset", in xcsi2rxss_probe()
922 if (IS_ERR(xcsi2rxss->rst_gpio)) in xcsi2rxss_probe()
923 return dev_err_probe(dev, PTR_ERR(xcsi2rxss->rst_gpio), in xcsi2rxss_probe()
930 xcsi2rxss->iomem = devm_platform_ioremap_resource(pdev, 0); in xcsi2rxss_probe()
931 if (IS_ERR(xcsi2rxss->iomem)) in xcsi2rxss_probe()
932 return PTR_ERR(xcsi2rxss->iomem); in xcsi2rxss_probe()
946 ret = clk_bulk_get(dev, num_clks, xcsi2rxss->clks); in xcsi2rxss_probe()
951 ret = clk_bulk_prepare_enable(num_clks, xcsi2rxss->clks); in xcsi2rxss_probe()
955 mutex_init(&xcsi2rxss->lock); in xcsi2rxss_probe()
961 xcsi2rxss->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK; in xcsi2rxss_probe()
962 xcsi2rxss->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; in xcsi2rxss_probe()
964 /* Initialize the default format */ in xcsi2rxss_probe()
965 xcsi2rxss->default_format.code = in xcsi2rxss_probe()
966 xcsi2rxss_get_nth_mbus(xcsi2rxss->datatype, 0); in xcsi2rxss_probe()
967 xcsi2rxss->default_format.field = V4L2_FIELD_NONE; in xcsi2rxss_probe()
968 xcsi2rxss->default_format.colorspace = V4L2_COLORSPACE_SRGB; in xcsi2rxss_probe()
969 xcsi2rxss->default_format.width = XCSI_DEFAULT_WIDTH; in xcsi2rxss_probe()
970 xcsi2rxss->default_format.height = XCSI_DEFAULT_HEIGHT; in xcsi2rxss_probe()
971 xcsi2rxss->format = xcsi2rxss->default_format; in xcsi2rxss_probe()
974 subdev = &xcsi2rxss->subdev; in xcsi2rxss_probe()
976 subdev->internal_ops = &xcsi2rxss_internal_ops; in xcsi2rxss_probe()
977 subdev->dev = dev; in xcsi2rxss_probe()
978 strscpy(subdev->name, dev_name(dev), sizeof(subdev->name)); in xcsi2rxss_probe()
979 subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; in xcsi2rxss_probe()
980 subdev->entity.ops = &xcsi2rxss_media_ops; in xcsi2rxss_probe()
983 ret = media_entity_pads_init(&subdev->entity, XCSI_MEDIA_PADS, in xcsi2rxss_probe()
984 xcsi2rxss->pads); in xcsi2rxss_probe()
998 media_entity_cleanup(&subdev->entity); in xcsi2rxss_probe()
999 mutex_destroy(&xcsi2rxss->lock); in xcsi2rxss_probe()
1000 clk_bulk_disable_unprepare(num_clks, xcsi2rxss->clks); in xcsi2rxss_probe()
1002 clk_bulk_put(num_clks, xcsi2rxss->clks); in xcsi2rxss_probe()
1009 struct v4l2_subdev *subdev = &xcsi2rxss->subdev; in xcsi2rxss_remove()
1013 media_entity_cleanup(&subdev->entity); in xcsi2rxss_remove()
1014 mutex_destroy(&xcsi2rxss->lock); in xcsi2rxss_remove()
1015 clk_bulk_disable_unprepare(num_clks, xcsi2rxss->clks); in xcsi2rxss_remove()
1016 clk_bulk_put(num_clks, xcsi2rxss->clks); in xcsi2rxss_remove()
1020 { .compatible = "xlnx,mipi-csi2-rx-subsystem-5.0", },
1027 .name = "xilinx-csi2rxss",
1037 MODULE_DESCRIPTION("Xilinx MIPI CSI-2 Rx Subsystem Driver");