diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-17 02:48:00 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-17 02:48:00 +0300 |
commit | 796e1c55717e9a6ff5c81b12289ffa1ffd919b6f (patch) | |
tree | 27ce45cb1227156b72c641dbcbf2b399d23ba63d /drivers/gpu/drm/exynos/exynos_mixer.c | |
parent | 8c334ce8f0fec7122fc3059c52a697b669a01b41 (diff) | |
parent | 45ee2dbc65cbf6910892c480e6f428be342fa733 (diff) | |
download | linux-796e1c55717e9a6ff5c81b12289ffa1ffd919b6f.tar.xz |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main drm pull, it has a shared branch with some alsa
crossover but everything should be acked by relevant people.
New drivers:
- ATMEL HLCDC driver
- designware HDMI core support (used in multiple SoCs).
core:
- lots more atomic modesetting work, properties and atomic ioctl
(hidden under option)
- bridge rework allows support for Samsung exynos chromebooks to
work finally.
- some more panels supported
i915:
- atomic plane update support
- DSI uses shared DSI infrastructure
- Skylake basic support is all merged now
- component framework used for i915/snd-hda interactions
- write-combine cpu memory mappings
- engine init code refactored
- full ppgtt enabled where execlists are enabled.
- cherryview rps/gpu turbo and pipe CRC support.
radeon:
- indirect draw support for evergreen/cayman
- SMC and manual fan control for SI/CI
- Displayport audio support
amdkfd:
- SDMA usermode queue support
- replace suballocator usage with more suitable one
- rework for allowing interfacing to more than radeon
nouveau:
- major renaming in prep for later splitting work
- merge arm platform driver into nouveau
- GK20A reclocking support
msm:
- conversion to atomic modesetting
- YUV support for mdp4/5
- eDP support
- hw cursor for mdp5
tegra:
- conversion to atomic modesetting
- better suspend/resume support for child devices
rcar-du:
- interlaced support
imx:
- move to using dw_hdmi shared support
- mode_fixup support
sti:
- DVO support
- HDMI infoframe support
exynos:
- refactoring and cleanup, removed lots of internal unnecessary
abstraction
- exynos7 DECON display controller support
Along with the usual bunch of fixes, cleanups etc"
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (724 commits)
drm/radeon: fix voltage setup on hawaii
drm/radeon/dp: Set EDP_CONFIGURATION_SET for bridge chips if necessary
drm/radeon: only enable kv/kb dpm interrupts once v3
drm/radeon: workaround for CP HW bug on CIK
drm/radeon: Don't try to enable write-combining without PAT
drm/radeon: use 0-255 rather than 0-100 for pwm fan range
drm/i915: Clamp efficient frequency to valid range
drm/i915: Really ignore long HPD pulses on eDP
drm/exynos: Add DECON driver
drm/i915: Correct the base value while updating LP_OUTPUT_HOLD in MIPI_PORT_CTRL
drm/i915: Insert a command barrier on BLT/BSD cache flushes
drm/i915: Drop vblank wait from intel_dp_link_down
drm/exynos: fix NULL pointer reference
drm/exynos: remove exynos_plane_dpms
drm/exynos: remove mode property of exynos crtc
drm/exynos: Remove exynos_plane_dpms() call with no effect
drm/i915: Squelch overzealous uncore reset WARN_ON
drm/i915: Take runtime pm reference on hangcheck_info
drm/i915: Correct the IOSF Dev_FN field for IOSF transfers
drm/exynos: fix DMA_ATTR_NO_KERNEL_MAPPING usage
...
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_mixer.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 165 |
1 files changed, 82 insertions, 83 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 064ed6597def..3518bc4654c5 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -72,6 +72,7 @@ struct mixer_resources { spinlock_t reg_slock; struct clk *mixer; struct clk *vp; + struct clk *hdmi; struct clk *sclk_mixer; struct clk *sclk_hdmi; struct clk *mout_mixer; @@ -84,10 +85,10 @@ enum mixer_version_id { }; struct mixer_context { - struct exynos_drm_manager manager; struct platform_device *pdev; struct device *dev; struct drm_device *drm_dev; + struct exynos_drm_crtc *crtc; int pipe; bool interlace; bool powered; @@ -103,11 +104,6 @@ struct mixer_context { atomic_t wait_vsync_event; }; -static inline struct mixer_context *mgr_to_mixer(struct exynos_drm_manager *mgr) -{ - return container_of(mgr, struct mixer_context, manager); -} - struct mixer_drv_data { enum mixer_version_id version; bool is_vp_enabled; @@ -417,8 +413,6 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) win_data = &ctx->win_data[win]; switch (win_data->pixel_format) { - case DRM_FORMAT_NV12MT: - tiled_mode = true; case DRM_FORMAT_NV12: crcb_mode = false; buf_num = 2; @@ -587,8 +581,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win) /* setup display size */ if (ctx->mxr_ver == MXR_VER_128_0_0_184 && win == MIXER_DEFAULT_WIN) { - val = MXR_MXR_RES_HEIGHT(win_data->fb_height); - val |= MXR_MXR_RES_WIDTH(win_data->fb_width); + val = MXR_MXR_RES_HEIGHT(win_data->mode_height); + val |= MXR_MXR_RES_WIDTH(win_data->mode_width); mixer_reg_write(res, MXR_RESOLUTION, val); } @@ -774,6 +768,12 @@ static int mixer_resources_init(struct mixer_context *mixer_ctx) return -ENODEV; } + mixer_res->hdmi = devm_clk_get(dev, "hdmi"); + if (IS_ERR(mixer_res->hdmi)) { + dev_err(dev, "failed to get clock 'hdmi'\n"); + return PTR_ERR(mixer_res->hdmi); + } + mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); if (IS_ERR(mixer_res->sclk_hdmi)) { dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); @@ -854,16 +854,15 @@ static int vp_resources_init(struct mixer_context *mixer_ctx) return 0; } -static int mixer_initialize(struct exynos_drm_manager *mgr, +static int mixer_initialize(struct mixer_context *mixer_ctx, struct drm_device *drm_dev) { int ret; - struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); struct exynos_drm_private *priv; priv = drm_dev->dev_private; - mgr->drm_dev = mixer_ctx->drm_dev = drm_dev; - mgr->pipe = mixer_ctx->pipe = priv->pipe++; + mixer_ctx->drm_dev = drm_dev; + mixer_ctx->pipe = priv->pipe++; /* acquire resources: regs, irqs, clocks */ ret = mixer_resources_init(mixer_ctx); @@ -887,17 +886,15 @@ static int mixer_initialize(struct exynos_drm_manager *mgr, return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev); } -static void mixer_mgr_remove(struct exynos_drm_manager *mgr) +static void mixer_ctx_remove(struct mixer_context *mixer_ctx) { - struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); - if (is_drm_iommu_supported(mixer_ctx->drm_dev)) drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev); } -static int mixer_enable_vblank(struct exynos_drm_manager *mgr) +static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) { - struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); + struct mixer_context *mixer_ctx = crtc->ctx; struct mixer_resources *res = &mixer_ctx->mixer_res; if (!mixer_ctx->powered) { @@ -912,34 +909,34 @@ static int mixer_enable_vblank(struct exynos_drm_manager *mgr) return 0; } -static void mixer_disable_vblank(struct exynos_drm_manager *mgr) +static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) { - struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); + struct mixer_context *mixer_ctx = crtc->ctx; struct mixer_resources *res = &mixer_ctx->mixer_res; /* disable vsync interrupt */ mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); } -static void mixer_win_mode_set(struct exynos_drm_manager *mgr, - struct exynos_drm_overlay *overlay) +static void mixer_win_mode_set(struct exynos_drm_crtc *crtc, + struct exynos_drm_plane *plane) { - struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); + struct mixer_context *mixer_ctx = crtc->ctx; struct hdmi_win_data *win_data; int win; - if (!overlay) { - DRM_ERROR("overlay is NULL\n"); + if (!plane) { + DRM_ERROR("plane is NULL\n"); return; } DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n", - overlay->fb_width, overlay->fb_height, - overlay->fb_x, overlay->fb_y, - overlay->crtc_width, overlay->crtc_height, - overlay->crtc_x, overlay->crtc_y); + plane->fb_width, plane->fb_height, + plane->fb_x, plane->fb_y, + plane->crtc_width, plane->crtc_height, + plane->crtc_x, plane->crtc_y); - win = overlay->zpos; + win = plane->zpos; if (win == DEFAULT_ZPOS) win = MIXER_DEFAULT_WIN; @@ -950,32 +947,32 @@ static void mixer_win_mode_set(struct exynos_drm_manager *mgr, win_data = &mixer_ctx->win_data[win]; - win_data->dma_addr = overlay->dma_addr[0]; - win_data->chroma_dma_addr = overlay->dma_addr[1]; - win_data->pixel_format = overlay->pixel_format; - win_data->bpp = overlay->bpp; + win_data->dma_addr = plane->dma_addr[0]; + win_data->chroma_dma_addr = plane->dma_addr[1]; + win_data->pixel_format = plane->pixel_format; + win_data->bpp = plane->bpp; - win_data->crtc_x = overlay->crtc_x; - win_data->crtc_y = overlay->crtc_y; - win_data->crtc_width = overlay->crtc_width; - win_data->crtc_height = overlay->crtc_height; + win_data->crtc_x = plane->crtc_x; + win_data->crtc_y = plane->crtc_y; + win_data->crtc_width = plane->crtc_width; + win_data->crtc_height = plane->crtc_height; - win_data->fb_x = overlay->fb_x; - win_data->fb_y = overlay->fb_y; - win_data->fb_width = overlay->fb_width; - win_data->fb_height = overlay->fb_height; - win_data->src_width = overlay->src_width; - win_data->src_height = overlay->src_height; + win_data->fb_x = plane->fb_x; + win_data->fb_y = plane->fb_y; + win_data->fb_width = plane->fb_width; + win_data->fb_height = plane->fb_height; + win_data->src_width = plane->src_width; + win_data->src_height = plane->src_height; - win_data->mode_width = overlay->mode_width; - win_data->mode_height = overlay->mode_height; + win_data->mode_width = plane->mode_width; + win_data->mode_height = plane->mode_height; - win_data->scan_flags = overlay->scan_flag; + win_data->scan_flags = plane->scan_flag; } -static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos) +static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos) { - struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); + struct mixer_context *mixer_ctx = crtc->ctx; int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; DRM_DEBUG_KMS("win: %d\n", win); @@ -995,9 +992,9 @@ static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos) mixer_ctx->win_data[win].enabled = true; } -static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) +static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos) { - struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); + struct mixer_context *mixer_ctx = crtc->ctx; struct mixer_resources *res = &mixer_ctx->mixer_res; int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; unsigned long flags; @@ -1023,9 +1020,9 @@ static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) mixer_ctx->win_data[win].enabled = false; } -static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) +static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) { - struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); + struct mixer_context *mixer_ctx = crtc->ctx; int err; mutex_lock(&mixer_ctx->mixer_mutex); @@ -1035,7 +1032,7 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) } mutex_unlock(&mixer_ctx->mixer_mutex); - err = drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe); + err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe); if (err < 0) { DRM_DEBUG_KMS("failed to acquire vblank counter\n"); return; @@ -1052,26 +1049,24 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) HZ/20)) DRM_DEBUG_KMS("vblank wait timed out.\n"); - drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe); + drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe); } -static void mixer_window_suspend(struct exynos_drm_manager *mgr) +static void mixer_window_suspend(struct mixer_context *ctx) { - struct mixer_context *ctx = mgr_to_mixer(mgr); struct hdmi_win_data *win_data; int i; for (i = 0; i < MIXER_WIN_NR; i++) { win_data = &ctx->win_data[i]; win_data->resume = win_data->enabled; - mixer_win_disable(mgr, i); + mixer_win_disable(ctx->crtc, i); } - mixer_wait_for_vblank(mgr); + mixer_wait_for_vblank(ctx->crtc); } -static void mixer_window_resume(struct exynos_drm_manager *mgr) +static void mixer_window_resume(struct mixer_context *ctx) { - struct mixer_context *ctx = mgr_to_mixer(mgr); struct hdmi_win_data *win_data; int i; @@ -1080,13 +1075,12 @@ static void mixer_window_resume(struct exynos_drm_manager *mgr) win_data->enabled = win_data->resume; win_data->resume = false; if (win_data->enabled) - mixer_win_commit(mgr, i); + mixer_win_commit(ctx->crtc, i); } } -static void mixer_poweron(struct exynos_drm_manager *mgr) +static void mixer_poweron(struct mixer_context *ctx) { - struct mixer_context *ctx = mgr_to_mixer(mgr); struct mixer_resources *res = &ctx->mixer_res; mutex_lock(&ctx->mixer_mutex); @@ -1100,6 +1094,7 @@ static void mixer_poweron(struct exynos_drm_manager *mgr) pm_runtime_get_sync(ctx->dev); clk_prepare_enable(res->mixer); + clk_prepare_enable(res->hdmi); if (ctx->vp_enabled) { clk_prepare_enable(res->vp); if (ctx->has_sclk) @@ -1115,12 +1110,11 @@ static void mixer_poweron(struct exynos_drm_manager *mgr) mixer_reg_write(res, MXR_INT_EN, ctx->int_en); mixer_win_reset(ctx); - mixer_window_resume(mgr); + mixer_window_resume(ctx); } -static void mixer_poweroff(struct exynos_drm_manager *mgr) +static void mixer_poweroff(struct mixer_context *ctx) { - struct mixer_context *ctx = mgr_to_mixer(mgr); struct mixer_resources *res = &ctx->mixer_res; mutex_lock(&ctx->mixer_mutex); @@ -1131,7 +1125,7 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr) mutex_unlock(&ctx->mixer_mutex); mixer_stop(ctx); - mixer_window_suspend(mgr); + mixer_window_suspend(ctx); ctx->int_en = mixer_reg_read(res, MXR_INT_EN); @@ -1139,6 +1133,7 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr) ctx->powered = false; mutex_unlock(&ctx->mixer_mutex); + clk_disable_unprepare(res->hdmi); clk_disable_unprepare(res->mixer); if (ctx->vp_enabled) { clk_disable_unprepare(res->vp); @@ -1149,16 +1144,16 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr) pm_runtime_put_sync(ctx->dev); } -static void mixer_dpms(struct exynos_drm_manager *mgr, int mode) +static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode) { switch (mode) { case DRM_MODE_DPMS_ON: - mixer_poweron(mgr); + mixer_poweron(crtc->ctx); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - mixer_poweroff(mgr); + mixer_poweroff(crtc->ctx); break; default: DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); @@ -1186,7 +1181,7 @@ int mixer_check_mode(struct drm_display_mode *mode) return -EINVAL; } -static struct exynos_drm_manager_ops mixer_manager_ops = { +static struct exynos_drm_crtc_ops mixer_crtc_ops = { .dpms = mixer_dpms, .enable_vblank = mixer_enable_vblank, .disable_vblank = mixer_disable_vblank, @@ -1257,24 +1252,31 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) struct drm_device *drm_dev = data; int ret; - ret = mixer_initialize(&ctx->manager, drm_dev); + ret = mixer_initialize(ctx, drm_dev); if (ret) return ret; - ret = exynos_drm_crtc_create(&ctx->manager); - if (ret) { - mixer_mgr_remove(&ctx->manager); - return ret; + ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, + EXYNOS_DISPLAY_TYPE_HDMI, + &mixer_crtc_ops, ctx); + if (IS_ERR(ctx->crtc)) { + mixer_ctx_remove(ctx); + ret = PTR_ERR(ctx->crtc); + goto free_ctx; } return 0; + +free_ctx: + devm_kfree(dev, ctx); + return ret; } static void mixer_unbind(struct device *dev, struct device *master, void *data) { struct mixer_context *ctx = dev_get_drvdata(dev); - mixer_mgr_remove(&ctx->manager); + mixer_ctx_remove(ctx); } static const struct component_ops mixer_component_ops = { @@ -1297,9 +1299,6 @@ static int mixer_probe(struct platform_device *pdev) mutex_init(&ctx->mixer_mutex); - ctx->manager.type = EXYNOS_DISPLAY_TYPE_HDMI; - ctx->manager.ops = &mixer_manager_ops; - if (dev->of_node) { const struct of_device_id *match; @@ -1321,7 +1320,7 @@ static int mixer_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctx); ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC, - ctx->manager.type); + EXYNOS_DISPLAY_TYPE_HDMI); if (ret) return ret; |