// 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 "imx227.h"

#include <endian.h>
#include <lib/device-protocol/i2c.h>
#include <lib/driver-unit-test/utils.h>
#include <lib/fit/result.h>
#include <lib/trace/event.h>
#include <threads.h>
#include <zircon/types.h>

#include <ddk/debug.h>
#include <ddk/metadata.h>
#include <ddk/metadata/camera.h>
#include <ddk/protocol/camera/sensor.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>
#include <hw/reg.h>

#include "src/camera/drivers/sensors/imx227/constants.h"
#include "src/camera/drivers/sensors/imx227/imx227-bind.h"
#include "src/camera/drivers/sensors/imx227/imx227_modes.h"
#include "src/camera/drivers/sensors/imx227/imx227_seq.h"
#include "src/camera/drivers/sensors/imx227/mipi_ccs_regs.h"

namespace camera {

// Gets the register value from the sequence table.
// |id| : Index of the sequence table.
// |address| : Address of the register.
fit::result<uint8_t, zx_status_t> Imx227Device::GetRegisterValueFromSequence(uint8_t index,
                                                                             uint16_t address) {
  TRACE_DURATION("camera", "Imx227Device::GetRegisterValueFromSequence");
  if (index >= kSEQUENCE_TABLE.size()) {
    return fit::error(ZX_ERR_INVALID_ARGS);
  }
  const InitSeqFmt* sequence = kSEQUENCE_TABLE[index];
  while (true) {
    uint16_t register_address = sequence->address;
    uint16_t register_value = sequence->value;
    uint16_t register_len = sequence->len;
    if (register_address == kEndOfSequence && register_value == 0 && register_len == 0) {
      break;
    }
    if (address == register_address) {
      return fit::ok(register_value);
    }
    sequence++;
  }
  return fit::error(ZX_ERR_NOT_FOUND);
}

zx_status_t Imx227Device::InitPdev() {
  std::lock_guard guard(lock_);

  // I2c for communicating with the sensor.
  if (!i2c_.is_valid()) {
    zxlogf(ERROR, "%s; I2C not available", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  // Clk for gating clocks for sensor.
  if (!clk24_.is_valid()) {
    zxlogf(ERROR, "%s; clk24_ not available", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  // Mipi for init and de-init.
  if (!mipi_.is_valid()) {
    zxlogf(ERROR, "%s; mipi_ not available", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  // GPIOs
  if (!gpio_vana_enable_.is_valid()) {
    zxlogf(ERROR, "%s; gpio_vana_enable_ not available", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  if (!gpio_vdig_enable_.is_valid()) {
    zxlogf(ERROR, "%s; gpio_vdig_enable_ not available", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  if (!gpio_cam_rst_.is_valid()) {
    zxlogf(ERROR, "%s; gpio_cam_rst_ not available", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  // Set the GPIO to output and set them to their initial values
  // before the power up sequence.
  gpio_cam_rst_.ConfigOut(1);
  gpio_vana_enable_.ConfigOut(0);
  gpio_vdig_enable_.ConfigOut(0);
  return ZX_OK;
}

fit::result<uint16_t, zx_status_t> Imx227Device::Read16(uint16_t addr) {
  TRACE_DURATION("camera", "Imx227Device::Read16", "addr", addr);
  auto result = Read8(addr);
  if (result.is_error()) {
    return result.take_error_result();
  }
  auto upper_byte = result.value();
  result = Read8(addr + 1);
  if (result.is_error()) {
    return result.take_error_result();
  }
  auto lower_byte = result.value();
  uint16_t reg_value = upper_byte << kByteShift | lower_byte;
  return fit::ok(reg_value);
}

fit::result<uint8_t, zx_status_t> Imx227Device::Read8(uint16_t addr) {
  TRACE_DURATION("camera", "Imx227Device::Read8", "addr", addr);
  // Convert the address to Big Endian format.
  // The camera sensor expects in this format.
  uint16_t buf = htobe16(addr);
  uint8_t val = 0;
  auto status =
      i2c_.WriteReadSync(reinterpret_cast<uint8_t*>(&buf), sizeof(buf), &val, sizeof(val));
  if (status != ZX_OK) {
    zxlogf(ERROR, "Imx227Device: could not read reg addr: 0x%08x  status: %d", addr, status);
    return fit::error(status);
  }
  return fit::ok(val);
}

zx_status_t Imx227Device::Write16(uint16_t addr, uint16_t val) {
  TRACE_DURATION("camera", "Imx227Device::Write16", "addr", addr, "val", val);
  // Convert the arguments to big endian to match the register spec.
  // First two bytes are the address, third and fourth are the value to be written.
  addr = htobe16(addr);
  val = htobe16(val);
  std::array<uint8_t, 4> buf;
  buf[0] = static_cast<uint8_t>(addr & kByteMask);
  buf[1] = static_cast<uint8_t>((addr >> kByteShift) & kByteMask);
  buf[2] = static_cast<uint8_t>(val & kByteMask);
  buf[3] = static_cast<uint8_t>((val >> kByteShift) & kByteMask);
  auto status = i2c_.WriteSync(buf.data(), buf.size());
  if (status != ZX_OK) {
    zxlogf(ERROR,
           "Imx227Device: could not write reg addr/val: 0x%08x/0x%08x status: "
           "%d\n",
           addr, val, status);
  }
  return status;
}

zx_status_t Imx227Device::Write8(uint16_t addr, uint8_t val) {
  TRACE_DURATION("camera", "Imx227Device::Write8", "addr", addr, "val", val);
  // Convert the arguments to big endian to match the register spec.
  // First two bytes are the address, third one is the value to be written.
  addr = htobe16(addr);
  std::array<uint8_t, 3> buf;
  buf[0] = static_cast<uint8_t>(addr & kByteMask);
  buf[1] = static_cast<uint8_t>((addr >> kByteShift) & kByteMask);
  buf[2] = val;

  auto status = i2c_.WriteSync(buf.data(), buf.size());
  if (status != ZX_OK) {
    zxlogf(ERROR,
           "Imx227Device: could not write reg addr/val: 0x%08x/0x%08x status: "
           "%d\n",
           addr, val, status);
  }
  return status;
}

bool Imx227Device::ValidateSensorID() {
  auto result = Read16(kSensorModelIdReg);
  if (result.is_error()) {
    return false;
  }
  return result.value() == kSensorId;
}

zx_status_t Imx227Device::InitSensor(uint8_t idx) {
  TRACE_DURATION("camera", "Imx227Device::InitSensor");
  if (idx >= kSEQUENCE_TABLE.size()) {
    return ZX_ERR_INVALID_ARGS;
  }

  const InitSeqFmt* sequence = kSEQUENCE_TABLE[idx];
  bool init_command = true;

  while (init_command) {
    uint16_t address = sequence->address;
    uint8_t value = sequence->value;

    switch (address) {
      case 0x0000: {
        if (sequence->value == 0 && sequence->len == 0) {
          init_command = false;
        } else {
          Write8(address, value);
        }
        break;
      }
      default:
        Write8(address, value);
        break;
    }
    sequence++;
  }
  return ZX_OK;
}

void Imx227Device::HwInit() {
  TRACE_DURATION("camera", "Imx227Device::HwInit");
  // Power up sequence. Reference: Page 51- IMX227-0AQH5-C datasheet.
  gpio_vana_enable_.Write(1);
  zx_nanosleep(zx_deadline_after(ZX_MSEC(50)));

  gpio_vdig_enable_.Write(1);
  zx_nanosleep(zx_deadline_after(ZX_MSEC(50)));

  // Enable 24M clock for sensor.
  clk24_.Enable();
  zx_nanosleep(zx_deadline_after(ZX_MSEC(10)));

  gpio_cam_rst_.Write(0);
  zx_nanosleep(zx_deadline_after(ZX_MSEC(50)));
}

void Imx227Device::HwDeInit() {
  TRACE_DURATION("camera", "Imx227Device::HwDeInit");
  gpio_cam_rst_.Write(1);
  zx_nanosleep(zx_deadline_after(ZX_MSEC(50)));

  clk24_.Disable();
  zx_nanosleep(zx_deadline_after(ZX_MSEC(10)));

  gpio_vdig_enable_.Write(0);
  zx_nanosleep(zx_deadline_after(ZX_MSEC(50)));

  gpio_vana_enable_.Write(0);
  zx_nanosleep(zx_deadline_after(ZX_MSEC(50)));
}

zx_status_t Imx227Device::InitMipiCsi(uint8_t mode) {
  mipi_info_t mipi_info;
  mipi_adap_info_t adap_info;

  mipi_info.lanes = available_modes[mode].lanes;
  mipi_info.ui_value = 1000 / available_modes[mode].mbps;
  if ((1000 % available_modes[mode].mbps) != 0) {
    mipi_info.ui_value += 1;
  }

  adap_info.format = MIPI_IMAGE_FORMAT_AM_RAW10;
  adap_info.resolution.width = available_modes[mode].resolution_in.x;
  adap_info.resolution.height = available_modes[mode].resolution_in.y;
  adap_info.path = MIPI_PATH_PATH0;
  adap_info.mode = MIPI_MODES_DIR_MODE;
  auto status = mipi_.Init(&mipi_info, &adap_info);
  return status;
}

fit::result<int32_t, zx_status_t> Imx227Device::GetTemperature() {
  std::lock_guard guard(lock_);
  // Enable temperature control
  zx_status_t status = Write8(kTempCtrlReg, 0x01);
  if (status != ZX_OK) {
    return fit::error(status);
  }
  auto result = Read8(kTempOutputReg);
  if (result.is_error()) {
    return result.take_error_result();
  }
  auto retval = static_cast<int32_t>(result.value());
  return fit::ok(retval);
}

fit::result<uint32_t, zx_status_t> Imx227Device::GetLinesPerSecond() {
  auto result_hi =
      GetRegisterValueFromSequence(available_modes[current_mode_].idx, kLineLengthPckReg);
  auto result_lo =
      GetRegisterValueFromSequence(available_modes[current_mode_].idx, kLineLengthPckReg + 1);
  if (result_hi.is_error() || result_lo.is_error()) {
    return fit::error(ZX_ERR_INTERNAL);
  }
  uint16_t line_length_pclk = (result_hi.value() << 8) | result_lo.value();
  uint32_t lines_per_second = kMasterClock / line_length_pclk;
  return fit::ok(lines_per_second);
}

float Imx227Device::AnalogRegValueToTotalGain(uint16_t reg_value) {
  return (static_cast<float>(analog_gain_.m0_ * reg_value + analog_gain_.c0_)) /
         (static_cast<float>(analog_gain_.m1_ * reg_value + analog_gain_.c1_));
}

uint16_t Imx227Device::AnalogTotalGainToRegValue(float gain) {
  float value;
  uint16_t register_value;

  // Compute the register value.
  if (analog_gain_.m0_ == 0) {
    value = ((analog_gain_.c0_ / gain) - analog_gain_.c1_) / analog_gain_.m1_;
  } else {
    value = (analog_gain_.c1_ * gain - analog_gain_.c0_) / analog_gain_.m0_;
  }

  // Round the final result, which is quantized to the gain code step size.
  value += 0.5f * analog_gain_.gain_code_step_size_;

  // Convert and clamp.
  register_value = value;

  if (register_value < analog_gain_.gain_code_min_) {
    register_value = analog_gain_.gain_code_min_;
  }

  register_value =
      (register_value - analog_gain_.gain_code_min_) / analog_gain_.gain_code_step_size_;
  register_value = register_value * analog_gain_.gain_code_step_size_ + analog_gain_.gain_code_min_;

  if (register_value > analog_gain_.gain_code_max_) {
    register_value = analog_gain_.gain_code_max_;
  }

  return register_value;
}

float Imx227Device::DigitalRegValueToTotalGain(uint16_t reg_value) {
  return static_cast<float>(reg_value) / (1 << kDigitalGainShift);
}

uint16_t Imx227Device::DigitalTotalGainToRegValue(float gain) {
  float value;
  uint16_t register_value;

  // Compute the register value.
  value = gain * (1 << kDigitalGainShift);

  // Round the final result, which is quantized to the gain code step size.
  value += 0.5f * digital_gain_.gain_step_size_;

  // Convert and clamp.
  register_value = value;

  if (register_value < digital_gain_.gain_min_) {
    register_value = digital_gain_.gain_min_;
  }

  register_value = (register_value - digital_gain_.gain_min_) / digital_gain_.gain_step_size_;
  register_value = register_value * digital_gain_.gain_step_size_ + digital_gain_.gain_min_;

  if (register_value > digital_gain_.gain_max_) {
    register_value = digital_gain_.gain_max_;
  }

  return register_value;
}
zx_status_t Imx227Device::ReadAnalogGainConstants() {
  auto result_m0 = Read16(kAnalogGainM0Reg);
  auto result_m1 = Read16(kAnalogGainM1Reg);
  auto result_c0 = Read16(kAnalogGainC0Reg);
  auto result_c1 = Read16(kAnalogGainC1Reg);
  auto result_amin = Read16(kAnalogGainCodeMinReg);
  auto result_amax = Read16(kAnalogGainCodeMaxReg);
  auto result_astep = Read16(kAnalogGainCodeStepSizeReg);

  if (result_m0.is_error() || result_m1.is_error() || result_c0.is_error() ||
      result_c1.is_error() || result_amin.is_error() || result_amax.is_error() ||
      result_astep.is_error()) {
    return ZX_ERR_BAD_STATE;
  }

  analog_gain_.m0_ = result_m0.value();
  analog_gain_.m1_ = result_m1.value();
  analog_gain_.c0_ = result_c0.value();
  analog_gain_.c1_ = result_c1.value();
  analog_gain_.gain_code_min_ = result_amin.value();
  analog_gain_.gain_code_max_ = result_amax.value();
  analog_gain_.gain_code_step_size_ = result_astep.value();

  // Validate the m0,1 constraint
  if (!(analog_gain_.m0_ == 0) ^ (analog_gain_.m1_ == 0)) {
    return ZX_ERR_BAD_STATE;
  }

  return ZX_OK;
}

zx_status_t Imx227Device::ReadDigitalGainConstants() {
  auto result_dmin = Read16(kDigitalGainMinReg);
  auto result_dmax = Read16(kDigitalGainMaxReg);
  auto result_dstep = Read16(kDigitalGainStepSizeReg);

  if (result_dmin.is_error() || result_dmax.is_error() || result_dstep.is_error()) {
    return ZX_ERR_BAD_STATE;
  }

  digital_gain_.gain_min_ = result_dmin.value();
  digital_gain_.gain_max_ = result_dmax.value();
  digital_gain_.gain_step_size_ = result_dstep.value();
  return ZX_OK;
}

// TODO(jsasinowski): Determine if this can be called less frequently.
zx_status_t Imx227Device::ReadGainConstants() {
  if (gain_constants_valid_) {
    return ZX_OK;
  }

  auto status = ReadAnalogGainConstants();
  if (status != ZX_OK) {
    return status;
  }

  status = ReadDigitalGainConstants();
  if (status != ZX_OK) {
    return status;
  }

  gain_constants_valid_ = true;
  return ZX_OK;
}

zx_status_t Imx227Device::SetGroupedParameterHold(bool enable) {
  auto status = Write8(kGroupedParameterHoldReg, enable ? 1 : 0);
  return status;
}

zx_status_t Imx227Device::Create(zx_device_t* parent, std::unique_ptr<Imx227Device>* device_out) {
  ddk::CompositeProtocolClient composite(parent);
  if (!composite.is_valid()) {
    zxlogf(ERROR, "%s could not get composite protocoln", __func__);
    return ZX_ERR_NOT_SUPPORTED;
  }

  auto sensor_device = std::make_unique<Imx227Device>(parent, composite);

  zx_status_t status = sensor_device->InitPdev();
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s InitPdev failed", __func__);
    return status;
  }
  *device_out = std::move(sensor_device);
  return status;
}

void Imx227Device::ShutDown() {}

void Imx227Device::DdkUnbind(ddk::UnbindTxn txn) { txn.Reply(); }

void Imx227Device::DdkRelease() {
  ShutDown();
  delete this;
}

zx_status_t Imx227Device::CreateAndBind(void* /*ctx*/, zx_device_t* parent) {
  std::unique_ptr<Imx227Device> device;
  zx_status_t status = Imx227Device::Create(parent, &device);
  if (status != ZX_OK) {
    zxlogf(ERROR, "imx227: Could not setup imx227 sensor device: %d", status);
    return status;
  }
  std::array<zx_device_prop_t, 1> props = {{
      {BIND_PLATFORM_PROTO, 0, ZX_PROTOCOL_CAMERA_SENSOR2},
  }};

  status = device->DdkAdd(
      ddk::DeviceAddArgs("imx227").set_flags(DEVICE_ADD_ALLOW_MULTI_COMPOSITE).set_props(props));
  if (status != ZX_OK) {
    zxlogf(ERROR, "imx227: Could not add imx227 sensor device: %d", status);
    return status;
  }
  zxlogf(INFO, "imx227 driver added");

  // `device` intentionally leaked as it is now held by DevMgr.
  __UNUSED auto* dev = device.release();
  return ZX_OK;
}

bool Imx227Device::RunUnitTests(void* ctx, zx_device_t* parent, zx_handle_t channel) {
  return driver_unit_test::RunZxTests("Imx227Tests", parent, channel);
}

static constexpr zx_driver_ops_t driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = Imx227Device::CreateAndBind;
  ops.run_unit_tests = Imx227Device::RunUnitTests;
  return ops;
}();

}  // namespace camera

// clang-format off
ZIRCON_DRIVER(imx227, camera::driver_ops, "imx227", "0.1");
