diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 05:54:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 05:54:23 -0700 |
commit | 37be944a0270402f9cda291a930b0286f6dc92f5 (patch) | |
tree | 6a91a9eb86450f4a18a8871f04a1ef810e7b55d6 /drivers/gpu/drm/exynos/exynos_drm_encoder.c | |
parent | ca836a25435ef1b9914840ed0a310c9b6ac261d1 (diff) | |
parent | 1717c0e23f411147490c7a3312b894f0ea9a5fb1 (diff) |
Merge branch 'drm-core-next' of git://people.freedesktop.org/~airlied/linux
* 'drm-core-next' of git://people.freedesktop.org/~airlied/linux: (290 commits)
Revert "drm/ttm: add a way to bo_wait for either the last read or last write"
Revert "drm/radeon/kms: add a new gem_wait ioctl with read/write flags"
vmwgfx: Don't pass unused arguments to do_dirty functions
vmwgfx: Emulate depth 32 framebuffers
drm/radeon: Lower the severity of the radeon lockup messages.
drm/i915/dp: Fix eDP on PCH DP on CPT/PPT
drm/i915/dp: Introduce is_cpu_edp()
drm/i915: use correct SPD type value
drm/i915: fix ILK+ infoframe support
drm/i915: add DP test request handling
drm/i915: read full receiver capability field during DP hot plug
drm/i915/dp: Remove eDP special cases from bandwidth checks
drm/i915/dp: Fix the math in intel_dp_link_required
drm/i915/panel: Always record the backlight level again (but cleverly)
i915: Move i915_read/write out of line
drm/i915: remove transcoder PLL mashing from mode_set per specs
drm/i915: if transcoder disable fails, say which
drm/i915: set watermarks for third pipe on IVB
drm/i915: export a CPT mode set verification function
drm/i915: fix transcoder PLL select masking
...
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_encoder.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_encoder.c | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c new file mode 100644 index 000000000000..7cf6fa86a67e --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -0,0 +1,271 @@ +/* exynos_drm_encoder.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Authors: + * Inki Dae <inki.dae@samsung.com> + * Joonyoung Shim <jy0922.shim@samsung.com> + * Seung-Woo Kim <sw0312.kim@samsung.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" +#include "drm_crtc_helper.h" + +#include "exynos_drm_drv.h" +#include "exynos_drm_crtc.h" +#include "exynos_drm_encoder.h" + +#define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\ + drm_encoder) + +/* + * exynos specific encoder structure. + * + * @drm_encoder: encoder object. + * @manager: specific encoder has its own manager to control a hardware + * appropriately and we can access a hardware drawing on this manager. + */ +struct exynos_drm_encoder { + struct drm_encoder drm_encoder; + struct exynos_drm_manager *manager; +}; + +static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_connector *connector; + struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); + + DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode); + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->encoder == encoder) { + struct exynos_drm_display *display = manager->display; + + if (display && display->power_on) + display->power_on(manager->dev, mode); + } + } +} + +static bool +exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + DRM_DEBUG_KMS("%s\n", __FILE__); + + /* drm framework doesn't check NULL. */ + + return true; +} + +static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_connector *connector; + struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); + struct exynos_drm_manager_ops *manager_ops = manager->ops; + struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; + struct exynos_drm_overlay *overlay = get_exynos_drm_overlay(dev, + encoder->crtc); + + DRM_DEBUG_KMS("%s\n", __FILE__); + + mode = adjusted_mode; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->encoder == encoder) { + if (manager_ops && manager_ops->mode_set) + manager_ops->mode_set(manager->dev, mode); + + if (overlay_ops && overlay_ops->mode_set) + overlay_ops->mode_set(manager->dev, overlay); + } + } +} + +static void exynos_drm_encoder_prepare(struct drm_encoder *encoder) +{ + DRM_DEBUG_KMS("%s\n", __FILE__); + + /* drm framework doesn't check NULL. */ +} + +static void exynos_drm_encoder_commit(struct drm_encoder *encoder) +{ + struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); + struct exynos_drm_manager_ops *manager_ops = manager->ops; + struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + if (manager_ops && manager_ops->commit) + manager_ops->commit(manager->dev); + + if (overlay_ops && overlay_ops->commit) + overlay_ops->commit(manager->dev); +} + +static struct drm_crtc * +exynos_drm_encoder_get_crtc(struct drm_encoder *encoder) +{ + return encoder->crtc; +} + +static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = { + .dpms = exynos_drm_encoder_dpms, + .mode_fixup = exynos_drm_encoder_mode_fixup, + .mode_set = exynos_drm_encoder_mode_set, + .prepare = exynos_drm_encoder_prepare, + .commit = exynos_drm_encoder_commit, + .get_crtc = exynos_drm_encoder_get_crtc, +}; + +static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) +{ + struct exynos_drm_encoder *exynos_encoder = + to_exynos_encoder(encoder); + + DRM_DEBUG_KMS("%s\n", __FILE__); + + exynos_encoder->manager->pipe = -1; + + drm_encoder_cleanup(encoder); + encoder->dev->mode_config.num_encoder--; + kfree(exynos_encoder); +} + +static struct drm_encoder_funcs exynos_encoder_funcs = { + .destroy = exynos_drm_encoder_destroy, +}; + +struct drm_encoder * +exynos_drm_encoder_create(struct drm_device *dev, + struct exynos_drm_manager *manager, + unsigned int possible_crtcs) +{ + struct drm_encoder *encoder; + struct exynos_drm_encoder *exynos_encoder; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + if (!manager || !possible_crtcs) + return NULL; + + if (!manager->dev) + return NULL; + + exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL); + if (!exynos_encoder) { + DRM_ERROR("failed to allocate encoder\n"); + return NULL; + } + + exynos_encoder->manager = manager; + encoder = &exynos_encoder->drm_encoder; + encoder->possible_crtcs = possible_crtcs; + + DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); + + drm_encoder_init(dev, encoder, &exynos_encoder_funcs, + DRM_MODE_ENCODER_TMDS); + + drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs); + + DRM_DEBUG_KMS("encoder has been created\n"); + + return encoder; +} + +struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder) +{ + return to_exynos_encoder(encoder)->manager; +} + +void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, + void (*fn)(struct drm_encoder *, void *)) +{ + struct drm_device *dev = crtc->dev; + struct drm_encoder *encoder; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc != crtc) + continue; + + fn(encoder, data); + } +} + +void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data) +{ + struct exynos_drm_manager *manager = + to_exynos_encoder(encoder)->manager; + struct exynos_drm_manager_ops *manager_ops = manager->ops; + int crtc = *(int *)data; + + if (manager->pipe == -1) + manager->pipe = crtc; + + if (manager_ops->enable_vblank) + manager_ops->enable_vblank(manager->dev); +} + +void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data) +{ + struct exynos_drm_manager *manager = + to_exynos_encoder(encoder)->manager; + struct exynos_drm_manager_ops *manager_ops = manager->ops; + int crtc = *(int *)data; + + if (manager->pipe == -1) + manager->pipe = crtc; + + if (manager_ops->disable_vblank) + manager_ops->disable_vblank(manager->dev); +} + +void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) +{ + struct exynos_drm_manager *manager = + to_exynos_encoder(encoder)->manager; + struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; + + overlay_ops->commit(manager->dev); +} + +void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data) +{ + struct exynos_drm_manager *manager = + to_exynos_encoder(encoder)->manager; + struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; + struct exynos_drm_overlay *overlay = data; + + overlay_ops->mode_set(manager->dev, overlay); +} + +MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); +MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); +MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>"); +MODULE_DESCRIPTION("Samsung SoC DRM Encoder Driver"); +MODULE_LICENSE("GPL"); |