Lines Matching +full:lvds +full:- +full:4 +full:bits
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
28 #include <linux/bits.h>
32 #include <linux/media-bus-format.h>
63 #define REG_DSI_LANE_LEFT_RIGHT_PIXELS BIT(7) /* DSI85-only */
64 #define REG_DSI_LANE_DSI_CHANNEL_MODE_DUAL 0 /* DSI85-only */
65 #define REG_DSI_LANE_DSI_CHANNEL_MODE_2SINGLE BIT(6) /* DSI85-only */
75 /* LVDS registers */
80 #define REG_LVDS_FMT_LVDS_LINK_CFG BIT(4) /* 0:AB 1:A-only */
87 #define REG_LVDS_VCOM_CHB_LVDS_VOCM BIT(4)
93 #define REG_LVDS_LANE_CHB_REVERSE_LVDS BIT(4)
97 #define REG_LVDS_CM_CHA_LVDS_CM_ADJUST(n) (((n) & 0x3) << 4)
122 #define REG_IRQ_EN_CHA_COR_ECC_ERR_EN BIT(4)
130 #define REG_IRQ_STAT_CHA_COR_ECC_ERR BIT(4)
252 static const int lvds_vod_swing_data_table[2][4][2] = {
267 static const int lvds_vod_swing_clock_table[2][4][2] = {
292 return drm_bridge_attach(bridge->encoder, ctx->panel_bridge, in sn65dsi83_attach()
293 &ctx->bridge, flags); in sn65dsi83_attach()
300 if (!ctx->dsi) in sn65dsi83_detach()
303 ctx->dsi = NULL; in sn65dsi83_detach()
311 * 000 - 25 MHz <= LVDS_CLK < 37.5 MHz in sn65dsi83_get_lvds_range()
312 * 001 - 37.5 MHz <= LVDS_CLK < 62.5 MHz in sn65dsi83_get_lvds_range()
313 * 010 - 62.5 MHz <= LVDS_CLK < 87.5 MHz in sn65dsi83_get_lvds_range()
314 * 011 - 87.5 MHz <= LVDS_CLK < 112.5 MHz in sn65dsi83_get_lvds_range()
315 * 100 - 112.5 MHz <= LVDS_CLK < 137.5 MHz in sn65dsi83_get_lvds_range()
316 * 101 - 137.5 MHz <= LVDS_CLK <= 154 MHz in sn65dsi83_get_lvds_range()
323 int mode_clock = mode->clock; in sn65dsi83_get_lvds_range()
325 if (ctx->lvds_dual_link) in sn65dsi83_get_lvds_range()
328 return (mode_clock - 12500) / 25000; in sn65dsi83_get_lvds_range()
336 * 0x00 through 0x07 - Reserved in sn65dsi83_get_dsi_range()
337 * 0x08 - 40 <= DSI_CLK < 45 MHz in sn65dsi83_get_dsi_range()
338 * 0x09 - 45 <= DSI_CLK < 50 MHz in sn65dsi83_get_dsi_range()
340 * 0x63 - 495 <= DSI_CLK < 500 MHz in sn65dsi83_get_dsi_range()
341 * 0x64 - 500 MHz in sn65dsi83_get_dsi_range()
342 * 0x65 through 0xFF - Reserved in sn65dsi83_get_dsi_range()
348 return DIV_ROUND_UP(clamp((unsigned int)mode->clock * in sn65dsi83_get_dsi_range()
349 mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) / in sn65dsi83_get_dsi_range()
350 ctx->dsi->lanes / 2, 40000U, 500000U), 5000U); in sn65dsi83_get_dsi_range()
355 /* The divider is (DSI_CLK / LVDS_CLK) - 1, which really is: */ in sn65dsi83_get_dsi_div()
356 unsigned int dsi_div = mipi_dsi_pixel_format_to_bpp(ctx->dsi->format); in sn65dsi83_get_dsi_div()
358 dsi_div /= ctx->dsi->lanes; in sn65dsi83_get_dsi_div()
360 if (!ctx->lvds_dual_link) in sn65dsi83_get_dsi_div()
363 return dsi_div - 1; in sn65dsi83_get_dsi_div()
370 struct drm_atomic_state *state = old_bridge_state->base.state; in sn65dsi83_atomic_pre_enable()
383 ret = regulator_enable(ctx->vcc); in sn65dsi83_atomic_pre_enable()
385 dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret); in sn65dsi83_atomic_pre_enable()
390 gpiod_set_value_cansleep(ctx->enable_gpio, 1); in sn65dsi83_atomic_pre_enable()
393 /* Get the LVDS format from the bridge state. */ in sn65dsi83_atomic_pre_enable()
396 switch (bridge_state->output_bus_cfg.format) { in sn65dsi83_atomic_pre_enable()
412 * LVDS bus pixel format, use SPWG24 default in sn65dsi83_atomic_pre_enable()
417 dev_warn(ctx->dev, in sn65dsi83_atomic_pre_enable()
418 …"Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n", in sn65dsi83_atomic_pre_enable()
419 bridge_state->output_bus_cfg.format); in sn65dsi83_atomic_pre_enable()
428 bridge->encoder); in sn65dsi83_atomic_pre_enable()
429 crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; in sn65dsi83_atomic_pre_enable()
431 mode = &crtc_state->adjusted_mode; in sn65dsi83_atomic_pre_enable()
434 regmap_write(ctx->regmap, REG_RC_RESET, 0x00); in sn65dsi83_atomic_pre_enable()
435 regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00); in sn65dsi83_atomic_pre_enable()
438 regmap_write(ctx->regmap, REG_RC_LVDS_PLL, in sn65dsi83_atomic_pre_enable()
441 regmap_write(ctx->regmap, REG_DSI_CLK, in sn65dsi83_atomic_pre_enable()
443 regmap_write(ctx->regmap, REG_RC_DSI_CLK, in sn65dsi83_atomic_pre_enable()
446 /* Set number of DSI lanes and LVDS link config. */ in sn65dsi83_atomic_pre_enable()
447 regmap_write(ctx->regmap, REG_DSI_LANE, in sn65dsi83_atomic_pre_enable()
449 REG_DSI_LANE_CHA_DSI_LANES(~(ctx->dsi->lanes - 1)) | in sn65dsi83_atomic_pre_enable()
450 /* CHB is DSI85-only, set to default on DSI83/DSI84 */ in sn65dsi83_atomic_pre_enable()
453 regmap_write(ctx->regmap, REG_DSI_EQ, 0x00); in sn65dsi83_atomic_pre_enable()
456 val = (mode->flags & DRM_MODE_FLAG_NHSYNC ? in sn65dsi83_atomic_pre_enable()
458 (mode->flags & DRM_MODE_FLAG_NVSYNC ? in sn65dsi83_atomic_pre_enable()
461 /* Set up bits-per-pixel, 18bpp or 24bpp. */ in sn65dsi83_atomic_pre_enable()
464 if (ctx->lvds_dual_link) in sn65dsi83_atomic_pre_enable()
468 /* Set up LVDS format, JEIDA/Format 1 or SPWG/Format 2 */ in sn65dsi83_atomic_pre_enable()
471 if (ctx->lvds_dual_link) in sn65dsi83_atomic_pre_enable()
475 /* Set up LVDS output config (DSI84,DSI85) */ in sn65dsi83_atomic_pre_enable()
476 if (!ctx->lvds_dual_link) in sn65dsi83_atomic_pre_enable()
479 regmap_write(ctx->regmap, REG_LVDS_FMT, val); in sn65dsi83_atomic_pre_enable()
480 regmap_write(ctx->regmap, REG_LVDS_VCOM, in sn65dsi83_atomic_pre_enable()
481 REG_LVDS_VCOM_CHA_LVDS_VOD_SWING(ctx->lvds_vod_swing_conf[CHANNEL_A]) | in sn65dsi83_atomic_pre_enable()
482 REG_LVDS_VCOM_CHB_LVDS_VOD_SWING(ctx->lvds_vod_swing_conf[CHANNEL_B])); in sn65dsi83_atomic_pre_enable()
483 regmap_write(ctx->regmap, REG_LVDS_LANE, in sn65dsi83_atomic_pre_enable()
484 (ctx->lvds_dual_link_even_odd_swap ? in sn65dsi83_atomic_pre_enable()
486 (ctx->lvds_term_conf[CHANNEL_A] ? in sn65dsi83_atomic_pre_enable()
488 (ctx->lvds_term_conf[CHANNEL_B] ? in sn65dsi83_atomic_pre_enable()
490 regmap_write(ctx->regmap, REG_LVDS_CM, 0x00); in sn65dsi83_atomic_pre_enable()
492 le16val = cpu_to_le16(mode->hdisplay); in sn65dsi83_atomic_pre_enable()
493 regmap_bulk_write(ctx->regmap, REG_VID_CHA_ACTIVE_LINE_LENGTH_LOW, in sn65dsi83_atomic_pre_enable()
495 le16val = cpu_to_le16(mode->vdisplay); in sn65dsi83_atomic_pre_enable()
496 regmap_bulk_write(ctx->regmap, REG_VID_CHA_VERTICAL_DISPLAY_SIZE_LOW, in sn65dsi83_atomic_pre_enable()
500 regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &le16val, 2); in sn65dsi83_atomic_pre_enable()
501 le16val = cpu_to_le16(mode->hsync_end - mode->hsync_start); in sn65dsi83_atomic_pre_enable()
502 regmap_bulk_write(ctx->regmap, REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW, in sn65dsi83_atomic_pre_enable()
504 le16val = cpu_to_le16(mode->vsync_end - mode->vsync_start); in sn65dsi83_atomic_pre_enable()
505 regmap_bulk_write(ctx->regmap, REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW, in sn65dsi83_atomic_pre_enable()
507 regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_BACK_PORCH, in sn65dsi83_atomic_pre_enable()
508 mode->htotal - mode->hsync_end); in sn65dsi83_atomic_pre_enable()
509 regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_BACK_PORCH, in sn65dsi83_atomic_pre_enable()
510 mode->vtotal - mode->vsync_end); in sn65dsi83_atomic_pre_enable()
511 regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_FRONT_PORCH, in sn65dsi83_atomic_pre_enable()
512 mode->hsync_start - mode->hdisplay); in sn65dsi83_atomic_pre_enable()
513 regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_FRONT_PORCH, in sn65dsi83_atomic_pre_enable()
514 mode->vsync_start - mode->vdisplay); in sn65dsi83_atomic_pre_enable()
515 regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN, 0x00); in sn65dsi83_atomic_pre_enable()
518 regmap_write(ctx->regmap, REG_RC_PLL_EN, REG_RC_PLL_EN_PLL_EN); in sn65dsi83_atomic_pre_enable()
520 ret = regmap_read_poll_timeout(ctx->regmap, REG_RC_LVDS_PLL, pval, in sn65dsi83_atomic_pre_enable()
524 dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret); in sn65dsi83_atomic_pre_enable()
526 regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00); in sn65dsi83_atomic_pre_enable()
531 regmap_write(ctx->regmap, REG_RC_RESET, REG_RC_RESET_SOFT_RESET); in sn65dsi83_atomic_pre_enable()
544 regmap_read(ctx->regmap, REG_IRQ_STAT, &pval); in sn65dsi83_atomic_enable()
545 regmap_write(ctx->regmap, REG_IRQ_STAT, pval); in sn65dsi83_atomic_enable()
549 regmap_read(ctx->regmap, REG_IRQ_STAT, &pval); in sn65dsi83_atomic_enable()
551 dev_err(ctx->dev, "Unexpected link status 0x%02x\n", pval); in sn65dsi83_atomic_enable()
561 gpiod_set_value_cansleep(ctx->enable_gpio, 0); in sn65dsi83_atomic_disable()
564 ret = regulator_disable(ctx->vcc); in sn65dsi83_atomic_disable()
566 dev_err(ctx->dev, "Failed to disable vcc: %d\n", ret); in sn65dsi83_atomic_disable()
568 regcache_mark_dirty(ctx->regmap); in sn65dsi83_atomic_disable()
576 /* LVDS output clock range 25..154 MHz */ in sn65dsi83_mode_valid()
577 if (mode->clock < 25000) in sn65dsi83_mode_valid()
579 if (mode->clock > 154000) in sn65dsi83_mode_valid()
604 /* This is the DSI-end bus format */ in sn65dsi83_atomic_get_input_bus_fmts()
639 return -EINVAL; in sn65dsi83_select_lvds_vod_swing()
644 struct device *dev = ctx->dev; in sn65dsi83_parse_lvds_endpoint()
662 endpoint = of_graph_get_endpoint_by_regs(dev->of_node, endpoint_reg, -1); in sn65dsi83_parse_lvds_endpoint()
664 of_property_read_u32(endpoint, "ti,lvds-termination-ohms", &lvds_term); in sn65dsi83_parse_lvds_endpoint()
666 ctx->lvds_term_conf[channel] = OHM_100; in sn65dsi83_parse_lvds_endpoint()
668 ctx->lvds_term_conf[channel] = OHM_200; in sn65dsi83_parse_lvds_endpoint()
670 ret = -EINVAL; in sn65dsi83_parse_lvds_endpoint()
674 ret_data = of_property_read_u32_array(endpoint, "ti,lvds-vod-swing-data-microvolt", in sn65dsi83_parse_lvds_endpoint()
676 if (ret_data != 0 && ret_data != -EINVAL) { in sn65dsi83_parse_lvds_endpoint()
681 ret_clock = of_property_read_u32_array(endpoint, "ti,lvds-vod-swing-clock-microvolt", in sn65dsi83_parse_lvds_endpoint()
683 if (ret_clock != 0 && ret_clock != -EINVAL) { in sn65dsi83_parse_lvds_endpoint()
689 if (ret_data == -EINVAL && ret_clock == -EINVAL) in sn65dsi83_parse_lvds_endpoint()
695 lvds_vod_swing_clk, ctx->lvds_term_conf[channel]); in sn65dsi83_parse_lvds_endpoint()
702 ctx->lvds_vod_swing_conf[channel] = lvds_vod_swing_conf; in sn65dsi83_parse_lvds_endpoint()
712 struct device *dev = ctx->dev; in sn65dsi83_parse_dt()
723 ctx->lvds_dual_link = false; in sn65dsi83_parse_dt()
724 ctx->lvds_dual_link_even_odd_swap = false; in sn65dsi83_parse_dt()
729 port2 = of_graph_get_port_by_id(dev->of_node, 2); in sn65dsi83_parse_dt()
730 port3 = of_graph_get_port_by_id(dev->of_node, 3); in sn65dsi83_parse_dt()
736 ctx->lvds_dual_link = true; in sn65dsi83_parse_dt()
737 /* Odd pixels to LVDS Channel A, even pixels to B */ in sn65dsi83_parse_dt()
738 ctx->lvds_dual_link_even_odd_swap = false; in sn65dsi83_parse_dt()
740 ctx->lvds_dual_link = true; in sn65dsi83_parse_dt()
741 /* Even pixels to LVDS Channel A, odd pixels to B */ in sn65dsi83_parse_dt()
742 ctx->lvds_dual_link_even_odd_swap = true; in sn65dsi83_parse_dt()
746 panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0); in sn65dsi83_parse_dt()
750 ctx->panel_bridge = panel_bridge; in sn65dsi83_parse_dt()
752 ctx->vcc = devm_regulator_get(dev, "vcc"); in sn65dsi83_parse_dt()
753 if (IS_ERR(ctx->vcc)) in sn65dsi83_parse_dt()
754 return dev_err_probe(dev, PTR_ERR(ctx->vcc), in sn65dsi83_parse_dt()
762 struct device *dev = ctx->dev; in sn65dsi83_host_attach()
774 endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); in sn65dsi83_host_attach()
775 dsi_lanes = drm_of_get_data_lanes_count(endpoint, 1, 4); in sn65dsi83_host_attach()
782 return -EPROBE_DEFER; in sn65dsi83_host_attach()
792 ctx->dsi = dsi; in sn65dsi83_host_attach()
794 dsi->lanes = dsi_lanes; in sn65dsi83_host_attach()
795 dsi->format = MIPI_DSI_FMT_RGB888; in sn65dsi83_host_attach()
796 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | in sn65dsi83_host_attach()
812 struct device *dev = &client->dev; in sn65dsi83_probe()
819 return -ENOMEM; in sn65dsi83_probe()
821 ctx->dev = dev; in sn65dsi83_probe()
823 if (dev->of_node) { in sn65dsi83_probe()
827 model = id->driver_data; in sn65dsi83_probe()
831 ctx->enable_gpio = devm_gpiod_get_optional(ctx->dev, "enable", in sn65dsi83_probe()
833 if (IS_ERR(ctx->enable_gpio)) in sn65dsi83_probe()
834 return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "failed to get enable GPIO\n"); in sn65dsi83_probe()
842 ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config); in sn65dsi83_probe()
843 if (IS_ERR(ctx->regmap)) in sn65dsi83_probe()
844 return dev_err_probe(dev, PTR_ERR(ctx->regmap), "failed to get regmap\n"); in sn65dsi83_probe()
849 ctx->bridge.funcs = &sn65dsi83_funcs; in sn65dsi83_probe()
850 ctx->bridge.of_node = dev->of_node; in sn65dsi83_probe()
851 ctx->bridge.pre_enable_prev_first = true; in sn65dsi83_probe()
852 drm_bridge_add(&ctx->bridge); in sn65dsi83_probe()
863 drm_bridge_remove(&ctx->bridge); in sn65dsi83_probe()
871 drm_bridge_remove(&ctx->bridge); in sn65dsi83_remove()
900 MODULE_DESCRIPTION("TI SN65DSI83 DSI to LVDS bridge driver");