[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Re: [PATCH v3] sh: sm501: add 2D engine support
From: |
Blue Swirl |
Subject: |
[Qemu-devel] Re: [PATCH v3] sh: sm501: add 2D engine support |
Date: |
Sat, 15 May 2010 17:01:23 +0300 |
Thanks, applied.
On 5/15/10, Shin-ichiro KAWASAKI <address@hidden> wrote:
> This patch reflects Blue Swirl's second review.
> Rebased with recent commit, and modified field name with underscore prefix.
>
>
> Best Regards,
> Shin-ichiro KAWASAKI
>
>
>
> ---------------------------------------------------------------------------
>
> In linux kernel v2.6.33, sm501 frame buffer driver modified to support
> 2D graphics engine on sm501 chip. One example is "fill rectangle" operation.
> But current qemu's sm501 emulation doesn't support it. This results in
> graphics console disturbance.
>
> This patch introduces sm501 2D graphics engine emulation and solve this
> problem.
>
> Signed-off-by: Shin-ichiro KAWASAKI <address@hidden>
>
> Add SM501 2D hardware engine support.
>
> - Add 2D engine register set read/write handlers.
> - Support 'fill rectangle'. Other operations are left for future work.
> - Update SM501 support status comment.
>
> ---
> hw/sm501.c | 172
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 169 insertions(+), 3 deletions(-)
>
> diff --git a/hw/sm501.c b/hw/sm501.c
>
> index 9310014..7ce809a 100644
>
> --- a/hw/sm501.c
> +++ b/hw/sm501.c
>
> @@ -31,16 +31,16 @@
> #include "qdev-addr.h"
>
>
> /*
> - * Status: 2008/11/02
> + * Status: 2010/05/07
> * - Minimum implementation for Linux console : mmio regs and CRT layer.
> - * - Always updates full screen.
> + * - 2D grapihcs acceleration partially supported : only fill rectangle.
> *
> * TODO:
> * - Panel support
> - * - Hardware cursor support
> * - Touch panel support
> * - USB support
> * - UART support
> + * - More 2D graphics engine support
> * - Performance tuning
> */
>
>
> @@ -510,6 +510,18 @@ typedef struct SM501State {
>
> uint32_t dc_crt_hwc_color_1_2;
> uint32_t dc_crt_hwc_color_3;
>
>
> + uint32_t twoD_destination;
> + uint32_t twoD_dimension;
> + uint32_t twoD_control;
> + uint32_t twoD_pitch;
> + uint32_t twoD_foreground;
> + uint32_t twoD_stretch;
> + uint32_t twoD_color_compare_mask;
> + uint32_t twoD_mask;
> + uint32_t twoD_window_width;
> + uint32_t twoD_source_base;
> + uint32_t twoD_destination_base;
>
> +
> } SM501State;
>
> static uint32_t get_local_mem_size_index(uint32_t size)
>
> @@ -619,6 +631,69 @@ static int within_hwc_y_range(SM501State *state, int y,
> int crt)
>
> return (hwc_y <= y && y < hwc_y + SM501_HWC_HEIGHT);
> }
>
> +static void sm501_2d_operation(SM501State * s)
> +{
> + /* obtain operation parameters */
>
> + int operation = (s->twoD_control >> 16) & 0x1f;
> + int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
> + int dst_y = s->twoD_destination & 0xFFFF;
> + int operation_width = (s->twoD_dimension >> 16) & 0x1FFF;
> + int operation_height = s->twoD_dimension & 0xFFFF;
> + uint32_t color = s->twoD_foreground;
> + int format_flags = (s->twoD_stretch >> 20) & 0x3;
> + int addressing = (s->twoD_stretch >> 16) & 0xF;
>
> +
> + /* get frame buffer info */
> +#if 0 /* for future use */
>
> + uint8_t * src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF);
> +#endif
> + uint8_t * dst = s->local_mem + (s->twoD_destination_base & 0x03FFFFFF);
>
> + int dst_width = (s->dc_crt_h_total & 0x00000FFF) + 1;
> +
> + if (addressing != 0x0) {
> + printf("%s: only XY addressing is supported.\n", __func__);
> + abort();
> + }
> +
>
> + if ((s->twoD_source_base & 0x08000000) ||
> + (s->twoD_destination_base & 0x08000000)) {
>
> + printf("%s: only local memory is supported.\n", __func__);
> + abort();
> + }
> +
> + switch (operation) {
> + case 0x01: /* fill rectangle */
> +
> +#define FILL_RECT(_bpp, _pixel_type) {
> \
> + int y, x;
> \
> + for (y = 0; y < operation_height; y++) {
> \
> + for (x = 0; x < operation_width; x++) {
> \
> + int index = ((dst_y + y) * dst_width + dst_x + x) * _bpp;
> \
> + *(_pixel_type*)&dst[index] = (_pixel_type)color;
> \
> + }
> \
> + }
> \
> + }
> +
> + switch (format_flags) {
> + case 0:
> + FILL_RECT(1, uint8_t);
> + break;
> + case 1:
> + FILL_RECT(2, uint16_t);
> + break;
> + case 2:
> + FILL_RECT(4, uint32_t);
> + break;
> + }
> + break;
> +
> + default:
> + printf("non-implemented SM501 2D operation. %d\n", operation);
> + abort();
> + break;
> + }
> +}
> +
> static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t
> addr)
> {
> SM501State * s = (SM501State *)opaque;
>
> @@ -969,6 +1044,92 @@ static CPUWriteMemoryFunc * const
> sm501_disp_ctrl_writefn[] = {
>
> &sm501_disp_ctrl_write,
> };
>
> +static uint32_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr)
> +{
> + SM501State * s = (SM501State *)opaque;
> + uint32_t ret = 0;
> + SM501_DPRINTF("sm501 2d engine regs : read addr=%x\n", (int)addr);
> +
> + switch(addr) {
> + case SM501_2D_SOURCE_BASE:
>
> + ret = s->twoD_source_base;
>
> + break;
> + default:
> + printf("sm501 disp ctrl : not implemented register read."
> + " addr=%x\n", (int)addr);
> + abort();
> + }
> +
> + return ret;
> +}
> +
> +static void sm501_2d_engine_write(void *opaque,
> + target_phys_addr_t addr, uint32_t value)
> +{
> + SM501State * s = (SM501State *)opaque;
> + SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n",
> + addr, value);
> +
> + switch(addr) {
> + case SM501_2D_DESTINATION:
>
> + s->twoD_destination = value;
>
> + break;
> + case SM501_2D_DIMENSION:
>
> + s->twoD_dimension = value;
>
> + break;
> + case SM501_2D_CONTROL:
>
> + s->twoD_control = value;
>
> +
> + /* do 2d operation if start flag is set. */
> + if (value & 0x80000000) {
> + sm501_2d_operation(s);
>
> + s->twoD_control &= ~0x80000000; /* start flag down */
>
> + }
> +
> + break;
> + case SM501_2D_PITCH:
>
> + s->twoD_pitch = value;
>
> + break;
> + case SM501_2D_FOREGROUND:
>
> + s->twoD_foreground = value;
>
> + break;
> + case SM501_2D_STRETCH:
>
> + s->twoD_stretch = value;
>
> + break;
> + case SM501_2D_COLOR_COMPARE_MASK:
>
> + s->twoD_color_compare_mask = value;
>
> + break;
> + case SM501_2D_MASK:
>
> + s->twoD_mask = value;
>
> + break;
> + case SM501_2D_WINDOW_WIDTH:
>
> + s->twoD_window_width = value;
>
> + break;
> + case SM501_2D_SOURCE_BASE:
>
> + s->twoD_source_base = value;
>
> + break;
> + case SM501_2D_DESTINATION_BASE:
>
> + s->twoD_destination_base = value;
>
> + break;
> + default:
> + printf("sm501 2d engine : not implemented register write."
> + " addr=%x, val=%x\n", (int)addr, value);
> + abort();
> + }
> +}
> +
> +static CPUReadMemoryFunc * const sm501_2d_engine_readfn[] = {
> + NULL,
> + NULL,
> + &sm501_2d_engine_read,
> +};
> +
> +static CPUWriteMemoryFunc * const sm501_2d_engine_writefn[] = {
> + NULL,
> + NULL,
> + &sm501_2d_engine_write,
> +};
> +
> /* draw line functions for all console modes */
>
> #include "pixel_ops.h"
>
> @@ -1195,6 +1356,7 @@ void sm501_init(uint32_t base, uint32_t
> local_mem_bytes, qemu_irq irq,
> DeviceState *dev;
>
> int sm501_system_config_index;
> int sm501_disp_ctrl_index;
> + int sm501_2d_engine_index;
>
> /* allocate management data region */
> s = (SM501State *)qemu_mallocz(sizeof(SM501State));
>
> @@ -1223,6 +1385,10 @@ void sm501_init(uint32_t base, uint32_t
> local_mem_bytes, qemu_irq irq,
>
> sm501_disp_ctrl_writefn,
> s);
> cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
> 0x1000, sm501_disp_ctrl_index);
> + sm501_2d_engine_index = cpu_register_io_memory(sm501_2d_engine_readfn,
> + sm501_2d_engine_writefn,
> s);
> + cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_2D_ENGINE,
> + 0x54, sm501_2d_engine_index);
>
> /* bridge to usb host emulation module */
>
> dev = qdev_create(NULL, "sysbus-ohci");
>