9 #include "tdm_nexell.h"
10 #include <tdm_helper.h>
11 #include <tbm_drm_helper.h>
15 #define TDM_NEXELL_NAME "vigs"
17 static tdm_nexell_data *nexell_data;
20 static struct udev_device *
21 _tdm_find_primary_gpu(void)
24 struct udev_enumerate *e;
25 struct udev_list_entry *entry;
26 const char *path, *id;
27 struct udev_device *device, *drm_device, *pci;
31 TDM_ERR("fail to initialize udev context\n");
35 e = udev_enumerate_new(udev);
36 udev_enumerate_add_match_subsystem(e, "drm");
37 udev_enumerate_add_match_sysname(e, "card[0-9]*");
39 udev_enumerate_scan_devices(e);
41 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
42 path = udev_list_entry_get_name(entry);
43 device = udev_device_new_from_syspath(udev, path);
47 pci = udev_device_get_parent_with_subsystem_devtype(device,
50 id = udev_device_get_sysattr_value(pci, "boot_vga");
51 if (id && !strcmp(id, "1")) {
53 udev_device_unref(drm_device);
62 udev_device_unref(device);
65 udev_enumerate_unref(e);
70 _tdm_nexell_udev_fd_handler(int fd, tdm_event_loop_mask mask, void *user_data)
72 tdm_nexell_data *edata = (tdm_nexell_data*)user_data;
73 struct udev_device *dev;
79 dev = udev_monitor_receive_device(edata->uevent_monitor);
81 TDM_ERR("couldn't receive device");
82 return TDM_ERROR_OPERATION_FAILED;
85 udev_devnum = udev_device_get_devnum(dev);
87 ret = fstat(edata->drm_fd, &s);
89 TDM_ERR("fstat failed");
90 return TDM_ERROR_OPERATION_FAILED;
93 hotplug = udev_device_get_property_value(dev, "HOTPLUG");
95 if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
96 hotplug && atoi(hotplug) == 1)
99 tdm_nexell_display_update_output_status(edata);
102 udev_device_unref(dev);
104 return TDM_ERROR_NONE;
108 _tdm_nexell_udev_init(tdm_nexell_data *edata)
110 struct udev *u = NULL;
111 struct udev_monitor *mon = NULL;
115 TDM_ERR("couldn't create udev");
119 mon = udev_monitor_new_from_netlink(u, "udev");
121 TDM_ERR("couldn't create udev monitor");
125 if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") > 0 ||
126 udev_monitor_enable_receiving(mon) < 0) {
127 TDM_ERR("add match subsystem failed");
131 edata->uevent_source =
132 tdm_event_loop_add_fd_handler(edata->dpy, udev_monitor_get_fd(mon),
133 TDM_EVENT_LOOP_READABLE,
134 _tdm_nexell_udev_fd_handler,
136 if (!edata->uevent_source) {
137 TDM_ERR("couldn't create udev event source");
141 edata->uevent_monitor = mon;
143 TDM_INFO("hotplug monitor created");
148 udev_monitor_unref(mon);
154 _tdm_nexell_udev_deinit(tdm_nexell_data *edata)
156 if (edata->uevent_source) {
157 tdm_event_loop_source_remove(edata->uevent_source);
158 edata->uevent_source = NULL;
161 if (edata->uevent_monitor) {
162 struct udev *u = udev_monitor_get_udev(edata->uevent_monitor);
163 udev_monitor_unref(edata->uevent_monitor);
165 edata->uevent_monitor = NULL;
166 TDM_INFO("hotplug monitor destroyed");
172 _tdm_nexell_open_drm(void)
176 fd = drmOpen(TDM_NEXELL_NAME, NULL);
178 TDM_WRN("Cannot open '%s' drm", TDM_NEXELL_NAME);
183 struct udev_device *drm_device = NULL;
184 const char *filename;
185 TDM_WRN("Cannot open drm device.. search by udev");
187 drm_device = _tdm_find_primary_gpu();
188 if (drm_device == NULL) {
189 TDM_ERR("fail to find drm device\n");
193 filename = udev_device_get_devnode(drm_device);
195 fd = open(filename, O_RDWR | O_CLOEXEC);
197 TDM_ERR("Cannot open drm device(%s)\n", filename);
199 TDM_DBG("open drm device (name:%s, fd:%d)", filename, fd);
201 udev_device_unref(drm_device);
209 tdm_nexell_deinit(tdm_backend_data *bdata)
211 if (nexell_data != bdata)
217 _tdm_nexell_udev_deinit(nexell_data);
220 tdm_nexell_display_destroy_output_list(nexell_data);
222 if (nexell_data->plane_res)
223 drmModeFreePlaneResources(nexell_data->plane_res);
224 if (nexell_data->mode_res)
225 drmModeFreeResources(nexell_data->mode_res);
226 if (nexell_data->drm_fd >= 0)
227 close(nexell_data->drm_fd);
234 tdm_nexell_init(tdm_display *dpy, tdm_error *error)
236 tdm_func_display nexell_func_display;
237 tdm_func_output nexell_func_output;
238 tdm_func_layer nexell_func_layer;
240 tdm_func_pp nexell_func_pp;
245 TDM_ERR("display is null");
247 *error = TDM_ERROR_INVALID_PARAMETER;
252 TDM_ERR("failed: init twice");
254 *error = TDM_ERROR_BAD_REQUEST;
258 nexell_data = calloc(1, sizeof(tdm_nexell_data));
260 TDM_ERR("alloc failed");
262 *error = TDM_ERROR_OUT_OF_MEMORY;
266 LIST_INITHEAD(&nexell_data->output_list);
267 LIST_INITHEAD(&nexell_data->buffer_list);
269 memset(&nexell_func_display, 0, sizeof(nexell_func_display));
270 nexell_func_display.display_get_capability = nexell_display_get_capability;
271 nexell_func_display.display_get_pp_capability = nexell_display_get_pp_capability;
272 nexell_func_display.display_get_outputs = nexell_display_get_outputs;
273 nexell_func_display.display_get_fd = nexell_display_get_fd;
274 nexell_func_display.display_handle_events = nexell_display_handle_events;
275 nexell_func_display.display_create_pp = nexell_display_create_pp;
277 memset(&nexell_func_output, 0, sizeof(nexell_func_output));
278 nexell_func_output.output_get_capability = nexell_output_get_capability;
279 nexell_func_output.output_get_layers = nexell_output_get_layers;
280 nexell_func_output.output_set_property = nexell_output_set_property;
281 nexell_func_output.output_get_property = nexell_output_get_property;
282 nexell_func_output.output_wait_vblank = nexell_output_wait_vblank;
283 nexell_func_output.output_set_vblank_handler = nexell_output_set_vblank_handler;
284 nexell_func_output.output_commit = nexell_output_commit;
285 nexell_func_output.output_set_commit_handler = nexell_output_set_commit_handler;
286 nexell_func_output.output_set_dpms = nexell_output_set_dpms;
287 nexell_func_output.output_get_dpms = nexell_output_get_dpms;
288 nexell_func_output.output_set_mode = nexell_output_set_mode;
289 nexell_func_output.output_get_mode = nexell_output_get_mode;
291 nexell_func_output.output_set_status_handler = nexell_output_set_status_handler;
294 memset(&nexell_func_layer, 0, sizeof(nexell_func_layer));
295 nexell_func_layer.layer_get_capability = nexell_layer_get_capability;
296 nexell_func_layer.layer_set_property = nexell_layer_set_property;
297 nexell_func_layer.layer_get_property = nexell_layer_get_property;
298 nexell_func_layer.layer_set_info = nexell_layer_set_info;
299 nexell_func_layer.layer_get_info = nexell_layer_get_info;
300 nexell_func_layer.layer_set_buffer = nexell_layer_set_buffer;
301 nexell_func_layer.layer_unset_buffer = nexell_layer_unset_buffer;
304 memset(&nexell_func_pp, 0, sizeof(nexell_func_pp));
305 nexell_func_pp.pp_destroy = nexell_pp_destroy;
306 nexell_func_pp.pp_set_info = nexell_pp_set_info;
307 nexell_func_pp.pp_attach = nexell_pp_attach;
308 nexell_func_pp.pp_commit = nexell_pp_commit;
309 nexell_func_pp.pp_set_done_handler = nexell_pp_set_done_handler;
312 ret = tdm_backend_register_func_display(dpy, &nexell_func_display);
313 if (ret != TDM_ERROR_NONE)
316 ret = tdm_backend_register_func_output(dpy, &nexell_func_output);
317 if (ret != TDM_ERROR_NONE)
320 ret = tdm_backend_register_func_layer(dpy, &nexell_func_layer);
321 if (ret != TDM_ERROR_NONE)
325 ret = tdm_backend_register_func_pp(dpy, &nexell_func_pp);
326 if (ret != TDM_ERROR_NONE)
330 nexell_data->dpy = dpy;
332 /* The drm master fd can be opened by a tbm backend module in
333 * tbm_bufmgr_init() time. In this case, we just get it from tbm.
335 nexell_data->drm_fd = tbm_drm_helper_get_master_fd();
336 if (nexell_data->drm_fd < 0) {
337 nexell_data->drm_fd = _tdm_nexell_open_drm();
339 if (nexell_data->drm_fd < 0) {
340 ret = TDM_ERROR_OPERATION_FAILED;
344 tbm_drm_helper_set_tbm_master_fd(nexell_data->drm_fd);
347 TDM_INFO("master fd(%d)", nexell_data->drm_fd);
350 _tdm_nexell_udev_init(nexell_data);
353 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47
354 if (drmSetClientCap(nexell_data->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) {
355 TDM_WRN("Set DRM_CLIENT_CAP_UNIVERSAL_PLANES failed");
357 TDM_INFO("has universal planes");
358 nexell_data->has_universal_plane = 1;
362 nexell_data->mode_res = drmModeGetResources(nexell_data->drm_fd);
363 if (!nexell_data->mode_res) {
364 TDM_ERR("no drm resource: %m");
365 ret = TDM_ERROR_OPERATION_FAILED;
369 nexell_data->plane_res = drmModeGetPlaneResources(nexell_data->drm_fd);
370 if (!nexell_data->plane_res) {
371 TDM_ERR("no drm plane resource: %m");
372 ret = TDM_ERROR_OPERATION_FAILED;
376 if (nexell_data->plane_res->count_planes <= 0) {
377 TDM_ERR("no drm plane resource");
378 ret = TDM_ERROR_OPERATION_FAILED;
382 ret = tdm_nexell_display_create_output_list(nexell_data);
383 if (ret != TDM_ERROR_NONE)
386 ret = tdm_nexell_display_create_layer_list(nexell_data);
387 if (ret != TDM_ERROR_NONE)
391 *error = TDM_ERROR_NONE;
393 TDM_INFO("init success!");
395 return (tdm_backend_data *)nexell_data;
400 tdm_nexell_deinit(nexell_data);
402 TDM_ERR("init failed!");
406 tdm_backend_module tdm_backend_module_data = {
409 TDM_BACKEND_SET_ABI_VERSION(1, 1),