Lines Matching full:csis

3  * Samsung CSIS MIPI CSI-2 receiver driver.
5 * The Samsung CSIS IP is a MIPI CSI-2 receiver found in various NXP i.MX7 and
37 #define CSIS_DRIVER_NAME "imx-mipi-csis"
48 /* CSIS version */
53 /* CSIS common control */
64 /* CSIS clock control */
73 /* CSIS Interrupt mask */
90 /* CSIS Interrupt source */
480 * CSIS outputs data in quad pixel mode regardless of the mode
482 * the IP cores connected to the CSIS in i.MX SoCs (CSI bridge
488 * format to RAW8. If the CSIS ends up being integrated in an
511 static inline u32 mipi_csis_read(struct mipi_csis_device *csis, u32 reg) in mipi_csis_read() argument
513 return readl(csis->regs + reg); in mipi_csis_read()
516 static inline void mipi_csis_write(struct mipi_csis_device *csis, u32 reg, in mipi_csis_write() argument
519 writel(val, csis->regs + reg); in mipi_csis_write()
522 static void mipi_csis_enable_interrupts(struct mipi_csis_device *csis, bool on) in mipi_csis_enable_interrupts() argument
524 mipi_csis_write(csis, MIPI_CSIS_INT_MSK, on ? 0xffffffff : 0); in mipi_csis_enable_interrupts()
525 mipi_csis_write(csis, MIPI_CSIS_DBG_INTR_MSK, on ? 0xffffffff : 0); in mipi_csis_enable_interrupts()
528 static void mipi_csis_sw_reset(struct mipi_csis_device *csis) in mipi_csis_sw_reset() argument
530 u32 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); in mipi_csis_sw_reset()
532 mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, in mipi_csis_sw_reset()
537 static void mipi_csis_system_enable(struct mipi_csis_device *csis, int on) in mipi_csis_system_enable() argument
541 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); in mipi_csis_system_enable()
546 mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, val); in mipi_csis_system_enable()
548 val = mipi_csis_read(csis, MIPI_CSIS_DPHY_CMN_CTRL); in mipi_csis_system_enable()
551 mask = (1 << (csis->bus.num_data_lanes + 1)) - 1; in mipi_csis_system_enable()
554 mipi_csis_write(csis, MIPI_CSIS_DPHY_CMN_CTRL, val); in mipi_csis_system_enable()
557 static void __mipi_csis_set_format(struct mipi_csis_device *csis, in __mipi_csis_set_format() argument
564 val = mipi_csis_read(csis, MIPI_CSIS_ISP_CONFIG_CH(0)); in __mipi_csis_set_format()
573 * when the CSIS is connected to a receiver that supports either option, in __mipi_csis_set_format()
575 * that integrate the CSIS can operate in 16-bit bit mode, and some do in __mipi_csis_set_format()
585 mipi_csis_write(csis, MIPI_CSIS_ISP_CONFIG_CH(0), val); in __mipi_csis_set_format()
589 mipi_csis_write(csis, MIPI_CSIS_ISP_RESOL_CH(0), val); in __mipi_csis_set_format()
592 static int mipi_csis_calculate_params(struct mipi_csis_device *csis, in mipi_csis_calculate_params() argument
599 link_freq = v4l2_get_link_freq(csis->src_sd->ctrl_handler, in mipi_csis_calculate_params()
601 csis->bus.num_data_lanes * 2); in mipi_csis_calculate_params()
603 dev_err(csis->dev, "Unable to obtain link frequency: %d\n", in mipi_csis_calculate_params()
611 dev_dbg(csis->dev, "Out-of-bound lane rate %u\n", lane_rate); in mipi_csis_calculate_params()
621 csis->hs_settle = (lane_rate - 5000000) / 45000000; in mipi_csis_calculate_params()
622 csis->clk_settle = 0; in mipi_csis_calculate_params()
624 dev_dbg(csis->dev, "lane rate %u, Tclk_settle %u, Ths_settle %u\n", in mipi_csis_calculate_params()
625 lane_rate, csis->clk_settle, csis->hs_settle); in mipi_csis_calculate_params()
627 if (csis->debug.hs_settle < 0xff) { in mipi_csis_calculate_params()
628 dev_dbg(csis->dev, "overriding Ths_settle with %u\n", in mipi_csis_calculate_params()
629 csis->debug.hs_settle); in mipi_csis_calculate_params()
630 csis->hs_settle = csis->debug.hs_settle; in mipi_csis_calculate_params()
633 if (csis->debug.clk_settle < 4) { in mipi_csis_calculate_params()
634 dev_dbg(csis->dev, "overriding Tclk_settle with %u\n", in mipi_csis_calculate_params()
635 csis->debug.clk_settle); in mipi_csis_calculate_params()
636 csis->clk_settle = csis->debug.clk_settle; in mipi_csis_calculate_params()
642 static void mipi_csis_set_params(struct mipi_csis_device *csis, in mipi_csis_set_params() argument
646 int lanes = csis->bus.num_data_lanes; in mipi_csis_set_params()
649 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); in mipi_csis_set_params()
652 if (csis->info->version == MIPI_CSIS_V3_3) in mipi_csis_set_params()
654 mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, val); in mipi_csis_set_params()
656 __mipi_csis_set_format(csis, format, csis_fmt); in mipi_csis_set_params()
658 mipi_csis_write(csis, MIPI_CSIS_DPHY_CMN_CTRL, in mipi_csis_set_params()
659 MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(csis->hs_settle) | in mipi_csis_set_params()
660 MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(csis->clk_settle)); in mipi_csis_set_params()
665 mipi_csis_write(csis, MIPI_CSIS_ISP_SYNC_CH(0), val); in mipi_csis_set_params()
667 val = mipi_csis_read(csis, MIPI_CSIS_CLK_CTRL); in mipi_csis_set_params()
671 mipi_csis_write(csis, MIPI_CSIS_CLK_CTRL, val); in mipi_csis_set_params()
673 mipi_csis_write(csis, MIPI_CSIS_DPHY_BCTRL_L, in mipi_csis_set_params()
681 mipi_csis_write(csis, MIPI_CSIS_DPHY_BCTRL_H, 0); in mipi_csis_set_params()
684 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); in mipi_csis_set_params()
685 mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, in mipi_csis_set_params()
690 static int mipi_csis_clk_enable(struct mipi_csis_device *csis) in mipi_csis_clk_enable() argument
692 return clk_bulk_prepare_enable(csis->info->num_clocks, csis->clks); in mipi_csis_clk_enable()
695 static void mipi_csis_clk_disable(struct mipi_csis_device *csis) in mipi_csis_clk_disable() argument
697 clk_bulk_disable_unprepare(csis->info->num_clocks, csis->clks); in mipi_csis_clk_disable()
700 static int mipi_csis_clk_get(struct mipi_csis_device *csis) in mipi_csis_clk_get() argument
705 csis->clks = devm_kcalloc(csis->dev, csis->info->num_clocks, in mipi_csis_clk_get()
706 sizeof(*csis->clks), GFP_KERNEL); in mipi_csis_clk_get()
708 if (!csis->clks) in mipi_csis_clk_get()
711 for (i = 0; i < csis->info->num_clocks; i++) in mipi_csis_clk_get()
712 csis->clks[i].id = mipi_csis_clk_id[i]; in mipi_csis_clk_get()
714 ret = devm_clk_bulk_get(csis->dev, csis->info->num_clocks, in mipi_csis_clk_get()
715 csis->clks); in mipi_csis_clk_get()
720 ret = clk_set_rate(csis->clks[MIPI_CSIS_CLK_WRAP].clk, in mipi_csis_clk_get()
721 csis->clk_frequency); in mipi_csis_clk_get()
723 dev_err(csis->dev, "set rate=%d failed: %d\n", in mipi_csis_clk_get()
724 csis->clk_frequency, ret); in mipi_csis_clk_get()
729 static void mipi_csis_start_stream(struct mipi_csis_device *csis, in mipi_csis_start_stream() argument
733 mipi_csis_sw_reset(csis); in mipi_csis_start_stream()
734 mipi_csis_set_params(csis, format, csis_fmt); in mipi_csis_start_stream()
735 mipi_csis_system_enable(csis, true); in mipi_csis_start_stream()
736 mipi_csis_enable_interrupts(csis, true); in mipi_csis_start_stream()
739 static void mipi_csis_stop_stream(struct mipi_csis_device *csis) in mipi_csis_stop_stream() argument
741 mipi_csis_enable_interrupts(csis, false); in mipi_csis_stop_stream()
742 mipi_csis_system_enable(csis, false); in mipi_csis_stop_stream()
747 struct mipi_csis_device *csis = dev_id; in mipi_csis_irq_handler() local
753 status = mipi_csis_read(csis, MIPI_CSIS_INT_SRC); in mipi_csis_irq_handler()
754 dbg_status = mipi_csis_read(csis, MIPI_CSIS_DBG_INTR_SRC); in mipi_csis_irq_handler()
756 spin_lock_irqsave(&csis->slock, flags); in mipi_csis_irq_handler()
759 if ((status & MIPI_CSIS_INT_SRC_ERRORS) || csis->debug.enable) { in mipi_csis_irq_handler()
761 struct mipi_csis_event *event = &csis->events[i]; in mipi_csis_irq_handler()
768 spin_unlock_irqrestore(&csis->slock, flags); in mipi_csis_irq_handler()
770 mipi_csis_write(csis, MIPI_CSIS_INT_SRC, status); in mipi_csis_irq_handler()
771 mipi_csis_write(csis, MIPI_CSIS_DBG_INTR_SRC, dbg_status); in mipi_csis_irq_handler()
780 static int mipi_csis_phy_enable(struct mipi_csis_device *csis) in mipi_csis_phy_enable() argument
782 if (csis->info->version != MIPI_CSIS_V3_3) in mipi_csis_phy_enable()
785 return regulator_enable(csis->mipi_phy_regulator); in mipi_csis_phy_enable()
788 static int mipi_csis_phy_disable(struct mipi_csis_device *csis) in mipi_csis_phy_disable() argument
790 if (csis->info->version != MIPI_CSIS_V3_3) in mipi_csis_phy_disable()
793 return regulator_disable(csis->mipi_phy_regulator); in mipi_csis_phy_disable()
796 static void mipi_csis_phy_reset(struct mipi_csis_device *csis) in mipi_csis_phy_reset() argument
798 if (csis->info->version != MIPI_CSIS_V3_3) in mipi_csis_phy_reset()
801 reset_control_assert(csis->mrst); in mipi_csis_phy_reset()
803 reset_control_deassert(csis->mrst); in mipi_csis_phy_reset()
806 static int mipi_csis_phy_init(struct mipi_csis_device *csis) in mipi_csis_phy_init() argument
808 if (csis->info->version != MIPI_CSIS_V3_3) in mipi_csis_phy_init()
812 csis->mrst = devm_reset_control_get_exclusive(csis->dev, NULL); in mipi_csis_phy_init()
813 if (IS_ERR(csis->mrst)) in mipi_csis_phy_init()
814 return PTR_ERR(csis->mrst); in mipi_csis_phy_init()
816 csis->mipi_phy_regulator = devm_regulator_get(csis->dev, "phy"); in mipi_csis_phy_init()
817 if (IS_ERR(csis->mipi_phy_regulator)) in mipi_csis_phy_init()
818 return PTR_ERR(csis->mipi_phy_regulator); in mipi_csis_phy_init()
820 return regulator_set_voltage(csis->mipi_phy_regulator, 1000000, in mipi_csis_phy_init()
828 static void mipi_csis_clear_counters(struct mipi_csis_device *csis) in mipi_csis_clear_counters() argument
833 spin_lock_irqsave(&csis->slock, flags); in mipi_csis_clear_counters()
835 csis->events[i].counter = 0; in mipi_csis_clear_counters()
836 spin_unlock_irqrestore(&csis->slock, flags); in mipi_csis_clear_counters()
839 static void mipi_csis_log_counters(struct mipi_csis_device *csis, bool non_errors) in mipi_csis_log_counters() argument
846 spin_lock_irqsave(&csis->slock, flags); in mipi_csis_log_counters()
849 if (csis->events[i].counter > 0 || csis->debug.enable) in mipi_csis_log_counters()
850 dev_info(csis->dev, "%s events: %d\n", in mipi_csis_log_counters()
851 csis->events[i].name, in mipi_csis_log_counters()
852 csis->events[i].counter); in mipi_csis_log_counters()
854 spin_unlock_irqrestore(&csis->slock, flags); in mipi_csis_log_counters()
857 static int mipi_csis_dump_regs(struct mipi_csis_device *csis) in mipi_csis_dump_regs() argument
881 if (!pm_runtime_get_if_in_use(csis->dev)) in mipi_csis_dump_regs()
884 dev_info(csis->dev, "--- REGISTERS ---\n"); in mipi_csis_dump_regs()
887 cfg = mipi_csis_read(csis, registers[i].offset); in mipi_csis_dump_regs()
888 dev_info(csis->dev, "%14s: 0x%08x\n", registers[i].name, cfg); in mipi_csis_dump_regs()
891 pm_runtime_put(csis->dev); in mipi_csis_dump_regs()
898 struct mipi_csis_device *csis = m->private; in mipi_csis_dump_regs_show() local
900 return mipi_csis_dump_regs(csis); in mipi_csis_dump_regs_show()
904 static void mipi_csis_debugfs_init(struct mipi_csis_device *csis) in mipi_csis_debugfs_init() argument
906 csis->debug.hs_settle = UINT_MAX; in mipi_csis_debugfs_init()
907 csis->debug.clk_settle = UINT_MAX; in mipi_csis_debugfs_init()
909 csis->debugfs_root = debugfs_create_dir(dev_name(csis->dev), NULL); in mipi_csis_debugfs_init()
911 debugfs_create_bool("debug_enable", 0600, csis->debugfs_root, in mipi_csis_debugfs_init()
912 &csis->debug.enable); in mipi_csis_debugfs_init()
913 debugfs_create_file("dump_regs", 0600, csis->debugfs_root, csis, in mipi_csis_debugfs_init()
915 debugfs_create_u32("tclk_settle", 0600, csis->debugfs_root, in mipi_csis_debugfs_init()
916 &csis->debug.clk_settle); in mipi_csis_debugfs_init()
917 debugfs_create_u32("ths_settle", 0600, csis->debugfs_root, in mipi_csis_debugfs_init()
918 &csis->debug.hs_settle); in mipi_csis_debugfs_init()
921 static void mipi_csis_debugfs_exit(struct mipi_csis_device *csis) in mipi_csis_debugfs_exit() argument
923 debugfs_remove_recursive(csis->debugfs_root); in mipi_csis_debugfs_exit()
937 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_s_stream() local
944 v4l2_subdev_call(csis->src_sd, video, s_stream, 0); in mipi_csis_s_stream()
946 mipi_csis_stop_stream(csis); in mipi_csis_s_stream()
947 if (csis->debug.enable) in mipi_csis_s_stream()
948 mipi_csis_log_counters(csis, true); in mipi_csis_s_stream()
950 pm_runtime_put(csis->dev); in mipi_csis_s_stream()
960 ret = mipi_csis_calculate_params(csis, csis_fmt); in mipi_csis_s_stream()
964 mipi_csis_clear_counters(csis); in mipi_csis_s_stream()
966 ret = pm_runtime_resume_and_get(csis->dev); in mipi_csis_s_stream()
970 mipi_csis_start_stream(csis, format, csis_fmt); in mipi_csis_s_stream()
972 ret = v4l2_subdev_call(csis->src_sd, video, s_stream, 1); in mipi_csis_s_stream()
976 mipi_csis_log_counters(csis, true); in mipi_csis_s_stream()
983 mipi_csis_stop_stream(csis); in mipi_csis_s_stream()
984 pm_runtime_put(csis->dev); in mipi_csis_s_stream()
996 * The CSIS can't transcode in any way, the source format is identical in mipi_csis_enum_mbus_code()
1030 * The CSIS can't transcode in any way, the source format can't be in mipi_csis_set_fmt()
1150 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_log_status() local
1152 mipi_csis_log_counters(csis, true); in mipi_csis_log_status()
1153 if (csis->debug.enable) in mipi_csis_log_status()
1154 mipi_csis_dump_regs(csis); in mipi_csis_log_status()
1190 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_link_setup() local
1193 dev_dbg(csis->dev, "link setup %s -> %s", remote_pad->entity->name, in mipi_csis_link_setup()
1203 if (csis->src_sd) in mipi_csis_link_setup()
1206 csis->src_sd = remote_sd; in mipi_csis_link_setup()
1208 csis->src_sd = NULL; in mipi_csis_link_setup()
1234 struct mipi_csis_device *csis = mipi_notifier_to_csis_state(notifier); in mipi_csis_notify_bound() local
1235 struct media_pad *sink = &csis->sd.entity.pads[CSIS_PAD_SINK]; in mipi_csis_notify_bound()
1244 static int mipi_csis_async_register(struct mipi_csis_device *csis) in mipi_csis_async_register() argument
1254 v4l2_async_subdev_nf_init(&csis->notifier, &csis->sd); in mipi_csis_async_register()
1256 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csis->dev), 0, 0, in mipi_csis_async_register()
1267 dev_err(csis->dev, in mipi_csis_async_register()
1274 csis->bus = vep.bus.mipi_csi2; in mipi_csis_async_register()
1276 dev_dbg(csis->dev, "data lanes: %d\n", csis->bus.num_data_lanes); in mipi_csis_async_register()
1277 dev_dbg(csis->dev, "flags: 0x%08x\n", csis->bus.flags); in mipi_csis_async_register()
1279 asd = v4l2_async_nf_add_fwnode_remote(&csis->notifier, ep, in mipi_csis_async_register()
1288 csis->notifier.ops = &mipi_csis_notify_ops; in mipi_csis_async_register()
1290 ret = v4l2_async_nf_register(&csis->notifier); in mipi_csis_async_register()
1294 return v4l2_async_register_subdev(&csis->sd); in mipi_csis_async_register()
1309 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_runtime_suspend() local
1312 ret = mipi_csis_phy_disable(csis); in mipi_csis_runtime_suspend()
1316 mipi_csis_clk_disable(csis); in mipi_csis_runtime_suspend()
1324 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_runtime_resume() local
1327 ret = mipi_csis_phy_enable(csis); in mipi_csis_runtime_resume()
1331 ret = mipi_csis_clk_enable(csis); in mipi_csis_runtime_resume()
1333 mipi_csis_phy_disable(csis); in mipi_csis_runtime_resume()
1349 static int mipi_csis_subdev_init(struct mipi_csis_device *csis) in mipi_csis_subdev_init() argument
1351 struct v4l2_subdev *sd = &csis->sd; in mipi_csis_subdev_init()
1356 snprintf(sd->name, sizeof(sd->name), "csis-%s", in mipi_csis_subdev_init()
1357 dev_name(csis->dev)); in mipi_csis_subdev_init()
1365 sd->dev = csis->dev; in mipi_csis_subdev_init()
1367 csis->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK in mipi_csis_subdev_init()
1369 csis->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE in mipi_csis_subdev_init()
1371 ret = media_entity_pads_init(&sd->entity, CSIS_PADS_NUM, csis->pads); in mipi_csis_subdev_init()
1384 static int mipi_csis_parse_dt(struct mipi_csis_device *csis) in mipi_csis_parse_dt() argument
1386 struct device_node *node = csis->dev->of_node; in mipi_csis_parse_dt()
1389 &csis->clk_frequency)) in mipi_csis_parse_dt()
1390 csis->clk_frequency = DEFAULT_SCLK_CSIS_FREQ; in mipi_csis_parse_dt()
1398 struct mipi_csis_device *csis; in mipi_csis_probe() local
1402 csis = devm_kzalloc(dev, sizeof(*csis), GFP_KERNEL); in mipi_csis_probe()
1403 if (!csis) in mipi_csis_probe()
1406 spin_lock_init(&csis->slock); in mipi_csis_probe()
1408 csis->dev = dev; in mipi_csis_probe()
1409 csis->info = of_device_get_match_data(dev); in mipi_csis_probe()
1411 memcpy(csis->events, mipi_csis_events, sizeof(csis->events)); in mipi_csis_probe()
1414 ret = mipi_csis_parse_dt(csis); in mipi_csis_probe()
1421 csis->regs = devm_platform_ioremap_resource(pdev, 0); in mipi_csis_probe()
1422 if (IS_ERR(csis->regs)) in mipi_csis_probe()
1423 return PTR_ERR(csis->regs); in mipi_csis_probe()
1429 ret = mipi_csis_phy_init(csis); in mipi_csis_probe()
1433 ret = mipi_csis_clk_get(csis); in mipi_csis_probe()
1438 mipi_csis_phy_reset(csis); in mipi_csis_probe()
1442 dev_name(dev), csis); in mipi_csis_probe()
1449 ret = mipi_csis_subdev_init(csis); in mipi_csis_probe()
1453 platform_set_drvdata(pdev, &csis->sd); in mipi_csis_probe()
1455 ret = mipi_csis_async_register(csis); in mipi_csis_probe()
1462 mipi_csis_debugfs_init(csis); in mipi_csis_probe()
1473 csis->bus.num_data_lanes, csis->clk_frequency); in mipi_csis_probe()
1478 mipi_csis_debugfs_exit(csis); in mipi_csis_probe()
1480 v4l2_subdev_cleanup(&csis->sd); in mipi_csis_probe()
1481 media_entity_cleanup(&csis->sd.entity); in mipi_csis_probe()
1482 v4l2_async_nf_unregister(&csis->notifier); in mipi_csis_probe()
1483 v4l2_async_nf_cleanup(&csis->notifier); in mipi_csis_probe()
1484 v4l2_async_unregister_subdev(&csis->sd); in mipi_csis_probe()
1492 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_remove() local
1494 mipi_csis_debugfs_exit(csis); in mipi_csis_remove()
1495 v4l2_async_nf_unregister(&csis->notifier); in mipi_csis_remove()
1496 v4l2_async_nf_cleanup(&csis->notifier); in mipi_csis_remove()
1497 v4l2_async_unregister_subdev(&csis->sd); in mipi_csis_remove()
1503 v4l2_subdev_cleanup(&csis->sd); in mipi_csis_remove()
1504 media_entity_cleanup(&csis->sd.entity); in mipi_csis_remove()