| // 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 "arm-isp.h" |
| #include "arm-isp-regs.h" |
| #include <ddk/binding.h> |
| #include <ddk/debug.h> |
| #include <ddk/metadata.h> |
| #include <fbl/alloc_checker.h> |
| #include <fbl/auto_call.h> |
| #include <fbl/unique_ptr.h> |
| #include <hw/reg.h> |
| #include <memory> |
| #include <stdlib.h> |
| #include <threads.h> |
| #include <unistd.h> |
| #include <zircon/types.h> |
| |
| namespace camera { |
| |
| namespace { |
| |
| constexpr uint32_t kHiu = 0; |
| constexpr uint32_t kPowerDomain = 1; |
| constexpr uint32_t kMemoryDomain = 2; |
| constexpr uint32_t kReset = 3; |
| |
| } // namespace |
| |
| void ArmIspDevice::IspHWReset(bool reset) { |
| if (reset) { |
| reset_mmio_->ClearBits32(1 << 1, RESET4_LEVEL); |
| } else { |
| reset_mmio_->SetBits32(1 << 1, RESET4_LEVEL); |
| } |
| } |
| |
| void ArmIspDevice::PowerUpIsp() { |
| // set bit[18-19]=0 |
| power_mmio_->ClearBits32(1 << 18 | 1 << 19, AO_RTI_GEN_PWR_SLEEP0); |
| zx_nanosleep(zx_deadline_after(ZX_MSEC(5))); |
| |
| // set bit[18-19]=0 |
| power_mmio_->ClearBits32(1 << 18 | 1 << 19, AO_RTI_GEN_PWR_ISO0); |
| |
| // MEM_PD_REG0 set 0 |
| memory_pd_mmio_->Write32(0, HHI_ISP_MEM_PD_REG0); |
| // MEM_PD_REG1 set 0 |
| memory_pd_mmio_->Write32(0, HHI_ISP_MEM_PD_REG1); |
| |
| // Refer to reference source code |
| hiu_mmio_->Write32(0x5b446585, HHI_CSI_PHY_CNTL0); |
| hiu_mmio_->Write32(0x803f4321, HHI_CSI_PHY_CNTL1); |
| } |
| |
| zx_status_t ArmIspDevice::InitIsp() { |
| // The ISP and MIPI module is in same power domain. |
| // So if we don't call the power sequence of ISP, the mipi module |
| // won't work and it will block accesses to the mipi register block. |
| PowerUpIsp(); |
| |
| IspHWReset(true); |
| |
| // TODO(braval@): Interrupt Init() |
| |
| IspHWReset(false); |
| |
| return ZX_OK; |
| } |
| |
| zx_status_t ArmIspDevice::InitPdev(zx_device_t* parent) { |
| if (!pdev_.is_valid()) { |
| return ZX_ERR_NO_RESOURCES; |
| } |
| |
| zx_status_t status = pdev_.MapMmio(kHiu, &hiu_mmio_); |
| if (status != ZX_OK) { |
| zxlogf(ERROR, "%s: pdev_.MapMmio failed %d\n", __func__, status); |
| return status; |
| } |
| |
| status = pdev_.MapMmio(kPowerDomain, &power_mmio_); |
| if (status != ZX_OK) { |
| zxlogf(ERROR, "%s: pdev_.MapMmio failed %d\n", __func__, status); |
| return status; |
| } |
| |
| status = pdev_.MapMmio(kMemoryDomain, &memory_pd_mmio_); |
| if (status != ZX_OK) { |
| zxlogf(ERROR, "%s: pdev_.MapMmio failed %d\n", __func__, status); |
| return status; |
| } |
| |
| status = pdev_.MapMmio(kReset, &reset_mmio_); |
| if (status != ZX_OK) { |
| zxlogf(ERROR, "%s: pdev_.MapMmio failed %d\n", __func__, status); |
| return status; |
| } |
| |
| return status; |
| } |
| |
| // static |
| zx_status_t ArmIspDevice::Create(zx_device_t* parent) { |
| fbl::AllocChecker ac; |
| auto isp_device = std::unique_ptr<ArmIspDevice>(new (&ac) ArmIspDevice(parent)); |
| if (!ac.check()) { |
| return ZX_ERR_NO_MEMORY; |
| } |
| |
| zx_status_t status = isp_device->InitPdev(parent); |
| if (status != ZX_OK) { |
| return status; |
| } |
| |
| status = isp_device->DdkAdd("arm-isp"); |
| if (status != ZX_OK) { |
| zxlogf(ERROR, "arm-isp: Could not create arm-isp device: %d\n", status); |
| return status; |
| } else { |
| zxlogf(INFO, "arm-isp: Added arm-isp device\n"); |
| } |
| |
| // isp_device intentionally leaked as it is now held by DevMgr. |
| __UNUSED auto ptr = isp_device.release(); |
| |
| return status; |
| } |
| |
| ArmIspDevice::~ArmIspDevice() { |
| } |
| |
| void ArmIspDevice::DdkUnbind() { |
| ShutDown(); |
| DdkRemove(); |
| } |
| |
| void ArmIspDevice::DdkRelease() { |
| delete this; |
| } |
| |
| void ArmIspDevice::ShutDown() { |
| } |
| |
| } // namespace camera |