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

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.2   root      462:     ram_addr_t local_mem_offset;
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: {
                    596:     uint16_t color_reg = 0;
                    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       root      729: static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
                    730: {
                    731:     SM501State * s = (SM501State *)opaque;
                    732:     uint32_t ret = 0;
                    733:     SM501_DPRINTF("sm501 system config regs : read addr=%x\n", (int)addr);
                    734: 
                    735:     switch(addr) {
                    736:     case SM501_SYSTEM_CONTROL:
                    737:        ret = s->system_control;
                    738:        break;
                    739:     case SM501_MISC_CONTROL:
                    740:        ret = s->misc_control;
                    741:        break;
                    742:     case SM501_GPIO31_0_CONTROL:
                    743:        ret = s->gpio_31_0_control;
                    744:        break;
                    745:     case SM501_GPIO63_32_CONTROL:
                    746:        ret = s->gpio_63_32_control;
                    747:        break;
                    748:     case SM501_DEVICEID:
                    749:        ret = 0x050100A0;
                    750:        break;
                    751:     case SM501_DRAM_CONTROL:
                    752:        ret = (s->dram_control & 0x07F107C0) | s->local_mem_size_index << 13;
                    753:        break;
                    754:     case SM501_IRQ_MASK:
                    755:        ret = s->irq_mask;
                    756:        break;
                    757:     case SM501_MISC_TIMING:
                    758:        /* TODO : simulate gate control */
                    759:        ret = s->misc_timing;
                    760:        break;
                    761:     case SM501_CURRENT_GATE:
                    762:        /* TODO : simulate gate control */
                    763:        ret = 0x00021807;
                    764:        break;
                    765:     case SM501_CURRENT_CLOCK:
                    766:        ret = 0x2A1A0A09;
                    767:        break;
                    768:     case SM501_POWER_MODE_CONTROL:
                    769:        ret = s->power_mode_control;
                    770:        break;
                    771: 
                    772:     default:
                    773:        printf("sm501 system config : not implemented register read."
                    774:               " addr=%x\n", (int)addr);
1.1.1.4   root      775:         abort();
1.1       root      776:     }
                    777: 
                    778:     return ret;
                    779: }
                    780: 
                    781: static void sm501_system_config_write(void *opaque,
                    782:                                      target_phys_addr_t addr, uint32_t value)
                    783: {
                    784:     SM501State * s = (SM501State *)opaque;
                    785:     SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n",
                    786:                  addr, value);
                    787: 
                    788:     switch(addr) {
                    789:     case SM501_SYSTEM_CONTROL:
                    790:        s->system_control = value & 0xE300B8F7;
                    791:        break;
                    792:     case SM501_MISC_CONTROL:
                    793:        s->misc_control = value & 0xFF7FFF20;
                    794:        break;
                    795:     case SM501_GPIO31_0_CONTROL:
                    796:        s->gpio_31_0_control = value;
                    797:        break;
                    798:     case SM501_GPIO63_32_CONTROL:
                    799:        s->gpio_63_32_control = value;
                    800:        break;
                    801:     case SM501_DRAM_CONTROL:
                    802:        s->local_mem_size_index = (value >> 13) & 0x7;
                    803:        /* rODO : check validity of size change */
                    804:        s->dram_control |=  value & 0x7FFFFFC3;
                    805:        break;
                    806:     case SM501_IRQ_MASK:
                    807:        s->irq_mask = value;
                    808:        break;
                    809:     case SM501_MISC_TIMING:
                    810:        s->misc_timing = value & 0xF31F1FFF;
                    811:        break;
                    812:     case SM501_POWER_MODE_0_GATE:
                    813:     case SM501_POWER_MODE_1_GATE:
                    814:     case SM501_POWER_MODE_0_CLOCK:
                    815:     case SM501_POWER_MODE_1_CLOCK:
                    816:        /* TODO : simulate gate & clock control */
                    817:        break;
                    818:     case SM501_POWER_MODE_CONTROL:
                    819:        s->power_mode_control = value & 0x00000003;
                    820:        break;
                    821: 
                    822:     default:
                    823:        printf("sm501 system config : not implemented register write."
                    824:               " addr=%x, val=%x\n", (int)addr, value);
1.1.1.4   root      825:         abort();
1.1       root      826:     }
                    827: }
                    828: 
1.1.1.3   root      829: static CPUReadMemoryFunc * const sm501_system_config_readfn[] = {
1.1       root      830:     NULL,
                    831:     NULL,
                    832:     &sm501_system_config_read,
                    833: };
                    834: 
1.1.1.3   root      835: static CPUWriteMemoryFunc * const sm501_system_config_writefn[] = {
1.1       root      836:     NULL,
                    837:     NULL,
                    838:     &sm501_system_config_write,
                    839: };
                    840: 
                    841: static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr)
                    842: {
                    843:     SM501State * s = (SM501State *)opaque;
                    844:     SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr);
                    845: 
                    846:     /* TODO : consider BYTE/WORD access */
                    847:     /* TODO : consider endian */
                    848: 
1.1.1.5 ! root      849:     assert(range_covers_byte(0, 0x400 * 3, addr));
1.1       root      850:     return *(uint32_t*)&s->dc_palette[addr];
                    851: }
                    852: 
                    853: static void sm501_palette_write(void *opaque,
                    854:                                target_phys_addr_t addr, uint32_t value)
                    855: {
                    856:     SM501State * s = (SM501State *)opaque;
                    857:     SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n",
                    858:                  (int)addr, value);
                    859: 
                    860:     /* TODO : consider BYTE/WORD access */
                    861:     /* TODO : consider endian */
                    862: 
1.1.1.5 ! root      863:     assert(range_covers_byte(0, 0x400 * 3, addr));
1.1       root      864:     *(uint32_t*)&s->dc_palette[addr] = value;
                    865: }
                    866: 
                    867: static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr)
                    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: 
                    961: static void sm501_disp_ctrl_write(void *opaque,
                    962:                                           target_phys_addr_t addr,
                    963:                                           uint32_t value)
                    964: {
                    965:     SM501State * s = (SM501State *)opaque;
                    966:     SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n",
                    967:                  addr, value);
                    968: 
                    969:     switch(addr) {
                    970:     case SM501_DC_PANEL_CONTROL:
                    971:        s->dc_panel_control = value & 0x0FFF73FF;
                    972:        break;
                    973:     case SM501_DC_PANEL_PANNING_CONTROL:
                    974:        s->dc_panel_panning_control = value & 0xFF3FFF3F;
                    975:        break;
                    976:     case SM501_DC_PANEL_FB_ADDR:
                    977:        s->dc_panel_fb_addr = value & 0x8FFFFFF0;
                    978:        break;
                    979:     case SM501_DC_PANEL_FB_OFFSET:
                    980:        s->dc_panel_fb_offset = value & 0x3FF03FF0;
                    981:        break;
                    982:     case SM501_DC_PANEL_FB_WIDTH:
                    983:        s->dc_panel_fb_width = value & 0x0FFF0FFF;
                    984:        break;
                    985:     case SM501_DC_PANEL_FB_HEIGHT:
                    986:        s->dc_panel_fb_height = value & 0x0FFF0FFF;
                    987:        break;
                    988:     case SM501_DC_PANEL_TL_LOC:
                    989:        s->dc_panel_tl_location = value & 0x07FF07FF;
                    990:        break;
                    991:     case SM501_DC_PANEL_BR_LOC:
                    992:        s->dc_panel_br_location = value & 0x07FF07FF;
                    993:        break;
                    994: 
                    995:     case SM501_DC_PANEL_H_TOT:
                    996:        s->dc_panel_h_total = value & 0x0FFF0FFF;
                    997:        break;
                    998:     case SM501_DC_PANEL_H_SYNC:
                    999:        s->dc_panel_h_sync = value & 0x00FF0FFF;
                   1000:        break;
                   1001:     case SM501_DC_PANEL_V_TOT:
                   1002:        s->dc_panel_v_total = value & 0x0FFF0FFF;
                   1003:        break;
                   1004:     case SM501_DC_PANEL_V_SYNC:
                   1005:        s->dc_panel_v_sync = value & 0x003F0FFF;
                   1006:        break;
                   1007: 
                   1008:     case SM501_DC_PANEL_HWC_ADDR:
                   1009:        s->dc_panel_hwc_addr = value & 0x8FFFFFF0;
                   1010:        break;
                   1011:     case SM501_DC_PANEL_HWC_LOC:
1.1.1.4   root     1012:        s->dc_panel_hwc_location = value & 0x0FFF0FFF;
1.1       root     1013:        break;
                   1014:     case SM501_DC_PANEL_HWC_COLOR_1_2:
1.1.1.4   root     1015:        s->dc_panel_hwc_color_1_2 = value;
1.1       root     1016:        break;
                   1017:     case SM501_DC_PANEL_HWC_COLOR_3:
1.1.1.4   root     1018:        s->dc_panel_hwc_color_3 = value & 0x0000FFFF;
1.1       root     1019:        break;
                   1020: 
                   1021:     case SM501_DC_CRT_CONTROL:
                   1022:        s->dc_crt_control = value & 0x0003FFFF;
                   1023:        break;
                   1024:     case SM501_DC_CRT_FB_ADDR:
                   1025:        s->dc_crt_fb_addr = value & 0x8FFFFFF0;
                   1026:        break;
                   1027:     case SM501_DC_CRT_FB_OFFSET:
                   1028:        s->dc_crt_fb_offset = value & 0x3FF03FF0;
                   1029:        break;
                   1030:     case SM501_DC_CRT_H_TOT:
                   1031:        s->dc_crt_h_total = value & 0x0FFF0FFF;
                   1032:        break;
                   1033:     case SM501_DC_CRT_H_SYNC:
                   1034:        s->dc_crt_h_sync = value & 0x00FF0FFF;
                   1035:        break;
                   1036:     case SM501_DC_CRT_V_TOT:
                   1037:        s->dc_crt_v_total = value & 0x0FFF0FFF;
                   1038:        break;
                   1039:     case SM501_DC_CRT_V_SYNC:
                   1040:        s->dc_crt_v_sync = value & 0x003F0FFF;
                   1041:        break;
                   1042: 
                   1043:     case SM501_DC_CRT_HWC_ADDR:
                   1044:        s->dc_crt_hwc_addr = value & 0x8FFFFFF0;
                   1045:        break;
                   1046:     case SM501_DC_CRT_HWC_LOC:
1.1.1.4   root     1047:        s->dc_crt_hwc_location = value & 0x0FFF0FFF;
1.1       root     1048:        break;
                   1049:     case SM501_DC_CRT_HWC_COLOR_1_2:
1.1.1.4   root     1050:        s->dc_crt_hwc_color_1_2 = value;
1.1       root     1051:        break;
                   1052:     case SM501_DC_CRT_HWC_COLOR_3:
1.1.1.4   root     1053:        s->dc_crt_hwc_color_3 = value & 0x0000FFFF;
1.1       root     1054:        break;
                   1055: 
                   1056:     case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
                   1057:         sm501_palette_write(opaque, addr - SM501_DC_PANEL_PALETTE, value);
                   1058:         break;
                   1059: 
                   1060:     default:
                   1061:        printf("sm501 disp ctrl : not implemented register write."
                   1062:               " addr=%x, val=%x\n", (int)addr, value);
1.1.1.4   root     1063:         abort();
1.1       root     1064:     }
                   1065: }
                   1066: 
1.1.1.3   root     1067: static CPUReadMemoryFunc * const sm501_disp_ctrl_readfn[] = {
1.1       root     1068:     NULL,
                   1069:     NULL,
                   1070:     &sm501_disp_ctrl_read,
                   1071: };
                   1072: 
1.1.1.3   root     1073: static CPUWriteMemoryFunc * const sm501_disp_ctrl_writefn[] = {
1.1       root     1074:     NULL,
                   1075:     NULL,
                   1076:     &sm501_disp_ctrl_write,
                   1077: };
                   1078: 
1.1.1.4   root     1079: static uint32_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr)
                   1080: {
                   1081:     SM501State * s = (SM501State *)opaque;
                   1082:     uint32_t ret = 0;
                   1083:     SM501_DPRINTF("sm501 2d engine regs : read addr=%x\n", (int)addr);
                   1084: 
                   1085:     switch(addr) {
                   1086:     case SM501_2D_SOURCE_BASE:
                   1087:         ret = s->twoD_source_base;
                   1088:         break;
                   1089:     default:
                   1090:         printf("sm501 disp ctrl : not implemented register read."
                   1091:                " addr=%x\n", (int)addr);
                   1092:         abort();
                   1093:     }
                   1094: 
                   1095:     return ret;
                   1096: }
                   1097: 
                   1098: static void sm501_2d_engine_write(void *opaque,
                   1099:                                   target_phys_addr_t addr, uint32_t value)
                   1100: {
                   1101:     SM501State * s = (SM501State *)opaque;
                   1102:     SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n",
                   1103:                   addr, value);
                   1104: 
                   1105:     switch(addr) {
1.1.1.5 ! root     1106:     case SM501_2D_SOURCE:
        !          1107:         s->twoD_source = value;
        !          1108:         break;
1.1.1.4   root     1109:     case SM501_2D_DESTINATION:
                   1110:         s->twoD_destination = value;
                   1111:         break;
                   1112:     case SM501_2D_DIMENSION:
                   1113:         s->twoD_dimension = value;
                   1114:         break;
                   1115:     case SM501_2D_CONTROL:
                   1116:         s->twoD_control = value;
                   1117: 
                   1118:         /* do 2d operation if start flag is set. */
                   1119:         if (value & 0x80000000) {
                   1120:             sm501_2d_operation(s);
                   1121:             s->twoD_control &= ~0x80000000; /* start flag down */
                   1122:         }
                   1123: 
                   1124:         break;
                   1125:     case SM501_2D_PITCH:
                   1126:         s->twoD_pitch = value;
                   1127:         break;
                   1128:     case SM501_2D_FOREGROUND:
                   1129:         s->twoD_foreground = value;
                   1130:         break;
                   1131:     case SM501_2D_STRETCH:
                   1132:         s->twoD_stretch = value;
                   1133:         break;
                   1134:     case SM501_2D_COLOR_COMPARE_MASK:
                   1135:         s->twoD_color_compare_mask = value;
                   1136:         break;
                   1137:     case SM501_2D_MASK:
                   1138:         s->twoD_mask = value;
                   1139:         break;
                   1140:     case SM501_2D_WINDOW_WIDTH:
                   1141:         s->twoD_window_width = value;
                   1142:         break;
                   1143:     case SM501_2D_SOURCE_BASE:
                   1144:         s->twoD_source_base = value;
                   1145:         break;
                   1146:     case SM501_2D_DESTINATION_BASE:
                   1147:         s->twoD_destination_base = value;
                   1148:         break;
                   1149:     default:
                   1150:         printf("sm501 2d engine : not implemented register write."
                   1151:                " addr=%x, val=%x\n", (int)addr, value);
                   1152:         abort();
                   1153:     }
                   1154: }
                   1155: 
                   1156: static CPUReadMemoryFunc * const sm501_2d_engine_readfn[] = {
                   1157:     NULL,
                   1158:     NULL,
                   1159:     &sm501_2d_engine_read,
                   1160: };
                   1161: 
                   1162: static CPUWriteMemoryFunc * const sm501_2d_engine_writefn[] = {
                   1163:     NULL,
                   1164:     NULL,
                   1165:     &sm501_2d_engine_write,
                   1166: };
                   1167: 
1.1       root     1168: /* draw line functions for all console modes */
                   1169: 
                   1170: #include "pixel_ops.h"
                   1171: 
                   1172: typedef void draw_line_func(uint8_t *d, const uint8_t *s,
                   1173:                            int width, const uint32_t *pal);
                   1174: 
1.1.1.4   root     1175: typedef void draw_hwc_line_func(SM501State * s, int crt, uint8_t * palette,
                   1176:                                 int c_y, uint8_t *d, int width);
                   1177: 
1.1       root     1178: #define DEPTH 8
                   1179: #include "sm501_template.h"
                   1180: 
                   1181: #define DEPTH 15
                   1182: #include "sm501_template.h"
                   1183: 
                   1184: #define BGR_FORMAT
                   1185: #define DEPTH 15
                   1186: #include "sm501_template.h"
                   1187: 
                   1188: #define DEPTH 16
                   1189: #include "sm501_template.h"
                   1190: 
                   1191: #define BGR_FORMAT
                   1192: #define DEPTH 16
                   1193: #include "sm501_template.h"
                   1194: 
                   1195: #define DEPTH 32
                   1196: #include "sm501_template.h"
                   1197: 
                   1198: #define BGR_FORMAT
                   1199: #define DEPTH 32
                   1200: #include "sm501_template.h"
                   1201: 
                   1202: static draw_line_func * draw_line8_funcs[] = {
                   1203:     draw_line8_8,
                   1204:     draw_line8_15,
                   1205:     draw_line8_16,
                   1206:     draw_line8_32,
                   1207:     draw_line8_32bgr,
                   1208:     draw_line8_15bgr,
                   1209:     draw_line8_16bgr,
                   1210: };
                   1211: 
                   1212: static draw_line_func * draw_line16_funcs[] = {
                   1213:     draw_line16_8,
                   1214:     draw_line16_15,
                   1215:     draw_line16_16,
                   1216:     draw_line16_32,
                   1217:     draw_line16_32bgr,
                   1218:     draw_line16_15bgr,
                   1219:     draw_line16_16bgr,
                   1220: };
                   1221: 
                   1222: static draw_line_func * draw_line32_funcs[] = {
                   1223:     draw_line32_8,
                   1224:     draw_line32_15,
                   1225:     draw_line32_16,
                   1226:     draw_line32_32,
                   1227:     draw_line32_32bgr,
                   1228:     draw_line32_15bgr,
                   1229:     draw_line32_16bgr,
                   1230: };
                   1231: 
1.1.1.4   root     1232: static draw_hwc_line_func * draw_hwc_line_funcs[] = {
                   1233:     draw_hwc_line_8,
                   1234:     draw_hwc_line_15,
                   1235:     draw_hwc_line_16,
                   1236:     draw_hwc_line_32,
                   1237:     draw_hwc_line_32bgr,
                   1238:     draw_hwc_line_15bgr,
                   1239:     draw_hwc_line_16bgr,
                   1240: };
                   1241: 
1.1       root     1242: static inline int get_depth_index(DisplayState *s)
                   1243: {
                   1244:     switch(ds_get_bits_per_pixel(s)) {
                   1245:     default:
                   1246:     case 8:
                   1247:        return 0;
                   1248:     case 15:
                   1249:         return 1;
                   1250:     case 16:
                   1251:         return 2;
                   1252:     case 32:
1.1.1.2   root     1253:        if (is_surface_bgr(s->surface))
                   1254:            return 4;
                   1255:        else
                   1256:            return 3;
1.1       root     1257:     }
                   1258: }
                   1259: 
                   1260: static void sm501_draw_crt(SM501State * s)
                   1261: {
                   1262:     int y;
                   1263:     int width = (s->dc_crt_h_total & 0x00000FFF) + 1;
                   1264:     int height = (s->dc_crt_v_total & 0x00000FFF) + 1;
                   1265: 
                   1266:     uint8_t  * src = s->local_mem;
                   1267:     int src_bpp = 0;
                   1268:     int dst_bpp = ds_get_bytes_per_pixel(s->ds) + (ds_get_bits_per_pixel(s->ds) % 8 ? 1 : 0);
                   1269:     uint32_t * palette = (uint32_t *)&s->dc_palette[SM501_DC_CRT_PALETTE
                   1270:                                                    - SM501_DC_PANEL_PALETTE];
1.1.1.4   root     1271:     uint8_t hwc_palette[3 * 3];
1.1       root     1272:     int ds_depth_index = get_depth_index(s->ds);
                   1273:     draw_line_func * draw_line = NULL;
1.1.1.4   root     1274:     draw_hwc_line_func * draw_hwc_line = NULL;
1.1       root     1275:     int full_update = 0;
                   1276:     int y_start = -1;
1.1.1.5 ! root     1277:     ram_addr_t page_min = ~0l;
        !          1278:     ram_addr_t page_max = 0l;
1.1.1.2   root     1279:     ram_addr_t offset = s->local_mem_offset;
1.1       root     1280: 
                   1281:     /* choose draw_line function */
                   1282:     switch (s->dc_crt_control & 3) {
                   1283:     case SM501_DC_CRT_CONTROL_8BPP:
                   1284:        src_bpp = 1;
                   1285:        draw_line = draw_line8_funcs[ds_depth_index];
                   1286:        break;
                   1287:     case SM501_DC_CRT_CONTROL_16BPP:
                   1288:        src_bpp = 2;
                   1289:        draw_line = draw_line16_funcs[ds_depth_index];
                   1290:        break;
                   1291:     case SM501_DC_CRT_CONTROL_32BPP:
                   1292:        src_bpp = 4;
                   1293:        draw_line = draw_line32_funcs[ds_depth_index];
                   1294:        break;
                   1295:     default:
                   1296:        printf("sm501 draw crt : invalid DC_CRT_CONTROL=%x.\n",
                   1297:               s->dc_crt_control);
1.1.1.4   root     1298:         abort();
1.1       root     1299:        break;
                   1300:     }
                   1301: 
1.1.1.4   root     1302:     /* set up to draw hardware cursor */
                   1303:     if (is_hwc_enabled(s, 1)) {
                   1304:         int i;
                   1305: 
                   1306:         /* get cursor palette */
                   1307:         for (i = 0; i < 3; i++) {
                   1308:             uint16_t rgb565 = get_hwc_color(s, 1, i + 1);
                   1309:             hwc_palette[i * 3 + 0] = (rgb565 & 0xf800) >> 8; /* red */
                   1310:             hwc_palette[i * 3 + 1] = (rgb565 & 0x07e0) >> 3; /* green */
                   1311:             hwc_palette[i * 3 + 2] = (rgb565 & 0x001f) << 3; /* blue */
                   1312:         }
                   1313: 
                   1314:         /* choose cursor draw line function */
                   1315:         draw_hwc_line = draw_hwc_line_funcs[ds_depth_index];
                   1316:     }
                   1317: 
1.1       root     1318:     /* adjust console size */
                   1319:     if (s->last_width != width || s->last_height != height) {
                   1320:        qemu_console_resize(s->ds, width, height);
                   1321:        s->last_width = width;
                   1322:        s->last_height = height;
                   1323:        full_update = 1;
                   1324:     }
                   1325: 
                   1326:     /* draw each line according to conditions */
                   1327:     for (y = 0; y < height; y++) {
1.1.1.4   root     1328:        int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
                   1329:        int update = full_update || update_hwc;
1.1.1.2   root     1330:        ram_addr_t page0 = offset & TARGET_PAGE_MASK;
                   1331:        ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK;
                   1332:        ram_addr_t page;
1.1       root     1333: 
                   1334:        /* check dirty flags for each line */
                   1335:        for (page = page0; page <= page1; page += TARGET_PAGE_SIZE)
                   1336:            if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG))
                   1337:                update = 1;
                   1338: 
                   1339:        /* draw line and change status */
                   1340:        if (update) {
1.1.1.4   root     1341:             uint8_t * d = &(ds_get_data(s->ds)[y * width * dst_bpp]);
                   1342: 
                   1343:             /* draw graphics layer */
                   1344:             draw_line(d, src, width, palette);
                   1345: 
                   1346:             /* draw haredware cursor */
                   1347:             if (update_hwc) {
                   1348:                 draw_hwc_line(s, 1, hwc_palette, y - get_hwc_y(s, 1), d, width);
                   1349:             }
                   1350: 
1.1       root     1351:            if (y_start < 0)
                   1352:                y_start = y;
                   1353:            if (page0 < page_min)
                   1354:                page_min = page0;
                   1355:            if (page1 > page_max)
                   1356:                page_max = page1;
                   1357:        } else {
                   1358:            if (y_start >= 0) {
                   1359:                /* flush to display */
                   1360:                dpy_update(s->ds, 0, y_start, width, y - y_start);
                   1361:                y_start = -1;
                   1362:            }
                   1363:        }
                   1364: 
                   1365:        src += width * src_bpp;
1.1.1.2   root     1366:        offset += width * src_bpp;
1.1       root     1367:     }
                   1368: 
                   1369:     /* complete flush to display */
                   1370:     if (y_start >= 0)
                   1371:        dpy_update(s->ds, 0, y_start, width, y - y_start);
                   1372: 
                   1373:     /* clear dirty flags */
1.1.1.5 ! root     1374:     if (page_min != ~0l) {
1.1       root     1375:        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
                   1376:                                        VGA_DIRTY_FLAG);
1.1.1.5 ! root     1377:     }
1.1       root     1378: }
                   1379: 
                   1380: static void sm501_update_display(void *opaque)
                   1381: {
                   1382:     SM501State * s = (SM501State *)opaque;
                   1383: 
                   1384:     if (s->dc_crt_control & SM501_DC_CRT_CONTROL_ENABLE)
                   1385:        sm501_draw_crt(s);
                   1386: }
                   1387: 
1.1.1.2   root     1388: void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
                   1389:                 CharDriverState *chr)
1.1       root     1390: {
                   1391:     SM501State * s;
1.1.1.4   root     1392:     DeviceState *dev;
1.1       root     1393:     int sm501_system_config_index;
                   1394:     int sm501_disp_ctrl_index;
1.1.1.4   root     1395:     int sm501_2d_engine_index;
1.1       root     1396: 
                   1397:     /* allocate management data region */
                   1398:     s = (SM501State *)qemu_mallocz(sizeof(SM501State));
                   1399:     s->base = base;
                   1400:     s->local_mem_size_index
                   1401:        = get_local_mem_size_index(local_mem_bytes);
                   1402:     SM501_DPRINTF("local mem size=%x. index=%d\n", get_local_mem_size(s),
                   1403:                  s->local_mem_size_index);
                   1404:     s->system_control = 0x00100000;
                   1405:     s->misc_control = 0x00001000; /* assumes SH, active=low */
                   1406:     s->dc_panel_control = 0x00010000;
                   1407:     s->dc_crt_control = 0x00010000;
                   1408: 
                   1409:     /* allocate local memory */
1.1.1.4   root     1410:     s->local_mem_offset = qemu_ram_alloc(NULL, "sm501.local", local_mem_bytes);
1.1.1.2   root     1411:     s->local_mem = qemu_get_ram_ptr(s->local_mem_offset);
                   1412:     cpu_register_physical_memory(base, local_mem_bytes, s->local_mem_offset);
1.1       root     1413: 
                   1414:     /* map mmio */
                   1415:     sm501_system_config_index
1.1.1.2   root     1416:        = cpu_register_io_memory(sm501_system_config_readfn,
1.1.1.5 ! root     1417:                                 sm501_system_config_writefn, s,
        !          1418:                                  DEVICE_NATIVE_ENDIAN);
1.1       root     1419:     cpu_register_physical_memory(base + MMIO_BASE_OFFSET,
                   1420:                                 0x6c, sm501_system_config_index);
1.1.1.2   root     1421:     sm501_disp_ctrl_index = cpu_register_io_memory(sm501_disp_ctrl_readfn,
1.1.1.5 ! root     1422:                                                   sm501_disp_ctrl_writefn, s,
        !          1423:                                                    DEVICE_NATIVE_ENDIAN);
1.1       root     1424:     cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
                   1425:                                  0x1000, sm501_disp_ctrl_index);
1.1.1.4   root     1426:     sm501_2d_engine_index = cpu_register_io_memory(sm501_2d_engine_readfn,
1.1.1.5 ! root     1427:                                                    sm501_2d_engine_writefn, s,
        !          1428:                                                    DEVICE_NATIVE_ENDIAN);
1.1.1.4   root     1429:     cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_2D_ENGINE,
                   1430:                                  0x54, sm501_2d_engine_index);
1.1       root     1431: 
1.1.1.2   root     1432:     /* bridge to usb host emulation module */
1.1.1.4   root     1433:     dev = qdev_create(NULL, "sysbus-ohci");
                   1434:     qdev_prop_set_uint32(dev, "num-ports", 2);
                   1435:     qdev_prop_set_taddr(dev, "dma-offset", base);
                   1436:     qdev_init_nofail(dev);
                   1437:     sysbus_mmio_map(sysbus_from_qdev(dev), 0,
                   1438:                     base + MMIO_BASE_OFFSET + SM501_USB_HOST);
                   1439:     sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
1.1.1.2   root     1440: 
1.1       root     1441:     /* bridge to serial emulation module */
1.1.1.4   root     1442:     if (chr) {
                   1443: #ifdef TARGET_WORDS_BIGENDIAN
                   1444:         serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
                   1445:                        NULL, /* TODO : chain irq to IRL */
                   1446:                        115200, chr, 1, 1);
                   1447: #else
                   1448:         serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
                   1449:                        NULL, /* TODO : chain irq to IRL */
                   1450:                        115200, chr, 1, 0);
                   1451: #endif
                   1452:     }
1.1       root     1453: 
                   1454:     /* create qemu graphic console */
                   1455:     s->ds = graphic_console_init(sm501_update_display, NULL,
                   1456:                                 NULL, NULL, s);
                   1457: }

unix.superglobalmegacorp.com

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