// Copyright 2019 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 "sgm37603a.h"

#include <lib/ddk/debug.h>
#include <lib/ddk/platform-defs.h>

#include <algorithm>
#include <memory>

#include <ddktl/fidl.h>
#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>

#include "src/ui/backlight/drivers/sg-micro/sgm37603a-bind.h"

namespace {

constexpr int64_t kEnableSleepTimeMs = 20;

}  // namespace

namespace backlight {

zx_status_t Sgm37603a::Create(void* ctx, zx_device_t* parent) {
  ddk::I2cChannel i2c(parent, "i2c");
  if (!i2c.is_valid()) {
    zxlogf(ERROR, "%s: could not get protocol ZX_PROTOCOL_I2C", __FILE__);
    return ZX_ERR_NO_RESOURCES;
  }

  ddk::GpioProtocolClient reset_gpio(parent, "gpio");
  if (!reset_gpio.is_valid()) {
    zxlogf(ERROR, "%s: could not get protocol ZX_PROTOCOL_GPIO", __FILE__);
    return ZX_ERR_NO_RESOURCES;
  }

  fbl::AllocChecker ac;
  std::unique_ptr<Sgm37603a> device(new (&ac) Sgm37603a(parent, i2c, reset_gpio));
  if (!ac.check()) {
    zxlogf(ERROR, "%s: Sgm37603a alloc failed", __FILE__);
    return ZX_ERR_NO_MEMORY;
  }

  zx_status_t status = device->SetBacklightState(true, 1.0);
  if (status != ZX_OK) {
    return status;
  }

  if ((status = device->DdkAdd("sgm37603a")) != ZX_OK) {
    zxlogf(ERROR, "%s: DdkAdd failed", __FILE__);
    return status;
  }

  __UNUSED auto* dummy = device.release();

  return ZX_OK;
}

zx_status_t Sgm37603a::EnableBacklight() {
  zx_status_t status = reset_gpio_.ConfigOut(1);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to enable backlight driver", __FILE__);
    return status;
  }

  zx::nanosleep(zx::deadline_after(zx::msec(kEnableSleepTimeMs)));

  for (size_t i = 0; i < countof(kDefaultRegValues); i++) {
    status = i2c_.WriteSync(kDefaultRegValues[i], sizeof(kDefaultRegValues[i]));
    if (status != ZX_OK) {
      zxlogf(ERROR, "%s: Failed to configure backlight driver", __FILE__);
      return status;
    }
  }

  return ZX_OK;
}

zx_status_t Sgm37603a::DisableBacklight() {
  zx_status_t status = reset_gpio_.ConfigOut(0);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to disable backlight driver", __FILE__);
    return status;
  }

  return ZX_OK;
}

void Sgm37603a::GetStateNormalized(GetStateNormalizedCompleter::Sync& completer) {
  FidlBacklight::wire::State state = {};
  auto status = GetBacklightState(&state.backlight_on, &state.brightness);
  if (status == ZX_OK) {
    completer.ReplySuccess(state);
  } else {
    completer.ReplyError(status);
  }
}

void Sgm37603a::SetStateNormalized(FidlBacklight::wire::State state,
                                   SetStateNormalizedCompleter::Sync& completer) {
  auto status = SetBacklightState(state.backlight_on, state.brightness);
  if (status == ZX_OK) {
    completer.ReplySuccess();
  } else {
    completer.ReplyError(status);
  }
}

void Sgm37603a::GetStateAbsolute(GetStateAbsoluteCompleter::Sync& completer) {
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

void Sgm37603a::SetStateAbsolute(FidlBacklight::wire::State state,
                                 SetStateAbsoluteCompleter::Sync& completer) {
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

void Sgm37603a::GetMaxAbsoluteBrightness(GetMaxAbsoluteBrightnessCompleter::Sync& completer) {
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

void Sgm37603a::SetNormalizedBrightnessScale(
    __UNUSED double scale, SetNormalizedBrightnessScaleCompleter::Sync& completer) {
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

void Sgm37603a::GetNormalizedBrightnessScale(
    GetNormalizedBrightnessScaleCompleter::Sync& completer) {
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

zx_status_t Sgm37603a::DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
  DdkTransaction transaction(txn);
  fidl::WireDispatch<FidlBacklight::Device>(this, msg, &transaction);
  return transaction.Status();
}

zx_status_t Sgm37603a::GetBacklightState(bool* power, double* brightness) {
  *power = enabled_;
  *brightness = brightness_;
  return ZX_OK;
}

zx_status_t Sgm37603a::SetBacklightState(bool power, double brightness) {
  if (!power) {
    enabled_ = false;
    brightness_ = 0;

    return DisableBacklight();
  } else if (!enabled_) {
    enabled_ = true;

    zx_status_t status = EnableBacklight();
    if (status != ZX_OK) {
      return status;
    }
  }

  brightness = std::max(brightness, 0.0);
  brightness = std::min(brightness, 1.0);

  uint16_t brightness_value = static_cast<uint16_t>(brightness * kMaxBrightnessRegValue);
  const uint8_t brightness_regs[][2] = {
      {kBrightnessLsb, static_cast<uint8_t>(brightness_value & kBrightnessLsbMask)},
      {kBrightnessMsb, static_cast<uint8_t>(brightness_value >> kBrightnessLsbBits)},
  };

  for (size_t i = 0; i < countof(brightness_regs); i++) {
    zx_status_t status = i2c_.WriteSync(brightness_regs[i], sizeof(brightness_regs[i]));
    if (status != ZX_OK) {
      zxlogf(ERROR, "%s: Failed to set brightness register", __FILE__);
      return status;
    }
  }

  brightness_ = brightness;
  return ZX_OK;
}

}  // namespace backlight

static constexpr zx_driver_ops_t sgm37603a_driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = backlight::Sgm37603a::Create;
  return ops;
}();

ZIRCON_DRIVER(sgm37603a, sgm37603a_driver_ops, "zircon", "0.1");
