Lines Matching +full:poc +full:- +full:supply
1 // SPDX-License-Identifier: GPL-2.0
13 #include <linux/i2c-mux.h>
18 #include <media/v4l2-cci.h>
19 #include <media/v4l2-ctrls.h>
20 #include <media/v4l2-fwnode.h>
21 #include <media/v4l2-subdev.h>
96 struct regulator *poc; member
126 return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N, in max96714_enable_tx_port()
133 return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N, in max96714_disable_tx_port()
141 cci_read(priv->regmap, MAX96714_MIPI_STDBY_N, &val, NULL); in max96714_tx_port_enabled()
151 const u32 h_active = fmt->width; in max96714_apply_patgen_timing()
156 const u32 v_active = fmt->height; in max96714_apply_patgen_timing()
167 cci_update_bits(priv->regmap, MAX96714_IO_CHK0, in max96714_apply_patgen_timing()
170 dev_info(&priv->client->dev, "height: %d width: %d\n", fmt->height, in max96714_apply_patgen_timing()
171 fmt->width); in max96714_apply_patgen_timing()
173 cci_write(priv->regmap, MAX96714_PATGEN_VS_DLY, 0, &ret); in max96714_apply_patgen_timing()
174 cci_write(priv->regmap, MAX96714_PATGEN_VS_HIGH, v_sw * h_tot, &ret); in max96714_apply_patgen_timing()
175 cci_write(priv->regmap, MAX96714_PATGEN_VS_LOW, in max96714_apply_patgen_timing()
177 cci_write(priv->regmap, MAX96714_PATGEN_HS_HIGH, h_sw, &ret); in max96714_apply_patgen_timing()
178 cci_write(priv->regmap, MAX96714_PATGEN_HS_LOW, h_active + h_fp + h_bp, in max96714_apply_patgen_timing()
180 cci_write(priv->regmap, MAX96714_PATGEN_V2D, in max96714_apply_patgen_timing()
182 cci_write(priv->regmap, MAX96714_PATGEN_HS_CNT, v_tot, &ret); in max96714_apply_patgen_timing()
183 cci_write(priv->regmap, MAX96714_PATGEN_DE_HIGH, h_active, &ret); in max96714_apply_patgen_timing()
184 cci_write(priv->regmap, MAX96714_PATGEN_DE_LOW, h_fp + h_sw + h_bp, in max96714_apply_patgen_timing()
186 cci_write(priv->regmap, MAX96714_PATGEN_DE_CNT, v_active, &ret); in max96714_apply_patgen_timing()
188 cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_A, 0xfecc00, &ret); in max96714_apply_patgen_timing()
190 cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_B, 0x006aa7, &ret); in max96714_apply_patgen_timing()
191 cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_A, 0x3c, &ret); in max96714_apply_patgen_timing()
192 cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_B, 0x3c, &ret); in max96714_apply_patgen_timing()
193 cci_write(priv->regmap, MAX96714_PATGEN_CHKB_ALT, 0x3c, &ret); in max96714_apply_patgen_timing()
194 cci_write(priv->regmap, MAX96714_PATGEN_GRAD_INC, 0x10, &ret); in max96714_apply_patgen_timing()
205 if (priv->pattern) in max96714_apply_patgen()
208 cci_write(priv->regmap, MAX96714_PATGEN_0, priv->pattern ? 0xfb : 0, in max96714_apply_patgen()
211 val = FIELD_PREP(MAX96714_PATGEN_MODE, priv->pattern); in max96714_apply_patgen()
212 cci_update_bits(priv->regmap, MAX96714_PATGEN_1, MAX96714_PATGEN_MODE, in max96714_apply_patgen()
220 container_of(ctrl->handler, struct max96714_priv, ctrl_handler); in max96714_s_ctrl()
223 switch (ctrl->id) { in max96714_s_ctrl()
225 if (priv->enabled_source_streams) in max96714_s_ctrl()
226 return -EBUSY; in max96714_s_ctrl()
227 priv->pattern = ctrl->val; in max96714_s_ctrl()
230 return -EINVAL; in max96714_s_ctrl()
233 ret = cci_update_bits(priv->regmap, MAX96714_MIPI_PHY0, in max96714_s_ctrl()
235 priv->pattern ? MAX96714_FORCE_CSI_OUT : 0, NULL); in max96714_s_ctrl()
238 return cci_update_bits(priv->regmap, MAX96714_MIPI_TX52, in max96714_s_ctrl()
240 priv->pattern ? 0 : MAX96714_TUN_EN, &ret); in max96714_s_ctrl()
261 if (!priv->enabled_source_streams) in max96714_enable_streams()
268 if (!priv->pattern) { in max96714_enable_streams()
269 if (!priv->rxport.source.sd) { in max96714_enable_streams()
270 ret = -ENODEV; in max96714_enable_streams()
280 ret = v4l2_subdev_enable_streams(priv->rxport.source.sd, in max96714_enable_streams()
281 priv->rxport.source.pad, in max96714_enable_streams()
287 priv->enabled_source_streams |= streams_mask; in max96714_enable_streams()
292 if (!priv->enabled_source_streams) in max96714_enable_streams()
305 if (!priv->pattern) { in max96714_disable_streams()
314 ret = v4l2_subdev_disable_streams(priv->rxport.source.sd, in max96714_disable_streams()
315 priv->rxport.source.pad, in max96714_disable_streams()
321 priv->enabled_source_streams &= ~streams_mask; in max96714_disable_streams()
323 if (!priv->enabled_source_streams) in max96714_disable_streams()
336 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE && in max96714_set_fmt()
337 priv->enabled_source_streams) in max96714_set_fmt()
338 return -EBUSY; in max96714_set_fmt()
341 if (format->pad == MAX96714_PAD_SOURCE) in max96714_set_fmt()
344 fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream); in max96714_set_fmt()
346 return -EINVAL; in max96714_set_fmt()
348 *fmt = format->format; in max96714_set_fmt()
350 fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad, in max96714_set_fmt()
351 format->stream); in max96714_set_fmt()
353 return -EINVAL; in max96714_set_fmt()
355 *fmt = format->format; in max96714_set_fmt()
377 if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX) in _max96714_set_routing()
378 return -EINVAL; in _max96714_set_routing()
395 if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams) in max96714_set_routing()
396 return -EBUSY; in max96714_set_routing()
435 cci_read(priv->regmap, MAX96714_LINK_LOCK, &val, NULL); in max96714_link_locked()
442 struct device *dev = &priv->client->dev; in max96714_link_status()
451 cci_read(priv->regmap, MAX96714_VIDEO_RX8, &val, NULL); in max96714_pipe_locked()
458 struct device *dev = &priv->client->dev; in max96714_pipe_status()
465 struct device *dev = &priv->client->dev; in max96714_csi_status()
468 cci_read(priv->regmap, MAX96714_BACKTOP25, &freq, NULL); in max96714_csi_status()
478 struct device *dev = &priv->client->dev; in max96714_log_status()
515 struct max96714_priv *priv = sd_to_max96714(notifier->sd); in max96714_notify_bound()
516 struct device *dev = &priv->client->dev; in max96714_notify_bound()
519 ret = media_entity_get_fwnode_pad(&subdev->entity, in max96714_notify_bound()
520 priv->rxport.source.ep_fwnode, in max96714_notify_bound()
523 dev_err(dev, "Failed to find pad for %s\n", subdev->name); in max96714_notify_bound()
527 priv->rxport.source.sd = subdev; in max96714_notify_bound()
528 priv->rxport.source.pad = ret; in max96714_notify_bound()
530 ret = media_create_pad_link(&priv->rxport.source.sd->entity, in max96714_notify_bound()
531 priv->rxport.source.pad, &priv->sd.entity, in max96714_notify_bound()
536 dev_err(dev, "Unable to link %s:%u -> %s:%u\n", in max96714_notify_bound()
537 priv->rxport.source.sd->name, priv->rxport.source.pad, in max96714_notify_bound()
538 priv->sd.name, MAX96714_PAD_SINK); in max96714_notify_bound()
551 struct device *dev = &priv->client->dev; in max96714_v4l2_notifier_register()
552 struct max96714_rxport *rxport = &priv->rxport; in max96714_v4l2_notifier_register()
556 if (!rxport->source.ep_fwnode) in max96714_v4l2_notifier_register()
559 v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd); in max96714_v4l2_notifier_register()
561 asd = v4l2_async_nf_add_fwnode(&priv->notifier, in max96714_v4l2_notifier_register()
562 rxport->source.ep_fwnode, in max96714_v4l2_notifier_register()
566 v4l2_async_nf_cleanup(&priv->notifier); in max96714_v4l2_notifier_register()
570 priv->notifier.ops = &max96714_notify_ops; in max96714_v4l2_notifier_register()
572 ret = v4l2_async_nf_register(&priv->notifier); in max96714_v4l2_notifier_register()
575 v4l2_async_nf_cleanup(&priv->notifier); in max96714_v4l2_notifier_register()
584 struct device *dev = &priv->client->dev; in max96714_create_subdev()
587 v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96714_subdev_ops); in max96714_create_subdev()
588 priv->sd.internal_ops = &max96714_internal_ops; in max96714_create_subdev()
590 v4l2_ctrl_handler_init(&priv->ctrl_handler, 1); in max96714_create_subdev()
591 priv->sd.ctrl_handler = &priv->ctrl_handler; in max96714_create_subdev()
593 v4l2_ctrl_new_int_menu(&priv->ctrl_handler, NULL, V4L2_CID_LINK_FREQ, in max96714_create_subdev()
594 0, 0, &priv->tx_link_freq); in max96714_create_subdev()
595 v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, in max96714_create_subdev()
598 ARRAY_SIZE(max96714_test_pattern) - 1, in max96714_create_subdev()
600 if (priv->ctrl_handler.error) { in max96714_create_subdev()
601 ret = priv->ctrl_handler.error; in max96714_create_subdev()
605 priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS; in max96714_create_subdev()
606 priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; in max96714_create_subdev()
607 priv->sd.entity.ops = &max96714_entity_ops; in max96714_create_subdev()
609 priv->pads[MAX96714_PAD_SINK].flags = MEDIA_PAD_FL_SINK; in max96714_create_subdev()
610 priv->pads[MAX96714_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; in max96714_create_subdev()
612 ret = media_entity_pads_init(&priv->sd.entity, in max96714_create_subdev()
614 priv->pads); in max96714_create_subdev()
618 priv->sd.state_lock = priv->sd.ctrl_handler->lock; in max96714_create_subdev()
620 ret = v4l2_subdev_init_finalize(&priv->sd); in max96714_create_subdev()
630 ret = v4l2_async_register_subdev(&priv->sd); in max96714_create_subdev()
639 v4l2_async_nf_unregister(&priv->notifier); in max96714_create_subdev()
640 v4l2_async_nf_cleanup(&priv->notifier); in max96714_create_subdev()
642 v4l2_subdev_cleanup(&priv->sd); in max96714_create_subdev()
644 media_entity_cleanup(&priv->sd.entity); in max96714_create_subdev()
646 v4l2_ctrl_handler_free(&priv->ctrl_handler); in max96714_create_subdev()
653 v4l2_async_nf_unregister(&priv->notifier); in max96714_destroy_subdev()
654 v4l2_async_nf_cleanup(&priv->notifier); in max96714_destroy_subdev()
655 v4l2_async_unregister_subdev(&priv->sd); in max96714_destroy_subdev()
657 v4l2_subdev_cleanup(&priv->sd); in max96714_destroy_subdev()
659 media_entity_cleanup(&priv->sd.entity); in max96714_destroy_subdev()
660 v4l2_ctrl_handler_free(&priv->ctrl_handler); in max96714_destroy_subdev()
670 priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev, in max96714_i2c_mux_init()
673 if (!priv->mux) in max96714_i2c_mux_init()
674 return -ENOMEM; in max96714_i2c_mux_init()
676 return i2c_mux_add_adapter(priv->mux, 0, 0); in max96714_i2c_mux_init()
688 mipi = &priv->mipi_csi2; in max96714_init_tx_port()
689 val = div_u64(priv->tx_link_freq * 2, MHZ(100)); in max96714_init_tx_port()
691 cci_update_bits(priv->regmap, MAX96714_BACKTOP25, in max96714_init_tx_port()
694 val = FIELD_PREP(MAX96714_CSI2_LANE_CNT_MASK, mipi->num_data_lanes - 1); in max96714_init_tx_port()
695 cci_update_bits(priv->regmap, MAX96714_MIPI_LANE_CNT, in max96714_init_tx_port()
700 for (lane = 0; lane < mipi->num_data_lanes + 1; lane++) { in max96714_init_tx_port()
701 if (!mipi->lane_polarities[lane]) in max96714_init_tx_port()
708 val |= BIT(lane - 1); in max96714_init_tx_port()
714 cci_update_bits(priv->regmap, MAX96714_MIPI_POLARITY, in max96714_init_tx_port()
719 for (lane = 0; lane < mipi->num_data_lanes; lane++) { in max96714_init_tx_port()
720 val |= (mipi->data_lanes[lane] - 1) << (lane * 2); in max96714_init_tx_port()
721 lanes_used |= BIT(mipi->data_lanes[lane] - 1); in max96714_init_tx_port()
736 return cci_write(priv->regmap, MAX96714_MIPI_LANE_MAP, val, &ret); in max96714_init_tx_port()
741 struct max96714_rxport *rxport = &priv->rxport; in max96714_rxport_enable_poc()
743 if (!rxport->poc) in max96714_rxport_enable_poc()
746 return regulator_enable(rxport->poc); in max96714_rxport_enable_poc()
751 struct max96714_rxport *rxport = &priv->rxport; in max96714_rxport_disable_poc()
753 if (!rxport->poc) in max96714_rxport_disable_poc()
756 return regulator_disable(rxport->poc); in max96714_rxport_disable_poc()
761 struct device *dev = &priv->client->dev; in max96714_parse_dt_txport()
770 return -EINVAL; in max96714_parse_dt_txport()
776 return -EINVAL; in max96714_parse_dt_txport()
780 ret = -EINVAL; in max96714_parse_dt_txport()
784 priv->tx_link_freq = vep.link_frequencies[0]; in max96714_parse_dt_txport()
786 if (priv->tx_link_freq < MHZ(50) || priv->tx_link_freq > MHZ(1250) || in max96714_parse_dt_txport()
787 (u32)priv->tx_link_freq % MHZ(50)) { in max96714_parse_dt_txport()
789 ret = -EINVAL; in max96714_parse_dt_txport()
797 ret = -EINVAL; in max96714_parse_dt_txport()
801 priv->mipi_csi2 = vep.bus.mipi_csi2; in max96714_parse_dt_txport()
811 static const char *poc_name = "port0-poc"; in max96714_parse_dt_rxport()
812 struct max96714_rxport *rxport = &priv->rxport; in max96714_parse_dt_rxport()
813 struct device *dev = &priv->client->dev; in max96714_parse_dt_rxport()
820 return -ENOENT; in max96714_parse_dt_rxport()
822 rxport->source.ep_fwnode = fwnode_graph_get_remote_endpoint(ep_fwnode); in max96714_parse_dt_rxport()
825 if (!rxport->source.ep_fwnode) { in max96714_parse_dt_rxport()
827 return -EINVAL; in max96714_parse_dt_rxport()
830 rxport->poc = devm_regulator_get_optional(dev, poc_name); in max96714_parse_dt_rxport()
831 if (IS_ERR(rxport->poc)) { in max96714_parse_dt_rxport()
832 ret = PTR_ERR(rxport->poc); in max96714_parse_dt_rxport()
833 if (ret == -ENODEV) { in max96714_parse_dt_rxport()
834 rxport->poc = NULL; in max96714_parse_dt_rxport()
836 dev_err(dev, "rx: failed to get POC supply: %d\n", ret); in max96714_parse_dt_rxport()
844 fwnode_handle_put(rxport->source.ep_fwnode); in max96714_parse_dt_rxport()
861 if (ret && ret == -ENOENT) in max96714_parse_dt()
869 struct device *dev = &priv->client->dev; in max96714_enable_core_hw()
873 if (priv->pd_gpio) { in max96714_enable_core_hw()
875 gpiod_set_value_cansleep(priv->pd_gpio, 1); in max96714_enable_core_hw()
877 gpiod_set_value_cansleep(priv->pd_gpio, 0); in max96714_enable_core_hw()
882 ret = cci_read(priv->regmap, MAX96714_REG13, &val, NULL); in max96714_enable_core_hw()
891 ret = -EOPNOTSUPP; in max96714_enable_core_hw()
895 ret = cci_read(priv->regmap, MAX96714_DEV_REV, &val, NULL); in max96714_enable_core_hw()
902 ret = cci_read(priv->regmap, MAX96714_MIPI_TX52, &val, NULL); in max96714_enable_core_hw()
908 ret = -EOPNOTSUPP; in max96714_enable_core_hw()
915 gpiod_set_value_cansleep(priv->pd_gpio, 1); in max96714_enable_core_hw()
921 gpiod_set_value_cansleep(priv->pd_gpio, 1); in max96714_disable_core_hw()
926 struct device *dev = &priv->client->dev; in max96714_get_hw_resources()
928 priv->regmap = devm_cci_regmap_init_i2c(priv->client, 16); in max96714_get_hw_resources()
929 if (IS_ERR(priv->regmap)) in max96714_get_hw_resources()
930 return PTR_ERR(priv->regmap); in max96714_get_hw_resources()
932 priv->pd_gpio = in max96714_get_hw_resources()
934 if (IS_ERR(priv->pd_gpio)) in max96714_get_hw_resources()
935 return dev_err_probe(dev, PTR_ERR(priv->pd_gpio), in max96714_get_hw_resources()
942 struct device *dev = &client->dev; in max96714_probe()
948 return -ENOMEM; in max96714_probe()
950 priv->client = client; in max96714_probe()
981 i2c_mux_del_adapters(priv->mux); in max96714_probe()
985 fwnode_handle_put(priv->rxport.source.ep_fwnode); in max96714_probe()
998 i2c_mux_del_adapters(priv->mux); in max96714_remove()
1000 fwnode_handle_put(priv->rxport.source.ep_fwnode); in max96714_remove()
1002 gpiod_set_value_cansleep(priv->pd_gpio, 1); in max96714_remove()