/* 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 = false;

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);
  buffer->drm_device_fd = fd;

  return true;
}

void ply_monitor_close(ply_frame_buffer_t *buffer)
{
  if (buffer->drm_device_fd >= 0) {
    drmClose(buffer->drm_device_fd);
    buffer->drm_device_fd = -1;
  }
}


