blob: fc8f675acb4896877998d72debd2247fa0270d30 [file]
// 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.
#define MAGMA_DLOG_ENABLE 1
#include <map>
#include <gtest/gtest.h>
#include <helper/platform_device_helper.h>
#include "src/graphics/drivers/msd-qcom-adreno/src/instructions.h"
#include "src/graphics/drivers/msd-qcom-adreno/src/msd_qcom_device.h"
namespace {
// Intercept all accesses to the register IO space and record the writes.
class TestHook : public magma::RegisterIo::Hook {
public:
void Write32(uint32_t offset, uint32_t val) override { map_[offset] = val; }
void Read32(uint32_t offset, uint32_t val) override {}
void Read64(uint32_t offset, uint64_t val) override {}
std::map<uint32_t, uint32_t> map_;
};
} // namespace
class TestQcomDevice : public ::testing::Test {
public:
void CreateAndDestroy() {
auto device = MsdQcomDevice::Create(GetTestDeviceHandle());
ASSERT_TRUE(device);
DLOG("Got chip id: 0x%x", device->GetChipId());
DLOG("Got gmem size: 0x%x", device->GetGmemSize());
uint64_t firmware_addr = device->firmware()->gpu_addr();
EXPECT_EQ(firmware_addr, MsdQcomDevice::kSystemGpuAddrBase);
DLOG("Got firmware addr: 0x%lx", firmware_addr);
uint64_t ringbuffer_addr;
EXPECT_TRUE(device->ringbuffer()->GetGpuAddress(&ringbuffer_addr));
DLOG("Got ringbuffer addr: 0x%lx", ringbuffer_addr);
}
// Contains the expected set of register writes from hardware init,
// as recorded below.
static std::vector<std::pair<uint32_t, uint32_t>> sparse_register_dump;
void HardwareInit() {
auto device = std::make_unique<MsdQcomDevice>();
EXPECT_TRUE(device->Init(GetTestDeviceHandle(), std::make_unique<TestHook>()));
auto hook = static_cast<TestHook*>(device->register_io()->hook());
EXPECT_EQ(hook->map_.size(), sparse_register_dump.size());
for (auto& pair : sparse_register_dump) {
auto iter = hook->map_.find(pair.first);
bool found = (iter != hook->map_.end());
EXPECT_TRUE(found);
if (found) {
uint32_t expected = pair.second;
uint32_t actual = iter->second;
EXPECT_EQ(expected, actual) << "Mismatch at offset 0x" << std::hex << pair.first;
}
}
// Dump list of writes
if (false) {
for (auto iter : hook->map_) {
DLOG("{ 0x%08x, 0x%08x },", iter.first, iter.second);
}
}
}
void RegisterWrite() {
auto device = std::make_unique<MsdQcomDevice>();
EXPECT_TRUE(device->Init(GetTestDeviceHandle(), nullptr));
constexpr uint32_t kScratchRegAddr = 0x00000885 << 2;
// Initialize register to something arbitrary
device->register_io()->Write32(kScratchRegAddr, 123456789);
uint32_t expected = 0xabbadada;
Packet4::write(device->ringbuffer(), kScratchRegAddr >> 2, 0xabbadada);
uint32_t tail = device->ringbuffer()->tail() / sizeof(uint32_t);
device->FlushRingbuffer(tail);
EXPECT_TRUE(device->WaitForIdleRingbuffer(tail));
EXPECT_EQ(expected, device->register_io()->Read32(kScratchRegAddr));
}
void MemoryWrite() {
auto device = std::make_unique<MsdQcomDevice>();
EXPECT_TRUE(device->Init(GetTestDeviceHandle(), nullptr));
auto buffer = std::shared_ptr<magma::PlatformBuffer>(
magma::PlatformBuffer::Create(magma::page_size(), "test"));
void* ptr;
ASSERT_TRUE(buffer->MapCpu(&ptr));
*reinterpret_cast<uint32_t*>(ptr) = 123456789;
constexpr uint32_t kScratchRegAddr = 0x00000885 << 2;
uint32_t expected = 0xabbadada;
device->register_io()->Write32(kScratchRegAddr, expected);
auto gpu_mapping = AddressSpace::MapBufferGpu(device->address_space(), buffer);
ASSERT_TRUE(gpu_mapping);
std::vector<uint32_t> packet{
kScratchRegAddr >> 2,
magma::lower_32_bits(gpu_mapping->gpu_addr()),
magma::upper_32_bits(gpu_mapping->gpu_addr()),
};
Packet7::write(device->ringbuffer(), Packet7::OpCode::CpRegisterToMemory, packet);
uint32_t tail = device->ringbuffer()->tail() / sizeof(uint32_t);
device->FlushRingbuffer(tail);
EXPECT_TRUE(device->WaitForIdleRingbuffer(tail));
uint32_t value = *reinterpret_cast<uint32_t*>(ptr);
EXPECT_EQ(expected, value);
}
};
TEST_F(TestQcomDevice, CreateAndDestroy) { TestQcomDevice::CreateAndDestroy(); }
TEST_F(TestQcomDevice, HardwareInit) { TestQcomDevice::HardwareInit(); }
TEST_F(TestQcomDevice, RegisterWrite) { TestQcomDevice::RegisterWrite(); }
TEST_F(TestQcomDevice, MemoryWrite) { TestQcomDevice::MemoryWrite(); }
std::vector<std::pair<uint32_t, uint32_t>> TestQcomDevice::sparse_register_dump = {
// { offset, value }
{0x00000040, 0x00000003}, {0x0000007c, 0x401fffff}, {0x00001400, 0x00000001},
{0x00002000, 0xfe008000}, {0x00002004, 0x00000000}, {0x00002008, 0x0800020c},
{0x0000201c, 0x00000009}, {0x00002020, 0x00000001}, {0x000020c0, 0xfe000000},
{0x000020c4, 0x00000000}, {0x0000213c, 0x00000003}, {0x00002140, 0x01440600},
{0x00002144, 0x8008ae50}, {0x00002148, 0x804c9624}, {0x0000214c, 0x80208630},
{0x00002150, 0x80049e70}, {0x00002154, 0x861c9e78}, {0x00002158, 0xa040f000},
{0x0000215c, 0x000cfc00}, {0x00002160, 0x8000050e}, {0x00002164, 0x0000050f},
{0x00002168, 0x80000510}, {0x0000216c, 0x13e40000}, {0x00002170, 0x00280501},
{0x00002174, 0x01100511}, {0x00002178, 0x80380e00}, {0x0000217c, 0x80008e00},
{0x00002180, 0x803c8e50}, {0x00002184, 0x8000be02}, {0x00002188, 0xc7ccbe20},
{0x0000218c, 0x82080800}, {0x00002190, 0x802008a0}, {0x00002194, 0x806408ab},
{0x00002198, 0x81340900}, {0x0000219c, 0x81d8098d}, {0x000021a0, 0x00100980},
{0x000021a4, 0x8000a630}, {0x00002304, 0x8040362c}, {0x00002308, 0x010000c0},
{0x0000230c, 0x00000080}, {0x00002340, 0x00000000}, {0x00002634, 0x00000001},
{0x00003804, 0x00400000}, {0x00003814, 0xffffffc0}, {0x00003818, 0x0001ffff},
{0x0000381c, 0xfffff000}, {0x00003820, 0x0001ffff}, {0x00003824, 0xfffff000},
{0x00003828, 0x0001ffff}, {0x0000382c, 0xff000000}, {0x00003830, 0x00000000},
{0x00003834, 0xff0fffff}, {0x00003838, 0x00000000}, {0x0000385c, 0x00000004},
{0x00003860, 0x00000804}, {0x00003864, 0x00000001}, {0x0000c0a8, 0x00000009},
{0x00023820, 0x00000004}, {0x00027800, 0x00180000}, {0x0002b808, 0x00000004},
{0x0002d810, 0x00000004}, {0x0003d000, 0x00000000}, {0x0003e000, 0x00000000},
{0x0003e004, 0x00000000}, {0x0003e008, 0x00000000}, {0x0003e00c, 0x00000000},
};