Lines Matching full:csi2

215 static u32 rzg2l_csi2_read(struct rzg2l_csi2 *csi2, unsigned int reg)  in rzg2l_csi2_read()  argument
217 return ioread32(csi2->base + reg); in rzg2l_csi2_read()
220 static void rzg2l_csi2_write(struct rzg2l_csi2 *csi2, unsigned int reg, in rzg2l_csi2_write() argument
223 iowrite32(data, csi2->base + reg); in rzg2l_csi2_write()
226 static void rzg2l_csi2_set(struct rzg2l_csi2 *csi2, unsigned int reg, u32 set) in rzg2l_csi2_set() argument
228 rzg2l_csi2_write(csi2, reg, rzg2l_csi2_read(csi2, reg) | set); in rzg2l_csi2_set()
231 static void rzg2l_csi2_clr(struct rzg2l_csi2 *csi2, unsigned int reg, u32 clr) in rzg2l_csi2_clr() argument
233 rzg2l_csi2_write(csi2, reg, rzg2l_csi2_read(csi2, reg) & ~clr); in rzg2l_csi2_clr()
236 static int rzg2l_csi2_calc_mbps(struct rzg2l_csi2 *csi2) in rzg2l_csi2_calc_mbps() argument
238 struct v4l2_subdev *source = csi2->remote_source; in rzg2l_csi2_calc_mbps()
248 dev_err(csi2->dev, "no pixel rate control in subdev %s\n", in rzg2l_csi2_calc_mbps()
253 state = v4l2_subdev_lock_and_get_active_state(&csi2->subdev); in rzg2l_csi2_calc_mbps()
263 do_div(mbps, csi2->lanes * 1000000); in rzg2l_csi2_calc_mbps()
272 static int rzg2l_csi2_dphy_disable(struct rzg2l_csi2 *csi2) in rzg2l_csi2_dphy_disable() argument
277 ret = reset_control_assert(csi2->cmn_rstb); in rzg2l_csi2_dphy_disable()
282 clk_disable_unprepare(csi2->sysclk); in rzg2l_csi2_dphy_disable()
285 rzg2l_csi2_clr(csi2, CSIDPHYCTRL0, CSIDPHYCTRL0_EN_LDO1200); in rzg2l_csi2_dphy_disable()
288 rzg2l_csi2_clr(csi2, CSIDPHYCTRL0, CSIDPHYCTRL0_EN_BGR); in rzg2l_csi2_dphy_disable()
290 csi2->dphy_enabled = false; in rzg2l_csi2_dphy_disable()
295 static int rzg2l_csi2_dphy_enable(struct rzg2l_csi2 *csi2) in rzg2l_csi2_dphy_enable() argument
303 mbps = rzg2l_csi2_calc_mbps(csi2); in rzg2l_csi2_dphy_enable()
307 csi2->hsfreq = mbps; in rzg2l_csi2_dphy_enable()
313 if (csi2->hsfreq <= dphy_timing->max_hsfreq) in rzg2l_csi2_dphy_enable()
327 rzg2l_csi2_write(csi2, CSIDPHYTIM0, dphytim0); in rzg2l_csi2_dphy_enable()
328 rzg2l_csi2_write(csi2, CSIDPHYTIM1, dphytim1); in rzg2l_csi2_dphy_enable()
331 rzg2l_csi2_write(csi2, CSIDPHYSKW0, CSIDPHYSKW0_DEFAULT_SKW); in rzg2l_csi2_dphy_enable()
334 rzg2l_csi2_set(csi2, CSIDPHYCTRL0, CSIDPHYCTRL0_EN_BGR); in rzg2l_csi2_dphy_enable()
340 rzg2l_csi2_set(csi2, CSIDPHYCTRL0, CSIDPHYCTRL0_EN_LDO1200); in rzg2l_csi2_dphy_enable()
346 ret = clk_prepare_enable(csi2->sysclk); in rzg2l_csi2_dphy_enable()
348 rzg2l_csi2_dphy_disable(csi2); in rzg2l_csi2_dphy_enable()
350 csi2->dphy_enabled = true; in rzg2l_csi2_dphy_enable()
357 struct rzg2l_csi2 *csi2 = sd_to_csi2(sd); in rzg2l_csi2_dphy_setting() local
360 return rzg2l_csi2_dphy_enable(csi2); in rzg2l_csi2_dphy_setting()
362 return rzg2l_csi2_dphy_disable(csi2); in rzg2l_csi2_dphy_setting()
365 static int rzg2l_csi2_mipi_link_enable(struct rzg2l_csi2 *csi2) in rzg2l_csi2_mipi_link_enable() argument
367 unsigned long vclk_rate = csi2->vclk_rate / HZ_PER_MHZ; in rzg2l_csi2_mipi_link_enable()
371 rzg2l_csi2_write(csi2, CSI2nMCT0, CSI2nMCT0_VDLN(csi2->lanes)); in rzg2l_csi2_mipi_link_enable()
375 frrskw = DIV_ROUND_UP(frrskw_coeff, csi2->hsfreq); in rzg2l_csi2_mipi_link_enable()
376 frrclk = DIV_ROUND_UP(frrclk_coeff, csi2->hsfreq); in rzg2l_csi2_mipi_link_enable()
377 rzg2l_csi2_write(csi2, CSI2nMCT2, CSI2nMCT2_FRRSKW(frrskw) | in rzg2l_csi2_mipi_link_enable()
387 rzg2l_csi2_write(csi2, CSI2nDTEL, 0xf778ff0f); in rzg2l_csi2_mipi_link_enable()
388 rzg2l_csi2_write(csi2, CSI2nDTEH, 0x00ffff1f); in rzg2l_csi2_mipi_link_enable()
390 clk_disable_unprepare(csi2->vclk); in rzg2l_csi2_mipi_link_enable()
393 rzg2l_csi2_write(csi2, CSI2nMCT3, CSI2nMCT3_RXEN); in rzg2l_csi2_mipi_link_enable()
395 return clk_prepare_enable(csi2->vclk); in rzg2l_csi2_mipi_link_enable()
398 static int rzg2l_csi2_mipi_link_disable(struct rzg2l_csi2 *csi2) in rzg2l_csi2_mipi_link_disable() argument
403 rzg2l_csi2_clr(csi2, CSI2nMCT3, CSI2nMCT3_RXEN); in rzg2l_csi2_mipi_link_disable()
406 rzg2l_csi2_write(csi2, CSI2nRTCT, CSI2nRTCT_VSRST); in rzg2l_csi2_mipi_link_disable()
410 if (!(rzg2l_csi2_read(csi2, CSI2nRTST) & CSI2nRTST_VSRSTS)) in rzg2l_csi2_mipi_link_disable()
416 dev_err(csi2->dev, "Clearing CSI2nRTST.VSRSTS timed out\n"); in rzg2l_csi2_mipi_link_disable()
423 struct rzg2l_csi2 *csi2 = sd_to_csi2(sd); in rzg2l_csi2_mipi_link_setting() local
427 ret = rzg2l_csi2_mipi_link_enable(csi2); in rzg2l_csi2_mipi_link_setting()
429 ret = rzg2l_csi2_mipi_link_disable(csi2); in rzg2l_csi2_mipi_link_setting()
436 struct rzg2l_csi2 *csi2 = sd_to_csi2(sd); in rzg2l_csi2_s_stream() local
441 ret = pm_runtime_resume_and_get(csi2->dev); in rzg2l_csi2_s_stream()
449 ret = reset_control_deassert(csi2->cmn_rstb); in rzg2l_csi2_s_stream()
454 ret = v4l2_subdev_call(csi2->remote_source, video, s_stream, enable); in rzg2l_csi2_s_stream()
469 pm_runtime_put_sync(csi2->dev); in rzg2l_csi2_s_stream()
475 reset_control_assert(csi2->cmn_rstb); in rzg2l_csi2_s_stream()
479 pm_runtime_put_sync(csi2->dev); in rzg2l_csi2_s_stream()
490 struct rzg2l_csi2 *csi2 = sd_to_csi2(sd); in rzg2l_csi2_post_streamoff() local
498 if (csi2->dphy_enabled) in rzg2l_csi2_post_streamoff()
615 struct rzg2l_csi2 *csi2 = notifier_to_csi2(notifier); in rzg2l_csi2_notify_bound() local
617 csi2->remote_source = subdev; in rzg2l_csi2_notify_bound()
619 dev_dbg(csi2->dev, "Bound subdev: %s pad\n", subdev->name); in rzg2l_csi2_notify_bound()
622 &csi2->subdev.entity, 0, in rzg2l_csi2_notify_bound()
631 struct rzg2l_csi2 *csi2 = notifier_to_csi2(notifier); in rzg2l_csi2_notify_unbind() local
633 csi2->remote_source = NULL; in rzg2l_csi2_notify_unbind()
635 dev_dbg(csi2->dev, "Unbind subdev %s\n", subdev->name); in rzg2l_csi2_notify_unbind()
643 static int rzg2l_csi2_parse_v4l2(struct rzg2l_csi2 *csi2, in rzg2l_csi2_parse_v4l2() argument
650 csi2->lanes = vep->bus.mipi_csi2.num_data_lanes; in rzg2l_csi2_parse_v4l2()
655 static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2) in rzg2l_csi2_parse_dt() argument
665 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi2->dev), 0, 0, 0); in rzg2l_csi2_parse_dt()
667 dev_err(csi2->dev, "Not connected to subdevice\n"); in rzg2l_csi2_parse_dt()
673 dev_err(csi2->dev, "Could not parse v4l2 endpoint\n"); in rzg2l_csi2_parse_dt()
678 ret = rzg2l_csi2_parse_v4l2(csi2, &v4l2_ep); in rzg2l_csi2_parse_dt()
687 v4l2_async_subdev_nf_init(&csi2->notifier, &csi2->subdev); in rzg2l_csi2_parse_dt()
688 csi2->notifier.ops = &rzg2l_csi2_notify_ops; in rzg2l_csi2_parse_dt()
690 asd = v4l2_async_nf_add_fwnode(&csi2->notifier, fwnode, in rzg2l_csi2_parse_dt()
696 ret = v4l2_async_nf_register(&csi2->notifier); in rzg2l_csi2_parse_dt()
698 v4l2_async_nf_cleanup(&csi2->notifier); in rzg2l_csi2_parse_dt()
703 static int rzg2l_validate_csi2_lanes(struct rzg2l_csi2 *csi2) in rzg2l_validate_csi2_lanes() argument
708 if (csi2->lanes != 1 && csi2->lanes != 2 && csi2->lanes != 4) { in rzg2l_validate_csi2_lanes()
709 dev_err(csi2->dev, "Unsupported number of data-lanes: %u\n", in rzg2l_validate_csi2_lanes()
710 csi2->lanes); in rzg2l_validate_csi2_lanes()
714 ret = pm_runtime_resume_and_get(csi2->dev); in rzg2l_validate_csi2_lanes()
719 lanes = (rzg2l_csi2_read(csi2, CSI2nMCG) & CSI2nMCG_SDLN) >> 8; in rzg2l_validate_csi2_lanes()
720 if (lanes < csi2->lanes) { in rzg2l_validate_csi2_lanes()
721 dev_err(csi2->dev, in rzg2l_validate_csi2_lanes()
722 "Failed to support %d data lanes\n", csi2->lanes); in rzg2l_validate_csi2_lanes()
726 pm_runtime_put_sync(csi2->dev); in rzg2l_validate_csi2_lanes()
741 struct rzg2l_csi2 *csi2; in rzg2l_csi2_probe() local
744 csi2 = devm_kzalloc(&pdev->dev, sizeof(*csi2), GFP_KERNEL); in rzg2l_csi2_probe()
745 if (!csi2) in rzg2l_csi2_probe()
748 csi2->base = devm_platform_ioremap_resource(pdev, 0); in rzg2l_csi2_probe()
749 if (IS_ERR(csi2->base)) in rzg2l_csi2_probe()
750 return PTR_ERR(csi2->base); in rzg2l_csi2_probe()
752 csi2->cmn_rstb = devm_reset_control_get_exclusive(&pdev->dev, "cmn-rstb"); in rzg2l_csi2_probe()
753 if (IS_ERR(csi2->cmn_rstb)) in rzg2l_csi2_probe()
754 return dev_err_probe(&pdev->dev, PTR_ERR(csi2->cmn_rstb), in rzg2l_csi2_probe()
757 csi2->presetn = devm_reset_control_get_shared(&pdev->dev, "presetn"); in rzg2l_csi2_probe()
758 if (IS_ERR(csi2->presetn)) in rzg2l_csi2_probe()
759 return dev_err_probe(&pdev->dev, PTR_ERR(csi2->presetn), in rzg2l_csi2_probe()
762 csi2->sysclk = devm_clk_get(&pdev->dev, "system"); in rzg2l_csi2_probe()
763 if (IS_ERR(csi2->sysclk)) in rzg2l_csi2_probe()
764 return dev_err_probe(&pdev->dev, PTR_ERR(csi2->sysclk), in rzg2l_csi2_probe()
767 csi2->vclk = devm_clk_get(&pdev->dev, "video"); in rzg2l_csi2_probe()
768 if (IS_ERR(csi2->vclk)) in rzg2l_csi2_probe()
769 return dev_err_probe(&pdev->dev, PTR_ERR(csi2->vclk), in rzg2l_csi2_probe()
771 csi2->vclk_rate = clk_get_rate(csi2->vclk); in rzg2l_csi2_probe()
773 csi2->dev = &pdev->dev; in rzg2l_csi2_probe()
775 platform_set_drvdata(pdev, csi2); in rzg2l_csi2_probe()
777 ret = rzg2l_csi2_parse_dt(csi2); in rzg2l_csi2_probe()
783 ret = rzg2l_validate_csi2_lanes(csi2); in rzg2l_csi2_probe()
787 csi2->subdev.dev = &pdev->dev; in rzg2l_csi2_probe()
788 v4l2_subdev_init(&csi2->subdev, &rzg2l_csi2_subdev_ops); in rzg2l_csi2_probe()
789 csi2->subdev.internal_ops = &rzg2l_csi2_internal_ops; in rzg2l_csi2_probe()
790 v4l2_set_subdevdata(&csi2->subdev, &pdev->dev); in rzg2l_csi2_probe()
791 snprintf(csi2->subdev.name, sizeof(csi2->subdev.name), in rzg2l_csi2_probe()
793 csi2->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; in rzg2l_csi2_probe()
795 csi2->subdev.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; in rzg2l_csi2_probe()
796 csi2->subdev.entity.ops = &rzg2l_csi2_entity_ops; in rzg2l_csi2_probe()
798 csi2->pads[RZG2L_CSI2_SINK].flags = MEDIA_PAD_FL_SINK; in rzg2l_csi2_probe()
800 * TODO: RZ/G2L CSI2 supports 4 virtual channels, as virtual in rzg2l_csi2_probe()
804 csi2->pads[RZG2L_CSI2_SOURCE].flags = MEDIA_PAD_FL_SOURCE; in rzg2l_csi2_probe()
805 ret = media_entity_pads_init(&csi2->subdev.entity, 2, csi2->pads); in rzg2l_csi2_probe()
809 ret = v4l2_subdev_init_finalize(&csi2->subdev); in rzg2l_csi2_probe()
813 ret = v4l2_async_register_subdev(&csi2->subdev); in rzg2l_csi2_probe()
820 v4l2_subdev_cleanup(&csi2->subdev); in rzg2l_csi2_probe()
822 v4l2_async_nf_unregister(&csi2->notifier); in rzg2l_csi2_probe()
823 v4l2_async_nf_cleanup(&csi2->notifier); in rzg2l_csi2_probe()
824 media_entity_cleanup(&csi2->subdev.entity); in rzg2l_csi2_probe()
833 struct rzg2l_csi2 *csi2 = platform_get_drvdata(pdev); in rzg2l_csi2_remove() local
835 v4l2_async_nf_unregister(&csi2->notifier); in rzg2l_csi2_remove()
836 v4l2_async_nf_cleanup(&csi2->notifier); in rzg2l_csi2_remove()
837 v4l2_async_unregister_subdev(&csi2->subdev); in rzg2l_csi2_remove()
838 v4l2_subdev_cleanup(&csi2->subdev); in rzg2l_csi2_remove()
839 media_entity_cleanup(&csi2->subdev.entity); in rzg2l_csi2_remove()
845 struct rzg2l_csi2 *csi2 = dev_get_drvdata(dev); in rzg2l_csi2_pm_runtime_suspend() local
847 reset_control_assert(csi2->presetn); in rzg2l_csi2_pm_runtime_suspend()
854 struct rzg2l_csi2 *csi2 = dev_get_drvdata(dev); in rzg2l_csi2_pm_runtime_resume() local
856 return reset_control_deassert(csi2->presetn); in rzg2l_csi2_pm_runtime_resume()
865 { .compatible = "renesas,rzg2l-csi2", },
874 .name = "rzg2l-csi2",
883 MODULE_DESCRIPTION("Renesas RZ/G2L MIPI CSI2 receiver driver");