9 #include "tdm_nexell.h"
10 #include <tdm_helper.h>
11 #include <tbm_drm_helper.h>
14 #define TDM_NEXELL_ENABLE_HWC 1
16 #define TDM_NEXELL_NAME "nexell"
18 static tdm_nexell_data *nexell_data;
21 static struct udev_device *
22 _tdm_find_primary_gpu(void)
25 struct udev_enumerate *e;
26 struct udev_list_entry *entry;
27 const char *path, *id;
28 struct udev_device *device, *drm_device, *pci;
32 TDM_ERR("fail to initialize udev context\n");
36 e = udev_enumerate_new(udev);
37 udev_enumerate_add_match_subsystem(e, "drm");
38 udev_enumerate_add_match_sysname(e, "card[0-9]*");
40 udev_enumerate_scan_devices(e);
42 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
43 path = udev_list_entry_get_name(entry);
44 device = udev_device_new_from_syspath(udev, path);
48 pci = udev_device_get_parent_with_subsystem_devtype(device,
51 id = udev_device_get_sysattr_value(pci, "boot_vga");
52 if (id && !strcmp(id, "1")) {
54 udev_device_unref(drm_device);
63 udev_device_unref(device);
66 udev_enumerate_unref(e);
71 _tdm_nexell_udev_fd_handler(int fd, tdm_event_loop_mask mask, void *user_data)
73 tdm_nexell_data *edata = (tdm_nexell_data*)user_data;
74 struct udev_device *dev;
80 dev = udev_monitor_receive_device(edata->uevent_monitor);
82 TDM_ERR("couldn't receive device");
83 return TDM_ERROR_OPERATION_FAILED;
86 udev_devnum = udev_device_get_devnum(dev);
88 ret = fstat(edata->drm_fd, &s);
90 TDM_ERR("fstat failed");
91 return TDM_ERROR_OPERATION_FAILED;
94 hotplug = udev_device_get_property_value(dev, "HOTPLUG");
96 if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
97 hotplug && atoi(hotplug) == 1)
100 tdm_nexell_display_update_output_status(edata);
103 udev_device_unref(dev);
105 return TDM_ERROR_NONE;
109 _tdm_nexell_udev_init(tdm_nexell_data *edata)
111 struct udev *u = NULL;
112 struct udev_monitor *mon = NULL;
116 TDM_ERR("couldn't create udev");
120 mon = udev_monitor_new_from_netlink(u, "udev");
122 TDM_ERR("couldn't create udev monitor");
126 if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") > 0 ||
127 udev_monitor_enable_receiving(mon) < 0) {
128 TDM_ERR("add match subsystem failed");
132 edata->uevent_source =
133 tdm_event_loop_add_fd_handler(edata->dpy, udev_monitor_get_fd(mon),
134 TDM_EVENT_LOOP_READABLE,
135 _tdm_nexell_udev_fd_handler,
137 if (!edata->uevent_source) {
138 TDM_ERR("couldn't create udev event source");
142 edata->uevent_monitor = mon;
144 TDM_INFO("hotplug monitor created");
149 udev_monitor_unref(mon);
155 _tdm_nexell_udev_deinit(tdm_nexell_data *edata)
157 if (edata->uevent_source) {
158 tdm_event_loop_source_remove(edata->uevent_source);
159 edata->uevent_source = NULL;
162 if (edata->uevent_monitor) {
163 struct udev *u = udev_monitor_get_udev(edata->uevent_monitor);
164 udev_monitor_unref(edata->uevent_monitor);
166 edata->uevent_monitor = NULL;
167 TDM_INFO("hotplug monitor destroyed");
173 _tdm_nexell_open_drm(void)
177 fd = drmOpen(TDM_NEXELL_NAME, NULL);
179 TDM_WRN("Cannot open '%s' drm", TDM_NEXELL_NAME);
184 struct udev_device *drm_device = NULL;
185 const char *filename;
186 TDM_WRN("Cannot open drm device.. search by udev");
188 drm_device = _tdm_find_primary_gpu();
189 if (drm_device == NULL) {
190 TDM_ERR("fail to find drm device\n");
194 filename = udev_device_get_devnode(drm_device);
196 fd = open(filename, O_RDWR | O_CLOEXEC);
198 TDM_ERR("Cannot open drm device(%s)\n", filename);
200 TDM_DBG("open drm device (name:%s, fd:%d)", filename, fd);
202 udev_device_unref(drm_device);
210 tdm_nexell_deinit(tdm_backend_data *bdata)
212 if (nexell_data != bdata)
218 _tdm_nexell_udev_deinit(nexell_data);
221 tdm_nexell_display_destroy_output_list(nexell_data);
222 tdm_nexell_data_destroy_buffer_list(nexell_data);
224 if (nexell_data->plane_res)
225 drmModeFreePlaneResources(nexell_data->plane_res);
226 if (nexell_data->mode_res)
227 drmModeFreeResources(nexell_data->mode_res);
228 if (nexell_data->drm_fd >= 0)
229 close(nexell_data->drm_fd);
230 if (nexell_data->scaler_fd >= 0)
231 close(nexell_data->scaler_fd);
238 tdm_nexell_init(tdm_display *dpy, tdm_error *error)
240 tdm_func_display nexell_func_display;
241 tdm_func_output nexell_func_output;
242 tdm_func_layer nexell_func_layer;
243 tdm_func_hwc nexell_func_hwc;
244 tdm_func_hwc_window nexell_func_hwc_window;
246 tdm_func_pp nexell_func_pp;
252 TDM_ERR("display is null");
254 *error = TDM_ERROR_INVALID_PARAMETER;
259 TDM_ERR("failed: init twice");
261 *error = TDM_ERROR_BAD_REQUEST;
265 nexell_data = calloc(1, sizeof(tdm_nexell_data));
267 TDM_ERR("alloc failed");
269 *error = TDM_ERROR_OUT_OF_MEMORY;
273 str = getenv("TDM_HWC");
276 nexell_data->hwc_mode = strtol(str, &end, 10);;
279 /* enable the tdm_hwc */
280 nexell_data->hwc_mode = TDM_NEXELL_ENABLE_HWC;
282 LIST_INITHEAD(&nexell_data->output_list);
283 LIST_INITHEAD(&nexell_data->buffer_list);
285 memset(&nexell_func_display, 0, sizeof(nexell_func_display));
286 nexell_func_display.display_get_capability = nexell_display_get_capability;
287 nexell_func_display.display_get_pp_capability = nexell_display_get_pp_capability;
288 nexell_func_display.display_get_outputs = nexell_display_get_outputs;
289 nexell_func_display.display_get_fd = nexell_display_get_fd;
290 nexell_func_display.display_handle_events = nexell_display_handle_events;
291 nexell_func_display.display_create_pp = nexell_display_create_pp;
293 memset(&nexell_func_output, 0, sizeof(nexell_func_output));
294 nexell_func_output.output_get_capability = nexell_output_get_capability;
295 nexell_func_output.output_get_layers = nexell_output_get_layers;
296 nexell_func_output.output_set_property = nexell_output_set_property;
297 nexell_func_output.output_get_property = nexell_output_get_property;
298 nexell_func_output.output_wait_vblank = nexell_output_wait_vblank;
299 nexell_func_output.output_set_vblank_handler = nexell_output_set_vblank_handler;
300 nexell_func_output.output_commit = nexell_output_commit;
301 nexell_func_output.output_set_commit_handler = nexell_output_set_commit_handler;
302 nexell_func_output.output_set_dpms = nexell_output_set_dpms;
303 nexell_func_output.output_get_dpms = nexell_output_get_dpms;
304 nexell_func_output.output_set_mode = nexell_output_set_mode;
305 nexell_func_output.output_get_mode = nexell_output_get_mode;
306 nexell_func_output.output_set_mirror = NULL;
307 nexell_func_output.output_unset_mirror = NULL;
309 nexell_func_output.output_set_status_handler = nexell_output_set_status_handler;
312 if (nexell_data->hwc_mode) {
313 nexell_func_output.output_get_hwc = nexell_output_get_hwc;
315 memset(&nexell_func_hwc, 0, sizeof(nexell_func_hwc));
316 nexell_func_hwc.hwc_create_window = nexell_hwc_create_window;
317 nexell_func_hwc.hwc_get_video_supported_formats = nexell_hwc_get_video_supported_formats;
318 nexell_func_hwc.hwc_get_video_available_properties = NULL;
319 nexell_func_hwc.hwc_get_capabilities = nexell_hwc_get_capabilities;
320 nexell_func_hwc.hwc_get_available_properties = nexell_hwc_get_available_properties;
321 nexell_func_hwc.hwc_get_client_target_buffer_queue = nexell_hwc_get_client_target_buffer_queue;
322 nexell_func_hwc.hwc_set_client_target_buffer = nexell_hwc_set_client_target_buffer;
323 nexell_func_hwc.hwc_set_client_target_acquire_fence = NULL;
324 nexell_func_hwc.hwc_validate = nexell_hwc_validate;
325 nexell_func_hwc.hwc_get_changed_composition_types = nexell_hwc_get_changed_composition_types;
326 nexell_func_hwc.hwc_accept_validation = nexell_hwc_accept_validation;
327 nexell_func_hwc.hwc_commit = nexell_hwc_commit;
328 nexell_func_hwc.hwc_set_commit_handler = nexell_hwc_set_commit_handler;
329 nexell_func_hwc.hwc_get_commit_fence = NULL;
330 nexell_func_hwc.hwc_get_release_fences = NULL;
332 memset(&nexell_func_hwc_window, 0, sizeof(nexell_func_hwc_window));
333 nexell_func_hwc_window.hwc_window_destroy = nexell_hwc_window_destroy;
334 nexell_func_hwc_window.hwc_window_acquire_buffer_queue = nexell_hwc_window_acquire_buffer_queue;
335 nexell_func_hwc_window.hwc_window_release_buffer_queue = nexell_hwc_window_release_buffer_queue;
336 nexell_func_hwc_window.hwc_window_set_composition_type = nexell_hwc_window_set_composition_type;
337 nexell_func_hwc_window.hwc_window_set_buffer_damage = nexell_hwc_window_set_buffer_damage;
338 nexell_func_hwc_window.hwc_window_set_info = nexell_hwc_window_set_info;
339 nexell_func_hwc_window.hwc_window_set_buffer = nexell_hwc_window_set_buffer;
340 nexell_func_hwc_window.hwc_window_set_property = nexell_hwc_window_set_property;
341 nexell_func_hwc_window.hwc_window_get_property = nexell_hwc_window_get_property;
342 nexell_func_hwc_window.hwc_window_get_constraints = nexell_hwc_window_get_constraints;
343 nexell_func_hwc_window.hwc_window_set_name = nexell_hwc_window_set_name;
344 nexell_func_hwc_window.hwc_window_set_cursor_image = nexell_hwc_window_set_cursor_image;
347 memset(&nexell_func_layer, 0, sizeof(nexell_func_layer));
348 nexell_func_layer.layer_get_capability = nexell_layer_get_capability;
349 nexell_func_layer.layer_set_property = nexell_layer_set_property;
350 nexell_func_layer.layer_get_property = nexell_layer_get_property;
351 nexell_func_layer.layer_set_info = nexell_layer_set_info;
352 nexell_func_layer.layer_get_info = nexell_layer_get_info;
353 nexell_func_layer.layer_set_buffer = nexell_layer_set_buffer;
354 nexell_func_layer.layer_unset_buffer = nexell_layer_unset_buffer;
357 memset(&nexell_func_pp, 0, sizeof(nexell_func_pp));
358 nexell_func_pp.pp_destroy = nexell_pp_destroy;
359 nexell_func_pp.pp_set_info = nexell_pp_set_info;
360 nexell_func_pp.pp_attach = nexell_pp_attach;
361 nexell_func_pp.pp_commit = nexell_pp_commit;
362 nexell_func_pp.pp_set_done_handler = nexell_pp_set_done_handler;
365 ret = tdm_backend_register_func_display(dpy, &nexell_func_display);
366 if (ret != TDM_ERROR_NONE)
369 ret = tdm_backend_register_func_output(dpy, &nexell_func_output);
370 if (ret != TDM_ERROR_NONE)
373 if (nexell_data->hwc_mode) {
374 ret = tdm_backend_register_func_hwc(dpy, &nexell_func_hwc);
375 if (ret != TDM_ERROR_NONE)
378 ret = tdm_backend_register_func_hwc_window(dpy, &nexell_func_hwc_window);
379 if (ret != TDM_ERROR_NONE)
383 ret = tdm_backend_register_func_layer(dpy, &nexell_func_layer);
384 if (ret != TDM_ERROR_NONE)
388 ret = tdm_backend_register_func_pp(dpy, &nexell_func_pp);
389 if (ret != TDM_ERROR_NONE)
393 nexell_data->dpy = dpy;
395 /* The drm master fd can be opened by a tbm backend module in
396 * tbm_bufmgr_init() time. In this case, we just get it from tbm.
398 nexell_data->drm_fd = tbm_drm_helper_get_master_fd();
399 if (nexell_data->drm_fd < 0) {
400 nexell_data->drm_fd = _tdm_nexell_open_drm();
402 if (nexell_data->drm_fd < 0) {
403 ret = TDM_ERROR_OPERATION_FAILED;
407 tbm_drm_helper_set_tbm_master_fd(nexell_data->drm_fd);
410 TDM_INFO("master fd(%d)", nexell_data->drm_fd);
412 nexell_data->scaler_fd = open("/dev/scaler", O_RDWR);
413 if (nexell_data->scaler_fd < 0)
414 TDM_ERR("scaler open fail. cannot use pp.");
417 _tdm_nexell_udev_init(nexell_data);
420 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
421 if (drmSetClientCap(nexell_data->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) {
422 TDM_WRN("Set DRM_CLIENT_CAP_UNIVERSAL_PLANES failed");
424 TDM_INFO("has universal planes");
425 nexell_data->has_universal_plane = 1;
428 if (drmSetClientCap(nexell_data->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0) {
429 TDM_WRN("Set DRM_CLIENT_CAP_ATOMIC failed");
431 TDM_INFO("has atomic");
432 nexell_data->has_atomic = 1;
436 nexell_data->mode_res = drmModeGetResources(nexell_data->drm_fd);
437 if (!nexell_data->mode_res) {
438 TDM_ERR("no drm resource: %m");
439 ret = TDM_ERROR_OPERATION_FAILED;
443 nexell_data->plane_res = drmModeGetPlaneResources(nexell_data->drm_fd);
444 if (!nexell_data->plane_res) {
445 TDM_ERR("no drm plane resource: %m");
446 ret = TDM_ERROR_OPERATION_FAILED;
450 if (nexell_data->plane_res->count_planes <= 0) {
451 TDM_ERR("no drm plane resource");
452 ret = TDM_ERROR_OPERATION_FAILED;
456 ret = tdm_nexell_display_create_output_list(nexell_data);
457 if (ret != TDM_ERROR_NONE)
460 ret = tdm_nexell_display_create_layer_list(nexell_data);
461 if (ret != TDM_ERROR_NONE)
465 *error = TDM_ERROR_NONE;
467 TDM_INFO("init success!");
469 return (tdm_backend_data *)nexell_data;
474 tdm_nexell_deinit(nexell_data);
476 TDM_ERR("init failed!");
480 tdm_backend_module tdm_backend_module_data = {
483 TDM_BACKEND_SET_ABI_VERSION(2, 0),