Lines Matching +full:sdm845 +full:- +full:camss

1 // SPDX-License-Identifier: GPL-2.0
3 * camss-csid.c
5 * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
7 * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
8 * Copyright (C) 2015-2018 Linaro Ltd.
19 #include <media/media-entity.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-subdev.h>
24 #include "camss-csid.h"
25 #include "camss-csid-gen1.h"
26 #include "camss.h"
40 "Pseudo-random Data",
528 * csid_set_clock_rates - Calculate and set clock rates on CSID module
533 struct device *dev = csid->camss->dev; in csid_set_clock_rates()
539 fmt = csid_get_fmt_entry(csid->res->formats->formats, csid->res->formats->nformats, in csid_set_clock_rates()
540 csid->fmt[MSM_CSIPHY_PAD_SINK].code); in csid_set_clock_rates()
541 link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp, in csid_set_clock_rates()
542 csid->phy.lane_cnt); in csid_set_clock_rates()
546 for (i = 0; i < csid->nclocks; i++) { in csid_set_clock_rates()
547 struct camss_clock *clock = &csid->clock[i]; in csid_set_clock_rates()
549 if (!strcmp(clock->name, "csi0") || in csid_set_clock_rates()
550 !strcmp(clock->name, "csi1") || in csid_set_clock_rates()
551 !strcmp(clock->name, "csi2") || in csid_set_clock_rates()
552 !strcmp(clock->name, "csi3")) { in csid_set_clock_rates()
558 for (j = 0; j < clock->nfreqs; j++) in csid_set_clock_rates()
559 if (min_rate < clock->freq[j]) in csid_set_clock_rates()
562 if (j == clock->nfreqs) { in csid_set_clock_rates()
565 return -EINVAL; in csid_set_clock_rates()
571 j = clock->nfreqs - 1; in csid_set_clock_rates()
573 rate = clk_round_rate(clock->clk, clock->freq[j]); in csid_set_clock_rates()
577 return -EINVAL; in csid_set_clock_rates()
580 ret = clk_set_rate(clock->clk, rate); in csid_set_clock_rates()
585 } else if (clock->nfreqs) { in csid_set_clock_rates()
586 clk_set_rate(clock->clk, clock->freq[0]); in csid_set_clock_rates()
594 * csid_set_power - Power on/off CSID module
603 struct camss *camss = csid->camss; in csid_set_power() local
604 struct device *dev = camss->dev; in csid_set_power()
609 * From SDM845 onwards, the VFE needs to be powered on before in csid_set_power()
613 ret = csid->res->parent_dev_ops->get(camss, csid->id); in csid_set_power()
621 ret = regulator_bulk_enable(csid->num_supplies, in csid_set_power()
622 csid->supplies); in csid_set_power()
630 regulator_bulk_disable(csid->num_supplies, in csid_set_power()
631 csid->supplies); in csid_set_power()
636 ret = camss_enable_clocks(csid->nclocks, csid->clock, dev); in csid_set_power()
638 regulator_bulk_disable(csid->num_supplies, in csid_set_power()
639 csid->supplies); in csid_set_power()
644 csid->phy.need_vc_update = true; in csid_set_power()
646 enable_irq(csid->irq); in csid_set_power()
648 ret = csid->res->hw_ops->reset(csid); in csid_set_power()
650 disable_irq(csid->irq); in csid_set_power()
651 camss_disable_clocks(csid->nclocks, csid->clock); in csid_set_power()
652 regulator_bulk_disable(csid->num_supplies, in csid_set_power()
653 csid->supplies); in csid_set_power()
658 csid->res->hw_ops->hw_version(csid); in csid_set_power()
660 disable_irq(csid->irq); in csid_set_power()
661 camss_disable_clocks(csid->nclocks, csid->clock); in csid_set_power()
662 regulator_bulk_disable(csid->num_supplies, in csid_set_power()
663 csid->supplies); in csid_set_power()
665 csid->res->parent_dev_ops->put(camss, csid->id); in csid_set_power()
672 * csid_set_stream - Enable/disable streaming on CSID module
686 ret = v4l2_ctrl_handler_setup(&csid->ctrls); in csid_set_stream()
688 dev_err(csid->camss->dev, in csid_set_stream()
693 if (!csid->testgen.enabled && in csid_set_stream()
694 !media_pad_remote_pad_first(&csid->pads[MSM_CSID_PAD_SINK])) in csid_set_stream()
695 return -ENOLINK; in csid_set_stream()
698 if (csid->phy.need_vc_update) { in csid_set_stream()
699 csid->res->hw_ops->configure_stream(csid, enable); in csid_set_stream()
700 csid->phy.need_vc_update = false; in csid_set_stream()
707 * __csid_get_format - Get pointer to format structure
724 return &csid->fmt[pad]; in __csid_get_format()
728 * csid_try_format - Handle try format by pad subdev method
747 for (i = 0; i < csid->res->formats->nformats; i++) in csid_try_format()
748 if (fmt->code == csid->res->formats->formats[i].code) in csid_try_format()
752 if (i >= csid->res->formats->nformats) in csid_try_format()
753 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; in csid_try_format()
755 fmt->width = clamp_t(u32, fmt->width, 1, 8191); in csid_try_format()
756 fmt->height = clamp_t(u32, fmt->height, 1, 8191); in csid_try_format()
758 fmt->field = V4L2_FIELD_NONE; in csid_try_format()
759 fmt->colorspace = V4L2_COLORSPACE_SRGB; in csid_try_format()
764 if (csid->testgen_mode->cur.val == 0) { in csid_try_format()
767 u32 code = fmt->code; in csid_try_format()
771 fmt->code = csid->res->hw_ops->src_pad_code(csid, fmt->code, 0, code); in csid_try_format()
776 for (i = 0; i < csid->res->formats->nformats; i++) in csid_try_format()
777 if (csid->res->formats->formats[i].code == fmt->code) in csid_try_format()
781 if (i >= csid->res->formats->nformats) in csid_try_format()
782 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; in csid_try_format()
784 fmt->width = clamp_t(u32, fmt->width, 1, 8191); in csid_try_format()
785 fmt->height = clamp_t(u32, fmt->height, 1, 8191); in csid_try_format()
787 fmt->field = V4L2_FIELD_NONE; in csid_try_format()
792 fmt->colorspace = V4L2_COLORSPACE_SRGB; in csid_try_format()
796 * csid_enum_mbus_code - Handle pixel format enumeration
800 * return -EINVAL or zero on success
808 if (code->pad == MSM_CSID_PAD_SINK) { in csid_enum_mbus_code()
809 if (code->index >= csid->res->formats->nformats) in csid_enum_mbus_code()
810 return -EINVAL; in csid_enum_mbus_code()
812 code->code = csid->res->formats->formats[code->index].code; in csid_enum_mbus_code()
814 if (csid->testgen_mode->cur.val == 0) { in csid_enum_mbus_code()
819 code->which); in csid_enum_mbus_code()
821 code->code = csid->res->hw_ops->src_pad_code(csid, sink_fmt->code, in csid_enum_mbus_code()
822 code->index, 0); in csid_enum_mbus_code()
823 if (!code->code) in csid_enum_mbus_code()
824 return -EINVAL; in csid_enum_mbus_code()
826 if (code->index >= csid->res->formats->nformats) in csid_enum_mbus_code()
827 return -EINVAL; in csid_enum_mbus_code()
829 code->code = csid->res->formats->formats[code->index].code; in csid_enum_mbus_code()
837 * csid_enum_frame_size - Handle frame size enumeration
841 * return -EINVAL or zero on success
850 if (fse->index != 0) in csid_enum_frame_size()
851 return -EINVAL; in csid_enum_frame_size()
853 format.code = fse->code; in csid_enum_frame_size()
856 csid_try_format(csid, sd_state, fse->pad, &format, fse->which); in csid_enum_frame_size()
857 fse->min_width = format.width; in csid_enum_frame_size()
858 fse->min_height = format.height; in csid_enum_frame_size()
860 if (format.code != fse->code) in csid_enum_frame_size()
861 return -EINVAL; in csid_enum_frame_size()
863 format.code = fse->code; in csid_enum_frame_size()
864 format.width = -1; in csid_enum_frame_size()
865 format.height = -1; in csid_enum_frame_size()
866 csid_try_format(csid, sd_state, fse->pad, &format, fse->which); in csid_enum_frame_size()
867 fse->max_width = format.width; in csid_enum_frame_size()
868 fse->max_height = format.height; in csid_enum_frame_size()
874 * csid_get_format - Handle get format by pads subdev method
879 * Return -EINVAL or zero on success
888 format = __csid_get_format(csid, sd_state, fmt->pad, fmt->which); in csid_get_format()
890 return -EINVAL; in csid_get_format()
892 fmt->format = *format; in csid_get_format()
898 * csid_set_format - Handle set format by pads subdev method
903 * Return -EINVAL or zero on success
913 format = __csid_get_format(csid, sd_state, fmt->pad, fmt->which); in csid_set_format()
915 return -EINVAL; in csid_set_format()
917 csid_try_format(csid, sd_state, fmt->pad, &fmt->format, fmt->which); in csid_set_format()
918 *format = fmt->format; in csid_set_format()
921 if (fmt->pad == MSM_CSID_PAD_SINK) { in csid_set_format()
923 format = __csid_get_format(csid, sd_state, i, fmt->which); in csid_set_format()
925 *format = fmt->format; in csid_set_format()
926 csid_try_format(csid, sd_state, i, format, fmt->which); in csid_set_format()
934 * csid_init_formats - Initialize formats on all pads
955 return csid_set_format(sd, fh ? fh->state : NULL, &format); in csid_init_formats()
959 * csid_set_test_pattern - Set test generator's pattern mode
967 struct csid_testgen_config *tg = &csid->testgen; in csid_set_test_pattern()
970 if (value && media_pad_remote_pad_first(&csid->pads[MSM_CSID_PAD_SINK])) in csid_set_test_pattern()
971 return -EBUSY; in csid_set_test_pattern()
973 tg->enabled = !!value; in csid_set_test_pattern()
975 return csid->res->hw_ops->configure_testgen_pattern(csid, value); in csid_set_test_pattern()
979 * csid_s_ctrl - Handle set control subdev method
986 struct csid_device *csid = container_of(ctrl->handler, in csid_s_ctrl()
988 int ret = -EINVAL; in csid_s_ctrl()
990 switch (ctrl->id) { in csid_s_ctrl()
992 ret = csid_set_test_pattern(csid, ctrl->val); in csid_s_ctrl()
1004 * msm_csid_subdev_init - Initialize CSID device structure and resources
1011 int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, in msm_csid_subdev_init() argument
1014 struct device *dev = camss->dev; in msm_csid_subdev_init()
1019 csid->camss = camss; in msm_csid_subdev_init()
1020 csid->id = id; in msm_csid_subdev_init()
1021 csid->res = &res->csid; in msm_csid_subdev_init()
1023 if (dev_WARN_ONCE(dev, !csid->res->parent_dev_ops, in msm_csid_subdev_init()
1025 return -EINVAL; in msm_csid_subdev_init()
1028 csid->res->hw_ops->subdev_init(csid); in msm_csid_subdev_init()
1032 if (camss->res->version == CAMSS_8250) { in msm_csid_subdev_init()
1038 csid->base = csid->res->parent_dev_ops->get_base_address(camss, id) in msm_csid_subdev_init()
1041 csid->base = csid->res->parent_dev_ops->get_base_address(camss, id) in msm_csid_subdev_init()
1044 csid->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); in msm_csid_subdev_init()
1045 if (IS_ERR(csid->base)) in msm_csid_subdev_init()
1046 return PTR_ERR(csid->base); in msm_csid_subdev_init()
1051 ret = platform_get_irq_byname(pdev, res->interrupt[0]); in msm_csid_subdev_init()
1055 csid->irq = ret; in msm_csid_subdev_init()
1056 snprintf(csid->irq_name, sizeof(csid->irq_name), "%s_%s%d", in msm_csid_subdev_init()
1057 dev_name(dev), MSM_CSID_NAME, csid->id); in msm_csid_subdev_init()
1058 ret = devm_request_irq(dev, csid->irq, csid->res->hw_ops->isr, in msm_csid_subdev_init()
1060 csid->irq_name, csid); in msm_csid_subdev_init()
1068 csid->nclocks = 0; in msm_csid_subdev_init()
1069 while (res->clock[csid->nclocks]) in msm_csid_subdev_init()
1070 csid->nclocks++; in msm_csid_subdev_init()
1072 csid->clock = devm_kcalloc(dev, csid->nclocks, sizeof(*csid->clock), in msm_csid_subdev_init()
1074 if (!csid->clock) in msm_csid_subdev_init()
1075 return -ENOMEM; in msm_csid_subdev_init()
1077 for (i = 0; i < csid->nclocks; i++) { in msm_csid_subdev_init()
1078 struct camss_clock *clock = &csid->clock[i]; in msm_csid_subdev_init()
1080 clock->clk = devm_clk_get(dev, res->clock[i]); in msm_csid_subdev_init()
1081 if (IS_ERR(clock->clk)) in msm_csid_subdev_init()
1082 return PTR_ERR(clock->clk); in msm_csid_subdev_init()
1084 clock->name = res->clock[i]; in msm_csid_subdev_init()
1086 clock->nfreqs = 0; in msm_csid_subdev_init()
1087 while (res->clock_rate[i][clock->nfreqs]) in msm_csid_subdev_init()
1088 clock->nfreqs++; in msm_csid_subdev_init()
1090 if (!clock->nfreqs) { in msm_csid_subdev_init()
1091 clock->freq = NULL; in msm_csid_subdev_init()
1095 clock->freq = devm_kcalloc(dev, in msm_csid_subdev_init()
1096 clock->nfreqs, in msm_csid_subdev_init()
1097 sizeof(*clock->freq), in msm_csid_subdev_init()
1099 if (!clock->freq) in msm_csid_subdev_init()
1100 return -ENOMEM; in msm_csid_subdev_init()
1102 for (j = 0; j < clock->nfreqs; j++) in msm_csid_subdev_init()
1103 clock->freq[j] = res->clock_rate[i][j]; in msm_csid_subdev_init()
1107 for (i = 0; i < ARRAY_SIZE(res->regulators); i++) { in msm_csid_subdev_init()
1108 if (res->regulators[i]) in msm_csid_subdev_init()
1109 csid->num_supplies++; in msm_csid_subdev_init()
1112 if (csid->num_supplies) { in msm_csid_subdev_init()
1113 csid->supplies = devm_kmalloc_array(camss->dev, in msm_csid_subdev_init()
1114 csid->num_supplies, in msm_csid_subdev_init()
1115 sizeof(*csid->supplies), in msm_csid_subdev_init()
1117 if (!csid->supplies) in msm_csid_subdev_init()
1118 return -ENOMEM; in msm_csid_subdev_init()
1121 for (i = 0; i < csid->num_supplies; i++) in msm_csid_subdev_init()
1122 csid->supplies[i].supply = res->regulators[i]; in msm_csid_subdev_init()
1124 ret = devm_regulator_bulk_get(camss->dev, csid->num_supplies, in msm_csid_subdev_init()
1125 csid->supplies); in msm_csid_subdev_init()
1129 init_completion(&csid->reset_complete); in msm_csid_subdev_init()
1135 * msm_csid_get_csid_id - Get CSID HW module id
1144 *id = csid->id; in msm_csid_get_csid_id()
1148 * csid_get_lane_assign - Calculate CSI2 lane assign configuration parameter
1149 * @lane_cfg - CSI2 lane configuration
1158 for (i = 0; i < lane_cfg->num_data; i++) in csid_get_lane_assign()
1159 lane_assign |= lane_cfg->data[i].pos << (i * 4); in csid_get_lane_assign()
1165 * csid_link_setup - Setup CSID connections
1179 return -EBUSY; in csid_link_setup()
1181 if ((local->flags & MEDIA_PAD_FL_SINK) && in csid_link_setup()
1193 if (csid->testgen_mode->cur.val != 0) in csid_link_setup()
1194 return -EBUSY; in csid_link_setup()
1196 sd = media_entity_to_v4l2_subdev(remote->entity); in csid_link_setup()
1201 if (!csiphy->cfg.csi2) in csid_link_setup()
1202 return -EPERM; in csid_link_setup()
1204 csid->phy.csiphy_id = csiphy->id; in csid_link_setup()
1206 lane_cfg = &csiphy->cfg.csi2->lane_cfg; in csid_link_setup()
1207 csid->phy.lane_cnt = lane_cfg->num_data; in csid_link_setup()
1208 csid->phy.lane_assign = csid_get_lane_assign(lane_cfg); in csid_link_setup()
1211 if (local->flags & MEDIA_PAD_FL_SOURCE) { in csid_link_setup()
1214 struct device *dev = csid->camss->dev; in csid_link_setup()
1217 csid->phy.en_vc |= BIT(local->index - 1); in csid_link_setup()
1219 csid->phy.en_vc &= ~BIT(local->index - 1); in csid_link_setup()
1221 csid->phy.need_vc_update = true; in csid_link_setup()
1224 __func__, csid->phy.en_vc); in csid_link_setup()
1263 * msm_csid_register_entity - Register subdev node for CSID module
1272 struct v4l2_subdev *sd = &csid->subdev; in msm_csid_register_entity()
1273 struct media_pad *pads = csid->pads; in msm_csid_register_entity()
1274 struct device *dev = csid->camss->dev; in msm_csid_register_entity()
1279 sd->internal_ops = &csid_v4l2_internal_ops; in msm_csid_register_entity()
1280 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | in msm_csid_register_entity()
1282 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", in msm_csid_register_entity()
1283 MSM_CSID_NAME, csid->id); in msm_csid_register_entity()
1286 ret = v4l2_ctrl_handler_init(&csid->ctrls, 1); in msm_csid_register_entity()
1292 csid->testgen_mode = v4l2_ctrl_new_std_menu_items(&csid->ctrls, in msm_csid_register_entity()
1294 csid->testgen.nmodes, 0, 0, in msm_csid_register_entity()
1295 csid->testgen.modes); in msm_csid_register_entity()
1297 if (csid->ctrls.error) { in msm_csid_register_entity()
1298 dev_err(dev, "Failed to init ctrl: %d\n", csid->ctrls.error); in msm_csid_register_entity()
1299 ret = csid->ctrls.error; in msm_csid_register_entity()
1303 csid->subdev.ctrl_handler = &csid->ctrls; in msm_csid_register_entity()
1315 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; in msm_csid_register_entity()
1316 sd->entity.ops = &csid_media_ops; in msm_csid_register_entity()
1317 ret = media_entity_pads_init(&sd->entity, MSM_CSID_PADS_NUM, pads); in msm_csid_register_entity()
1332 media_entity_cleanup(&sd->entity); in msm_csid_register_entity()
1334 v4l2_ctrl_handler_free(&csid->ctrls); in msm_csid_register_entity()
1340 * msm_csid_unregister_entity - Unregister CSID module subdev node
1345 v4l2_device_unregister_subdev(&csid->subdev); in msm_csid_unregister_entity()
1346 media_entity_cleanup(&csid->subdev.entity); in msm_csid_unregister_entity()
1347 v4l2_ctrl_handler_free(&csid->ctrls); in msm_csid_unregister_entity()
1352 return csid->camss->res->csid_res[csid->id].csid.is_lite; in csid_is_lite()