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
38 #define CSIS_DRIVER_NAME "imx-mipi-csis"
49 /* CSIS version */
54 /* CSIS common control */
65 /* CSIS clock control */
74 /* CSIS Interrupt mask */
91 /* CSIS Interrupt source */
485 * CSIS outputs data in quad pixel mode regardless of the mode
487 * the IP cores connected to the CSIS in i.MX SoCs (CSI bridge
493 * format to RAW8. If the CSIS ends up being integrated in an
516 static inline u32 mipi_csis_read(struct mipi_csis_device *csis, u32 reg) in mipi_csis_read() argument
518 return readl(csis->regs + reg); in mipi_csis_read()
521 static inline void mipi_csis_write(struct mipi_csis_device *csis, u32 reg, in mipi_csis_write() argument
524 writel(val, csis->regs + reg); in mipi_csis_write()
527 static void mipi_csis_enable_interrupts(struct mipi_csis_device *csis, bool on) in mipi_csis_enable_interrupts() argument
529 mipi_csis_write(csis, MIPI_CSIS_INT_MSK, on ? 0xffffffff : 0); in mipi_csis_enable_interrupts()
530 mipi_csis_write(csis, MIPI_CSIS_DBG_INTR_MSK, on ? 0xffffffff : 0); in mipi_csis_enable_interrupts()
533 static void mipi_csis_sw_reset(struct mipi_csis_device *csis) in mipi_csis_sw_reset() argument
535 u32 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); in mipi_csis_sw_reset()
537 mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, in mipi_csis_sw_reset()
542 static void mipi_csis_system_enable(struct mipi_csis_device *csis, int on) in mipi_csis_system_enable() argument
546 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); in mipi_csis_system_enable()
551 mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, val); in mipi_csis_system_enable()
553 val = mipi_csis_read(csis, MIPI_CSIS_DPHY_CMN_CTRL); in mipi_csis_system_enable()
556 mask = (1 << (csis->bus.num_data_lanes + 1)) - 1; in mipi_csis_system_enable()
559 mipi_csis_write(csis, MIPI_CSIS_DPHY_CMN_CTRL, val); in mipi_csis_system_enable()
562 static void __mipi_csis_set_format(struct mipi_csis_device *csis, in __mipi_csis_set_format() argument
569 val = mipi_csis_read(csis, MIPI_CSIS_ISP_CONFIG_CH(0)); in __mipi_csis_set_format()
578 * when the CSIS is connected to a receiver that supports either option, in __mipi_csis_set_format()
580 * that integrate the CSIS can operate in 16-bit bit mode, and some do in __mipi_csis_set_format()
590 mipi_csis_write(csis, MIPI_CSIS_ISP_CONFIG_CH(0), val); in __mipi_csis_set_format()
594 mipi_csis_write(csis, MIPI_CSIS_ISP_RESOL_CH(0), val); in __mipi_csis_set_format()
597 static int mipi_csis_calculate_params(struct mipi_csis_device *csis, in mipi_csis_calculate_params() argument
604 link_freq = v4l2_get_link_freq(csis->source.sd->ctrl_handler, in mipi_csis_calculate_params()
606 csis->bus.num_data_lanes * 2); in mipi_csis_calculate_params()
608 dev_err(csis->dev, "Unable to obtain link frequency: %d\n", in mipi_csis_calculate_params()
616 dev_dbg(csis->dev, "Out-of-bound lane rate %u\n", lane_rate); in mipi_csis_calculate_params()
626 csis->hs_settle = (lane_rate - 5000000) / 45000000; in mipi_csis_calculate_params()
627 csis->clk_settle = 0; in mipi_csis_calculate_params()
629 dev_dbg(csis->dev, "lane rate %u, Tclk_settle %u, Ths_settle %u\n", in mipi_csis_calculate_params()
630 lane_rate, csis->clk_settle, csis->hs_settle); in mipi_csis_calculate_params()
632 if (csis->debug.hs_settle < 0xff) { in mipi_csis_calculate_params()
633 dev_dbg(csis->dev, "overriding Ths_settle with %u\n", in mipi_csis_calculate_params()
634 csis->debug.hs_settle); in mipi_csis_calculate_params()
635 csis->hs_settle = csis->debug.hs_settle; in mipi_csis_calculate_params()
638 if (csis->debug.clk_settle < 4) { in mipi_csis_calculate_params()
639 dev_dbg(csis->dev, "overriding Tclk_settle with %u\n", in mipi_csis_calculate_params()
640 csis->debug.clk_settle); in mipi_csis_calculate_params()
641 csis->clk_settle = csis->debug.clk_settle; in mipi_csis_calculate_params()
647 static void mipi_csis_set_params(struct mipi_csis_device *csis, in mipi_csis_set_params() argument
651 int lanes = csis->bus.num_data_lanes; in mipi_csis_set_params()
654 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); in mipi_csis_set_params()
657 if (csis->info->version == MIPI_CSIS_V3_3) in mipi_csis_set_params()
659 mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, val); in mipi_csis_set_params()
661 __mipi_csis_set_format(csis, format, csis_fmt); in mipi_csis_set_params()
663 mipi_csis_write(csis, MIPI_CSIS_DPHY_CMN_CTRL, in mipi_csis_set_params()
664 MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(csis->hs_settle) | in mipi_csis_set_params()
665 MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(csis->clk_settle)); in mipi_csis_set_params()
670 mipi_csis_write(csis, MIPI_CSIS_ISP_SYNC_CH(0), val); in mipi_csis_set_params()
672 val = mipi_csis_read(csis, MIPI_CSIS_CLK_CTRL); in mipi_csis_set_params()
676 mipi_csis_write(csis, MIPI_CSIS_CLK_CTRL, val); in mipi_csis_set_params()
678 mipi_csis_write(csis, MIPI_CSIS_DPHY_BCTRL_L, in mipi_csis_set_params()
686 mipi_csis_write(csis, MIPI_CSIS_DPHY_BCTRL_H, 0); in mipi_csis_set_params()
689 val = mipi_csis_read(csis, MIPI_CSIS_CMN_CTRL); in mipi_csis_set_params()
690 mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, in mipi_csis_set_params()
695 static int mipi_csis_clk_enable(struct mipi_csis_device *csis) in mipi_csis_clk_enable() argument
697 return clk_bulk_prepare_enable(csis->info->num_clocks, csis->clks); in mipi_csis_clk_enable()
700 static void mipi_csis_clk_disable(struct mipi_csis_device *csis) in mipi_csis_clk_disable() argument
702 clk_bulk_disable_unprepare(csis->info->num_clocks, csis->clks); in mipi_csis_clk_disable()
705 static int mipi_csis_clk_get(struct mipi_csis_device *csis) in mipi_csis_clk_get() argument
710 csis->clks = devm_kcalloc(csis->dev, csis->info->num_clocks, in mipi_csis_clk_get()
711 sizeof(*csis->clks), GFP_KERNEL); in mipi_csis_clk_get()
713 if (!csis->clks) in mipi_csis_clk_get()
716 for (i = 0; i < csis->info->num_clocks; i++) in mipi_csis_clk_get()
717 csis->clks[i].id = mipi_csis_clk_id[i]; in mipi_csis_clk_get()
719 ret = devm_clk_bulk_get(csis->dev, csis->info->num_clocks, in mipi_csis_clk_get()
720 csis->clks); in mipi_csis_clk_get()
725 ret = clk_set_rate(csis->clks[MIPI_CSIS_CLK_WRAP].clk, in mipi_csis_clk_get()
726 csis->clk_frequency); in mipi_csis_clk_get()
728 dev_err(csis->dev, "set rate=%d failed: %d\n", in mipi_csis_clk_get()
729 csis->clk_frequency, ret); in mipi_csis_clk_get()
734 static void mipi_csis_start_stream(struct mipi_csis_device *csis, in mipi_csis_start_stream() argument
738 mipi_csis_sw_reset(csis); in mipi_csis_start_stream()
739 mipi_csis_set_params(csis, format, csis_fmt); in mipi_csis_start_stream()
740 mipi_csis_system_enable(csis, true); in mipi_csis_start_stream()
741 mipi_csis_enable_interrupts(csis, true); in mipi_csis_start_stream()
744 static void mipi_csis_stop_stream(struct mipi_csis_device *csis) in mipi_csis_stop_stream() argument
746 mipi_csis_enable_interrupts(csis, false); in mipi_csis_stop_stream()
747 mipi_csis_system_enable(csis, false); in mipi_csis_stop_stream()
750 static void mipi_csis_queue_event_sof(struct mipi_csis_device *csis) in mipi_csis_queue_event_sof() argument
757 frame = mipi_csis_read(csis, MIPI_CSIS_FRAME_COUNTER_CH(0)); in mipi_csis_queue_event_sof()
759 v4l2_event_queue(csis->sd.devnode, &event); in mipi_csis_queue_event_sof()
764 struct mipi_csis_device *csis = dev_id; in mipi_csis_irq_handler() local
770 status = mipi_csis_read(csis, MIPI_CSIS_INT_SRC); in mipi_csis_irq_handler()
771 dbg_status = mipi_csis_read(csis, MIPI_CSIS_DBG_INTR_SRC); in mipi_csis_irq_handler()
773 spin_lock_irqsave(&csis->slock, flags); in mipi_csis_irq_handler()
776 if ((status & MIPI_CSIS_INT_SRC_ERRORS) || csis->debug.enable) { in mipi_csis_irq_handler()
778 struct mipi_csis_event *event = &csis->events[i]; in mipi_csis_irq_handler()
787 mipi_csis_queue_event_sof(csis); in mipi_csis_irq_handler()
789 spin_unlock_irqrestore(&csis->slock, flags); in mipi_csis_irq_handler()
791 mipi_csis_write(csis, MIPI_CSIS_INT_SRC, status); in mipi_csis_irq_handler()
792 mipi_csis_write(csis, MIPI_CSIS_DBG_INTR_SRC, dbg_status); in mipi_csis_irq_handler()
801 static int mipi_csis_phy_enable(struct mipi_csis_device *csis) in mipi_csis_phy_enable() argument
803 if (csis->info->version != MIPI_CSIS_V3_3) in mipi_csis_phy_enable()
806 return regulator_enable(csis->mipi_phy_regulator); in mipi_csis_phy_enable()
809 static int mipi_csis_phy_disable(struct mipi_csis_device *csis) in mipi_csis_phy_disable() argument
811 if (csis->info->version != MIPI_CSIS_V3_3) in mipi_csis_phy_disable()
814 return regulator_disable(csis->mipi_phy_regulator); in mipi_csis_phy_disable()
817 static void mipi_csis_phy_reset(struct mipi_csis_device *csis) in mipi_csis_phy_reset() argument
819 if (csis->info->version != MIPI_CSIS_V3_3) in mipi_csis_phy_reset()
822 reset_control_assert(csis->mrst); in mipi_csis_phy_reset()
824 reset_control_deassert(csis->mrst); in mipi_csis_phy_reset()
827 static int mipi_csis_phy_init(struct mipi_csis_device *csis) in mipi_csis_phy_init() argument
829 if (csis->info->version != MIPI_CSIS_V3_3) in mipi_csis_phy_init()
833 csis->mrst = devm_reset_control_get_exclusive(csis->dev, NULL); in mipi_csis_phy_init()
834 if (IS_ERR(csis->mrst)) in mipi_csis_phy_init()
835 return PTR_ERR(csis->mrst); in mipi_csis_phy_init()
837 csis->mipi_phy_regulator = devm_regulator_get(csis->dev, "phy"); in mipi_csis_phy_init()
838 if (IS_ERR(csis->mipi_phy_regulator)) in mipi_csis_phy_init()
839 return PTR_ERR(csis->mipi_phy_regulator); in mipi_csis_phy_init()
841 return regulator_set_voltage(csis->mipi_phy_regulator, 1000000, in mipi_csis_phy_init()
849 static void mipi_csis_clear_counters(struct mipi_csis_device *csis) in mipi_csis_clear_counters() argument
854 spin_lock_irqsave(&csis->slock, flags); in mipi_csis_clear_counters()
856 csis->events[i].counter = 0; in mipi_csis_clear_counters()
857 spin_unlock_irqrestore(&csis->slock, flags); in mipi_csis_clear_counters()
860 static void mipi_csis_log_counters(struct mipi_csis_device *csis, bool non_errors) in mipi_csis_log_counters() argument
868 spin_lock_irqsave(&csis->slock, flags); in mipi_csis_log_counters()
870 counters[i] = csis->events[i].counter; in mipi_csis_log_counters()
871 spin_unlock_irqrestore(&csis->slock, flags); in mipi_csis_log_counters()
874 if (counters[i] > 0 || csis->debug.enable) in mipi_csis_log_counters()
875 dev_info(csis->dev, "%s events: %d\n", in mipi_csis_log_counters()
876 csis->events[i].name, in mipi_csis_log_counters()
881 static int mipi_csis_dump_regs(struct mipi_csis_device *csis) in mipi_csis_dump_regs() argument
905 if (!pm_runtime_get_if_in_use(csis->dev)) in mipi_csis_dump_regs()
908 dev_info(csis->dev, "--- REGISTERS ---\n"); in mipi_csis_dump_regs()
911 cfg = mipi_csis_read(csis, registers[i].offset); in mipi_csis_dump_regs()
912 dev_info(csis->dev, "%14s: 0x%08x\n", registers[i].name, cfg); in mipi_csis_dump_regs()
915 pm_runtime_put(csis->dev); in mipi_csis_dump_regs()
922 struct mipi_csis_device *csis = m->private; in mipi_csis_dump_regs_show() local
924 return mipi_csis_dump_regs(csis); in mipi_csis_dump_regs_show()
928 static void mipi_csis_debugfs_init(struct mipi_csis_device *csis) in mipi_csis_debugfs_init() argument
930 csis->debug.hs_settle = UINT_MAX; in mipi_csis_debugfs_init()
931 csis->debug.clk_settle = UINT_MAX; in mipi_csis_debugfs_init()
933 csis->debugfs_root = debugfs_create_dir(dev_name(csis->dev), NULL); in mipi_csis_debugfs_init()
935 debugfs_create_bool("debug_enable", 0600, csis->debugfs_root, in mipi_csis_debugfs_init()
936 &csis->debug.enable); in mipi_csis_debugfs_init()
937 debugfs_create_file("dump_regs", 0600, csis->debugfs_root, csis, in mipi_csis_debugfs_init()
939 debugfs_create_u32("tclk_settle", 0600, csis->debugfs_root, in mipi_csis_debugfs_init()
940 &csis->debug.clk_settle); in mipi_csis_debugfs_init()
941 debugfs_create_u32("ths_settle", 0600, csis->debugfs_root, in mipi_csis_debugfs_init()
942 &csis->debug.hs_settle); in mipi_csis_debugfs_init()
945 static void mipi_csis_debugfs_exit(struct mipi_csis_device *csis) in mipi_csis_debugfs_exit() argument
947 debugfs_remove_recursive(csis->debugfs_root); in mipi_csis_debugfs_exit()
961 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_s_stream() local
968 v4l2_subdev_disable_streams(csis->source.sd, in mipi_csis_s_stream()
969 csis->source.pad->index, BIT(0)); in mipi_csis_s_stream()
971 mipi_csis_stop_stream(csis); in mipi_csis_s_stream()
972 if (csis->debug.enable) in mipi_csis_s_stream()
973 mipi_csis_log_counters(csis, true); in mipi_csis_s_stream()
975 pm_runtime_put(csis->dev); in mipi_csis_s_stream()
985 ret = mipi_csis_calculate_params(csis, csis_fmt); in mipi_csis_s_stream()
989 mipi_csis_clear_counters(csis); in mipi_csis_s_stream()
991 ret = pm_runtime_resume_and_get(csis->dev); in mipi_csis_s_stream()
995 mipi_csis_start_stream(csis, format, csis_fmt); in mipi_csis_s_stream()
997 ret = v4l2_subdev_enable_streams(csis->source.sd, in mipi_csis_s_stream()
998 csis->source.pad->index, BIT(0)); in mipi_csis_s_stream()
1002 mipi_csis_log_counters(csis, true); in mipi_csis_s_stream()
1009 mipi_csis_stop_stream(csis); in mipi_csis_s_stream()
1010 pm_runtime_put(csis->dev); in mipi_csis_s_stream()
1022 * The CSIS can't transcode in any way, the source format is identical in mipi_csis_enum_mbus_code()
1056 * The CSIS can't transcode in any way, the source format can't be in mipi_csis_set_fmt()
1174 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_log_status() local
1176 mipi_csis_log_counters(csis, true); in mipi_csis_log_status()
1177 if (csis->debug.enable) in mipi_csis_log_status()
1178 mipi_csis_dump_regs(csis); in mipi_csis_log_status()
1232 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_link_setup() local
1235 dev_dbg(csis->dev, "link setup %s -> %s", remote_pad->entity->name, in mipi_csis_link_setup()
1245 if (csis->source.sd) in mipi_csis_link_setup()
1248 csis->source.sd = remote_sd; in mipi_csis_link_setup()
1249 csis->source.pad = remote_pad; in mipi_csis_link_setup()
1251 csis->source.sd = NULL; in mipi_csis_link_setup()
1252 csis->source.pad = NULL; in mipi_csis_link_setup()
1278 struct mipi_csis_device *csis = mipi_notifier_to_csis_state(notifier); in mipi_csis_notify_bound() local
1279 struct media_pad *sink = &csis->sd.entity.pads[CSIS_PAD_SINK]; in mipi_csis_notify_bound()
1288 static int mipi_csis_async_register(struct mipi_csis_device *csis) in mipi_csis_async_register() argument
1298 v4l2_async_subdev_nf_init(&csis->notifier, &csis->sd); in mipi_csis_async_register()
1300 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csis->dev), 0, 0, in mipi_csis_async_register()
1311 dev_err(csis->dev, in mipi_csis_async_register()
1318 csis->bus = vep.bus.mipi_csi2; in mipi_csis_async_register()
1320 dev_dbg(csis->dev, "data lanes: %d\n", csis->bus.num_data_lanes); in mipi_csis_async_register()
1321 dev_dbg(csis->dev, "flags: 0x%08x\n", csis->bus.flags); in mipi_csis_async_register()
1323 asd = v4l2_async_nf_add_fwnode_remote(&csis->notifier, ep, in mipi_csis_async_register()
1332 csis->notifier.ops = &mipi_csis_notify_ops; in mipi_csis_async_register()
1334 ret = v4l2_async_nf_register(&csis->notifier); in mipi_csis_async_register()
1338 return v4l2_async_register_subdev(&csis->sd); in mipi_csis_async_register()
1353 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_runtime_suspend() local
1356 ret = mipi_csis_phy_disable(csis); in mipi_csis_runtime_suspend()
1360 mipi_csis_clk_disable(csis); in mipi_csis_runtime_suspend()
1368 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_runtime_resume() local
1371 ret = mipi_csis_phy_enable(csis); in mipi_csis_runtime_resume()
1375 ret = mipi_csis_clk_enable(csis); in mipi_csis_runtime_resume()
1377 mipi_csis_phy_disable(csis); in mipi_csis_runtime_resume()
1393 static int mipi_csis_subdev_init(struct mipi_csis_device *csis) in mipi_csis_subdev_init() argument
1395 struct v4l2_subdev *sd = &csis->sd; in mipi_csis_subdev_init()
1401 snprintf(sd->name, sizeof(sd->name), "csis-%s", in mipi_csis_subdev_init()
1402 dev_name(csis->dev)); in mipi_csis_subdev_init()
1410 sd->dev = csis->dev; in mipi_csis_subdev_init()
1412 csis->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK in mipi_csis_subdev_init()
1414 csis->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE in mipi_csis_subdev_init()
1416 ret = media_entity_pads_init(&sd->entity, CSIS_PADS_NUM, csis->pads); in mipi_csis_subdev_init()
1429 static int mipi_csis_parse_dt(struct mipi_csis_device *csis) in mipi_csis_parse_dt() argument
1431 struct device_node *node = csis->dev->of_node; in mipi_csis_parse_dt()
1434 &csis->clk_frequency)) in mipi_csis_parse_dt()
1435 csis->clk_frequency = DEFAULT_SCLK_CSIS_FREQ; in mipi_csis_parse_dt()
1443 struct mipi_csis_device *csis; in mipi_csis_probe() local
1447 csis = devm_kzalloc(dev, sizeof(*csis), GFP_KERNEL); in mipi_csis_probe()
1448 if (!csis) in mipi_csis_probe()
1451 spin_lock_init(&csis->slock); in mipi_csis_probe()
1453 csis->dev = dev; in mipi_csis_probe()
1454 csis->info = of_device_get_match_data(dev); in mipi_csis_probe()
1456 memcpy(csis->events, mipi_csis_events, sizeof(csis->events)); in mipi_csis_probe()
1459 ret = mipi_csis_parse_dt(csis); in mipi_csis_probe()
1466 csis->regs = devm_platform_ioremap_resource(pdev, 0); in mipi_csis_probe()
1467 if (IS_ERR(csis->regs)) in mipi_csis_probe()
1468 return PTR_ERR(csis->regs); in mipi_csis_probe()
1474 ret = mipi_csis_phy_init(csis); in mipi_csis_probe()
1478 ret = mipi_csis_clk_get(csis); in mipi_csis_probe()
1483 mipi_csis_phy_reset(csis); in mipi_csis_probe()
1487 dev_name(dev), csis); in mipi_csis_probe()
1494 ret = mipi_csis_subdev_init(csis); in mipi_csis_probe()
1498 platform_set_drvdata(pdev, &csis->sd); in mipi_csis_probe()
1500 ret = mipi_csis_async_register(csis); in mipi_csis_probe()
1507 mipi_csis_debugfs_init(csis); in mipi_csis_probe()
1518 csis->bus.num_data_lanes, csis->clk_frequency); in mipi_csis_probe()
1523 mipi_csis_debugfs_exit(csis); in mipi_csis_probe()
1525 v4l2_subdev_cleanup(&csis->sd); in mipi_csis_probe()
1526 media_entity_cleanup(&csis->sd.entity); in mipi_csis_probe()
1527 v4l2_async_nf_unregister(&csis->notifier); in mipi_csis_probe()
1528 v4l2_async_nf_cleanup(&csis->notifier); in mipi_csis_probe()
1529 v4l2_async_unregister_subdev(&csis->sd); in mipi_csis_probe()
1537 struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd); in mipi_csis_remove() local
1539 mipi_csis_debugfs_exit(csis); in mipi_csis_remove()
1540 v4l2_async_nf_unregister(&csis->notifier); in mipi_csis_remove()
1541 v4l2_async_nf_cleanup(&csis->notifier); in mipi_csis_remove()
1542 v4l2_async_unregister_subdev(&csis->sd); in mipi_csis_remove()
1548 v4l2_subdev_cleanup(&csis->sd); in mipi_csis_remove()
1549 media_entity_cleanup(&csis->sd.entity); in mipi_csis_remove()