Skip to content

Commit

Permalink
Merge branch 'exynos-drm-fixes' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/daeinki/drm-exynos into drm-fixes

   This pull-request fixes hdmi power-off order issue, mixer issues
   related to power on/off, and includes trivial fixups.

* 'exynos-drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: enable vsync interrupt while waiting for vblank
  drm/exynos: soft reset mixer before reconfigure after power-on
  drm/exynos: allow multiple layer updates per vsync for mixer
  drm/exynos: stop mixer before gating clocks during poweroff
  drm/exynos: set power state variable after enabling clocks and power
  drm/exynos: disable unused windows on apply
  drm/exynos: Fix de-registration ordering
  drm/exynos: change zero to NULL for sparse
  drm/exynos: dpi: Fix NULL pointer dereference with legacy bindings
  drm/exynos: hdmi: fix power order issue
  • Loading branch information
Dave Airlie committed Jun 25, 2014
2 parents b0a2c15 + 5d39b9e commit b5f4843
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 21 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/exynos_drm_dpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ exynos_dpi_detect(struct drm_connector *connector, bool force)
{
struct exynos_dpi *ctx = connector_to_dpi(connector);

if (!ctx->panel->connector)
if (ctx->panel && !ctx->panel->connector)
drm_panel_attach(ctx->panel, &ctx->connector);

return connector_status_connected;
Expand Down
8 changes: 4 additions & 4 deletions drivers/gpu/drm/exynos/exynos_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,24 +765,24 @@ static int exynos_drm_init(void)

return 0;

err_unregister_pd:
platform_device_unregister(exynos_drm_pdev);

err_remove_vidi:
#ifdef CONFIG_DRM_EXYNOS_VIDI
exynos_drm_remove_vidi();

err_unregister_pd:
#endif
platform_device_unregister(exynos_drm_pdev);

return ret;
}

static void exynos_drm_exit(void)
{
platform_driver_unregister(&exynos_drm_platform_driver);
#ifdef CONFIG_DRM_EXYNOS_VIDI
exynos_drm_remove_vidi();
#endif
platform_device_unregister(exynos_drm_pdev);
platform_driver_unregister(&exynos_drm_platform_driver);
}

module_init(exynos_drm_init);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/exynos_drm_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ struct exynos_drm_display * exynos_dpi_probe(struct device *dev);
int exynos_dpi_remove(struct device *dev);
#else
static inline struct exynos_drm_display *
exynos_dpi_probe(struct device *dev) { return 0; }
exynos_dpi_probe(struct device *dev) { return NULL; }
static inline int exynos_dpi_remove(struct device *dev) { return 0; }
#endif

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_fimd.c
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,8 @@ static void fimd_apply(struct exynos_drm_manager *mgr)
win_data = &ctx->win_data[i];
if (win_data->enabled)
fimd_win_commit(mgr, i);
else
fimd_win_disable(mgr, i);
}

fimd_commit(mgr);
Expand Down
19 changes: 19 additions & 0 deletions drivers/gpu/drm/exynos/exynos_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2090,6 +2090,11 @@ static void hdmi_poweroff(struct exynos_drm_display *display)

static void hdmi_dpms(struct exynos_drm_display *display, int mode)
{
struct hdmi_context *hdata = display->ctx;
struct drm_encoder *encoder = hdata->encoder;
struct drm_crtc *crtc = encoder->crtc;
struct drm_crtc_helper_funcs *funcs = NULL;

DRM_DEBUG_KMS("mode %d\n", mode);

switch (mode) {
Expand All @@ -2099,6 +2104,20 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode)
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
/*
* The SFRs of VP and Mixer are updated by Vertical Sync of
* Timing generator which is a part of HDMI so the sequence
* to disable TV Subsystem should be as following,
* VP -> Mixer -> HDMI
*
* Below codes will try to disable Mixer and VP(if used)
* prior to disabling HDMI.
*/
if (crtc)
funcs = crtc->helper_private;
if (funcs && funcs->dpms)
(*funcs->dpms)(crtc, mode);

hdmi_poweroff(display);
break;
default:
Expand Down
50 changes: 35 additions & 15 deletions drivers/gpu/drm/exynos/exynos_mixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,20 @@ static void mixer_run(struct mixer_context *ctx)
mixer_regs_dump(ctx);
}

static void mixer_stop(struct mixer_context *ctx)
{
struct mixer_resources *res = &ctx->mixer_res;
int timeout = 20;

mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);

while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
--timeout)
usleep_range(10000, 12000);

mixer_regs_dump(ctx);
}

static void vp_video_buffer(struct mixer_context *ctx, int win)
{
struct mixer_resources *res = &ctx->mixer_res;
Expand Down Expand Up @@ -497,13 +511,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
static void mixer_layer_update(struct mixer_context *ctx)
{
struct mixer_resources *res = &ctx->mixer_res;
u32 val;

val = mixer_reg_read(res, MXR_CFG);

/* allow one update per vsync only */
if (!(val & MXR_CFG_LAYER_UPDATE_COUNT_MASK))
mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
}

static void mixer_graph_buffer(struct mixer_context *ctx, int win)
Expand Down Expand Up @@ -1010,6 +1019,8 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
}
mutex_unlock(&mixer_ctx->mixer_mutex);

drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe);

atomic_set(&mixer_ctx->wait_vsync_event, 1);

/*
Expand All @@ -1020,6 +1031,8 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
!atomic_read(&mixer_ctx->wait_vsync_event),
HZ/20))
DRM_DEBUG_KMS("vblank wait timed out.\n");

drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe);
}

static void mixer_window_suspend(struct exynos_drm_manager *mgr)
Expand Down Expand Up @@ -1061,7 +1074,7 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
mutex_unlock(&ctx->mixer_mutex);
return;
}
ctx->powered = true;

mutex_unlock(&ctx->mixer_mutex);

pm_runtime_get_sync(ctx->dev);
Expand All @@ -1072,6 +1085,12 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
clk_prepare_enable(res->sclk_mixer);
}

mutex_lock(&ctx->mixer_mutex);
ctx->powered = true;
mutex_unlock(&ctx->mixer_mutex);

mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);

mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
mixer_win_reset(ctx);

Expand All @@ -1084,27 +1103,28 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
struct mixer_resources *res = &ctx->mixer_res;

mutex_lock(&ctx->mixer_mutex);
if (!ctx->powered)
goto out;
if (!ctx->powered) {
mutex_unlock(&ctx->mixer_mutex);
return;
}
mutex_unlock(&ctx->mixer_mutex);

mixer_stop(ctx);
mixer_window_suspend(mgr);

ctx->int_en = mixer_reg_read(res, MXR_INT_EN);

mutex_lock(&ctx->mixer_mutex);
ctx->powered = false;
mutex_unlock(&ctx->mixer_mutex);

clk_disable_unprepare(res->mixer);
if (ctx->vp_enabled) {
clk_disable_unprepare(res->vp);
clk_disable_unprepare(res->sclk_mixer);
}

pm_runtime_put_sync(ctx->dev);

mutex_lock(&ctx->mixer_mutex);
ctx->powered = false;

out:
mutex_unlock(&ctx->mixer_mutex);
}

static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/exynos/regs-mixer.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
#define MXR_STATUS_BIG_ENDIAN (1 << 3)
#define MXR_STATUS_ENDIAN_MASK (1 << 3)
#define MXR_STATUS_SYNC_ENABLE (1 << 2)
#define MXR_STATUS_REG_IDLE (1 << 1)
#define MXR_STATUS_REG_RUN (1 << 0)

/* bits for MXR_CFG */
Expand Down

0 comments on commit b5f4843

Please sign in to comment.