Lines Matching +full:dual +full:- +full:lvds +full:- +full:odd +full:- +full:pixels
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 #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 */
250 return drm_bridge_attach(bridge->encoder, ctx->panel_bridge, in sn65dsi83_attach()
251 &ctx->bridge, flags); in sn65dsi83_attach()
258 if (!ctx->dsi) in sn65dsi83_detach()
261 ctx->dsi = NULL; in sn65dsi83_detach()
269 * 000 - 25 MHz <= LVDS_CLK < 37.5 MHz in sn65dsi83_get_lvds_range()
270 * 001 - 37.5 MHz <= LVDS_CLK < 62.5 MHz in sn65dsi83_get_lvds_range()
271 * 010 - 62.5 MHz <= LVDS_CLK < 87.5 MHz in sn65dsi83_get_lvds_range()
272 * 011 - 87.5 MHz <= LVDS_CLK < 112.5 MHz in sn65dsi83_get_lvds_range()
273 * 100 - 112.5 MHz <= LVDS_CLK < 137.5 MHz in sn65dsi83_get_lvds_range()
274 * 101 - 137.5 MHz <= LVDS_CLK <= 154 MHz in sn65dsi83_get_lvds_range()
281 int mode_clock = mode->clock; in sn65dsi83_get_lvds_range()
283 if (ctx->lvds_dual_link) in sn65dsi83_get_lvds_range()
286 return (mode_clock - 12500) / 25000; in sn65dsi83_get_lvds_range()
294 * 0x00 through 0x07 - Reserved in sn65dsi83_get_dsi_range()
295 * 0x08 - 40 <= DSI_CLK < 45 MHz in sn65dsi83_get_dsi_range()
296 * 0x09 - 45 <= DSI_CLK < 50 MHz in sn65dsi83_get_dsi_range()
298 * 0x63 - 495 <= DSI_CLK < 500 MHz in sn65dsi83_get_dsi_range()
299 * 0x64 - 500 MHz in sn65dsi83_get_dsi_range()
300 * 0x65 through 0xFF - Reserved in sn65dsi83_get_dsi_range()
306 return DIV_ROUND_UP(clamp((unsigned int)mode->clock * in sn65dsi83_get_dsi_range()
307 mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) / in sn65dsi83_get_dsi_range()
308 ctx->dsi->lanes / 2, 40000U, 500000U), 5000U); in sn65dsi83_get_dsi_range()
313 /* The divider is (DSI_CLK / LVDS_CLK) - 1, which really is: */ in sn65dsi83_get_dsi_div()
314 unsigned int dsi_div = mipi_dsi_pixel_format_to_bpp(ctx->dsi->format); in sn65dsi83_get_dsi_div()
316 dsi_div /= ctx->dsi->lanes; in sn65dsi83_get_dsi_div()
318 if (!ctx->lvds_dual_link) in sn65dsi83_get_dsi_div()
321 return dsi_div - 1; in sn65dsi83_get_dsi_div()
328 struct drm_atomic_state *state = old_bridge_state->base.state; in sn65dsi83_atomic_pre_enable()
341 ret = regulator_enable(ctx->vcc); in sn65dsi83_atomic_pre_enable()
343 dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret); in sn65dsi83_atomic_pre_enable()
348 gpiod_set_value_cansleep(ctx->enable_gpio, 1); in sn65dsi83_atomic_pre_enable()
351 /* Get the LVDS format from the bridge state. */ in sn65dsi83_atomic_pre_enable()
354 switch (bridge_state->output_bus_cfg.format) { in sn65dsi83_atomic_pre_enable()
370 * LVDS bus pixel format, use SPWG24 default in sn65dsi83_atomic_pre_enable()
375 dev_warn(ctx->dev, in sn65dsi83_atomic_pre_enable()
376 …"Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n", in sn65dsi83_atomic_pre_enable()
377 bridge_state->output_bus_cfg.format); in sn65dsi83_atomic_pre_enable()
386 bridge->encoder); in sn65dsi83_atomic_pre_enable()
387 crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; in sn65dsi83_atomic_pre_enable()
389 mode = &crtc_state->adjusted_mode; in sn65dsi83_atomic_pre_enable()
392 regmap_write(ctx->regmap, REG_RC_RESET, 0x00); in sn65dsi83_atomic_pre_enable()
393 regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00); in sn65dsi83_atomic_pre_enable()
396 regmap_write(ctx->regmap, REG_RC_LVDS_PLL, in sn65dsi83_atomic_pre_enable()
399 regmap_write(ctx->regmap, REG_DSI_CLK, in sn65dsi83_atomic_pre_enable()
401 regmap_write(ctx->regmap, REG_RC_DSI_CLK, in sn65dsi83_atomic_pre_enable()
404 /* Set number of DSI lanes and LVDS link config. */ in sn65dsi83_atomic_pre_enable()
405 regmap_write(ctx->regmap, REG_DSI_LANE, in sn65dsi83_atomic_pre_enable()
407 REG_DSI_LANE_CHA_DSI_LANES(~(ctx->dsi->lanes - 1)) | in sn65dsi83_atomic_pre_enable()
408 /* CHB is DSI85-only, set to default on DSI83/DSI84 */ in sn65dsi83_atomic_pre_enable()
411 regmap_write(ctx->regmap, REG_DSI_EQ, 0x00); in sn65dsi83_atomic_pre_enable()
414 val = (mode->flags & DRM_MODE_FLAG_NHSYNC ? in sn65dsi83_atomic_pre_enable()
416 (mode->flags & DRM_MODE_FLAG_NVSYNC ? in sn65dsi83_atomic_pre_enable()
419 /* Set up bits-per-pixel, 18bpp or 24bpp. */ in sn65dsi83_atomic_pre_enable()
422 if (ctx->lvds_dual_link) in sn65dsi83_atomic_pre_enable()
426 /* Set up LVDS format, JEIDA/Format 1 or SPWG/Format 2 */ in sn65dsi83_atomic_pre_enable()
429 if (ctx->lvds_dual_link) in sn65dsi83_atomic_pre_enable()
433 /* Set up LVDS output config (DSI84,DSI85) */ in sn65dsi83_atomic_pre_enable()
434 if (!ctx->lvds_dual_link) in sn65dsi83_atomic_pre_enable()
437 regmap_write(ctx->regmap, REG_LVDS_FMT, val); in sn65dsi83_atomic_pre_enable()
438 regmap_write(ctx->regmap, REG_LVDS_VCOM, 0x05); in sn65dsi83_atomic_pre_enable()
439 regmap_write(ctx->regmap, REG_LVDS_LANE, in sn65dsi83_atomic_pre_enable()
440 (ctx->lvds_dual_link_even_odd_swap ? in sn65dsi83_atomic_pre_enable()
444 regmap_write(ctx->regmap, REG_LVDS_CM, 0x00); in sn65dsi83_atomic_pre_enable()
446 le16val = cpu_to_le16(mode->hdisplay); in sn65dsi83_atomic_pre_enable()
447 regmap_bulk_write(ctx->regmap, REG_VID_CHA_ACTIVE_LINE_LENGTH_LOW, in sn65dsi83_atomic_pre_enable()
449 le16val = cpu_to_le16(mode->vdisplay); in sn65dsi83_atomic_pre_enable()
450 regmap_bulk_write(ctx->regmap, REG_VID_CHA_VERTICAL_DISPLAY_SIZE_LOW, in sn65dsi83_atomic_pre_enable()
454 regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &le16val, 2); in sn65dsi83_atomic_pre_enable()
455 le16val = cpu_to_le16(mode->hsync_end - mode->hsync_start); in sn65dsi83_atomic_pre_enable()
456 regmap_bulk_write(ctx->regmap, REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW, in sn65dsi83_atomic_pre_enable()
458 le16val = cpu_to_le16(mode->vsync_end - mode->vsync_start); in sn65dsi83_atomic_pre_enable()
459 regmap_bulk_write(ctx->regmap, REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW, in sn65dsi83_atomic_pre_enable()
461 regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_BACK_PORCH, in sn65dsi83_atomic_pre_enable()
462 mode->htotal - mode->hsync_end); in sn65dsi83_atomic_pre_enable()
463 regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_BACK_PORCH, in sn65dsi83_atomic_pre_enable()
464 mode->vtotal - mode->vsync_end); in sn65dsi83_atomic_pre_enable()
465 regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_FRONT_PORCH, in sn65dsi83_atomic_pre_enable()
466 mode->hsync_start - mode->hdisplay); in sn65dsi83_atomic_pre_enable()
467 regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_FRONT_PORCH, in sn65dsi83_atomic_pre_enable()
468 mode->vsync_start - mode->vdisplay); in sn65dsi83_atomic_pre_enable()
469 regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN, 0x00); in sn65dsi83_atomic_pre_enable()
472 regmap_write(ctx->regmap, REG_RC_PLL_EN, REG_RC_PLL_EN_PLL_EN); in sn65dsi83_atomic_pre_enable()
474 ret = regmap_read_poll_timeout(ctx->regmap, REG_RC_LVDS_PLL, pval, in sn65dsi83_atomic_pre_enable()
478 dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret); in sn65dsi83_atomic_pre_enable()
480 regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00); in sn65dsi83_atomic_pre_enable()
485 regmap_write(ctx->regmap, REG_RC_RESET, REG_RC_RESET_SOFT_RESET); in sn65dsi83_atomic_pre_enable()
498 regmap_read(ctx->regmap, REG_IRQ_STAT, &pval); in sn65dsi83_atomic_enable()
499 regmap_write(ctx->regmap, REG_IRQ_STAT, pval); in sn65dsi83_atomic_enable()
503 regmap_read(ctx->regmap, REG_IRQ_STAT, &pval); in sn65dsi83_atomic_enable()
505 dev_err(ctx->dev, "Unexpected link status 0x%02x\n", pval); in sn65dsi83_atomic_enable()
515 gpiod_set_value_cansleep(ctx->enable_gpio, 0); in sn65dsi83_atomic_disable()
518 ret = regulator_disable(ctx->vcc); in sn65dsi83_atomic_disable()
520 dev_err(ctx->dev, "Failed to disable vcc: %d\n", ret); in sn65dsi83_atomic_disable()
522 regcache_mark_dirty(ctx->regmap); in sn65dsi83_atomic_disable()
530 /* LVDS output clock range 25..154 MHz */ in sn65dsi83_mode_valid()
531 if (mode->clock < 25000) in sn65dsi83_mode_valid()
533 if (mode->clock > 154000) in sn65dsi83_mode_valid()
558 /* This is the DSI-end bus format */ in sn65dsi83_atomic_get_input_bus_fmts()
582 struct device *dev = ctx->dev; in sn65dsi83_parse_dt()
584 ctx->lvds_dual_link = false; in sn65dsi83_parse_dt()
585 ctx->lvds_dual_link_even_odd_swap = false; in sn65dsi83_parse_dt()
590 port2 = of_graph_get_port_by_id(dev->of_node, 2); in sn65dsi83_parse_dt()
591 port3 = of_graph_get_port_by_id(dev->of_node, 3); in sn65dsi83_parse_dt()
597 ctx->lvds_dual_link = true; in sn65dsi83_parse_dt()
598 /* Odd pixels to LVDS Channel A, even pixels to B */ in sn65dsi83_parse_dt()
599 ctx->lvds_dual_link_even_odd_swap = false; in sn65dsi83_parse_dt()
601 ctx->lvds_dual_link = true; in sn65dsi83_parse_dt()
602 /* Even pixels to LVDS Channel A, odd pixels to B */ in sn65dsi83_parse_dt()
603 ctx->lvds_dual_link_even_odd_swap = true; in sn65dsi83_parse_dt()
607 panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0); in sn65dsi83_parse_dt()
611 ctx->panel_bridge = panel_bridge; in sn65dsi83_parse_dt()
613 ctx->vcc = devm_regulator_get(dev, "vcc"); in sn65dsi83_parse_dt()
614 if (IS_ERR(ctx->vcc)) in sn65dsi83_parse_dt()
615 return dev_err_probe(dev, PTR_ERR(ctx->vcc), in sn65dsi83_parse_dt()
623 struct device *dev = ctx->dev; in sn65dsi83_host_attach()
635 endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); in sn65dsi83_host_attach()
643 return -EPROBE_DEFER; in sn65dsi83_host_attach()
653 ctx->dsi = dsi; in sn65dsi83_host_attach()
655 dsi->lanes = dsi_lanes; in sn65dsi83_host_attach()
656 dsi->format = MIPI_DSI_FMT_RGB888; in sn65dsi83_host_attach()
657 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | in sn65dsi83_host_attach()
673 struct device *dev = &client->dev; in sn65dsi83_probe()
680 return -ENOMEM; in sn65dsi83_probe()
682 ctx->dev = dev; in sn65dsi83_probe()
684 if (dev->of_node) { in sn65dsi83_probe()
688 model = id->driver_data; in sn65dsi83_probe()
692 ctx->enable_gpio = devm_gpiod_get_optional(ctx->dev, "enable", in sn65dsi83_probe()
694 if (IS_ERR(ctx->enable_gpio)) in sn65dsi83_probe()
695 return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "failed to get enable GPIO\n"); in sn65dsi83_probe()
703 ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config); in sn65dsi83_probe()
704 if (IS_ERR(ctx->regmap)) in sn65dsi83_probe()
705 return dev_err_probe(dev, PTR_ERR(ctx->regmap), "failed to get regmap\n"); in sn65dsi83_probe()
710 ctx->bridge.funcs = &sn65dsi83_funcs; in sn65dsi83_probe()
711 ctx->bridge.of_node = dev->of_node; in sn65dsi83_probe()
712 ctx->bridge.pre_enable_prev_first = true; in sn65dsi83_probe()
713 drm_bridge_add(&ctx->bridge); in sn65dsi83_probe()
724 drm_bridge_remove(&ctx->bridge); in sn65dsi83_probe()
732 drm_bridge_remove(&ctx->bridge); in sn65dsi83_remove()
761 MODULE_DESCRIPTION("TI SN65DSI83 DSI to LVDS bridge driver");