diff --git a/hw/display/apple_displaypipe_v2.c b/hw/display/apple_displaypipe_v2.c index 565b94ea73..52da9ed139 100644 --- a/hw/display/apple_displaypipe_v2.c +++ b/hw/display/apple_displaypipe_v2.c @@ -26,7 +26,6 @@ #include "hw/qdev-properties.h" #include "hw/resettable.h" #include "qemu/error-report.h" -#include "qemu/log.h" #include "qom/object.h" #include "sysemu/dma.h" #include "ui/console.h" @@ -36,8 +35,7 @@ // #define DEBUG_DISP #ifdef DEBUG_DISP -#define DISP_DBGLOG(fmt, ...) \ - qemu_log_mask(LOG_GUEST_ERROR, fmt "\n", __VA_ARGS__) +#define DISP_DBGLOG(fmt, ...) info_report(fmt, __VA_ARGS__) #else #define DISP_DBGLOG(fmt, ...) \ do { \ @@ -45,7 +43,7 @@ #endif /** - * Block bases + * Block Bases (DisplayTarget5) * 0x40000 | Control * 0x48000 | Vertical Frame Timing Generator * 0x50000 | Generic Pipe 0 @@ -58,69 +56,69 @@ * 0x84000 | Content Dependent Frame Duration * 0x88000 | SPLR (Sub-Pixel Layout R?) * 0x90000 | Burn-In Compensation Sampler - * 0xA0000 | PDC - * 0xB0000 | PCC - * 0xF0000 | DBM + * 0xA0000 | PDC (Panel D? Correction?) + * 0xB0000 | PCC (Pixel Color Correction?) + * 0xF0000 | DBM (Dynamic Backlight Modulation?) */ -#define REG_CONTROL_INT_FILTER 0x45818 -#define CONTROL_INT_FILTER_MODE_CHANGED BIT(1) -#define CONTROL_INT_FILTER_DISP_UNDERRUN BIT(3) -#define CONTROL_INT_FILTER_VBLANK BIT(10) // "Swap Done" -#define CONTROL_INT_FILTER_SUB_FRAME_OVERFLOW BIT(11) -#define CONTROL_INT_FILTER_M3 BIT(13) -#define CONTROL_INT_FILTER_PCC BIT(17) -#define CONTROL_INT_FILTER_VSYNC BIT(19) // "Start accumulating" -#define CONTROL_INT_FILTER_FRAME_DONE BIT(20) // "Frame Processed" -#define CONTROL_INT_FILTER_AXI_READ_ERR BIT(30) -#define CONTROL_INT_FILTER_AXI_WRITE_ERR BIT(31) -#define REG_CONTROL_VERSION 0x46020 -#define CONTROL_VERSION_A0 0x70044 -#define CONTROL_VERSION_A1 0x70045 -#define REG_CONTROL_FRAME_SIZE 0x4603C -#define REG_CONTROL_CONFIG 0x46040 -#define REG_CONTROL_OUT_FIFO_CLK_GATE 0x46074 -#define REG_CONTROL_OUT_FIFO_DEPTH 0x46084 -#define REG_CONTROL_COMPRESSION_CFG 0x460E0 -#define REG_CONTROL_BACKPRESSURE 0x46120 -#define REG_CONTROL_POWER_GATE_CTRL 0x46158 -#define REG_CONTROL_BIS_UPDATE_INTERVAL 0x46198 -#define REG_CONTROL_MIN_BANDWIDTH_RATE 0x461C0 -#define REG_CONTROL_BANDWIDTH_RATE_SCALE_FACTOR 0x461C4 -#define REG_CONTROL_PIO_DMA_BANDWIDTH_RATE 0x461C8 -#define REG_CONTROL_REPLAY_DMA_BANDWIDTH_RATE 0x461CC -#define REG_CONTROL_GATE_CONTROL 0x461D0 -#define REG_CONTROL_READ_LINK_GATE_METRIC 0x461D4 -#define REG_CONTROL_READ_LTR_CONFIG 0x461D8 -#define REG_CONTROL_LTR_TIMER 0x461DC -#define REG_CONTROL_WRITE_LTR_CONFIG 0x461E0 - -#define GP_BLOCK_BASE 0x50000 -#define REG_GP_REG_SIZE 0x08000 -#define REG_GP_CONFIG_CONTROL 0x00004 +#define REG_CONTROL_INT_STATUS (0x45818) +#define CONTROL_INT_STATUS_MODE_CHANGED BIT(1) +#define CONTROL_INT_STATUS_DISP_UNDERRUN BIT(3) +#define CONTROL_INT_STATUS_VBLANK BIT(10) // "Swap Done" +#define CONTROL_INT_STATUS_SUB_FRAME_OVERFLOW BIT(11) +#define CONTROL_INT_STATUS_M3 BIT(13) +#define CONTROL_INT_STATUS_PCC BIT(17) +// #define CONTROL_INT_STATUS_?? BIT(19) // "Start accumulating" +// #define CONTROL_INT_STATUS_?? BIT(20) // "Frame Processed" +#define CONTROL_INT_STATUS_AXI_READ_ERR BIT(30) +#define CONTROL_INT_STATUS_AXI_WRITE_ERR BIT(31) +#define REG_CONTROL_VERSION (0x46020) +#define CONTROL_VERSION_A0 (0x70044) +#define CONTROL_VERSION_A1 (0x70045) +#define REG_CONTROL_FRAME_SIZE (0x4603C) +#define REG_CONTROL_CONFIG (0x46040) +#define REG_CONTROL_OUT_FIFO_CLK_GATE (0x46074) +#define REG_CONTROL_OUT_FIFO_DEPTH (0x46084) +#define REG_CONTROL_COMPRESSION_CFG (0x460E0) +#define REG_CONTROL_BACKPRESSURE (0x46120) +#define REG_CONTROL_POWER_GATE_CTRL (0x46158) +#define REG_CONTROL_BIS_UPDATE_INTERVAL (0x46198) +#define REG_CONTROL_MIN_BANDWIDTH_RATE (0x461C0) +#define REG_CONTROL_BANDWIDTH_RATE_SCALE_FACTOR (0x461C4) +#define REG_CONTROL_PIO_DMA_BANDWIDTH_RATE (0x461C8) +#define REG_CONTROL_REPLAY_DMA_BANDWIDTH_RATE (0x461CC) +#define REG_CONTROL_GATE_CONTROL (0x461D0) +#define REG_CONTROL_READ_LINK_GATE_METRIC (0x461D4) +#define REG_CONTROL_READ_LTR_CONFIG (0x461D8) +#define REG_CONTROL_LTR_TIMER (0x461DC) +#define REG_CONTROL_WRITE_LTR_CONFIG (0x461E0) + +#define GP_BLOCK_BASE (0x50000) +#define REG_GP_REG_SIZE (0x08000) +#define REG_GP_CONFIG_CONTROL (0x00004) #define GP_CONFIG_CONTROL_RUN BIT(0) #define GP_CONFIG_CONTROL_USE_DMA BIT(18) #define GP_CONFIG_CONTROL_HDR BIT(24) #define GP_CONFIG_CONTROL_ENABLED BIT(31) -#define REG_GP_PIXEL_FORMAT 0x0001C -#define GP_PIXEL_FORMAT_BGRA ((BIT(4) << 22) | BIT(24) | BIT(13)) -#define GP_PIXEL_FORMAT_BGRA_MASK ((BIT(4) << 22) | BIT(24) | 3 << 13) +#define REG_GP_PIXEL_FORMAT (0x0001C) +#define GP_PIXEL_FORMAT_BGRA ((BIT(4) << 22) | BIT(24) | (3 << 13)) #define GP_PIXEL_FORMAT_ARGB ((BIT(4) << 22) | BIT(24)) #define GP_PIXEL_FORMAT_COMPRESSED BIT(30) -#define REG_GP_LAYER_0_START 0x00030 -#define REG_GP_LAYER_1_START 0x00034 -#define REG_GP_LAYER_0_END 0x00040 -#define REG_GP_LAYER_1_END 0x00044 -#define REG_GP_LAYER_0_STRIDE 0x00060 -#define REG_GP_LAYER_1_STRIDE 0x00064 -#define REG_GP_LAYER_0_SIZE 0x00070 -#define REG_GP_LAYER_1_SIZE 0x00074 -#define REG_GP_FRAME_SIZE 0x00080 -#define REG_GP_CRC 0x00160 -#define REG_GP_BANDWIDTH_RATE 0x00170 -#define REG_GP_STATUS 0x00184 +#define REG_GP_BASE (0x00030) +#define REG_GP_END (0x00040) +#define REG_GP_STRIDE (0x00060) +#define REG_GP_SIZE (0x00070) +#define REG_GP_FRAME_SIZE (0x00080) +#define REG_GP_CRC (0x00160) +#define REG_GP_BANDWIDTH_RATE (0x00170) +#define REG_GP_STATUS (0x00184) #define GP_STATUS_DECOMPRESSION_FAIL BIT(0) +static void apple_disp_update_irqs(AppleDisplayPipeV2State *s) +{ + qemu_set_irq(s->irqs[0], (s->int_status & CONTROL_INT_STATUS_VBLANK) != 0); +} + #define GP_BLOCK_BASE_FOR(i) (GP_BLOCK_BASE + i * REG_GP_REG_SIZE) #define GP_BLOCK_END_FOR(i) (GP_BLOCK_BASE_FOR(i) + (REG_GP_REG_SIZE - 1)) @@ -141,38 +139,35 @@ static void apple_disp_gp_reg_write(GenPipeState *s, hwaddr addr, uint64_t data) s->pixel_format = (uint32_t)data; break; } - case REG_GP_LAYER_0_START: { - DISP_DBGLOG("[GP%zu] Layer 0 start <- 0x" HWADDR_FMT_plx, s->index, - data); - s->layers[0].start = (uint32_t)data; + case REG_GP_BASE: { + DISP_DBGLOG("[GP%zu] Base <- 0x" HWADDR_FMT_plx, s->index, data); + s->base = (uint32_t)data; break; } - case REG_GP_LAYER_0_END: { - DISP_DBGLOG("[GP%zu] Layer 0 end <- 0x" HWADDR_FMT_plx, s->index, data); - s->layers[0].end = (uint32_t)data; + case REG_GP_END: { + DISP_DBGLOG("[GP%zu] End <- 0x" HWADDR_FMT_plx, s->index, data); + s->end = (uint32_t)data; break; } - case REG_GP_LAYER_0_STRIDE: { - DISP_DBGLOG("[GP%zu] Layer 0 stride <- 0x" HWADDR_FMT_plx, s->index, - data); - s->layers[0].stride = (uint32_t)data; + case REG_GP_STRIDE: { + DISP_DBGLOG("[GP%zu] Stride <- 0x" HWADDR_FMT_plx, s->index, data); + s->stride = (uint32_t)data; break; } - case REG_GP_LAYER_0_SIZE: { - DISP_DBGLOG("[GP%zu] Layer 0 size <- 0x" HWADDR_FMT_plx, s->index, - data); - s->layers[0].size = (uint32_t)data; + case REG_GP_SIZE: { + DISP_DBGLOG("[GP%zu] Size <- 0x" HWADDR_FMT_plx, s->index, data); + s->size = (uint32_t)data; break; } case REG_GP_FRAME_SIZE: { - DISP_DBGLOG("[GP%zu] Frame size <- 0x" HWADDR_FMT_plx, s->index, data); + DISP_DBGLOG("[GP%zu] Frame Size <- 0x" HWADDR_FMT_plx, s->index, data); s->height = data & 0xFFFF; s->width = (data >> 16) & 0xFFFF; break; } default: { - DISP_DBGLOG("[GP%zu] Unknown write @ 0x" HWADDR_FMT_plx - " value: 0x" HWADDR_FMT_plx, + DISP_DBGLOG("[GP%zu] Unknown @ 0x" HWADDR_FMT_plx + " <- 0x" HWADDR_FMT_plx, s->index, addr, data); break; } @@ -190,124 +185,119 @@ static uint32_t apple_disp_gp_reg_read(GenPipeState *s, hwaddr addr) DISP_DBGLOG("[GP%zu] Pixel format -> 0x%x", s->index, s->pixel_format); return s->pixel_format; } - case REG_GP_LAYER_0_START: { - DISP_DBGLOG("[GP%zu] Layer 0 start -> 0x%x", s->index, - s->layers[0].start); - return s->layers[0].start; + case REG_GP_BASE: { + DISP_DBGLOG("[GP%zu] Base -> 0x%x", s->index, s->base); + return s->base; } - case REG_GP_LAYER_0_END: { - DISP_DBGLOG("[GP%zu] Layer 0 end -> 0x%x", s->index, s->layers[0].end); - return s->layers[0].end; + case REG_GP_END: { + DISP_DBGLOG("[GP%zu] End -> 0x%x", s->index, s->end); + return s->end; } - case REG_GP_LAYER_0_STRIDE: { - DISP_DBGLOG("[GP%zu] Layer 0 stride -> 0x%x", s->index, - s->layers[0].stride); - return s->layers[0].stride; + case REG_GP_STRIDE: { + DISP_DBGLOG("[GP%zu] Stride -> 0x%x", s->index, s->stride); + return s->stride; } - case REG_GP_LAYER_0_SIZE: { - DISP_DBGLOG("[GP%zu] Layer 0 size -> 0x%x", s->index, - s->layers[0].size); - return s->layers[0].size; + case REG_GP_SIZE: { + DISP_DBGLOG("[GP%zu] Size -> 0x%x", s->index, s->size); + return s->size; } case REG_GP_FRAME_SIZE: { - DISP_DBGLOG("[GP%zu] Frame size -> 0x%x (width: %d height: %d)", + DISP_DBGLOG("[GP%zu] Frame Size -> 0x%x (width: %d height: %d)", s->index, (s->width << 16) | s->height, s->width, s->height); return (s->width << 16) | s->height; } default: { - DISP_DBGLOG("[GP%zu] Unknown read @ 0x" HWADDR_FMT_plx, s->index, addr); + DISP_DBGLOG("[GP%zu] Unknown @ 0x" HWADDR_FMT_plx " -> " HWADDR_FMT_plx, + s->index, addr, (hwaddr)0); return 0; } } } -static uint8_t *apple_disp_gp_read_layer(GenPipeState *s, size_t i, - AddressSpace *dma_as, size_t *size_out) +static void apple_gp_draw_bh(void *opaque) { - size_t size; + GenPipeState *s; + pixman_format_code_t src_fmt; uint8_t *buf; - *size_out = 0; - - if (!s->layers[i].start || !s->layers[i].end) { - return NULL; - } + s = (GenPipeState *)opaque; - size = s->layers[i].end - s->layers[i].start; - buf = g_malloc(size); + uint16_t height = s->size & 0xFFFF; + uint16_t width = (s->size >> 16) & 0xFFFF; - if (dma_memory_read(dma_as, s->layers[i].start, buf, size, - MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { - g_free(buf); - return NULL; + // TODO: Decompress the data and display it properly. + if (s->pixel_format & GP_PIXEL_FORMAT_COMPRESSED) { + error_report("[GP%zu] Dropping frame as it's compressed.", s->index); + return; } - *size_out = size; - return buf; -} + DISP_DBGLOG("[GP%zu] Width and height is %dx%d.", s->index, width, height); + DISP_DBGLOG("[GP%zu] Stride is %d.", s->index, s->stride); -static void apple_gp_draw_bh(void *opaque) -{ - GenPipeState *s; - size_t size; - uint8_t *buf; - - s = (GenPipeState *)opaque; - size = 0; - buf = apple_disp_gp_read_layer(s, 0, s->dma_as, &size); + if (height == 0 || width == 0 || s->stride == 0) { + error_report( + "[GP%zu] Dropping frame as width, height or stride is zero.", + s->index); + return; + } - if (buf == NULL) { + if (width > s->disp_width || height > s->disp_height) { + error_report("[GP%zu] Dropping frame as it's larger than the screen.", + s->index); return; } - // TODO: Blend both layers. 2nd layer is currently not used. - uint16_t height = s->layers[0].size & 0xFFFF; - uint16_t width = (s->layers[0].size >> 16) & 0xFFFF; - DISP_DBGLOG("[GP%zu] Layer 0 width and height is %dx%d.", s->index, width, - height); - DISP_DBGLOG("[GP%zu] Layer 0 stride is %d.", s->index, s->layers[0].stride); - if ((s->pixel_format & GP_PIXEL_FORMAT_BGRA_MASK) == - GP_PIXEL_FORMAT_BGRA_MASK) { + if ((s->pixel_format & GP_PIXEL_FORMAT_BGRA) == GP_PIXEL_FORMAT_BGRA) { DISP_DBGLOG("[GP%zu] Pixel Format is BGRA (0x%X).", s->index, s->pixel_format); + src_fmt = PIXMAN_b8g8r8a8; } else if ((s->pixel_format & GP_PIXEL_FORMAT_ARGB) == GP_PIXEL_FORMAT_ARGB) { DISP_DBGLOG("[GP%zu] Pixel Format is ARGB (0x%X).", s->index, s->pixel_format); + src_fmt = PIXMAN_a8r8g8b8; } else { - DISP_DBGLOG("[GP%zu] Pixel Format is unknown (0x%X).", s->index, - s->pixel_format); - } - // TODO: Decompress the data and display it properly. - if (s->pixel_format & GP_PIXEL_FORMAT_COMPRESSED) { - error_report("[GP%zu] Dropping frame, because it is compressed.", - s->index); + error_report("[GP%zu] Pixel Format is unknown (0x%X).", s->index, + s->pixel_format); return; } - for (uint16_t y = 0; y < height; y++) { - uint8_t *dest = memory_region_get_ram_ptr(s->vram); - memcpy(dest + (y * (s->disp_state->width * sizeof(uint32_t))), - buf + (y * s->layers[0].stride), width * sizeof(uint32_t)); + + buf = g_malloc(height * width * s->stride); + if (dma_memory_read(s->dma_as, s->base, buf, s->end - s->base, + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { + error_report("[GP%zu] Failed to read from DMA.", s->index); + g_free(buf); + return; } - memory_region_set_dirty(s->vram, 0, - s->height * s->width * sizeof(uint32_t)); + + // TODO: Where is the destination X and Y? + pixman_image_t *image = pixman_image_create_bits( + src_fmt, width, height, (uint32_t *)buf, s->stride); + pixman_image_composite32(PIXMAN_OP_OVER, image, NULL, s->disp_image, 0, 0, + 0, 0, 0, 0, width, height); + pixman_image_unref(image); g_free(buf); - s->disp_state->int_filter |= CONTROL_INT_FILTER_FRAME_DONE; - qemu_irq_raise(s->disp_state->irqs[2 + s->index]); + memory_region_set_dirty(s->vram, 0, height * s->width * sizeof(uint32_t)); } -static bool apple_genpipev2_init(GenPipeState *s, size_t index, +static void apple_genpipev2_init(GenPipeState *s, size_t index, MemoryRegion *vram, AddressSpace *dma_as, - AppleDisplayPipeV2State *disp_state) + pixman_image_t *disp_image, + uint16_t disp_width, uint16_t disp_height) { + if (s->bh != NULL) { + qemu_bh_delete(s->bh); + } + memset(s, 0, sizeof(*s)); s->index = index; s->vram = vram; s->dma_as = dma_as; s->bh = qemu_bh_new(apple_gp_draw_bh, s); - s->disp_state = disp_state; - return true; + s->disp_image = disp_image; + s->disp_width = disp_width; + s->disp_height = disp_height; } static void apple_disp_reg_write(void *opaque, hwaddr addr, uint64_t data, @@ -325,26 +315,16 @@ static void apple_disp_reg_write(void *opaque, hwaddr addr, uint64_t data, case GP_BLOCK_BASE_FOR(0)... GP_BLOCK_END_FOR(0): apple_disp_gp_reg_write(&s->genpipes[0], addr, data); break; - case GP_BLOCK_BASE_FOR(1)... GP_BLOCK_END_FOR(1): apple_disp_gp_reg_write(&s->genpipes[1], addr, data); break; - - case REG_CONTROL_INT_FILTER: - s->int_filter &= ~(uint32_t)data; - if ((s->int_filter & - (CONTROL_INT_FILTER_VBLANK | CONTROL_INT_FILTER_VSYNC)) == 0) { - qemu_irq_lower(s->irqs[0]); - } - if ((s->int_filter & CONTROL_INT_FILTER_FRAME_DONE) == 0) { - qemu_irq_lower(s->irqs[2]); - qemu_irq_lower(s->irqs[3]); - } + case REG_CONTROL_INT_STATUS: + s->int_status &= ~(uint32_t)data; + apple_disp_update_irqs(s); break; - default: - DISP_DBGLOG("[disp] Unknown write @ 0x" HWADDR_FMT_plx - " value: 0x" HWADDR_FMT_plx, + DISP_DBGLOG("[disp] Unknown @ 0x" HWADDR_FMT_plx + " <- 0x" HWADDR_FMT_plx, addr, data); break; } @@ -376,9 +356,9 @@ static uint64_t apple_disp_reg_read(void *opaque, hwaddr addr, DISP_DBGLOG("[disp] Frame Size -> 0x%x", (s->width << 16) | s->height); return (s->width << 16) | s->height; } - case REG_CONTROL_INT_FILTER: { - DISP_DBGLOG("[disp] Int Filter -> 0x%x", s->int_filter); - return s->int_filter; + case REG_CONTROL_INT_STATUS: { + DISP_DBGLOG("[disp] Int Status -> 0x%x", s->int_status); + return s->int_status; } default: DISP_DBGLOG("[disp] Unknown read @ 0x" HWADDR_FMT_plx, addr); @@ -400,20 +380,6 @@ static const MemoryRegionOps apple_disp_v2_reg_ops = { static uint32_t disp_timing_info[] = { 0x33C, 0x90, 0x1, 0x1, 0x700, 0x1, 0x1, 0x1 }; -static void vblank_timer_tick(void *opaque) -{ - AppleDisplayPipeV2State *s; - - s = APPLE_DISPLAYPIPE_V2(opaque); - - s->int_filter |= CONTROL_INT_FILTER_VBLANK; - qemu_irq_raise(s->irqs[0]); - - timer_mod(s->vblank_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - NANOSECONDS_PER_SECOND / s->refresh_rate * 1000); -} - AppleDisplayPipeV2State *apple_displaypipe_v2_create(DTBNode *node) { DeviceState *dev; @@ -446,8 +412,6 @@ AppleDisplayPipeV2State *apple_displaypipe_v2_create(DTBNode *node) sysbus_init_irq(sbd, &s->irqs[i]); } - s->vblank_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, vblank_timer_tick, s); - return s; } @@ -474,9 +438,6 @@ static void apple_displaypipe_v2_gfx_update(void *opaque) AppleDisplayPipeV2State *s = APPLE_DISPLAYPIPE_V2(opaque); DisplaySurface *surface = qemu_console_surface(s->console); - s->int_filter |= CONTROL_INT_FILTER_VSYNC; - qemu_irq_raise(s->irqs[0]); - int stride = s->width * sizeof(uint32_t); int first = 0, last = 0; @@ -492,27 +453,14 @@ static void apple_displaypipe_v2_gfx_update(void *opaque) if (first >= 0) { dpy_gfx_update(s->console, 0, first, s->width, last - first + 1); } -} - -// TODO: Width/Height changes? Is that even possible? -static void apple_displaypipe_v2_ui_info(void *opaque, uint32_t head, - QemuUIInfo *info) -{ - AppleDisplayPipeV2State *s; - - if (!info->width || !info->height || !info->refresh_rate) { - return; - } - - s = APPLE_DISPLAYPIPE_V2(opaque); - s->refresh_rate = info->refresh_rate; + s->int_status |= CONTROL_INT_STATUS_VBLANK; + apple_disp_update_irqs(s); } static const GraphicHwOps apple_displaypipe_v2_ops = { .invalidate = apple_displaypipe_v2_invalidate, .gfx_update = apple_displaypipe_v2_gfx_update, - .ui_info = apple_displaypipe_v2_ui_info, }; static void apple_displaypipe_v2_reset_hold(Object *obj, ResetType type) @@ -520,12 +468,20 @@ static void apple_displaypipe_v2_reset_hold(Object *obj, ResetType type) AppleDisplayPipeV2State *s = APPLE_DISPLAYPIPE_V2(obj); s->invalidated = true; - s->int_filter = 0; - qemu_irq_lower(s->irqs[0]); - qemu_irq_lower(s->irqs[2]); - qemu_irq_lower(s->irqs[3]); - apple_genpipev2_init(&s->genpipes[0], 0, &s->vram, &s->dma_as, s); - apple_genpipev2_init(&s->genpipes[1], 1, &s->vram, &s->dma_as, s); + + s->int_status = 0; + apple_disp_update_irqs(s); + + qemu_pixman_image_unref(s->disp_image); + s->disp_image = pixman_image_create_bits( + PIXMAN_a8r8g8b8, s->width, s->height, + (uint32_t *)memory_region_get_ram_ptr(&s->vram), + s->width * sizeof(uint32_t)); + + apple_genpipev2_init(&s->genpipes[0], 0, &s->vram, &s->dma_as, + s->disp_image, s->width, s->height); + apple_genpipev2_init(&s->genpipes[1], 1, &s->vram, &s->dma_as, + s->disp_image, s->width, s->height); memset(memory_region_get_ram_ptr(&s->vram), 0, memory_region_size(&s->vram)); @@ -538,17 +494,11 @@ static void apple_displaypipe_v2_realize(DeviceState *dev, Error **errp) s->console = graphic_console_init(dev, 0, &apple_displaypipe_v2_ops, s); qemu_console_resize(s->console, s->width, s->height); - - timer_mod(s->vblank_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - NANOSECONDS_PER_SECOND / s->refresh_rate * 1000); } static Property apple_displaypipe_v2_props[] = { DEFINE_PROP_UINT32("width", AppleDisplayPipeV2State, width, 828), DEFINE_PROP_UINT32("height", AppleDisplayPipeV2State, height, 1792), - DEFINE_PROP_UINT32("refresh-rate", AppleDisplayPipeV2State, refresh_rate, - 60000), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/display/apple_displaypipe_v2.h b/include/hw/display/apple_displaypipe_v2.h index df8676ac6d..d938e9eafb 100644 --- a/include/hw/display/apple_displaypipe_v2.h +++ b/include/hw/display/apple_displaypipe_v2.h @@ -28,25 +28,22 @@ #define TYPE_APPLE_DISPLAYPIPE_V2 "apple-displaypipe-v2" OBJECT_DECLARE_SIMPLE_TYPE(AppleDisplayPipeV2State, APPLE_DISPLAYPIPE_V2); -typedef struct { - uint32_t start; - uint32_t end; - uint32_t stride; - uint32_t size; -} GenPipeLayer; - typedef struct { size_t index; + pixman_image_t *disp_image; MemoryRegion *vram; AddressSpace *dma_as; QEMUBH *bh; - // TODO: Not have this field. - AppleDisplayPipeV2State *disp_state; + uint16_t disp_width; + uint16_t disp_height; uint32_t config_control; uint32_t pixel_format; uint16_t width; uint16_t height; - GenPipeLayer layers[2]; + uint32_t base; + uint32_t end; + uint32_t stride; + uint32_t size; } GenPipeState; struct AppleDisplayPipeV2State { @@ -54,14 +51,16 @@ struct AppleDisplayPipeV2State { SysBusDevice parent_obj; /*< public >*/ - QEMUTimer *vblank_timer; - uint32_t width, height, refresh_rate; - MemoryRegion up_regs, vram; + uint32_t width; + uint32_t height; + pixman_image_t *disp_image; + MemoryRegion up_regs; + MemoryRegion vram; MemoryRegion *dma_mr; AddressSpace dma_as; MemoryRegionSection vram_section; qemu_irq irqs[9]; - uint32_t int_filter; + uint32_t int_status; GenPipeState genpipes[2]; QemuConsole *console; bool invalidated;