blob: bce781b7bb5fd7d1ef2cc2c21eeed91d1165da5f [file] [log] [blame]
Daniel Vetter321a95a2016-08-29 10:27:49 +02001/*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include <linux/export.h>
24#include <drm/drmP.h>
25#include <drm/drm_encoder.h>
26
27#include "drm_crtc_internal.h"
28
29static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
30 { DRM_MODE_ENCODER_NONE, "None" },
31 { DRM_MODE_ENCODER_DAC, "DAC" },
32 { DRM_MODE_ENCODER_TMDS, "TMDS" },
33 { DRM_MODE_ENCODER_LVDS, "LVDS" },
34 { DRM_MODE_ENCODER_TVDAC, "TV" },
35 { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
36 { DRM_MODE_ENCODER_DSI, "DSI" },
37 { DRM_MODE_ENCODER_DPMST, "DP MST" },
38 { DRM_MODE_ENCODER_DPI, "DPI" },
39};
40
41int drm_encoder_register_all(struct drm_device *dev)
42{
43 struct drm_encoder *encoder;
44 int ret = 0;
45
46 drm_for_each_encoder(encoder, dev) {
47 if (encoder->funcs->late_register)
48 ret = encoder->funcs->late_register(encoder);
49 if (ret)
50 return ret;
51 }
52
53 return 0;
54}
55
56void drm_encoder_unregister_all(struct drm_device *dev)
57{
58 struct drm_encoder *encoder;
59
60 drm_for_each_encoder(encoder, dev) {
61 if (encoder->funcs->early_unregister)
62 encoder->funcs->early_unregister(encoder);
63 }
64}
65
66/**
67 * drm_encoder_init - Init a preallocated encoder
68 * @dev: drm device
69 * @encoder: the encoder to init
70 * @funcs: callbacks for this encoder
71 * @encoder_type: user visible type of the encoder
72 * @name: printf style format string for the encoder name, or NULL for default name
73 *
74 * Initialises a preallocated encoder. Encoder should be
75 * subclassed as part of driver encoder objects.
76 *
77 * Returns:
78 * Zero on success, error code on failure.
79 */
80int drm_encoder_init(struct drm_device *dev,
81 struct drm_encoder *encoder,
82 const struct drm_encoder_funcs *funcs,
83 int encoder_type, const char *name, ...)
84{
85 int ret;
86
87 drm_modeset_lock_all(dev);
88
89 ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
90 if (ret)
91 goto out_unlock;
92
93 encoder->dev = dev;
94 encoder->encoder_type = encoder_type;
95 encoder->funcs = funcs;
96 if (name) {
97 va_list ap;
98
99 va_start(ap, name);
100 encoder->name = kvasprintf(GFP_KERNEL, name, ap);
101 va_end(ap);
102 } else {
103 encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
104 drm_encoder_enum_list[encoder_type].name,
105 encoder->base.id);
106 }
107 if (!encoder->name) {
108 ret = -ENOMEM;
109 goto out_put;
110 }
111
112 list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
113 encoder->index = dev->mode_config.num_encoder++;
114
115out_put:
116 if (ret)
117 drm_mode_object_unregister(dev, &encoder->base);
118
119out_unlock:
120 drm_modeset_unlock_all(dev);
121
122 return ret;
123}
124EXPORT_SYMBOL(drm_encoder_init);
125
126/**
127 * drm_encoder_cleanup - cleans up an initialised encoder
128 * @encoder: encoder to cleanup
129 *
130 * Cleans up the encoder but doesn't free the object.
131 */
132void drm_encoder_cleanup(struct drm_encoder *encoder)
133{
134 struct drm_device *dev = encoder->dev;
135
136 /* Note that the encoder_list is considered to be static; should we
137 * remove the drm_encoder at runtime we would have to decrement all
138 * the indices on the drm_encoder after us in the encoder_list.
139 */
140
141 drm_modeset_lock_all(dev);
142 drm_mode_object_unregister(dev, &encoder->base);
143 kfree(encoder->name);
144 list_del(&encoder->head);
145 dev->mode_config.num_encoder--;
146 drm_modeset_unlock_all(dev);
147
148 memset(encoder, 0, sizeof(*encoder));
149}
150EXPORT_SYMBOL(drm_encoder_cleanup);
151
152static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
153{
154 struct drm_connector *connector;
155 struct drm_device *dev = encoder->dev;
156 bool uses_atomic = false;
157
158 /* For atomic drivers only state objects are synchronously updated and
159 * protected by modeset locks, so check those first. */
160 drm_for_each_connector(connector, dev) {
161 if (!connector->state)
162 continue;
163
164 uses_atomic = true;
165
166 if (connector->state->best_encoder != encoder)
167 continue;
168
169 return connector->state->crtc;
170 }
171
172 /* Don't return stale data (e.g. pending async disable). */
173 if (uses_atomic)
174 return NULL;
175
176 return encoder->crtc;
177}
178
179/**
180 * drm_mode_getencoder - get encoder configuration
181 * @dev: drm device for the ioctl
182 * @data: data pointer for the ioctl
183 * @file_priv: drm file for the ioctl call
184 *
185 * Construct a encoder configuration structure to return to the user.
186 *
187 * Called by the user via ioctl.
188 *
189 * Returns:
190 * Zero on success, negative errno on failure.
191 */
192int drm_mode_getencoder(struct drm_device *dev, void *data,
193 struct drm_file *file_priv)
194{
195 struct drm_mode_get_encoder *enc_resp = data;
196 struct drm_encoder *encoder;
197 struct drm_crtc *crtc;
198
199 if (!drm_core_check_feature(dev, DRIVER_MODESET))
200 return -EINVAL;
201
202 encoder = drm_encoder_find(dev, enc_resp->encoder_id);
203 if (!encoder)
204 return -ENOENT;
205
206 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
207 crtc = drm_encoder_get_crtc(encoder);
208 if (crtc)
209 enc_resp->crtc_id = crtc->base.id;
210 else
211 enc_resp->crtc_id = 0;
212 drm_modeset_unlock(&dev->mode_config.connection_mutex);
213
214 enc_resp->encoder_type = encoder->encoder_type;
215 enc_resp->encoder_id = encoder->base.id;
216 enc_resp->possible_crtcs = encoder->possible_crtcs;
217 enc_resp->possible_clones = encoder->possible_clones;
218
219 return 0;
220}