Lines Matching +full:dpi +full:- +full:to +full:- +full:lvds

1 // SPDX-License-Identifier: GPL-2.0-or-later
7 * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
14 #include <linux/media-bus-format.h>
37 /* -----------------------------------------------------------------------------
43 return (val & mxsfb->devdata->hs_wdth_mask) << in set_hsync_pulse_width()
44 mxsfb->devdata->hs_wdth_shift; in set_hsync_pulse_width()
54 struct drm_device *drm = mxsfb->drm; in mxsfb_set_formats()
55 const u32 format = mxsfb->crtc.primary->state->fb->format->format; in mxsfb_set_formats()
58 DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n", in mxsfb_set_formats()
64 ctrl1 = readl(mxsfb->base + LCDC_CTRL1); in mxsfb_set_formats()
69 dev_dbg(drm->dev, "Setting up RGB565 mode\n"); in mxsfb_set_formats()
74 dev_dbg(drm->dev, "Setting up XRGB8888 mode\n"); in mxsfb_set_formats()
92 dev_err(drm->dev, "Unknown media bus format 0x%x\n", bus_format); in mxsfb_set_formats()
96 writel(ctrl1, mxsfb->base + LCDC_CTRL1); in mxsfb_set_formats()
97 writel(ctrl, mxsfb->base + LCDC_CTRL); in mxsfb_set_formats()
102 struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode; in mxsfb_set_mode()
105 writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) | in mxsfb_set_mode()
106 TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay), in mxsfb_set_mode()
107 mxsfb->base + mxsfb->devdata->transfer_count); in mxsfb_set_mode()
109 vsync_pulse_len = m->crtc_vsync_end - m->crtc_vsync_start; in mxsfb_set_mode()
115 if (m->flags & DRM_MODE_FLAG_PHSYNC) in mxsfb_set_mode()
117 if (m->flags & DRM_MODE_FLAG_PVSYNC) in mxsfb_set_mode()
125 * Drive on positive edge -> display samples on falling edge in mxsfb_set_mode()
126 * DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE -> VDCTRL0_DOTCLK_ACT_FALLING in mxsfb_set_mode()
131 writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0); in mxsfb_set_mode()
134 writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1); in mxsfb_set_mode()
137 hsync_pulse_len = m->crtc_hsync_end - m->crtc_hsync_start; in mxsfb_set_mode()
139 VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal), in mxsfb_set_mode()
140 mxsfb->base + LCDC_VDCTRL2); in mxsfb_set_mode()
142 writel(SET_HOR_WAIT_CNT(m->crtc_htotal - m->crtc_hsync_start) | in mxsfb_set_mode()
143 SET_VERT_WAIT_CNT(m->crtc_vtotal - m->crtc_vsync_start), in mxsfb_set_mode()
144 mxsfb->base + LCDC_VDCTRL3); in mxsfb_set_mode()
146 writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay), in mxsfb_set_mode()
147 mxsfb->base + LCDC_VDCTRL4); in mxsfb_set_mode()
155 if (mxsfb->clk_disp_axi) in mxsfb_enable_controller()
156 clk_prepare_enable(mxsfb->clk_disp_axi); in mxsfb_enable_controller()
157 clk_prepare_enable(mxsfb->clk); in mxsfb_enable_controller()
160 if (mxsfb->devdata->has_ctrl2) { in mxsfb_enable_controller()
161 reg = readl(mxsfb->base + LCDC_V4_CTRL2); in mxsfb_enable_controller()
164 writel(reg, mxsfb->base + LCDC_V4_CTRL2); in mxsfb_enable_controller()
167 /* If it was disabled, re-enable the mode again */ in mxsfb_enable_controller()
168 writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET); in mxsfb_enable_controller()
171 reg = readl(mxsfb->base + LCDC_VDCTRL4); in mxsfb_enable_controller()
173 writel(reg, mxsfb->base + LCDC_VDCTRL4); in mxsfb_enable_controller()
180 * to 800x480 DPI panel and i.MX8MM connected to DPI->DSI->LVDS in mxsfb_enable_controller()
182 * the image on the panel shifts to the right and wraps around. in mxsfb_enable_controller()
187 * It seems this problem is known and is due to sporadic underflows in mxsfb_enable_controller()
195 * Set this bit to enable the LCDIF block to recover in the next in mxsfb_enable_controller()
198 * Enable this bit to mitigate the sporadic underflows. in mxsfb_enable_controller()
200 reg = readl(mxsfb->base + LCDC_CTRL1); in mxsfb_enable_controller()
202 writel(reg, mxsfb->base + LCDC_CTRL1); in mxsfb_enable_controller()
204 writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET); in mxsfb_enable_controller()
215 writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_CLR); in mxsfb_disable_controller()
217 readl_poll_timeout(mxsfb->base + LCDC_CTRL, reg, !(reg & CTRL_RUN), in mxsfb_disable_controller()
220 reg = readl(mxsfb->base + LCDC_VDCTRL4); in mxsfb_disable_controller()
222 writel(reg, mxsfb->base + LCDC_VDCTRL4); in mxsfb_disable_controller()
224 clk_disable_unprepare(mxsfb->clk); in mxsfb_disable_controller()
225 if (mxsfb->clk_disp_axi) in mxsfb_disable_controller()
226 clk_disable_unprepare(mxsfb->clk_disp_axi); in mxsfb_disable_controller()
247 * It seems, you can't re-program the controller if it is still in mxsfb_reset_block()
248 * running. This may lead to shifted pictures (FIFO issue?), so in mxsfb_reset_block()
252 ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST); in mxsfb_reset_block()
256 writel(CTRL_CLKGATE, mxsfb->base + LCDC_CTRL + REG_CLR); in mxsfb_reset_block()
258 ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST); in mxsfb_reset_block()
262 ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE); in mxsfb_reset_block()
267 writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET); in mxsfb_reset_block()
268 readl(mxsfb->base + LCDC_CTRL1); in mxsfb_reset_block()
269 writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_CLR); in mxsfb_reset_block()
270 readl(mxsfb->base + LCDC_CTRL1); in mxsfb_reset_block()
272 if (mxsfb->devdata->has_overlay) in mxsfb_reset_block()
273 writel(0, mxsfb->base + LCDC_AS_CTRL); in mxsfb_reset_block()
282 struct drm_device *drm = mxsfb->crtc.dev; in mxsfb_crtc_mode_set_nofb()
283 struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode; in mxsfb_crtc_mode_set_nofb()
284 u32 bus_flags = mxsfb->connector->display_info.bus_flags; in mxsfb_crtc_mode_set_nofb()
287 if (mxsfb->bridge && mxsfb->bridge->timings) in mxsfb_crtc_mode_set_nofb()
288 bus_flags = mxsfb->bridge->timings->input_bus_flags; in mxsfb_crtc_mode_set_nofb()
290 bus_flags = bridge_state->input_bus_cfg.flags; in mxsfb_crtc_mode_set_nofb()
292 DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n", in mxsfb_crtc_mode_set_nofb()
293 m->crtc_clock, in mxsfb_crtc_mode_set_nofb()
294 (int)(clk_get_rate(mxsfb->clk) / 1000)); in mxsfb_crtc_mode_set_nofb()
295 DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n", in mxsfb_crtc_mode_set_nofb()
297 DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags); in mxsfb_crtc_mode_set_nofb()
306 clk_set_rate(mxsfb->clk, m->crtc_clock * 1000); in mxsfb_crtc_mode_set_nofb()
316 bool has_primary = crtc_state->plane_mask & in mxsfb_crtc_atomic_check()
317 drm_plane_mask(crtc->primary); in mxsfb_crtc_atomic_check()
319 /* The primary plane has to be enabled when the CRTC is active. */ in mxsfb_crtc_atomic_check()
320 if (crtc_state->active && !has_primary) in mxsfb_crtc_atomic_check()
321 return -EINVAL; in mxsfb_crtc_atomic_check()
332 event = crtc->state->event; in mxsfb_crtc_atomic_flush()
333 crtc->state->event = NULL; in mxsfb_crtc_atomic_flush()
338 spin_lock_irq(&crtc->dev->event_lock); in mxsfb_crtc_atomic_flush()
343 spin_unlock_irq(&crtc->dev->event_lock); in mxsfb_crtc_atomic_flush()
349 struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); in mxsfb_crtc_atomic_enable()
351 crtc->primary); in mxsfb_crtc_atomic_enable()
353 struct drm_device *drm = mxsfb->drm; in mxsfb_crtc_atomic_enable()
357 pm_runtime_get_sync(drm->dev); in mxsfb_crtc_atomic_enable()
362 /* If there is a bridge attached to the LCDIF, use its bus format */ in mxsfb_crtc_atomic_enable()
363 if (mxsfb->bridge) { in mxsfb_crtc_atomic_enable()
366 mxsfb->bridge); in mxsfb_crtc_atomic_enable()
370 bus_format = bridge_state->input_bus_cfg.format; in mxsfb_crtc_atomic_enable()
373 dev_warn_once(drm->dev, in mxsfb_crtc_atomic_enable()
381 if (!bus_format && mxsfb->connector->display_info.num_bus_formats) in mxsfb_crtc_atomic_enable()
382 bus_format = mxsfb->connector->display_info.bus_formats[0]; in mxsfb_crtc_atomic_enable()
384 /* If all else fails, default to RGB888_1X24 */ in mxsfb_crtc_atomic_enable()
390 /* Write cur_buf as well to avoid an initial corrupt frame */ in mxsfb_crtc_atomic_enable()
391 dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); in mxsfb_crtc_atomic_enable()
393 writel(dma_addr, mxsfb->base + mxsfb->devdata->cur_buf); in mxsfb_crtc_atomic_enable()
394 writel(dma_addr, mxsfb->base + mxsfb->devdata->next_buf); in mxsfb_crtc_atomic_enable()
403 struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); in mxsfb_crtc_atomic_disable()
404 struct drm_device *drm = mxsfb->drm; in mxsfb_crtc_atomic_disable()
409 spin_lock_irq(&drm->event_lock); in mxsfb_crtc_atomic_disable()
410 event = crtc->state->event; in mxsfb_crtc_atomic_disable()
412 crtc->state->event = NULL; in mxsfb_crtc_atomic_disable()
415 spin_unlock_irq(&drm->event_lock); in mxsfb_crtc_atomic_disable()
420 pm_runtime_put_sync(drm->dev); in mxsfb_crtc_atomic_disable()
425 struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); in mxsfb_crtc_enable_vblank()
428 writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); in mxsfb_crtc_enable_vblank()
429 writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET); in mxsfb_crtc_enable_vblank()
436 struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); in mxsfb_crtc_disable_vblank()
439 writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR); in mxsfb_crtc_disable_vblank()
440 writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); in mxsfb_crtc_disable_vblank()
448 return -ENODEV; in mxsfb_crtc_set_crc_source()
450 mxsfb = to_mxsfb_drm_private(crtc->dev); in mxsfb_crtc_set_crc_source()
453 mxsfb->crc_active = true; in mxsfb_crtc_set_crc_source()
455 mxsfb->crc_active = false; in mxsfb_crtc_set_crc_source()
457 return -EINVAL; in mxsfb_crtc_set_crc_source()
466 return -ENODEV; in mxsfb_crtc_verify_crc_source()
470 source, crtc->name); in mxsfb_crtc_verify_crc_source()
471 return -EINVAL; in mxsfb_crtc_verify_crc_source()
509 /* -----------------------------------------------------------------------------
517 /* -----------------------------------------------------------------------------
526 struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); in mxsfb_plane_atomic_check()
530 &mxsfb->crtc); in mxsfb_plane_atomic_check()
541 struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); in mxsfb_plane_primary_atomic_update()
546 dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); in mxsfb_plane_primary_atomic_update()
548 writel(dma_addr, mxsfb->base + mxsfb->devdata->next_buf); in mxsfb_plane_primary_atomic_update()
556 struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); in mxsfb_plane_overlay_atomic_update()
562 dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0); in mxsfb_plane_overlay_atomic_update()
564 writel(0, mxsfb->base + LCDC_AS_CTRL); in mxsfb_plane_overlay_atomic_update()
569 * HACK: The hardware seems to output 64 bytes of data of unknown in mxsfb_plane_overlay_atomic_update()
570 * origin, and then to proceed with the framebuffer. Until the reason in mxsfb_plane_overlay_atomic_update()
576 writel(dma_addr, mxsfb->base + LCDC_AS_NEXT_BUF); in mxsfb_plane_overlay_atomic_update()
579 * If the plane was previously disabled, write LCDC_AS_BUF as well to in mxsfb_plane_overlay_atomic_update()
582 if (!old_pstate->fb) in mxsfb_plane_overlay_atomic_update()
583 writel(dma_addr, mxsfb->base + LCDC_AS_BUF); in mxsfb_plane_overlay_atomic_update()
587 switch (new_pstate->fb->format->format) { in mxsfb_plane_overlay_atomic_update()
611 writel(ctrl, mxsfb->base + LCDC_AS_CTRL); in mxsfb_plane_overlay_atomic_update()
617 struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); in mxsfb_plane_overlay_atomic_disable()
619 writel(0, mxsfb->base + LCDC_AS_CTRL); in mxsfb_plane_overlay_atomic_disable()
670 /* -----------------------------------------------------------------------------
676 struct drm_encoder *encoder = &mxsfb->encoder; in mxsfb_kms_init()
677 struct drm_crtc *crtc = &mxsfb->crtc; in mxsfb_kms_init()
680 drm_plane_helper_add(&mxsfb->planes.primary, in mxsfb_kms_init()
682 ret = drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1, in mxsfb_kms_init()
691 if (mxsfb->devdata->has_overlay) { in mxsfb_kms_init()
692 drm_plane_helper_add(&mxsfb->planes.overlay, in mxsfb_kms_init()
694 ret = drm_universal_plane_init(mxsfb->drm, in mxsfb_kms_init()
695 &mxsfb->planes.overlay, 1, in mxsfb_kms_init()
706 if (mxsfb->devdata->has_crc32) { in mxsfb_kms_init()
707 ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, in mxsfb_kms_init()
708 &mxsfb->planes.primary, NULL, in mxsfb_kms_init()
712 ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, in mxsfb_kms_init()
713 &mxsfb->planes.primary, NULL, in mxsfb_kms_init()
719 encoder->possible_crtcs = drm_crtc_mask(crtc); in mxsfb_kms_init()
720 return drm_encoder_init(mxsfb->drm, encoder, &mxsfb_encoder_funcs, in mxsfb_kms_init()