/* * drivers/staging/omapdrm/omap_encoder.c * * Copyright (C) 2011 Texas Instruments * Author: Rob Clark <rob@ti.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ #include "omap_drv.h" #include "drm_crtc.h" #include "drm_crtc_helper.h" /* * encoder funcs */ #define to_omap_encoder(x) container_of(x, struct omap_encoder, base) struct omap_encoder { struct drm_encoder base; struct omap_overlay_manager *mgr; }; static void omap_encoder_destroy(struct drm_encoder *encoder) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); DBG("%s", omap_encoder->mgr->name); drm_encoder_cleanup(encoder); kfree(omap_encoder); } static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); DBG("%s: %d", omap_encoder->mgr->name, mode); } static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); DBG("%s", omap_encoder->mgr->name); return true; } static void omap_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); struct drm_device *dev = encoder->dev; struct omap_drm_private *priv = dev->dev_private; int i; mode = adjusted_mode; DBG("%s: set mode: %dx%d", omap_encoder->mgr->name, mode->hdisplay, mode->vdisplay); for (i = 0; i < priv->num_connectors; i++) { struct drm_connector *connector = priv->connectors[i]; if (connector->encoder == encoder) { omap_connector_mode_set(connector, mode); } } } static void omap_encoder_prepare(struct drm_encoder *encoder) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; DBG("%s", omap_encoder->mgr->name); encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); } static void omap_encoder_commit(struct drm_encoder *encoder) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; DBG("%s", omap_encoder->mgr->name); omap_encoder->mgr->apply(omap_encoder->mgr); encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); } static const struct drm_encoder_funcs omap_encoder_funcs = { .destroy = omap_encoder_destroy, }; static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { .dpms = omap_encoder_dpms, .mode_fixup = omap_encoder_mode_fixup, .mode_set = omap_encoder_mode_set, .prepare = omap_encoder_prepare, .commit = omap_encoder_commit, }; struct omap_overlay_manager *omap_encoder_get_manager( struct drm_encoder *encoder) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); return omap_encoder->mgr; } /* initialize encoder */ struct drm_encoder *omap_encoder_init(struct drm_device *dev, struct omap_overlay_manager *mgr) { struct drm_encoder *encoder = NULL; struct omap_encoder *omap_encoder; struct omap_overlay_manager_info info; int ret; DBG("%s", mgr->name); omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL); if (!omap_encoder) { dev_err(dev->dev, "could not allocate encoder\n"); goto fail; } omap_encoder->mgr = mgr; encoder = &omap_encoder->base; drm_encoder_init(dev, encoder, &omap_encoder_funcs, DRM_MODE_ENCODER_TMDS); drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs); mgr->get_manager_info(mgr, &info); /* TODO: fix hard-coded setup.. */ info.default_color = 0x00000000; info.trans_key = 0x00000000; info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; info.trans_enabled = false; ret = mgr->set_manager_info(mgr, &info); if (ret) { dev_err(dev->dev, "could not set manager info\n"); goto fail; } ret = mgr->apply(mgr); if (ret) { dev_err(dev->dev, "could not apply\n"); goto fail; } return encoder; fail: if (encoder) { omap_encoder_destroy(encoder); } return NULL; }