878fda8bc3641289f148c03a53a4494d845e46ed
[platform/adaptation/spreadtrum/libtdm-sprd.git] / src / tdm_sprd.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #if HAVE_UDEV
6 #include <libudev.h>
7 #endif
8
9 #include "tdm_sprd.h"
10 #include <tdm_helper.h>
11 #include <tbm_drm_helper.h>
12
13 #define SET_DRM_IRQ
14
15 #define SPRD_DRM_NAME "sprd"
16
17 static tdm_sprd_data *sprd_data;
18
19 static int
20 _tdm_sprd_open_drm(void)
21 {
22         int fd = -1;
23
24         fd = drmOpen(SPRD_DRM_NAME, NULL);
25         if (fd < 0)
26                 TDM_ERR("Cannot open '%s' drm", SPRD_DRM_NAME);
27
28 #ifdef HAVE_UDEV
29         if (fd < 0) {
30                 struct udev *udev;
31                 struct udev_enumerate *e;
32                 struct udev_list_entry *entry;
33                 struct udev_device *device, *drm_device, *device_parent;
34                 const char *filename;
35
36                 TDM_WRN("Cannot open drm device.. search by udev");
37                 udev = udev_new();
38                 if (!udev) {
39                         TDM_ERR("fail to initialize udev context\n");
40                         goto close_l;
41                 }
42
43                 /* Will try to find sys path /sprd-drm/drm/card0 */
44                 e = udev_enumerate_new(udev);
45                 udev_enumerate_add_match_subsystem(e, "drm");
46                 udev_enumerate_add_match_sysname(e, "card[0-9]*");
47                 udev_enumerate_scan_devices(e);
48
49                 drm_device = NULL;
50                 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
51                         device = udev_device_new_from_syspath(udev_enumerate_get_udev(e),
52                                                                                                         udev_list_entry_get_name
53                                                                                                         (entry));
54                         device_parent = udev_device_get_parent(device);
55                         /* Not need unref device_parent. device_parent and device have same refcnt */
56                         if (device_parent) {
57                                 if (strcmp(udev_device_get_sysname(device_parent), "sprd-drm") == 0) {
58                                         drm_device = device;
59                                         TDM_DBG("Found drm device: '%s' (%s)\n",
60                                                         udev_device_get_syspath(drm_device),
61                                                         udev_device_get_sysname(device_parent));
62                                         break;
63                                 }
64                         }
65                         udev_device_unref(device);
66                 }
67
68                 if (drm_device == NULL) {
69                         TDM_ERR("fail to find drm device\n");
70                         udev_enumerate_unref(e);
71                         udev_unref(udev);
72                         goto close_l;
73                 }
74
75                 filename = udev_device_get_devnode(drm_device);
76
77                 fd = open(filename, O_RDWR | O_CLOEXEC);
78                 if (fd < 0)
79                         TDM_ERR("Cannot open drm device(%s)\n", filename);
80
81                 udev_device_unref(drm_device);
82                 udev_enumerate_unref(e);
83                 udev_unref(udev);
84         }
85 close_l:
86 #endif
87
88 #ifdef SET_DRM_IRQ
89         drmCtlInstHandler(fd, 78);
90 #endif
91
92         return fd;
93 }
94
95 void
96 tdm_sprd_deinit(tdm_backend_data *bdata)
97 {
98         if (sprd_data != bdata)
99                 return;
100
101         TDM_INFO("deinit");
102         tdm_sprd_display_destroy_buffer_list(sprd_data);
103         tdm_sprd_display_destroy_output_list(sprd_data);
104         tdm_sprd_display_deinit_event_handling(sprd_data);
105
106         if (sprd_data->drm_fd >= 0)
107                 close(sprd_data->drm_fd);
108
109         free(sprd_data);
110         sprd_data = NULL;
111 }
112
113 tdm_backend_data *
114 tdm_sprd_init(tdm_display *dpy, tdm_error *error)
115 {
116         tdm_func_display sprd_func_display;
117         tdm_func_output sprd_func_output;
118         tdm_func_layer sprd_func_layer;
119         tdm_func_hwc sprd_func_hwc;
120         tdm_func_hwc_window sprd_func_hwc_window;
121         tdm_func_pp sprd_func_pp;
122         tdm_func_capture sprd_func_capture;
123         tdm_error ret;
124         char *str;
125
126         if (!dpy) {
127                 TDM_ERR("display is null");
128                 if (error)
129                         *error = TDM_ERROR_INVALID_PARAMETER;
130                 return NULL;
131         }
132
133         if (sprd_data) {
134                 TDM_ERR("failed_l: init twice");
135                 if (error)
136                         *error = TDM_ERROR_BAD_REQUEST;
137                 return NULL;
138         }
139
140         sprd_data = calloc(1, sizeof(tdm_sprd_data));
141         if (!sprd_data) {
142                 TDM_ERR("alloc failed_l");
143                 if (error)
144                         *error = TDM_ERROR_OUT_OF_MEMORY;
145                 return NULL;
146         }
147
148         str = getenv("TDM_HWC");
149         if (str)
150                 sprd_data->hwc_mode = strtol(str, NULL, 10);
151
152         LIST_INITHEAD(&sprd_data->output_list);
153         LIST_INITHEAD(&sprd_data->buffer_list);
154
155         memset(&sprd_func_display, 0, sizeof(sprd_func_display));
156         sprd_func_display.display_get_capability = sprd_display_get_capability;
157         sprd_func_display.display_get_pp_capability = sprd_display_get_pp_capability;
158         sprd_func_display.display_get_outputs = sprd_display_get_outputs;
159         sprd_func_display.display_get_fd = sprd_display_get_fd;
160         sprd_func_display.display_handle_events = sprd_display_handle_events;
161         sprd_func_display.display_create_pp = sprd_display_create_pp;
162         sprd_func_display.display_get_capture_capability = sprd_capture_get_capability;
163
164         memset(&sprd_func_output, 0, sizeof(sprd_func_output));
165         sprd_func_output.output_get_capability = sprd_output_get_capability;
166         sprd_func_output.output_get_layers = sprd_output_get_layers;
167         sprd_func_output.output_set_property = sprd_output_set_property;
168         sprd_func_output.output_get_property = sprd_output_get_property;
169         sprd_func_output.output_wait_vblank = sprd_output_wait_vblank;
170         sprd_func_output.output_set_vblank_handler = sprd_output_set_vblank_handler;
171         sprd_func_output.output_commit = sprd_output_commit;
172         sprd_func_output.output_set_commit_handler = sprd_output_set_commit_handler;
173         sprd_func_output.output_set_dpms = sprd_output_set_dpms;
174         sprd_func_output.output_get_dpms = sprd_output_get_dpms;
175         sprd_func_output.output_set_mode = sprd_output_set_mode;
176         sprd_func_output.output_get_mode = sprd_output_get_mode;
177         sprd_func_output.output_create_capture = sprd_capture_create;
178         if (sprd_data->hwc_mode) {
179                 sprd_func_output.output_get_hwc = sprd_output_get_hwc;
180
181                 memset(&sprd_func_hwc, 0, sizeof(sprd_func_hwc));
182                 sprd_func_hwc.hwc_create_window = sprd_hwc_create_window;
183                 sprd_func_hwc.hwc_get_supported_formats = sprd_hwc_get_supported_formats;
184                 sprd_func_hwc.hwc_get_available_properties = sprd_hwc_get_available_properties;
185                 sprd_func_hwc.hwc_get_client_target_buffer_queue = sprd_hwc_get_client_target_buffer_queue;
186                 sprd_func_hwc.hwc_set_client_target_buffer = sprd_hwc_set_client_target_buffer;
187                 sprd_func_hwc.hwc_validate = sprd_hwc_validate;
188                 sprd_func_hwc.hwc_get_changed_composition_types = sprd_hwc_get_changed_composition_types;
189                 sprd_func_hwc.hwc_accept_changes = sprd_hwc_accept_changes;
190                 sprd_func_hwc.hwc_commit = sprd_hwc_commit;
191                 sprd_func_hwc.hwc_set_commit_handler = sprd_hwc_set_commit_handler;
192
193                 memset(&sprd_func_hwc_window, 0, sizeof(sprd_func_hwc_window));
194                 sprd_func_hwc_window.hwc_window_destroy = sprd_hwc_window_destroy;
195                 sprd_func_hwc_window.hwc_window_get_buffer_queue = NULL;
196                 sprd_func_hwc_window.hwc_window_set_composition_type = sprd_hwc_window_set_composition_type;
197                 sprd_func_hwc_window.hwc_window_set_buffer_damage = sprd_hwc_window_set_buffer_damage;
198                 sprd_func_hwc_window.hwc_window_set_info = sprd_hwc_window_set_info;
199                 sprd_func_hwc_window.hwc_window_get_info = sprd_hwc_window_get_info;
200                 sprd_func_hwc_window.hwc_window_set_buffer = sprd_hwc_window_set_buffer;
201                 sprd_func_hwc_window.hwc_window_set_property = sprd_hwc_window_set_property;
202                 sprd_func_hwc_window.hwc_window_get_property = sprd_hwc_window_get_property;
203         }
204
205         memset(&sprd_func_layer, 0, sizeof(sprd_func_layer));
206         sprd_func_layer.layer_get_capability = sprd_layer_get_capability;
207         sprd_func_layer.layer_set_property = sprd_layer_set_property;
208         sprd_func_layer.layer_get_property = sprd_layer_get_property;
209         sprd_func_layer.layer_set_info = sprd_layer_set_info;
210         sprd_func_layer.layer_get_info = sprd_layer_get_info;
211         sprd_func_layer.layer_set_buffer = sprd_layer_set_buffer;
212         sprd_func_layer.layer_unset_buffer = sprd_layer_unset_buffer;
213         sprd_func_layer.layer_get_buffer_flags = sprd_layer_get_buffer_flags;
214
215         memset(&sprd_func_pp, 0, sizeof(sprd_func_pp));
216         sprd_func_pp.pp_destroy = sprd_pp_destroy;
217         sprd_func_pp.pp_set_info = sprd_pp_set_info;
218         sprd_func_pp.pp_attach = sprd_pp_attach;
219         sprd_func_pp.pp_commit = sprd_pp_commit;
220         sprd_func_pp.pp_set_done_handler = sprd_pp_set_done_handler;
221
222         memset(&sprd_func_capture, 0, sizeof(sprd_func_capture));
223         sprd_func_capture.capture_attach = sprd_capture_attach;
224         sprd_func_capture.capture_commit = sprd_capture_commit;
225         sprd_func_capture.capture_destroy = sprd_capture_destroy;
226         sprd_func_capture.capture_set_done_handler = sprd_capture_set_done_handler;
227         sprd_func_capture.capture_set_info = sprd_capture_set_info;
228
229         ret = tdm_backend_register_func_display(dpy, &sprd_func_display);
230         if (ret != TDM_ERROR_NONE)
231                 goto failed_l;
232
233         ret = tdm_backend_register_func_output(dpy, &sprd_func_output);
234         if (ret != TDM_ERROR_NONE)
235                 goto failed_l;
236
237         ret = tdm_backend_register_func_layer(dpy, &sprd_func_layer);
238         if (ret != TDM_ERROR_NONE)
239                 goto failed_l;
240
241         if (sprd_data->hwc_mode) {
242                 ret = tdm_backend_register_func_hwc_window(dpy, &sprd_func_hwc_window);
243                 if (ret != TDM_ERROR_NONE)
244                         goto failed_l;
245         }
246
247
248         ret = tdm_backend_register_func_pp(dpy, &sprd_func_pp);
249         if (ret != TDM_ERROR_NONE)
250                 goto failed_l;
251
252         ret = tdm_backend_register_func_capture(dpy, &sprd_func_capture);
253         if (ret != TDM_ERROR_NONE)
254                 goto failed_l;
255
256         sprd_data->dpy = dpy;
257         sprd_data->drm_fd = -1;
258
259         /* The drm master fd can be opened by a tbm backend module in
260          * tbm_bufmgr_init() time. In this case, we just get it from tbm.
261          */
262         sprd_data->drm_fd = tbm_drm_helper_get_master_fd();
263         if (sprd_data->drm_fd < 0) {
264                 sprd_data->drm_fd = _tdm_sprd_open_drm();
265
266                 if (sprd_data->drm_fd < 0) {
267                         ret = TDM_ERROR_OPERATION_FAILED;
268                         goto failed_l;
269                 }
270
271                 tbm_drm_helper_set_tbm_master_fd(sprd_data->drm_fd);
272         }
273
274         TDM_INFO("master fd(%d)", sprd_data->drm_fd);
275
276 #if 0
277         if (drmSetClientCap(sprd_data->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0)
278                 TDM_WRN("Set DRM_CLIENT_CAP_UNIVERSAL_PLANES failed_l");
279 #endif
280
281         ret = tdm_sprd_display_create_output_list(sprd_data);
282         if (ret != TDM_ERROR_NONE)
283                 goto failed_l;
284
285         ret = tdm_sprd_display_init_event_handling(sprd_data);
286         if (ret != TDM_ERROR_NONE)
287                 goto failed_l;
288         if (error)
289                 *error = TDM_ERROR_NONE;
290
291         TDM_INFO("init success!");
292
293         return (tdm_backend_data *)sprd_data;
294 failed_l:
295         if (error)
296                 *error = ret;
297
298         tdm_sprd_deinit(sprd_data);
299
300         TDM_ERR("init failed!");
301         return NULL;
302 }
303
304 tdm_backend_module tdm_backend_module_data = {
305         "sprd",
306         "Samsung",
307         TDM_BACKEND_ABI_VERSION,
308         tdm_sprd_init,
309         tdm_sprd_deinit
310 };
311