Example #1
0
static int
stereo_find_crtc(drmModeRes *res, drmModeConnector *conn,
                 struct gbm_dev *dev)
{
        drmModeEncoder *enc;
        unsigned int i, j;
        int32_t crtc;

        /* first try the currently conected encoder+crtc */
        if (conn->encoder_id) {
                enc = drmModeGetEncoder(dev->fd, conn->encoder_id);
                if (enc->crtc_id >= 0) {
                        drmModeFreeEncoder(enc);
                        dev->crtc = enc->crtc_id;
                        return 0;
                }
        }

        /* If the connector is not currently bound to an encoder
         * iterate all other available encoders to find a matching
         * CRTC. */
        for (i = 0; i < conn->count_encoders; ++i) {
                enc = drmModeGetEncoder(dev->fd, conn->encoders[i]);
                if (!enc) {
                        fprintf(stderr,
                                "cannot retrieve encoder %u:%u (%d): %m\n",
                                i, conn->encoders[i], errno);
                        continue;
                }

                /* iterate all global CRTCs */
                for (j = 0; j < res->count_crtcs; ++j) {
                        /* check whether this CRTC works with the encoder */
                        if (!(enc->possible_crtcs & (1 << j)))
                                continue;

                        /* check that no other device already uses this CRTC */
                        crtc = res->crtcs[j];

                        /* we have found a CRTC, so save it and return */
                        if (crtc >= 0) {
                                drmModeFreeEncoder(enc);
                                dev->crtc = crtc;
                                return 0;
                        }
                }

                drmModeFreeEncoder(enc);
        }

        fprintf(stderr, "cannot find suitable CRTC for connector %u\n",
                conn->connector_id);
        return -ENOENT;
}
static drmModeCrtc *
find_crtc_for_connector (int fd, drmModeRes * res, drmModeConnector * conn,
    guint * pipe)
{
  int i;
  int crtc_id;
  drmModeEncoder *enc;
  drmModeCrtc *crtc;
  guint32 crtcs_for_connector = 0;

  crtc_id = -1;
  for (i = 0; i < res->count_encoders; i++) {
    enc = drmModeGetEncoder (fd, res->encoders[i]);
    if (enc) {
      if (enc->encoder_id == conn->encoder_id) {
        crtc_id = enc->crtc_id;
        drmModeFreeEncoder (enc);
        break;
      }
      drmModeFreeEncoder (enc);
    }
  }

  /* If no active crtc was found, pick the first possible crtc */
  if (crtc_id == -1) {
    for (i = 0; i < conn->count_encoders; i++) {
      enc = drmModeGetEncoder (fd, conn->encoders[i]);
      crtcs_for_connector |= enc->possible_crtcs;
      drmModeFreeEncoder (enc);
    }

    if (crtcs_for_connector != 0)
      crtc_id = res->crtcs[ffs (crtcs_for_connector) - 1];
  }

  if (crtc_id == -1)
    return NULL;

  for (i = 0; i < res->count_crtcs; i++) {
    crtc = drmModeGetCrtc (fd, res->crtcs[i]);
    if (crtc) {
      if (crtc_id == crtc->crtc_id) {
        if (pipe)
          *pipe = i;
        return crtc;
      }
      drmModeFreeCrtc (crtc);
    }
  }

  return NULL;
}
Example #3
0
static drmModeEncoder *
find_encoder_for_connector (ply_renderer_backend_t *backend,
                            drmModeConnector       *connector)
{
  int i;
  drmModeEncoder *encoder;

  assert (backend != NULL);

  for (i = 0; i < connector->count_encoders; i++)
    {
      encoder = drmModeGetEncoder (backend->device_fd,
                                   connector->encoders[i]);

      if (encoder == NULL)
        continue;

      if (encoder->encoder_id == connector->encoder_id)
        return encoder;

      drmModeFreeEncoder (encoder);
    }

  return NULL;
}
Example #4
0
/* XXX: Checking this repeatedly actually hangs the GPU. I have literally no
 *      idea why. */
static void
connector_check_current_state(struct kms_atomic_connector_state *connector)
{
	struct kms_atomic_connector_state connector_kernel;
	drmModeConnectorPtr legacy;
	uint32_t crtc_id;

	legacy = drmModeGetConnectorCurrent(connector->state->desc->fd,
					    connector->obj);
	igt_assert(legacy);

	if (legacy->encoder_id) {
		drmModeEncoderPtr legacy_enc;

		legacy_enc = drmModeGetEncoder(connector->state->desc->fd,
					       legacy->encoder_id);
		igt_assert(legacy_enc);

		crtc_id = legacy_enc->crtc_id;
		drmModeFreeEncoder(legacy_enc);
	} else {
		crtc_id = 0;
	}

	igt_assert_eq_u32(crtc_id, connector->crtc_id);

	memcpy(&connector_kernel, connector, sizeof(connector_kernel));
	connector_get_current_state(&connector_kernel);
	do_or_die(memcmp(&connector_kernel, connector,
			 sizeof(connector_kernel)));

	drmModeFreeConnector(legacy);
}
Example #5
0
/**
 * Remember the original CRTC status and set the CRTC
 */
static boolean
drm_display_set_crtc(struct native_display *ndpy, int crtc_idx,
                     uint32_t buffer_id, uint32_t x, uint32_t y,
                     uint32_t *connectors, int num_connectors,
                     drmModeModeInfoPtr mode)
{
   struct drm_display *drmdpy = drm_display(ndpy);
   struct drm_crtc *drmcrtc = &drmdpy->saved_crtcs[crtc_idx];
   uint32_t crtc_id;
   int err;

   if (drmcrtc->crtc) {
      crtc_id = drmcrtc->crtc->crtc_id;
   }
   else {
      int count = 0, i;

      /*
       * Choose the CRTC once.  It could be more dynamic, but let's keep it
       * simple for now.
       */
      crtc_id = drm_display_choose_crtc(&drmdpy->base,
            connectors, num_connectors);

      /* save the original CRTC status */
      drmcrtc->crtc = drmModeGetCrtc(drmdpy->fd, crtc_id);
      if (!drmcrtc->crtc)
         return FALSE;

      for (i = 0; i < drmdpy->num_connectors; i++) {
         struct drm_connector *drmconn = &drmdpy->connectors[i];
         drmModeConnectorPtr connector = drmconn->connector;
         drmModeEncoderPtr encoder;

         encoder = drmModeGetEncoder(drmdpy->fd, connector->encoder_id);
         if (encoder) {
            if (encoder->crtc_id == crtc_id) {
               drmcrtc->connectors[count++] = connector->connector_id;
               if (count >= Elements(drmcrtc->connectors))
                  break;
            }
            drmModeFreeEncoder(encoder);
         }
      }

      drmcrtc->num_connectors = count;
   }

   err = drmModeSetCrtc(drmdpy->fd, crtc_id, buffer_id, x, y,
         connectors, num_connectors, mode);
   if (err) {
      drmModeFreeCrtc(drmcrtc->crtc);
      drmcrtc->crtc = NULL;
      drmcrtc->num_connectors = 0;

      return FALSE;
   }

   return TRUE;
}
Example #6
0
File: drm.c Project: ibab/swc
static bool find_available_crtc(drmModeRes * resources,
                                drmModeConnector * connector,
                                uint32_t taken_crtcs, uint32_t * crtc)
{
    uint32_t encoder_index, crtc_index;
    uint32_t possible_crtcs;
    drmModeEncoder * encoder;

    for (encoder_index = 0;
         encoder_index < connector->count_encoders;
         ++encoder_index)
    {
        encoder = drmModeGetEncoder(swc.drm->fd,
                                    connector->encoders[encoder_index]);
        possible_crtcs = encoder->possible_crtcs;
        drmModeFreeEncoder(encoder);

        for (crtc_index = 0; crtc_index < resources->count_crtcs; ++crtc_index)
        {
            if ((possible_crtcs & (1 << crtc_index))
                && !(taken_crtcs & (1 << crtc_index)))
            {
                *crtc = crtc_index;
                return true;
            }
        }
    }

    return false;
}
Example #7
0
static gboolean
device_find_crtc (Device *device)
{
  gboolean ret = FALSE;
  drmModeRes *resources;
  drmModeConnector *connector;
  drmModeEncoder *encoder;
  drmModeCrtc *crtc;
  int i;

  resources = drmModeGetResources (device->fd);
  if (resources == NULL)
    {
      g_warning ("Unable to get DRI device resources fd=%d: %m", device->fd);
      goto out;
    }

  /* Find the first active connector to display on. */
  for (i = 0; i < resources->count_connectors; i++)
    {
      connector = drmModeGetConnector (device->fd,
                                       resources->connectors[i]);
      if (connector == NULL)
        continue;

      if (connector->connection == DRM_MODE_CONNECTED &&
          connector->count_modes > 0)
        break;

      drmModeFreeConnector(connector);
    }

  if (i == resources->count_connectors)
    {
      g_warning ("Could not find an active connector");
      goto out;
    }

  /* Find an associated encoder for that connector. */
  encoder = drmModeGetEncoder (device->fd, connector->encoder_id);

  /* Now grab the CRTC for that encoder. */
  crtc = drmModeGetCrtc (device->fd, encoder->crtc_id);

  device->resources = resources;
  device->connector = connector;
  device->crtc = crtc;

  ret = TRUE;

 out:
  return ret;
}
Example #8
0
/**
 * Choose a CRTC that supports all given connectors.
 */
static uint32_t
drm_display_choose_crtc(struct native_display *ndpy,
                        uint32_t *connectors, int num_connectors)
{
   struct drm_display *drmdpy = drm_display(ndpy);
   int idx;

   for (idx = 0; idx < drmdpy->resources->count_crtcs; idx++) {
      boolean found_crtc = TRUE;
      int i, j;

      for (i = 0; i < num_connectors; i++) {
         drmModeConnectorPtr connector;
         int encoder_idx = -1;

         connector = drmModeGetConnector(drmdpy->fd, connectors[i]);
         if (!connector) {
            found_crtc = FALSE;
            break;
         }

         /* find an encoder the CRTC supports */
         for (j = 0; j < connector->count_encoders; j++) {
            drmModeEncoderPtr encoder =
               drmModeGetEncoder(drmdpy->fd, connector->encoders[j]);
            if (encoder->possible_crtcs & (1 << idx)) {
               encoder_idx = j;
               break;
            }
            drmModeFreeEncoder(encoder);
         }

         drmModeFreeConnector(connector);
         if (encoder_idx < 0) {
            found_crtc = FALSE;
            break;
         }
      }

      if (found_crtc)
         break;
   }

   if (idx >= drmdpy->resources->count_crtcs) {
      _eglLog(_EGL_WARNING,
            "failed to find a CRTC that supports the given %d connectors",
            num_connectors);
      return 0;
   }

   return drmdpy->resources->crtcs[idx];
}
drmModeEncoderPtr
IntelHWComposerDrm::getEncoder(int disp)
{
    if (mDrmFd < 0) {
        ALOGE("%s: invalid drm FD\n", __func__);
        return NULL;
    }

    uint32_t req_encoder_type = 0;

    switch (disp) {
        case OUTPUT_MIPI0:
        case OUTPUT_MIPI1:
            req_encoder_type = DRM_MODE_ENCODER_MIPI;
            break;
        case OUTPUT_HDMI:
            req_encoder_type = DRM_MODE_ENCODER_TMDS;
            break;
        default:
            ALOGW("%s: invalid device number: %d\n", __func__, disp);
            return NULL;
    }

    drmModeResPtr resources = drmModeGetResources(mDrmFd);
    if (!resources || !resources->encoders) {
        ALOGE("%s: fail to get drm resources. %s\n", __func__, strerror(errno));
        return NULL;
    }

    drmModeEncoderPtr encoder = NULL;
    for (int i = 0; i < resources->count_encoders; i++) {
        encoder = drmModeGetEncoder(mDrmFd, resources->encoders[i]);

        if (!encoder) {
            ALOGW("%s: Failed to get encoder\n", __func__);
            continue;
        }

        if (encoder->encoder_type == req_encoder_type)
            break;

        drmModeFreeEncoder(encoder);
        encoder = NULL;
    }
    drmModeFreeResources(resources);

    if (encoder == NULL)
        ALOGW("%s: fail to get required encoder\n", __func__);

    return encoder;
}
Example #10
0
void QKmsScreen::initializeScreenMode()
{
    //Determine optimal mode for screen
    drmModeRes *resources = drmModeGetResources(m_device->fd());
    if (!resources)
        qFatal("drmModeGetResources failed");

    drmModeConnector *connector = drmModeGetConnector(m_device->fd(), m_connectorId);
    drmModeModeInfo *mode = 0;
    for (int i = 0; i < connector->count_modes; ++i) {
        if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
            mode = &connector->modes[i];
            break;
        }
    }
    if (!mode)
        mode = &builtin_1024x768;

    drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
    if (encoder == 0)
        qFatal("No encoder for connector.");

    int i;
    for (i = 0; i < resources->count_crtcs; i++) {
        if (encoder->possible_crtcs & (1 << i))
            break;
    }
    if (i == resources->count_crtcs)
        qFatal("No usable crtc for encoder.");

    m_oldCrtc = drmModeGetCrtc(m_device->fd(), encoder->crtc_id);

    m_crtcId = resources->crtcs[i];
    m_mode = *mode;
    m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay);
    qDebug() << "kms initialized with geometry" << m_geometry;
    m_depth = 32;
    m_format = QImage::Format_RGB32;
    m_physicalSize = QSizeF(connector->mmWidth, connector->mmHeight);

    m_gbmSurface = gbm_surface_create(m_device->gbmDevice(),
                                      m_mode.hdisplay, m_mode.vdisplay,
                                      GBM_BO_FORMAT_XRGB8888,
                                      GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

    qDebug() << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay;
    //Cleanup
    drmModeFreeEncoder(encoder);
    drmModeFreeConnector(connector);
    drmModeFreeResources(resources);
}
Example #11
0
static EGLBoolean
setup_kms(int fd, struct kms *kms)
{
   drmModeRes *resources;
   drmModeConnector *connector;
   drmModeEncoder *encoder;
   int i;

   resources = drmModeGetResources(fd);
   if (!resources) {
      fprintf(stderr, "drmModeGetResources failed\n");
      return EGL_FALSE;
   }

   for (i = 0; i < resources->count_connectors; i++) {
      connector = drmModeGetConnector(fd, resources->connectors[i]);
      if (connector == NULL)
	 continue;

      if (connector->connection == DRM_MODE_CONNECTED &&
	  connector->count_modes > 0)
	 break;

      drmModeFreeConnector(connector);
   }

   if (i == resources->count_connectors) {
      fprintf(stderr, "No currently active connector found.\n");
      return EGL_FALSE;
   }

   for (i = 0; i < resources->count_encoders; i++) {
      encoder = drmModeGetEncoder(fd, resources->encoders[i]);

      if (encoder == NULL)
	 continue;

      if (encoder->encoder_id == connector->encoder_id)
	 break;

      drmModeFreeEncoder(encoder);
   }

   kms->connector = connector;
   kms->encoder = encoder;
   kms->mode = connector->modes[0];

   return EGL_TRUE;
}
Example #12
0
static void printEncoders(int fd, uint32_t* ids, uint32_t count) {
	int i;

	for (i = 0; i < count; i++) {
		drmModeEncoder *enc;
		enc = drmModeGetEncoder(fd, ids[i]);
		fprintf(stdout, "      Encoder %u:\n", enc->encoder_id);
		fprintf(stdout, "        Type: %s\n", getEncoderType(enc->encoder_type));
		fprintf(stdout, "        CRTC: %u\n", enc->crtc_id);
		fprintf(stdout, "        Possible CRTCs: %1$u, %1$#08x, %1$#016o, %2$s\n", enc->possible_crtcs, bitList(enc->possible_crtcs));
		fprintf(stdout, "        Possible Clones: %1$u, %1$#08x, %1$#016o, %2$s\n", enc->possible_clones, bitList(enc->possible_clones));
		fprintf(stdout, "\n");
		drmModeFreeEncoder(enc);
	}
}
Example #13
0
void QKmsScreen::initializeScreenMode()
{
    //Determine optimal mode for screen
    drmModeRes *resources = drmModeGetResources(m_device->fd());
    if (!resources)
        qFatal("drmModeGetResources failed");

    drmModeConnector *connector = drmModeGetConnector(m_device->fd(), m_connectorId);
    drmModeModeInfo *mode = 0;
    if (connector->count_modes > 0)
        mode = &connector->modes[0];
    else
        mode = &builtin_1024x768;

    drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
    if (encoder == 0)
        qFatal("No encoder for connector.");

    int i;
    for (i = 0; i < resources->count_crtcs; i++) {
        if (encoder->possible_crtcs & (1 << i))
            break;
    }
    if (i == resources->count_crtcs)
        qFatal("No usable crtc for encoder.");

    m_crtcId = resources->crtcs[i];
    m_mode = *mode;
    m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay);
    m_depth = 32;
    m_format = QImage::Format_RGB32;
    m_physicalSize = QSizeF(connector->mmWidth, connector->mmHeight);

    //Setup three buffers for current mode
    m_bufferManager.setupBuffersForMode(m_mode, 3);

    //Set the Mode of the screen.
    int ret = drmModeSetCrtc(m_device->fd(), m_crtcId, m_bufferManager.displayFramebufferId(),
                             0, 0, &m_connectorId, 1, &m_mode);
    if (ret)
        qFatal("failed to set mode");

    //Cleanup
    drmModeFreeEncoder(encoder);
    drmModeFreeConnector(connector);
    drmModeFreeResources(resources);
}
Example #14
0
/**
 * Get the index of the CRTC of the monitor connected to a connector
 * 
 * @param   connection       The identifier for the connection to the card
 * @param   connector_index  The index of the connector
 * @return                   The index of the CRTC
 */
int blueshift_drm_get_crtc(int connection, int connector_index)
{
  card_connection* card = card_connections + connection;
  drmModeEncoder* encoder = drmModeGetEncoder(card->fd, card->connectors[connector_index]->encoder_id);
  uint32_t crtc_id = encoder->crtc_id;
  drmModeRes* res = card->res;
  int crtc;
  int n;
  
  drmModeFreeEncoder(encoder);
  
  n = res->count_crtcs;
  for (crtc = 0; crtc < n; crtc++)
    if (*(res->crtcs + crtc) == crtc_id)
      return crtc;
  
  return -1;
}
Example #15
0
static drmModeCrtc *
find_crtc_for_connector (int fd, drmModeRes * res, drmModeConnector * conn,
    guint * pipe)
{
  int i;
  int crtc_id;
  drmModeEncoder *enc;
  drmModeCrtc *crtc;

  crtc_id = -1;
  for (i = 0; i < res->count_encoders; i++) {
    enc = drmModeGetEncoder (fd, res->encoders[i]);
    if (enc) {
      if (enc->encoder_id == conn->encoder_id) {
        crtc_id = enc->crtc_id;
        drmModeFreeEncoder (enc);
        break;
      }
      drmModeFreeEncoder (enc);
    }
  }

  if (crtc_id == -1)
    return NULL;

  for (i = 0; i < res->count_crtcs; i++) {
    crtc = drmModeGetCrtc (fd, res->crtcs[i]);
    if (crtc) {
      if (crtc_id == crtc->crtc_id) {
        if (pipe)
          *pipe = i;
        return crtc;
      }
      drmModeFreeCrtc (crtc);
    }
  }

  return NULL;
}
Example #16
0
bool CDRMUtils::GetEncoder()
{
  for(auto i = 0; i < m_drm_resources->count_encoders; i++)
  {
    m_encoder->encoder = drmModeGetEncoder(m_fd, m_drm_resources->encoders[i]);
    if(m_encoder->encoder->encoder_id == m_connector->connector->encoder_id)
    {
      CLog::Log(LOGDEBUG, "CDRMUtils::%s - found encoder: %d", __FUNCTION__,
                                                               m_encoder->encoder->encoder_id);
      break;
    }
    drmModeFreeEncoder(m_encoder->encoder);
    m_encoder->encoder = nullptr;
  }

  if(!m_encoder->encoder)
  {
    CLog::Log(LOGERROR, "CDRMUtils::%s - could not get encoder: %s", __FUNCTION__, strerror(errno));
    return false;
  }

  return true;
}
Example #17
0
bool drm_get_encoder(int fd)
{
   unsigned i;

   for (i = 0; (int)i < g_drm_resources->count_encoders; i++)
   {
      g_drm_encoder = drmModeGetEncoder(fd, g_drm_resources->encoders[i]);

      if (!g_drm_encoder)
         continue;

      if (g_drm_encoder->encoder_id == g_drm_connector->encoder_id)
         break;

      drmModeFreeEncoder(g_drm_encoder);
      g_drm_encoder = NULL;
   }

   if (!g_drm_encoder)
   {
      RARCH_WARN("[DRM]: Couldn't find DRM encoder.\n");
      return false;
   }

   for (i = 0; (int)i < g_drm_connector->count_modes; i++)
   {
      RARCH_LOG("[DRM]: Mode %d: (%s) %d x %d, %u Hz\n",
            i,
            g_drm_connector->modes[i].name,
            g_drm_connector->modes[i].hdisplay,
            g_drm_connector->modes[i].vdisplay,
            g_drm_connector->modes[i].vrefresh);
   }

   return true;
}
Example #18
0
int main(int argc, char **argv)
{
	int drmfd;
	int vtfd;
	unsigned int i, j;
	drmModeRes *res = NULL;
	drmModeEncoder *enc = NULL;
	drmModeConnector *conn = NULL;
	uint32_t fb_id, conn_id, crtc_id;
	long int vt_args;
	struct drm_mode_create_dumb fbo_create_args = {0};
	struct drm_mode_map_dumb fbo_map_args = {0};
	struct drm_mode_destroy_dumb fbo_close_args = {0};
	uint32_t gem_handle;
	uint8_t *fb_virt = NULL; /* start address of dumb fb */
	uint32_t fb_pitch;
	uint32_t fb_size;
	drmModeModeInfo curr_mode; /* store current mode infomation */

	vtfd = open("/dev/tty1", O_RDWR | O_CLOEXEC);

	/* trigger a vt switch to /dev/tty1 and wait for available */
	ioctl(vtfd, VT_ACTIVATE, 1);
	ioctl(vtfd, VT_WAITACTIVE, 1);

	ioctl(vtfd, KDGETMODE, &vt_args);
	printf("switch to %s mode on tty1\n", vt_args == KD_TEXT ? "TEXT" : "GFX");

	/* from now on, we can do pixel dance on dumb fb */
	drmfd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);

	res = drmModeGetResources(drmfd);

	for (i = 0; i < res->count_connectors; i++) {

		conn = drmModeGetConnector(drmfd, res->connectors[i]);
		conn_id = conn->connector_id;

		if (conn->connection != DRM_MODE_CONNECTED) {
			printf("conn:[%d] is offline\n", conn->connector_id);
			drmModeFreeConnector(conn);
			continue;
		}

		/* we choose max valid mode */
		memcpy(&curr_mode, &conn->modes[0], sizeof(curr_mode));
		printf("conn:[%d] is online %dx%d@%dHZ\n", conn->connector_id, curr_mode.hdisplay, curr_mode.vdisplay, curr_mode.vrefresh);

		enc = drmModeGetEncoder(drmfd, conn->encoder_id);

		crtc_id = enc->crtc_id;
		drmModeFreeEncoder(enc);

		/* create dumb fb and retrieve aperture */
		fbo_create_args.width = curr_mode.hdisplay;
		fbo_create_args.height = curr_mode.vdisplay;
		fbo_create_args.bpp = 32;

		drmIoctl(drmfd, DRM_IOCTL_MODE_CREATE_DUMB, &fbo_create_args);

		gem_handle = fbo_create_args.handle;
		fb_size = fbo_create_args.size;
		fb_pitch = fbo_create_args.pitch;

		drmModeAddFB(drmfd, curr_mode.hdisplay, curr_mode.vdisplay, 24, 32, fb_pitch, gem_handle, &fb_id);

		fbo_map_args.handle = gem_handle;
		drmIoctl(drmfd, DRM_IOCTL_MODE_MAP_DUMB, &fbo_map_args);

		fb_virt = mmap(0, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, drmfd, fbo_map_args.offset);

		drmModeFreeConnector(conn);
	}

	drmModeFreeResources(res);

	drmModeSetCrtc(drmfd, crtc_id, fb_id, 0, 0, &conn_id, 1, &curr_mode);

	for (i = 0; i < curr_mode.vdisplay; i++) {
		for (j = 0; j < curr_mode.hdisplay; j++) {
			//*((uint32_t *)(fb_virt + fb_pitch * i + j * 4)) = i * j;
			*((uint32_t *)(fb_virt + fb_pitch * i + j * 4)) = 0xFFFFFF;
		}
	}

	/* say hello */
	draw_8x8_char(10, 10, fb_virt, fb_pitch, 'h');
	draw_8x8_char(18, 10, fb_virt, fb_pitch, 'e');
	draw_8x8_char(26, 10, fb_virt, fb_pitch, 'l');
	draw_8x8_char(34, 10, fb_virt, fb_pitch, 'l');
	draw_8x8_char(42, 10, fb_virt, fb_pitch, 'o');

	draw_8x8_char(50, 10, fb_virt, fb_pitch, ' ');
	draw_8x8_char(58, 10, fb_virt, fb_pitch, 'r');
	draw_8x8_char(66, 10, fb_virt, fb_pitch, 'e');
	draw_8x8_char(74, 10, fb_virt, fb_pitch, 'd');
	draw_8x8_char(82, 10, fb_virt, fb_pitch, 'h');
	draw_8x8_char(90, 10, fb_virt, fb_pitch, 'a');
	draw_8x8_char(98, 10, fb_virt, fb_pitch, 't');
	draw_8x8_char(106, 10, fb_virt, fb_pitch, '!');

	draw_8x16_char(110, 100, fb_virt, fb_pitch, 'h');
	draw_8x16_char(118, 100, fb_virt, fb_pitch, 'e');
	draw_8x16_char(126, 100, fb_virt, fb_pitch, 'l');
	draw_8x16_char(134, 100, fb_virt, fb_pitch, 'l');
	draw_8x16_char(142, 100, fb_virt, fb_pitch, 'o');

	draw_8x16_char(150, 100, fb_virt, fb_pitch, ' ');
	draw_8x16_char(158, 100, fb_virt, fb_pitch, 'r');
	draw_8x16_char(166, 100, fb_virt, fb_pitch, 'e');
	draw_8x16_char(174, 100, fb_virt, fb_pitch, 'd');
	draw_8x16_char(182, 100, fb_virt, fb_pitch, 'h');
	draw_8x16_char(190, 100, fb_virt, fb_pitch, 'a');
	draw_8x16_char(198, 100, fb_virt, fb_pitch, 't');
	draw_8x16_char(206, 100, fb_virt, fb_pitch, '!');

	usleep(5000000);

	/* unwind anything we done */
	munmap(fb_virt, fb_size);

	drmModeRmFB(drmfd, fb_id);

	fbo_close_args.handle = gem_handle;
	drmIoctl(drmfd, DRM_IOCTL_MODE_DESTROY_DUMB, &fbo_close_args);

	close(drmfd);

	/* switch back to /dev/tty7 for convinience */
	ioctl(vtfd, VT_ACTIVATE, 7);
	ioctl(vtfd, VT_WAITACTIVE, 7);

	close(vtfd);
	return 0;
}
static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
			     struct modeset_dev *dev)
{
	drmModeEncoder *enc;
	unsigned int i, j;
	int32_t crtc;
	struct modeset_dev *iter;

	/* first try the currently conected encoder+crtc */
	if (conn->encoder_id)
		enc = drmModeGetEncoder(fd, conn->encoder_id);
	else
		enc = NULL;

	if (enc) {
		if (enc->crtc_id) {
			crtc = enc->crtc_id;
			for (iter = modeset_list; iter; iter = iter->next) {
				if (iter->crtc == crtc) {
					crtc = -1;
					break;
				}
			}

			if (crtc >= 0) {
				drmModeFreeEncoder(enc);
				dev->crtc = crtc;
				return 0;
			}
		}

		drmModeFreeEncoder(enc);
	}

	/* If the connector is not currently bound to an encoder or if the
	 * encoder+crtc is already used by another connector (actually unlikely
	 * but lets be safe), iterate all other available encoders to find a
	 * matching CRTC. */
	for (i = 0; i < conn->count_encoders; ++i) {
		enc = drmModeGetEncoder(fd, conn->encoders[i]);
		if (!enc) {
			fprintf(stderr, "cannot retrieve encoder %u:%u (%d): %m\n",
				i, conn->encoders[i], errno);
			continue;
		}

		/* iterate all global CRTCs */
		for (j = 0; j < res->count_crtcs; ++j) {
			/* check whether this CRTC works with the encoder */
			if (!(enc->possible_crtcs & (1 << j)))
				continue;

			/* check that no other device already uses this CRTC */
			crtc = res->crtcs[j];
			for (iter = modeset_list; iter; iter = iter->next) {
				if (iter->crtc == crtc) {
					crtc = -1;
					break;
				}
			}

			/* we have found a CRTC, so save it and return */
			if (crtc >= 0) {
				drmModeFreeEncoder(enc);
				dev->crtc = crtc;
				return 0;
			}
		}

		drmModeFreeEncoder(enc);
	}

	fprintf(stderr, "cannot find suitable CRTC for connector %u\n",
		conn->connector_id);
	return -ENOENT;
}
Example #20
0
static gboolean
_cogl_winsys_egl_display_setup (CoglDisplay *display,
                                GError **error)
{
  CoglDisplayEGL *egl_display = display->winsys;
  CoglDisplayKMS *kms_display;
  CoglRendererEGL *egl_renderer = display->renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;
  CoglEGLWinsysFeature surfaceless_feature = 0;
  const char *surfaceless_feature_name = "";
  drmModeRes *resources;
  drmModeConnector *connector;
  drmModeEncoder *encoder;
  int i;

  kms_display = g_slice_new0 (CoglDisplayKMS);
  egl_display->platform = kms_display;

  switch (display->renderer->driver)
    {
    case COGL_DRIVER_GL:
      surfaceless_feature = COGL_EGL_WINSYS_FEATURE_SURFACELESS_OPENGL;
      surfaceless_feature_name = "opengl";
      break;
    case COGL_DRIVER_GLES1:
      surfaceless_feature = COGL_EGL_WINSYS_FEATURE_SURFACELESS_GLES1;
      surfaceless_feature_name = "gles1";
      break;
    case COGL_DRIVER_GLES2:
      surfaceless_feature = COGL_EGL_WINSYS_FEATURE_SURFACELESS_GLES2;
      surfaceless_feature_name = "gles2";
      break;
    }

  if (!(egl_renderer->private_features & surfaceless_feature))
    {
      g_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_INIT,
                   "EGL_KHR_surfaceless_%s extension not available",
                   surfaceless_feature_name);
      return FALSE;
    }

  resources = drmModeGetResources (kms_renderer->fd);
  if (!resources)
    {
      g_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_INIT,
                   "drmModeGetResources failed");
      return FALSE;
    }

  for (i = 0; i < resources->count_connectors; i++)
    {
      connector = drmModeGetConnector (kms_renderer->fd,
                                       resources->connectors[i]);
      if (connector == NULL)
        continue;

      if (connector->connection == DRM_MODE_CONNECTED &&
          connector->count_modes > 0)
        break;

      drmModeFreeConnector(connector);
    }

  if (i == resources->count_connectors)
    {
      g_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_INIT,
                   "No currently active connector found");
      return FALSE;
    }

  for (i = 0; i < resources->count_encoders; i++)
    {
      encoder = drmModeGetEncoder (kms_renderer->fd, resources->encoders[i]);

      if (encoder == NULL)
        continue;

      if (encoder->encoder_id == connector->encoder_id)
        break;

      drmModeFreeEncoder (encoder);
    }

  kms_display->saved_crtc = drmModeGetCrtc (kms_renderer->fd,
                                            encoder->crtc_id);

  kms_display->connector = connector;
  kms_display->encoder = encoder;
  kms_display->mode = connector->modes[0];
  kms_display->width = kms_display->mode.hdisplay;
  kms_display->height = kms_display->mode.vdisplay;

  return TRUE;
}
static void
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
{
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
  drmModeRes *resources;
  GHashTable *modes;
  GHashTableIter iter;
  drmModeModeInfo *mode;
  unsigned int i, j, k;
  unsigned int n_actual_outputs;
  int width, height;
  MetaOutput *old_outputs;
  unsigned int n_old_outputs;

  resources = drmModeGetResources(manager_kms->fd);
  modes = g_hash_table_new (drm_mode_hash, drm_mode_equal);

  manager->max_screen_width = resources->max_width;
  manager->max_screen_height = resources->max_height;

  manager->power_save_mode = META_POWER_SAVE_ON;

  old_outputs = manager->outputs;
  n_old_outputs = manager->n_outputs;

  /* Note: we must not free the public structures (output, crtc, monitor
     mode and monitor info) here, they must be kept alive until the API
     users are done with them after we emit monitors-changed, and thus
     are freed by the platform-independent layer. */
  free_resources (manager_kms);

  manager_kms->n_connectors = resources->count_connectors;
  manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors);
  for (i = 0; i < manager_kms->n_connectors; i++)
    {
      drmModeConnector *connector;

      connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]);
      manager_kms->connectors[i] = connector;

      if (connector->connection == DRM_MODE_CONNECTED)
        {
          /* Collect all modes for this connector */
          for (j = 0; j < (unsigned)connector->count_modes; j++)
            g_hash_table_add (modes, &connector->modes[j]);
        }
    }

  manager_kms->n_encoders = resources->count_encoders;
  manager_kms->encoders = g_new (drmModeEncoder *, manager_kms->n_encoders);
  for (i = 0; i < manager_kms->n_encoders; i++)
    {
      manager_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd,
                                                    resources->encoders[i]);
    }

  manager->n_modes = g_hash_table_size (modes);
  manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
  g_hash_table_iter_init (&iter, modes);
  i = 0;
  while (g_hash_table_iter_next (&iter, NULL, (gpointer)&mode))
    {
      MetaMonitorMode *meta_mode;

      meta_mode = &manager->modes[i];

      meta_mode->mode_id = i;
      meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN);
      meta_mode->width = mode->hdisplay;
      meta_mode->height = mode->vdisplay;
      meta_mode->refresh_rate = (1000 * mode->clock /
                                 ((float)mode->htotal * mode->vtotal));

      meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode);
      meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;

      i++;
    }
  g_hash_table_destroy (modes);

  manager->n_crtcs = resources->count_crtcs;
  manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
  width = 0; height = 0;
  for (i = 0; i < (unsigned)resources->count_crtcs; i++)
    {
      drmModeCrtc *crtc;
      MetaCRTC *meta_crtc;

      crtc = drmModeGetCrtc (manager_kms->fd, resources->crtcs[i]);

      meta_crtc = &manager->crtcs[i];

      meta_crtc->crtc_id = crtc->crtc_id;
      meta_crtc->rect.x = crtc->x;
      meta_crtc->rect.y = crtc->y;
      meta_crtc->rect.width = crtc->width;
      meta_crtc->rect.height = crtc->height;
      meta_crtc->is_dirty = FALSE;
      meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
      /* FIXME: implement! */
      meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;

      if (crtc->mode_valid)
        {
          for (j = 0; j < manager->n_modes; j++)
            {
              if (drm_mode_equal (&crtc->mode, manager->modes[j].driver_private))
                {
                  meta_crtc->current_mode = &manager->modes[j];
                  break;
                }
            }

          width = MAX (width, meta_crtc->rect.x + meta_crtc->rect.width);
          height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
        }

      drmModeFreeCrtc (crtc);
    }

  manager->screen_width = width;
  manager->screen_height = height;

  manager->outputs = g_new0 (MetaOutput, manager_kms->n_connectors);
  n_actual_outputs = 0;

  for (i = 0; i < manager_kms->n_connectors; i++)
    {
      MetaOutput *meta_output, *old_output;
      MetaOutputKms *output_kms;
      drmModeConnector *connector;
      GArray *crtcs;
      unsigned int crtc_mask;
      GBytes *edid;

      connector = manager_kms->connectors[i];
      meta_output = &manager->outputs[n_actual_outputs];

      if (connector->connection == DRM_MODE_CONNECTED)
	{
          meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
          meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;

	  meta_output->winsys_id = connector->connector_id;
	  meta_output->name = make_output_name (connector);
	  meta_output->width_mm = connector->mmWidth;
	  meta_output->height_mm = connector->mmHeight;

          switch (connector->subpixel)
            {
            case DRM_MODE_SUBPIXEL_NONE:
              meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
              break;
            case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
              meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
              break;
            case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
              meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR;
              break;
            case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
              meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB;
              break;
            case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
              meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR;
              break;
            case DRM_MODE_SUBPIXEL_UNKNOWN:
            default:
              meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
              break;
            }

	  meta_output->n_modes = connector->count_modes;
	  meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
	  for (j = 0; j < meta_output->n_modes; j++)
            meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]);
	  meta_output->preferred_mode = meta_output->modes[0];

          output_kms->connector = connector;
          output_kms->n_encoders = connector->count_encoders;
          output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders);

          crtc_mask = ~(unsigned int)0;
	  for (j = 0; j < output_kms->n_encoders; j++)
	    {
              output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]);

              /* We only list CRTCs as supported if they are supported by all encoders
                 for this connectors.

                 This is what xf86-video-modesetting does (see drmmode_output_init())
              */
              crtc_mask &= output_kms->encoders[j]->possible_crtcs;

              if (output_kms->encoders[j]->encoder_id == connector->encoder_id)
                output_kms->current_encoder = output_kms->encoders[j];
            }

          crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCRTC*));

          for (j = 0; j < manager->n_crtcs; j++)
            {
              if (crtc_mask & (1 << j))
                {
                  MetaCRTC *crtc = &manager->crtcs[j];
                  g_array_append_val (crtcs, crtc);
		}
	    }

	  meta_output->n_possible_crtcs = crtcs->len;
	  meta_output->possible_crtcs = (void*)g_array_free (crtcs, FALSE);

          if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0)
            {
              for (j = 0; j < manager->n_crtcs; j++)
                {
                  if (manager->crtcs[j].crtc_id == output_kms->current_encoder->crtc_id)
                    {
                      meta_output->crtc = &manager->crtcs[j];
                      break;
                    }
                }
            }
          else
            meta_output->crtc = NULL;

          old_output = find_output_by_id (old_outputs, n_old_outputs,
                                          meta_output->winsys_id);
          if (old_output)
            {
              meta_output->is_primary = old_output->is_primary;
              meta_output->is_presentation = old_output->is_presentation;
            }
          else
            {
              meta_output->is_primary = FALSE;
              meta_output->is_presentation = FALSE;
            }

          find_properties (manager_kms, output_kms);

          edid = read_output_edid (manager_kms, meta_output);
          if (edid)
            {
              MonitorInfo *parsed_edid;
              gsize len;

              parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
              if (parsed_edid)
                {
                  meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
                  meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
                  meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);

                  g_free (parsed_edid);
                }

              g_bytes_unref (edid);
            }
          if (!meta_output->vendor)
            {
              meta_output->vendor = g_strdup ("unknown");
              meta_output->product = g_strdup ("unknown");
              meta_output->serial = g_strdup ("unknown");
            }

          /* FIXME: backlight is a very driver specific thing unfortunately,
             every DDX does its own thing, and the dumb KMS API does not include it.

             For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
             (one for each major HW maker, and then some).
             We can't do the same because we're not root.
             It might be best to leave backlight out of the story and rely on the setuid
             helper in gnome-settings-daemon.
          */
	  meta_output->backlight_min = 0;
          meta_output->backlight_max = 0;
          meta_output->backlight = -1;

	  n_actual_outputs++;
	}
    }
static void connector_find_preferred_mode(int gfx_fd,
					  drmModeRes *gfx_resources,
					  struct connector *c)
{
	drmModeConnector *connector;
	drmModeEncoder *encoder = NULL;
	int i, j;

	/* First, find the connector & mode */
	c->mode_valid = 0;
	connector = drmModeGetConnector(gfx_fd, c->id);
	if (!connector) {
		printf("could not get connector %d: %s\n",
			c->id,
			strerror(errno));
		drmModeFreeConnector(connector);
		return;
	}

	if (connector->connection != DRM_MODE_CONNECTED) {
		drmModeFreeConnector(connector);
		return;
	}

	if (!connector->count_modes) {
		printf("connector %d has no modes\n",
			c->id);
		drmModeFreeConnector(connector);
		return;
	}

	if (connector->connector_id != c->id) {
		printf("connector id doesn't match (%d != %d)\n",
			connector->connector_id,
			c->id);
		drmModeFreeConnector(connector);
		return;
	}

	for (j = 0; j < connector->count_modes; j++) {
		c->mode = connector->modes[j];
		if (c->mode.type & DRM_MODE_TYPE_PREFERRED) {
			c->mode_valid = 1;
			break;
		}
	}

	if (!c->mode_valid) {
		if (connector->count_modes > 0) {
			/* use the first mode as test mode */
			c->mode = connector->modes[0];
			c->mode_valid = 1;
		} else {
			printf("failed to find any modes on connector %d\n",
				c->id);
			return;
		}
	}

	/* Now get the encoder */
	for (i = 0; i < connector->count_encoders; i++) {
		encoder = drmModeGetEncoder(gfx_fd, connector->encoders[i]);

		if (!encoder) {
			printf("could not get encoder %i: %s\n",
				gfx_resources->encoders[i],
				strerror(errno));
			drmModeFreeEncoder(encoder);
			continue;
		}

		break;
	}

	c->encoder = encoder;

	if (i == gfx_resources->count_encoders) {
		printf("failed to find encoder\n");
		c->mode_valid = 0;
		return;
	}

	/* Find first CRTC not in use */
	for (i = 0; i < gfx_resources->count_crtcs; i++) {
		if (gfx_resources->crtcs[i] && (c->encoder->possible_crtcs & (1<<i)))
			break;
	}
	c->crtc = gfx_resources->crtcs[i];
	c->pipe = i;

	gfx_resources->crtcs[i] = 0;

	c->connector = connector;
}
static CoglOutputKMS *
find_output (int _index,
             int fd,
             drmModeRes *resources,
             int *excluded_connectors,
             int n_excluded_connectors,
             CoglError **error)
{
  char *connector_env_name = g_strdup_printf ("COGL_KMS_CONNECTOR%d", _index);
  char *mode_env_name;
  drmModeConnector *connector;
  drmModeEncoder *encoder;
  CoglOutputKMS *output;
  drmModeModeInfo *modes;
  int n_modes;

  if (getenv (connector_env_name))
    {
      unsigned long id = strtoul (getenv (connector_env_name), NULL, 10);
      connector = drmModeGetConnector (fd, id);
    }
  else
    connector = NULL;
  g_free (connector_env_name);

  if (connector == NULL)
    connector = find_connector (fd, resources,
                                excluded_connectors, n_excluded_connectors);
  if (connector == NULL)
    {
      _cogl_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_INIT,
                   "No currently active connector found");
      return NULL;
    }

  /* XXX: At this point it seems connector->encoder_id may be an invalid id of 0
   * even though the connector is marked as connected. Referencing ->encoders[0]
   * seems more reliable. */
  encoder = drmModeGetEncoder (fd, connector->encoders[0]);

  output = g_slice_new0 (CoglOutputKMS);
  output->connector = connector;
  output->encoder = encoder;
  output->saved_crtc = drmModeGetCrtc (fd, encoder->crtc_id);

  if (is_panel (connector->connector_type))
    {
      n_modes = connector->count_modes + 1;
      modes = g_new (drmModeModeInfo, n_modes);
      memcpy (modes, connector->modes,
              sizeof (drmModeModeInfo) * connector->count_modes);
      /* TODO: parse EDID */
      modes[n_modes - 1] = builtin_1024x768;
    }
  else
    {
      n_modes = connector->count_modes;
      modes = g_new (drmModeModeInfo, n_modes);
      memcpy (modes, connector->modes,
              sizeof (drmModeModeInfo) * n_modes);
    }

  mode_env_name = g_strdup_printf ("COGL_KMS_CONNECTOR%d_MODE", _index);
  if (getenv (mode_env_name))
    {
      const char *name = getenv (mode_env_name);
      int i;
      CoglBool found = FALSE;
      drmModeModeInfo mode;

      for (i = 0; i < n_modes; i++)
        {
          if (strcmp (modes[i].name, name) == 0)
            {
              found = TRUE;
              break;
            }
        }
      if (!found)
        {
          g_free (mode_env_name);
          _cogl_set_error (error, COGL_WINSYS_ERROR,
                       COGL_WINSYS_ERROR_INIT,
                       "COGL_KMS_CONNECTOR%d_MODE of %s could not be found",
                       _index, name);
          return NULL;
        }
      n_modes = 1;
      mode = modes[i];
      g_free (modes);
      modes = g_new (drmModeModeInfo, 1);
      modes[0] = mode;
    }
  g_free (mode_env_name);

  output->modes = modes;
  output->n_modes = n_modes;

  return output;
}
Example #24
0
static bool init_drm(void)
{
   int ret;
   drmModeConnector *connector;
   uint i;

   drm.fd = open("/dev/dri/card0", O_RDWR);

   if (drm.fd < 0)
   {
      RARCH_LOG ("DRM: could not open drm device\n");
      return false;
   }

   /* Programmer!! Save your sanity!!
    * VERY important or we won't get all the available planes on drmGetPlaneResources()!
    * We also need to enable the ATOMIC cap to see the atomic properties in objects!! */
   ret = drmSetClientCap(drm.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
   if (ret) 
      RARCH_ERR ("DRM: can't set UNIVERSAL PLANES cap.\n");
   else
      RARCH_LOG ("DRM: UNIVERSAL PLANES cap set\n");


   ret = drmSetClientCap(drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
   if (ret)
   { 
      /*If this happens, check kernel support and kernel parameters 
       * (add i915.nuclear_pageflip=y to the kernel boot line for example) */
      RARCH_ERR ("DRM: can't set ATOMIC caps: %s\n", strerror(errno));
   }
   else
      RARCH_LOG ("DRM: ATOMIC caps set\n");

   drm.resources = drmModeGetResources(drm.fd);
   if (!drm.resources)
   {
      RARCH_ERR ("DRM: drmModeGetResources failed\n");
      return false;
   }

   /* Find a connected connector. */
   for (i = 0; i < (uint)drm.resources->count_connectors; i++)
   {
      connector = drmModeGetConnector(drm.fd, drm.resources->connectors[i]);
      /* It's connected, let's use it. */
      if (connector->connection == DRM_MODE_CONNECTED)
         break;
      drmModeFreeConnector(connector);
      connector = NULL;
   }

   if (!connector)
   {
      RARCH_ERR ("DRM: no connected connector found\n");
      return false;
   }

   /* Find encoder */
   for (i = 0; i < (uint)drm.resources->count_encoders; i++)
   {
      drm.encoder = drmModeGetEncoder(drm.fd, drm.resources->encoders[i]);
      if (drm.encoder->encoder_id == connector->encoder_id)
         break;
      drmModeFreeEncoder(drm.encoder);
      drm.encoder = NULL;
   }

   if (!drm.encoder)
   {
      RARCH_ERR ("DRM: no encoder found.\n");
      return false;
   }

   drm.crtc_id = drm.encoder->crtc_id;
   drm.connector_id = connector->connector_id;

   /* Backup original crtc and it's mode, so we can restore the original video mode 
    * on exit in case we change it. */
   drm.orig_crtc = drmModeGetCrtc(drm.fd, drm.encoder->crtc_id);
   drm.current_mode = &(drm.orig_crtc->mode);

   /* Set mode physical video mode. Not really needed, but clears TTY console. */
   struct modeset_buf buf;
   buf.width = drm.current_mode->hdisplay;
   buf.height = drm.current_mode->vdisplay;
   ret = modeset_create_dumbfb(drm.fd, &buf, 4, DRM_FORMAT_XRGB8888);	
   if (ret)
   {
      RARCH_ERR ("DRM: can't create dumb fb\n");
   }

   if (drmModeSetCrtc(drm.fd, drm.crtc_id, buf.fb_id, 0, 0,
            &drm.connector_id, 1, drm.current_mode))
   {
      RARCH_ERR ("DRM: failed to set mode\n");	
      return false;
   }

   return true;
}
bool IntelHWComposerDrm::detectDrmModeInfo()
{
    ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: detecting drm mode info...\n", __func__);

    if (mDrmFd < 0) {
        ALOGE("%s: invalid drm FD\n", __func__);
        return false;
    }

    /*try to get drm resources*/
    drmModeResPtr resources = drmModeGetResources(mDrmFd);
    if (!resources || !resources->connectors) {
        ALOGE("%s: fail to get drm resources. %s\n", __func__, strerror(errno));
        return false;
    }

    /*get mipi0 info*/
    drmModeConnectorPtr connector = NULL;
    drmModeEncoderPtr encoder = NULL;
    drmModeCrtcPtr crtc = NULL;
    drmModeConnectorPtr connectors[OUTPUT_MAX];
    drmModeModeInfoPtr mode = NULL;
    drmModeFBPtr fbInfo = NULL;

    for (int i = 0; i < resources->count_connectors; i++) {
        connector = drmModeGetConnector(mDrmFd, resources->connectors[i]);
        if (!connector) {
            ALOGW("%s: fail to get drm connector\n", __func__);
            continue;
        }

        int outputIndex = -1;
        if (connector->connector_type == DRM_MODE_CONNECTOR_MIPI ||
            connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
            ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: got MIPI/LVDS connector\n", __func__);
            if (connector->connector_type_id == 1)
                outputIndex = OUTPUT_MIPI0;
            else if (connector->connector_type_id == 2)
                outputIndex = OUTPUT_MIPI1;
            else {
                ALOGW("%s: unknown connector type\n", __func__);
                outputIndex = OUTPUT_MIPI0;
            }
        } else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID) {
            ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: got HDMI connector\n", __func__);
            outputIndex = OUTPUT_HDMI;
        }

        /*update connection status*/
        setOutputConnection(outputIndex, connector->connection);

        /*get related encoder*/
        encoder = drmModeGetEncoder(mDrmFd, connector->encoder_id);
        if (!encoder) {
            ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: fail to get drm encoder\n", __func__);
            drmModeFreeConnector(connector);
            setOutputConnection(outputIndex, DRM_MODE_DISCONNECTED);
            continue;
        }

        /*get related crtc*/
        crtc = drmModeGetCrtc(mDrmFd, encoder->crtc_id);
        if (!crtc) {
            ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: fail to get drm crtc\n", __func__);
            drmModeFreeEncoder(encoder);
            drmModeFreeConnector(connector);
            setOutputConnection(outputIndex, DRM_MODE_DISCONNECTED);
            continue;
        }
        /*set crtc mode*/
        setOutputMode(outputIndex, &crtc->mode, crtc->mode_valid);

        // get fb info
        fbInfo = drmModeGetFB(mDrmFd, crtc->buffer_id);
        if (!fbInfo) {
            ALOGD("%s: fail to get fb info\n", __func__);
            drmModeFreeCrtc(crtc);
            drmModeFreeEncoder(encoder);
            drmModeFreeConnector(connector);
            setOutputConnection(outputIndex, DRM_MODE_DISCONNECTED);
            continue;
        }

        setOutputFBInfo(outputIndex, fbInfo);

        /*free all crtc/connector/encoder*/
        drmModeFreeFB(fbInfo);
        drmModeFreeCrtc(crtc);
        drmModeFreeEncoder(encoder);
        drmModeFreeConnector(connector);
    }

    drmModeFreeResources(resources);

    drmModeConnection mipi0 = getOutputConnection(OUTPUT_MIPI0);
    drmModeConnection mipi1 = getOutputConnection(OUTPUT_MIPI1);
    drmModeConnection hdmi = getOutputConnection(OUTPUT_HDMI);

    detectMDSModeChange();

    ALOGD_IF(ALLOW_MONITOR_PRINT,
           "%s: mipi/lvds %s, mipi1 %s, hdmi %s, displayMode %d\n",
        __func__,
        ((mipi0 == DRM_MODE_CONNECTED) ? "connected" : "disconnected"),
        ((mipi1 == DRM_MODE_CONNECTED) ? "connected" : "disconnected"),
        ((hdmi == DRM_MODE_CONNECTED) ? "connected" : "disconnected"),
        getDisplayMode());

    return true;
}
Example #26
0
static bool gfx_ctx_drm_egl_init(void *data)
{
   const char *gpu;
   int i;
   unsigned monitor_index;
   unsigned gpu_index = 0;
   unsigned monitor = max(g_settings.video.monitor_index, 1);
   struct string_list *gpu_descriptors  = NULL;

   gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)calloc(1, sizeof(gfx_ctx_drm_egl_data_t));

   if (!drm)
      return NULL;

   drm->g_drm_fd = -1;
   gpu_descriptors = (struct string_list*)dir_list_new("/dev/dri", NULL, false);

nextgpu:
   free_drm_resources(drm);

   if (!gpu_descriptors || gpu_index == gpu_descriptors->size)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't find a suitable DRM device.\n");
      goto error;
   }
   gpu = gpu_descriptors->elems[gpu_index++].data;

   drm->g_drm_fd = open(gpu, O_RDWR);
   if (drm->g_drm_fd < 0)
   {
      RARCH_WARN("[KMS/EGL]: Couldn't open DRM device.\n");
      goto nextgpu;
   }

   drm->g_resources = drmModeGetResources(drm->g_drm_fd);
   if (!drm->g_resources)
   {
      RARCH_WARN("[KMS/EGL]: Couldn't get device resources.\n");
      goto nextgpu;
   }

   /* Enumerate all connectors. */
   monitor_index = 0;
   RARCH_LOG("[KMS/EGL]: Found %d connectors.\n",
         drm->g_resources->count_connectors);

   for (i = 0; i < drm->g_resources->count_connectors; i++)
   {
      drmModeConnectorPtr conn = drmModeGetConnector(
            drm->g_drm_fd, drm->g_resources->connectors[i]);

      if (conn)
      {
         bool connected = conn->connection == DRM_MODE_CONNECTED;
         RARCH_LOG("[KMS/EGL]: Connector %d connected: %s\n", i, connected ? "yes" : "no");
         RARCH_LOG("[KMS/EGL]: Connector %d has %d modes.\n", i, conn->count_modes);
         if (connected && conn->count_modes > 0)
         {
            monitor_index++;
            RARCH_LOG("[KMS/EGL]: Connector %d assigned to monitor index: #%u.\n", i, monitor_index);
         }
         drmModeFreeConnector(conn);
      }
   }

   monitor_index = 0;
   for (i = 0; i < drm->g_resources->count_connectors; i++)
   {
      drm->g_connector = drmModeGetConnector(drm->g_drm_fd,
            drm->g_resources->connectors[i]);

      if (!drm->g_connector)
         continue;
      if (drm->g_connector->connection == DRM_MODE_CONNECTED
            && drm->g_connector->count_modes > 0)
      {
         monitor_index++;
         if (monitor_index == monitor)
            break;
      }

      drmModeFreeConnector(drm->g_connector);
      drm->g_connector = NULL;
   }

   if (!drm->g_connector)
   {
      RARCH_WARN("[KMS/EGL]: Couldn't get device connector.\n");
      goto nextgpu;
   }

   for (i = 0; i < drm->g_resources->count_encoders; i++)
   {
      drm->g_encoder = drmModeGetEncoder(drm->g_drm_fd,
            drm->g_resources->encoders[i]);

      if (!drm->g_encoder)
         continue;
      if (drm->g_encoder->encoder_id == drm->g_connector->encoder_id)
         break;

      drmModeFreeEncoder(drm->g_encoder);
      drm->g_encoder = NULL;
   }

   if (!drm->g_encoder)
   {
      RARCH_WARN("[KMS/EGL]: Couldn't find DRM encoder.\n");
      goto nextgpu;
   }

   for (i = 0; i < drm->g_connector->count_modes; i++)
   {
      RARCH_LOG("[KMS/EGL]: Mode %d: (%s) %d x %d, %u Hz\n",
            i,
            drm->g_connector->modes[i].name,
            drm->g_connector->modes[i].hdisplay,
            drm->g_connector->modes[i].vdisplay,
            drm->g_connector->modes[i].vrefresh);
   }

   drm->g_crtc_id   = drm->g_encoder->crtc_id;
   drm->g_orig_crtc = drmModeGetCrtc(drm->g_drm_fd, drm->g_crtc_id);
   if (!drm->g_orig_crtc)
      RARCH_WARN("[KMS/EGL]: Cannot find original CRTC.\n");

   drm->g_connector_id = drm->g_connector->connector_id;

   /* First mode is assumed to be the "optimal" 
    * one for get_video_size() purposes. */
   drm->g_fb_width  = drm->g_connector->modes[0].hdisplay;
   drm->g_fb_height = drm->g_connector->modes[0].vdisplay;

   drm->g_gbm_dev = gbm_create_device(drm->g_drm_fd);

   if (!drm->g_gbm_dev)
   {
      RARCH_WARN("[KMS/EGL]: Couldn't create GBM device.\n");
      goto nextgpu;
   }

   dir_list_free(gpu_descriptors);

   driver.video_context_data = drm;

   return true;

error:
   dir_list_free(gpu_descriptors);

   gfx_ctx_drm_egl_destroy_resources(drm);

   if (drm)
      free(drm);

   return false;
}
Example #27
0
int init_drm(void)
{
	static const char *modules[] = {
			"i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "msm"
	};
	drmModeRes *resources;
	drmModeConnector *connector = NULL;
	drmModeEncoder *encoder = NULL;
	int i, area;

	for (i = 0; i < ARRAY_SIZE(modules); i++) {
		printf("trying to load module %s...", modules[i]);
		drm.fd = drmOpen(modules[i], NULL);
		if (drm.fd < 0) {
			printf("failed.\n");
		} else {
			printf("success.\n");
			break;
		}
	}

	if (drm.fd < 0) {
		printf("could not open drm device\n");
		return -1;
	}

	resources = drmModeGetResources(drm.fd);
	if (!resources) {
		printf("drmModeGetResources failed: %s\n", strerror(errno));
		return -1;
	}

	/* find a connected connector: */
	for (i = 0; i < resources->count_connectors; i++) {
		connector = drmModeGetConnector(drm.fd, resources->connectors[i]);
		if (connector->connection == DRM_MODE_CONNECTED) {
			/* it's connected, let's use this! */
			break;
		}
		drmModeFreeConnector(connector);
		connector = NULL;
	}

	if (!connector) {
		/* we could be fancy and listen for hotplug events and wait for
		 * a connector..
		 */
		printf("no connected connector!\n");
		return -1;
	}

	/* find highest resolution mode: */
	for (i = 0, area = 0; i < connector->count_modes; i++) {
		drmModeModeInfo *current_mode = &connector->modes[i];
		int current_area = current_mode->hdisplay * current_mode->vdisplay;
		if (current_area > area) {
			drm.mode = current_mode;
			area = current_area;
		}
	}

	if (!drm.mode) {
		printf("could not find mode!\n");
		return -1;
	}

	/* find encoder: */
	for (i = 0; i < resources->count_encoders; i++) {
		encoder = drmModeGetEncoder(drm.fd, resources->encoders[i]);
		if (encoder->encoder_id == connector->encoder_id)
			break;
		drmModeFreeEncoder(encoder);
		encoder = NULL;
	}

	if (!encoder) {
		printf("no encoder!\n");
		return -1;
	}

	drm.crtc_id = encoder->crtc_id;
	drm.connector_id = connector->connector_id;

	return 0;
}
Example #28
0
int DrmResources::Init() {
    char path[PROPERTY_VALUE_MAX];
    property_get("hwc.drm.device", path, "/dev/dri/card0");

    /* TODO: Use drmOpenControl here instead */
    fd_ = open(path, O_RDWR);
    if (fd_ < 0) {
        ALOGE("Failed to open dri- %s", strerror(-errno));
        return -ENODEV;
    }

    int ret = drmSetClientCap(fd_, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
    if (ret) {
        ALOGE("Failed to set universal plane cap %d", ret);
        return ret;
    }

    ret = drmSetClientCap(fd_, DRM_CLIENT_CAP_ATOMIC, 1);
    if (ret) {
        ALOGE("Failed to set atomic cap %d", ret);
        return ret;
    }

    drmModeResPtr res = drmModeGetResources(fd_);
    if (!res) {
        ALOGE("Failed to get DrmResources resources");
        return -ENODEV;
    }

    bool found_primary = false;
    int display_num = 1;

    for (int i = 0; !ret && i < res->count_crtcs; ++i) {
        drmModeCrtcPtr c = drmModeGetCrtc(fd_, res->crtcs[i]);
        if (!c) {
            ALOGE("Failed to get crtc %d", res->crtcs[i]);
            ret = -ENODEV;
            break;
        }

        DrmCrtc *crtc = new DrmCrtc(this, c, i);

        drmModeFreeCrtc(c);

        if (!crtc) {
            ALOGE("Failed to allocate crtc %d", res->crtcs[i]);
            ret = -ENOMEM;
            break;
        }

        ret = crtc->Init();
        if (ret) {
            ALOGE("Failed to initialize crtc %d", res->crtcs[i]);
            delete crtc;
            break;
        }
        crtcs_.push_back(crtc);
    }

    for (int i = 0; !ret && i < res->count_encoders; ++i) {
        drmModeEncoderPtr e = drmModeGetEncoder(fd_, res->encoders[i]);
        if (!e) {
            ALOGE("Failed to get encoder %d", res->encoders[i]);
            ret = -ENODEV;
            break;
        }

        std::vector<DrmCrtc *> possible_crtcs;
        DrmCrtc *current_crtc = NULL;
        for (std::vector<DrmCrtc *>::const_iterator iter = crtcs_.begin();
                iter != crtcs_.end(); ++iter) {
            if ((1 << (*iter)->pipe()) & e->possible_crtcs)
                possible_crtcs.push_back(*iter);

            if ((*iter)->id() == e->crtc_id)
                current_crtc = (*iter);
        }

        DrmEncoder *enc = new DrmEncoder(e, current_crtc, possible_crtcs);

        drmModeFreeEncoder(e);

        if (!enc) {
            ALOGE("Failed to allocate enc %d", res->encoders[i]);
            ret = -ENOMEM;
            break;
        }
        encoders_.push_back(enc);
    }

    for (int i = 0; !ret && i < res->count_connectors; ++i) {
        drmModeConnectorPtr c = drmModeGetConnector(fd_, res->connectors[i]);
        if (!c) {
            ALOGE("Failed to get connector %d", res->connectors[i]);
            ret = -ENODEV;
            break;
        }

        std::vector<DrmEncoder *> possible_encoders;
        DrmEncoder *current_encoder = NULL;
        for (int j = 0; j < c->count_encoders; ++j) {
            for (std::vector<DrmEncoder *>::const_iterator iter = encoders_.begin();
                    iter != encoders_.end(); ++iter) {
                if ((*iter)->id() == c->encoders[j])
                    possible_encoders.push_back((*iter));
                if ((*iter)->id() == c->encoder_id)
                    current_encoder = *iter;
            }
        }

        DrmConnector *conn =
            new DrmConnector(this, c, current_encoder, possible_encoders);

        drmModeFreeConnector(c);

        if (!conn) {
            ALOGE("Failed to allocate conn %d", res->connectors[i]);
            ret = -ENOMEM;
            break;
        }

        ret = conn->Init();
        if (ret) {
            ALOGE("Init connector %d failed", res->connectors[i]);
            delete conn;
            break;
        }
        connectors_.push_back(conn);

        if (conn->built_in() && !found_primary) {
            conn->set_display(0);
            found_primary = true;
        } else {
            conn->set_display(display_num);
            ++display_num;
        }
    }
    if (res)
        drmModeFreeResources(res);

    // Catch-all for the above loops
    if (ret)
        return ret;

    drmModePlaneResPtr plane_res = drmModeGetPlaneResources(fd_);
    if (!plane_res) {
        ALOGE("Failed to get plane resources");
        return -ENOENT;
    }

    for (uint32_t i = 0; i < plane_res->count_planes; ++i) {
        drmModePlanePtr p = drmModeGetPlane(fd_, plane_res->planes[i]);
        if (!p) {
            ALOGE("Failed to get plane %d", plane_res->planes[i]);
            ret = -ENODEV;
            break;
        }

        DrmPlane *plane = new DrmPlane(this, p);

        drmModeFreePlane(p);

        if (!plane) {
            ALOGE("Allocate plane %d failed", plane_res->planes[i]);
            ret = -ENOMEM;
            break;
        }

        ret = plane->Init();
        if (ret) {
            ALOGE("Init plane %d failed", plane_res->planes[i]);
            delete plane;
            break;
        }

        planes_.push_back(plane);
    }
    drmModeFreePlaneResources(plane_res);
    if (ret)
        return ret;

    return compositor_.Init();
}
Example #29
0
static void connector_find_mode(int fd, struct connector *c,
				drmModeRes *resources)
{
	drmModeConnector *connector;
	int i, j;

	/* First, find the connector & mode */
	c->mode = NULL;
	for (i = 0; i < resources->count_connectors; i++) {
		connector = drmModeGetConnector(fd, resources->connectors[i]);

		if (!connector) {
			fprintf(stderr, "could not get connector %i: %s\n",
				resources->connectors[i], strerror(errno));
			drmModeFreeConnector(connector);
			continue;
		}

		if (!connector->count_modes) {
			drmModeFreeConnector(connector);
			continue;
		}

		if (connector->connector_id != c->id) {
			drmModeFreeConnector(connector);
			continue;
		}

		for (j = 0; j < connector->count_modes; j++) {
			c->mode = &connector->modes[j];
			if (!strcmp(c->mode->name, c->mode_str))
				break;
		}

		/* Found it, break out */
		if (c->mode)
			break;

		drmModeFreeConnector(connector);
	}

	if (!c->mode) {
		fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
		return;
	}

	/* Now get the encoder */
	for (i = 0; i < resources->count_encoders; i++) {
		c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);

		if (!c->encoder) {
			fprintf(stderr, "could not get encoder %i: %s\n",
				resources->encoders[i], strerror(errno));
			drmModeFreeEncoder(c->encoder);
			continue;
		}

		if (c->encoder->encoder_id  == connector->encoder_id)
			break;

		drmModeFreeEncoder(c->encoder);
	}

	if (c->crtc == -1)
		c->crtc = c->encoder->crtc_id;
}
Example #30
0
bool
NativeStateDRM::init()
{
    fd_ = open("/dev/dri/card0", O_RDWR);

    if (fd_ < 0) {
        Log::error("Failed to find a suitable DRM device\n");
        return false;
    }

    resources_ = drmModeGetResources(fd_);
    if (!resources_) {
        Log::error("drmModeGetResources failed\n");
        return false;
    }

    // Find a connected connector
    for (int c = 0; c < resources_->count_connectors; c++) {
        connector_ = drmModeGetConnector(fd_, resources_->connectors[c]);
        if (DRM_MODE_CONNECTED == connector_->connection) {
            break;
        }
        drmModeFreeConnector(connector_);
        connector_ = 0;
    }

    if (!connector_) {
        Log::error("Failed to find a suitable connector\n");
        return false;
    }

    // Find the best resolution (we will always operate full-screen).
    unsigned int bestArea(0);
    for (int m = 0; m < connector_->count_modes; m++) {
        drmModeModeInfo* curMode = &connector_->modes[m];
        unsigned int curArea = curMode->hdisplay * curMode->vdisplay;
        if (curArea > bestArea) {
            mode_ = curMode;
            bestArea = curArea;
        }
    }

    if (!mode_) {
        Log::error("Failed to find a suitable mode\n");
        return false;
    }

    // Find a suitable encoder
    for (int e = 0; e < resources_->count_encoders; e++) {
        encoder_ = drmModeGetEncoder(fd_, resources_->encoders[e]);
        if (encoder_ && encoder_->encoder_id == connector_->encoder_id) {
            break;
        }
        drmModeFreeEncoder(encoder_);
        encoder_ = 0;
    }

    if (!encoder_) {
        Log::error("Failed to find a suitable encoder\n");
        return false;
    }

    if (!init_gbm()) {
        return false;
    }

    crtc_ = drmModeGetCrtc(fd_, encoder_->crtc_id);
    if (!crtc_) {
        Log::error("Failed to get current CRTC\n");
        return false;
    }

    signal(SIGINT, &NativeStateDRM::quit_handler);

    return true;
}