Lines Matching refs:csidev
358 static int stm32_csi_setup_lane_merger(struct stm32_csi_dev *csidev) in stm32_csi_setup_lane_merger() argument
363 for (i = 0; i < csidev->num_lanes; i++) { in stm32_csi_setup_lane_merger()
364 if (!csidev->lanes[i] || csidev->lanes[i] > STM32_CSI_LANES_MAX) { in stm32_csi_setup_lane_merger()
365 dev_err(csidev->dev, "Invalid lane id (%d)\n", csidev->lanes[i]); in stm32_csi_setup_lane_merger()
368 lmcfgr |= (csidev->lanes[i] << ((i * 4) + STM32_CSI_LMCFGR_DLMAP_SHIFT)); in stm32_csi_setup_lane_merger()
371 lmcfgr |= (csidev->num_lanes << STM32_CSI_LMCFGR_LANENB_SHIFT); in stm32_csi_setup_lane_merger()
373 writel_relaxed(lmcfgr, csidev->base + STM32_CSI_LMCFGR); in stm32_csi_setup_lane_merger()
378 static void stm32_csi_phy_reg_write(struct stm32_csi_dev *csidev, in stm32_csi_phy_reg_write() argument
384 writel_relaxed(STM32_CSI_PTCR1_TWM, csidev->base + STM32_CSI_PTCR1); in stm32_csi_phy_reg_write()
387 writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0); in stm32_csi_phy_reg_write()
390 writel_relaxed(STM32_CSI_PTCR1_TWM, csidev->base + STM32_CSI_PTCR1); in stm32_csi_phy_reg_write()
396 writel_relaxed(0, csidev->base + STM32_CSI_PTCR0); in stm32_csi_phy_reg_write()
399 writel_relaxed(0, csidev->base + STM32_CSI_PTCR1); in stm32_csi_phy_reg_write()
403 csidev->base + STM32_CSI_PTCR1); in stm32_csi_phy_reg_write()
406 writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0); in stm32_csi_phy_reg_write()
410 writel_relaxed(0, csidev->base + STM32_CSI_PTCR0); in stm32_csi_phy_reg_write()
413 writel_relaxed(STM32_CSI_PTCR1_TWM, csidev->base + STM32_CSI_PTCR1); in stm32_csi_phy_reg_write()
416 writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0); in stm32_csi_phy_reg_write()
421 csidev->base + STM32_CSI_PTCR1); in stm32_csi_phy_reg_write()
427 writel_relaxed(0, csidev->base + STM32_CSI_PTCR0); in stm32_csi_phy_reg_write()
430 writel_relaxed(0, csidev->base + STM32_CSI_PTCR1); in stm32_csi_phy_reg_write()
435 csidev->base + STM32_CSI_PTCR1); in stm32_csi_phy_reg_write()
438 writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0); in stm32_csi_phy_reg_write()
441 writel_relaxed(0, csidev->base + STM32_CSI_PTCR0); in stm32_csi_phy_reg_write()
444 static int stm32_csi_start(struct stm32_csi_dev *csidev, in stm32_csi_start() argument
458 dev_dbg(csidev->dev, "Starting the CSI2\n"); in stm32_csi_start()
465 if (!csidev->s_subdev) in stm32_csi_start()
468 link_freq = v4l2_get_link_freq(csidev->s_subdev->ctrl_handler, in stm32_csi_start()
469 fmt->bpp, 2 * csidev->num_lanes); in stm32_csi_start()
475 dev_dbg(csidev->dev, "Computed Mbps: %u\n", mbps); in stm32_csi_start()
482 dev_err(csidev->dev, "Unsupported PHY speed (%u Mbps)", mbps); in stm32_csi_start()
486 dev_dbg(csidev->dev, "PHY settings: (%u Mbps, %u HS FRange, %u OSC Freq)\n", in stm32_csi_start()
493 if (csidev->num_lanes == 2) { in stm32_csi_start()
498 ret = pm_runtime_get_sync(csidev->dev); in stm32_csi_start()
503 phy_clk_frate = clk_get_rate(csidev->clks[STM32_CSI_CLK_CSI2PHY].clk); in stm32_csi_start()
505 pm_runtime_put(csidev->dev); in stm32_csi_start()
506 dev_err(csidev->dev, "CSI2PHY clock rate invalid (0)\n"); in stm32_csi_start()
510 ret = stm32_csi_setup_lane_merger(csidev); in stm32_csi_start()
512 pm_runtime_put(csidev->dev); in stm32_csi_start()
517 writel_relaxed(STM32_CSI_CR_CSIEN, csidev->base + STM32_CSI_CR); in stm32_csi_start()
520 writel_relaxed(STM32_CSI_SR0_ERRORS, csidev->base + STM32_CSI_IER0); in stm32_csi_start()
523 writel_relaxed(lanes_ie, csidev->base + STM32_CSI_IER1); in stm32_csi_start()
527 writel_relaxed(0, csidev->base + STM32_CSI_PRCR); in stm32_csi_start()
530 writel_relaxed(0, csidev->base + STM32_CSI_PCR); in stm32_csi_start()
533 writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0); in stm32_csi_start()
535 writel_relaxed(0, csidev->base + STM32_CSI_PTCR0); in stm32_csi_start()
542 csidev->base + STM32_CSI_PFCR); in stm32_csi_start()
545 stm32_csi_phy_reg_write(csidev, 0x08, 0x38); in stm32_csi_start()
549 stm32_csi_phy_reg_write(csidev, 0xe4, 0x11); in stm32_csi_start()
553 stm32_csi_phy_reg_write(csidev, 0xe2, phy_regs->osc_freq_target & 0xFF); in stm32_csi_start()
554 stm32_csi_phy_reg_write(csidev, 0xe3, (phy_regs->osc_freq_target >> 8) & 0x0F); in stm32_csi_start()
556 writel_relaxed(STM32_CSI_PFCR_DLD | readl_relaxed(csidev->base + STM32_CSI_PFCR), in stm32_csi_start()
557 csidev->base + STM32_CSI_PFCR); in stm32_csi_start()
560 writel_relaxed(lanes_en | STM32_CSI_PCR_CLEN, csidev->base + STM32_CSI_PCR); in stm32_csi_start()
562 csidev->base + STM32_CSI_PCR); in stm32_csi_start()
564 writel_relaxed(STM32_CSI_PRCR_PEN, csidev->base + STM32_CSI_PRCR); in stm32_csi_start()
567 writel_relaxed(0, csidev->base + STM32_CSI_PMCR); in stm32_csi_start()
572 static void stm32_csi_stop(struct stm32_csi_dev *csidev) in stm32_csi_stop() argument
574 dev_dbg(csidev->dev, "Stopping the CSI2\n"); in stm32_csi_stop()
577 writel_relaxed(0, csidev->base + STM32_CSI_PCR); in stm32_csi_stop()
580 writel_relaxed(0, csidev->base + STM32_CSI_IER0); in stm32_csi_stop()
581 writel_relaxed(0, csidev->base + STM32_CSI_IER1); in stm32_csi_stop()
584 writel_relaxed(0, csidev->base + STM32_CSI_CR); in stm32_csi_stop()
586 pm_runtime_put(csidev->dev); in stm32_csi_stop()
589 static int stm32_csi_start_vc(struct stm32_csi_dev *csidev, in stm32_csi_start_vc() argument
605 dev_dbg(csidev->dev, "VC%d: enable AllDT mode\n", vc); in stm32_csi_start_vc()
610 dev_dbg(csidev->dev, "VC%d: enable DT0(0x%x)/DT0FT(0x%x)\n", in stm32_csi_start_vc()
613 writel_relaxed(cfgr1, csidev->base + STM32_CSI_VCXCFGR1(vc)); in stm32_csi_start_vc()
617 csidev->base + STM32_CSI_CR); in stm32_csi_start_vc()
619 ret = readl_relaxed_poll_timeout(csidev->base + STM32_CSI_SR0, in stm32_csi_start_vc()
624 dev_err(csidev->dev, "failed to start VC(%d)\n", vc); in stm32_csi_start_vc()
631 static int stm32_csi_stop_vc(struct stm32_csi_dev *csidev, u32 vc) in stm32_csi_stop_vc() argument
638 csidev->base + STM32_CSI_CR); in stm32_csi_stop_vc()
640 ret = readl_relaxed_poll_timeout(csidev->base + STM32_CSI_SR0, in stm32_csi_stop_vc()
645 dev_err(csidev->dev, "failed to stop VC(%d)\n", vc); in stm32_csi_stop_vc()
650 writel_relaxed(0, csidev->base + STM32_CSI_VCXCFGR1(vc)); in stm32_csi_stop_vc()
651 writel_relaxed(0, csidev->base + STM32_CSI_VCXCFGR2(vc)); in stm32_csi_stop_vc()
660 struct stm32_csi_dev *csidev = to_csidev(sd); in stm32_csi_disable_streams() local
663 ret = v4l2_subdev_disable_streams(csidev->s_subdev, in stm32_csi_disable_streams()
664 csidev->s_subdev_pad_nb, BIT_ULL(0)); in stm32_csi_disable_streams()
669 ret = stm32_csi_stop_vc(csidev, 0); in stm32_csi_disable_streams()
671 dev_err(csidev->dev, "Failed to stop VC0\n"); in stm32_csi_disable_streams()
673 stm32_csi_stop(csidev); in stm32_csi_disable_streams()
682 struct stm32_csi_dev *csidev = to_csidev(sd); in stm32_csi_enable_streams() local
685 ret = stm32_csi_start(csidev, state); in stm32_csi_enable_streams()
690 ret = stm32_csi_start_vc(csidev, state, 0); in stm32_csi_enable_streams()
692 dev_err(csidev->dev, "Failed to start VC0\n"); in stm32_csi_enable_streams()
693 stm32_csi_stop(csidev); in stm32_csi_enable_streams()
697 ret = v4l2_subdev_enable_streams(csidev->s_subdev, in stm32_csi_enable_streams()
698 csidev->s_subdev_pad_nb, BIT_ULL(0)); in stm32_csi_enable_streams()
700 stm32_csi_stop_vc(csidev, 0); in stm32_csi_enable_streams()
701 stm32_csi_stop(csidev); in stm32_csi_enable_streams()
734 struct stm32_csi_dev *csidev = to_csidev(sd); in stm32_csi_set_pad_format() local
740 dev_dbg(csidev->dev, "Unsupported code %d, use default\n", in stm32_csi_set_pad_format()
760 struct stm32_csi_dev *csidev = to_csidev(sd); in stm32_csi_log_status() local
764 spin_lock_irqsave(&csidev->slock, flags); in stm32_csi_log_status()
767 if (csidev->sr0_counters[i]) in stm32_csi_log_status()
768 dev_info(csidev->dev, "%s events: %d\n", in stm32_csi_log_status()
770 csidev->sr0_counters[i]); in stm32_csi_log_status()
774 if (csidev->sr1_counters[i]) in stm32_csi_log_status()
775 dev_info(csidev->dev, "%s events: %d\n", in stm32_csi_log_status()
777 csidev->sr1_counters[i]); in stm32_csi_log_status()
780 spin_unlock_irqrestore(&csidev->slock, flags); in stm32_csi_log_status()
816 struct stm32_csi_dev *csidev = to_csidev(sd); in stm32_csi_async_bound() local
823 dev_err(csidev->dev, "Couldn't find output pad for subdev %s\n", in stm32_csi_async_bound()
828 csidev->s_subdev = s_subdev; in stm32_csi_async_bound()
829 csidev->s_subdev_pad_nb = remote_pad; in stm32_csi_async_bound()
831 return media_create_pad_link(&csidev->s_subdev->entity, in stm32_csi_async_bound()
832 remote_pad, &csidev->sd.entity, in stm32_csi_async_bound()
844 struct stm32_csi_dev *csidev = arg; in stm32_csi_irq_thread() local
849 sr0 = readl_relaxed(csidev->base + STM32_CSI_SR0); in stm32_csi_irq_thread()
850 sr1 = readl_relaxed(csidev->base + STM32_CSI_SR1); in stm32_csi_irq_thread()
854 csidev->base + STM32_CSI_FCR0); in stm32_csi_irq_thread()
856 csidev->base + STM32_CSI_FCR1); in stm32_csi_irq_thread()
858 spin_lock_irqsave(&csidev->slock, flags); in stm32_csi_irq_thread()
862 csidev->sr0_counters[i]++; in stm32_csi_irq_thread()
866 csidev->sr1_counters[i]++; in stm32_csi_irq_thread()
868 spin_unlock_irqrestore(&csidev->slock, flags); in stm32_csi_irq_thread()
873 static int stm32_csi_get_resources(struct stm32_csi_dev *csidev, in stm32_csi_get_resources() argument
878 csidev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); in stm32_csi_get_resources()
879 if (IS_ERR(csidev->base)) in stm32_csi_get_resources()
880 return dev_err_probe(&pdev->dev, PTR_ERR(csidev->base), in stm32_csi_get_resources()
884 csidev->clks[i].id = stm32_csi_clks_id[i]; in stm32_csi_get_resources()
887 csidev->clks); in stm32_csi_get_resources()
891 csidev->supplies[0].supply = "vdd"; in stm32_csi_get_resources()
892 csidev->supplies[1].supply = "vdda18"; in stm32_csi_get_resources()
893 ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(csidev->supplies), in stm32_csi_get_resources()
894 csidev->supplies); in stm32_csi_get_resources()
905 dev_name(&pdev->dev), csidev); in stm32_csi_get_resources()
913 static int stm32_csi_parse_dt(struct stm32_csi_dev *csidev) in stm32_csi_parse_dt() argument
921 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csidev->dev), 0, 0, in stm32_csi_parse_dt()
924 dev_err(csidev->dev, "Could not find the endpoint\n"); in stm32_csi_parse_dt()
931 dev_err(csidev->dev, "Could not parse v4l2 endpoint\n"); in stm32_csi_parse_dt()
935 csidev->num_lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes; in stm32_csi_parse_dt()
936 if (csidev->num_lanes > STM32_CSI_LANES_MAX) { in stm32_csi_parse_dt()
937 dev_err(csidev->dev, "Unsupported number of data-lanes: %d\n", in stm32_csi_parse_dt()
938 csidev->num_lanes); in stm32_csi_parse_dt()
942 memcpy(csidev->lanes, v4l2_ep.bus.mipi_csi2.data_lanes, in stm32_csi_parse_dt()
943 sizeof(csidev->lanes)); in stm32_csi_parse_dt()
945 ep = fwnode_graph_get_next_endpoint(dev_fwnode(csidev->dev), NULL); in stm32_csi_parse_dt()
947 dev_err(csidev->dev, "Failed to get next endpoint\n"); in stm32_csi_parse_dt()
951 v4l2_async_subdev_nf_init(&csidev->notifier, &csidev->sd); in stm32_csi_parse_dt()
953 asd = v4l2_async_nf_add_fwnode_remote(&csidev->notifier, ep, in stm32_csi_parse_dt()
959 dev_err(csidev->dev, "Failed to add fwnode remote subdev\n"); in stm32_csi_parse_dt()
963 csidev->notifier.ops = &stm32_csi_notifier_ops; in stm32_csi_parse_dt()
965 ret = v4l2_async_nf_register(&csidev->notifier); in stm32_csi_parse_dt()
967 dev_err(csidev->dev, "Failed to register notifier\n"); in stm32_csi_parse_dt()
968 v4l2_async_nf_cleanup(&csidev->notifier); in stm32_csi_parse_dt()
977 struct stm32_csi_dev *csidev; in stm32_csi_probe() local
981 csidev = devm_kzalloc(&pdev->dev, sizeof(*csidev), GFP_KERNEL); in stm32_csi_probe()
982 if (!csidev) in stm32_csi_probe()
985 platform_set_drvdata(pdev, csidev); in stm32_csi_probe()
986 csidev->dev = &pdev->dev; in stm32_csi_probe()
988 spin_lock_init(&csidev->slock); in stm32_csi_probe()
990 ret = stm32_csi_get_resources(csidev, pdev); in stm32_csi_probe()
994 ret = stm32_csi_parse_dt(csidev); in stm32_csi_probe()
998 csidev->sd.owner = THIS_MODULE; in stm32_csi_probe()
999 csidev->sd.dev = &pdev->dev; in stm32_csi_probe()
1000 csidev->sd.internal_ops = &stm32_csi_subdev_internal_ops; in stm32_csi_probe()
1001 v4l2_subdev_init(&csidev->sd, &stm32_csi_subdev_ops); in stm32_csi_probe()
1002 v4l2_set_subdevdata(&csidev->sd, &pdev->dev); in stm32_csi_probe()
1003 snprintf(csidev->sd.name, sizeof(csidev->sd.name), "%s", in stm32_csi_probe()
1007 csidev->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; in stm32_csi_probe()
1008 csidev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in stm32_csi_probe()
1009 csidev->pads[STM32_CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK; in stm32_csi_probe()
1010 csidev->pads[STM32_CSI_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; in stm32_csi_probe()
1012 ret = media_entity_pads_init(&csidev->sd.entity, STM32_CSI_PAD_MAX, in stm32_csi_probe()
1013 csidev->pads); in stm32_csi_probe()
1017 ret = v4l2_subdev_init_finalize(&csidev->sd); in stm32_csi_probe()
1021 ret = v4l2_async_register_subdev(&csidev->sd); in stm32_csi_probe()
1052 "Probed CSI with %u lanes\n", csidev->num_lanes); in stm32_csi_probe()
1057 v4l2_async_nf_cleanup(&csidev->notifier); in stm32_csi_probe()
1064 struct stm32_csi_dev *csidev = platform_get_drvdata(pdev); in stm32_csi_remove() local
1066 v4l2_async_unregister_subdev(&csidev->sd); in stm32_csi_remove()
1073 struct stm32_csi_dev *csidev = dev_get_drvdata(dev); in stm32_csi_runtime_suspend() local
1076 clk_bulk_disable_unprepare(STM32_CSI_CLK_NB, csidev->clks); in stm32_csi_runtime_suspend()
1078 ret = regulator_bulk_disable(ARRAY_SIZE(csidev->supplies), in stm32_csi_runtime_suspend()
1079 csidev->supplies); in stm32_csi_runtime_suspend()
1088 struct stm32_csi_dev *csidev = dev_get_drvdata(dev); in stm32_csi_runtime_resume() local
1091 ret = regulator_bulk_enable(ARRAY_SIZE(csidev->supplies), in stm32_csi_runtime_resume()
1092 csidev->supplies); in stm32_csi_runtime_resume()
1096 ret = clk_bulk_prepare_enable(STM32_CSI_CLK_NB, csidev->clks); in stm32_csi_runtime_resume()
1103 ret = regulator_bulk_disable(ARRAY_SIZE(csidev->supplies), csidev->supplies); in stm32_csi_runtime_resume()
1107 dev_err(csidev->dev, "Failed to resume: %d\n", ret); in stm32_csi_runtime_resume()