/* ply-monitor.c - monitor setup via KMS
 *
 * Copyright (C) 2012, The Chromium OS Authors.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <xf86drm.h>
#include <xf86drmMode.h>

#include "ply-frame-buffer.h"
#include "ply-kms.h"
#include "ply-utils.h"

bool ply_monitor_set_monitors = true;

static drmModeCrtc *find_crtc_for_connector(int fd,
                                            drmModeRes *resources,
                                            drmModeConnector *connector) {
  int i;
  int encoder_crtc_id = -1;

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

    if (encoder) {
      if (encoder->encoder_id == connector->encoder_id) {
        encoder_crtc_id = encoder->crtc_id;
        drmModeFreeEncoder(encoder);
        break;
      }
      drmModeFreeEncoder(encoder);
    }
  }

  if (encoder_crtc_id == -1)
    return NULL;

  /* Find the crtc */
  for (i = 0; i < resources->count_crtcs; i++) {
    drmModeCrtc *crtc = drmModeGetCrtc(fd, resources->crtcs[i]);

    if (crtc) {
      if (encoder_crtc_id == crtc->crtc_id)
        return crtc;
      drmModeFreeCrtc(crtc);
    }
  }

  return NULL;
}

static bool is_connector_used(int fd,
                              drmModeRes *resources,
                              drmModeConnector *connector) {
  bool result = false;
  drmModeCrtc *crtc = find_crtc_for_connector(fd, resources, connector);

  if (crtc) {
    result = crtc->buffer_id != 0;
    drmModeFreeCrtc(crtc);
  }

  return result;
}

static drmModeConnector* find_used_connector_by_type(int fd,
                                                     drmModeRes *resources,
                                                     int type) {
  int i;
  for (i = 0; i < resources->count_connectors; i++) {
    drmModeConnector *connector;

    connector = drmModeGetConnector(fd, resources->connectors[i]);
    if (connector) {
      if ((connector->connector_type == type) &&
          (is_connector_used(fd, resources, connector)))
        return connector;

      drmModeFreeConnector(connector);
    }
  }
  return NULL;
}

static drmModeConnector* find_first_used_connector(int fd,
                                                   drmModeRes *resources) {
  int i;
  for (i = 0; i < resources->count_connectors; i++) {
    drmModeConnector *connector;

    connector = drmModeGetConnector(fd, resources->connectors[i]);
    if (connector) {
      if (is_connector_used(fd, resources, connector))
        return connector;

      drmModeFreeConnector(connector);
    }
  }
  return NULL;
}

static drmModeConnector *find_main_monitor(int fd,
                                           drmModeRes *resources) {
  int i;
  /*
   * Find the LVDS and eDP connectors. Those are the main screens.
   */
  int kConnectorPriority[] = {
    DRM_MODE_CONNECTOR_LVDS,
    DRM_MODE_CONNECTOR_eDP,
  };

  drmModeConnector *main_monitor_connector = NULL;
  i = 0;
  do {
    main_monitor_connector = find_used_connector_by_type(
                                 fd,
                                 resources,
                                 kConnectorPriority[i]);
    i++;
  } while (!main_monitor_connector && i < ARRAY_SIZE(kConnectorPriority));

  /*
   * If we didn't find a connector, grab the first one in use.
   */
  if (!main_monitor_connector)
    main_monitor_connector = find_first_used_connector(fd, resources);

  return main_monitor_connector;
}

static void disable_connector(int fd,
                              drmModeRes *resources,
                              drmModeConnector *connector) {
  drmModeCrtc *crtc = find_crtc_for_connector(fd, resources, connector);

  if (crtc) {
    drmModeSetCrtc(fd,
                   crtc->crtc_id,
                   0,     // buffer_id
                   0, 0,  // x,y
                   NULL,  // connectors
                   0,     // connector_count
                   NULL); // mode
    drmModeFreeCrtc(crtc);
  }
}

static void disable_non_main_connectors(int fd,
                                        drmModeRes *resources,
                                        drmModeConnector *main_connector) {
  int i;

  for (i = 0; i < resources->count_connectors; i++) {
    drmModeConnector *connector;

    connector = drmModeGetConnector(fd, resources->connectors[i]);
    if (connector->connector_id != main_connector->connector_id)
      disable_connector(fd, resources, connector);

    drmModeFreeConnector(connector);
  }
}

bool ply_monitor_setup(ply_frame_buffer_t *buffer) {
  int fd = ply_kms_open();
  ply_frame_buffer_area_t *area = &buffer->area;

  if (fd < 0) {
    fprintf(stderr, "Unable to open a KMS module\n");
    return false;
  }

  drmModeRes *resources = drmModeGetResources(fd);
  if (!resources) {
    fprintf(stderr, "Unable to get mode resources\n");
    drmClose(fd);
    return false;
  }

  drmModeConnector *main_monitor_connector = find_main_monitor(fd, resources);

  /*
   * If we didn't find any enabled connector, leave.
   */
  if (!main_monitor_connector) {
    drmModeFreeResources(resources);
    drmClose(fd);
    return false;
  }

  if (ply_monitor_set_monitors)
    disable_non_main_connectors(fd, resources, main_monitor_connector);

  drmModeCrtc *crtc = find_crtc_for_connector(fd, resources, main_monitor_connector);
  area->visible_width = crtc->mode.hdisplay;
  area->visible_height = crtc->mode.vdisplay;

  drmModeFreeCrtc(crtc);
  drmModeFreeConnector(main_monitor_connector);
  drmModeFreeResources(resources);
  drmClose(fd);

  return true;
}


