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

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

unix.superglobalmegacorp.com

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