aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2016-08-29 04:27:49 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2016-08-29 09:37:03 -0400
commit321a95ae35f2ec4f58c4cda28d3606cc6f2b97d1 (patch)
tree2f765ea3ec7aaf732e5bf4fb0fc23144709c9521
parent749cc6f7ed509e1be04e9c26d9cdc3c1f0dd13b4 (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.rst9
-rw-r--r--drivers/gpu/drm/Makefile3
-rw-r--r--drivers/gpu/drm/drm_crtc.c193
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h10
-rw-r--r--drivers/gpu/drm/drm_encoder.c220
-rw-r--r--include/drm/drm_crtc.h134
-rw-r--r--include/drm/drm_encoder.h167
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
128Encoder 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
128KMS Initialization and Cleanup 137KMS 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
18drm-$(CONFIG_COMPAT) += drm_ioc32.o 19drm-$(CONFIG_COMPAT) += drm_ioc32.o
19drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o 20drm-$(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
57static 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}
420EXPORT_SYMBOL(drm_crtc_cleanup); 408EXPORT_SYMBOL(drm_crtc_cleanup);
421 409
422static 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
437static 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 */
461int 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
496out_put:
497 if (ret)
498 drm_mode_object_unregister(dev, &encoder->base);
499
500out_unlock:
501 drm_modeset_unlock_all(dev);
502
503 return ret;
504}
505EXPORT_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 */
513void 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}
531EXPORT_SYMBOL(drm_encoder_cleanup);
532
533static unsigned int drm_num_planes(struct drm_device *dev) 410static 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
1175static 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 */
1215int 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);
106int drm_mode_destroyblob_ioctl(struct drm_device *dev, 106int drm_mode_destroyblob_ioctl(struct drm_device *dev,
107 void *data, struct drm_file *file_priv); 107 void *data, struct drm_file *file_priv);
108int drm_mode_getencoder(struct drm_device *dev,
109 void *data, struct drm_file *file_priv);
110int drm_mode_gamma_get_ioctl(struct drm_device *dev, 108int 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);
112int drm_mode_gamma_set_ioctl(struct drm_device *dev, 110int drm_mode_gamma_set_ioctl(struct drm_device *dev,
@@ -115,6 +113,14 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
115int drm_mode_page_flip_ioctl(struct drm_device *dev, 113int 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 */
117int drm_encoder_register_all(struct drm_device *dev);
118void drm_encoder_unregister_all(struct drm_device *dev);
119
120/* IOCTL */
121int drm_mode_getencoder(struct drm_device *dev,
122 void *data, struct drm_file *file_priv);
123
118/* drm_connector.c */ 124/* drm_connector.c */
119void drm_connector_ida_init(void); 125void drm_connector_ida_init(void);
120void drm_connector_ida_destroy(void); 126void 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
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}
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
44struct drm_device; 45struct drm_device;
45struct drm_mode_set; 46struct 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 */
669struct 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 */
732struct 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
2162extern __printf(5, 6)
2163int 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 */
2175static 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 */
2187static 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
2193extern __printf(8, 9) 2071extern __printf(8, 9)
2194int drm_universal_plane_init(struct drm_device *dev, 2072int 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,
2225extern int drm_crtc_force_disable(struct drm_crtc *crtc); 2103extern int drm_crtc_force_disable(struct drm_crtc *crtc);
2226extern int drm_crtc_force_disable_all(struct drm_device *dev); 2104extern int drm_crtc_force_disable_all(struct drm_device *dev);
2227 2105
2228extern void drm_encoder_cleanup(struct drm_encoder *encoder);
2229
2230extern void drm_mode_config_init(struct drm_device *dev); 2106extern void drm_mode_config_init(struct drm_device *dev);
2231extern void drm_mode_config_reset(struct drm_device *dev); 2107extern void drm_mode_config_reset(struct drm_device *dev);
2232extern void drm_mode_config_cleanup(struct drm_device *dev); 2108extern 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
2341static 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
2349static inline struct drm_property *drm_property_find(struct drm_device *dev, 2217static 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 */
35struct 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 */
98struct 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)
124int 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 */
136static 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. */
142static 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 */
151static 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
157static 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
165void drm_encoder_cleanup(struct drm_encoder *encoder);
166
167#endif