diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2019-12-17 15:57:54 +0300 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2019-12-17 15:57:54 +0300 |
commit | 6c56e8adc0011b3bc01b6b2bab7e41d5ecb43c0f (patch) | |
tree | 3baa1c367f120d7fcc1c30dbb8a6aff5fa5dd672 /drivers/gpu/drm/mcde | |
parent | d1eef1c619749b2a57e514a3fa67d9a516ffa919 (diff) | |
parent | 2156873f08c7893811f34177aa923ab1ea486591 (diff) | |
download | linux-6c56e8adc0011b3bc01b6b2bab7e41d5ecb43c0f.tar.xz |
Merge tag 'drm-misc-next-2019-12-16' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v5.6:
UAPI Changes:
- Add support for DMA-BUF HEAPS.
Cross-subsystem Changes:
- mipi dsi definition updates, pulled into drm-intel as well.
- Add lockdep annotations for dma_resv vs mmap_sem and fs_reclaim.
- Remove support for dma-buf kmap/kunmap.
- Constify fb_ops in all fbdev drivers, including drm drivers and drm-core, and media as well.
Core Changes:
- Small cleanups to ttm.
- Fix SCDC definition.
- Assorted cleanups to core.
- Add todo to remove load/unload hooks, and use generic fbdev emulation.
- Assorted documentation updates.
- Use blocking ww lock in ttm fault handler.
- Remove drm_fb_helper_fbdev_setup/teardown.
- Warning fixes with W=1 for atomic.
- Use drm_debug_enabled() instead of drm_debug flag testing in various drivers.
- Fallback to nontiled mode in fbdev emulation when not all tiles are present. (Later on reverted)
- Various kconfig indentation fixes in core and drivers.
- Fix freeing transactions in dp-mst correctly.
- Sean Paul is steping down as core maintainer. :-(
- Add lockdep annotations for atomic locks vs dma-resv.
- Prevent use-after-free for a bad job in drm_scheduler.
- Fill out all block sizes in the P01x and P210 definitions.
- Avoid division by zero in drm/rect, and fix bounds.
- Add drm/rect selftests.
- Add aspect ratio and alternate clocks for HDMI 4k modes.
- Add todo for drm_framebuffer_funcs and fb_create cleanup.
- Drop DRM_AUTH for prime import/export ioctls.
- Clear DP-MST payload id tables downstream when initializating.
- Fix for DSC throughput definition.
- Add extra FEC definitions.
- Fix fake offset in drm_gem_object_funs.mmap.
- Stop using encoder->bridge in core directly
- Handle bridge chaining slightly better.
- Add backlight support to drm/panel, and use it in many panel drivers.
- Increase max number of y420 modes from 128 to 256, as preparation to add the new modes.
Driver Changes:
- Small fixes all over.
- Fix documentation in vkms.
- Fix mmap_sem vs dma_resv in nouveau.
- Small cleanup in komeda.
- Add page flip support in gma500 for psb/cdv.
- Add ddc symlink in the connector sysfs directory for many drivers.
- Add support for analogic an6345, and fix small bugs in it.
- Add atomic modesetting support to ast.
- Fix radeon fault handler VMA race.
- Switch udl to use generic shmem helpers.
- Unconditional vblank handling for mcde.
- Miscellaneous fixes to mcde.
- Tweak debug output from komeda using debugfs.
- Add gamma and color transform support to komeda for DOU-IPS.
- Add support for sony acx424AKP panel.
- Various small cleanups to gma500.
- Use generic fbdev emulation in udl, and replace udl_framebuffer with generic implementation.
- Add support for Logic PD Type 28 panel.
- Use drm_panel_* wrapper functions in exynos/tegra/msm.
- Add devicetree bindings for generic DSI panels.
- Don't include drm_pci.h directly in many drivers.
- Add support for begin/end_cpu_access in udmabuf.
- Stop using drm_get_pci_dev in gma500 and mga200.
- Fixes to UDL damage handling, and use dma_buf_begin/end_cpu_access.
- Add devfreq thermal support to panfrost.
- Fix hotplug with daisy chained monitors by removing VCPI when disabling topology manager.
- meson: Add support for OSD1 plane AFBC commit.
- Stop displaying garbage when toggling ast primary plane on/off.
- More cleanups and fixes to UDL.
- Add D32 suport to komeda.
- Remove globle copy of drm_dev in gma500.
- Add support for Boe Himax8279d MIPI-DSI LCD panel.
- Add support for ingenic JZ4770 panel.
- Small null pointer deference fix in ingenic.
- Remove support for the special tfp420 driver, as there is a generic way to do it.
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ba73535a-9334-5302-2e1f-5208bd7390bd@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/mcde')
-rw-r--r-- | drivers/gpu/drm/mcde/mcde_display.c | 57 | ||||
-rw-r--r-- | drivers/gpu/drm/mcde/mcde_drm.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/mcde/mcde_drv.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/mcde/mcde_dsi.c | 177 | ||||
-rw-r--r-- | drivers/gpu/drm/mcde/mcde_dsi_regs.h | 21 |
5 files changed, 131 insertions, 143 deletions
diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index 751454ae3cd1..e59907e68854 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -498,24 +498,20 @@ static void mcde_configure_channel(struct mcde *mcde, enum mcde_channel ch, } /* Set up channel 0 sync (based on chnl_update_registers()) */ - if (mcde->te_sync) { - /* - * Turn on hardware TE0 synchronization - */ + if (mcde->video_mode || mcde->te_sync) val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT; - val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0 - << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; - } else { - /* - * Set up sync source to software, out sync formatter - * Code mostly from mcde_hw.c chnl_update_registers() - */ + else val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SOFTWARE << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT; + + if (mcde->te_sync) + val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0 + << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; + else val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; - } + writel(val, mcde->regs + sync); /* Set up pixels per line and lines per frame */ @@ -934,10 +930,17 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, val = readl(mcde->regs + MCDE_CRC); val |= MCDE_CRC_SYCEN0; writel(val, mcde->regs + MCDE_CRC); - - drm_crtc_vblank_on(crtc); } + drm_crtc_vblank_on(crtc); + + if (mcde->video_mode) + /* + * Keep FIFO permanently enabled in video mode, + * otherwise MCDE will stop feeding data to the panel. + */ + mcde_enable_fifo(mcde, MCDE_FIFO_A); + dev_info(drm->dev, "MCDE display is enabled\n"); } @@ -946,13 +949,22 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe) struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct mcde *mcde = drm->dev_private; + struct drm_pending_vblank_event *event; - if (mcde->te_sync) - drm_crtc_vblank_off(crtc); + drm_crtc_vblank_off(crtc); /* Disable FIFO A flow */ mcde_disable_fifo(mcde, MCDE_FIFO_A, true); + event = crtc->state->event; + if (event) { + crtc->state->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); + } + dev_info(drm->dev, "MCDE display is disabled\n"); } @@ -1048,8 +1060,9 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, */ if (fb) { mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0)); - /* Send a single frame using software sync */ - mcde_display_send_one_frame(mcde); + if (!mcde->video_mode) + /* Send a single frame using software sync */ + mcde_display_send_one_frame(mcde); dev_info_once(mcde->dev, "sent first display update\n"); } else { /* @@ -1097,6 +1110,8 @@ static struct drm_simple_display_pipe_funcs mcde_display_funcs = { .enable = mcde_display_enable, .disable = mcde_display_disable, .update = mcde_display_update, + .enable_vblank = mcde_display_enable_vblank, + .disable_vblank = mcde_display_disable_vblank, .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; @@ -1123,12 +1138,6 @@ int mcde_display_init(struct drm_device *drm) DRM_FORMAT_YUV422, }; - /* Provide vblank only when we have TE enabled */ - if (mcde->te_sync) { - mcde_display_funcs.enable_vblank = mcde_display_enable_vblank; - mcde_display_funcs.disable_vblank = mcde_display_disable_vblank; - } - ret = drm_simple_display_pipe_init(drm, &mcde->pipe, &mcde_display_funcs, formats, ARRAY_SIZE(formats), diff --git a/drivers/gpu/drm/mcde/mcde_drm.h b/drivers/gpu/drm/mcde/mcde_drm.h index dab4db021231..80edd6628979 100644 --- a/drivers/gpu/drm/mcde/mcde_drm.h +++ b/drivers/gpu/drm/mcde/mcde_drm.h @@ -19,6 +19,7 @@ struct mcde { struct mipi_dsi_device *mdsi; s16 stride; bool te_sync; + bool video_mode; bool oneshot_mode; unsigned int flow_active; spinlock_t flow_lock; /* Locks the channel flow control */ diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index 5649887d2b90..9008ddcfc528 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -179,18 +179,10 @@ static int mcde_modeset_init(struct drm_device *drm) mode_config->min_height = 1; mode_config->max_height = 1080; - /* - * Currently we only support vblank handling on the DSI bridge, using - * TE synchronization. If TE sync is not set up, it is still possible - * to push out a single update on demand, but this is hard for DRM to - * exploit. - */ - if (mcde->te_sync) { - ret = drm_vblank_init(drm, 1); - if (ret) { - dev_err(drm->dev, "failed to init vblank\n"); - goto out_config; - } + ret = drm_vblank_init(drm, 1); + if (ret) { + dev_err(drm->dev, "failed to init vblank\n"); + goto out_config; } ret = mcde_display_init(drm); @@ -339,8 +331,6 @@ static int mcde_probe(struct platform_device *pdev) drm->dev_private = mcde; platform_set_drvdata(pdev, drm); - /* Enable use of the TE signal and interrupt */ - mcde->te_sync = true; /* Enable continuous updates: this is what Linux' framebuffer expects */ mcde->oneshot_mode = false; drm->dev_private = mcde; diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c index ef4c630afe3f..d76106743f84 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi.c +++ b/drivers/gpu/drm/mcde/mcde_dsi.c @@ -39,7 +39,6 @@ struct mcde_dsi { struct device *dev; struct mcde *mcde; struct drm_bridge bridge; - struct drm_connector connector; struct drm_panel *panel; struct drm_bridge *bridge_out; struct mipi_dsi_host dsi_host; @@ -64,11 +63,6 @@ static inline struct mcde_dsi *host_to_mcde_dsi(struct mipi_dsi_host *h) return container_of(h, struct mcde_dsi, dsi_host); } -static inline struct mcde_dsi *connector_to_mcde_dsi(struct drm_connector *c) -{ - return container_of(c, struct mcde_dsi, connector); -} - bool mcde_dsi_irq(struct mipi_dsi_device *mdsi) { struct mcde_dsi *d; @@ -124,12 +118,41 @@ bool mcde_dsi_irq(struct mipi_dsi_device *mdsi) val = readl(d->regs + DSI_VID_MODE_STS_FLAG); if (val) - dev_err(d->dev, "some video mode error status\n"); + dev_dbg(d->dev, "DSI_VID_MODE_STS_FLAG = %08x\n", val); + if (val & DSI_VID_MODE_STS_VSG_RUNNING) + dev_dbg(d->dev, "VID mode VSG running\n"); + if (val & DSI_VID_MODE_STS_ERR_MISSING_DATA) + dev_err(d->dev, "VID mode missing data\n"); + if (val & DSI_VID_MODE_STS_ERR_MISSING_HSYNC) + dev_err(d->dev, "VID mode missing HSYNC\n"); + if (val & DSI_VID_MODE_STS_ERR_MISSING_VSYNC) + dev_err(d->dev, "VID mode missing VSYNC\n"); + if (val & DSI_VID_MODE_STS_REG_ERR_SMALL_LENGTH) + dev_err(d->dev, "VID mode less bytes than expected between two HSYNC\n"); + if (val & DSI_VID_MODE_STS_REG_ERR_SMALL_HEIGHT) + dev_err(d->dev, "VID mode less lines than expected between two VSYNC\n"); + if (val & (DSI_VID_MODE_STS_ERR_BURSTWRITE | + DSI_VID_MODE_STS_ERR_LINEWRITE | + DSI_VID_MODE_STS_ERR_LONGREAD)) + dev_err(d->dev, "VID mode read/write error\n"); + if (val & DSI_VID_MODE_STS_ERR_VRS_WRONG_LENGTH) + dev_err(d->dev, "VID mode received packets differ from expected size\n"); + if (val & DSI_VID_MODE_STS_VSG_RECOVERY) + dev_err(d->dev, "VID mode VSG in recovery mode\n"); writel(val, d->regs + DSI_VID_MODE_STS_CLR); return te_received; } +static void mcde_dsi_attach_to_mcde(struct mcde_dsi *d) +{ + d->mcde->mdsi = d->mdsi; + + d->mcde->video_mode = !!(d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO); + /* Enable use of the TE signal for all command mode panels */ + d->mcde->te_sync = !d->mcde->video_mode; +} + static int mcde_dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *mdsi) { @@ -148,7 +171,7 @@ static int mcde_dsi_host_attach(struct mipi_dsi_host *host, d->mdsi = mdsi; if (d->mcde) - d->mcde->mdsi = mdsi; + mcde_dsi_attach_to_mcde(d); return 0; } @@ -223,25 +246,25 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, if (txlen > 0) { val = 0; for (i = 0; i < 4 && i < txlen; i++) - val |= tx[i] << (i & 3) * 8; + val |= tx[i] << (i * 8); } writel(val, d->regs + DSI_DIRECT_CMD_WRDAT0); if (txlen > 4) { val = 0; for (i = 0; i < 4 && (i + 4) < txlen; i++) - val |= tx[i + 4] << (i & 3) * 8; + val |= tx[i + 4] << (i * 8); writel(val, d->regs + DSI_DIRECT_CMD_WRDAT1); } if (txlen > 8) { val = 0; for (i = 0; i < 4 && (i + 8) < txlen; i++) - val |= tx[i + 8] << (i & 3) * 8; + val |= tx[i + 8] << (i * 8); writel(val, d->regs + DSI_DIRECT_CMD_WRDAT2); } if (txlen > 12) { val = 0; for (i = 0; i < 4 && (i + 12) < txlen; i++) - val |= tx[i + 12] << (i & 3) * 8; + val |= tx[i + 12] << (i * 8); writel(val, d->regs + DSI_DIRECT_CMD_WRDAT3); } @@ -336,7 +359,7 @@ void mcde_dsi_te_request(struct mipi_dsi_device *mdsi) val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT; val |= 2 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT; val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN; - val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_SHORT_WRITE_1 << + val |= MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT; writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS); @@ -539,26 +562,6 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d, DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT; writel(val, d->regs + DSI_VID_VCA_SETTING2); - /* Put IF1 into video mode */ - val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL); - val |= DSI_MCTL_MAIN_DATA_CTL_IF1_MODE; - writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL); - - /* Disable command mode on IF1 */ - val = readl(d->regs + DSI_CMD_MODE_CTL); - val &= ~DSI_CMD_MODE_CTL_IF1_LP_EN; - writel(val, d->regs + DSI_CMD_MODE_CTL); - - /* Enable some error interrupts */ - val = readl(d->regs + DSI_VID_MODE_STS_CTL); - val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC; - val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA; - writel(val, d->regs + DSI_VID_MODE_STS_CTL); - - /* Enable video mode */ - val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL); - val |= DSI_MCTL_MAIN_DATA_CTL_VID_EN; - writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL); } static void mcde_dsi_start(struct mcde_dsi *d) @@ -670,30 +673,25 @@ static void mcde_dsi_start(struct mcde_dsi *d) static void mcde_dsi_bridge_enable(struct drm_bridge *bridge) { struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); + u32 val; + + if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) { + /* Enable video mode */ + val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL); + val |= DSI_MCTL_MAIN_DATA_CTL_VID_EN; + writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL); + } dev_info(d->dev, "enable DSI master\n"); }; -static void mcde_dsi_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adj) +static void mcde_dsi_bridge_pre_enable(struct drm_bridge *bridge) { struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); - unsigned long pixel_clock_hz = mode->clock * 1000; unsigned long hs_freq, lp_freq; u32 val; int ret; - if (!d->mdsi) { - dev_err(d->dev, "no DSI device attached to encoder!\n"); - return; - } - - dev_info(d->dev, "set DSI master to %dx%d %lu Hz %s mode\n", - mode->hdisplay, mode->vdisplay, pixel_clock_hz, - (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ? "VIDEO" : "CMD" - ); - /* Copy maximum clock frequencies */ if (d->mdsi->lp_rate) lp_freq = d->mdsi->lp_rate; @@ -732,7 +730,21 @@ static void mcde_dsi_bridge_mode_set(struct drm_bridge *bridge, d->hs_freq); if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) { - mcde_dsi_setup_video_mode(d, mode); + /* Put IF1 into video mode */ + val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL); + val |= DSI_MCTL_MAIN_DATA_CTL_IF1_MODE; + writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL); + + /* Disable command mode on IF1 */ + val = readl(d->regs + DSI_CMD_MODE_CTL); + val &= ~DSI_CMD_MODE_CTL_IF1_LP_EN; + writel(val, d->regs + DSI_CMD_MODE_CTL); + + /* Enable some error interrupts */ + val = readl(d->regs + DSI_VID_MODE_STS_CTL); + val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC; + val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA; + writel(val, d->regs + DSI_VID_MODE_STS_CTL); } else { /* Command mode, clear IF1 ID */ val = readl(d->regs + DSI_CMD_MODE_CTL); @@ -746,6 +758,26 @@ static void mcde_dsi_bridge_mode_set(struct drm_bridge *bridge, } } +static void mcde_dsi_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adj) +{ + struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); + + if (!d->mdsi) { + dev_err(d->dev, "no DSI device attached to encoder!\n"); + return; + } + + dev_info(d->dev, "set DSI master to %dx%d %u Hz %s mode\n", + mode->hdisplay, mode->vdisplay, mode->clock * 1000, + (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ? "VIDEO" : "CMD" + ); + + if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) + mcde_dsi_setup_video_mode(d, mode); +} + static void mcde_dsi_wait_for_command_mode_stop(struct mcde_dsi *d) { u32 val; @@ -811,67 +843,23 @@ static void mcde_dsi_bridge_disable(struct drm_bridge *bridge) clk_disable_unprepare(d->lp_clk); } -/* - * This connector needs no special handling, just use the default - * helpers for everything. It's pretty dummy. - */ -static const struct drm_connector_funcs mcde_dsi_connector_funcs = { - .reset = drm_atomic_helper_connector_reset, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static int mcde_dsi_get_modes(struct drm_connector *connector) -{ - struct mcde_dsi *d = connector_to_mcde_dsi(connector); - - /* Just pass the question to the panel */ - if (d->panel) - return drm_panel_get_modes(d->panel); - - /* TODO: deal with bridges */ - - return 0; -} - -static const struct drm_connector_helper_funcs -mcde_dsi_connector_helper_funcs = { - .get_modes = mcde_dsi_get_modes, -}; - static int mcde_dsi_bridge_attach(struct drm_bridge *bridge) { struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); struct drm_device *drm = bridge->dev; int ret; - drm_connector_helper_add(&d->connector, - &mcde_dsi_connector_helper_funcs); - if (!drm_core_check_feature(drm, DRIVER_ATOMIC)) { dev_err(d->dev, "we need atomic updates\n"); return -ENOTSUPP; } - ret = drm_connector_init(drm, &d->connector, - &mcde_dsi_connector_funcs, - DRM_MODE_CONNECTOR_DSI); - if (ret) { - dev_err(d->dev, "failed to initialize DSI bridge connector\n"); - return ret; - } - d->connector.polled = DRM_CONNECTOR_POLL_CONNECT; - /* The encoder in the bridge attached to the DSI bridge */ - drm_connector_attach_encoder(&d->connector, bridge->encoder); - /* Then we attach the DSI bridge to the output (panel etc) bridge */ + /* Attach the DSI bridge to the output (panel etc) bridge */ ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge); if (ret) { dev_err(d->dev, "failed to attach the DSI bridge\n"); return ret; } - d->connector.status = connector_status_connected; return 0; } @@ -881,6 +869,7 @@ static const struct drm_bridge_funcs mcde_dsi_bridge_funcs = { .mode_set = mcde_dsi_bridge_mode_set, .disable = mcde_dsi_bridge_disable, .enable = mcde_dsi_bridge_enable, + .pre_enable = mcde_dsi_bridge_pre_enable, }; static int mcde_dsi_bind(struct device *dev, struct device *master, @@ -901,7 +890,7 @@ static int mcde_dsi_bind(struct device *dev, struct device *master, d->mcde = mcde; /* If the display attached before binding, set this up */ if (d->mdsi) - d->mcde->mdsi = d->mdsi; + mcde_dsi_attach_to_mcde(d); /* Obtain the clocks */ d->hs_clk = devm_clk_get(dev, "hs"); diff --git a/drivers/gpu/drm/mcde/mcde_dsi_regs.h b/drivers/gpu/drm/mcde/mcde_dsi_regs.h index c9253321a3be..8089db805c57 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi_regs.h +++ b/drivers/gpu/drm/mcde/mcde_dsi_regs.h @@ -123,17 +123,6 @@ #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT BIT(3) #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT 8 #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_MASK 0x00003F00 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_TURN_ON_PERIPHERAL 50 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHUT_DOWN_PERIPHERAL 34 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_SHORT_WRITE_0 3 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_SHORT_WRITE_1 19 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_SHORT_WRITE_2 35 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_LONG_WRITE 41 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_SHORT_WRITE_0 5 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_SHORT_WRITE_1 21 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_LONG_WRITE 57 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_READ 6 -#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SET_MAX_PKT_SIZE 55 #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT 14 #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT 16 #define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN BIT(21) @@ -248,6 +237,16 @@ #define DSI_VID_MODE_STS 0x000000BC #define DSI_VID_MODE_STS_VSG_RUNNING BIT(0) +#define DSI_VID_MODE_STS_ERR_MISSING_DATA BIT(1) +#define DSI_VID_MODE_STS_ERR_MISSING_HSYNC BIT(2) +#define DSI_VID_MODE_STS_ERR_MISSING_VSYNC BIT(3) +#define DSI_VID_MODE_STS_REG_ERR_SMALL_LENGTH BIT(4) +#define DSI_VID_MODE_STS_REG_ERR_SMALL_HEIGHT BIT(5) +#define DSI_VID_MODE_STS_ERR_BURSTWRITE BIT(6) +#define DSI_VID_MODE_STS_ERR_LINEWRITE BIT(7) +#define DSI_VID_MODE_STS_ERR_LONGREAD BIT(8) +#define DSI_VID_MODE_STS_ERR_VRS_WRONG_LENGTH BIT(9) +#define DSI_VID_MODE_STS_VSG_RECOVERY BIT(10) #define DSI_VID_VCA_SETTING1 0x000000C0 #define DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_SHIFT 0 |