Lines Matching +full:sync +full:- +full:dual +full:- +full:dsi
1 // SPDX-License-Identifier: GPL-2.0
6 * - SN65DSI83
7 * = 1x Single-link DSI ~ 1x Single-link LVDS
8 * - Supported
9 * - Single-link LVDS mode tested
10 * - SN65DSI84
11 * = 1x Single-link DSI ~ 2x Single-link or 1x Dual-link LVDS
12 * - Supported
13 * - Dual-link LVDS mode tested
14 * - 2x Single-link LVDS mode unsupported
16 * - SN65DSI85
17 * = 2x Single-link or 1x Dual-link DSI ~ 2x Single-link or 1x Dual-link LVDS
18 * - Unsupported
32 #include <linux/media-bus-format.h>
63 /* DSI registers */
65 #define REG_DSI_LANE_LEFT_RIGHT_PIXELS BIT(7) /* DSI85-only */
66 #define REG_DSI_LANE_DSI_CHANNEL_MODE_DUAL 0 /* DSI85-only */
67 #define REG_DSI_LANE_DSI_CHANNEL_MODE_2SINGLE BIT(6) /* DSI85-only */
82 #define REG_LVDS_FMT_LVDS_LINK_CFG BIT(4) /* 0:AB 1:A-only */
156 struct mipi_dsi_device *dsi; member
297 return drm_bridge_attach(bridge->encoder, ctx->panel_bridge, in sn65dsi83_attach()
298 &ctx->bridge, flags); in sn65dsi83_attach()
305 if (!ctx->dsi) in sn65dsi83_detach()
308 ctx->dsi = NULL; in sn65dsi83_detach()
316 * 000 - 25 MHz <= LVDS_CLK < 37.5 MHz in sn65dsi83_get_lvds_range()
317 * 001 - 37.5 MHz <= LVDS_CLK < 62.5 MHz in sn65dsi83_get_lvds_range()
318 * 010 - 62.5 MHz <= LVDS_CLK < 87.5 MHz in sn65dsi83_get_lvds_range()
319 * 011 - 87.5 MHz <= LVDS_CLK < 112.5 MHz in sn65dsi83_get_lvds_range()
320 * 100 - 112.5 MHz <= LVDS_CLK < 137.5 MHz in sn65dsi83_get_lvds_range()
321 * 101 - 137.5 MHz <= LVDS_CLK <= 154 MHz in sn65dsi83_get_lvds_range()
328 int mode_clock = mode->clock; in sn65dsi83_get_lvds_range()
330 if (ctx->lvds_dual_link) in sn65dsi83_get_lvds_range()
333 return (mode_clock - 12500) / 25000; in sn65dsi83_get_lvds_range()
341 * 0x00 through 0x07 - Reserved in sn65dsi83_get_dsi_range()
342 * 0x08 - 40 <= DSI_CLK < 45 MHz in sn65dsi83_get_dsi_range()
343 * 0x09 - 45 <= DSI_CLK < 50 MHz in sn65dsi83_get_dsi_range()
345 * 0x63 - 495 <= DSI_CLK < 500 MHz in sn65dsi83_get_dsi_range()
346 * 0x64 - 500 MHz in sn65dsi83_get_dsi_range()
347 * 0x65 through 0xFF - Reserved in sn65dsi83_get_dsi_range()
348 * which is DSI clock in 5 MHz steps, clamped to 40..500 MHz. in sn65dsi83_get_dsi_range()
349 * The DSI clock are calculated as: in sn65dsi83_get_dsi_range()
353 return DIV_ROUND_UP(clamp((unsigned int)mode->clock * in sn65dsi83_get_dsi_range()
354 mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) / in sn65dsi83_get_dsi_range()
355 ctx->dsi->lanes / 2, 40000U, 500000U), 5000U); in sn65dsi83_get_dsi_range()
360 /* The divider is (DSI_CLK / LVDS_CLK) - 1, which really is: */ in sn65dsi83_get_dsi_div()
361 unsigned int dsi_div = mipi_dsi_pixel_format_to_bpp(ctx->dsi->format); in sn65dsi83_get_dsi_div()
363 dsi_div /= ctx->dsi->lanes; in sn65dsi83_get_dsi_div()
365 if (!ctx->lvds_dual_link) in sn65dsi83_get_dsi_div()
368 return dsi_div - 1; in sn65dsi83_get_dsi_div()
373 struct drm_device *dev = sn65dsi83->bridge.dev; in sn65dsi83_reset_pipe()
390 if (!sn65dsi83->bridge.encoder->crtc) { in sn65dsi83_reset_pipe()
392 * No CRTC attached -> No CRTC active outputs to reset in sn65dsi83_reset_pipe()
400 dev_warn(sn65dsi83->dev, "reset the pipe\n"); in sn65dsi83_reset_pipe()
402 err = drm_atomic_helper_reset_crtc(sn65dsi83->bridge.encoder->crtc, &ctx); in sn65dsi83_reset_pipe()
418 dev_err(ctx->dev, "reset pipe failed %pe\n", ERR_PTR(ret)); in sn65dsi83_reset_work()
421 if (ctx->irq) in sn65dsi83_reset_work()
422 enable_irq(ctx->irq); in sn65dsi83_reset_work()
432 * - the bridge doesn't answer in sn65dsi83_handle_errors()
433 * - the bridge signals an error in sn65dsi83_handle_errors()
436 ret = regmap_read(ctx->regmap, REG_IRQ_STAT, &irq_stat); in sn65dsi83_handle_errors()
444 if (ctx->irq) in sn65dsi83_handle_errors()
445 disable_irq_nosync(ctx->irq); in sn65dsi83_handle_errors()
447 schedule_work(&ctx->reset_work); in sn65dsi83_handle_errors()
458 schedule_delayed_work(&ctx->monitor_work, msecs_to_jiffies(1000)); in sn65dsi83_monitor_work()
463 schedule_delayed_work(&ctx->monitor_work, msecs_to_jiffies(1000)); in sn65dsi83_monitor_start()
468 cancel_delayed_work_sync(&ctx->monitor_work); in sn65dsi83_monitor_stop()
487 ret = regulator_enable(ctx->vcc); in sn65dsi83_atomic_pre_enable()
489 dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret); in sn65dsi83_atomic_pre_enable()
494 gpiod_set_value_cansleep(ctx->enable_gpio, 1); in sn65dsi83_atomic_pre_enable()
500 switch (bridge_state->output_bus_cfg.format) { in sn65dsi83_atomic_pre_enable()
521 dev_warn(ctx->dev, in sn65dsi83_atomic_pre_enable()
523 bridge_state->output_bus_cfg.format); in sn65dsi83_atomic_pre_enable()
532 bridge->encoder); in sn65dsi83_atomic_pre_enable()
533 crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; in sn65dsi83_atomic_pre_enable()
535 mode = &crtc_state->adjusted_mode; in sn65dsi83_atomic_pre_enable()
538 regmap_write(ctx->regmap, REG_RC_RESET, 0x00); in sn65dsi83_atomic_pre_enable()
539 regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00); in sn65dsi83_atomic_pre_enable()
541 /* Reference clock derived from DSI link clock. */ in sn65dsi83_atomic_pre_enable()
542 regmap_write(ctx->regmap, REG_RC_LVDS_PLL, in sn65dsi83_atomic_pre_enable()
545 regmap_write(ctx->regmap, REG_DSI_CLK, in sn65dsi83_atomic_pre_enable()
547 regmap_write(ctx->regmap, REG_RC_DSI_CLK, in sn65dsi83_atomic_pre_enable()
550 /* Set number of DSI lanes and LVDS link config. */ in sn65dsi83_atomic_pre_enable()
551 regmap_write(ctx->regmap, REG_DSI_LANE, in sn65dsi83_atomic_pre_enable()
553 REG_DSI_LANE_CHA_DSI_LANES(~(ctx->dsi->lanes - 1)) | in sn65dsi83_atomic_pre_enable()
554 /* CHB is DSI85-only, set to default on DSI83/DSI84 */ in sn65dsi83_atomic_pre_enable()
557 regmap_write(ctx->regmap, REG_DSI_EQ, 0x00); in sn65dsi83_atomic_pre_enable()
559 /* Set up sync signal polarity. */ in sn65dsi83_atomic_pre_enable()
560 val = (mode->flags & DRM_MODE_FLAG_NHSYNC ? in sn65dsi83_atomic_pre_enable()
562 (mode->flags & DRM_MODE_FLAG_NVSYNC ? in sn65dsi83_atomic_pre_enable()
564 val |= bridge_state->output_bus_cfg.flags & DRM_BUS_FLAG_DE_LOW ? in sn65dsi83_atomic_pre_enable()
567 /* Set up bits-per-pixel, 18bpp or 24bpp. */ in sn65dsi83_atomic_pre_enable()
570 if (ctx->lvds_dual_link) in sn65dsi83_atomic_pre_enable()
577 if (ctx->lvds_dual_link) in sn65dsi83_atomic_pre_enable()
582 if (!ctx->lvds_dual_link) in sn65dsi83_atomic_pre_enable()
585 regmap_write(ctx->regmap, REG_LVDS_FMT, val); in sn65dsi83_atomic_pre_enable()
586 regmap_write(ctx->regmap, REG_LVDS_VCOM, in sn65dsi83_atomic_pre_enable()
587 REG_LVDS_VCOM_CHA_LVDS_VOD_SWING(ctx->lvds_vod_swing_conf[CHANNEL_A]) | in sn65dsi83_atomic_pre_enable()
588 REG_LVDS_VCOM_CHB_LVDS_VOD_SWING(ctx->lvds_vod_swing_conf[CHANNEL_B])); in sn65dsi83_atomic_pre_enable()
589 regmap_write(ctx->regmap, REG_LVDS_LANE, in sn65dsi83_atomic_pre_enable()
590 (ctx->lvds_dual_link_even_odd_swap ? in sn65dsi83_atomic_pre_enable()
592 (ctx->lvds_term_conf[CHANNEL_A] ? in sn65dsi83_atomic_pre_enable()
594 (ctx->lvds_term_conf[CHANNEL_B] ? in sn65dsi83_atomic_pre_enable()
596 regmap_write(ctx->regmap, REG_LVDS_CM, 0x00); in sn65dsi83_atomic_pre_enable()
598 le16val = cpu_to_le16(mode->hdisplay); in sn65dsi83_atomic_pre_enable()
599 regmap_bulk_write(ctx->regmap, REG_VID_CHA_ACTIVE_LINE_LENGTH_LOW, in sn65dsi83_atomic_pre_enable()
601 le16val = cpu_to_le16(mode->vdisplay); in sn65dsi83_atomic_pre_enable()
602 regmap_bulk_write(ctx->regmap, REG_VID_CHA_VERTICAL_DISPLAY_SIZE_LOW, in sn65dsi83_atomic_pre_enable()
606 regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &le16val, 2); in sn65dsi83_atomic_pre_enable()
607 le16val = cpu_to_le16(mode->hsync_end - mode->hsync_start); in sn65dsi83_atomic_pre_enable()
608 regmap_bulk_write(ctx->regmap, REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW, in sn65dsi83_atomic_pre_enable()
610 le16val = cpu_to_le16(mode->vsync_end - mode->vsync_start); in sn65dsi83_atomic_pre_enable()
611 regmap_bulk_write(ctx->regmap, REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW, in sn65dsi83_atomic_pre_enable()
613 regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_BACK_PORCH, in sn65dsi83_atomic_pre_enable()
614 mode->htotal - mode->hsync_end); in sn65dsi83_atomic_pre_enable()
615 regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_BACK_PORCH, in sn65dsi83_atomic_pre_enable()
616 mode->vtotal - mode->vsync_end); in sn65dsi83_atomic_pre_enable()
617 regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_FRONT_PORCH, in sn65dsi83_atomic_pre_enable()
618 mode->hsync_start - mode->hdisplay); in sn65dsi83_atomic_pre_enable()
619 regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_FRONT_PORCH, in sn65dsi83_atomic_pre_enable()
620 mode->vsync_start - mode->vdisplay); in sn65dsi83_atomic_pre_enable()
621 regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN, 0x00); in sn65dsi83_atomic_pre_enable()
624 regmap_write(ctx->regmap, REG_RC_PLL_EN, REG_RC_PLL_EN_PLL_EN); in sn65dsi83_atomic_pre_enable()
626 ret = regmap_read_poll_timeout(ctx->regmap, REG_RC_LVDS_PLL, pval, in sn65dsi83_atomic_pre_enable()
630 dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret); in sn65dsi83_atomic_pre_enable()
632 regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00); in sn65dsi83_atomic_pre_enable()
637 regmap_write(ctx->regmap, REG_RC_RESET, REG_RC_RESET_SOFT_RESET); in sn65dsi83_atomic_pre_enable()
650 regmap_read(ctx->regmap, REG_IRQ_STAT, &pval); in sn65dsi83_atomic_enable()
651 regmap_write(ctx->regmap, REG_IRQ_STAT, pval); in sn65dsi83_atomic_enable()
655 regmap_read(ctx->regmap, REG_IRQ_STAT, &pval); in sn65dsi83_atomic_enable()
657 dev_err(ctx->dev, "Unexpected link status 0x%02x\n", pval); in sn65dsi83_atomic_enable()
659 if (ctx->irq) { in sn65dsi83_atomic_enable()
661 regmap_write(ctx->regmap, REG_IRQ_GLOBAL, REG_IRQ_GLOBAL_IRQ_EN); in sn65dsi83_atomic_enable()
662 regmap_write(ctx->regmap, REG_IRQ_EN, 0xff); in sn65dsi83_atomic_enable()
675 if (ctx->irq) { in sn65dsi83_atomic_disable()
677 regmap_write(ctx->regmap, REG_IRQ_EN, 0x0); in sn65dsi83_atomic_disable()
678 regmap_write(ctx->regmap, REG_IRQ_GLOBAL, 0x0); in sn65dsi83_atomic_disable()
685 gpiod_set_value_cansleep(ctx->enable_gpio, 0); in sn65dsi83_atomic_disable()
688 ret = regulator_disable(ctx->vcc); in sn65dsi83_atomic_disable()
690 dev_err(ctx->dev, "Failed to disable vcc: %d\n", ret); in sn65dsi83_atomic_disable()
692 regcache_mark_dirty(ctx->regmap); in sn65dsi83_atomic_disable()
701 if (mode->clock < 25000) in sn65dsi83_mode_valid()
703 if (mode->clock > 154000) in sn65dsi83_mode_valid()
728 /* This is the DSI-end bus format */ in sn65dsi83_atomic_get_input_bus_fmts()
763 return -EINVAL; in sn65dsi83_select_lvds_vod_swing()
768 struct device *dev = ctx->dev; in sn65dsi83_parse_lvds_endpoint()
786 endpoint = of_graph_get_endpoint_by_regs(dev->of_node, endpoint_reg, -1); in sn65dsi83_parse_lvds_endpoint()
788 of_property_read_u32(endpoint, "ti,lvds-termination-ohms", &lvds_term); in sn65dsi83_parse_lvds_endpoint()
790 ctx->lvds_term_conf[channel] = OHM_100; in sn65dsi83_parse_lvds_endpoint()
792 ctx->lvds_term_conf[channel] = OHM_200; in sn65dsi83_parse_lvds_endpoint()
794 ret = -EINVAL; in sn65dsi83_parse_lvds_endpoint()
798 ret_data = of_property_read_u32_array(endpoint, "ti,lvds-vod-swing-data-microvolt", in sn65dsi83_parse_lvds_endpoint()
800 if (ret_data != 0 && ret_data != -EINVAL) { in sn65dsi83_parse_lvds_endpoint()
805 ret_clock = of_property_read_u32_array(endpoint, "ti,lvds-vod-swing-clock-microvolt", in sn65dsi83_parse_lvds_endpoint()
807 if (ret_clock != 0 && ret_clock != -EINVAL) { in sn65dsi83_parse_lvds_endpoint()
813 if (ret_data == -EINVAL && ret_clock == -EINVAL) in sn65dsi83_parse_lvds_endpoint()
819 lvds_vod_swing_clk, ctx->lvds_term_conf[channel]); in sn65dsi83_parse_lvds_endpoint()
826 ctx->lvds_vod_swing_conf[channel] = lvds_vod_swing_conf; in sn65dsi83_parse_lvds_endpoint()
836 struct device *dev = ctx->dev; in sn65dsi83_parse_dt()
847 ctx->lvds_dual_link = false; in sn65dsi83_parse_dt()
848 ctx->lvds_dual_link_even_odd_swap = false; in sn65dsi83_parse_dt()
853 port2 = of_graph_get_port_by_id(dev->of_node, 2); in sn65dsi83_parse_dt()
854 port3 = of_graph_get_port_by_id(dev->of_node, 3); in sn65dsi83_parse_dt()
860 ctx->lvds_dual_link = true; in sn65dsi83_parse_dt()
862 ctx->lvds_dual_link_even_odd_swap = false; in sn65dsi83_parse_dt()
864 ctx->lvds_dual_link = true; in sn65dsi83_parse_dt()
866 ctx->lvds_dual_link_even_odd_swap = true; in sn65dsi83_parse_dt()
870 panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0); in sn65dsi83_parse_dt()
874 ctx->panel_bridge = panel_bridge; in sn65dsi83_parse_dt()
876 ctx->vcc = devm_regulator_get(dev, "vcc"); in sn65dsi83_parse_dt()
877 if (IS_ERR(ctx->vcc)) in sn65dsi83_parse_dt()
878 return dev_err_probe(dev, PTR_ERR(ctx->vcc), in sn65dsi83_parse_dt()
886 struct device *dev = ctx->dev; in sn65dsi83_host_attach()
889 struct mipi_dsi_device *dsi; in sn65dsi83_host_attach() local
898 endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); in sn65dsi83_host_attach()
906 return -EPROBE_DEFER; in sn65dsi83_host_attach()
911 dsi = devm_mipi_dsi_device_register_full(dev, host, &info); in sn65dsi83_host_attach()
912 if (IS_ERR(dsi)) in sn65dsi83_host_attach()
913 return dev_err_probe(dev, PTR_ERR(dsi), in sn65dsi83_host_attach()
914 "failed to create dsi device\n"); in sn65dsi83_host_attach()
916 ctx->dsi = dsi; in sn65dsi83_host_attach()
918 dsi->lanes = dsi_lanes; in sn65dsi83_host_attach()
919 dsi->format = MIPI_DSI_FMT_RGB888; in sn65dsi83_host_attach()
920 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | in sn65dsi83_host_attach()
924 ret = devm_mipi_dsi_attach(dev, dsi); in sn65dsi83_host_attach()
926 dev_err(dev, "failed to attach dsi to host: %d\n", ret); in sn65dsi83_host_attach()
944 struct device *dev = &client->dev; in sn65dsi83_probe()
951 return -ENOMEM; in sn65dsi83_probe()
953 ctx->dev = dev; in sn65dsi83_probe()
954 INIT_WORK(&ctx->reset_work, sn65dsi83_reset_work); in sn65dsi83_probe()
955 INIT_DELAYED_WORK(&ctx->monitor_work, sn65dsi83_monitor_work); in sn65dsi83_probe()
957 if (dev->of_node) { in sn65dsi83_probe()
961 model = id->driver_data; in sn65dsi83_probe()
965 ctx->enable_gpio = devm_gpiod_get_optional(ctx->dev, "enable", in sn65dsi83_probe()
967 if (IS_ERR(ctx->enable_gpio)) in sn65dsi83_probe()
968 return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "failed to get enable GPIO\n"); in sn65dsi83_probe()
976 ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config); in sn65dsi83_probe()
977 if (IS_ERR(ctx->regmap)) in sn65dsi83_probe()
978 return dev_err_probe(dev, PTR_ERR(ctx->regmap), "failed to get regmap\n"); in sn65dsi83_probe()
980 if (client->irq) { in sn65dsi83_probe()
981 ctx->irq = client->irq; in sn65dsi83_probe()
982 ret = devm_request_threaded_irq(ctx->dev, ctx->irq, NULL, sn65dsi83_irq, in sn65dsi83_probe()
983 IRQF_ONESHOT, dev_name(ctx->dev), ctx); in sn65dsi83_probe()
991 ctx->bridge.funcs = &sn65dsi83_funcs; in sn65dsi83_probe()
992 ctx->bridge.of_node = dev->of_node; in sn65dsi83_probe()
993 ctx->bridge.pre_enable_prev_first = true; in sn65dsi83_probe()
994 ctx->bridge.type = DRM_MODE_CONNECTOR_LVDS; in sn65dsi83_probe()
995 drm_bridge_add(&ctx->bridge); in sn65dsi83_probe()
999 dev_err_probe(dev, ret, "failed to attach DSI host\n"); in sn65dsi83_probe()
1006 drm_bridge_remove(&ctx->bridge); in sn65dsi83_probe()
1014 drm_bridge_remove(&ctx->bridge); in sn65dsi83_remove()
1043 MODULE_DESCRIPTION("TI SN65DSI83 DSI to LVDS bridge driver");