// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <errno.h>
#include <fcntl.h>
#include <fuchsia/gpu/clock/c/fidl.h>
#include <inttypes.h>
#include <lib/fdio/util.h>
#include <lib/fdio/watcher.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <zircon/device/thermal.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/port.h>
#include <zircon/syscalls/system.h>

#include <zx/handle.h>

// TODO(braval): Combine thermd & thermd_arm and have a unified
// code for the thermal deamon
static zx_status_t thermal_device_added(int dirfd, int event, const char* name,
                                        void* cookie) {
  if (event != WATCH_EVENT_ADD_FILE) {
    return ZX_OK;
  }
  if (!strcmp("000", name)) {
    // Device found, terminate watcher
    return ZX_ERR_STOP;
  } else {
    return ZX_OK;
  }
}

int main(int argc, char** argv) {
  printf("thermd: started\n");

  // TODO(braval): This sleep is not needed here but leaving it here
  // since the Intel thermd has it. Clean up when both deamons are
  // unified
  zx_nanosleep(zx_deadline_after(ZX_SEC(3)));

  int dirfd = open("/dev/class/thermal", O_DIRECTORY | O_RDONLY);
  if (dirfd < 0) {
    fprintf(stderr, "ERROR: Failed to open /dev/class/thermal: %d (errno %d)\n",
            dirfd, errno);
    return -1;
  }

  zx_status_t st =
      fdio_watch_directory(dirfd, thermal_device_added, ZX_TIME_INFINITE, NULL);
  if (st != ZX_ERR_STOP) {
    fprintf(stderr,
            "ERROR: watcher terminating without finding sensors, "
            "terminating thermd...\n");
    return -1;
  }

  // first device is the one we are interested
  int fd = open("/dev/class/thermal/000", O_RDWR);
  if (fd < 0) {
    fprintf(stderr, "ERROR: Failed to open sensor: %d (errno %d) \n", fd,
            errno);
    return -1;
  }

  // first device is the one we are interested
  int fd_gpu = open("/dev/class/gpu-thermal/000", O_RDONLY);
  if (fd_gpu < 0) {
    fprintf(stderr, "ERROR: Failed to open gpu: %d (errno %d) \n", fd_gpu,
            errno);
    return -1;
  }

  zx::handle gpu_handle;
  st = fdio_get_service_handle(fd_gpu, gpu_handle.reset_and_get_address());
  if (st != ZX_OK) {
    fprintf(stderr, "ERROR: Failed to get gpu service: %d\n", st);
    return -1;
  }

  thermal_device_info_t info;
  ssize_t rc = ioctl_thermal_get_device_info(fd, &info);
  if (rc != sizeof(info)) {
    fprintf(stderr, "ERROR: Failed to get thermal info: %zd\n", rc);
    return rc;
  }

  if (info.num_trip_points == 0) {
    fprintf(stderr, "Trip points not supported, exiting\n");
    return 0;
  }

  if (!info.active_cooling && !info.passive_cooling) {
    fprintf(stderr,
            "ERROR: No active or passive cooling present on device, "
            "terminating thermd...\n");
    return 0;
  }

  zx_handle_t port = ZX_HANDLE_INVALID;
  rc = ioctl_thermal_get_state_change_port(fd, &port);
  if (rc != sizeof(port)) {
    fprintf(stderr, "ERROR: Failed to get event: %zd\n", rc);
    return rc;
  }

  for (;;) {
    zx_port_packet_t packet;
    st = zx_port_wait(port, ZX_TIME_INFINITE, &packet);
    if (st != ZX_OK) {
      fprintf(stderr, "ERROR: Failed to wait on port: %d\n", st);
      return st;
    }

    uint32_t trip_idx = (uint32_t)packet.key;
    if (trip_idx > info.num_trip_points) {
      fprintf(stderr, "ERROR: Invalid trip index: terminating thermd\n");
      return -1;
    }

    if (info.passive_cooling) {
      uint32_t big_cluster_opp =
          info.trip_point_info[trip_idx].big_cluster_dvfs_opp;
      dvfs_info_t dvfs_info;

      // Set DVFS Opp for Big Cluster.
      dvfs_info.power_domain = BIG_CLUSTER_POWER_DOMAIN;
      dvfs_info.op_idx = big_cluster_opp;
      rc = ioctl_thermal_set_dvfs_opp(fd, &dvfs_info);
      if (rc < 0) {
        fprintf(stderr, "ERROR: Failed to set DVFS OPP for big cluster: %zd\n",
                rc);
        return rc;
      }

      // Check if it's big little.
      if (info.big_little) {
        // Set the DVFS Opp for Little Cluster.
        uint32_t little_cluster_opp =
            info.trip_point_info[trip_idx].little_cluster_dvfs_opp;
        dvfs_info.power_domain = LITTLE_CLUSTER_POWER_DOMAIN;
        dvfs_info.op_idx = little_cluster_opp;
        rc = ioctl_thermal_set_dvfs_opp(fd, &dvfs_info);
        if (rc < 0) {
          fprintf(stderr,
                  "ERROR: Failed to set DVFS OPP for little cluster: %zd\n",
                  rc);
          return rc;
        }
      }
    }

    if (info.active_cooling) {
      uint32_t fan_level = info.trip_point_info[trip_idx].fan_level;
      rc = ioctl_thermal_set_fan_level(fd, &fan_level);
      if (rc) {
        fprintf(stderr, "ERROR: Failed to set fan level: %zd\n", rc);
        return rc;
      }
    }

    if (info.gpu_throttling) {
      int gpu_clk_freq_source =
          info.trip_point_info[trip_idx].gpu_clk_freq_source;
      if (gpu_clk_freq_source != -1) {
        zx_status_t status2;
        st = fuchsia_gpu_clock_ClockSetFrequencySource(
            gpu_handle.get(), gpu_clk_freq_source, &status2);
        if (st != ZX_OK || status2 != ZX_OK) {
          fprintf(stderr,
                  "ERROR: Failed to change gpu clock freq source: %d %d\n", st,
                  status2);
          return -1;
        }
      }
    }
  }

  close(fd);

  printf("thermd terminating: %d\n", st);

  return 0;
}
