blob: 49011c904e627548c2baa8a80808458d5a4035c1 [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_CAMERA_DRIVERS_SENSORS_IMX227_IMX227_H_
#define SRC_CAMERA_DRIVERS_SENSORS_IMX227_IMX227_H_
#include <lib/device-protocol/i2c-channel.h>
#include <lib/device-protocol/pdev.h>
#include <lib/fit/result.h>
#include <array>
#include <mutex>
#include <ddk/platform-defs.h>
#include <ddktl/device.h>
#include <ddktl/protocol/camera/sensor.h>
#include <ddktl/protocol/camerasensor.h>
#include <ddktl/protocol/clock.h>
#include <ddktl/protocol/composite.h>
#include <ddktl/protocol/empty-protocol.h>
#include <ddktl/protocol/gpio.h>
#include <ddktl/protocol/mipicsi.h>
namespace camera {
// TODO(fxbug.dev/57529): Refactor into a class that incorporates relevant methods.
// TODO(jsasinowski): Generalize to cover additional gain modes.
struct AnalogGain {
// Analog gain constants queried from the sensor, per the SMIA spec.
// gain = (m0 * x + c0) / (m1 * x + c1)
// Exactly one of m0 and m1 must be 0.
int16_t m0_;
int16_t c0_;
int16_t m1_;
int16_t c1_;
uint16_t gain_code_min_;
uint16_t gain_code_max_;
uint16_t gain_code_step_size_;
// Flag to indicate when an update is needed.
bool update_gain_;
uint16_t gain_code_global_;
};
// TODO(jsasinowski): Refactor into a class that incorporates relevant methods.
struct DigitalGain {
uint16_t gain_min_;
uint16_t gain_max_;
uint16_t gain_step_size_;
// Flag to indicate when an update is needed.
bool update_gain_;
uint16_t gain_;
};
// TODO(jsasinowski): Refactor into a class that incorporates relevant methods.
struct IntegrationTime {
// Flag to indicate when an update is needed.
bool update_integration_time_;
uint16_t coarse_integration_time_;
};
class Imx227Device;
using DeviceType = ddk::Device<Imx227Device, ddk::Unbindable>;
class Imx227Device : public DeviceType,
public ddk::CameraSensor2Protocol<Imx227Device, ddk::base_protocol> {
public:
Imx227Device(zx_device_t* device, ddk::CompositeProtocolClient composite)
: DeviceType(device),
i2c_(composite, "i2c"),
gpio_vana_enable_(composite, "gpio-vana"),
gpio_vdig_enable_(composite, "gpio-vdig"),
gpio_cam_rst_(composite, "gpio-reset"),
clk24_(composite, "clock-sensor"),
mipi_(composite, "mipicsi") {}
static zx_status_t Create(zx_device_t* parent, std::unique_ptr<Imx227Device>* device_out);
static zx_status_t CreateAndBind(void* ctx, zx_device_t* parent);
static bool RunUnitTests(void* ctx, zx_device_t* parent, zx_handle_t channel);
// Methods required by the ddk mixins
void DdkUnbind(ddk::UnbindTxn txn);
void DdkRelease();
bool IsSensorOutOfReset() {
std::lock_guard guard(lock_);
return ValidateSensorID();
}
// OTP
// Read the sensor's entire OTP memory.
//
// Returns:
// A result with a vmo containing the OTP blob if the read succeeded. Otherwise returns a
// result with an error code.
fit::result<zx::vmo, zx_status_t> OtpRead();
// Validates the integrity of the data written to the OTP. A checksum is calculated from the
// written data and checked against a hard-coded value.
//
// Args:
// |vmo| VMO of data to be validated
//
// Returns:
// Whether the OTP data validated successfully.
static bool OtpValidate(const zx::vmo& vmo);
// |ZX_PROTOCOL_CAMERA_SENSOR2|
zx_status_t CameraSensor2Init();
void CameraSensor2DeInit();
zx_status_t CameraSensor2GetSensorId(uint32_t* out_id);
zx_status_t CameraSensor2GetAvailableModes(operating_mode_t* out_modes_list, size_t modes_count,
size_t* out_modes_actual);
zx_status_t CameraSensor2SetMode(uint32_t mode);
zx_status_t CameraSensor2StartStreaming();
void CameraSensor2StopStreaming();
zx_status_t CameraSensor2GetAnalogGain(float* out_gain);
zx_status_t CameraSensor2SetAnalogGain(float gain, float* out_gain);
zx_status_t CameraSensor2GetDigitalGain(float* out_gain);
zx_status_t CameraSensor2SetDigitalGain(float gain, float* out_gain);
zx_status_t CameraSensor2GetIntegrationTime(float* out_int_time);
zx_status_t CameraSensor2SetIntegrationTime(float int_time, float* out_int_time);
zx_status_t CameraSensor2Update();
zx_status_t CameraSensor2GetOtpSize(uint32_t* out_size);
zx_status_t CameraSensor2GetOtpData(uint32_t byte_count, uint32_t offset, zx::vmo* out_otp_data);
zx_status_t CameraSensor2GetTestPatternMode(uint16_t* out_value);
zx_status_t CameraSensor2SetTestPatternMode(uint16_t mode);
zx_status_t CameraSensor2GetTestPatternData(color_val_t* out_data);
zx_status_t CameraSensor2SetTestPatternData(const color_val_t* data);
zx_status_t CameraSensor2GetTestCursorData(rect_t* out_data);
zx_status_t CameraSensor2SetTestCursorData(const rect_t* data);
zx_status_t CameraSensor2GetExtensionValue(uint64_t id, extension_value_data_type_t* out_value);
zx_status_t CameraSensor2SetExtensionValue(uint64_t id, const extension_value_data_type_t* value,
extension_value_data_type_t* out_value);
protected:
// Protocols
ddk::I2cChannel i2c_;
ddk::GpioProtocolClient gpio_vana_enable_;
ddk::GpioProtocolClient gpio_vdig_enable_;
ddk::GpioProtocolClient gpio_cam_rst_;
ddk::ClockProtocolClient clk24_;
ddk::MipiCsiProtocolClient mipi_;
// Other
zx_status_t InitPdev();
private:
// I2C Helpers
// Returns ZX_OK and an uint16_t value if the read succeeds.
// Returns error if the I2C read fails.
fit::result<uint16_t, zx_status_t> Read16(uint16_t addr) __TA_REQUIRES(lock_);
// Returns ZX_OK and an uint8_t value if the read succeeds.
// Returns error if the I2C read fails.
fit::result<uint8_t, zx_status_t> Read8(uint16_t addr) __TA_REQUIRES(lock_);
// Returns ZX_OK if the write is successful otherwise returns an error.
zx_status_t Write16(uint16_t addr, uint16_t val) __TA_REQUIRES(lock_);
// Returns ZX_OK if the write is successful otherwise returns an error.
zx_status_t Write8(uint16_t addr, uint8_t val) __TA_REQUIRES(lock_);
// Other
zx_status_t InitMipiCsi(uint8_t mode) __TA_REQUIRES(lock_);
zx_status_t InitSensor(uint8_t idx) __TA_REQUIRES(lock_);
void HwInit() __TA_REQUIRES(lock_);
void HwDeInit() __TA_REQUIRES(lock_);
void ShutDown();
bool ValidateSensorID() __TA_REQUIRES(lock_);
// Read sensor temperature
// Ranges between -20C and 80C
fit::result<int32_t, zx_status_t> GetTemperature();
bool is_streaming_;
uint8_t num_modes_;
uint8_t current_mode_;
fit::result<uint8_t, zx_status_t> GetRegisterValueFromSequence(uint8_t index, uint16_t address);
// Timing data
fit::result<uint32_t, zx_status_t> GetLinesPerSecond();
// Exposure data
// Analog gain
AnalogGain analog_gain_;
zx_status_t ReadAnalogGainConstants() __TA_REQUIRES(lock_);
float AnalogRegValueToTotalGain(uint16_t);
uint16_t AnalogTotalGainToRegValue(float);
// Digital gain
DigitalGain digital_gain_;
zx_status_t ReadDigitalGainConstants() __TA_REQUIRES(lock_);
float DigitalRegValueToTotalGain(uint16_t);
uint16_t DigitalTotalGainToRegValue(float);
// Integration time
IntegrationTime integration_time_;
bool gain_constants_valid_ = false;
zx_status_t ReadGainConstants() __TA_REQUIRES(lock_);
zx_status_t SetGroupedParameterHold(bool) __TA_REQUIRES(lock_);
std::mutex lock_;
};
} // namespace camera
#endif // SRC_CAMERA_DRIVERS_SENSORS_IMX227_IMX227_H_