diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-08-29 04:27:49 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-08-29 09:37:03 -0400 |
commit | 321a95ae35f2ec4f58c4cda28d3606cc6f2b97d1 (patch) | |
tree | 2f765ea3ec7aaf732e5bf4fb0fc23144709c9521 | |
parent | 749cc6f7ed509e1be04e9c26d9cdc3c1f0dd13b4 (diff) |
drm: Extract drm_encoder.[hc]
Same treatment as before. Only hiccup is drm_crtc_mask, which
unfortunately can't be resolved until drm_crtc.h is less of a monster.
Untangle the header loop with a forward declaration for that static
inline.
Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20160829082757.17913-1-daniel.vetter@ffwll.ch
-rw-r--r-- | Documentation/gpu/drm-kms.rst | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 193 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc_internal.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_encoder.c | 220 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 134 | ||||
-rw-r--r-- | include/drm/drm_encoder.h | 167 |
7 files changed, 407 insertions, 329 deletions
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index fa948b4e029b..7f788caebea3 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst | |||
@@ -125,6 +125,15 @@ Connector Functions Reference | |||
125 | .. kernel-doc:: drivers/gpu/drm/drm_connector.c | 125 | .. kernel-doc:: drivers/gpu/drm/drm_connector.c |
126 | :export: | 126 | :export: |
127 | 127 | ||
128 | Encoder Abstraction | ||
129 | =================== | ||
130 | |||
131 | .. kernel-doc:: include/drm/drm_encoder.h | ||
132 | :internal: | ||
133 | |||
134 | .. kernel-doc:: drivers/gpu/drm/drm_encoder.c | ||
135 | :export: | ||
136 | |||
128 | KMS Initialization and Cleanup | 137 | KMS Initialization and Cleanup |
129 | ============================== | 138 | ============================== |
130 | 139 | ||
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 193ff2d09479..efdb4176230f 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -13,7 +13,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ | |||
13 | drm_trace_points.o drm_global.o drm_prime.o \ | 13 | drm_trace_points.o drm_global.o drm_prime.o \ |
14 | drm_rect.o drm_vma_manager.o drm_flip_work.o \ | 14 | drm_rect.o drm_vma_manager.o drm_flip_work.o \ |
15 | drm_modeset_lock.o drm_atomic.o drm_bridge.o \ | 15 | drm_modeset_lock.o drm_atomic.o drm_bridge.o \ |
16 | drm_framebuffer.o drm_connector.o drm_blend.o | 16 | drm_framebuffer.o drm_connector.o drm_blend.o \ |
17 | drm_encoder.o | ||
17 | 18 | ||
18 | drm-$(CONFIG_COMPAT) += drm_ioc32.o | 19 | drm-$(CONFIG_COMPAT) += drm_ioc32.o |
19 | drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o | 20 | drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 7f2510524f09..219cd4ee23b7 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -54,18 +54,6 @@ static const struct drm_prop_enum_list drm_plane_type_enum_list[] = { | |||
54 | { DRM_PLANE_TYPE_CURSOR, "Cursor" }, | 54 | { DRM_PLANE_TYPE_CURSOR, "Cursor" }, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static const struct drm_prop_enum_list drm_encoder_enum_list[] = { | ||
58 | { DRM_MODE_ENCODER_NONE, "None" }, | ||
59 | { DRM_MODE_ENCODER_DAC, "DAC" }, | ||
60 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, | ||
61 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, | ||
62 | { DRM_MODE_ENCODER_TVDAC, "TV" }, | ||
63 | { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, | ||
64 | { DRM_MODE_ENCODER_DSI, "DSI" }, | ||
65 | { DRM_MODE_ENCODER_DPMST, "DP MST" }, | ||
66 | { DRM_MODE_ENCODER_DPI, "DPI" }, | ||
67 | }; | ||
68 | |||
69 | /* | 57 | /* |
70 | * Optional properties | 58 | * Optional properties |
71 | */ | 59 | */ |
@@ -419,117 +407,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) | |||
419 | } | 407 | } |
420 | EXPORT_SYMBOL(drm_crtc_cleanup); | 408 | EXPORT_SYMBOL(drm_crtc_cleanup); |
421 | 409 | ||
422 | static int drm_encoder_register_all(struct drm_device *dev) | ||
423 | { | ||
424 | struct drm_encoder *encoder; | ||
425 | int ret = 0; | ||
426 | |||
427 | drm_for_each_encoder(encoder, dev) { | ||
428 | if (encoder->funcs->late_register) | ||
429 | ret = encoder->funcs->late_register(encoder); | ||
430 | if (ret) | ||
431 | return ret; | ||
432 | } | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static void drm_encoder_unregister_all(struct drm_device *dev) | ||
438 | { | ||
439 | struct drm_encoder *encoder; | ||
440 | |||
441 | drm_for_each_encoder(encoder, dev) { | ||
442 | if (encoder->funcs->early_unregister) | ||
443 | encoder->funcs->early_unregister(encoder); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * drm_encoder_init - Init a preallocated encoder | ||
449 | * @dev: drm device | ||
450 | * @encoder: the encoder to init | ||
451 | * @funcs: callbacks for this encoder | ||
452 | * @encoder_type: user visible type of the encoder | ||
453 | * @name: printf style format string for the encoder name, or NULL for default name | ||
454 | * | ||
455 | * Initialises a preallocated encoder. Encoder should be | ||
456 | * subclassed as part of driver encoder objects. | ||
457 | * | ||
458 | * Returns: | ||
459 | * Zero on success, error code on failure. | ||
460 | */ | ||
461 | int drm_encoder_init(struct drm_device *dev, | ||
462 | struct drm_encoder *encoder, | ||
463 | const struct drm_encoder_funcs *funcs, | ||
464 | int encoder_type, const char *name, ...) | ||
465 | { | ||
466 | int ret; | ||
467 | |||
468 | drm_modeset_lock_all(dev); | ||
469 | |||
470 | ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); | ||
471 | if (ret) | ||
472 | goto out_unlock; | ||
473 | |||
474 | encoder->dev = dev; | ||
475 | encoder->encoder_type = encoder_type; | ||
476 | encoder->funcs = funcs; | ||
477 | if (name) { | ||
478 | va_list ap; | ||
479 | |||
480 | va_start(ap, name); | ||
481 | encoder->name = kvasprintf(GFP_KERNEL, name, ap); | ||
482 | va_end(ap); | ||
483 | } else { | ||
484 | encoder->name = kasprintf(GFP_KERNEL, "%s-%d", | ||
485 | drm_encoder_enum_list[encoder_type].name, | ||
486 | encoder->base.id); | ||
487 | } | ||
488 | if (!encoder->name) { | ||
489 | ret = -ENOMEM; | ||
490 | goto out_put; | ||
491 | } | ||
492 | |||
493 | list_add_tail(&encoder->head, &dev->mode_config.encoder_list); | ||
494 | encoder->index = dev->mode_config.num_encoder++; | ||
495 | |||
496 | out_put: | ||
497 | if (ret) | ||
498 | drm_mode_object_unregister(dev, &encoder->base); | ||
499 | |||
500 | out_unlock: | ||
501 | drm_modeset_unlock_all(dev); | ||
502 | |||
503 | return ret; | ||
504 | } | ||
505 | EXPORT_SYMBOL(drm_encoder_init); | ||
506 | |||
507 | /** | ||
508 | * drm_encoder_cleanup - cleans up an initialised encoder | ||
509 | * @encoder: encoder to cleanup | ||
510 | * | ||
511 | * Cleans up the encoder but doesn't free the object. | ||
512 | */ | ||
513 | void drm_encoder_cleanup(struct drm_encoder *encoder) | ||
514 | { | ||
515 | struct drm_device *dev = encoder->dev; | ||
516 | |||
517 | /* Note that the encoder_list is considered to be static; should we | ||
518 | * remove the drm_encoder at runtime we would have to decrement all | ||
519 | * the indices on the drm_encoder after us in the encoder_list. | ||
520 | */ | ||
521 | |||
522 | drm_modeset_lock_all(dev); | ||
523 | drm_mode_object_unregister(dev, &encoder->base); | ||
524 | kfree(encoder->name); | ||
525 | list_del(&encoder->head); | ||
526 | dev->mode_config.num_encoder--; | ||
527 | drm_modeset_unlock_all(dev); | ||
528 | |||
529 | memset(encoder, 0, sizeof(*encoder)); | ||
530 | } | ||
531 | EXPORT_SYMBOL(drm_encoder_cleanup); | ||
532 | |||
533 | static unsigned int drm_num_planes(struct drm_device *dev) | 410 | static unsigned int drm_num_planes(struct drm_device *dev) |
534 | { | 411 | { |
535 | unsigned int num = 0; | 412 | unsigned int num = 0; |
@@ -1172,76 +1049,6 @@ int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, | |||
1172 | return 0; | 1049 | return 0; |
1173 | } | 1050 | } |
1174 | 1051 | ||
1175 | static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) | ||
1176 | { | ||
1177 | struct drm_connector *connector; | ||
1178 | struct drm_device *dev = encoder->dev; | ||
1179 | bool uses_atomic = false; | ||
1180 | |||
1181 | /* For atomic drivers only state objects are synchronously updated and | ||
1182 | * protected by modeset locks, so check those first. */ | ||
1183 | drm_for_each_connector(connector, dev) { | ||
1184 | if (!connector->state) | ||
1185 | continue; | ||
1186 | |||
1187 | uses_atomic = true; | ||
1188 | |||
1189 | if (connector->state->best_encoder != encoder) | ||
1190 | continue; | ||
1191 | |||
1192 | return connector->state->crtc; | ||
1193 | } | ||
1194 | |||
1195 | /* Don't return stale data (e.g. pending async disable). */ | ||
1196 | if (uses_atomic) | ||
1197 | return NULL; | ||
1198 | |||
1199 | return encoder->crtc; | ||
1200 | } | ||
1201 | |||
1202 | /** | ||
1203 | * drm_mode_getencoder - get encoder configuration | ||
1204 | * @dev: drm device for the ioctl | ||
1205 | * @data: data pointer for the ioctl | ||
1206 | * @file_priv: drm file for the ioctl call | ||
1207 | * | ||
1208 | * Construct a encoder configuration structure to return to the user. | ||
1209 | * | ||
1210 | * Called by the user via ioctl. | ||
1211 | * | ||
1212 | * Returns: | ||
1213 | * Zero on success, negative errno on failure. | ||
1214 | */ | ||
1215 | int drm_mode_getencoder(struct drm_device *dev, void *data, | ||
1216 | struct drm_file *file_priv) | ||
1217 | { | ||
1218 | struct drm_mode_get_encoder *enc_resp = data; | ||
1219 | struct drm_encoder *encoder; | ||
1220 | struct drm_crtc *crtc; | ||
1221 | |||
1222 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
1223 | return -EINVAL; | ||
1224 | |||
1225 | encoder = drm_encoder_find(dev, enc_resp->encoder_id); | ||
1226 | if (!encoder) | ||
1227 | return -ENOENT; | ||
1228 | |||
1229 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | ||
1230 | crtc = drm_encoder_get_crtc(encoder); | ||
1231 | if (crtc) | ||
1232 | enc_resp->crtc_id = crtc->base.id; | ||
1233 | else | ||
1234 | enc_resp->crtc_id = 0; | ||
1235 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | ||
1236 | |||
1237 | enc_resp->encoder_type = encoder->encoder_type; | ||
1238 | enc_resp->encoder_id = encoder->base.id; | ||
1239 | enc_resp->possible_crtcs = encoder->possible_crtcs; | ||
1240 | enc_resp->possible_clones = encoder->possible_clones; | ||
1241 | |||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1245 | /** | 1052 | /** |
1246 | * drm_mode_getplane_res - enumerate all plane resources | 1053 | * drm_mode_getplane_res - enumerate all plane resources |
1247 | * @dev: DRM device | 1054 | * @dev: DRM device |
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 62efb9d09a85..54f9a2c85965 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h | |||
@@ -105,8 +105,6 @@ int drm_mode_createblob_ioctl(struct drm_device *dev, | |||
105 | void *data, struct drm_file *file_priv); | 105 | void *data, struct drm_file *file_priv); |
106 | int drm_mode_destroyblob_ioctl(struct drm_device *dev, | 106 | int drm_mode_destroyblob_ioctl(struct drm_device *dev, |
107 | void *data, struct drm_file *file_priv); | 107 | void *data, struct drm_file *file_priv); |
108 | int drm_mode_getencoder(struct drm_device *dev, | ||
109 | void *data, struct drm_file *file_priv); | ||
110 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, | 108 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, |
111 | void *data, struct drm_file *file_priv); | 109 | void *data, struct drm_file *file_priv); |
112 | int drm_mode_gamma_set_ioctl(struct drm_device *dev, | 110 | int drm_mode_gamma_set_ioctl(struct drm_device *dev, |
@@ -115,6 +113,14 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, | |||
115 | int drm_mode_page_flip_ioctl(struct drm_device *dev, | 113 | int drm_mode_page_flip_ioctl(struct drm_device *dev, |
116 | void *data, struct drm_file *file_priv); | 114 | void *data, struct drm_file *file_priv); |
117 | 115 | ||
116 | /* drm_encoder.c */ | ||
117 | int drm_encoder_register_all(struct drm_device *dev); | ||
118 | void drm_encoder_unregister_all(struct drm_device *dev); | ||
119 | |||
120 | /* IOCTL */ | ||
121 | int drm_mode_getencoder(struct drm_device *dev, | ||
122 | void *data, struct drm_file *file_priv); | ||
123 | |||
118 | /* drm_connector.c */ | 124 | /* drm_connector.c */ |
119 | void drm_connector_ida_init(void); | 125 | void drm_connector_ida_init(void); |
120 | void drm_connector_ida_destroy(void); | 126 | void drm_connector_ida_destroy(void); |
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c new file mode 100644 index 000000000000..bce781b7bb5f --- /dev/null +++ b/drivers/gpu/drm/drm_encoder.c | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
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 | |||
29 | static 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 | |||
41 | int 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 | |||
56 | void 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 | */ | ||
80 | int 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 | |||
115 | out_put: | ||
116 | if (ret) | ||
117 | drm_mode_object_unregister(dev, &encoder->base); | ||
118 | |||
119 | out_unlock: | ||
120 | drm_modeset_unlock_all(dev); | ||
121 | |||
122 | return ret; | ||
123 | } | ||
124 | EXPORT_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 | */ | ||
132 | void 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 | } | ||
150 | EXPORT_SYMBOL(drm_encoder_cleanup); | ||
151 | |||
152 | static 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 | */ | ||
192 | int 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 | } | ||
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index bb214a114329..c459867ecb9c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <drm/drm_framebuffer.h> | 40 | #include <drm/drm_framebuffer.h> |
41 | #include <drm/drm_modes.h> | 41 | #include <drm/drm_modes.h> |
42 | #include <drm/drm_connector.h> | 42 | #include <drm/drm_connector.h> |
43 | #include <drm/drm_encoder.h> | ||
43 | 44 | ||
44 | struct drm_device; | 45 | struct drm_device; |
45 | struct drm_mode_set; | 46 | struct drm_mode_set; |
@@ -662,97 +663,6 @@ struct drm_crtc { | |||
662 | }; | 663 | }; |
663 | 664 | ||
664 | /** | 665 | /** |
665 | * struct drm_encoder_funcs - encoder controls | ||
666 | * | ||
667 | * Encoders sit between CRTCs and connectors. | ||
668 | */ | ||
669 | struct drm_encoder_funcs { | ||
670 | /** | ||
671 | * @reset: | ||
672 | * | ||
673 | * Reset encoder hardware and software state to off. This function isn't | ||
674 | * called by the core directly, only through drm_mode_config_reset(). | ||
675 | * It's not a helper hook only for historical reasons. | ||
676 | */ | ||
677 | void (*reset)(struct drm_encoder *encoder); | ||
678 | |||
679 | /** | ||
680 | * @destroy: | ||
681 | * | ||
682 | * Clean up encoder resources. This is only called at driver unload time | ||
683 | * through drm_mode_config_cleanup() since an encoder cannot be | ||
684 | * hotplugged in DRM. | ||
685 | */ | ||
686 | void (*destroy)(struct drm_encoder *encoder); | ||
687 | |||
688 | /** | ||
689 | * @late_register: | ||
690 | * | ||
691 | * This optional hook can be used to register additional userspace | ||
692 | * interfaces attached to the encoder like debugfs interfaces. | ||
693 | * It is called late in the driver load sequence from drm_dev_register(). | ||
694 | * Everything added from this callback should be unregistered in | ||
695 | * the early_unregister callback. | ||
696 | * | ||
697 | * Returns: | ||
698 | * | ||
699 | * 0 on success, or a negative error code on failure. | ||
700 | */ | ||
701 | int (*late_register)(struct drm_encoder *encoder); | ||
702 | |||
703 | /** | ||
704 | * @early_unregister: | ||
705 | * | ||
706 | * This optional hook should be used to unregister the additional | ||
707 | * userspace interfaces attached to the encoder from | ||
708 | * late_unregister(). It is called from drm_dev_unregister(), | ||
709 | * early in the driver unload sequence to disable userspace access | ||
710 | * before data structures are torndown. | ||
711 | */ | ||
712 | void (*early_unregister)(struct drm_encoder *encoder); | ||
713 | }; | ||
714 | |||
715 | /** | ||
716 | * struct drm_encoder - central DRM encoder structure | ||
717 | * @dev: parent DRM device | ||
718 | * @head: list management | ||
719 | * @base: base KMS object | ||
720 | * @name: human readable name, can be overwritten by the driver | ||
721 | * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h | ||
722 | * @possible_crtcs: bitmask of potential CRTC bindings | ||
723 | * @possible_clones: bitmask of potential sibling encoders for cloning | ||
724 | * @crtc: currently bound CRTC | ||
725 | * @bridge: bridge associated to the encoder | ||
726 | * @funcs: control functions | ||
727 | * @helper_private: mid-layer private data | ||
728 | * | ||
729 | * CRTCs drive pixels to encoders, which convert them into signals | ||
730 | * appropriate for a given connector or set of connectors. | ||
731 | */ | ||
732 | struct drm_encoder { | ||
733 | struct drm_device *dev; | ||
734 | struct list_head head; | ||
735 | |||
736 | struct drm_mode_object base; | ||
737 | char *name; | ||
738 | int encoder_type; | ||
739 | |||
740 | /** | ||
741 | * @index: Position inside the mode_config.list, can be used as an array | ||
742 | * index. It is invariant over the lifetime of the encoder. | ||
743 | */ | ||
744 | unsigned index; | ||
745 | |||
746 | uint32_t possible_crtcs; | ||
747 | uint32_t possible_clones; | ||
748 | |||
749 | struct drm_crtc *crtc; | ||
750 | struct drm_bridge *bridge; | ||
751 | const struct drm_encoder_funcs *funcs; | ||
752 | const struct drm_encoder_helper_funcs *helper_private; | ||
753 | }; | ||
754 | |||
755 | /** | ||
756 | * struct drm_plane_state - mutable plane state | 666 | * struct drm_plane_state - mutable plane state |
757 | * @plane: backpointer to the plane | 667 | * @plane: backpointer to the plane |
758 | * @crtc: currently bound CRTC, NULL if disabled | 668 | * @crtc: currently bound CRTC, NULL if disabled |
@@ -2114,7 +2024,6 @@ struct drm_mode_config { | |||
2114 | for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder))) | 2024 | for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder))) |
2115 | 2025 | ||
2116 | #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) | 2026 | #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) |
2117 | #define obj_to_encoder(x) container_of(x, struct drm_encoder, base) | ||
2118 | #define obj_to_mode(x) container_of(x, struct drm_display_mode, base) | 2027 | #define obj_to_mode(x) container_of(x, struct drm_display_mode, base) |
2119 | #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base) | 2028 | #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base) |
2120 | #define obj_to_property(x) container_of(x, struct drm_property, base) | 2029 | #define obj_to_property(x) container_of(x, struct drm_property, base) |
@@ -2159,37 +2068,6 @@ static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc) | |||
2159 | return 1 << drm_crtc_index(crtc); | 2068 | return 1 << drm_crtc_index(crtc); |
2160 | } | 2069 | } |
2161 | 2070 | ||
2162 | extern __printf(5, 6) | ||
2163 | int drm_encoder_init(struct drm_device *dev, | ||
2164 | struct drm_encoder *encoder, | ||
2165 | const struct drm_encoder_funcs *funcs, | ||
2166 | int encoder_type, const char *name, ...); | ||
2167 | |||
2168 | /** | ||
2169 | * drm_encoder_index - find the index of a registered encoder | ||
2170 | * @encoder: encoder to find index for | ||
2171 | * | ||
2172 | * Given a registered encoder, return the index of that encoder within a DRM | ||
2173 | * device's list of encoders. | ||
2174 | */ | ||
2175 | static inline unsigned int drm_encoder_index(struct drm_encoder *encoder) | ||
2176 | { | ||
2177 | return encoder->index; | ||
2178 | } | ||
2179 | |||
2180 | /** | ||
2181 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? | ||
2182 | * @encoder: encoder to test | ||
2183 | * @crtc: crtc to test | ||
2184 | * | ||
2185 | * Return false if @encoder can't be driven by @crtc, true otherwise. | ||
2186 | */ | ||
2187 | static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder, | ||
2188 | struct drm_crtc *crtc) | ||
2189 | { | ||
2190 | return !!(encoder->possible_crtcs & drm_crtc_mask(crtc)); | ||
2191 | } | ||
2192 | |||
2193 | extern __printf(8, 9) | 2071 | extern __printf(8, 9) |
2194 | int drm_universal_plane_init(struct drm_device *dev, | 2072 | int drm_universal_plane_init(struct drm_device *dev, |
2195 | struct drm_plane *plane, | 2073 | struct drm_plane *plane, |
@@ -2225,8 +2103,6 @@ extern void drm_crtc_get_hv_timing(const struct drm_display_mode *mode, | |||
2225 | extern int drm_crtc_force_disable(struct drm_crtc *crtc); | 2103 | extern int drm_crtc_force_disable(struct drm_crtc *crtc); |
2226 | extern int drm_crtc_force_disable_all(struct drm_device *dev); | 2104 | extern int drm_crtc_force_disable_all(struct drm_device *dev); |
2227 | 2105 | ||
2228 | extern void drm_encoder_cleanup(struct drm_encoder *encoder); | ||
2229 | |||
2230 | extern void drm_mode_config_init(struct drm_device *dev); | 2106 | extern void drm_mode_config_init(struct drm_device *dev); |
2231 | extern void drm_mode_config_reset(struct drm_device *dev); | 2107 | extern void drm_mode_config_reset(struct drm_device *dev); |
2232 | extern void drm_mode_config_cleanup(struct drm_device *dev); | 2108 | extern void drm_mode_config_cleanup(struct drm_device *dev); |
@@ -2338,14 +2214,6 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev, | |||
2338 | return mo ? obj_to_crtc(mo) : NULL; | 2214 | return mo ? obj_to_crtc(mo) : NULL; |
2339 | } | 2215 | } |
2340 | 2216 | ||
2341 | static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev, | ||
2342 | uint32_t id) | ||
2343 | { | ||
2344 | struct drm_mode_object *mo; | ||
2345 | mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); | ||
2346 | return mo ? obj_to_encoder(mo) : NULL; | ||
2347 | } | ||
2348 | |||
2349 | static inline struct drm_property *drm_property_find(struct drm_device *dev, | 2217 | static inline struct drm_property *drm_property_find(struct drm_device *dev, |
2350 | uint32_t id) | 2218 | uint32_t id) |
2351 | { | 2219 | { |
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h new file mode 100644 index 000000000000..2712fd1a686b --- /dev/null +++ b/include/drm/drm_encoder.h | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
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 | #ifndef __DRM_ENCODER_H__ | ||
24 | #define __DRM_ENCODER_H__ | ||
25 | |||
26 | #include <linux/list.h> | ||
27 | #include <linux/ctype.h> | ||
28 | #include <drm/drm_modeset.h> | ||
29 | |||
30 | /** | ||
31 | * struct drm_encoder_funcs - encoder controls | ||
32 | * | ||
33 | * Encoders sit between CRTCs and connectors. | ||
34 | */ | ||
35 | struct drm_encoder_funcs { | ||
36 | /** | ||
37 | * @reset: | ||
38 | * | ||
39 | * Reset encoder hardware and software state to off. This function isn't | ||
40 | * called by the core directly, only through drm_mode_config_reset(). | ||
41 | * It's not a helper hook only for historical reasons. | ||
42 | */ | ||
43 | void (*reset)(struct drm_encoder *encoder); | ||
44 | |||
45 | /** | ||
46 | * @destroy: | ||
47 | * | ||
48 | * Clean up encoder resources. This is only called at driver unload time | ||
49 | * through drm_mode_config_cleanup() since an encoder cannot be | ||
50 | * hotplugged in DRM. | ||
51 | */ | ||
52 | void (*destroy)(struct drm_encoder *encoder); | ||
53 | |||
54 | /** | ||
55 | * @late_register: | ||
56 | * | ||
57 | * This optional hook can be used to register additional userspace | ||
58 | * interfaces attached to the encoder like debugfs interfaces. | ||
59 | * It is called late in the driver load sequence from drm_dev_register(). | ||
60 | * Everything added from this callback should be unregistered in | ||
61 | * the early_unregister callback. | ||
62 | * | ||
63 | * Returns: | ||
64 | * | ||
65 | * 0 on success, or a negative error code on failure. | ||
66 | */ | ||
67 | int (*late_register)(struct drm_encoder *encoder); | ||
68 | |||
69 | /** | ||
70 | * @early_unregister: | ||
71 | * | ||
72 | * This optional hook should be used to unregister the additional | ||
73 | * userspace interfaces attached to the encoder from | ||
74 | * late_unregister(). It is called from drm_dev_unregister(), | ||
75 | * early in the driver unload sequence to disable userspace access | ||
76 | * before data structures are torndown. | ||
77 | */ | ||
78 | void (*early_unregister)(struct drm_encoder *encoder); | ||
79 | }; | ||
80 | |||
81 | /** | ||
82 | * struct drm_encoder - central DRM encoder structure | ||
83 | * @dev: parent DRM device | ||
84 | * @head: list management | ||
85 | * @base: base KMS object | ||
86 | * @name: human readable name, can be overwritten by the driver | ||
87 | * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h | ||
88 | * @possible_crtcs: bitmask of potential CRTC bindings | ||
89 | * @possible_clones: bitmask of potential sibling encoders for cloning | ||
90 | * @crtc: currently bound CRTC | ||
91 | * @bridge: bridge associated to the encoder | ||
92 | * @funcs: control functions | ||
93 | * @helper_private: mid-layer private data | ||
94 | * | ||
95 | * CRTCs drive pixels to encoders, which convert them into signals | ||
96 | * appropriate for a given connector or set of connectors. | ||
97 | */ | ||
98 | struct drm_encoder { | ||
99 | struct drm_device *dev; | ||
100 | struct list_head head; | ||
101 | |||
102 | struct drm_mode_object base; | ||
103 | char *name; | ||
104 | int encoder_type; | ||
105 | |||
106 | /** | ||
107 | * @index: Position inside the mode_config.list, can be used as an array | ||
108 | * index. It is invariant over the lifetime of the encoder. | ||
109 | */ | ||
110 | unsigned index; | ||
111 | |||
112 | uint32_t possible_crtcs; | ||
113 | uint32_t possible_clones; | ||
114 | |||
115 | struct drm_crtc *crtc; | ||
116 | struct drm_bridge *bridge; | ||
117 | const struct drm_encoder_funcs *funcs; | ||
118 | const struct drm_encoder_helper_funcs *helper_private; | ||
119 | }; | ||
120 | |||
121 | #define obj_to_encoder(x) container_of(x, struct drm_encoder, base) | ||
122 | |||
123 | __printf(5, 6) | ||
124 | int drm_encoder_init(struct drm_device *dev, | ||
125 | struct drm_encoder *encoder, | ||
126 | const struct drm_encoder_funcs *funcs, | ||
127 | int encoder_type, const char *name, ...); | ||
128 | |||
129 | /** | ||
130 | * drm_encoder_index - find the index of a registered encoder | ||
131 | * @encoder: encoder to find index for | ||
132 | * | ||
133 | * Given a registered encoder, return the index of that encoder within a DRM | ||
134 | * device's list of encoders. | ||
135 | */ | ||
136 | static inline unsigned int drm_encoder_index(struct drm_encoder *encoder) | ||
137 | { | ||
138 | return encoder->index; | ||
139 | } | ||
140 | |||
141 | /* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */ | ||
142 | static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc); | ||
143 | |||
144 | /** | ||
145 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? | ||
146 | * @encoder: encoder to test | ||
147 | * @crtc: crtc to test | ||
148 | * | ||
149 | * Return false if @encoder can't be driven by @crtc, true otherwise. | ||
150 | */ | ||
151 | static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder, | ||
152 | struct drm_crtc *crtc) | ||
153 | { | ||
154 | return !!(encoder->possible_crtcs & drm_crtc_mask(crtc)); | ||
155 | } | ||
156 | |||
157 | static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev, | ||
158 | uint32_t id) | ||
159 | { | ||
160 | struct drm_mode_object *mo; | ||
161 | mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); | ||
162 | return mo ? obj_to_encoder(mo) : NULL; | ||
163 | } | ||
164 | |||
165 | void drm_encoder_cleanup(struct drm_encoder *encoder); | ||
166 | |||
167 | #endif | ||