[intel-i915] Add support for rotation
This is a revert of the revert 455cc09565a4f9018cd9921e9184d857bc5b7133
with an additional fix in DdkSuspend to fix crashing during mexec.
Test: display-test, boot with zedboot image including change
Change-Id: I55dcbd21496155357c30d5ac6a83215c642f8d9a
diff --git a/system/dev/display/intel-i915/display-device.cpp b/system/dev/display/intel-i915/display-device.cpp
index 2161727..639b211 100644
--- a/system/dev/display/intel-i915/display-device.cpp
+++ b/system/dev/display/intel-i915/display-device.cpp
@@ -10,6 +10,7 @@
#include "registers.h"
#include "registers-dpll.h"
#include "registers-transcoder.h"
+#include "tiling.h"
namespace i915 {
@@ -136,10 +137,38 @@
plane_surface.WriteTo(controller_->mmio_space());
continue;
}
+ image_t* image = &primary->image;
+
+ const fbl::unique_ptr<GttRegion>& region = controller_->GetGttRegion(image->handle);
+ region->SetRotation(primary->transform_mode, *image);
+
+ uint32_t plane_width;
+ uint32_t plane_height;
+ uint32_t stride;
+ uint32_t x_offset;
+ uint32_t y_offset;
+ if (primary->transform_mode == FRAME_TRANSFORM_IDENTITY
+ || primary->transform_mode == FRAME_TRANSFORM_ROT_180) {
+ plane_width = primary->src_frame.width;
+ plane_height = primary->src_frame.height;
+ stride = width_in_tiles(image->type, image->width, image->pixel_format);
+ x_offset = primary->src_frame.x_pos;
+ y_offset = primary->src_frame.y_pos;
+ } else {
+ uint32_t tile_height = height_in_tiles(image->type, image->height, image->pixel_format);
+ uint32_t tile_px_height = get_tile_px_height(image->type, image->pixel_format);
+ uint32_t total_height = tile_height * tile_px_height;
+
+ plane_width = primary->src_frame.height;
+ plane_height = primary->src_frame.width;
+ stride = tile_height;
+ x_offset = total_height - primary->src_frame.y_pos - primary->src_frame.height;
+ y_offset = primary->src_frame.x_pos;
+ }
auto plane_size = pipe_regs.PlaneSurfaceSize(i).FromValue(0);
- plane_size.set_width_minus_1(primary->dest_frame.width - 1);
- plane_size.set_height_minus_1(primary->dest_frame.height - 1);
+ plane_size.set_width_minus_1(plane_width - 1);
+ plane_size.set_height_minus_1(plane_height - 1);
plane_size.WriteTo(mmio_space());
auto plane_pos = pipe_regs.PlanePosition(i).FromValue(0);
@@ -148,13 +177,12 @@
plane_pos.WriteTo(mmio_space());
auto plane_offset = pipe_regs.PlaneOffset(i).FromValue(0);
- plane_offset.set_start_x(primary->src_frame.x_pos);
- plane_offset.set_start_y(primary->src_frame.y_pos);
+ plane_offset.set_start_x(x_offset);
+ plane_offset.set_start_y(y_offset);
plane_offset.WriteTo(mmio_space());
auto stride_reg = pipe_regs.PlaneSurfaceStride(i).FromValue(0);
- stride_reg.set_stride(primary->image.type,
- primary->image.width, primary->image.pixel_format);
+ stride_reg.set_stride(stride);
stride_reg.WriteTo(controller_->mmio_space());
auto plane_ctrl = pipe_regs.PlaneControl(i).ReadFrom(controller_->mmio_space());
@@ -170,10 +198,19 @@
ZX_ASSERT(primary->image.type == IMAGE_TYPE_YF_TILED);
plane_ctrl.set_tiled_surface(plane_ctrl.kTilingYF);
}
+ if (primary->transform_mode == FRAME_TRANSFORM_IDENTITY) {
+ plane_ctrl.set_plane_rotation(plane_ctrl.kIdentity);
+ } else if (primary->transform_mode == FRAME_TRANSFORM_ROT_90) {
+ plane_ctrl.set_plane_rotation(plane_ctrl.k90deg);
+ } else if (primary->transform_mode == FRAME_TRANSFORM_ROT_180) {
+ plane_ctrl.set_plane_rotation(plane_ctrl.k180deg);
+ } else {
+ ZX_ASSERT(primary->transform_mode == FRAME_TRANSFORM_ROT_270);
+ plane_ctrl.set_plane_rotation(plane_ctrl.k270deg);
+ }
plane_ctrl.WriteTo(controller_->mmio_space());
- uint32_t base_address =
- static_cast<uint32_t>(reinterpret_cast<uint64_t>(primary->image.handle));
+ uint32_t base_address = static_cast<uint32_t>(region->base());
auto plane_surface = pipe_regs.PlaneSurface(i).ReadFrom(controller_->mmio_space());
plane_surface.set_surface_base_addr(base_address >> plane_surface.kRShiftCount);
diff --git a/system/dev/display/intel-i915/gtt.cpp b/system/dev/display/intel-i915/gtt.cpp
index 4d6335c..5fcaad3 100644
--- a/system/dev/display/intel-i915/gtt.cpp
+++ b/system/dev/display/intel-i915/gtt.cpp
@@ -12,6 +12,7 @@
#include "intel-i915.h"
#include "gtt.h"
#include "macros.h"
+#include "tiling.h"
#include "registers.h"
#define PAGE_PRESENT (1 << 0)
@@ -20,9 +21,10 @@
constexpr size_t kEntriesPerPinTxn = PAGE_SIZE / sizeof(zx_paddr_t);
-inline uint64_t gen_pte_encode(uint64_t bus_addr, bool valid)
+inline uint64_t gen_pte_encode(uint64_t bus_addr)
{
- return bus_addr | (valid ? PAGE_PRESENT : 0);
+ // Make every page present so we don't have to deal with padding for framebuffers
+ return bus_addr | PAGE_PRESENT;
}
inline uint32_t get_pte_offset(uint32_t idx) {
@@ -85,7 +87,7 @@
}
// Populate the gtt with the scratch buffer.
- uint64_t pte = gen_pte_encode(scratch_buffer_paddr_, false);
+ uint64_t pte = gen_pte_encode(scratch_buffer_paddr_);
unsigned i;
for (i = 0; i < gtt_size / sizeof(uint64_t); i++) {
controller_->mmio_space()->Write<uint64_t>(get_pte_offset(i), pte);
@@ -97,8 +99,8 @@
}
zx_status_t Gtt::AllocRegion(uint32_t length, uint32_t align_pow2,
- uint32_t pte_padding, fbl::unique_ptr<GttRegion>* region_out) {
- uint32_t region_length = ROUNDUP(length, PAGE_SIZE) + (pte_padding * PAGE_SIZE);
+ fbl::unique_ptr<GttRegion>* region_out) {
+ uint32_t region_length = ROUNDUP(length, PAGE_SIZE);
fbl::AllocChecker ac;
auto r = fbl::make_unique_checked<GttRegion>(&ac, this);
if (!ac.check()) {
@@ -107,26 +109,21 @@
if (region_allocator_.GetRegion(region_length, align_pow2, r->region_) != ZX_OK) {
return ZX_ERR_NO_RESOURCES;
}
- r->pte_padding_ = pte_padding;
*region_out = fbl::move(r);
return ZX_OK;
}
-void Gtt::SetupForMexec(uintptr_t stolen_fb, uint32_t length, uint32_t pte_padding) {
+void Gtt::SetupForMexec(uintptr_t stolen_fb, uint32_t length) {
// Just clobber everything to get the bootloader framebuffer to work.
unsigned pte_idx = 0;
for (unsigned i = 0; i < ROUNDUP(length, PAGE_SIZE) / PAGE_SIZE; i++, stolen_fb += PAGE_SIZE) {
- uint64_t pte = gen_pte_encode(stolen_fb, true);
+ uint64_t pte = gen_pte_encode(stolen_fb);
controller_->mmio_space()->Write<uint64_t>(get_pte_offset(pte_idx++), pte);
}
- uint64_t padding_pte = gen_pte_encode(scratch_buffer_paddr_, true);
- for (unsigned i = 0; i < pte_padding; i++) {
- controller_->mmio_space()->Write<uint64_t>(get_pte_offset(pte_idx++), padding_pte);
- }
controller_->mmio_space()->Read<uint32_t>(get_pte_offset(pte_idx - 1)); // Posting read
}
-GttRegion::GttRegion(Gtt* gtt) : gtt_(gtt) {}
+GttRegion::GttRegion(Gtt* gtt) : gtt_(gtt), is_rotated_(false) {}
GttRegion::~GttRegion() {
ClearRegion(false);
@@ -134,7 +131,7 @@
zx_status_t GttRegion::PopulateRegion(zx_handle_t vmo, uint64_t page_offset,
uint64_t length, bool writable) {
- if ((PAGE_SIZE * pte_padding_) + length > region_->size) {
+ if (length > region_->size) {
return ZX_ERR_INVALID_ARGS;
}
if (mapped_end_ != 0) {
@@ -179,15 +176,11 @@
for (unsigned i = 0; i < actual_entries; i++) {
for (unsigned j = 0;
j < gtt_->min_contiguity_ / PAGE_SIZE && pte_idx < pte_idx_end; j++) {
- uint64_t pte = gen_pte_encode(paddrs[i] + j * PAGE_SIZE, true);
+ uint64_t pte = gen_pte_encode(paddrs[i] + j * PAGE_SIZE);
gtt_->controller_->mmio_space()->Write<uint64_t>(get_pte_offset(pte_idx++), pte);
}
}
}
- uint64_t padding_pte = gen_pte_encode(gtt_->scratch_buffer_paddr_, true);
- for (unsigned i = 0; i < pte_padding_; i++) {
- gtt_->controller_->mmio_space()->Write<uint64_t>(get_pte_offset(pte_idx++), padding_pte);
- }
gtt_->controller_->mmio_space()->Read<uint32_t>(get_pte_offset(pte_idx - 1)); // Posting read
return ZX_OK;
@@ -199,7 +192,7 @@
}
uint32_t pte_idx = static_cast<uint32_t>(region_->base / PAGE_SIZE);
- uint64_t pte = gen_pte_encode(gtt_->scratch_buffer_paddr_, false);
+ uint64_t pte = gen_pte_encode(gtt_->scratch_buffer_paddr_);
auto mmio_space = gtt_->controller_->mmio_space();
for (unsigned i = 0; i < mapped_end_ / PAGE_SIZE; i++) {
@@ -223,4 +216,47 @@
vmo_ = ZX_HANDLE_INVALID;
}
+void GttRegion::SetRotation(uint32_t rotation, const image_t& image) {
+ bool rotated = (rotation == FRAME_TRANSFORM_ROT_90 || rotation == FRAME_TRANSFORM_ROT_270);
+ if (rotated == is_rotated_) {
+ return;
+ }
+ is_rotated_ = rotated;
+ // Displaying an image with 90/270 degree rotation requires rearranging the image's
+ // GTT mapping. Since permutations are composed of disjoint cycles and because we can
+ // calculate each page's location in the new mapping, we can remap the image by shifting
+ // the GTT entries around each cycle. We use one of the ignored bits in the global GTT
+ // PTEs to keep track of whether or not entries have been rotated.
+ constexpr uint32_t kRotatedFlag = (1 << 1);
+
+ uint64_t mask = is_rotated_ ? kRotatedFlag : 0;
+ uint32_t width = width_in_tiles(image.type, image.width, image.pixel_format);
+ uint32_t height = height_in_tiles(image.type, image.height, image.pixel_format);
+
+ auto mmio_space = gtt_->controller_->mmio_space();
+ uint32_t pte_offset = static_cast<uint32_t>(base() / PAGE_SIZE);
+ for (uint32_t i = 0; i < size() / PAGE_SIZE; i++) {
+ uint64_t entry = mmio_space->Read<uint64_t>(get_pte_offset(i + pte_offset));
+ uint32_t position = i;
+ // If the entry has already been cycled into the correct place, the
+ // loop check will immediately fail.
+ while ((entry & kRotatedFlag) != mask) {
+ if (mask) {
+ uint32_t x = position % width;
+ uint32_t y = position / width;
+ position = ((x + 1) * height) - y - 1;
+ } else {
+ uint32_t x = position % height;
+ uint32_t y = position / height;
+ position = ((height - x - 1) * width) + y;
+ }
+ uint32_t dest_offset = get_pte_offset(position + pte_offset);
+
+ uint64_t next_entry = mmio_space->Read<uint64_t>(dest_offset);
+ mmio_space->Write<uint64_t>(dest_offset, entry ^ kRotatedFlag);
+ entry = next_entry;
+ }
+ }
+}
+
} // namespace i915
diff --git a/system/dev/display/intel-i915/gtt.h b/system/dev/display/intel-i915/gtt.h
index 8189a67..5c8b58d 100644
--- a/system/dev/display/intel-i915/gtt.h
+++ b/system/dev/display/intel-i915/gtt.h
@@ -4,6 +4,7 @@
#pragma once
+#include <ddk/protocol/display-controller.h>
#include <fbl/unique_ptr.h>
#include <fbl/vector.h>
#include <hwreg/mmio.h>
@@ -21,6 +22,8 @@
explicit GttRegion(Gtt* gtt);
~GttRegion();
+ void SetRotation(uint32_t rotation, const image_t& image);
+
zx_status_t PopulateRegion(zx_handle_t vmo, uint64_t page_offset,
uint64_t length, bool writable = false);
void ClearRegion(bool close_vmo);
@@ -33,12 +36,13 @@
fbl::Vector<zx::pmt> pmts_;
uint32_t mapped_end_ = 0;
- uint32_t pte_padding_;
// The region's current vmo. The region does not own the vmo handle; it
// is up to the owner of the region to determine when the vmo should be
// closed.
zx_handle_t vmo_ = ZX_HANDLE_INVALID;
+ bool is_rotated_;
+
friend class Gtt;
};
@@ -48,9 +52,8 @@
~Gtt();
zx_status_t Init(Controller* controller);
zx_status_t AllocRegion(uint32_t length,
- uint32_t align_pow2, uint32_t pte_padding,
- fbl::unique_ptr<GttRegion>* region_out);
- void SetupForMexec(uintptr_t stolen_fb, uint32_t length, uint32_t pte_padding);
+ uint32_t align_pow2, fbl::unique_ptr<GttRegion>* region_out);
+ void SetupForMexec(uintptr_t stolen_fb, uint32_t length);
uint64_t size() const { return gfx_mem_size_; }
private:
diff --git a/system/dev/display/intel-i915/intel-i915.cpp b/system/dev/display/intel-i915/intel-i915.cpp
index a9b00e1..c677512 100644
--- a/system/dev/display/intel-i915/intel-i915.cpp
+++ b/system/dev/display/intel-i915/intel-i915.cpp
@@ -35,6 +35,7 @@
#include "registers-pipe.h"
#include "registers-transcoder.h"
#include "registers.h"
+#include "tiling.h"
#define INTEL_I915_BROADWELL_DID (0x1616)
@@ -639,14 +640,20 @@
return ZX_ERR_NO_MEMORY;
}
- uint32_t length = image->height * ZX_PIXEL_FORMAT_BYTES(image->pixel_format) *
- registers::PlaneSurfaceStride::compute_pixel_stride(image->type, image->width,
- image->pixel_format);
+ uint32_t length = width_in_tiles(image->type, image->width, image->pixel_format) *
+ height_in_tiles(image->type, image->height, image->pixel_format) *
+ get_tile_byte_size(image->type);
+
+ uint32_t align;
+ if (image->type == IMAGE_TYPE_SIMPLE) {
+ align = registers::PlaneSurface::kLinearAlignment;
+ } else if (image->type == IMAGE_TYPE_X_TILED) {
+ align = registers::PlaneSurface::kXTilingAlignment;
+ } else {
+ align = registers::PlaneSurface::kYTilingAlignment;
+ }
fbl::unique_ptr<GttRegion> gtt_region;
- zx_status_t status = gtt_.AllocRegion(length,
- registers::PlaneSurface::kLinearAlignment,
- registers::PlaneSurface::kTrailingPtePadding,
- >t_region);
+ zx_status_t status = gtt_.AllocRegion(length, align, >t_region);
if (status != ZX_OK) {
return status;
}
@@ -654,10 +661,7 @@
// The vsync logic requires that images not have base == 0
if (gtt_region->base() == 0) {
fbl::unique_ptr<GttRegion> alt_gtt_region;
- zx_status_t status = gtt_.AllocRegion(length,
- registers::PlaneSurface::kLinearAlignment,
- registers::PlaneSurface::kTrailingPtePadding,
- &alt_gtt_region);
+ zx_status_t status = gtt_.AllocRegion(length, align, &alt_gtt_region);
if (status != ZX_OK) {
return status;
}
@@ -684,6 +688,16 @@
}
}
+const fbl::unique_ptr<GttRegion>& Controller::GetGttRegion(void* handle) {
+ fbl::AutoLock lock(>t_lock_);
+ for (auto& region : imported_images_) {
+ if (region->base() == reinterpret_cast<uint64_t>(handle)) {
+ return region;
+ }
+ }
+ ZX_ASSERT(false);
+}
+
bool Controller::GetLayer(registers::Pipe pipe, uint32_t plane,
const display_config_t** configs, uint32_t display_count,
const layer_t** layer_out) {
@@ -1058,11 +1072,34 @@
continue;
}
primary_layer_t* primary = &config->layers[j]->cfg.primary;
- if (primary->transform_mode != FRAME_TRANSFORM_IDENTITY) {
+ if (primary->transform_mode == FRAME_TRANSFORM_ROT_90
+ || primary->transform_mode == FRAME_TRANSFORM_ROT_270) {
+ // Linear and x tiled images don't support 90/270 rotation
+ if (primary->image.type == IMAGE_TYPE_SIMPLE
+ || primary->image.type == IMAGE_TYPE_X_TILED) {
+ layer_cfg_result[i][j] |= CLIENT_TRANSFORM;
+ }
+ } else if (primary->transform_mode != FRAME_TRANSFORM_IDENTITY
+ && primary->transform_mode != FRAME_TRANSFORM_ROT_180) {
+ // Cover unsupported rotations
layer_cfg_result[i][j] |= CLIENT_TRANSFORM;
}
- if (primary->dest_frame.width != primary->src_frame.width
- || primary->dest_frame.height != primary->src_frame.height) {
+
+ uint32_t src_width;
+ uint32_t src_height;
+ if (primary->transform_mode == FRAME_TRANSFORM_IDENTITY
+ || primary->transform_mode == FRAME_TRANSFORM_ROT_180
+ || primary->transform_mode == FRAME_TRANSFORM_REFLECT_X
+ || primary->transform_mode == FRAME_TRANSFORM_REFLECT_Y) {
+ src_width = primary->src_frame.width;
+ src_height = primary->src_frame.height;
+ } else {
+ src_width = primary->src_frame.height;
+ src_height = primary->src_frame.width;
+ }
+
+ if (primary->dest_frame.width != src_width
+ || primary->dest_frame.height != src_height) {
layer_cfg_result[i][j] |= CLIENT_FRAME_SCALE;
}
}
@@ -1141,7 +1178,8 @@
}
uint32_t Controller::ComputeLinearStride(uint32_t width, zx_pixel_format_t format) {
- return registers::PlaneSurfaceStride::compute_pixel_stride(IMAGE_TYPE_SIMPLE, width, format);
+ return fbl::round_up(width,
+ get_tile_byte_width(IMAGE_TYPE_SIMPLE, format) / ZX_PIXEL_FORMAT_BYTES(format));
}
zx_status_t Controller::AllocateVmo(uint64_t size, zx_handle_t* vmo_out) {
@@ -1218,7 +1256,7 @@
}
fbl::unique_ptr<GttRegion> region;
zx_status_t status = gtt_.AllocRegion(static_cast<uint32_t>(page_count * PAGE_SIZE),
- PAGE_SIZE, 0, ®ion);
+ PAGE_SIZE, ®ion);
if (status != ZX_OK) {
return status;
}
@@ -1311,7 +1349,7 @@
{
fbl::AutoLock lock(>t_lock_);
- gtt_.SetupForMexec(fb, fb_size, registers::PlaneSurface::kTrailingPtePadding);
+ gtt_.SetupForMexec(fb, fb_size);
}
// Try to map the framebuffer and clear it. If not, oh well.
@@ -1331,7 +1369,7 @@
registers::PipeRegs pipe_regs(display->pipe());
auto plane_stride = pipe_regs.PlaneSurfaceStride(0).ReadFrom(mmio_space_.get());
- plane_stride.set_stride(IMAGE_TYPE_SIMPLE, stride, format);
+ plane_stride.set_stride(width_in_tiles(IMAGE_TYPE_SIMPLE, width, format));
plane_stride.WriteTo(mmio_space_.get());
auto plane_surface = pipe_regs.PlaneSurface(0).ReadFrom(mmio_space_.get());
diff --git a/system/dev/display/intel-i915/intel-i915.h b/system/dev/display/intel-i915/intel-i915.h
index 1b9aae5..4f46712 100644
--- a/system/dev/display/intel-i915/intel-i915.h
+++ b/system/dev/display/intel-i915/intel-i915.h
@@ -59,6 +59,8 @@
uint32_t ComputeLinearStride(uint32_t width, zx_pixel_format_t format);
zx_status_t AllocateVmo(uint64_t size, zx_handle_t* vmo_out);
+ const fbl::unique_ptr<GttRegion>& GetGttRegion(void* handle);
+
zx_status_t ReadPciConfig16(uint16_t addr, uint16_t* value_out);
zx_status_t MapPciMmio(uint32_t pci_bar, void** addr_out, uint64_t* size_out);
zx_status_t UnmapPciMmio(uint32_t pci_bar);
diff --git a/system/dev/display/intel-i915/registers-pipe.h b/system/dev/display/intel-i915/registers-pipe.h
index d670908..f717244 100644
--- a/system/dev/display/intel-i915/registers-pipe.h
+++ b/system/dev/display/intel-i915/registers-pipe.h
@@ -46,8 +46,6 @@
static constexpr uint32_t kLinearAlignment = 256 * 1024;
static constexpr uint32_t kXTilingAlignment = 256 * 1024;
static constexpr uint32_t kYTilingAlignment = 1024 * 1024;
- static constexpr uint32_t kTrailingPtePadding = 136;
- static constexpr uint32_t kHeaderPtePaddingFor180Or270 = 136;
DEF_BIT(3, ring_flip_source);
};
@@ -69,30 +67,6 @@
static constexpr uint32_t kBaseAddr = 0x70188;
DEF_FIELD(9, 0, stride);
-
- void set_stride(uint32_t tiling, uint32_t width, zx_pixel_format_t format) {
- uint32_t chunk_size = get_chunk_size(tiling, format);
- set_stride(fbl::round_up(width * ZX_PIXEL_FORMAT_BYTES(format), chunk_size) / chunk_size);
- }
-
- static uint32_t compute_pixel_stride(uint32_t tiling, uint32_t width,
- zx_pixel_format_t format) {
- uint32_t chunk_size = get_chunk_size(tiling, format);
- return fbl::round_up(width, chunk_size / ZX_PIXEL_FORMAT_BYTES(format));
- }
-
-private:
- static uint32_t get_chunk_size(uint32_t tiling, zx_pixel_format_t format) {
- switch (tiling) {
- case IMAGE_TYPE_SIMPLE: return 64;
- case IMAGE_TYPE_X_TILED: return 512;
- case IMAGE_TYPE_Y_LEGACY_TILED: return 128;
- case IMAGE_TYPE_YF_TILED: return ZX_PIXEL_FORMAT_BYTES(format) == 1 ? 64 : 128;
- default:
- ZX_ASSERT(false);
- return 0;
- }
- }
};
// PLANE_SIZE
@@ -138,6 +112,10 @@
DEF_FIELD(5, 4, alpha_mode);
DEF_BIT(3, allow_double_buffer_update_disable);
DEF_FIELD(1, 0, plane_rotation);
+ static constexpr uint32_t kIdentity = 0;
+ static constexpr uint32_t k90deg = 1;
+ static constexpr uint32_t k180deg = 2;
+ static constexpr uint32_t k270deg = 3;
};
// PLANE_BUF_CFG
diff --git a/system/dev/display/intel-i915/tiling.h b/system/dev/display/intel-i915/tiling.h
new file mode 100644
index 0000000..1e31cbb
--- /dev/null
+++ b/system/dev/display/intel-i915/tiling.h
@@ -0,0 +1,48 @@
+// 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.
+
+#pragma once
+
+#include <assert.h>
+#include <ddk/protocol/intel-gpu-core.h>
+#include <fbl/algorithm.h>
+#include <inttypes.h>
+#include <zircon/pixelformat.h>
+#include <zircon/device/display-controller.h>
+
+namespace i915 {
+
+static inline uint32_t get_tile_byte_width(uint32_t tiling, zx_pixel_format_t format) {
+ switch (tiling) {
+ case IMAGE_TYPE_SIMPLE: return 64;
+ case IMAGE_TYPE_X_TILED: return 512;
+ case IMAGE_TYPE_Y_LEGACY_TILED: return 128;
+ case IMAGE_TYPE_YF_TILED: return ZX_PIXEL_FORMAT_BYTES(format) == 1 ? 64 : 128;
+ default:
+ assert(false);
+ return 0;
+ }
+}
+
+static inline uint32_t get_tile_byte_size(uint32_t tiling) {
+ return tiling == IMAGE_TYPE_SIMPLE ? 64 : 4096;
+}
+
+static inline uint32_t get_tile_px_height(uint32_t tiling, zx_pixel_format_t format) {
+ return get_tile_byte_size(tiling) / get_tile_byte_width(tiling, format);
+}
+
+static inline uint32_t width_in_tiles(uint32_t tiling, uint32_t width,
+ zx_pixel_format_t format) {
+ uint32_t tile_width = get_tile_byte_width(tiling, format);
+ return ((width * ZX_PIXEL_FORMAT_BYTES(format))+ tile_width - 1) / tile_width;
+}
+
+static inline uint32_t height_in_tiles(uint32_t tiling, uint32_t height,
+ zx_pixel_format_t format) {
+ uint32_t tile_height = get_tile_px_height(tiling, format);
+ return (height + tile_height - 1) / tile_height;
+}
+
+} // namespace i915
diff --git a/system/fidl/display/display-controller.fidl b/system/fidl/display/display-controller.fidl
index dba28df..ebd432b 100644
--- a/system/fidl/display/display-controller.fidl
+++ b/system/fidl/display/display-controller.fidl
@@ -98,8 +98,9 @@
};
enum ConfigError : uint8 {
+ OK = 0;
// The requested layer configuration is invalid.
- INVALID_CONFIG = 0;
+ INVALID_CONFIG = 1;
};
struct ConfigResult {