qemu-devel
[Top][All Lists]
Advanced

[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");
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]