1/* 2 * drivers/staging/omapdrm/omap_encoder.c 3 * 4 * Copyright (C) 2011 Texas Instruments 5 * Author: Rob Clark <rob@ti.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 * more details. 15 * 16 * You should have received a copy of the GNU General Public License along with 17 * this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20#include "omap_drv.h" 21 22#include "drm_crtc.h" 23#include "drm_crtc_helper.h" 24 25/* 26 * encoder funcs 27 */ 28 29#define to_omap_encoder(x) container_of(x, struct omap_encoder, base) 30 31struct omap_encoder { 32 struct drm_encoder base; 33 struct omap_overlay_manager *mgr; 34}; 35 36static void omap_encoder_destroy(struct drm_encoder *encoder) 37{ 38 struct omap_encoder *omap_encoder = to_omap_encoder(encoder); 39 DBG("%s", omap_encoder->mgr->name); 40 drm_encoder_cleanup(encoder); 41 kfree(omap_encoder); 42} 43 44static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) 45{ 46 struct omap_encoder *omap_encoder = to_omap_encoder(encoder); 47 DBG("%s: %d", omap_encoder->mgr->name, mode); 48} 49 50static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, 51 struct drm_display_mode *mode, 52 struct drm_display_mode *adjusted_mode) 53{ 54 struct omap_encoder *omap_encoder = to_omap_encoder(encoder); 55 DBG("%s", omap_encoder->mgr->name); 56 return true; 57} 58 59static void omap_encoder_mode_set(struct drm_encoder *encoder, 60 struct drm_display_mode *mode, 61 struct drm_display_mode *adjusted_mode) 62{ 63 struct omap_encoder *omap_encoder = to_omap_encoder(encoder); 64 struct drm_device *dev = encoder->dev; 65 struct omap_drm_private *priv = dev->dev_private; 66 int i; 67 68 mode = adjusted_mode; 69 70 DBG("%s: set mode: %dx%d", omap_encoder->mgr->name, 71 mode->hdisplay, mode->vdisplay); 72 73 for (i = 0; i < priv->num_connectors; i++) { 74 struct drm_connector *connector = priv->connectors[i]; 75 if (connector->encoder == encoder) { 76 omap_connector_mode_set(connector, mode); 77 } 78 } 79} 80 81static void omap_encoder_prepare(struct drm_encoder *encoder) 82{ 83 struct omap_encoder *omap_encoder = to_omap_encoder(encoder); 84 struct drm_encoder_helper_funcs *encoder_funcs = 85 encoder->helper_private; 86 DBG("%s", omap_encoder->mgr->name); 87 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); 88} 89 90static void omap_encoder_commit(struct drm_encoder *encoder) 91{ 92 struct omap_encoder *omap_encoder = to_omap_encoder(encoder); 93 struct drm_encoder_helper_funcs *encoder_funcs = 94 encoder->helper_private; 95 DBG("%s", omap_encoder->mgr->name); 96 omap_encoder->mgr->apply(omap_encoder->mgr); 97 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); 98} 99 100static const struct drm_encoder_funcs omap_encoder_funcs = { 101 .destroy = omap_encoder_destroy, 102}; 103 104static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { 105 .dpms = omap_encoder_dpms, 106 .mode_fixup = omap_encoder_mode_fixup, 107 .mode_set = omap_encoder_mode_set, 108 .prepare = omap_encoder_prepare, 109 .commit = omap_encoder_commit, 110}; 111 112struct omap_overlay_manager *omap_encoder_get_manager( 113 struct drm_encoder *encoder) 114{ 115 struct omap_encoder *omap_encoder = to_omap_encoder(encoder); 116 return omap_encoder->mgr; 117} 118 119/* initialize encoder */ 120struct drm_encoder *omap_encoder_init(struct drm_device *dev, 121 struct omap_overlay_manager *mgr) 122{ 123 struct drm_encoder *encoder = NULL; 124 struct omap_encoder *omap_encoder; 125 struct omap_overlay_manager_info info; 126 int ret; 127 128 DBG("%s", mgr->name); 129 130 omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL); 131 if (!omap_encoder) { 132 dev_err(dev->dev, "could not allocate encoder\n"); 133 goto fail; 134 } 135 136 omap_encoder->mgr = mgr; 137 encoder = &omap_encoder->base; 138 139 drm_encoder_init(dev, encoder, &omap_encoder_funcs, 140 DRM_MODE_ENCODER_TMDS); 141 drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs); 142 143 mgr->get_manager_info(mgr, &info); 144 145 /* TODO: fix hard-coded setup.. */ 146 info.default_color = 0x00000000; 147 info.trans_key = 0x00000000; 148 info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; 149 info.trans_enabled = false; 150 151 ret = mgr->set_manager_info(mgr, &info); 152 if (ret) { 153 dev_err(dev->dev, "could not set manager info\n"); 154 goto fail; 155 } 156 157 ret = mgr->apply(mgr); 158 if (ret) { 159 dev_err(dev->dev, "could not apply\n"); 160 goto fail; 161 } 162 163 return encoder; 164 165fail: 166 if (encoder) { 167 omap_encoder_destroy(encoder); 168 } 169 170 return NULL; 171} 172