2 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
3 * Copyright (C) 2010-2011 LunarG Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 #define LOG_TAG "GRALLOC-KMS"
26 #include <cutils/properties.h>
27 #include <cutils/log.h>
34 #include "gralloc_drm.h"
35 #include "gralloc_drm_priv.h"
36 #include <hardware_legacy/uevent.h>
38 #include <drm_fourcc.h>
41 * Return true if a bo needs fb.
43 int gralloc_drm_bo_need_fb(const struct gralloc_drm_bo_t *bo)
45 return ((bo->handle->usage & GRALLOC_USAGE_HW_FB) &&
46 bo->drm->swap_mode != DRM_SWAP_COPY);
49 static unsigned int drm_format_from_hal(int hal_format)
52 case HAL_PIXEL_FORMAT_RGB_888:
53 case HAL_PIXEL_FORMAT_BGRA_8888:
54 return DRM_FORMAT_XRGB8888;
55 case HAL_PIXEL_FORMAT_RGBX_8888:
56 return DRM_FORMAT_XBGR8888;
57 case HAL_PIXEL_FORMAT_RGBA_8888:
58 return DRM_FORMAT_RGBA8888;
59 case HAL_PIXEL_FORMAT_RGB_565:
60 return DRM_FORMAT_RGB565;
61 case HAL_PIXEL_FORMAT_YV12:
62 return DRM_FORMAT_YUV420;
63 case HAL_PIXEL_FORMAT_DRM_NV12:
64 return DRM_FORMAT_NV12;
71 * Modify pitches, offsets and handles according to
72 * the format and return corresponding drm format value
74 static int resolve_drm_format(struct gralloc_drm_bo_t *bo,
75 uint32_t *pitches, uint32_t *offsets, uint32_t *handles)
77 struct gralloc_drm_t *drm = bo->drm;
79 pitches[0] = bo->handle->stride;
80 handles[0] = bo->fb_handle;
82 /* driver takes care of HW specific padding, alignment etc. */
83 if (drm->drv->resolve_format)
84 drm->drv->resolve_format(drm->drv, bo,
85 pitches, offsets, handles);
87 return drm_format_from_hal(bo->handle->format);
91 * Returns planes that are supported for a particular format
93 unsigned int planes_for_format(struct gralloc_drm_t *drm,
96 unsigned int i, j, mask = 0;
97 unsigned int drm_format = drm_format_from_hal(hal_format);
98 struct gralloc_drm_plane_t *plane = drm->planes;
100 /* no planes available */
104 /* iterate through planes, mark those that match format */
105 for (i=0; i<drm->plane_resources->count_planes; i++, plane++)
106 for (j=0; j<plane->drm_plane->count_formats; j++)
107 if (plane->drm_plane->formats[j] == drm_format)
108 mask |= (1U << plane->drm_plane->plane_id);
114 * Add a fb object for a bo.
116 int gralloc_drm_bo_add_fb(struct gralloc_drm_bo_t *bo)
118 uint32_t pitches[4] = { 0, 0, 0, 0 };
119 uint32_t offsets[4] = { 0, 0, 0, 0 };
120 uint32_t handles[4] = { 0, 0, 0, 0 };
125 int drm_format = resolve_drm_format(bo, pitches, offsets, handles);
127 if (drm_format == 0) {
128 ALOGE("error resolving drm format");
132 return drmModeAddFB2(bo->drm->fd,
133 bo->handle->width, bo->handle->height,
134 drm_format, handles, pitches, offsets,
135 (uint32_t *) &bo->fb_id, 0);
139 * Remove a fb object for a bo.
141 void gralloc_drm_bo_rm_fb(struct gralloc_drm_bo_t *bo)
144 drmModeRmFB(bo->drm->fd, bo->fb_id);
152 static int drm_kms_set_crtc(struct gralloc_drm_t *drm,
153 struct gralloc_drm_output *output, int fb_id)
157 ret = drmModeSetCrtc(drm->fd, output->crtc_id, fb_id,
158 0, 0, &output->connector_id, 1, &output->mode);
160 ALOGE("failed to set crtc (%s) (crtc_id %d, fb_id %d, conn %d, mode %dx%d)",
161 strerror(errno), output->crtc_id, fb_id, output->connector_id,
162 output->mode.hdisplay, output->mode.vdisplay);
166 if (drm->mode_quirk_vmwgfx)
167 ret = drmModeDirtyFB(drm->fd, fb_id, &drm->clip, 1);
173 * Callback for a page flip event.
175 static void page_flip_handler(int fd, unsigned int sequence,
176 unsigned int tv_sec, unsigned int tv_usec,
179 struct gralloc_drm_t *drm = (struct gralloc_drm_t *) user_data;
181 /* ack the last scheduled flip */
182 drm->current_front = drm->next_front;
183 drm->next_front = NULL;
189 static int gralloc_drm_bo_setplane(struct gralloc_drm_t *drm,
190 struct gralloc_drm_plane_t *plane)
192 struct gralloc_drm_bo_t *bo = NULL;
196 bo = gralloc_drm_bo_from_handle(plane->handle);
198 // create a framebuffer if does not exist
199 if (bo && bo->fb_id == 0) {
200 err = gralloc_drm_bo_add_fb(bo);
202 ALOGE("%s: could not create drm fb, (%s)",
203 __func__, strerror(-err));
208 err = drmModeSetPlane(drm->fd,
209 plane->drm_plane->plane_id,
210 drm->primary.crtc_id,
223 /* clear plane_mask so that this buffer won't be tried again */
224 struct gralloc_drm_handle_t *drm_handle =
225 (struct gralloc_drm_handle_t *) plane->handle;
226 drm_handle->plane_mask = 0;
228 ALOGE("drmModeSetPlane : error (%s) (plane %d crtc %d fb %d)",
230 plane->drm_plane->plane_id,
231 drm->primary.crtc_id,
236 gralloc_drm_bo_decref(plane->prev);
247 * Returns if a particular plane is supported with the implementation
249 static unsigned is_plane_supported(const struct gralloc_drm_t *drm,
250 const struct gralloc_drm_plane_t *plane)
252 /* Planes are only supported on primary pipe for now */
253 return plane->drm_plane->possible_crtcs & (1 << drm->primary.pipe);
257 * Sets all the active planes to be displayed.
259 static void gralloc_drm_set_planes(struct gralloc_drm_t *drm)
261 struct gralloc_drm_plane_t *plane = drm->planes;
263 for (i = 0; i < drm->plane_resources->count_planes;
265 /* plane is not in use at all */
266 if (!plane->active && !plane->handle)
269 /* plane is active, safety check if it is supported */
270 if (!is_plane_supported(drm, plane))
271 ALOGE("%s: plane %d is not supported",
272 __func__, plane->drm_plane->plane_id);
275 * Disable overlay if it is not active
276 * or if there is error during setplane
281 if (gralloc_drm_bo_setplane(drm, plane))
287 * Interface for HWC, used to reserve a plane for a layer.
289 int gralloc_drm_reserve_plane(struct gralloc_drm_t *drm,
290 buffer_handle_t handle,
302 struct gralloc_drm_handle_t *drm_handle =
303 gralloc_drm_handle(handle);
304 int plane_count = drm->plane_resources->count_planes;
305 struct gralloc_drm_plane_t *plane = drm->planes;
307 /* no supported planes for this handle */
308 if (!drm_handle->plane_mask) {
309 ALOGE("%s: buffer %p cannot be shown on a plane\n",
310 __func__, drm_handle);
314 for (j = 0; j < plane_count; j++, plane++) {
317 * handle may be suitable to be shown on a plane, in
318 * addition we need to check that this particular plane
319 * is supported by the current implementation
321 if (!is_plane_supported(drm, plane))
324 /* if plane is available and can support this buffer */
325 if (!plane->active &&
326 drm_handle->plane_mask &
327 (1U << plane->drm_plane->plane_id)) {
329 plane->dst_x = dst_x;
330 plane->dst_y = dst_y;
331 plane->dst_w = dst_w;
332 plane->dst_h = dst_h;
333 plane->src_x = src_x;
334 plane->src_y = src_y;
335 plane->src_w = src_w;
336 plane->src_h = src_h;
337 plane->handle = handle;
345 /* no free planes available */
350 * Interface for HWC, used to disable all the overlays. Plane id
351 * is also set to 0 as it should be mappable to a particular layer only
352 * if it has been reserved with 'reserve_plane'.
354 void gralloc_drm_disable_planes(struct gralloc_drm_t *drm)
356 struct gralloc_drm_plane_t *plane = drm->planes;
359 for (i = 0; i < drm->plane_resources->count_planes; i++, plane++) {
366 * Interface for HWC, used to change handle of a reserved plane.
368 int gralloc_drm_set_plane_handle(struct gralloc_drm_t *drm,
369 uint32_t id, buffer_handle_t handle)
371 struct gralloc_drm_plane_t *plane = drm->planes;
374 for (i = 0; i < drm->plane_resources->count_planes; i++, plane++)
375 if (plane->active && plane->id == id) {
376 plane->handle = handle;
384 * Schedule a page flip.
386 static int drm_kms_page_flip(struct gralloc_drm_t *drm,
387 struct gralloc_drm_bo_t *bo)
391 /* there is another flip pending */
392 while (drm->next_front) {
393 drm->waiting_flip = 1;
394 drmHandleEvent(drm->fd, &drm->evctx);
395 drm->waiting_flip = 0;
396 if (drm->next_front) {
397 /* record an error and break */
398 ALOGE("drmHandleEvent returned without flipping");
399 drm->current_front = drm->next_front;
400 drm->next_front = NULL;
407 pthread_mutex_lock(&drm->hdmi_mutex);
408 if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo) {
410 int dst_x1 = 0, dst_y1 = 0;
412 if (drm->hdmi.bo->handle->width > bo->handle->width)
413 dst_x1 = (drm->hdmi.bo->handle->width - bo->handle->width) / 2;
414 if (drm->hdmi.bo->handle->height > bo->handle->height)
415 dst_y1 = (drm->hdmi.bo->handle->height - bo->handle->height) / 2;
417 drm->drv->blit(drm->drv, drm->hdmi.bo, bo,
419 dst_x1 + bo->handle->width,
420 dst_y1 + bo->handle->height,
421 0, 0, bo->handle->width, bo->handle->height);
423 ret = drmModePageFlip(drm->fd, drm->hdmi.crtc_id, drm->hdmi.bo->fb_id, 0, NULL);
424 if (ret && errno != EBUSY)
425 ALOGE("failed to perform page flip for hdmi (%s) (crtc %d fb %d))",
426 strerror(errno), drm->hdmi.crtc_id, drm->hdmi.bo->fb_id);
428 pthread_mutex_unlock(&drm->hdmi_mutex);
430 /* set planes to be displayed */
431 gralloc_drm_set_planes(drm);
433 ret = drmModePageFlip(drm->fd, drm->primary.crtc_id, bo->fb_id,
434 DRM_MODE_PAGE_FLIP_EVENT, (void *) drm);
436 ALOGE("failed to perform page flip for primary (%s) (crtc %d fb %d))",
437 strerror(errno), drm->primary.crtc_id, bo->fb_id);
438 /* try to set mode for next frame */
443 drm->next_front = bo;
449 * Wait for the next post.
451 static void drm_kms_wait_for_post(struct gralloc_drm_t *drm, int flip)
453 unsigned int current, target;
457 if (drm->mode_quirk_vmwgfx)
462 memset(&vbl, 0, sizeof(vbl));
463 vbl.request.type = DRM_VBLANK_RELATIVE;
464 if (drm->vblank_secondary)
465 vbl.request.type |= DRM_VBLANK_SECONDARY;
466 vbl.request.sequence = 0;
468 /* get the current vblank */
469 ret = drmWaitVBlank(drm->fd, &vbl);
471 ALOGW("failed to get vblank");
475 current = vbl.reply.sequence;
479 target = drm->last_swap + drm->swap_interval - flip;
481 /* wait for vblank */
482 if (current < target || !flip) {
483 memset(&vbl, 0, sizeof(vbl));
484 vbl.request.type = DRM_VBLANK_ABSOLUTE;
485 if (drm->vblank_secondary)
486 vbl.request.type |= DRM_VBLANK_SECONDARY;
488 vbl.request.type |= DRM_VBLANK_NEXTONMISS;
489 if (target < current)
493 vbl.request.sequence = target;
495 ret = drmWaitVBlank(drm->fd, &vbl);
497 ALOGW("failed to wait vblank");
502 drm->last_swap = vbl.reply.sequence + flip;
506 * Post a bo. This is not thread-safe.
508 int gralloc_drm_bo_post(struct gralloc_drm_bo_t *bo)
510 struct gralloc_drm_t *drm = bo->drm;
513 if (!bo->fb_id && drm->swap_mode != DRM_SWAP_COPY) {
514 ALOGE("unable to post bo %p without fb", bo);
518 /* TODO spawn a thread to avoid waiting and race */
520 if (drm->first_post) {
521 if (drm->swap_mode == DRM_SWAP_COPY) {
522 struct gralloc_drm_bo_t *dst;
524 dst = (drm->next_front) ?
527 drm->drv->blit(drm->drv, dst, bo, 0, 0,
536 ret = drm_kms_set_crtc(drm, &drm->primary, bo->fb_id);
539 drm->current_front = bo;
540 if (drm->next_front == bo)
541 drm->next_front = NULL;
544 pthread_mutex_lock(&drm->hdmi_mutex);
545 if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo)
546 drm_kms_set_crtc(drm, &drm->hdmi, drm->hdmi.bo->fb_id);
547 pthread_mutex_unlock(&drm->hdmi_mutex);
552 switch (drm->swap_mode) {
554 if (drm->swap_interval > 1)
555 drm_kms_wait_for_post(drm, 1);
556 ret = drm_kms_page_flip(drm, bo);
557 if (drm->next_front) {
559 * wait if the driver says so or the current front
560 * will be written by CPU
562 if (drm->mode_sync_flip ||
563 (drm->current_front->handle->usage &
564 GRALLOC_USAGE_SW_WRITE_MASK))
565 drm_kms_page_flip(drm, NULL);
569 drm_kms_wait_for_post(drm, 0);
570 drm->drv->blit(drm->drv, drm->current_front,
577 if (drm->mode_quirk_vmwgfx)
578 ret = drmModeDirtyFB(drm->fd, drm->current_front->fb_id, &drm->clip, 1);
581 case DRM_SWAP_SETCRTC:
582 drm_kms_wait_for_post(drm, 0);
583 ret = drm_kms_set_crtc(drm, &drm->primary, bo->fb_id);
585 pthread_mutex_lock(&drm->hdmi_mutex);
586 if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo)
587 drm_kms_set_crtc(drm, &drm->hdmi, drm->hdmi.bo->fb_id);
588 pthread_mutex_unlock(&drm->hdmi_mutex);
590 drm->current_front = bo;
601 static struct gralloc_drm_t *drm_singleton;
603 static void on_signal(int sig)
605 struct gralloc_drm_t *drm = drm_singleton;
607 /* wait the pending flip */
608 if (drm && drm->swap_mode == DRM_SWAP_FLIP && drm->next_front) {
609 /* there is race, but this function is hacky enough to ignore that */
610 if (drm_singleton->waiting_flip)
611 usleep(100 * 1000); /* 100ms */
613 drm_kms_page_flip(drm_singleton, NULL);
619 static void drm_kms_init_features(struct gralloc_drm_t *drm)
621 const char *swap_mode;
623 /* call to the driver here, after KMS has been initialized */
624 drm->drv->init_kms_features(drm->drv, drm);
626 if (drm->swap_mode == DRM_SWAP_FLIP) {
627 struct sigaction act;
629 memset(&drm->evctx, 0, sizeof(drm->evctx));
630 drm->evctx.version = DRM_EVENT_CONTEXT_VERSION;
631 drm->evctx.page_flip_handler = page_flip_handler;
634 * XXX GPU tends to freeze if the program is terminiated with a
635 * flip pending. What is the right way to handle the
638 sigemptyset(&act.sa_mask);
639 act.sa_handler = on_signal;
641 sigaction(SIGINT, &act, NULL);
642 sigaction(SIGTERM, &act, NULL);
646 else if (drm->swap_mode == DRM_SWAP_COPY) {
647 struct gralloc_drm_bo_t *front;
650 /* create the real front buffer */
651 front = gralloc_drm_bo_create(drm,
652 drm->primary.mode.hdisplay,
653 drm->primary.mode.vdisplay,
654 drm->primary.fb_format,
655 GRALLOC_USAGE_HW_FB);
656 if (front && gralloc_drm_bo_add_fb(front)) {
657 gralloc_drm_bo_decref(front);
661 /* abuse next_front */
663 drm->next_front = front;
665 drm->swap_mode = DRM_SWAP_SETCRTC;
668 switch (drm->swap_mode) {
675 case DRM_SWAP_SETCRTC:
676 swap_mode = "set-crtc";
683 ALOGD("will use %s for fb posting", swap_mode);
686 static drmModeModeInfoPtr find_mode(drmModeConnectorPtr connector, int *bpp)
688 char value[PROPERTY_VALUE_MAX];
689 drmModeModeInfoPtr mode;
691 int xres = 0, yres = 0;
693 if (property_get("debug.drm.mode", value, NULL)) {
694 char *p = value, *end;
696 /* parse <xres>x<yres>[@<bpp>] */
697 if (sscanf(value, "%dx%d@%d", &xres, &yres, bpp) != 3) {
699 if (sscanf(value, "%dx%d", &xres, &yres) != 2)
703 if ((xres && yres) || *bpp) {
704 ALOGI("will find the closest match for %dx%d@%d",
714 for (i = 0; i < connector->count_modes; i++) {
715 drmModeModeInfoPtr m = &connector->modes[i];
719 tmp = (m->hdisplay - xres) * (m->hdisplay - xres) +
720 (m->vdisplay - yres) * (m->vdisplay - yres);
723 /* use the first preferred mode */
724 tmp = (m->type & DRM_MODE_TYPE_PREFERRED) ? 0 : dist;
735 /* fallback to the first mode */
737 mode = &connector->modes[0];
745 * Initialize KMS with a connector.
747 static int drm_kms_init_with_connector(struct gralloc_drm_t *drm,
748 struct gralloc_drm_output *output, drmModeConnectorPtr connector)
750 drmModeEncoderPtr encoder;
751 drmModeModeInfoPtr mode;
752 static int used_crtcs = 0;
755 if (!connector->count_modes)
758 encoder = drmModeGetEncoder(drm->fd, connector->encoders[0]);
762 /* find first possible crtc which is not used yet */
763 for (i = 0; i < drm->resources->count_crtcs; i++) {
764 if (encoder->possible_crtcs & (1 << i) &&
765 (used_crtcs & (1 << i)) != (1 << i))
769 used_crtcs |= (1 << i);
771 drmModeFreeEncoder(encoder);
772 if (i == drm->resources->count_crtcs)
776 output->crtc_id = drm->resources->crtcs[i];
777 output->connector_id = connector->connector_id;
780 /* print connector info */
781 if (connector->count_modes > 1) {
782 ALOGI("there are %d modes on connector 0x%x, type %d",
783 connector->count_modes,
784 connector->connector_id,
785 connector->connector_type);
786 for (i = 0; i < connector->count_modes; i++)
787 ALOGI(" %s", connector->modes[i].name);
790 ALOGI("there is one mode on connector 0x%d: %s",
791 connector->connector_id,
792 connector->modes[0].name);
795 mode = find_mode(connector, &bpp);
797 ALOGI("the best mode is %s", mode->name);
799 output->mode = *mode;
802 output->fb_format = HAL_PIXEL_FORMAT_RGB_565;
806 output->fb_format = HAL_PIXEL_FORMAT_BGRA_8888;
810 if (connector->mmWidth && connector->mmHeight) {
811 output->xdpi = (output->mode.hdisplay * 25.4 / connector->mmWidth);
812 output->ydpi = (output->mode.vdisplay * 25.4 / connector->mmHeight);
819 #ifdef DRM_MODE_FEATURE_DIRTYFB
822 drm->clip.x2 = output->mode.hdisplay;
823 drm->clip.y2 = output->mode.vdisplay;
831 * Fetch a connector of particular type
833 static drmModeConnectorPtr fetch_connector(struct gralloc_drm_t *drm,
841 for (i = 0; i < drm->resources->count_connectors; i++) {
842 drmModeConnectorPtr connector =
843 connector = drmModeGetConnector(drm->fd,
844 drm->resources->connectors[i]);
846 if (connector->connector_type == type &&
847 connector->connection == DRM_MODE_CONNECTED)
849 drmModeFreeConnector(connector);
857 * Initializes hdmi output with a connector and allocates
858 * a private framebuffer for it. This is called on startup if
859 * hdmi cable is connected and also on hotplug events.
861 static void init_hdmi_output(struct gralloc_drm_t *drm,
862 drmModeConnectorPtr connector)
864 drm_kms_init_with_connector(drm, &drm->hdmi, connector);
866 ALOGD("%s, allocate private buffer for hdmi [%dx%d]",
867 __func__, drm->hdmi.mode.hdisplay, drm->hdmi.mode.vdisplay);
869 drm->hdmi.bo = gralloc_drm_bo_create(drm,
870 drm->hdmi.mode.hdisplay, drm->hdmi.mode.vdisplay,
872 GRALLOC_USAGE_SW_WRITE_OFTEN|GRALLOC_USAGE_HW_RENDER);
874 gralloc_drm_bo_add_fb(drm->hdmi.bo);
876 drm->hdmi_mode = HDMI_CLONED;
877 drm->hdmi.active = 1;
882 * Thread that listens to uevents and checks if hdmi state changes
884 static void *hdmi_observer(void *data)
886 static char uevent_desc[4096];
887 drmModeConnectorPtr hdmi;
888 struct gralloc_drm_t *drm =
889 (struct gralloc_drm_t *) data;
893 memset(uevent_desc, 0, sizeof(uevent_desc));
898 int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
900 if(len && strstr(uevent_desc, "devices/virtual/switch/hdmi")) {
902 /* check what changed */
903 const char *prop = uevent_desc + strlen(uevent_desc) + 1;
907 const char *state = strstr(prop, "SWITCH_STATE=");
909 unsigned int value = 0;
910 state += strlen("SWITCH_STATE=");
913 pthread_mutex_lock(&drm->hdmi_mutex);
916 hdmi = fetch_connector(drm, DRM_MODE_CONNECTOR_HDMIA);
919 ALOGD("init hdmi on hotplug event");
920 init_hdmi_output(drm, hdmi);
922 /* will trigger modeset */
925 drmModeFreeConnector(hdmi);
927 pthread_mutex_unlock(&drm->hdmi_mutex);
931 drm->hdmi.active = 0;
933 ALOGD("destroy hdmi private buffer");
934 gralloc_drm_bo_decref(drm->hdmi.bo);
937 pthread_mutex_unlock(&drm->hdmi_mutex);
941 pthread_mutex_unlock(&drm->hdmi_mutex);
944 /* next property/value pair */
945 prop += strlen(prop) + 1;
946 if (prop - uevent_desc >= len)
960 int gralloc_drm_init_kms(struct gralloc_drm_t *drm)
962 drmModeConnectorPtr lvds, hdmi;
968 drm->resources = drmModeGetResources(drm->fd);
969 if (!drm->resources) {
970 ALOGE("failed to get modeset resources");
974 drm->plane_resources = drmModeGetPlaneResources(drm->fd);
975 if (!drm->plane_resources) {
976 ALOGD("no planes found from drm resources");
978 ALOGD("supported drm planes and formats");
979 /* fill a helper structure for hwcomposer */
980 drm->planes = calloc(drm->plane_resources->count_planes,
981 sizeof(struct gralloc_drm_plane_t));
983 for (i = 0; i < drm->plane_resources->count_planes; i++) {
987 drm->planes[i].drm_plane = drmModeGetPlane(drm->fd,
988 drm->plane_resources->planes[i]);
990 ALOGD("plane id %d", drm->planes[i].drm_plane->plane_id);
991 for (j = 0; j < drm->planes[i].drm_plane->count_formats; j++)
992 ALOGD(" format %c%c%c%c",
993 (drm->planes[i].drm_plane->formats[j]),
994 (drm->planes[i].drm_plane->formats[j])>>8,
995 (drm->planes[i].drm_plane->formats[j])>>16,
996 (drm->planes[i].drm_plane->formats[j])>>24);
1000 /* find the crtc/connector/mode to use */
1001 lvds = fetch_connector(drm, DRM_MODE_CONNECTOR_LVDS);
1003 drm_kms_init_with_connector(drm, &drm->primary, lvds);
1004 drmModeFreeConnector(lvds);
1005 drm->primary.active = 1;
1008 /* if still no connector, find first connected connector and try it */
1009 if (!drm->primary.active) {
1011 for (i = 0; i < drm->resources->count_connectors; i++) {
1012 drmModeConnectorPtr connector;
1014 connector = drmModeGetConnector(drm->fd,
1015 drm->resources->connectors[i]);
1017 if (connector->connection == DRM_MODE_CONNECTED) {
1018 if (!drm_kms_init_with_connector(drm,
1019 &drm->primary, connector))
1023 drmModeFreeConnector(connector);
1026 if (i == drm->resources->count_connectors) {
1027 ALOGE("failed to find a valid crtc/connector/mode combination");
1028 drmModeFreeResources(drm->resources);
1029 drm->resources = NULL;
1036 /* check if hdmi is connected already */
1037 hdmi = fetch_connector(drm, DRM_MODE_CONNECTOR_HDMIA);
1040 if (hdmi->connector_id == drm->primary.connector_id) {
1041 /* special case: our primary connector is hdmi */
1042 ALOGD("hdmi is the primary connector");
1043 goto skip_hdmi_modes;
1046 ALOGD("init hdmi on startup");
1047 init_hdmi_output(drm, hdmi);
1049 drmModeFreeConnector(hdmi);
1052 /* launch hdmi observer thread */
1053 pthread_mutex_init(&drm->hdmi_mutex, NULL);
1054 pthread_create(&drm->hdmi_hotplug_thread, NULL, hdmi_observer, drm);
1058 drm_kms_init_features(drm);
1059 drm->first_post = 1;
1064 void gralloc_drm_fini_kms(struct gralloc_drm_t *drm)
1066 switch (drm->swap_mode) {
1068 drm_kms_page_flip(drm, NULL);
1072 struct gralloc_drm_bo_t **bo = (drm->current_front) ?
1073 &drm->current_front : &drm->next_front;
1076 gralloc_drm_bo_decref(*bo);
1086 if (drm->resources) {
1087 drmModeFreeResources(drm->resources);
1088 drm->resources = NULL;
1093 for (i = 0; i < drm->plane_resources->count_planes; i++)
1094 drmModeFreePlane(drm->planes[i].drm_plane);
1099 if (drm->plane_resources) {
1100 drmModeFreePlaneResources(drm->plane_resources);
1101 drm->plane_resources = NULL;
1104 /* destroy private buffer of hdmi output */
1106 gralloc_drm_bo_decref(drm->hdmi.bo);
1108 drm_singleton = NULL;
1111 int gralloc_drm_is_kms_initialized(struct gralloc_drm_t *drm)
1113 return (drm->resources != NULL);
1117 * Initialize a framebuffer device with KMS info.
1119 void gralloc_drm_get_kms_info(struct gralloc_drm_t *drm,
1120 struct framebuffer_device_t *fb)
1122 *((uint32_t *) &fb->flags) = 0x0;
1123 *((uint32_t *) &fb->width) = drm->primary.mode.hdisplay;
1124 *((uint32_t *) &fb->height) = drm->primary.mode.vdisplay;
1125 *((int *) &fb->stride) = drm->primary.mode.hdisplay;
1126 *((float *) &fb->fps) = drm->primary.mode.vrefresh;
1128 *((int *) &fb->format) = drm->primary.fb_format;
1129 *((float *) &fb->xdpi) = drm->primary.xdpi;
1130 *((float *) &fb->ydpi) = drm->primary.ydpi;
1131 *((int *) &fb->minSwapInterval) = drm->swap_interval;
1132 *((int *) &fb->maxSwapInterval) = drm->swap_interval;
1136 * Return true if fb posting is pipelined.
1138 int gralloc_drm_is_kms_pipelined(struct gralloc_drm_t *drm)
1140 return (drm->swap_mode != DRM_SWAP_SETCRTC);