Lines Matching +full:dsi +full:- +full:lanes

1 // SPDX-License-Identifier: GPL-2.0
3 * RZ/G2L MIPI DSI Encoder Driver
45 unsigned int lanes; member
163 static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) in rzg2l_mipi_dsi_phy_write() argument
165 iowrite32(data, dsi->mmio + reg); in rzg2l_mipi_dsi_phy_write()
168 static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) in rzg2l_mipi_dsi_link_write() argument
170 iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg); in rzg2l_mipi_dsi_link_write()
173 static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg) in rzg2l_mipi_dsi_phy_read() argument
175 return ioread32(dsi->mmio + reg); in rzg2l_mipi_dsi_phy_read()
178 static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg) in rzg2l_mipi_dsi_link_read() argument
180 return ioread32(dsi->mmio + LINK_REG_OFFSET + reg); in rzg2l_mipi_dsi_link_read()
183 /* -----------------------------------------------------------------------------
187 static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi, in rzg2l_mipi_dsi_dphy_init() argument
199 /* All DSI global operation timings are set with recommended setting */ in rzg2l_mipi_dsi_dphy_init()
202 if (hsfreq <= dphy_timings->hsfreq_max) in rzg2l_mipi_dsi_dphy_init()
210 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); in rzg2l_mipi_dsi_dphy_init()
214 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); in rzg2l_mipi_dsi_dphy_init()
218 DSIDPHYTIM0_T_INIT(dphy_timings->t_init); in rzg2l_mipi_dsi_dphy_init()
219 dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) | in rzg2l_mipi_dsi_dphy_init()
220 DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) | in rzg2l_mipi_dsi_dphy_init()
223 dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) | in rzg2l_mipi_dsi_dphy_init()
224 DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) | in rzg2l_mipi_dsi_dphy_init()
225 DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) | in rzg2l_mipi_dsi_dphy_init()
226 DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero); in rzg2l_mipi_dsi_dphy_init()
227 dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) | in rzg2l_mipi_dsi_dphy_init()
228 DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) | in rzg2l_mipi_dsi_dphy_init()
229 DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) | in rzg2l_mipi_dsi_dphy_init()
230 DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero); in rzg2l_mipi_dsi_dphy_init()
232 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0); in rzg2l_mipi_dsi_dphy_init()
233 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1); in rzg2l_mipi_dsi_dphy_init()
234 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2); in rzg2l_mipi_dsi_dphy_init()
235 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3); in rzg2l_mipi_dsi_dphy_init()
237 ret = reset_control_deassert(dsi->rstc); in rzg2l_mipi_dsi_dphy_init()
246 static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi) in rzg2l_mipi_dsi_dphy_exit() argument
250 dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0); in rzg2l_mipi_dsi_dphy_exit()
253 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); in rzg2l_mipi_dsi_dphy_exit()
255 reset_control_assert(dsi->rstc); in rzg2l_mipi_dsi_dphy_exit()
258 static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, in rzg2l_mipi_dsi_startup() argument
274 * vclk * bpp = hsclk * 8 * lanes in rzg2l_mipi_dsi_startup()
277 * hsclk: DSI HS Byte clock frequency (Hz) in rzg2l_mipi_dsi_startup()
278 * lanes: number of data lanes in rzg2l_mipi_dsi_startup()
282 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); in rzg2l_mipi_dsi_startup()
283 hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes); in rzg2l_mipi_dsi_startup()
285 ret = pm_runtime_resume_and_get(dsi->dev); in rzg2l_mipi_dsi_startup()
289 clk_set_rate(dsi->vclk, mode->clock * 1000); in rzg2l_mipi_dsi_startup()
291 ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq); in rzg2l_mipi_dsi_startup()
295 /* Enable Data lanes and Clock lanes */ in rzg2l_mipi_dsi_startup()
296 txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN; in rzg2l_mipi_dsi_startup()
297 rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr); in rzg2l_mipi_dsi_startup()
301 * Currently MIPI DSI-IF just supports maximum FHD@60 with: in rzg2l_mipi_dsi_startup()
302 * - videoclock = 148.5 (MHz) in rzg2l_mipi_dsi_startup()
303 * - bpp: maximum 24bpp in rzg2l_mipi_dsi_startup()
304 * - data lanes: maximum 4 lanes in rzg2l_mipi_dsi_startup()
326 rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr); in rzg2l_mipi_dsi_startup()
329 rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr); in rzg2l_mipi_dsi_startup()
334 rzg2l_mipi_dsi_dphy_exit(dsi); in rzg2l_mipi_dsi_startup()
335 pm_runtime_put(dsi->dev); in rzg2l_mipi_dsi_startup()
340 static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi) in rzg2l_mipi_dsi_stop() argument
342 rzg2l_mipi_dsi_dphy_exit(dsi); in rzg2l_mipi_dsi_stop()
343 pm_runtime_put(dsi->dev); in rzg2l_mipi_dsi_stop()
346 static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi, in rzg2l_mipi_dsi_set_display_timing() argument
359 dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format); in rzg2l_mipi_dsi_set_display_timing()
369 if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) && in rzg2l_mipi_dsi_set_display_timing()
370 !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)) in rzg2l_mipi_dsi_set_display_timing()
373 rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr); in rzg2l_mipi_dsi_set_display_timing()
376 vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) | in rzg2l_mipi_dsi_set_display_timing()
377 VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start); in rzg2l_mipi_dsi_set_display_timing()
378 vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ? in rzg2l_mipi_dsi_set_display_timing()
381 vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) | in rzg2l_mipi_dsi_set_display_timing()
382 VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end); in rzg2l_mipi_dsi_set_display_timing()
384 vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) | in rzg2l_mipi_dsi_set_display_timing()
385 VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start); in rzg2l_mipi_dsi_set_display_timing()
386 vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ? in rzg2l_mipi_dsi_set_display_timing()
389 vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) | in rzg2l_mipi_dsi_set_display_timing()
390 VICH1HPSETR_HBP(mode->htotal - mode->hsync_end); in rzg2l_mipi_dsi_set_display_timing()
392 rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr); in rzg2l_mipi_dsi_set_display_timing()
393 rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr); in rzg2l_mipi_dsi_set_display_timing()
394 rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr); in rzg2l_mipi_dsi_set_display_timing()
395 rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr); in rzg2l_mipi_dsi_set_display_timing()
402 if (mode->clock > 74250) { in rzg2l_mipi_dsi_set_display_timing()
410 if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) in rzg2l_mipi_dsi_set_display_timing()
415 rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R, in rzg2l_mipi_dsi_set_display_timing()
419 static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi) in rzg2l_mipi_dsi_start_hs_clock() argument
426 is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS); in rzg2l_mipi_dsi_start_hs_clock()
432 rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr); in rzg2l_mipi_dsi_start_hs_clock()
437 2000, 20000, false, dsi, PLSR); in rzg2l_mipi_dsi_start_hs_clock()
439 dev_err(dsi->dev, "failed to start HS clock\n"); in rzg2l_mipi_dsi_start_hs_clock()
444 dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode", in rzg2l_mipi_dsi_start_hs_clock()
445 is_clk_cont ? "continuous" : "non-continuous"); in rzg2l_mipi_dsi_start_hs_clock()
450 static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi) in rzg2l_mipi_dsi_stop_hs_clock() argument
456 is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS); in rzg2l_mipi_dsi_stop_hs_clock()
459 rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, in rzg2l_mipi_dsi_stop_hs_clock()
466 2000, 20000, false, dsi, PLSR); in rzg2l_mipi_dsi_stop_hs_clock()
468 dev_err(dsi->dev, "failed to stop HS clock\n"); in rzg2l_mipi_dsi_stop_hs_clock()
476 static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi) in rzg2l_mipi_dsi_start_video() argument
485 rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r); in rzg2l_mipi_dsi_start_video()
489 2000, 20000, false, dsi, VICH1SR); in rzg2l_mipi_dsi_start_video()
491 dev_err(dsi->dev, "Failed to start video signal input\n"); in rzg2l_mipi_dsi_start_video()
496 static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi) in rzg2l_mipi_dsi_stop_video() argument
501 rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT); in rzg2l_mipi_dsi_stop_video()
504 2000, 20000, false, dsi, VICH1SR); in rzg2l_mipi_dsi_stop_video()
510 2000, 20000, false, dsi, LINKSR); in rzg2l_mipi_dsi_stop_video()
517 dev_err(dsi->dev, "Failed to stop video signal input\n"); in rzg2l_mipi_dsi_stop_video()
521 /* -----------------------------------------------------------------------------
528 struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); in rzg2l_mipi_dsi_attach() local
530 return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge, in rzg2l_mipi_dsi_attach()
537 struct drm_atomic_state *state = old_bridge_state->base.state; in rzg2l_mipi_dsi_atomic_enable()
538 struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); in rzg2l_mipi_dsi_atomic_enable() local
544 connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); in rzg2l_mipi_dsi_atomic_enable()
545 crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; in rzg2l_mipi_dsi_atomic_enable()
546 mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode; in rzg2l_mipi_dsi_atomic_enable()
548 ret = rzg2l_mipi_dsi_startup(dsi, mode); in rzg2l_mipi_dsi_atomic_enable()
552 rzg2l_mipi_dsi_set_display_timing(dsi, mode); in rzg2l_mipi_dsi_atomic_enable()
554 ret = rzg2l_mipi_dsi_start_hs_clock(dsi); in rzg2l_mipi_dsi_atomic_enable()
558 ret = rzg2l_mipi_dsi_start_video(dsi); in rzg2l_mipi_dsi_atomic_enable()
565 rzg2l_mipi_dsi_stop_hs_clock(dsi); in rzg2l_mipi_dsi_atomic_enable()
567 rzg2l_mipi_dsi_stop(dsi); in rzg2l_mipi_dsi_atomic_enable()
573 struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); in rzg2l_mipi_dsi_atomic_disable() local
575 rzg2l_mipi_dsi_stop_video(dsi); in rzg2l_mipi_dsi_atomic_disable()
576 rzg2l_mipi_dsi_stop_hs_clock(dsi); in rzg2l_mipi_dsi_atomic_disable()
577 rzg2l_mipi_dsi_stop(dsi); in rzg2l_mipi_dsi_atomic_disable()
585 if (mode->clock > 148500) in rzg2l_mipi_dsi_bridge_mode_valid()
601 /* -----------------------------------------------------------------------------
608 struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host); in rzg2l_mipi_dsi_host_attach() local
611 if (device->lanes > dsi->num_data_lanes) { in rzg2l_mipi_dsi_host_attach()
612 dev_err(dsi->dev, in rzg2l_mipi_dsi_host_attach()
614 device->lanes, dsi->num_data_lanes); in rzg2l_mipi_dsi_host_attach()
615 return -EINVAL; in rzg2l_mipi_dsi_host_attach()
618 switch (mipi_dsi_pixel_format_to_bpp(device->format)) { in rzg2l_mipi_dsi_host_attach()
623 dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format); in rzg2l_mipi_dsi_host_attach()
624 return -EINVAL; in rzg2l_mipi_dsi_host_attach()
627 dsi->lanes = device->lanes; in rzg2l_mipi_dsi_host_attach()
628 dsi->format = device->format; in rzg2l_mipi_dsi_host_attach()
629 dsi->mode_flags = device->mode_flags; in rzg2l_mipi_dsi_host_attach()
631 dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node, in rzg2l_mipi_dsi_host_attach()
633 if (IS_ERR(dsi->next_bridge)) { in rzg2l_mipi_dsi_host_attach()
634 ret = PTR_ERR(dsi->next_bridge); in rzg2l_mipi_dsi_host_attach()
635 dev_err(dsi->dev, "failed to get next bridge: %d\n", ret); in rzg2l_mipi_dsi_host_attach()
639 drm_bridge_add(&dsi->bridge); in rzg2l_mipi_dsi_host_attach()
647 struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host); in rzg2l_mipi_dsi_host_detach() local
649 drm_bridge_remove(&dsi->bridge); in rzg2l_mipi_dsi_host_detach()
659 /* -----------------------------------------------------------------------------
665 struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev); in rzg2l_mipi_pm_runtime_suspend() local
667 reset_control_assert(dsi->prstc); in rzg2l_mipi_pm_runtime_suspend()
668 reset_control_assert(dsi->arstc); in rzg2l_mipi_pm_runtime_suspend()
675 struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev); in rzg2l_mipi_pm_runtime_resume() local
678 ret = reset_control_deassert(dsi->arstc); in rzg2l_mipi_pm_runtime_resume()
682 ret = reset_control_deassert(dsi->prstc); in rzg2l_mipi_pm_runtime_resume()
684 reset_control_assert(dsi->arstc); in rzg2l_mipi_pm_runtime_resume()
693 /* -----------------------------------------------------------------------------
700 struct rzg2l_mipi_dsi *dsi; in rzg2l_mipi_dsi_probe() local
704 dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); in rzg2l_mipi_dsi_probe()
705 if (!dsi) in rzg2l_mipi_dsi_probe()
706 return -ENOMEM; in rzg2l_mipi_dsi_probe()
708 platform_set_drvdata(pdev, dsi); in rzg2l_mipi_dsi_probe()
709 dsi->dev = &pdev->dev; in rzg2l_mipi_dsi_probe()
711 ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4); in rzg2l_mipi_dsi_probe()
713 return dev_err_probe(dsi->dev, ret, in rzg2l_mipi_dsi_probe()
714 "missing or invalid data-lanes property\n"); in rzg2l_mipi_dsi_probe()
718 dsi->mmio = devm_platform_ioremap_resource(pdev, 0); in rzg2l_mipi_dsi_probe()
719 if (IS_ERR(dsi->mmio)) in rzg2l_mipi_dsi_probe()
720 return PTR_ERR(dsi->mmio); in rzg2l_mipi_dsi_probe()
722 dsi->vclk = devm_clk_get(dsi->dev, "vclk"); in rzg2l_mipi_dsi_probe()
723 if (IS_ERR(dsi->vclk)) in rzg2l_mipi_dsi_probe()
724 return PTR_ERR(dsi->vclk); in rzg2l_mipi_dsi_probe()
726 dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst"); in rzg2l_mipi_dsi_probe()
727 if (IS_ERR(dsi->rstc)) in rzg2l_mipi_dsi_probe()
728 return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc), in rzg2l_mipi_dsi_probe()
731 dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst"); in rzg2l_mipi_dsi_probe()
732 if (IS_ERR(dsi->arstc)) in rzg2l_mipi_dsi_probe()
733 return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc), in rzg2l_mipi_dsi_probe()
736 dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst"); in rzg2l_mipi_dsi_probe()
737 if (IS_ERR(dsi->prstc)) in rzg2l_mipi_dsi_probe()
738 return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc), in rzg2l_mipi_dsi_probe()
741 platform_set_drvdata(pdev, dsi); in rzg2l_mipi_dsi_probe()
743 pm_runtime_enable(dsi->dev); in rzg2l_mipi_dsi_probe()
745 ret = pm_runtime_resume_and_get(dsi->dev); in rzg2l_mipi_dsi_probe()
751 * mode->clock and format are not available. So initialize DPHY with in rzg2l_mipi_dsi_probe()
754 ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000); in rzg2l_mipi_dsi_probe()
758 txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR); in rzg2l_mipi_dsi_probe()
759 dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes); in rzg2l_mipi_dsi_probe()
760 rzg2l_mipi_dsi_dphy_exit(dsi); in rzg2l_mipi_dsi_probe()
761 pm_runtime_put(dsi->dev); in rzg2l_mipi_dsi_probe()
764 dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops; in rzg2l_mipi_dsi_probe()
765 dsi->bridge.of_node = dsi->dev->of_node; in rzg2l_mipi_dsi_probe()
768 dsi->host.dev = dsi->dev; in rzg2l_mipi_dsi_probe()
769 dsi->host.ops = &rzg2l_mipi_dsi_host_ops; in rzg2l_mipi_dsi_probe()
770 ret = mipi_dsi_host_register(&dsi->host); in rzg2l_mipi_dsi_probe()
777 rzg2l_mipi_dsi_dphy_exit(dsi); in rzg2l_mipi_dsi_probe()
778 pm_runtime_put(dsi->dev); in rzg2l_mipi_dsi_probe()
780 pm_runtime_disable(dsi->dev); in rzg2l_mipi_dsi_probe()
786 struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev); in rzg2l_mipi_dsi_remove() local
788 mipi_dsi_host_unregister(&dsi->host); in rzg2l_mipi_dsi_remove()
789 pm_runtime_disable(&pdev->dev); in rzg2l_mipi_dsi_remove()
793 { .compatible = "renesas,rzg2l-mipi-dsi" },
803 .name = "rzg2l-mipi-dsi",
812 MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver");