blob: b7486063415ccfca72757cc5c04993e4cc11c6eb [file] [log] [blame]
// 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 "tas5805.h"
#include <algorithm>
#include <memory>
#include <string.h>
#include <ddk/protocol/i2c-lib.h>
#include <ddk/protocol/i2c.h>
#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
namespace {
// clang-format off
constexpr uint8_t kRegSelectPage = 0x00;
constexpr uint8_t kRegReset = 0x01;
constexpr uint8_t kRegDeviceCtrl1 = 0x02;
constexpr uint8_t kRegDeviceCtrl2 = 0x03;
constexpr uint8_t kRegSapCtrl1 = 0x33;
constexpr uint8_t kRegDigitalVol = 0x4C;
constexpr uint8_t kRegResetBitCtrl = 0x01;
constexpr uint8_t kRegDeviceCtrl1BitsPbtlMode = 0x04;
constexpr uint8_t kRegDeviceCtrl1Bits1SpwMode = 0x01;
constexpr uint8_t kRegSapCtrl1Bits32bits = 0x03;
constexpr uint8_t kRegDeviceCtrl2BitsDeepSleep = 0x00;
constexpr uint8_t kRegDeviceCtrl2BitsPlay = 0x03;
// clang-format on
} // namespace
namespace audio {
namespace mt8167 {
std::unique_ptr<Tas5805> Tas5805::Create(ddk::I2cChannel i2c, uint32_t i2c_index) {
fbl::AllocChecker ac;
auto ptr = std::unique_ptr<Tas5805>(new (&ac) Tas5805(i2c));
if (!ac.check()) {
return nullptr;
}
return ptr;
}
zx_status_t Tas5805::Reset() {
return WriteReg(kRegReset, kRegResetBitCtrl);
}
zx_status_t Tas5805::SetGain(float gain) {
gain = std::clamp(gain, kMinGain, kMaxGain);
uint8_t gain_reg = static_cast<uint8_t>(48 - gain * 2);
zx_status_t status = WriteReg(kRegDigitalVol, gain_reg);
if (status != ZX_OK) {
return status;
}
current_gain_ = gain;
return status;
}
bool Tas5805::ValidGain(float gain) const {
return (gain <= kMaxGain) && (gain >= kMinGain);
}
zx_status_t Tas5805::Init() {
constexpr uint8_t defaults[][2] = {
{kRegSelectPage, 0x00},
{kRegDeviceCtrl1, kRegDeviceCtrl1BitsPbtlMode | kRegDeviceCtrl1Bits1SpwMode},
{kRegSapCtrl1, kRegSapCtrl1Bits32bits},
};
for (auto& i : defaults) {
zx_status_t status = WriteReg(i[0], i[1]);
if (status != ZX_OK) {
return status;
}
}
return ExitStandby();
}
zx_status_t Tas5805::Standby() {
zx_status_t status = WriteReg(kRegSelectPage, 0x00);
if (status != ZX_OK) {
return status;
}
return WriteReg(kRegDeviceCtrl2, kRegDeviceCtrl2BitsDeepSleep);
}
zx_status_t Tas5805::ExitStandby() {
zx_status_t status = WriteReg(kRegSelectPage, 0x00);
if (status != ZX_OK) {
return status;
}
return WriteReg(kRegDeviceCtrl2, kRegDeviceCtrl2BitsPlay);
}
zx_status_t Tas5805::WriteReg(uint8_t reg, uint8_t value) {
uint8_t write_buf[2];
write_buf[0] = reg;
write_buf[1] = value;
return i2c_.WriteSync(write_buf, 2);
}
} // namespace mt8167
} // namespace audio