1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <drm/drmP.h>
16#include "exynos_drm_drv.h"
17#include "exynos_drm_crtc.h"
18#include "exynos_drm_encoder.h"
19#include "exynos_drm_fbdev.h"
20
21static LIST_HEAD(exynos_drm_subdrv_list);
22
23int exynos_drm_create_enc_conn(struct drm_device *dev,
24 struct exynos_drm_display *display)
25{
26 struct drm_encoder *encoder;
27 int ret;
28 unsigned long possible_crtcs = 0;
29
30 ret = exynos_drm_crtc_get_pipe_from_type(dev, display->type);
31 if (ret < 0)
32 return ret;
33
34 possible_crtcs |= 1 << ret;
35
36
37 encoder = exynos_drm_encoder_create(dev, display, possible_crtcs);
38 if (!encoder) {
39 DRM_ERROR("failed to create encoder\n");
40 return -EFAULT;
41 }
42
43 display->encoder = encoder;
44
45 ret = display->ops->create_connector(display, encoder);
46 if (ret) {
47 DRM_ERROR("failed to create connector ret = %d\n", ret);
48 goto err_destroy_encoder;
49 }
50
51 return 0;
52
53err_destroy_encoder:
54 encoder->funcs->destroy(encoder);
55 return ret;
56}
57
58int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
59{
60 if (!subdrv)
61 return -EINVAL;
62
63 list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
64
65 return 0;
66}
67EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
68
69int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
70{
71 if (!subdrv)
72 return -EINVAL;
73
74 list_del(&subdrv->list);
75
76 return 0;
77}
78EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
79
80int exynos_drm_device_subdrv_probe(struct drm_device *dev)
81{
82 struct exynos_drm_subdrv *subdrv, *n;
83 int err;
84
85 if (!dev)
86 return -EINVAL;
87
88 list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
89 if (subdrv->probe) {
90 subdrv->drm_dev = dev;
91
92
93
94
95
96
97 err = subdrv->probe(dev, subdrv->dev);
98 if (err) {
99 DRM_DEBUG("exynos drm subdrv probe failed.\n");
100 list_del(&subdrv->list);
101 continue;
102 }
103 }
104 }
105
106 return 0;
107}
108EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_probe);
109
110int exynos_drm_device_subdrv_remove(struct drm_device *dev)
111{
112 struct exynos_drm_subdrv *subdrv;
113
114 if (!dev) {
115 WARN(1, "Unexpected drm device unregister!\n");
116 return -EINVAL;
117 }
118
119 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
120 if (subdrv->remove)
121 subdrv->remove(dev, subdrv->dev);
122 }
123
124 return 0;
125}
126EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_remove);
127
128int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
129{
130 struct exynos_drm_subdrv *subdrv;
131 int ret;
132
133 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
134 if (subdrv->open) {
135 ret = subdrv->open(dev, subdrv->dev, file);
136 if (ret)
137 goto err;
138 }
139 }
140
141 return 0;
142
143err:
144 list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
145 if (subdrv->close)
146 subdrv->close(dev, subdrv->dev, file);
147 }
148 return ret;
149}
150EXPORT_SYMBOL_GPL(exynos_drm_subdrv_open);
151
152void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
153{
154 struct exynos_drm_subdrv *subdrv;
155
156 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
157 if (subdrv->close)
158 subdrv->close(dev, subdrv->dev, file);
159 }
160}
161EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
162