// Copyright 2012 Google Inc. All Rights Reserved.
// Author: kedong@google.com (Ke Dong)

#ifndef BRUNO_PLATFORM_PERIPHERAL_FANCONTROL_H_
#define BRUNO_PLATFORM_PERIPHERAL_FANCONTROL_H_

#include "bruno/constructormagic.h"
#include "platform.h"
#include "mailbox.h"

namespace bruno_platform_peripheral {

class Platform;

#define DUTY_CYCLE_PWM_MIN_VALUE    0
#define DUTY_CYCLE_PWM_MAX_VALUE    100


typedef struct FanControlParams {
  uint16_t  temp_setpt;
  uint16_t  temp_max;
  uint16_t  temp_step;
  uint16_t  duty_cycle_min;
  uint16_t  duty_cycle_max;
  uint16_t  pwm_step;
  uint16_t  temp_overheat;

  FanControlParams& operator = (const FanControlParams& param) {
    temp_setpt = param.temp_setpt;
    temp_max = param.temp_max;
    temp_step = param.temp_step;
    duty_cycle_min = param.duty_cycle_min;
    duty_cycle_max = param.duty_cycle_max;
    pwm_step = param.pwm_step;
    temp_overheat = param.temp_overheat;
    return *this;
  }

}FanControlParams;


class FanControl: public Mailbox {
 public:
  enum StateType {
    OFF,
    VAR_SPEED,
    FULL_SPEED
  };

  enum FanControlParamsTypes {
    BRUNO_SOC = 0,
    BRUNO_IS_HDD,
    BRUNO_PARAMS_TYPES
  };

  static const unsigned int kPwmDefaultStartup;
  static const unsigned int kPwmMinValue;
  static const unsigned int kPwmMaxValue;
  static const unsigned int kFanSpeedNotSpinning;

  static const FanControlParams kGFMS100FanCtrlSocDefaults;
  static const FanControlParams kGFMS100FanCtrlHddDefaults;

  static const FanControlParams kGFRG200FanCtrlSocDefaults;

  static const FanControlParams kGFRG210FanCtrlSocDefaults;
  static const FanControlParams kGFRG210FanCtrlHddDefaults;

  static const FanControlParams kGFSC100FanCtrlSocDefaults;
  static const FanControlParams kGFSC100FanCtrlHddDefaults;

  static const FanControlParams kGFHD100FanCtrlSocDefaults;
  static const FanControlParams kGFHD200FanCtrlSocDefaults;
  static const FanControlParams kGFHD254FanCtrlSocDefaults;

  static const FanControlParams kGFLT110FanCtrlSocDefaults;

  explicit FanControl(Platform *platform)
      : state_(OFF),
        auto_mode_(true),
        duty_cycle_pwm_(kPwmMinValue),
        duty_cycle_startup_(kPwmDefaultStartup),
        period_(DUTY_CYCLE_PWM_MAX_VALUE-1),
        platform_(BRUNO_GFHD100),
        pfan_ctrl_params_(NULL),
        allocatedPlatformInstanceLocal_(false),
        platformInstance_(platform) {}

  virtual ~FanControl();

  bool Init(bool *gpio_mailbox_ready);
  void Terminate(void);
  bool DrivePwm(uint16_t duty_cycle);
  bool AdjustSpeed(uint16_t soc_temp, uint16_t hdd_temp, uint16_t fan_speed);
  void GetHddTemperature(uint16_t *phdd_temp);
  void GetOverheatTemperature(uint16_t *poverheat_temp);

 private:

  void InitParams(void);
  std::string ExecCmd(char* cmd, std::string *pattern);
  void ComputeDutyCycle(uint16_t soc_temp, uint16_t hdd_temp,
                        uint16_t fan_speed, uint16_t *new_duty_cycle_pwm);

  void dbgUpdateFanControlParams(void);
  bool dbgGetFanControlParamsFromParamsFile(uint8_t fc_idx);

  StateType state_;
  bool auto_mode_;
  uint16_t duty_cycle_pwm_;     /* current pwm duty cycle */
  uint16_t duty_cycle_startup_; /* initial duty cycle */
  /*
   * Period = period_ + 1 where period_ is the register value in chip.
   * (I have no idea why BRCM need it to be one short...), in this class, the
   * period_ value is the value you will set in register. But the real Period is
   * period_+1 mathmatically.
   * To bump up the CPU with full duty cycle, the On register needs to be set as
   * Period a.k.a period_+1.
   */
  uint16_t period_;

  /* Fan control parameters table
   * idx BRUNO_SOC: depending upon GFMS100 (Bruno-IS) or GFHD100 (Thin Bruno);
   * idx BRUNO_IS_HDD: use by HDD GFMS100
   * */
  enum BrunoPlatformTypes platform_;
  FanControlParams *pfan_ctrl_params_;
  bool allocatedPlatformInstanceLocal_;
  Platform *platformInstance_;

  FanControlParams *get_hdd_fan_ctrl_parms();
  bool if_hdd_temp_over_temp_max(const uint16_t hdd_temp, const FanControlParams *phdd) const;
  bool if_hdd_temp_over_temp_setpt(const uint16_t hdd_temp, const FanControlParams *phdd) const;
  bool if_hdd_temp_lower_than_temp_setpt(const uint16_t hdd_temp, const FanControlParams *phdd) const;

  DISALLOW_COPY_AND_ASSIGN(FanControl);
};

}  // namespace bruno_platform_peripheral

#endif // BRUNO_PLATFORM_PERIPHERAL_FANCONTROL_H_
