Annotation of qemu/hw/sm501.c, revision 1.1.1.7

1.1       root        1: /*
                      2:  * QEMU SM501 Device
                      3:  *
                      4:  * Copyright (c) 2008 Shin-ichiro KAWASAKI
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: 
                     25: #include <stdio.h>
                     26: #include "hw.h"
                     27: #include "pc.h"
                     28: #include "console.h"
                     29: #include "devices.h"
1.1.1.4   root       30: #include "sysbus.h"
                     31: #include "qdev-addr.h"
1.1.1.5   root       32: #include "range.h"
1.1       root       33: 
                     34: /*
1.1.1.4   root       35:  * Status: 2010/05/07
1.1       root       36:  *   - Minimum implementation for Linux console : mmio regs and CRT layer.
1.1.1.4   root       37:  *   - 2D grapihcs acceleration partially supported : only fill rectangle.
1.1       root       38:  *
                     39:  * TODO:
                     40:  *   - Panel support
                     41:  *   - Touch panel support
                     42:  *   - USB support
                     43:  *   - UART support
1.1.1.4   root       44:  *   - More 2D graphics engine support
1.1       root       45:  *   - Performance tuning
                     46:  */
                     47: 
                     48: //#define DEBUG_SM501
                     49: //#define DEBUG_BITBLT
                     50: 
                     51: #ifdef DEBUG_SM501
1.1.1.2   root       52: #define SM501_DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
1.1       root       53: #else
1.1.1.2   root       54: #define SM501_DPRINTF(fmt, ...) do {} while(0)
1.1       root       55: #endif
                     56: 
                     57: 
                     58: #define MMIO_BASE_OFFSET 0x3e00000
                     59: 
                     60: /* SM501 register definitions taken from "linux/include/linux/sm501-regs.h" */
                     61: 
                     62: /* System Configuration area */
                     63: /* System config base */
                     64: #define SM501_SYS_CONFIG               (0x000000)
                     65: 
                     66: /* config 1 */
                     67: #define SM501_SYSTEM_CONTROL           (0x000000)
                     68: 
                     69: #define SM501_SYSCTRL_PANEL_TRISTATE   (1<<0)
                     70: #define SM501_SYSCTRL_MEM_TRISTATE     (1<<1)
                     71: #define SM501_SYSCTRL_CRT_TRISTATE     (1<<2)
                     72: 
                     73: #define SM501_SYSCTRL_PCI_SLAVE_BURST_MASK (3<<4)
                     74: #define SM501_SYSCTRL_PCI_SLAVE_BURST_1        (0<<4)
                     75: #define SM501_SYSCTRL_PCI_SLAVE_BURST_2        (1<<4)
                     76: #define SM501_SYSCTRL_PCI_SLAVE_BURST_4        (2<<4)
                     77: #define SM501_SYSCTRL_PCI_SLAVE_BURST_8        (3<<4)
                     78: 
                     79: #define SM501_SYSCTRL_PCI_CLOCK_RUN_EN (1<<6)
                     80: #define SM501_SYSCTRL_PCI_RETRY_DISABLE        (1<<7)
                     81: #define SM501_SYSCTRL_PCI_SUBSYS_LOCK  (1<<11)
                     82: #define SM501_SYSCTRL_PCI_BURST_READ_EN        (1<<15)
                     83: 
                     84: /* miscellaneous control */
                     85: 
                     86: #define SM501_MISC_CONTROL             (0x000004)
                     87: 
                     88: #define SM501_MISC_BUS_SH              (0x0)
                     89: #define SM501_MISC_BUS_PCI             (0x1)
                     90: #define SM501_MISC_BUS_XSCALE          (0x2)
                     91: #define SM501_MISC_BUS_NEC             (0x6)
                     92: #define SM501_MISC_BUS_MASK            (0x7)
                     93: 
                     94: #define SM501_MISC_VR_62MB             (1<<3)
                     95: #define SM501_MISC_CDR_RESET           (1<<7)
                     96: #define SM501_MISC_USB_LB              (1<<8)
                     97: #define SM501_MISC_USB_SLAVE           (1<<9)
                     98: #define SM501_MISC_BL_1                        (1<<10)
                     99: #define SM501_MISC_MC                  (1<<11)
                    100: #define SM501_MISC_DAC_POWER           (1<<12)
                    101: #define SM501_MISC_IRQ_INVERT          (1<<16)
                    102: #define SM501_MISC_SH                  (1<<17)
                    103: 
                    104: #define SM501_MISC_HOLD_EMPTY          (0<<18)
                    105: #define SM501_MISC_HOLD_8              (1<<18)
                    106: #define SM501_MISC_HOLD_16             (2<<18)
                    107: #define SM501_MISC_HOLD_24             (3<<18)
                    108: #define SM501_MISC_HOLD_32             (4<<18)
                    109: #define SM501_MISC_HOLD_MASK           (7<<18)
                    110: 
                    111: #define SM501_MISC_FREQ_12             (1<<24)
                    112: #define SM501_MISC_PNL_24BIT           (1<<25)
                    113: #define SM501_MISC_8051_LE             (1<<26)
                    114: 
                    115: 
                    116: 
                    117: #define SM501_GPIO31_0_CONTROL         (0x000008)
                    118: #define SM501_GPIO63_32_CONTROL                (0x00000C)
                    119: #define SM501_DRAM_CONTROL             (0x000010)
                    120: 
                    121: /* command list */
                    122: #define SM501_ARBTRTN_CONTROL          (0x000014)
                    123: 
                    124: /* command list */
                    125: #define SM501_COMMAND_LIST_STATUS      (0x000024)
                    126: 
                    127: /* interrupt debug */
                    128: #define SM501_RAW_IRQ_STATUS           (0x000028)
                    129: #define SM501_RAW_IRQ_CLEAR            (0x000028)
                    130: #define SM501_IRQ_STATUS               (0x00002C)
                    131: #define SM501_IRQ_MASK                 (0x000030)
                    132: #define SM501_DEBUG_CONTROL            (0x000034)
                    133: 
                    134: /* power management */
                    135: #define SM501_POWERMODE_P2X_SRC                (1<<29)
                    136: #define SM501_POWERMODE_V2X_SRC                (1<<20)
                    137: #define SM501_POWERMODE_M_SRC          (1<<12)
                    138: #define SM501_POWERMODE_M1_SRC         (1<<4)
                    139: 
                    140: #define SM501_CURRENT_GATE             (0x000038)
                    141: #define SM501_CURRENT_CLOCK            (0x00003C)
                    142: #define SM501_POWER_MODE_0_GATE                (0x000040)
                    143: #define SM501_POWER_MODE_0_CLOCK       (0x000044)
                    144: #define SM501_POWER_MODE_1_GATE                (0x000048)
                    145: #define SM501_POWER_MODE_1_CLOCK       (0x00004C)
                    146: #define SM501_SLEEP_MODE_GATE          (0x000050)
                    147: #define SM501_POWER_MODE_CONTROL       (0x000054)
                    148: 
                    149: /* power gates for units within the 501 */
                    150: #define SM501_GATE_HOST                        (0)
                    151: #define SM501_GATE_MEMORY              (1)
                    152: #define SM501_GATE_DISPLAY             (2)
                    153: #define SM501_GATE_2D_ENGINE           (3)
                    154: #define SM501_GATE_CSC                 (4)
                    155: #define SM501_GATE_ZVPORT              (5)
                    156: #define SM501_GATE_GPIO                        (6)
                    157: #define SM501_GATE_UART0               (7)
                    158: #define SM501_GATE_UART1               (8)
                    159: #define SM501_GATE_SSP                 (10)
                    160: #define SM501_GATE_USB_HOST            (11)
                    161: #define SM501_GATE_USB_GADGET          (12)
                    162: #define SM501_GATE_UCONTROLLER         (17)
                    163: #define SM501_GATE_AC97                        (18)
                    164: 
                    165: /* panel clock */
                    166: #define SM501_CLOCK_P2XCLK             (24)
                    167: /* crt clock */
                    168: #define SM501_CLOCK_V2XCLK             (16)
                    169: /* main clock */
                    170: #define SM501_CLOCK_MCLK               (8)
                    171: /* SDRAM controller clock */
                    172: #define SM501_CLOCK_M1XCLK             (0)
                    173: 
                    174: /* config 2 */
                    175: #define SM501_PCI_MASTER_BASE          (0x000058)
                    176: #define SM501_ENDIAN_CONTROL           (0x00005C)
                    177: #define SM501_DEVICEID                 (0x000060)
                    178: /* 0x050100A0 */
                    179: 
                    180: #define SM501_DEVICEID_SM501           (0x05010000)
                    181: #define SM501_DEVICEID_IDMASK          (0xffff0000)
                    182: #define SM501_DEVICEID_REVMASK         (0x000000ff)
                    183: 
                    184: #define SM501_PLLCLOCK_COUNT           (0x000064)
                    185: #define SM501_MISC_TIMING              (0x000068)
                    186: #define SM501_CURRENT_SDRAM_CLOCK      (0x00006C)
                    187: 
                    188: #define SM501_PROGRAMMABLE_PLL_CONTROL (0x000074)
                    189: 
                    190: /* GPIO base */
                    191: #define SM501_GPIO                     (0x010000)
                    192: #define SM501_GPIO_DATA_LOW            (0x00)
                    193: #define SM501_GPIO_DATA_HIGH           (0x04)
                    194: #define SM501_GPIO_DDR_LOW             (0x08)
                    195: #define SM501_GPIO_DDR_HIGH            (0x0C)
                    196: #define SM501_GPIO_IRQ_SETUP           (0x10)
                    197: #define SM501_GPIO_IRQ_STATUS          (0x14)
                    198: #define SM501_GPIO_IRQ_RESET           (0x14)
                    199: 
                    200: /* I2C controller base */
                    201: #define SM501_I2C                      (0x010040)
                    202: #define SM501_I2C_BYTE_COUNT           (0x00)
                    203: #define SM501_I2C_CONTROL              (0x01)
                    204: #define SM501_I2C_STATUS               (0x02)
                    205: #define SM501_I2C_RESET                        (0x02)
                    206: #define SM501_I2C_SLAVE_ADDRESS                (0x03)
                    207: #define SM501_I2C_DATA                 (0x04)
                    208: 
                    209: /* SSP base */
                    210: #define SM501_SSP                      (0x020000)
                    211: 
                    212: /* Uart 0 base */
                    213: #define SM501_UART0                    (0x030000)
                    214: 
                    215: /* Uart 1 base */
                    216: #define SM501_UART1                    (0x030020)
                    217: 
                    218: /* USB host port base */
                    219: #define SM501_USB_HOST                 (0x040000)
                    220: 
                    221: /* USB slave/gadget base */
                    222: #define SM501_USB_GADGET               (0x060000)
                    223: 
                    224: /* USB slave/gadget data port base */
                    225: #define SM501_USB_GADGET_DATA          (0x070000)
                    226: 
                    227: /* Display controller/video engine base */
                    228: #define SM501_DC                       (0x080000)
                    229: 
                    230: /* common defines for the SM501 address registers */
                    231: #define SM501_ADDR_FLIP                        (1<<31)
                    232: #define SM501_ADDR_EXT                 (1<<27)
                    233: #define SM501_ADDR_CS1                 (1<<26)
                    234: #define SM501_ADDR_MASK                        (0x3f << 26)
                    235: 
                    236: #define SM501_FIFO_MASK                        (0x3 << 16)
                    237: #define SM501_FIFO_1                   (0x0 << 16)
                    238: #define SM501_FIFO_3                   (0x1 << 16)
                    239: #define SM501_FIFO_7                   (0x2 << 16)
                    240: #define SM501_FIFO_11                  (0x3 << 16)
                    241: 
                    242: /* common registers for panel and the crt */
                    243: #define SM501_OFF_DC_H_TOT             (0x000)
                    244: #define SM501_OFF_DC_V_TOT             (0x008)
                    245: #define SM501_OFF_DC_H_SYNC            (0x004)
                    246: #define SM501_OFF_DC_V_SYNC            (0x00C)
                    247: 
                    248: #define SM501_DC_PANEL_CONTROL         (0x000)
                    249: 
                    250: #define SM501_DC_PANEL_CONTROL_FPEN    (1<<27)
                    251: #define SM501_DC_PANEL_CONTROL_BIAS    (1<<26)
                    252: #define SM501_DC_PANEL_CONTROL_DATA    (1<<25)
                    253: #define SM501_DC_PANEL_CONTROL_VDD     (1<<24)
                    254: #define SM501_DC_PANEL_CONTROL_DP      (1<<23)
                    255: 
                    256: #define SM501_DC_PANEL_CONTROL_TFT_888 (0<<21)
                    257: #define SM501_DC_PANEL_CONTROL_TFT_333 (1<<21)
                    258: #define SM501_DC_PANEL_CONTROL_TFT_444 (2<<21)
                    259: 
                    260: #define SM501_DC_PANEL_CONTROL_DE      (1<<20)
                    261: 
                    262: #define SM501_DC_PANEL_CONTROL_LCD_TFT (0<<18)
                    263: #define SM501_DC_PANEL_CONTROL_LCD_STN8        (1<<18)
                    264: #define SM501_DC_PANEL_CONTROL_LCD_STN12 (2<<18)
                    265: 
                    266: #define SM501_DC_PANEL_CONTROL_CP      (1<<14)
                    267: #define SM501_DC_PANEL_CONTROL_VSP     (1<<13)
                    268: #define SM501_DC_PANEL_CONTROL_HSP     (1<<12)
                    269: #define SM501_DC_PANEL_CONTROL_CK      (1<<9)
                    270: #define SM501_DC_PANEL_CONTROL_TE      (1<<8)
                    271: #define SM501_DC_PANEL_CONTROL_VPD     (1<<7)
                    272: #define SM501_DC_PANEL_CONTROL_VP      (1<<6)
                    273: #define SM501_DC_PANEL_CONTROL_HPD     (1<<5)
                    274: #define SM501_DC_PANEL_CONTROL_HP      (1<<4)
                    275: #define SM501_DC_PANEL_CONTROL_GAMMA   (1<<3)
                    276: #define SM501_DC_PANEL_CONTROL_EN      (1<<2)
                    277: 
                    278: #define SM501_DC_PANEL_CONTROL_8BPP    (0<<0)
                    279: #define SM501_DC_PANEL_CONTROL_16BPP   (1<<0)
                    280: #define SM501_DC_PANEL_CONTROL_32BPP   (2<<0)
                    281: 
                    282: 
                    283: #define SM501_DC_PANEL_PANNING_CONTROL (0x004)
                    284: #define SM501_DC_PANEL_COLOR_KEY       (0x008)
                    285: #define SM501_DC_PANEL_FB_ADDR         (0x00C)
                    286: #define SM501_DC_PANEL_FB_OFFSET       (0x010)
                    287: #define SM501_DC_PANEL_FB_WIDTH                (0x014)
                    288: #define SM501_DC_PANEL_FB_HEIGHT       (0x018)
                    289: #define SM501_DC_PANEL_TL_LOC          (0x01C)
                    290: #define SM501_DC_PANEL_BR_LOC          (0x020)
                    291: #define SM501_DC_PANEL_H_TOT           (0x024)
                    292: #define SM501_DC_PANEL_H_SYNC          (0x028)
                    293: #define SM501_DC_PANEL_V_TOT           (0x02C)
                    294: #define SM501_DC_PANEL_V_SYNC          (0x030)
                    295: #define SM501_DC_PANEL_CUR_LINE                (0x034)
                    296: 
                    297: #define SM501_DC_VIDEO_CONTROL         (0x040)
                    298: #define SM501_DC_VIDEO_FB0_ADDR                (0x044)
                    299: #define SM501_DC_VIDEO_FB_WIDTH                (0x048)
                    300: #define SM501_DC_VIDEO_FB0_LAST_ADDR   (0x04C)
                    301: #define SM501_DC_VIDEO_TL_LOC          (0x050)
                    302: #define SM501_DC_VIDEO_BR_LOC          (0x054)
                    303: #define SM501_DC_VIDEO_SCALE           (0x058)
                    304: #define SM501_DC_VIDEO_INIT_SCALE      (0x05C)
                    305: #define SM501_DC_VIDEO_YUV_CONSTANTS   (0x060)
                    306: #define SM501_DC_VIDEO_FB1_ADDR                (0x064)
                    307: #define SM501_DC_VIDEO_FB1_LAST_ADDR   (0x068)
                    308: 
                    309: #define SM501_DC_VIDEO_ALPHA_CONTROL   (0x080)
                    310: #define SM501_DC_VIDEO_ALPHA_FB_ADDR   (0x084)
                    311: #define SM501_DC_VIDEO_ALPHA_FB_OFFSET (0x088)
                    312: #define SM501_DC_VIDEO_ALPHA_FB_LAST_ADDR      (0x08C)
                    313: #define SM501_DC_VIDEO_ALPHA_TL_LOC    (0x090)
                    314: #define SM501_DC_VIDEO_ALPHA_BR_LOC    (0x094)
                    315: #define SM501_DC_VIDEO_ALPHA_SCALE     (0x098)
                    316: #define SM501_DC_VIDEO_ALPHA_INIT_SCALE        (0x09C)
                    317: #define SM501_DC_VIDEO_ALPHA_CHROMA_KEY        (0x0A0)
                    318: #define SM501_DC_VIDEO_ALPHA_COLOR_LOOKUP      (0x0A4)
                    319: 
                    320: #define SM501_DC_PANEL_HWC_BASE                (0x0F0)
                    321: #define SM501_DC_PANEL_HWC_ADDR                (0x0F0)
                    322: #define SM501_DC_PANEL_HWC_LOC         (0x0F4)
                    323: #define SM501_DC_PANEL_HWC_COLOR_1_2   (0x0F8)
                    324: #define SM501_DC_PANEL_HWC_COLOR_3     (0x0FC)
                    325: 
                    326: #define SM501_HWC_EN                   (1<<31)
                    327: 
                    328: #define SM501_OFF_HWC_ADDR             (0x00)
                    329: #define SM501_OFF_HWC_LOC              (0x04)
                    330: #define SM501_OFF_HWC_COLOR_1_2                (0x08)
                    331: #define SM501_OFF_HWC_COLOR_3          (0x0C)
                    332: 
                    333: #define SM501_DC_ALPHA_CONTROL         (0x100)
                    334: #define SM501_DC_ALPHA_FB_ADDR         (0x104)
                    335: #define SM501_DC_ALPHA_FB_OFFSET       (0x108)
                    336: #define SM501_DC_ALPHA_TL_LOC          (0x10C)
                    337: #define SM501_DC_ALPHA_BR_LOC          (0x110)
                    338: #define SM501_DC_ALPHA_CHROMA_KEY      (0x114)
                    339: #define SM501_DC_ALPHA_COLOR_LOOKUP    (0x118)
                    340: 
                    341: #define SM501_DC_CRT_CONTROL           (0x200)
                    342: 
                    343: #define SM501_DC_CRT_CONTROL_TVP       (1<<15)
                    344: #define SM501_DC_CRT_CONTROL_CP                (1<<14)
                    345: #define SM501_DC_CRT_CONTROL_VSP       (1<<13)
                    346: #define SM501_DC_CRT_CONTROL_HSP       (1<<12)
                    347: #define SM501_DC_CRT_CONTROL_VS                (1<<11)
                    348: #define SM501_DC_CRT_CONTROL_BLANK     (1<<10)
                    349: #define SM501_DC_CRT_CONTROL_SEL       (1<<9)
                    350: #define SM501_DC_CRT_CONTROL_TE                (1<<8)
                    351: #define SM501_DC_CRT_CONTROL_PIXEL_MASK (0xF << 4)
                    352: #define SM501_DC_CRT_CONTROL_GAMMA     (1<<3)
                    353: #define SM501_DC_CRT_CONTROL_ENABLE    (1<<2)
                    354: 
                    355: #define SM501_DC_CRT_CONTROL_8BPP      (0<<0)
                    356: #define SM501_DC_CRT_CONTROL_16BPP     (1<<0)
                    357: #define SM501_DC_CRT_CONTROL_32BPP     (2<<0)
                    358: 
                    359: #define SM501_DC_CRT_FB_ADDR           (0x204)
                    360: #define SM501_DC_CRT_FB_OFFSET         (0x208)
                    361: #define SM501_DC_CRT_H_TOT             (0x20C)
                    362: #define SM501_DC_CRT_H_SYNC            (0x210)
                    363: #define SM501_DC_CRT_V_TOT             (0x214)
                    364: #define SM501_DC_CRT_V_SYNC            (0x218)
                    365: #define SM501_DC_CRT_SIGNATURE_ANALYZER        (0x21C)
                    366: #define SM501_DC_CRT_CUR_LINE          (0x220)
                    367: #define SM501_DC_CRT_MONITOR_DETECT    (0x224)
                    368: 
                    369: #define SM501_DC_CRT_HWC_BASE          (0x230)
                    370: #define SM501_DC_CRT_HWC_ADDR          (0x230)
                    371: #define SM501_DC_CRT_HWC_LOC           (0x234)
                    372: #define SM501_DC_CRT_HWC_COLOR_1_2     (0x238)
                    373: #define SM501_DC_CRT_HWC_COLOR_3       (0x23C)
                    374: 
                    375: #define SM501_DC_PANEL_PALETTE         (0x400)
                    376: 
                    377: #define SM501_DC_VIDEO_PALETTE         (0x800)
                    378: 
                    379: #define SM501_DC_CRT_PALETTE           (0xC00)
                    380: 
                    381: /* Zoom Video port base */
                    382: #define SM501_ZVPORT                   (0x090000)
                    383: 
                    384: /* AC97/I2S base */
                    385: #define SM501_AC97                     (0x0A0000)
                    386: 
                    387: /* 8051 micro controller base */
                    388: #define SM501_UCONTROLLER              (0x0B0000)
                    389: 
                    390: /* 8051 micro controller SRAM base */
                    391: #define SM501_UCONTROLLER_SRAM         (0x0C0000)
                    392: 
                    393: /* DMA base */
                    394: #define SM501_DMA                      (0x0D0000)
                    395: 
                    396: /* 2d engine base */
                    397: #define SM501_2D_ENGINE                        (0x100000)
                    398: #define SM501_2D_SOURCE                        (0x00)
                    399: #define SM501_2D_DESTINATION           (0x04)
                    400: #define SM501_2D_DIMENSION             (0x08)
                    401: #define SM501_2D_CONTROL               (0x0C)
                    402: #define SM501_2D_PITCH                 (0x10)
                    403: #define SM501_2D_FOREGROUND            (0x14)
                    404: #define SM501_2D_BACKGROUND            (0x18)
                    405: #define SM501_2D_STRETCH               (0x1C)
                    406: #define SM501_2D_COLOR_COMPARE         (0x20)
                    407: #define SM501_2D_COLOR_COMPARE_MASK    (0x24)
                    408: #define SM501_2D_MASK                  (0x28)
                    409: #define SM501_2D_CLIP_TL               (0x2C)
                    410: #define SM501_2D_CLIP_BR               (0x30)
                    411: #define SM501_2D_MONO_PATTERN_LOW      (0x34)
                    412: #define SM501_2D_MONO_PATTERN_HIGH     (0x38)
                    413: #define SM501_2D_WINDOW_WIDTH          (0x3C)
                    414: #define SM501_2D_SOURCE_BASE           (0x40)
                    415: #define SM501_2D_DESTINATION_BASE      (0x44)
                    416: #define SM501_2D_ALPHA                 (0x48)
                    417: #define SM501_2D_WRAP                  (0x4C)
                    418: #define SM501_2D_STATUS                        (0x50)
                    419: 
                    420: #define SM501_CSC_Y_SOURCE_BASE                (0xC8)
                    421: #define SM501_CSC_CONSTANTS            (0xCC)
                    422: #define SM501_CSC_Y_SOURCE_X           (0xD0)
                    423: #define SM501_CSC_Y_SOURCE_Y           (0xD4)
                    424: #define SM501_CSC_U_SOURCE_BASE                (0xD8)
                    425: #define SM501_CSC_V_SOURCE_BASE                (0xDC)
                    426: #define SM501_CSC_SOURCE_DIMENSION     (0xE0)
                    427: #define SM501_CSC_SOURCE_PITCH         (0xE4)
                    428: #define SM501_CSC_DESTINATION          (0xE8)
                    429: #define SM501_CSC_DESTINATION_DIMENSION        (0xEC)
                    430: #define SM501_CSC_DESTINATION_PITCH    (0xF0)
                    431: #define SM501_CSC_SCALE_FACTOR         (0xF4)
                    432: #define SM501_CSC_DESTINATION_BASE     (0xF8)
                    433: #define SM501_CSC_CONTROL              (0xFC)
                    434: 
                    435: /* 2d engine data port base */
                    436: #define SM501_2D_ENGINE_DATA           (0x110000)
                    437: 
                    438: /* end of register definitions */
                    439: 
1.1.1.4   root      440: #define SM501_HWC_WIDTH                       (64)
                    441: #define SM501_HWC_HEIGHT                      (64)
1.1       root      442: 
                    443: /* SM501 local memory size taken from "linux/drivers/mfd/sm501.c" */
                    444: static const uint32_t sm501_mem_local_size[] = {
                    445:        [0]     = 4*1024*1024,
                    446:        [1]     = 8*1024*1024,
                    447:        [2]     = 16*1024*1024,
                    448:        [3]     = 32*1024*1024,
                    449:        [4]     = 64*1024*1024,
                    450:        [5]     = 2*1024*1024,
                    451: };
                    452: #define get_local_mem_size(s) sm501_mem_local_size[(s)->local_mem_size_index]
                    453: 
                    454: typedef struct SM501State {
                    455:     /* graphic console status */
                    456:     DisplayState *ds;
                    457: 
                    458:     /* status & internal resources */
                    459:     target_phys_addr_t base;
                    460:     uint32_t local_mem_size_index;
                    461:     uint8_t * local_mem;
1.1.1.6   root      462:     MemoryRegion local_mem_region;
1.1       root      463:     uint32_t last_width;
                    464:     uint32_t last_height;
                    465: 
                    466:     /* mmio registers */
                    467:     uint32_t system_control;
                    468:     uint32_t misc_control;
                    469:     uint32_t gpio_31_0_control;
                    470:     uint32_t gpio_63_32_control;
                    471:     uint32_t dram_control;
                    472:     uint32_t irq_mask;
                    473:     uint32_t misc_timing;
                    474:     uint32_t power_mode_control;
                    475: 
                    476:     uint32_t uart0_ier;
                    477:     uint32_t uart0_lcr;
                    478:     uint32_t uart0_mcr;
                    479:     uint32_t uart0_scr;
                    480: 
                    481:     uint8_t dc_palette[0x400 * 3];
                    482: 
                    483:     uint32_t dc_panel_control;
                    484:     uint32_t dc_panel_panning_control;
                    485:     uint32_t dc_panel_fb_addr;
                    486:     uint32_t dc_panel_fb_offset;
                    487:     uint32_t dc_panel_fb_width;
                    488:     uint32_t dc_panel_fb_height;
                    489:     uint32_t dc_panel_tl_location;
                    490:     uint32_t dc_panel_br_location;
                    491:     uint32_t dc_panel_h_total;
                    492:     uint32_t dc_panel_h_sync;
                    493:     uint32_t dc_panel_v_total;
                    494:     uint32_t dc_panel_v_sync;
                    495: 
                    496:     uint32_t dc_panel_hwc_addr;
                    497:     uint32_t dc_panel_hwc_location;
                    498:     uint32_t dc_panel_hwc_color_1_2;
                    499:     uint32_t dc_panel_hwc_color_3;
                    500: 
                    501:     uint32_t dc_crt_control;
                    502:     uint32_t dc_crt_fb_addr;
                    503:     uint32_t dc_crt_fb_offset;
                    504:     uint32_t dc_crt_h_total;
                    505:     uint32_t dc_crt_h_sync;
                    506:     uint32_t dc_crt_v_total;
                    507:     uint32_t dc_crt_v_sync;
                    508: 
                    509:     uint32_t dc_crt_hwc_addr;
                    510:     uint32_t dc_crt_hwc_location;
                    511:     uint32_t dc_crt_hwc_color_1_2;
                    512:     uint32_t dc_crt_hwc_color_3;
                    513: 
1.1.1.5   root      514:     uint32_t twoD_source;
1.1.1.4   root      515:     uint32_t twoD_destination;
                    516:     uint32_t twoD_dimension;
                    517:     uint32_t twoD_control;
                    518:     uint32_t twoD_pitch;
                    519:     uint32_t twoD_foreground;
                    520:     uint32_t twoD_stretch;
                    521:     uint32_t twoD_color_compare_mask;
                    522:     uint32_t twoD_mask;
                    523:     uint32_t twoD_window_width;
                    524:     uint32_t twoD_source_base;
                    525:     uint32_t twoD_destination_base;
                    526: 
1.1       root      527: } SM501State;
                    528: 
                    529: static uint32_t get_local_mem_size_index(uint32_t size)
                    530: {
                    531:     uint32_t norm_size = 0;
                    532:     int i, index = 0;
                    533: 
                    534:     for (i = 0; i < ARRAY_SIZE(sm501_mem_local_size); i++) {
                    535:        uint32_t new_size = sm501_mem_local_size[i];
                    536:        if (new_size >= size) {
                    537:            if (norm_size == 0 || norm_size > new_size) {
                    538:                norm_size = new_size;
                    539:                index = i;
                    540:            }
                    541:        }
                    542:     }
                    543: 
                    544:     return index;
                    545: }
                    546: 
1.1.1.4   root      547: /**
                    548:  * Check the availability of hardware cursor.
                    549:  * @param crt  0 for PANEL, 1 for CRT.
                    550:  */
                    551: static inline int is_hwc_enabled(SM501State *state, int crt)
                    552: {
                    553:     uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
                    554:     return addr & 0x80000000;
                    555: }
                    556: 
                    557: /**
                    558:  * Get the address which holds cursor pattern data.
                    559:  * @param crt  0 for PANEL, 1 for CRT.
                    560:  */
                    561: static inline uint32_t get_hwc_address(SM501State *state, int crt)
                    562: {
                    563:     uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
                    564:     return (addr & 0x03FFFFF0)/* >> 4*/;
                    565: }
                    566: 
                    567: /**
                    568:  * Get the cursor position in y coordinate.
                    569:  * @param crt  0 for PANEL, 1 for CRT.
                    570:  */
                    571: static inline uint32_t get_hwc_y(SM501State *state, int crt)
                    572: {
                    573:     uint32_t location = crt ? state->dc_crt_hwc_location
                    574:                             : state->dc_panel_hwc_location;
                    575:     return (location & 0x07FF0000) >> 16;
                    576: }
                    577: 
                    578: /**
                    579:  * Get the cursor position in x coordinate.
                    580:  * @param crt  0 for PANEL, 1 for CRT.
                    581:  */
                    582: static inline uint32_t get_hwc_x(SM501State *state, int crt)
                    583: {
                    584:     uint32_t location = crt ? state->dc_crt_hwc_location
                    585:                             : state->dc_panel_hwc_location;
                    586:     return location & 0x000007FF;
                    587: }
                    588: 
                    589: /**
                    590:  * Get the cursor position in x coordinate.
                    591:  * @param crt  0 for PANEL, 1 for CRT.
                    592:  * @param index  0, 1, 2 or 3 which specifies color of corsor dot.
                    593:  */
                    594: static inline uint16_t get_hwc_color(SM501State *state, int crt, int index)
                    595: {
1.1.1.7 ! root      596:     uint32_t color_reg = 0;
1.1.1.4   root      597:     uint16_t color_565 = 0;
                    598: 
                    599:     if (index == 0) {
                    600:         return 0;
                    601:     }
                    602: 
                    603:     switch (index) {
                    604:     case 1:
                    605:     case 2:
                    606:         color_reg = crt ? state->dc_crt_hwc_color_1_2
                    607:                         : state->dc_panel_hwc_color_1_2;
                    608:         break;
                    609:     case 3:
                    610:         color_reg = crt ? state->dc_crt_hwc_color_3
                    611:                         : state->dc_panel_hwc_color_3;
                    612:         break;
                    613:     default:
                    614:         printf("invalid hw cursor color.\n");
                    615:         abort();
                    616:     }
                    617: 
                    618:     switch (index) {
                    619:     case 1:
                    620:     case 3:
                    621:         color_565 = (uint16_t)(color_reg & 0xFFFF);
                    622:         break;
                    623:     case 2:
                    624:         color_565 = (uint16_t)((color_reg >> 16) & 0xFFFF);
                    625:         break;
                    626:     }
                    627:     return color_565;
                    628: }
                    629: 
                    630: static int within_hwc_y_range(SM501State *state, int y, int crt)
                    631: {
                    632:     int hwc_y = get_hwc_y(state, crt);
                    633:     return (hwc_y <= y && y < hwc_y + SM501_HWC_HEIGHT);
                    634: }
                    635: 
                    636: static void sm501_2d_operation(SM501State * s)
                    637: {
                    638:     /* obtain operation parameters */
                    639:     int operation = (s->twoD_control >> 16) & 0x1f;
1.1.1.5   root      640:     int rtl = s->twoD_control & 0x8000000;
                    641:     int src_x = (s->twoD_source >> 16) & 0x01FFF;
                    642:     int src_y = s->twoD_source & 0xFFFF;
1.1.1.4   root      643:     int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
                    644:     int dst_y = s->twoD_destination & 0xFFFF;
                    645:     int operation_width = (s->twoD_dimension >> 16) & 0x1FFF;
                    646:     int operation_height = s->twoD_dimension & 0xFFFF;
                    647:     uint32_t color = s->twoD_foreground;
                    648:     int format_flags = (s->twoD_stretch >> 20) & 0x3;
                    649:     int addressing = (s->twoD_stretch >> 16) & 0xF;
                    650: 
                    651:     /* get frame buffer info */
                    652:     uint8_t * src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF);
                    653:     uint8_t * dst = s->local_mem + (s->twoD_destination_base & 0x03FFFFFF);
1.1.1.5   root      654:     int src_width = (s->dc_crt_h_total & 0x00000FFF) + 1;
1.1.1.4   root      655:     int dst_width = (s->dc_crt_h_total & 0x00000FFF) + 1;
                    656: 
                    657:     if (addressing != 0x0) {
                    658:         printf("%s: only XY addressing is supported.\n", __func__);
                    659:         abort();
                    660:     }
                    661: 
                    662:     if ((s->twoD_source_base & 0x08000000) ||
                    663:         (s->twoD_destination_base & 0x08000000)) {
                    664:         printf("%s: only local memory is supported.\n", __func__);
                    665:         abort();
                    666:     }
                    667: 
                    668:     switch (operation) {
1.1.1.5   root      669:     case 0x00: /* copy area */
                    670: #define COPY_AREA(_bpp, _pixel_type, rtl) {                                 \
                    671:         int y, x, index_d, index_s;                                         \
                    672:         for (y = 0; y < operation_height; y++) {                            \
                    673:             for (x = 0; x < operation_width; x++) {                         \
                    674:                 if (rtl) {                                                  \
                    675:                     index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \
                    676:                     index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \
                    677:                 } else {                                                    \
                    678:                     index_s = ((src_y + y) * src_width + src_x + x) * _bpp; \
                    679:                     index_d = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \
                    680:                 }                                                           \
                    681:                 *(_pixel_type*)&dst[index_d] = *(_pixel_type*)&src[index_s];\
                    682:             }                                                               \
                    683:         }                                                                   \
                    684:     }
                    685:         switch (format_flags) {
                    686:         case 0:
                    687:             COPY_AREA(1, uint8_t, rtl);
                    688:             break;
                    689:         case 1:
                    690:             COPY_AREA(2, uint16_t, rtl);
                    691:             break;
                    692:         case 2:
                    693:             COPY_AREA(4, uint32_t, rtl);
                    694:             break;
                    695:         }
                    696:         break;
1.1.1.4   root      697: 
1.1.1.5   root      698:     case 0x01: /* fill rectangle */
1.1.1.4   root      699: #define FILL_RECT(_bpp, _pixel_type) {                                      \
                    700:         int y, x;                                                           \
                    701:         for (y = 0; y < operation_height; y++) {                            \
                    702:             for (x = 0; x < operation_width; x++) {                         \
                    703:                 int index = ((dst_y + y) * dst_width + dst_x + x) * _bpp;   \
                    704:                 *(_pixel_type*)&dst[index] = (_pixel_type)color;            \
                    705:             }                                                               \
                    706:         }                                                                   \
                    707:     }
                    708: 
                    709:         switch (format_flags) {
                    710:         case 0:
                    711:             FILL_RECT(1, uint8_t);
                    712:             break;
                    713:         case 1:
                    714:             FILL_RECT(2, uint16_t);
                    715:             break;
                    716:         case 2:
                    717:             FILL_RECT(4, uint32_t);
                    718:             break;
                    719:         }
                    720:         break;
                    721: 
                    722:     default:
                    723:         printf("non-implemented SM501 2D operation. %d\n", operation);
                    724:         abort();
                    725:         break;
                    726:     }
                    727: }
                    728: 
1.1.1.6   root      729: static uint64_t sm501_system_config_read(void *opaque, target_phys_addr_t addr,
                    730:                                          unsigned size)
1.1       root      731: {
                    732:     SM501State * s = (SM501State *)opaque;
                    733:     uint32_t ret = 0;
                    734:     SM501_DPRINTF("sm501 system config regs : read addr=%x\n", (int)addr);
                    735: 
                    736:     switch(addr) {
                    737:     case SM501_SYSTEM_CONTROL:
                    738:        ret = s->system_control;
                    739:        break;
                    740:     case SM501_MISC_CONTROL:
                    741:        ret = s->misc_control;
                    742:        break;
                    743:     case SM501_GPIO31_0_CONTROL:
                    744:        ret = s->gpio_31_0_control;
                    745:        break;
                    746:     case SM501_GPIO63_32_CONTROL:
                    747:        ret = s->gpio_63_32_control;
                    748:        break;
                    749:     case SM501_DEVICEID:
                    750:        ret = 0x050100A0;
                    751:        break;
                    752:     case SM501_DRAM_CONTROL:
                    753:        ret = (s->dram_control & 0x07F107C0) | s->local_mem_size_index << 13;
                    754:        break;
                    755:     case SM501_IRQ_MASK:
                    756:        ret = s->irq_mask;
                    757:        break;
                    758:     case SM501_MISC_TIMING:
                    759:        /* TODO : simulate gate control */
                    760:        ret = s->misc_timing;
                    761:        break;
                    762:     case SM501_CURRENT_GATE:
                    763:        /* TODO : simulate gate control */
                    764:        ret = 0x00021807;
                    765:        break;
                    766:     case SM501_CURRENT_CLOCK:
                    767:        ret = 0x2A1A0A09;
                    768:        break;
                    769:     case SM501_POWER_MODE_CONTROL:
                    770:        ret = s->power_mode_control;
                    771:        break;
                    772: 
                    773:     default:
                    774:        printf("sm501 system config : not implemented register read."
                    775:               " addr=%x\n", (int)addr);
1.1.1.4   root      776:         abort();
1.1       root      777:     }
                    778: 
                    779:     return ret;
                    780: }
                    781: 
1.1.1.6   root      782: static void sm501_system_config_write(void *opaque, target_phys_addr_t addr,
                    783:                                       uint64_t value, unsigned size)
1.1       root      784: {
                    785:     SM501State * s = (SM501State *)opaque;
                    786:     SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n",
1.1.1.6   root      787:                  (uint32_t)addr, (uint32_t)value);
1.1       root      788: 
                    789:     switch(addr) {
                    790:     case SM501_SYSTEM_CONTROL:
                    791:        s->system_control = value & 0xE300B8F7;
                    792:        break;
                    793:     case SM501_MISC_CONTROL:
                    794:        s->misc_control = value & 0xFF7FFF20;
                    795:        break;
                    796:     case SM501_GPIO31_0_CONTROL:
                    797:        s->gpio_31_0_control = value;
                    798:        break;
                    799:     case SM501_GPIO63_32_CONTROL:
                    800:        s->gpio_63_32_control = value;
                    801:        break;
                    802:     case SM501_DRAM_CONTROL:
                    803:        s->local_mem_size_index = (value >> 13) & 0x7;
                    804:        /* rODO : check validity of size change */
                    805:        s->dram_control |=  value & 0x7FFFFFC3;
                    806:        break;
                    807:     case SM501_IRQ_MASK:
                    808:        s->irq_mask = value;
                    809:        break;
                    810:     case SM501_MISC_TIMING:
                    811:        s->misc_timing = value & 0xF31F1FFF;
                    812:        break;
                    813:     case SM501_POWER_MODE_0_GATE:
                    814:     case SM501_POWER_MODE_1_GATE:
                    815:     case SM501_POWER_MODE_0_CLOCK:
                    816:     case SM501_POWER_MODE_1_CLOCK:
                    817:        /* TODO : simulate gate & clock control */
                    818:        break;
                    819:     case SM501_POWER_MODE_CONTROL:
                    820:        s->power_mode_control = value & 0x00000003;
                    821:        break;
                    822: 
                    823:     default:
                    824:        printf("sm501 system config : not implemented register write."
1.1.1.6   root      825:               " addr=%x, val=%x\n", (int)addr, (uint32_t)value);
1.1.1.4   root      826:         abort();
1.1       root      827:     }
                    828: }
                    829: 
1.1.1.6   root      830: static const MemoryRegionOps sm501_system_config_ops = {
                    831:     .read = sm501_system_config_read,
                    832:     .write = sm501_system_config_write,
                    833:     .valid = {
                    834:         .min_access_size = 4,
                    835:         .max_access_size = 4,
                    836:     },
                    837:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1       root      838: };
                    839: 
                    840: static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr)
                    841: {
                    842:     SM501State * s = (SM501State *)opaque;
                    843:     SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr);
                    844: 
                    845:     /* TODO : consider BYTE/WORD access */
                    846:     /* TODO : consider endian */
                    847: 
1.1.1.5   root      848:     assert(range_covers_byte(0, 0x400 * 3, addr));
1.1       root      849:     return *(uint32_t*)&s->dc_palette[addr];
                    850: }
                    851: 
                    852: static void sm501_palette_write(void *opaque,
                    853:                                target_phys_addr_t addr, uint32_t value)
                    854: {
                    855:     SM501State * s = (SM501State *)opaque;
                    856:     SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n",
                    857:                  (int)addr, value);
                    858: 
                    859:     /* TODO : consider BYTE/WORD access */
                    860:     /* TODO : consider endian */
                    861: 
1.1.1.5   root      862:     assert(range_covers_byte(0, 0x400 * 3, addr));
1.1       root      863:     *(uint32_t*)&s->dc_palette[addr] = value;
                    864: }
                    865: 
1.1.1.6   root      866: static uint64_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr,
                    867:                                      unsigned size)
1.1       root      868: {
                    869:     SM501State * s = (SM501State *)opaque;
                    870:     uint32_t ret = 0;
                    871:     SM501_DPRINTF("sm501 disp ctrl regs : read addr=%x\n", (int)addr);
                    872: 
                    873:     switch(addr) {
                    874: 
                    875:     case SM501_DC_PANEL_CONTROL:
                    876:        ret = s->dc_panel_control;
                    877:        break;
                    878:     case SM501_DC_PANEL_PANNING_CONTROL:
                    879:        ret = s->dc_panel_panning_control;
                    880:        break;
                    881:     case SM501_DC_PANEL_FB_ADDR:
                    882:        ret = s->dc_panel_fb_addr;
                    883:        break;
                    884:     case SM501_DC_PANEL_FB_OFFSET:
                    885:        ret = s->dc_panel_fb_offset;
                    886:        break;
                    887:     case SM501_DC_PANEL_FB_WIDTH:
                    888:        ret = s->dc_panel_fb_width;
                    889:        break;
                    890:     case SM501_DC_PANEL_FB_HEIGHT:
                    891:        ret = s->dc_panel_fb_height;
                    892:        break;
                    893:     case SM501_DC_PANEL_TL_LOC:
                    894:        ret = s->dc_panel_tl_location;
                    895:        break;
                    896:     case SM501_DC_PANEL_BR_LOC:
                    897:        ret = s->dc_panel_br_location;
                    898:        break;
                    899: 
                    900:     case SM501_DC_PANEL_H_TOT:
                    901:        ret = s->dc_panel_h_total;
                    902:        break;
                    903:     case SM501_DC_PANEL_H_SYNC:
                    904:        ret = s->dc_panel_h_sync;
                    905:        break;
                    906:     case SM501_DC_PANEL_V_TOT:
                    907:        ret = s->dc_panel_v_total;
                    908:        break;
                    909:     case SM501_DC_PANEL_V_SYNC:
                    910:        ret = s->dc_panel_v_sync;
                    911:        break;
                    912: 
                    913:     case SM501_DC_CRT_CONTROL:
                    914:        ret = s->dc_crt_control;
                    915:        break;
                    916:     case SM501_DC_CRT_FB_ADDR:
                    917:        ret = s->dc_crt_fb_addr;
                    918:        break;
                    919:     case SM501_DC_CRT_FB_OFFSET:
                    920:        ret = s->dc_crt_fb_offset;
                    921:        break;
                    922:     case SM501_DC_CRT_H_TOT:
                    923:        ret = s->dc_crt_h_total;
                    924:        break;
                    925:     case SM501_DC_CRT_H_SYNC:
                    926:        ret = s->dc_crt_h_sync;
                    927:        break;
                    928:     case SM501_DC_CRT_V_TOT:
                    929:        ret = s->dc_crt_v_total;
                    930:        break;
                    931:     case SM501_DC_CRT_V_SYNC:
                    932:        ret = s->dc_crt_v_sync;
                    933:        break;
                    934: 
                    935:     case SM501_DC_CRT_HWC_ADDR:
                    936:        ret = s->dc_crt_hwc_addr;
                    937:        break;
                    938:     case SM501_DC_CRT_HWC_LOC:
1.1.1.4   root      939:        ret = s->dc_crt_hwc_location;
1.1       root      940:        break;
                    941:     case SM501_DC_CRT_HWC_COLOR_1_2:
1.1.1.4   root      942:        ret = s->dc_crt_hwc_color_1_2;
1.1       root      943:        break;
                    944:     case SM501_DC_CRT_HWC_COLOR_3:
1.1.1.4   root      945:        ret = s->dc_crt_hwc_color_3;
1.1       root      946:        break;
                    947: 
                    948:     case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
                    949:         ret = sm501_palette_read(opaque, addr - SM501_DC_PANEL_PALETTE);
                    950:         break;
                    951: 
                    952:     default:
                    953:        printf("sm501 disp ctrl : not implemented register read."
                    954:               " addr=%x\n", (int)addr);
1.1.1.4   root      955:         abort();
1.1       root      956:     }
                    957: 
                    958:     return ret;
                    959: }
                    960: 
1.1.1.6   root      961: static void sm501_disp_ctrl_write(void *opaque, target_phys_addr_t addr,
                    962:                                   uint64_t value, unsigned size)
1.1       root      963: {
                    964:     SM501State * s = (SM501State *)opaque;
                    965:     SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n",
1.1.1.6   root      966:                  (unsigned)addr, (unsigned)value);
1.1       root      967: 
                    968:     switch(addr) {
                    969:     case SM501_DC_PANEL_CONTROL:
                    970:        s->dc_panel_control = value & 0x0FFF73FF;
                    971:        break;
                    972:     case SM501_DC_PANEL_PANNING_CONTROL:
                    973:        s->dc_panel_panning_control = value & 0xFF3FFF3F;
                    974:        break;
                    975:     case SM501_DC_PANEL_FB_ADDR:
                    976:        s->dc_panel_fb_addr = value & 0x8FFFFFF0;
                    977:        break;
                    978:     case SM501_DC_PANEL_FB_OFFSET:
                    979:        s->dc_panel_fb_offset = value & 0x3FF03FF0;
                    980:        break;
                    981:     case SM501_DC_PANEL_FB_WIDTH:
                    982:        s->dc_panel_fb_width = value & 0x0FFF0FFF;
                    983:        break;
                    984:     case SM501_DC_PANEL_FB_HEIGHT:
                    985:        s->dc_panel_fb_height = value & 0x0FFF0FFF;
                    986:        break;
                    987:     case SM501_DC_PANEL_TL_LOC:
                    988:        s->dc_panel_tl_location = value & 0x07FF07FF;
                    989:        break;
                    990:     case SM501_DC_PANEL_BR_LOC:
                    991:        s->dc_panel_br_location = value & 0x07FF07FF;
                    992:        break;
                    993: 
                    994:     case SM501_DC_PANEL_H_TOT:
                    995:        s->dc_panel_h_total = value & 0x0FFF0FFF;
                    996:        break;
                    997:     case SM501_DC_PANEL_H_SYNC:
                    998:        s->dc_panel_h_sync = value & 0x00FF0FFF;
                    999:        break;
                   1000:     case SM501_DC_PANEL_V_TOT:
                   1001:        s->dc_panel_v_total = value & 0x0FFF0FFF;
                   1002:        break;
                   1003:     case SM501_DC_PANEL_V_SYNC:
                   1004:        s->dc_panel_v_sync = value & 0x003F0FFF;
                   1005:        break;
                   1006: 
                   1007:     case SM501_DC_PANEL_HWC_ADDR:
                   1008:        s->dc_panel_hwc_addr = value & 0x8FFFFFF0;
                   1009:        break;
                   1010:     case SM501_DC_PANEL_HWC_LOC:
1.1.1.4   root     1011:        s->dc_panel_hwc_location = value & 0x0FFF0FFF;
1.1       root     1012:        break;
                   1013:     case SM501_DC_PANEL_HWC_COLOR_1_2:
1.1.1.4   root     1014:        s->dc_panel_hwc_color_1_2 = value;
1.1       root     1015:        break;
                   1016:     case SM501_DC_PANEL_HWC_COLOR_3:
1.1.1.4   root     1017:        s->dc_panel_hwc_color_3 = value & 0x0000FFFF;
1.1       root     1018:        break;
                   1019: 
                   1020:     case SM501_DC_CRT_CONTROL:
                   1021:        s->dc_crt_control = value & 0x0003FFFF;
                   1022:        break;
                   1023:     case SM501_DC_CRT_FB_ADDR:
                   1024:        s->dc_crt_fb_addr = value & 0x8FFFFFF0;
                   1025:        break;
                   1026:     case SM501_DC_CRT_FB_OFFSET:
                   1027:        s->dc_crt_fb_offset = value & 0x3FF03FF0;
                   1028:        break;
                   1029:     case SM501_DC_CRT_H_TOT:
                   1030:        s->dc_crt_h_total = value & 0x0FFF0FFF;
                   1031:        break;
                   1032:     case SM501_DC_CRT_H_SYNC:
                   1033:        s->dc_crt_h_sync = value & 0x00FF0FFF;
                   1034:        break;
                   1035:     case SM501_DC_CRT_V_TOT:
                   1036:        s->dc_crt_v_total = value & 0x0FFF0FFF;
                   1037:        break;
                   1038:     case SM501_DC_CRT_V_SYNC:
                   1039:        s->dc_crt_v_sync = value & 0x003F0FFF;
                   1040:        break;
                   1041: 
                   1042:     case SM501_DC_CRT_HWC_ADDR:
                   1043:        s->dc_crt_hwc_addr = value & 0x8FFFFFF0;
                   1044:        break;
                   1045:     case SM501_DC_CRT_HWC_LOC:
1.1.1.4   root     1046:        s->dc_crt_hwc_location = value & 0x0FFF0FFF;
1.1       root     1047:        break;
                   1048:     case SM501_DC_CRT_HWC_COLOR_1_2:
1.1.1.4   root     1049:        s->dc_crt_hwc_color_1_2 = value;
1.1       root     1050:        break;
                   1051:     case SM501_DC_CRT_HWC_COLOR_3:
1.1.1.4   root     1052:        s->dc_crt_hwc_color_3 = value & 0x0000FFFF;
1.1       root     1053:        break;
                   1054: 
                   1055:     case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
                   1056:         sm501_palette_write(opaque, addr - SM501_DC_PANEL_PALETTE, value);
                   1057:         break;
                   1058: 
                   1059:     default:
                   1060:        printf("sm501 disp ctrl : not implemented register write."
1.1.1.6   root     1061:               " addr=%x, val=%x\n", (int)addr, (unsigned)value);
1.1.1.4   root     1062:         abort();
1.1       root     1063:     }
                   1064: }
                   1065: 
1.1.1.6   root     1066: static const MemoryRegionOps sm501_disp_ctrl_ops = {
                   1067:     .read = sm501_disp_ctrl_read,
                   1068:     .write = sm501_disp_ctrl_write,
                   1069:     .valid = {
                   1070:         .min_access_size = 4,
                   1071:         .max_access_size = 4,
                   1072:     },
                   1073:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1       root     1074: };
                   1075: 
1.1.1.6   root     1076: static uint64_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr,
                   1077:                                      unsigned size)
1.1.1.4   root     1078: {
                   1079:     SM501State * s = (SM501State *)opaque;
                   1080:     uint32_t ret = 0;
                   1081:     SM501_DPRINTF("sm501 2d engine regs : read addr=%x\n", (int)addr);
                   1082: 
                   1083:     switch(addr) {
                   1084:     case SM501_2D_SOURCE_BASE:
                   1085:         ret = s->twoD_source_base;
                   1086:         break;
                   1087:     default:
                   1088:         printf("sm501 disp ctrl : not implemented register read."
                   1089:                " addr=%x\n", (int)addr);
                   1090:         abort();
                   1091:     }
                   1092: 
                   1093:     return ret;
                   1094: }
                   1095: 
1.1.1.6   root     1096: static void sm501_2d_engine_write(void *opaque, target_phys_addr_t addr,
                   1097:                                   uint64_t value, unsigned size)
1.1.1.4   root     1098: {
                   1099:     SM501State * s = (SM501State *)opaque;
                   1100:     SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n",
1.1.1.6   root     1101:                   (unsigned)addr, (unsigned)value);
1.1.1.4   root     1102: 
                   1103:     switch(addr) {
1.1.1.5   root     1104:     case SM501_2D_SOURCE:
                   1105:         s->twoD_source = value;
                   1106:         break;
1.1.1.4   root     1107:     case SM501_2D_DESTINATION:
                   1108:         s->twoD_destination = value;
                   1109:         break;
                   1110:     case SM501_2D_DIMENSION:
                   1111:         s->twoD_dimension = value;
                   1112:         break;
                   1113:     case SM501_2D_CONTROL:
                   1114:         s->twoD_control = value;
                   1115: 
                   1116:         /* do 2d operation if start flag is set. */
                   1117:         if (value & 0x80000000) {
                   1118:             sm501_2d_operation(s);
                   1119:             s->twoD_control &= ~0x80000000; /* start flag down */
                   1120:         }
                   1121: 
                   1122:         break;
                   1123:     case SM501_2D_PITCH:
                   1124:         s->twoD_pitch = value;
                   1125:         break;
                   1126:     case SM501_2D_FOREGROUND:
                   1127:         s->twoD_foreground = value;
                   1128:         break;
                   1129:     case SM501_2D_STRETCH:
                   1130:         s->twoD_stretch = value;
                   1131:         break;
                   1132:     case SM501_2D_COLOR_COMPARE_MASK:
                   1133:         s->twoD_color_compare_mask = value;
                   1134:         break;
                   1135:     case SM501_2D_MASK:
                   1136:         s->twoD_mask = value;
                   1137:         break;
                   1138:     case SM501_2D_WINDOW_WIDTH:
                   1139:         s->twoD_window_width = value;
                   1140:         break;
                   1141:     case SM501_2D_SOURCE_BASE:
                   1142:         s->twoD_source_base = value;
                   1143:         break;
                   1144:     case SM501_2D_DESTINATION_BASE:
                   1145:         s->twoD_destination_base = value;
                   1146:         break;
                   1147:     default:
                   1148:         printf("sm501 2d engine : not implemented register write."
1.1.1.6   root     1149:                " addr=%x, val=%x\n", (int)addr, (unsigned)value);
1.1.1.4   root     1150:         abort();
                   1151:     }
                   1152: }
                   1153: 
1.1.1.6   root     1154: static const MemoryRegionOps sm501_2d_engine_ops = {
                   1155:     .read = sm501_2d_engine_read,
                   1156:     .write = sm501_2d_engine_write,
                   1157:     .valid = {
                   1158:         .min_access_size = 4,
                   1159:         .max_access_size = 4,
                   1160:     },
                   1161:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1.1.4   root     1162: };
                   1163: 
1.1       root     1164: /* draw line functions for all console modes */
                   1165: 
                   1166: #include "pixel_ops.h"
                   1167: 
                   1168: typedef void draw_line_func(uint8_t *d, const uint8_t *s,
                   1169:                            int width, const uint32_t *pal);
                   1170: 
1.1.1.4   root     1171: typedef void draw_hwc_line_func(SM501State * s, int crt, uint8_t * palette,
                   1172:                                 int c_y, uint8_t *d, int width);
                   1173: 
1.1       root     1174: #define DEPTH 8
                   1175: #include "sm501_template.h"
                   1176: 
                   1177: #define DEPTH 15
                   1178: #include "sm501_template.h"
                   1179: 
                   1180: #define BGR_FORMAT
                   1181: #define DEPTH 15
                   1182: #include "sm501_template.h"
                   1183: 
                   1184: #define DEPTH 16
                   1185: #include "sm501_template.h"
                   1186: 
                   1187: #define BGR_FORMAT
                   1188: #define DEPTH 16
                   1189: #include "sm501_template.h"
                   1190: 
                   1191: #define DEPTH 32
                   1192: #include "sm501_template.h"
                   1193: 
                   1194: #define BGR_FORMAT
                   1195: #define DEPTH 32
                   1196: #include "sm501_template.h"
                   1197: 
                   1198: static draw_line_func * draw_line8_funcs[] = {
                   1199:     draw_line8_8,
                   1200:     draw_line8_15,
                   1201:     draw_line8_16,
                   1202:     draw_line8_32,
                   1203:     draw_line8_32bgr,
                   1204:     draw_line8_15bgr,
                   1205:     draw_line8_16bgr,
                   1206: };
                   1207: 
                   1208: static draw_line_func * draw_line16_funcs[] = {
                   1209:     draw_line16_8,
                   1210:     draw_line16_15,
                   1211:     draw_line16_16,
                   1212:     draw_line16_32,
                   1213:     draw_line16_32bgr,
                   1214:     draw_line16_15bgr,
                   1215:     draw_line16_16bgr,
                   1216: };
                   1217: 
                   1218: static draw_line_func * draw_line32_funcs[] = {
                   1219:     draw_line32_8,
                   1220:     draw_line32_15,
                   1221:     draw_line32_16,
                   1222:     draw_line32_32,
                   1223:     draw_line32_32bgr,
                   1224:     draw_line32_15bgr,
                   1225:     draw_line32_16bgr,
                   1226: };
                   1227: 
1.1.1.4   root     1228: static draw_hwc_line_func * draw_hwc_line_funcs[] = {
                   1229:     draw_hwc_line_8,
                   1230:     draw_hwc_line_15,
                   1231:     draw_hwc_line_16,
                   1232:     draw_hwc_line_32,
                   1233:     draw_hwc_line_32bgr,
                   1234:     draw_hwc_line_15bgr,
                   1235:     draw_hwc_line_16bgr,
                   1236: };
                   1237: 
1.1       root     1238: static inline int get_depth_index(DisplayState *s)
                   1239: {
                   1240:     switch(ds_get_bits_per_pixel(s)) {
                   1241:     default:
                   1242:     case 8:
                   1243:        return 0;
                   1244:     case 15:
                   1245:         return 1;
                   1246:     case 16:
                   1247:         return 2;
                   1248:     case 32:
1.1.1.2   root     1249:        if (is_surface_bgr(s->surface))
                   1250:            return 4;
                   1251:        else
                   1252:            return 3;
1.1       root     1253:     }
                   1254: }
                   1255: 
                   1256: static void sm501_draw_crt(SM501State * s)
                   1257: {
                   1258:     int y;
                   1259:     int width = (s->dc_crt_h_total & 0x00000FFF) + 1;
                   1260:     int height = (s->dc_crt_v_total & 0x00000FFF) + 1;
                   1261: 
                   1262:     uint8_t  * src = s->local_mem;
                   1263:     int src_bpp = 0;
                   1264:     int dst_bpp = ds_get_bytes_per_pixel(s->ds) + (ds_get_bits_per_pixel(s->ds) % 8 ? 1 : 0);
                   1265:     uint32_t * palette = (uint32_t *)&s->dc_palette[SM501_DC_CRT_PALETTE
                   1266:                                                    - SM501_DC_PANEL_PALETTE];
1.1.1.4   root     1267:     uint8_t hwc_palette[3 * 3];
1.1       root     1268:     int ds_depth_index = get_depth_index(s->ds);
                   1269:     draw_line_func * draw_line = NULL;
1.1.1.4   root     1270:     draw_hwc_line_func * draw_hwc_line = NULL;
1.1       root     1271:     int full_update = 0;
                   1272:     int y_start = -1;
1.1.1.5   root     1273:     ram_addr_t page_min = ~0l;
                   1274:     ram_addr_t page_max = 0l;
1.1.1.6   root     1275:     ram_addr_t offset = 0;
1.1       root     1276: 
                   1277:     /* choose draw_line function */
                   1278:     switch (s->dc_crt_control & 3) {
                   1279:     case SM501_DC_CRT_CONTROL_8BPP:
                   1280:        src_bpp = 1;
                   1281:        draw_line = draw_line8_funcs[ds_depth_index];
                   1282:        break;
                   1283:     case SM501_DC_CRT_CONTROL_16BPP:
                   1284:        src_bpp = 2;
                   1285:        draw_line = draw_line16_funcs[ds_depth_index];
                   1286:        break;
                   1287:     case SM501_DC_CRT_CONTROL_32BPP:
                   1288:        src_bpp = 4;
                   1289:        draw_line = draw_line32_funcs[ds_depth_index];
                   1290:        break;
                   1291:     default:
                   1292:        printf("sm501 draw crt : invalid DC_CRT_CONTROL=%x.\n",
                   1293:               s->dc_crt_control);
1.1.1.4   root     1294:         abort();
1.1       root     1295:        break;
                   1296:     }
                   1297: 
1.1.1.4   root     1298:     /* set up to draw hardware cursor */
                   1299:     if (is_hwc_enabled(s, 1)) {
                   1300:         int i;
                   1301: 
                   1302:         /* get cursor palette */
                   1303:         for (i = 0; i < 3; i++) {
                   1304:             uint16_t rgb565 = get_hwc_color(s, 1, i + 1);
                   1305:             hwc_palette[i * 3 + 0] = (rgb565 & 0xf800) >> 8; /* red */
                   1306:             hwc_palette[i * 3 + 1] = (rgb565 & 0x07e0) >> 3; /* green */
                   1307:             hwc_palette[i * 3 + 2] = (rgb565 & 0x001f) << 3; /* blue */
                   1308:         }
                   1309: 
                   1310:         /* choose cursor draw line function */
                   1311:         draw_hwc_line = draw_hwc_line_funcs[ds_depth_index];
                   1312:     }
                   1313: 
1.1       root     1314:     /* adjust console size */
                   1315:     if (s->last_width != width || s->last_height != height) {
                   1316:        qemu_console_resize(s->ds, width, height);
                   1317:        s->last_width = width;
                   1318:        s->last_height = height;
                   1319:        full_update = 1;
                   1320:     }
                   1321: 
                   1322:     /* draw each line according to conditions */
                   1323:     for (y = 0; y < height; y++) {
1.1.1.4   root     1324:        int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
                   1325:        int update = full_update || update_hwc;
1.1.1.7 ! root     1326:         ram_addr_t page0 = offset;
        !          1327:         ram_addr_t page1 = offset + width * src_bpp - 1;
1.1       root     1328: 
                   1329:        /* check dirty flags for each line */
1.1.1.7 ! root     1330:         update = memory_region_get_dirty(&s->local_mem_region, page0,
        !          1331:                                          page1 - page0, DIRTY_MEMORY_VGA);
1.1       root     1332: 
                   1333:        /* draw line and change status */
                   1334:        if (update) {
1.1.1.4   root     1335:             uint8_t * d = &(ds_get_data(s->ds)[y * width * dst_bpp]);
                   1336: 
                   1337:             /* draw graphics layer */
                   1338:             draw_line(d, src, width, palette);
                   1339: 
                   1340:             /* draw haredware cursor */
                   1341:             if (update_hwc) {
                   1342:                 draw_hwc_line(s, 1, hwc_palette, y - get_hwc_y(s, 1), d, width);
                   1343:             }
                   1344: 
1.1       root     1345:            if (y_start < 0)
                   1346:                y_start = y;
                   1347:            if (page0 < page_min)
                   1348:                page_min = page0;
                   1349:            if (page1 > page_max)
                   1350:                page_max = page1;
                   1351:        } else {
                   1352:            if (y_start >= 0) {
                   1353:                /* flush to display */
                   1354:                dpy_update(s->ds, 0, y_start, width, y - y_start);
                   1355:                y_start = -1;
                   1356:            }
                   1357:        }
                   1358: 
                   1359:        src += width * src_bpp;
1.1.1.2   root     1360:        offset += width * src_bpp;
1.1       root     1361:     }
                   1362: 
                   1363:     /* complete flush to display */
                   1364:     if (y_start >= 0)
                   1365:        dpy_update(s->ds, 0, y_start, width, y - y_start);
                   1366: 
                   1367:     /* clear dirty flags */
1.1.1.5   root     1368:     if (page_min != ~0l) {
1.1.1.6   root     1369:        memory_region_reset_dirty(&s->local_mem_region,
                   1370:                                   page_min, page_max + TARGET_PAGE_SIZE,
                   1371:                                   DIRTY_MEMORY_VGA);
1.1.1.5   root     1372:     }
1.1       root     1373: }
                   1374: 
                   1375: static void sm501_update_display(void *opaque)
                   1376: {
                   1377:     SM501State * s = (SM501State *)opaque;
                   1378: 
                   1379:     if (s->dc_crt_control & SM501_DC_CRT_CONTROL_ENABLE)
                   1380:        sm501_draw_crt(s);
                   1381: }
                   1382: 
1.1.1.6   root     1383: void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
                   1384:                 uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr)
1.1       root     1385: {
                   1386:     SM501State * s;
1.1.1.4   root     1387:     DeviceState *dev;
1.1.1.6   root     1388:     MemoryRegion *sm501_system_config = g_new(MemoryRegion, 1);
                   1389:     MemoryRegion *sm501_disp_ctrl = g_new(MemoryRegion, 1);
                   1390:     MemoryRegion *sm501_2d_engine = g_new(MemoryRegion, 1);
1.1       root     1391: 
                   1392:     /* allocate management data region */
1.1.1.6   root     1393:     s = (SM501State *)g_malloc0(sizeof(SM501State));
1.1       root     1394:     s->base = base;
                   1395:     s->local_mem_size_index
                   1396:        = get_local_mem_size_index(local_mem_bytes);
                   1397:     SM501_DPRINTF("local mem size=%x. index=%d\n", get_local_mem_size(s),
                   1398:                  s->local_mem_size_index);
                   1399:     s->system_control = 0x00100000;
                   1400:     s->misc_control = 0x00001000; /* assumes SH, active=low */
                   1401:     s->dc_panel_control = 0x00010000;
                   1402:     s->dc_crt_control = 0x00010000;
                   1403: 
                   1404:     /* allocate local memory */
1.1.1.7 ! root     1405:     memory_region_init_ram(&s->local_mem_region, "sm501.local",
1.1.1.6   root     1406:                            local_mem_bytes);
1.1.1.7 ! root     1407:     vmstate_register_ram_global(&s->local_mem_region);
1.1.1.6   root     1408:     s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region);
                   1409:     memory_region_add_subregion(address_space_mem, base, &s->local_mem_region);
1.1       root     1410: 
                   1411:     /* map mmio */
1.1.1.6   root     1412:     memory_region_init_io(sm501_system_config, &sm501_system_config_ops, s,
                   1413:                           "sm501-system-config", 0x6c);
                   1414:     memory_region_add_subregion(address_space_mem, base + MMIO_BASE_OFFSET,
                   1415:                                 sm501_system_config);
                   1416:     memory_region_init_io(sm501_disp_ctrl, &sm501_disp_ctrl_ops, s,
                   1417:                           "sm501-disp-ctrl", 0x1000);
                   1418:     memory_region_add_subregion(address_space_mem,
                   1419:                                 base + MMIO_BASE_OFFSET + SM501_DC,
                   1420:                                 sm501_disp_ctrl);
                   1421:     memory_region_init_io(sm501_2d_engine, &sm501_2d_engine_ops, s,
                   1422:                           "sm501-2d-engine", 0x54);
                   1423:     memory_region_add_subregion(address_space_mem,
                   1424:                                 base + MMIO_BASE_OFFSET + SM501_2D_ENGINE,
                   1425:                                 sm501_2d_engine);
1.1       root     1426: 
1.1.1.2   root     1427:     /* bridge to usb host emulation module */
1.1.1.4   root     1428:     dev = qdev_create(NULL, "sysbus-ohci");
                   1429:     qdev_prop_set_uint32(dev, "num-ports", 2);
                   1430:     qdev_prop_set_taddr(dev, "dma-offset", base);
                   1431:     qdev_init_nofail(dev);
                   1432:     sysbus_mmio_map(sysbus_from_qdev(dev), 0,
                   1433:                     base + MMIO_BASE_OFFSET + SM501_USB_HOST);
                   1434:     sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
1.1.1.2   root     1435: 
1.1       root     1436:     /* bridge to serial emulation module */
1.1.1.4   root     1437:     if (chr) {
1.1.1.6   root     1438:         serial_mm_init(address_space_mem,
                   1439:                        base + MMIO_BASE_OFFSET + SM501_UART0, 2,
1.1.1.4   root     1440:                        NULL, /* TODO : chain irq to IRL */
1.1.1.6   root     1441:                        115200, chr, DEVICE_NATIVE_ENDIAN);
1.1.1.4   root     1442:     }
1.1       root     1443: 
                   1444:     /* create qemu graphic console */
                   1445:     s->ds = graphic_console_init(sm501_update_display, NULL,
                   1446:                                 NULL, NULL, s);
                   1447: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.