blob: 5927cdb544dd0ef636018079320e8464792e4d62 [file] [log] [blame]
// 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.
#ifndef SRC_UI_BACKLIGHT_DRIVERS_TI_LP8556_TI_LP8556_H_
#define SRC_UI_BACKLIGHT_DRIVERS_TI_LP8556_TI_LP8556_H_
#include <fuchsia/hardware/backlight/llcpp/fidl.h>
#include <fuchsia/hardware/power/sensor/llcpp/fidl.h>
#include <lib/ddk/hw/reg.h>
#include <lib/device-protocol/i2c-channel.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/mmio/mmio.h>
#include <optional>
#include <ddktl/device.h>
#include <ddktl/protocol/empty-protocol.h>
#include <hwreg/bitfields.h>
#include "ti-lp8556Metadata.h"
namespace ti {
#define LOG_ERROR(fmt, ...) zxlogf(ERROR, "[%s %d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...) zxlogf(INFO, "[%s %d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
#define LOG_SPEW(fmt, ...) zxlogf(TRACE, "[%s %d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
#define LOG_TRACE zxlogf(INFO, "[%s %d]", __func__, __LINE__)
constexpr uint8_t kBacklightBrightnessLsbReg = 0x10;
constexpr uint8_t kBacklightBrightnessMsbReg = 0x11;
constexpr uint8_t kDeviceControlReg = 0x1;
constexpr uint8_t kCurrentLsbReg = 0xA0;
constexpr uint8_t kCfgReg = 0xA1;
constexpr uint8_t kCfg2Reg = 0xA2;
constexpr uint32_t kAOBrightnessStickyReg = (0x04e << 2);
constexpr uint8_t kBacklightOn = 0x85;
constexpr uint8_t kBacklightOff = 0x84;
constexpr uint8_t kCfg2Default = 0x30;
constexpr uint16_t kBrightnessRegMask = 0xFFF;
constexpr uint16_t kBrightnessRegMaxValue = kBrightnessRegMask;
constexpr uint16_t kBrightnessMsbShift = 8;
constexpr uint16_t kBrightnessLsbMask = 0xFF;
constexpr uint8_t kBrightnessMsbByteMask = 0xF;
constexpr uint16_t kBrightnessMsbMask = (kBrightnessMsbByteMask << kBrightnessMsbShift);
constexpr int kTableSize = 16;
constexpr int kBrightnessStep = 256;
constexpr float kMinTableBrightness = 256;
constexpr float kMaxCurrentSetting = 4095;
constexpr float kMinBrightnessSetting = 0;
constexpr float kMaxBrightnessSetting = 4095;
constexpr int kNumBacklightDriverChannels = 6;
constexpr int kMilliampPerAmp = 1000;
class Lp8556Device;
using DeviceType = ddk::Device<Lp8556Device, ddk::Unbindable, ddk::Messageable>;
namespace FidlBacklight = fuchsia_hardware_backlight;
namespace FidlPowerSensor = fuchsia_hardware_power_sensor;
class BrightnessStickyReg : public hwreg::RegisterBase<BrightnessStickyReg, uint32_t> {
public:
// This bit is used to distinguish between a zero register value and an unset value.
// A zero value indicates that the sticky register has not been set (so a default of 100%
// brightness will be used by the bootloader).
// With this bit set, a zero brightness value is encoded as 0x1000 to distinguish it from an unset
// value.
DEF_BIT(12, is_valid);
DEF_FIELD(11, 0, brightness);
static auto Get() { return hwreg::RegisterAddr<BrightnessStickyReg>(kAOBrightnessStickyReg); }
};
class Lp8556Device : public DeviceType,
public ddk::EmptyProtocol<ZX_PROTOCOL_BACKLIGHT>,
public fidl::WireInterface<FidlBacklight::Device>,
public fidl::WireInterface<FidlPowerSensor::Device> {
public:
Lp8556Device(zx_device_t* parent, ddk::I2cChannel i2c, ddk::MmioBuffer mmio)
: DeviceType(parent), i2c_(std::move(i2c)), mmio_(std::move(mmio)) {}
zx_status_t Init();
// Methods required by the ddk mixins
void DdkUnbind(ddk::UnbindTxn txn);
void DdkRelease();
zx_status_t DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn);
zx_status_t GetBacklightState(bool* power, double* brightness);
zx_status_t SetBacklightState(bool power, double brightness);
double GetDeviceBrightness() { return brightness_; }
bool GetDevicePower() { return power_; }
uint8_t GetCfg2() { return cfg2_; }
void SetMaxAbsoluteBrightnessNits(double brightness_nits) {
max_absolute_brightness_nits_ = brightness_nits;
if (max_absolute_brightness_nits_property_) {
max_absolute_brightness_nits_property_.Set(brightness_nits);
} else {
max_absolute_brightness_nits_property_ =
root_.CreateDouble("max_absolute_brightness_nits", brightness_nits);
}
}
zx::vmo InspectVmo() { return inspector_.DuplicateVmo(); }
enum class PanelType {
kBoe = 0,
kKd = 1,
kNumTypes = 2,
};
double GetBacklightPower(double backlight_brightness);
double GetBrightnesstoCurrentScalar();
double GetBacklightVoltage(double backlight_brightness, PanelType panel_type);
double GetDriverEfficiency(double backlight_brightness);
PanelType GetPanelType();
// FIDL calls
void GetStateNormalized(GetStateNormalizedCompleter::Sync& completer) override;
void SetStateNormalized(FidlBacklight::wire::State state,
SetStateNormalizedCompleter::Sync& completer) override;
// Note: the device is calibrated at the factory to find a normalized brightness scale value that
// corresponds to a set maximum brightness in nits. GetStateAbsolute() will return an error if
// the normalized brightness scale is not set to the calibrated value, as there is no universal
// way to map other scale values to absolute brightness.
void GetStateAbsolute(GetStateAbsoluteCompleter::Sync& completer) override;
// Note: this changes the normalized brightness scale back to the calibrated value in order to set
// the absolute brightness.
void SetStateAbsolute(FidlBacklight::wire::State state,
SetStateAbsoluteCompleter::Sync& completer) override;
void GetMaxAbsoluteBrightness(GetMaxAbsoluteBrightnessCompleter::Sync& completer) override;
void SetNormalizedBrightnessScale(
double scale, SetNormalizedBrightnessScaleCompleter::Sync& completer) override;
void GetNormalizedBrightnessScale(
GetNormalizedBrightnessScaleCompleter::Sync& completer) override;
void GetPowerWatts(GetPowerWattsCompleter::Sync& completer) override;
private:
zx_status_t SetCurrentScale(uint16_t scale);
inspect::Inspector inspector_;
inspect::Node root_;
// TODO(rashaeqbal): Switch from I2C to PWM in order to support a larger brightness range.
// Needs a PWM driver.
ddk::I2cChannel i2c_;
ddk::MmioBuffer mmio_;
// brightness is set to maximum from bootloader if the persistent brightness sticky register is
// not set.
double brightness_ = 1.0;
uint16_t scale_ = 1.0;
uint16_t calibrated_scale_ = UINT16_MAX;
bool power_ = true;
uint8_t cfg2_;
std::optional<double> max_absolute_brightness_nits_;
inspect::DoubleProperty brightness_property_;
inspect::UintProperty persistent_brightness_property_;
inspect::UintProperty scale_property_;
inspect::UintProperty calibrated_scale_property_;
inspect::BoolProperty power_property_;
inspect::DoubleProperty max_absolute_brightness_nits_property_;
TiLp8556Metadata metadata_ = {};
double backlight_power_ = 0;
double max_current_ = 0.0;
};
} // namespace ti
#endif // SRC_UI_BACKLIGHT_DRIVERS_TI_LP8556_TI_LP8556_H_