Lines Matching +full:dpi +full:- +full:to +full:- +full:lvds
1 // SPDX-License-Identifier: GPL-2.0
6 * 2xDSI/2xLVDS/1xDPI -> 2xDSI/2xLVDS/1xDPI
8 * 1xDSI -> 1xLVDS
17 #include <linux/media-bus-format.h>
41 /* DSI lane count - 0 means 4 lanes ; 1, 2, 3 means 1, 2, 3 lanes. */
107 return drm_bridge_attach(bridge->encoder, ctx->panel_bridge, in lt9211_attach()
108 &ctx->bridge, flags); in lt9211_attach()
117 ret = regmap_bulk_read(ctx->regmap, REG_CHIPID0, chipid, 3); in lt9211_read_chipid()
119 dev_err(ctx->dev, "Failed to read Chip ID: %d\n", ret); in lt9211_read_chipid()
126 dev_err(ctx->dev, "Unknown Chip ID: 0x%02x 0x%02x 0x%02x\n", in lt9211_read_chipid()
128 return -EINVAL; in lt9211_read_chipid()
149 return regmap_multi_reg_write(ctx->regmap, lt9211_system_init_seq, in lt9211_system_init()
161 /* ORR with 0xf8 here to enable DSI DN/DP swap. */ in lt9211_configure_rx()
174 /* 0x8588: BIT 6 set = MIPI-RX, BIT 4 unset = LVDS-TX */ in lt9211_configure_rx()
177 { REG_DSI_LANE, REG_DSI_LANE_COUNT(ctx->dsi->lanes) }, in lt9211_configure_rx()
193 ret = regmap_multi_reg_write(ctx->regmap, lt9211_rx_phy_seq, in lt9211_configure_rx()
198 ret = regmap_multi_reg_write(ctx->regmap, lt9211_rx_cal_reset_seq, in lt9211_configure_rx()
203 ret = regmap_multi_reg_write(ctx->regmap, lt9211_rx_dig_seq, in lt9211_configure_rx()
208 ret = regmap_multi_reg_write(ctx->regmap, lt9211_rx_div_reset_seq, in lt9211_configure_rx()
215 return regmap_multi_reg_write(ctx->regmap, lt9211_rx_div_clear_seq, in lt9211_configure_rx()
230 ret = regmap_write(ctx->regmap, 0x8600, 0x01); in lt9211_autodetect_rx()
234 /* Give the chip time to lock onto RX stream. */ in lt9211_autodetect_rx()
238 ret = regmap_bulk_read(ctx->regmap, 0x8608, bc, sizeof(bc)); in lt9211_autodetect_rx()
245 /* Width/Height/Format Auto-detection */ in lt9211_autodetect_rx()
246 ret = regmap_bulk_read(ctx->regmap, 0xd082, buf, sizeof(buf)); in lt9211_autodetect_rx()
259 dev_err(ctx->dev, "Unsupported DSI pixel format 0x%01x\n", in lt9211_autodetect_rx()
261 return -EINVAL; in lt9211_autodetect_rx()
264 if (width != mode->hdisplay) { in lt9211_autodetect_rx()
265 dev_err(ctx->dev, in lt9211_autodetect_rx()
267 width, mode->hdisplay); in lt9211_autodetect_rx()
268 return -EINVAL; in lt9211_autodetect_rx()
271 if (height != mode->vdisplay) { in lt9211_autodetect_rx()
272 dev_err(ctx->dev, in lt9211_autodetect_rx()
274 height, mode->vdisplay); in lt9211_autodetect_rx()
275 return -EINVAL; in lt9211_autodetect_rx()
278 dev_dbg(ctx->dev, "RX: %dx%d format=0x%01x byteclock=%d kHz\n", in lt9211_autodetect_rx()
288 { 0xd00d, (mode->vtotal >> 8) & 0xff }, in lt9211_configure_timing()
289 { 0xd00e, mode->vtotal & 0xff }, in lt9211_configure_timing()
290 { 0xd00f, (mode->vdisplay >> 8) & 0xff }, in lt9211_configure_timing()
291 { 0xd010, mode->vdisplay & 0xff }, in lt9211_configure_timing()
292 { 0xd011, (mode->htotal >> 8) & 0xff }, in lt9211_configure_timing()
293 { 0xd012, mode->htotal & 0xff }, in lt9211_configure_timing()
294 { 0xd013, (mode->hdisplay >> 8) & 0xff }, in lt9211_configure_timing()
295 { 0xd014, mode->hdisplay & 0xff }, in lt9211_configure_timing()
296 { 0xd015, (mode->vsync_end - mode->vsync_start) & 0xff }, in lt9211_configure_timing()
297 { 0xd016, (mode->hsync_end - mode->hsync_start) & 0xff }, in lt9211_configure_timing()
298 { 0xd017, ((mode->vsync_start - mode->vdisplay) >> 8) & 0xff }, in lt9211_configure_timing()
299 { 0xd018, (mode->vsync_start - mode->vdisplay) & 0xff }, in lt9211_configure_timing()
300 { 0xd019, ((mode->hsync_start - mode->hdisplay) >> 8) & 0xff }, in lt9211_configure_timing()
301 { 0xd01a, (mode->hsync_start - mode->hdisplay) & 0xff }, in lt9211_configure_timing()
304 return regmap_multi_reg_write(ctx->regmap, lt9211_timing, in lt9211_configure_timing()
332 ret = regmap_write(ctx->regmap, 0x822d, 0x48); in lt9211_configure_plls()
336 if (mode->clock < 44000) { in lt9211_configure_plls()
337 ret = regmap_write(ctx->regmap, 0x8235, 0x83); in lt9211_configure_plls()
338 } else if (mode->clock < 88000) { in lt9211_configure_plls()
339 ret = regmap_write(ctx->regmap, 0x8235, 0x82); in lt9211_configure_plls()
340 } else if (mode->clock < 176000) { in lt9211_configure_plls()
341 ret = regmap_write(ctx->regmap, 0x8235, 0x81); in lt9211_configure_plls()
343 dev_err(ctx->dev, in lt9211_configure_plls()
345 mode->clock); in lt9211_configure_plls()
346 return -EINVAL; in lt9211_configure_plls()
352 /* Wait for the DeSSC PLL to stabilize. */ in lt9211_configure_plls()
355 ret = regmap_multi_reg_write(ctx->regmap, lt9211_pcr_seq, in lt9211_configure_plls()
361 ret = regmap_read_poll_timeout(ctx->regmap, 0xd087, pval, pval & 0x8, in lt9211_configure_plls()
364 dev_err(ctx->dev, "PCR unstable, ret=%i\n", ret); in lt9211_configure_plls()
373 /* DPI output disable */ in lt9211_configure_tx()
375 /* BIT(7) is LVDS dual-port */ in lt9211_configure_tx()
376 { 0x823b, 0x38 | (ctx->lvds_dual_link ? BIT(7) : 0) }, in lt9211_configure_tx()
390 /* LVDS channel order, Odd:Even 0x10..A:B, 0x40..B:A */ in lt9211_configure_tx()
391 { 0x8646, ctx->lvds_dual_link_even_odd_swap ? 0x40 : 0x10 }, in lt9211_configure_tx()
401 { 0x855c, ctx->lvds_dual_link ? BIT(0) : 0 }, in lt9211_configure_tx()
414 { 0x8237, ctx->lvds_dual_link ? 0x2a : 0x29 }, in lt9211_configure_tx()
426 ret = regmap_multi_reg_write(ctx->regmap, system_lt9211_tx_phy_seq, in lt9211_configure_tx()
431 ret = regmap_multi_reg_write(ctx->regmap, system_lt9211_tx_dig_seq, in lt9211_configure_tx()
436 ret = regmap_multi_reg_write(ctx->regmap, system_lt9211_tx_pll_seq, in lt9211_configure_tx()
441 ret = regmap_read_poll_timeout(ctx->regmap, 0x871f, pval, pval & 0x80, in lt9211_configure_tx()
444 dev_err(ctx->dev, "TX PLL unstable, ret=%i\n", ret); in lt9211_configure_tx()
448 ret = regmap_read_poll_timeout(ctx->regmap, 0x8720, pval, pval & 0x80, in lt9211_configure_tx()
451 dev_err(ctx->dev, "TX PLL unstable, ret=%i\n", ret); in lt9211_configure_tx()
462 struct drm_atomic_state *state = old_bridge_state->base.state; in lt9211_atomic_enable()
473 ret = regulator_enable(ctx->vccio); in lt9211_atomic_enable()
475 dev_err(ctx->dev, "Failed to enable vccio: %d\n", ret); in lt9211_atomic_enable()
480 gpiod_set_value(ctx->reset_gpio, 1); in lt9211_atomic_enable()
481 usleep_range(20000, 21000); /* Very long post-reset delay. */ in lt9211_atomic_enable()
483 /* Get the LVDS format from the bridge state. */ in lt9211_atomic_enable()
485 bus_flags = bridge_state->output_bus_cfg.flags; in lt9211_atomic_enable()
487 switch (bridge_state->output_bus_cfg.format) { in lt9211_atomic_enable()
503 * LVDS bus pixel format, use SPWG24 default in lt9211_atomic_enable()
508 dev_warn(ctx->dev, in lt9211_atomic_enable()
509 …"Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n", in lt9211_atomic_enable()
510 bridge_state->output_bus_cfg.format); in lt9211_atomic_enable()
515 * Retrieve the CRTC adjusted mode. This requires a little dance to go in lt9211_atomic_enable()
516 * from the bridge to the encoder, to the connector and to the CRTC. in lt9211_atomic_enable()
519 bridge->encoder); in lt9211_atomic_enable()
520 crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; in lt9211_atomic_enable()
522 mode = &crtc_state->adjusted_mode; in lt9211_atomic_enable()
553 dev_dbg(ctx->dev, "LT9211 enabled.\n"); in lt9211_atomic_enable()
566 gpiod_set_value(ctx->reset_gpio, 0); in lt9211_atomic_disable()
569 ret = regulator_disable(ctx->vccio); in lt9211_atomic_disable()
571 dev_err(ctx->dev, "Failed to disable vccio: %d\n", ret); in lt9211_atomic_disable()
573 regcache_mark_dirty(ctx->regmap); in lt9211_atomic_disable()
581 /* LVDS output clock range 25..176 MHz */ in lt9211_mode_valid()
582 if (mode->clock < 25000) in lt9211_mode_valid()
584 if (mode->clock > 176000) in lt9211_mode_valid()
609 /* This is the DSI-end bus format */ in lt9211_atomic_get_input_bus_fmts()
631 struct device *dev = ctx->dev; in lt9211_parse_dt()
636 ctx->vccio = devm_regulator_get(dev, "vccio"); in lt9211_parse_dt()
637 if (IS_ERR(ctx->vccio)) in lt9211_parse_dt()
638 return dev_err_probe(dev, PTR_ERR(ctx->vccio), in lt9211_parse_dt()
639 "Failed to get supply 'vccio'\n"); in lt9211_parse_dt()
641 ctx->lvds_dual_link = false; in lt9211_parse_dt()
642 ctx->lvds_dual_link_even_odd_swap = false; in lt9211_parse_dt()
644 port2 = of_graph_get_port_by_id(dev->of_node, 2); in lt9211_parse_dt()
645 port3 = of_graph_get_port_by_id(dev->of_node, 3); in lt9211_parse_dt()
651 ctx->lvds_dual_link = true; in lt9211_parse_dt()
652 /* Odd pixels to LVDS Channel A, even pixels to B */ in lt9211_parse_dt()
653 ctx->lvds_dual_link_even_odd_swap = false; in lt9211_parse_dt()
655 ctx->lvds_dual_link = true; in lt9211_parse_dt()
656 /* Even pixels to LVDS Channel A, odd pixels to B */ in lt9211_parse_dt()
657 ctx->lvds_dual_link_even_odd_swap = true; in lt9211_parse_dt()
660 ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, &panel_bridge); in lt9211_parse_dt()
669 ctx->panel_bridge = panel_bridge; in lt9211_parse_dt()
681 struct device *dev = ctx->dev; in lt9211_host_attach()
689 endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); in lt9211_host_attach()
697 return -EPROBE_DEFER; in lt9211_host_attach()
705 "failed to create dsi device\n"); in lt9211_host_attach()
707 ctx->dsi = dsi; in lt9211_host_attach()
709 dsi->lanes = dsi_lanes; in lt9211_host_attach()
710 dsi->format = MIPI_DSI_FMT_RGB888; in lt9211_host_attach()
711 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | in lt9211_host_attach()
716 dev_err(dev, "failed to attach dsi to host: %d\n", ret); in lt9211_host_attach()
726 struct device *dev = &client->dev; in lt9211_probe()
732 return -ENOMEM; in lt9211_probe()
734 ctx->dev = dev; in lt9211_probe()
740 ctx->reset_gpio = devm_gpiod_get_optional(ctx->dev, "reset", in lt9211_probe()
742 if (IS_ERR(ctx->reset_gpio)) in lt9211_probe()
743 return PTR_ERR(ctx->reset_gpio); in lt9211_probe()
751 ctx->regmap = devm_regmap_init_i2c(client, <9211_regmap_config); in lt9211_probe()
752 if (IS_ERR(ctx->regmap)) in lt9211_probe()
753 return PTR_ERR(ctx->regmap); in lt9211_probe()
758 ctx->bridge.funcs = <9211_funcs; in lt9211_probe()
759 ctx->bridge.of_node = dev->of_node; in lt9211_probe()
760 drm_bridge_add(&ctx->bridge); in lt9211_probe()
764 drm_bridge_remove(&ctx->bridge); in lt9211_probe()
773 drm_bridge_remove(&ctx->bridge); in lt9211_remove()
800 MODULE_DESCRIPTION("Lontium LT9211 DSI/LVDS/DPI bridge driver");