Lines Matching full:csi2

218 static u32 rzg2l_csi2_read(struct rzg2l_csi2 *csi2, unsigned int reg)  in rzg2l_csi2_read()  argument
220 return ioread32(csi2->base + reg); in rzg2l_csi2_read()
223 static void rzg2l_csi2_write(struct rzg2l_csi2 *csi2, unsigned int reg, in rzg2l_csi2_write() argument
226 iowrite32(data, csi2->base + reg); in rzg2l_csi2_write()
229 static void rzg2l_csi2_set(struct rzg2l_csi2 *csi2, unsigned int reg, u32 set) in rzg2l_csi2_set() argument
231 rzg2l_csi2_write(csi2, reg, rzg2l_csi2_read(csi2, reg) | set); in rzg2l_csi2_set()
234 static void rzg2l_csi2_clr(struct rzg2l_csi2 *csi2, unsigned int reg, u32 clr) in rzg2l_csi2_clr() argument
236 rzg2l_csi2_write(csi2, reg, rzg2l_csi2_read(csi2, reg) & ~clr); in rzg2l_csi2_clr()
239 static int rzg2l_csi2_calc_mbps(struct rzg2l_csi2 *csi2) in rzg2l_csi2_calc_mbps() argument
241 struct v4l2_subdev *source = csi2->remote_source; in rzg2l_csi2_calc_mbps()
251 dev_err(csi2->dev, "no pixel rate control in subdev %s\n", in rzg2l_csi2_calc_mbps()
256 state = v4l2_subdev_lock_and_get_active_state(&csi2->subdev); in rzg2l_csi2_calc_mbps()
266 do_div(mbps, csi2->lanes * 1000000); in rzg2l_csi2_calc_mbps()
275 static int rzg2l_csi2_dphy_disable(struct rzg2l_csi2 *csi2) in rzg2l_csi2_dphy_disable() argument
280 ret = reset_control_assert(csi2->cmn_rstb); in rzg2l_csi2_dphy_disable()
285 clk_disable_unprepare(csi2->sysclk); in rzg2l_csi2_dphy_disable()
288 rzg2l_csi2_clr(csi2, CSIDPHYCTRL0, CSIDPHYCTRL0_EN_LDO1200); in rzg2l_csi2_dphy_disable()
291 rzg2l_csi2_clr(csi2, CSIDPHYCTRL0, CSIDPHYCTRL0_EN_BGR); in rzg2l_csi2_dphy_disable()
293 csi2->dphy_enabled = false; in rzg2l_csi2_dphy_disable()
298 static int rzg2l_csi2_dphy_enable(struct rzg2l_csi2 *csi2) in rzg2l_csi2_dphy_enable() argument
306 mbps = rzg2l_csi2_calc_mbps(csi2); in rzg2l_csi2_dphy_enable()
310 csi2->hsfreq = mbps; in rzg2l_csi2_dphy_enable()
316 if (csi2->hsfreq <= dphy_timing->max_hsfreq) in rzg2l_csi2_dphy_enable()
330 rzg2l_csi2_write(csi2, CSIDPHYTIM0, dphytim0); in rzg2l_csi2_dphy_enable()
331 rzg2l_csi2_write(csi2, CSIDPHYTIM1, dphytim1); in rzg2l_csi2_dphy_enable()
334 rzg2l_csi2_write(csi2, CSIDPHYSKW0, CSIDPHYSKW0_DEFAULT_SKW); in rzg2l_csi2_dphy_enable()
337 rzg2l_csi2_set(csi2, CSIDPHYCTRL0, CSIDPHYCTRL0_EN_BGR); in rzg2l_csi2_dphy_enable()
343 rzg2l_csi2_set(csi2, CSIDPHYCTRL0, CSIDPHYCTRL0_EN_LDO1200); in rzg2l_csi2_dphy_enable()
349 ret = clk_prepare_enable(csi2->sysclk); in rzg2l_csi2_dphy_enable()
351 rzg2l_csi2_dphy_disable(csi2); in rzg2l_csi2_dphy_enable()
353 csi2->dphy_enabled = true; in rzg2l_csi2_dphy_enable()
360 struct rzg2l_csi2 *csi2 = sd_to_csi2(sd); in rzg2l_csi2_dphy_setting() local
363 return rzg2l_csi2_dphy_enable(csi2); in rzg2l_csi2_dphy_setting()
365 return rzg2l_csi2_dphy_disable(csi2); in rzg2l_csi2_dphy_setting()
368 static int rzg2l_csi2_mipi_link_enable(struct rzg2l_csi2 *csi2) in rzg2l_csi2_mipi_link_enable() argument
370 unsigned long vclk_rate = csi2->vclk_rate / HZ_PER_MHZ; in rzg2l_csi2_mipi_link_enable()
374 rzg2l_csi2_write(csi2, CSI2nMCT0, CSI2nMCT0_VDLN(csi2->lanes)); in rzg2l_csi2_mipi_link_enable()
378 frrskw = DIV_ROUND_UP(frrskw_coeff, csi2->hsfreq); in rzg2l_csi2_mipi_link_enable()
379 frrclk = DIV_ROUND_UP(frrclk_coeff, csi2->hsfreq); in rzg2l_csi2_mipi_link_enable()
380 rzg2l_csi2_write(csi2, CSI2nMCT2, CSI2nMCT2_FRRSKW(frrskw) | in rzg2l_csi2_mipi_link_enable()
390 rzg2l_csi2_write(csi2, CSI2nDTEL, 0xf778ff0f); in rzg2l_csi2_mipi_link_enable()
391 rzg2l_csi2_write(csi2, CSI2nDTEH, 0x00ffff1f); in rzg2l_csi2_mipi_link_enable()
393 clk_disable_unprepare(csi2->vclk); in rzg2l_csi2_mipi_link_enable()
396 rzg2l_csi2_write(csi2, CSI2nMCT3, CSI2nMCT3_RXEN); in rzg2l_csi2_mipi_link_enable()
398 return clk_prepare_enable(csi2->vclk); in rzg2l_csi2_mipi_link_enable()
401 static int rzg2l_csi2_mipi_link_disable(struct rzg2l_csi2 *csi2) in rzg2l_csi2_mipi_link_disable() argument
406 rzg2l_csi2_clr(csi2, CSI2nMCT3, CSI2nMCT3_RXEN); in rzg2l_csi2_mipi_link_disable()
409 rzg2l_csi2_write(csi2, CSI2nRTCT, CSI2nRTCT_VSRST); in rzg2l_csi2_mipi_link_disable()
413 if (!(rzg2l_csi2_read(csi2, CSI2nRTST) & CSI2nRTST_VSRSTS)) in rzg2l_csi2_mipi_link_disable()
419 dev_err(csi2->dev, "Clearing CSI2nRTST.VSRSTS timed out\n"); in rzg2l_csi2_mipi_link_disable()
426 struct rzg2l_csi2 *csi2 = sd_to_csi2(sd); in rzg2l_csi2_mipi_link_setting() local
430 ret = rzg2l_csi2_mipi_link_enable(csi2); in rzg2l_csi2_mipi_link_setting()
432 ret = rzg2l_csi2_mipi_link_disable(csi2); in rzg2l_csi2_mipi_link_setting()
439 struct rzg2l_csi2 *csi2 = sd_to_csi2(sd); in rzg2l_csi2_s_stream() local
444 ret = pm_runtime_resume_and_get(csi2->dev); in rzg2l_csi2_s_stream()
452 ret = reset_control_deassert(csi2->cmn_rstb); in rzg2l_csi2_s_stream()
457 ret = v4l2_subdev_call(csi2->remote_source, video, s_stream, enable); in rzg2l_csi2_s_stream()
472 pm_runtime_put_sync(csi2->dev); in rzg2l_csi2_s_stream()
478 reset_control_assert(csi2->cmn_rstb); in rzg2l_csi2_s_stream()
482 pm_runtime_put_sync(csi2->dev); in rzg2l_csi2_s_stream()
493 struct rzg2l_csi2 *csi2 = sd_to_csi2(sd); in rzg2l_csi2_post_streamoff() local
501 if (csi2->dphy_enabled) in rzg2l_csi2_post_streamoff()
594 struct rzg2l_csi2 *csi2 = sd_to_csi2(sd); in rzg2l_csi2_get_frame_desc() local
597 if (!csi2->remote_source) in rzg2l_csi2_get_frame_desc()
600 remote_pad = media_pad_remote_pad_unique(&csi2->pads[RZG2L_CSI2_SINK]); in rzg2l_csi2_get_frame_desc()
602 dev_err(csi2->dev, "can't get source pad of %s (%ld)\n", in rzg2l_csi2_get_frame_desc()
603 csi2->remote_source->name, PTR_ERR(remote_pad)); in rzg2l_csi2_get_frame_desc()
606 return v4l2_subdev_call(csi2->remote_source, pad, get_frame_desc, in rzg2l_csi2_get_frame_desc()
641 struct rzg2l_csi2 *csi2 = notifier_to_csi2(notifier); in rzg2l_csi2_notify_bound() local
643 csi2->remote_source = subdev; in rzg2l_csi2_notify_bound()
645 dev_dbg(csi2->dev, "Bound subdev: %s pad\n", subdev->name); in rzg2l_csi2_notify_bound()
648 &csi2->subdev.entity, 0, in rzg2l_csi2_notify_bound()
657 struct rzg2l_csi2 *csi2 = notifier_to_csi2(notifier); in rzg2l_csi2_notify_unbind() local
659 csi2->remote_source = NULL; in rzg2l_csi2_notify_unbind()
661 dev_dbg(csi2->dev, "Unbind subdev %s\n", subdev->name); in rzg2l_csi2_notify_unbind()
669 static int rzg2l_csi2_parse_v4l2(struct rzg2l_csi2 *csi2, in rzg2l_csi2_parse_v4l2() argument
676 csi2->lanes = vep->bus.mipi_csi2.num_data_lanes; in rzg2l_csi2_parse_v4l2()
681 static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2) in rzg2l_csi2_parse_dt() argument
691 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi2->dev), 0, 0, 0); in rzg2l_csi2_parse_dt()
693 dev_err(csi2->dev, "Not connected to subdevice\n"); in rzg2l_csi2_parse_dt()
699 dev_err(csi2->dev, "Could not parse v4l2 endpoint\n"); in rzg2l_csi2_parse_dt()
704 ret = rzg2l_csi2_parse_v4l2(csi2, &v4l2_ep); in rzg2l_csi2_parse_dt()
713 v4l2_async_subdev_nf_init(&csi2->notifier, &csi2->subdev); in rzg2l_csi2_parse_dt()
714 csi2->notifier.ops = &rzg2l_csi2_notify_ops; in rzg2l_csi2_parse_dt()
716 asd = v4l2_async_nf_add_fwnode(&csi2->notifier, fwnode, in rzg2l_csi2_parse_dt()
722 ret = v4l2_async_nf_register(&csi2->notifier); in rzg2l_csi2_parse_dt()
724 v4l2_async_nf_cleanup(&csi2->notifier); in rzg2l_csi2_parse_dt()
729 static int rzg2l_validate_csi2_lanes(struct rzg2l_csi2 *csi2) in rzg2l_validate_csi2_lanes() argument
734 if (csi2->lanes != 1 && csi2->lanes != 2 && csi2->lanes != 4) { in rzg2l_validate_csi2_lanes()
735 dev_err(csi2->dev, "Unsupported number of data-lanes: %u\n", in rzg2l_validate_csi2_lanes()
736 csi2->lanes); in rzg2l_validate_csi2_lanes()
740 ret = pm_runtime_resume_and_get(csi2->dev); in rzg2l_validate_csi2_lanes()
745 lanes = (rzg2l_csi2_read(csi2, CSI2nMCG) & CSI2nMCG_SDLN) >> 8; in rzg2l_validate_csi2_lanes()
746 if (lanes < csi2->lanes) { in rzg2l_validate_csi2_lanes()
747 dev_err(csi2->dev, in rzg2l_validate_csi2_lanes()
748 "Failed to support %d data lanes\n", csi2->lanes); in rzg2l_validate_csi2_lanes()
752 pm_runtime_put_sync(csi2->dev); in rzg2l_validate_csi2_lanes()
767 struct rzg2l_csi2 *csi2; in rzg2l_csi2_probe() local
770 csi2 = devm_kzalloc(&pdev->dev, sizeof(*csi2), GFP_KERNEL); in rzg2l_csi2_probe()
771 if (!csi2) in rzg2l_csi2_probe()
774 csi2->base = devm_platform_ioremap_resource(pdev, 0); in rzg2l_csi2_probe()
775 if (IS_ERR(csi2->base)) in rzg2l_csi2_probe()
776 return PTR_ERR(csi2->base); in rzg2l_csi2_probe()
778 csi2->cmn_rstb = devm_reset_control_get_exclusive(&pdev->dev, "cmn-rstb"); in rzg2l_csi2_probe()
779 if (IS_ERR(csi2->cmn_rstb)) in rzg2l_csi2_probe()
780 return dev_err_probe(&pdev->dev, PTR_ERR(csi2->cmn_rstb), in rzg2l_csi2_probe()
783 csi2->presetn = devm_reset_control_get_shared(&pdev->dev, "presetn"); in rzg2l_csi2_probe()
784 if (IS_ERR(csi2->presetn)) in rzg2l_csi2_probe()
785 return dev_err_probe(&pdev->dev, PTR_ERR(csi2->presetn), in rzg2l_csi2_probe()
788 csi2->sysclk = devm_clk_get(&pdev->dev, "system"); in rzg2l_csi2_probe()
789 if (IS_ERR(csi2->sysclk)) in rzg2l_csi2_probe()
790 return dev_err_probe(&pdev->dev, PTR_ERR(csi2->sysclk), in rzg2l_csi2_probe()
793 csi2->vclk = devm_clk_get(&pdev->dev, "video"); in rzg2l_csi2_probe()
794 if (IS_ERR(csi2->vclk)) in rzg2l_csi2_probe()
795 return dev_err_probe(&pdev->dev, PTR_ERR(csi2->vclk), in rzg2l_csi2_probe()
797 csi2->vclk_rate = clk_get_rate(csi2->vclk); in rzg2l_csi2_probe()
799 csi2->dev = &pdev->dev; in rzg2l_csi2_probe()
801 platform_set_drvdata(pdev, csi2); in rzg2l_csi2_probe()
803 ret = rzg2l_csi2_parse_dt(csi2); in rzg2l_csi2_probe()
809 ret = rzg2l_validate_csi2_lanes(csi2); in rzg2l_csi2_probe()
813 csi2->subdev.dev = &pdev->dev; in rzg2l_csi2_probe()
814 v4l2_subdev_init(&csi2->subdev, &rzg2l_csi2_subdev_ops); in rzg2l_csi2_probe()
815 csi2->subdev.internal_ops = &rzg2l_csi2_internal_ops; in rzg2l_csi2_probe()
816 v4l2_set_subdevdata(&csi2->subdev, &pdev->dev); in rzg2l_csi2_probe()
817 snprintf(csi2->subdev.name, sizeof(csi2->subdev.name), in rzg2l_csi2_probe()
819 csi2->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; in rzg2l_csi2_probe()
821 csi2->subdev.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; in rzg2l_csi2_probe()
822 csi2->subdev.entity.ops = &rzg2l_csi2_entity_ops; in rzg2l_csi2_probe()
824 csi2->pads[RZG2L_CSI2_SINK].flags = MEDIA_PAD_FL_SINK | in rzg2l_csi2_probe()
827 * TODO: RZ/G2L CSI2 supports 4 virtual channels, as virtual in rzg2l_csi2_probe()
831 csi2->pads[RZG2L_CSI2_SOURCE].flags = MEDIA_PAD_FL_SOURCE | in rzg2l_csi2_probe()
833 ret = media_entity_pads_init(&csi2->subdev.entity, ARRAY_SIZE(csi2->pads), in rzg2l_csi2_probe()
834 csi2->pads); in rzg2l_csi2_probe()
838 ret = v4l2_subdev_init_finalize(&csi2->subdev); in rzg2l_csi2_probe()
842 ret = v4l2_async_register_subdev(&csi2->subdev); in rzg2l_csi2_probe()
849 v4l2_subdev_cleanup(&csi2->subdev); in rzg2l_csi2_probe()
851 v4l2_async_nf_unregister(&csi2->notifier); in rzg2l_csi2_probe()
852 v4l2_async_nf_cleanup(&csi2->notifier); in rzg2l_csi2_probe()
853 media_entity_cleanup(&csi2->subdev.entity); in rzg2l_csi2_probe()
862 struct rzg2l_csi2 *csi2 = platform_get_drvdata(pdev); in rzg2l_csi2_remove() local
864 v4l2_async_nf_unregister(&csi2->notifier); in rzg2l_csi2_remove()
865 v4l2_async_nf_cleanup(&csi2->notifier); in rzg2l_csi2_remove()
866 v4l2_async_unregister_subdev(&csi2->subdev); in rzg2l_csi2_remove()
867 v4l2_subdev_cleanup(&csi2->subdev); in rzg2l_csi2_remove()
868 media_entity_cleanup(&csi2->subdev.entity); in rzg2l_csi2_remove()
874 struct rzg2l_csi2 *csi2 = dev_get_drvdata(dev); in rzg2l_csi2_pm_runtime_suspend() local
876 reset_control_assert(csi2->presetn); in rzg2l_csi2_pm_runtime_suspend()
883 struct rzg2l_csi2 *csi2 = dev_get_drvdata(dev); in rzg2l_csi2_pm_runtime_resume() local
885 return reset_control_deassert(csi2->presetn); in rzg2l_csi2_pm_runtime_resume()
894 { .compatible = "renesas,rzg2l-csi2", },
903 .name = "rzg2l-csi2",
912 MODULE_DESCRIPTION("Renesas RZ/G2L MIPI CSI2 receiver driver");