Statistics
| Branch: | Revision:

root / hw / sm501.c @ a67ba3b6

History | View | Annotate | Download (33.7 kB)

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"
30

    
31
/*
32
 * Status: 2008/11/02
33
 *   - Minimum implementation for Linux console : mmio regs and CRT layer.
34
 *   - Always updates full screen.
35
 *
36
 * TODO:
37
 *   - Panel support
38
 *   - Hardware cursor support
39
 *   - Touch panel support
40
 *   - USB support
41
 *   - UART support
42
 *   - Performance tuning
43
 */
44

    
45
//#define DEBUG_SM501
46
//#define DEBUG_BITBLT
47

    
48
#ifdef DEBUG_SM501
49
#define SM501_DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
50
#else
51
#define SM501_DPRINTF(fmt, ...) do {} while(0)
52
#endif
53

    
54

    
55
#define MMIO_BASE_OFFSET 0x3e00000
56

    
57
/* SM501 register definitions taken from "linux/include/linux/sm501-regs.h" */
58

    
59
/* System Configuration area */
60
/* System config base */
61
#define SM501_SYS_CONFIG                (0x000000)
62

    
63
/* config 1 */
64
#define SM501_SYSTEM_CONTROL                 (0x000000)
65

    
66
#define SM501_SYSCTRL_PANEL_TRISTATE        (1<<0)
67
#define SM501_SYSCTRL_MEM_TRISTATE        (1<<1)
68
#define SM501_SYSCTRL_CRT_TRISTATE        (1<<2)
69

    
70
#define SM501_SYSCTRL_PCI_SLAVE_BURST_MASK (3<<4)
71
#define SM501_SYSCTRL_PCI_SLAVE_BURST_1        (0<<4)
72
#define SM501_SYSCTRL_PCI_SLAVE_BURST_2        (1<<4)
73
#define SM501_SYSCTRL_PCI_SLAVE_BURST_4        (2<<4)
74
#define SM501_SYSCTRL_PCI_SLAVE_BURST_8        (3<<4)
75

    
76
#define SM501_SYSCTRL_PCI_CLOCK_RUN_EN        (1<<6)
77
#define SM501_SYSCTRL_PCI_RETRY_DISABLE        (1<<7)
78
#define SM501_SYSCTRL_PCI_SUBSYS_LOCK        (1<<11)
79
#define SM501_SYSCTRL_PCI_BURST_READ_EN        (1<<15)
80

    
81
/* miscellaneous control */
82

    
83
#define SM501_MISC_CONTROL                (0x000004)
84

    
85
#define SM501_MISC_BUS_SH                (0x0)
86
#define SM501_MISC_BUS_PCI                (0x1)
87
#define SM501_MISC_BUS_XSCALE                (0x2)
88
#define SM501_MISC_BUS_NEC                (0x6)
89
#define SM501_MISC_BUS_MASK                (0x7)
90

    
91
#define SM501_MISC_VR_62MB                (1<<3)
92
#define SM501_MISC_CDR_RESET                (1<<7)
93
#define SM501_MISC_USB_LB                (1<<8)
94
#define SM501_MISC_USB_SLAVE                (1<<9)
95
#define SM501_MISC_BL_1                        (1<<10)
96
#define SM501_MISC_MC                        (1<<11)
97
#define SM501_MISC_DAC_POWER                (1<<12)
98
#define SM501_MISC_IRQ_INVERT                (1<<16)
99
#define SM501_MISC_SH                        (1<<17)
100

    
101
#define SM501_MISC_HOLD_EMPTY                (0<<18)
102
#define SM501_MISC_HOLD_8                (1<<18)
103
#define SM501_MISC_HOLD_16                (2<<18)
104
#define SM501_MISC_HOLD_24                (3<<18)
105
#define SM501_MISC_HOLD_32                (4<<18)
106
#define SM501_MISC_HOLD_MASK                (7<<18)
107

    
108
#define SM501_MISC_FREQ_12                (1<<24)
109
#define SM501_MISC_PNL_24BIT                (1<<25)
110
#define SM501_MISC_8051_LE                (1<<26)
111

    
112

    
113

    
114
#define SM501_GPIO31_0_CONTROL                (0x000008)
115
#define SM501_GPIO63_32_CONTROL                (0x00000C)
116
#define SM501_DRAM_CONTROL                (0x000010)
117

    
118
/* command list */
119
#define SM501_ARBTRTN_CONTROL                (0x000014)
120

    
121
/* command list */
122
#define SM501_COMMAND_LIST_STATUS        (0x000024)
123

    
124
/* interrupt debug */
125
#define SM501_RAW_IRQ_STATUS                (0x000028)
126
#define SM501_RAW_IRQ_CLEAR                (0x000028)
127
#define SM501_IRQ_STATUS                (0x00002C)
128
#define SM501_IRQ_MASK                        (0x000030)
129
#define SM501_DEBUG_CONTROL                (0x000034)
130

    
131
/* power management */
132
#define SM501_POWERMODE_P2X_SRC                (1<<29)
133
#define SM501_POWERMODE_V2X_SRC                (1<<20)
134
#define SM501_POWERMODE_M_SRC                (1<<12)
135
#define SM501_POWERMODE_M1_SRC                (1<<4)
136

    
137
#define SM501_CURRENT_GATE                (0x000038)
138
#define SM501_CURRENT_CLOCK                (0x00003C)
139
#define SM501_POWER_MODE_0_GATE                (0x000040)
140
#define SM501_POWER_MODE_0_CLOCK        (0x000044)
141
#define SM501_POWER_MODE_1_GATE                (0x000048)
142
#define SM501_POWER_MODE_1_CLOCK        (0x00004C)
143
#define SM501_SLEEP_MODE_GATE                (0x000050)
144
#define SM501_POWER_MODE_CONTROL        (0x000054)
145

    
146
/* power gates for units within the 501 */
147
#define SM501_GATE_HOST                        (0)
148
#define SM501_GATE_MEMORY                (1)
149
#define SM501_GATE_DISPLAY                (2)
150
#define SM501_GATE_2D_ENGINE                (3)
151
#define SM501_GATE_CSC                        (4)
152
#define SM501_GATE_ZVPORT                (5)
153
#define SM501_GATE_GPIO                        (6)
154
#define SM501_GATE_UART0                (7)
155
#define SM501_GATE_UART1                (8)
156
#define SM501_GATE_SSP                        (10)
157
#define SM501_GATE_USB_HOST                (11)
158
#define SM501_GATE_USB_GADGET                (12)
159
#define SM501_GATE_UCONTROLLER                (17)
160
#define SM501_GATE_AC97                        (18)
161

    
162
/* panel clock */
163
#define SM501_CLOCK_P2XCLK                (24)
164
/* crt clock */
165
#define SM501_CLOCK_V2XCLK                (16)
166
/* main clock */
167
#define SM501_CLOCK_MCLK                (8)
168
/* SDRAM controller clock */
169
#define SM501_CLOCK_M1XCLK                (0)
170

    
171
/* config 2 */
172
#define SM501_PCI_MASTER_BASE                (0x000058)
173
#define SM501_ENDIAN_CONTROL                (0x00005C)
174
#define SM501_DEVICEID                        (0x000060)
175
/* 0x050100A0 */
176

    
177
#define SM501_DEVICEID_SM501                (0x05010000)
178
#define SM501_DEVICEID_IDMASK                (0xffff0000)
179
#define SM501_DEVICEID_REVMASK                (0x000000ff)
180

    
181
#define SM501_PLLCLOCK_COUNT                (0x000064)
182
#define SM501_MISC_TIMING                (0x000068)
183
#define SM501_CURRENT_SDRAM_CLOCK        (0x00006C)
184

    
185
#define SM501_PROGRAMMABLE_PLL_CONTROL        (0x000074)
186

    
187
/* GPIO base */
188
#define SM501_GPIO                        (0x010000)
189
#define SM501_GPIO_DATA_LOW                (0x00)
190
#define SM501_GPIO_DATA_HIGH                (0x04)
191
#define SM501_GPIO_DDR_LOW                (0x08)
192
#define SM501_GPIO_DDR_HIGH                (0x0C)
193
#define SM501_GPIO_IRQ_SETUP                (0x10)
194
#define SM501_GPIO_IRQ_STATUS                (0x14)
195
#define SM501_GPIO_IRQ_RESET                (0x14)
196

    
197
/* I2C controller base */
198
#define SM501_I2C                        (0x010040)
199
#define SM501_I2C_BYTE_COUNT                (0x00)
200
#define SM501_I2C_CONTROL                (0x01)
201
#define SM501_I2C_STATUS                (0x02)
202
#define SM501_I2C_RESET                        (0x02)
203
#define SM501_I2C_SLAVE_ADDRESS                (0x03)
204
#define SM501_I2C_DATA                        (0x04)
205

    
206
/* SSP base */
207
#define SM501_SSP                        (0x020000)
208

    
209
/* Uart 0 base */
210
#define SM501_UART0                        (0x030000)
211

    
212
/* Uart 1 base */
213
#define SM501_UART1                        (0x030020)
214

    
215
/* USB host port base */
216
#define SM501_USB_HOST                        (0x040000)
217

    
218
/* USB slave/gadget base */
219
#define SM501_USB_GADGET                (0x060000)
220

    
221
/* USB slave/gadget data port base */
222
#define SM501_USB_GADGET_DATA                (0x070000)
223

    
224
/* Display controller/video engine base */
225
#define SM501_DC                        (0x080000)
226

    
227
/* common defines for the SM501 address registers */
228
#define SM501_ADDR_FLIP                        (1<<31)
229
#define SM501_ADDR_EXT                        (1<<27)
230
#define SM501_ADDR_CS1                        (1<<26)
231
#define SM501_ADDR_MASK                        (0x3f << 26)
232

    
233
#define SM501_FIFO_MASK                        (0x3 << 16)
234
#define SM501_FIFO_1                        (0x0 << 16)
235
#define SM501_FIFO_3                        (0x1 << 16)
236
#define SM501_FIFO_7                        (0x2 << 16)
237
#define SM501_FIFO_11                        (0x3 << 16)
238

    
239
/* common registers for panel and the crt */
240
#define SM501_OFF_DC_H_TOT                (0x000)
241
#define SM501_OFF_DC_V_TOT                (0x008)
242
#define SM501_OFF_DC_H_SYNC                (0x004)
243
#define SM501_OFF_DC_V_SYNC                (0x00C)
244

    
245
#define SM501_DC_PANEL_CONTROL                (0x000)
246

    
247
#define SM501_DC_PANEL_CONTROL_FPEN        (1<<27)
248
#define SM501_DC_PANEL_CONTROL_BIAS        (1<<26)
249
#define SM501_DC_PANEL_CONTROL_DATA        (1<<25)
250
#define SM501_DC_PANEL_CONTROL_VDD        (1<<24)
251
#define SM501_DC_PANEL_CONTROL_DP        (1<<23)
252

    
253
#define SM501_DC_PANEL_CONTROL_TFT_888        (0<<21)
254
#define SM501_DC_PANEL_CONTROL_TFT_333        (1<<21)
255
#define SM501_DC_PANEL_CONTROL_TFT_444        (2<<21)
256

    
257
#define SM501_DC_PANEL_CONTROL_DE        (1<<20)
258

    
259
#define SM501_DC_PANEL_CONTROL_LCD_TFT        (0<<18)
260
#define SM501_DC_PANEL_CONTROL_LCD_STN8        (1<<18)
261
#define SM501_DC_PANEL_CONTROL_LCD_STN12 (2<<18)
262

    
263
#define SM501_DC_PANEL_CONTROL_CP        (1<<14)
264
#define SM501_DC_PANEL_CONTROL_VSP        (1<<13)
265
#define SM501_DC_PANEL_CONTROL_HSP        (1<<12)
266
#define SM501_DC_PANEL_CONTROL_CK        (1<<9)
267
#define SM501_DC_PANEL_CONTROL_TE        (1<<8)
268
#define SM501_DC_PANEL_CONTROL_VPD        (1<<7)
269
#define SM501_DC_PANEL_CONTROL_VP        (1<<6)
270
#define SM501_DC_PANEL_CONTROL_HPD        (1<<5)
271
#define SM501_DC_PANEL_CONTROL_HP        (1<<4)
272
#define SM501_DC_PANEL_CONTROL_GAMMA        (1<<3)
273
#define SM501_DC_PANEL_CONTROL_EN        (1<<2)
274

    
275
#define SM501_DC_PANEL_CONTROL_8BPP        (0<<0)
276
#define SM501_DC_PANEL_CONTROL_16BPP        (1<<0)
277
#define SM501_DC_PANEL_CONTROL_32BPP        (2<<0)
278

    
279

    
280
#define SM501_DC_PANEL_PANNING_CONTROL        (0x004)
281
#define SM501_DC_PANEL_COLOR_KEY        (0x008)
282
#define SM501_DC_PANEL_FB_ADDR                (0x00C)
283
#define SM501_DC_PANEL_FB_OFFSET        (0x010)
284
#define SM501_DC_PANEL_FB_WIDTH                (0x014)
285
#define SM501_DC_PANEL_FB_HEIGHT        (0x018)
286
#define SM501_DC_PANEL_TL_LOC                (0x01C)
287
#define SM501_DC_PANEL_BR_LOC                (0x020)
288
#define SM501_DC_PANEL_H_TOT                (0x024)
289
#define SM501_DC_PANEL_H_SYNC                (0x028)
290
#define SM501_DC_PANEL_V_TOT                (0x02C)
291
#define SM501_DC_PANEL_V_SYNC                (0x030)
292
#define SM501_DC_PANEL_CUR_LINE                (0x034)
293

    
294
#define SM501_DC_VIDEO_CONTROL                (0x040)
295
#define SM501_DC_VIDEO_FB0_ADDR                (0x044)
296
#define SM501_DC_VIDEO_FB_WIDTH                (0x048)
297
#define SM501_DC_VIDEO_FB0_LAST_ADDR        (0x04C)
298
#define SM501_DC_VIDEO_TL_LOC                (0x050)
299
#define SM501_DC_VIDEO_BR_LOC                (0x054)
300
#define SM501_DC_VIDEO_SCALE                (0x058)
301
#define SM501_DC_VIDEO_INIT_SCALE        (0x05C)
302
#define SM501_DC_VIDEO_YUV_CONSTANTS        (0x060)
303
#define SM501_DC_VIDEO_FB1_ADDR                (0x064)
304
#define SM501_DC_VIDEO_FB1_LAST_ADDR        (0x068)
305

    
306
#define SM501_DC_VIDEO_ALPHA_CONTROL        (0x080)
307
#define SM501_DC_VIDEO_ALPHA_FB_ADDR        (0x084)
308
#define SM501_DC_VIDEO_ALPHA_FB_OFFSET        (0x088)
309
#define SM501_DC_VIDEO_ALPHA_FB_LAST_ADDR        (0x08C)
310
#define SM501_DC_VIDEO_ALPHA_TL_LOC        (0x090)
311
#define SM501_DC_VIDEO_ALPHA_BR_LOC        (0x094)
312
#define SM501_DC_VIDEO_ALPHA_SCALE        (0x098)
313
#define SM501_DC_VIDEO_ALPHA_INIT_SCALE        (0x09C)
314
#define SM501_DC_VIDEO_ALPHA_CHROMA_KEY        (0x0A0)
315
#define SM501_DC_VIDEO_ALPHA_COLOR_LOOKUP        (0x0A4)
316

    
317
#define SM501_DC_PANEL_HWC_BASE                (0x0F0)
318
#define SM501_DC_PANEL_HWC_ADDR                (0x0F0)
319
#define SM501_DC_PANEL_HWC_LOC                (0x0F4)
320
#define SM501_DC_PANEL_HWC_COLOR_1_2        (0x0F8)
321
#define SM501_DC_PANEL_HWC_COLOR_3        (0x0FC)
322

    
323
#define SM501_HWC_EN                        (1<<31)
324

    
325
#define SM501_OFF_HWC_ADDR                (0x00)
326
#define SM501_OFF_HWC_LOC                (0x04)
327
#define SM501_OFF_HWC_COLOR_1_2                (0x08)
328
#define SM501_OFF_HWC_COLOR_3                (0x0C)
329

    
330
#define SM501_DC_ALPHA_CONTROL                (0x100)
331
#define SM501_DC_ALPHA_FB_ADDR                (0x104)
332
#define SM501_DC_ALPHA_FB_OFFSET        (0x108)
333
#define SM501_DC_ALPHA_TL_LOC                (0x10C)
334
#define SM501_DC_ALPHA_BR_LOC                (0x110)
335
#define SM501_DC_ALPHA_CHROMA_KEY        (0x114)
336
#define SM501_DC_ALPHA_COLOR_LOOKUP        (0x118)
337

    
338
#define SM501_DC_CRT_CONTROL                (0x200)
339

    
340
#define SM501_DC_CRT_CONTROL_TVP        (1<<15)
341
#define SM501_DC_CRT_CONTROL_CP                (1<<14)
342
#define SM501_DC_CRT_CONTROL_VSP        (1<<13)
343
#define SM501_DC_CRT_CONTROL_HSP        (1<<12)
344
#define SM501_DC_CRT_CONTROL_VS                (1<<11)
345
#define SM501_DC_CRT_CONTROL_BLANK        (1<<10)
346
#define SM501_DC_CRT_CONTROL_SEL        (1<<9)
347
#define SM501_DC_CRT_CONTROL_TE                (1<<8)
348
#define SM501_DC_CRT_CONTROL_PIXEL_MASK (0xF << 4)
349
#define SM501_DC_CRT_CONTROL_GAMMA        (1<<3)
350
#define SM501_DC_CRT_CONTROL_ENABLE        (1<<2)
351

    
352
#define SM501_DC_CRT_CONTROL_8BPP        (0<<0)
353
#define SM501_DC_CRT_CONTROL_16BPP        (1<<0)
354
#define SM501_DC_CRT_CONTROL_32BPP        (2<<0)
355

    
356
#define SM501_DC_CRT_FB_ADDR                (0x204)
357
#define SM501_DC_CRT_FB_OFFSET                (0x208)
358
#define SM501_DC_CRT_H_TOT                (0x20C)
359
#define SM501_DC_CRT_H_SYNC                (0x210)
360
#define SM501_DC_CRT_V_TOT                (0x214)
361
#define SM501_DC_CRT_V_SYNC                (0x218)
362
#define SM501_DC_CRT_SIGNATURE_ANALYZER        (0x21C)
363
#define SM501_DC_CRT_CUR_LINE                (0x220)
364
#define SM501_DC_CRT_MONITOR_DETECT        (0x224)
365

    
366
#define SM501_DC_CRT_HWC_BASE                (0x230)
367
#define SM501_DC_CRT_HWC_ADDR                (0x230)
368
#define SM501_DC_CRT_HWC_LOC                (0x234)
369
#define SM501_DC_CRT_HWC_COLOR_1_2        (0x238)
370
#define SM501_DC_CRT_HWC_COLOR_3        (0x23C)
371

    
372
#define SM501_DC_PANEL_PALETTE                (0x400)
373

    
374
#define SM501_DC_VIDEO_PALETTE                (0x800)
375

    
376
#define SM501_DC_CRT_PALETTE                (0xC00)
377

    
378
/* Zoom Video port base */
379
#define SM501_ZVPORT                        (0x090000)
380

    
381
/* AC97/I2S base */
382
#define SM501_AC97                        (0x0A0000)
383

    
384
/* 8051 micro controller base */
385
#define SM501_UCONTROLLER                (0x0B0000)
386

    
387
/* 8051 micro controller SRAM base */
388
#define SM501_UCONTROLLER_SRAM                (0x0C0000)
389

    
390
/* DMA base */
391
#define SM501_DMA                        (0x0D0000)
392

    
393
/* 2d engine base */
394
#define SM501_2D_ENGINE                        (0x100000)
395
#define SM501_2D_SOURCE                        (0x00)
396
#define SM501_2D_DESTINATION                (0x04)
397
#define SM501_2D_DIMENSION                (0x08)
398
#define SM501_2D_CONTROL                (0x0C)
399
#define SM501_2D_PITCH                        (0x10)
400
#define SM501_2D_FOREGROUND                (0x14)
401
#define SM501_2D_BACKGROUND                (0x18)
402
#define SM501_2D_STRETCH                (0x1C)
403
#define SM501_2D_COLOR_COMPARE                (0x20)
404
#define SM501_2D_COLOR_COMPARE_MASK         (0x24)
405
#define SM501_2D_MASK                        (0x28)
406
#define SM501_2D_CLIP_TL                (0x2C)
407
#define SM501_2D_CLIP_BR                (0x30)
408
#define SM501_2D_MONO_PATTERN_LOW        (0x34)
409
#define SM501_2D_MONO_PATTERN_HIGH        (0x38)
410
#define SM501_2D_WINDOW_WIDTH                (0x3C)
411
#define SM501_2D_SOURCE_BASE                (0x40)
412
#define SM501_2D_DESTINATION_BASE        (0x44)
413
#define SM501_2D_ALPHA                        (0x48)
414
#define SM501_2D_WRAP                        (0x4C)
415
#define SM501_2D_STATUS                        (0x50)
416

    
417
#define SM501_CSC_Y_SOURCE_BASE                (0xC8)
418
#define SM501_CSC_CONSTANTS                (0xCC)
419
#define SM501_CSC_Y_SOURCE_X                (0xD0)
420
#define SM501_CSC_Y_SOURCE_Y                (0xD4)
421
#define SM501_CSC_U_SOURCE_BASE                (0xD8)
422
#define SM501_CSC_V_SOURCE_BASE                (0xDC)
423
#define SM501_CSC_SOURCE_DIMENSION        (0xE0)
424
#define SM501_CSC_SOURCE_PITCH                (0xE4)
425
#define SM501_CSC_DESTINATION                (0xE8)
426
#define SM501_CSC_DESTINATION_DIMENSION        (0xEC)
427
#define SM501_CSC_DESTINATION_PITCH        (0xF0)
428
#define SM501_CSC_SCALE_FACTOR                (0xF4)
429
#define SM501_CSC_DESTINATION_BASE        (0xF8)
430
#define SM501_CSC_CONTROL                (0xFC)
431

    
432
/* 2d engine data port base */
433
#define SM501_2D_ENGINE_DATA                (0x110000)
434

    
435
/* end of register definitions */
436

    
437
#define SM501_HWC_WIDTH                       (64)
438
#define SM501_HWC_HEIGHT                      (64)
439

    
440
/* SM501 local memory size taken from "linux/drivers/mfd/sm501.c" */
441
static const uint32_t sm501_mem_local_size[] = {
442
        [0]        = 4*1024*1024,
443
        [1]        = 8*1024*1024,
444
        [2]        = 16*1024*1024,
445
        [3]        = 32*1024*1024,
446
        [4]        = 64*1024*1024,
447
        [5]        = 2*1024*1024,
448
};
449
#define get_local_mem_size(s) sm501_mem_local_size[(s)->local_mem_size_index]
450

    
451
typedef struct SM501State {
452
    /* graphic console status */
453
    DisplayState *ds;
454

    
455
    /* status & internal resources */
456
    target_phys_addr_t base;
457
    uint32_t local_mem_size_index;
458
    uint8_t * local_mem;
459
    ram_addr_t local_mem_offset;
460
    uint32_t last_width;
461
    uint32_t last_height;
462

    
463
    /* mmio registers */
464
    uint32_t system_control;
465
    uint32_t misc_control;
466
    uint32_t gpio_31_0_control;
467
    uint32_t gpio_63_32_control;
468
    uint32_t dram_control;
469
    uint32_t irq_mask;
470
    uint32_t misc_timing;
471
    uint32_t power_mode_control;
472

    
473
    uint32_t uart0_ier;
474
    uint32_t uart0_lcr;
475
    uint32_t uart0_mcr;
476
    uint32_t uart0_scr;
477

    
478
    uint8_t dc_palette[0x400 * 3];
479

    
480
    uint32_t dc_panel_control;
481
    uint32_t dc_panel_panning_control;
482
    uint32_t dc_panel_fb_addr;
483
    uint32_t dc_panel_fb_offset;
484
    uint32_t dc_panel_fb_width;
485
    uint32_t dc_panel_fb_height;
486
    uint32_t dc_panel_tl_location;
487
    uint32_t dc_panel_br_location;
488
    uint32_t dc_panel_h_total;
489
    uint32_t dc_panel_h_sync;
490
    uint32_t dc_panel_v_total;
491
    uint32_t dc_panel_v_sync;
492

    
493
    uint32_t dc_panel_hwc_addr;
494
    uint32_t dc_panel_hwc_location;
495
    uint32_t dc_panel_hwc_color_1_2;
496
    uint32_t dc_panel_hwc_color_3;
497

    
498
    uint32_t dc_crt_control;
499
    uint32_t dc_crt_fb_addr;
500
    uint32_t dc_crt_fb_offset;
501
    uint32_t dc_crt_h_total;
502
    uint32_t dc_crt_h_sync;
503
    uint32_t dc_crt_v_total;
504
    uint32_t dc_crt_v_sync;
505

    
506
    uint32_t dc_crt_hwc_addr;
507
    uint32_t dc_crt_hwc_location;
508
    uint32_t dc_crt_hwc_color_1_2;
509
    uint32_t dc_crt_hwc_color_3;
510

    
511
} SM501State;
512

    
513
static uint32_t get_local_mem_size_index(uint32_t size)
514
{
515
    uint32_t norm_size = 0;
516
    int i, index = 0;
517

    
518
    for (i = 0; i < ARRAY_SIZE(sm501_mem_local_size); i++) {
519
        uint32_t new_size = sm501_mem_local_size[i];
520
        if (new_size >= size) {
521
            if (norm_size == 0 || norm_size > new_size) {
522
                norm_size = new_size;
523
                index = i;
524
            }
525
        }
526
    }
527

    
528
    return index;
529
}
530

    
531
/**
532
 * Check the availability of hardware cursor.
533
 * @param crt  0 for PANEL, 1 for CRT.
534
 */
535
static inline int is_hwc_enabled(SM501State *state, int crt)
536
{
537
    uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
538
    return addr & 0x80000000;
539
}
540

    
541
/**
542
 * Get the address which holds cursor pattern data.
543
 * @param crt  0 for PANEL, 1 for CRT.
544
 */
545
static inline uint32_t get_hwc_address(SM501State *state, int crt)
546
{
547
    uint32_t addr = crt ? state->dc_crt_hwc_addr : state->dc_panel_hwc_addr;
548
    return (addr & 0x03FFFFF0)/* >> 4*/;
549
}
550

    
551
/**
552
 * Get the cursor position in y coordinate.
553
 * @param crt  0 for PANEL, 1 for CRT.
554
 */
555
static inline uint32_t get_hwc_y(SM501State *state, int crt)
556
{
557
    uint32_t location = crt ? state->dc_crt_hwc_location
558
                            : state->dc_panel_hwc_location;
559
    return (location & 0x07FF0000) >> 16;
560
}
561

    
562
/**
563
 * Get the cursor position in x coordinate.
564
 * @param crt  0 for PANEL, 1 for CRT.
565
 */
566
static inline uint32_t get_hwc_x(SM501State *state, int crt)
567
{
568
    uint32_t location = crt ? state->dc_crt_hwc_location
569
                            : state->dc_panel_hwc_location;
570
    return location & 0x000007FF;
571
}
572

    
573
/**
574
 * Get the cursor position in x coordinate.
575
 * @param crt  0 for PANEL, 1 for CRT.
576
 * @param index  0, 1, 2 or 3 which specifies color of corsor dot.
577
 */
578
static inline uint16_t get_hwc_color(SM501State *state, int crt, int index)
579
{
580
    uint16_t color_reg = 0;
581
    uint16_t color_565 = 0;
582

    
583
    if (index == 0) {
584
        return 0;
585
    }
586

    
587
    switch (index) {
588
    case 1:
589
    case 2:
590
        color_reg = crt ? state->dc_crt_hwc_color_1_2
591
                        : state->dc_panel_hwc_color_1_2;
592
        break;
593
    case 3:
594
        color_reg = crt ? state->dc_crt_hwc_color_3
595
                        : state->dc_panel_hwc_color_3;
596
        break;
597
    default:
598
        printf("invalid hw cursor color.\n");
599
        abort();
600
    }
601

    
602
    switch (index) {
603
    case 1:
604
    case 3:
605
        color_565 = (uint16_t)(color_reg & 0xFFFF);
606
        break;
607
    case 2:
608
        color_565 = (uint16_t)((color_reg >> 16) & 0xFFFF);
609
        break;
610
    }
611
    return color_565;
612
}
613

    
614
static int within_hwc_y_range(SM501State *state, int y, int crt)
615
{
616
    int hwc_y = get_hwc_y(state, crt);
617
    return (hwc_y <= y && y < hwc_y + SM501_HWC_HEIGHT);
618
}
619

    
620
static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
621
{
622
    SM501State * s = (SM501State *)opaque;
623
    uint32_t ret = 0;
624
    SM501_DPRINTF("sm501 system config regs : read addr=%x\n", (int)addr);
625

    
626
    switch(addr) {
627
    case SM501_SYSTEM_CONTROL:
628
        ret = s->system_control;
629
        break;
630
    case SM501_MISC_CONTROL:
631
        ret = s->misc_control;
632
        break;
633
    case SM501_GPIO31_0_CONTROL:
634
        ret = s->gpio_31_0_control;
635
        break;
636
    case SM501_GPIO63_32_CONTROL:
637
        ret = s->gpio_63_32_control;
638
        break;
639
    case SM501_DEVICEID:
640
        ret = 0x050100A0;
641
        break;
642
    case SM501_DRAM_CONTROL:
643
        ret = (s->dram_control & 0x07F107C0) | s->local_mem_size_index << 13;
644
        break;
645
    case SM501_IRQ_MASK:
646
        ret = s->irq_mask;
647
        break;
648
    case SM501_MISC_TIMING:
649
        /* TODO : simulate gate control */
650
        ret = s->misc_timing;
651
        break;
652
    case SM501_CURRENT_GATE:
653
        /* TODO : simulate gate control */
654
        ret = 0x00021807;
655
        break;
656
    case SM501_CURRENT_CLOCK:
657
        ret = 0x2A1A0A09;
658
        break;
659
    case SM501_POWER_MODE_CONTROL:
660
        ret = s->power_mode_control;
661
        break;
662

    
663
    default:
664
        printf("sm501 system config : not implemented register read."
665
               " addr=%x\n", (int)addr);
666
        abort();
667
    }
668

    
669
    return ret;
670
}
671

    
672
static void sm501_system_config_write(void *opaque,
673
                                      target_phys_addr_t addr, uint32_t value)
674
{
675
    SM501State * s = (SM501State *)opaque;
676
    SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n",
677
                  addr, value);
678

    
679
    switch(addr) {
680
    case SM501_SYSTEM_CONTROL:
681
        s->system_control = value & 0xE300B8F7;
682
        break;
683
    case SM501_MISC_CONTROL:
684
        s->misc_control = value & 0xFF7FFF20;
685
        break;
686
    case SM501_GPIO31_0_CONTROL:
687
        s->gpio_31_0_control = value;
688
        break;
689
    case SM501_GPIO63_32_CONTROL:
690
        s->gpio_63_32_control = value;
691
        break;
692
    case SM501_DRAM_CONTROL:
693
        s->local_mem_size_index = (value >> 13) & 0x7;
694
        /* rODO : check validity of size change */
695
        s->dram_control |=  value & 0x7FFFFFC3;
696
        break;
697
    case SM501_IRQ_MASK:
698
        s->irq_mask = value;
699
        break;
700
    case SM501_MISC_TIMING:
701
        s->misc_timing = value & 0xF31F1FFF;
702
        break;
703
    case SM501_POWER_MODE_0_GATE:
704
    case SM501_POWER_MODE_1_GATE:
705
    case SM501_POWER_MODE_0_CLOCK:
706
    case SM501_POWER_MODE_1_CLOCK:
707
        /* TODO : simulate gate & clock control */
708
        break;
709
    case SM501_POWER_MODE_CONTROL:
710
        s->power_mode_control = value & 0x00000003;
711
        break;
712

    
713
    default:
714
        printf("sm501 system config : not implemented register write."
715
               " addr=%x, val=%x\n", (int)addr, value);
716
        abort();
717
    }
718
}
719

    
720
static CPUReadMemoryFunc * const sm501_system_config_readfn[] = {
721
    NULL,
722
    NULL,
723
    &sm501_system_config_read,
724
};
725

    
726
static CPUWriteMemoryFunc * const sm501_system_config_writefn[] = {
727
    NULL,
728
    NULL,
729
    &sm501_system_config_write,
730
};
731

    
732
static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr)
733
{
734
    SM501State * s = (SM501State *)opaque;
735
    SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr);
736

    
737
    /* TODO : consider BYTE/WORD access */
738
    /* TODO : consider endian */
739

    
740
    assert(0 <= addr && addr < 0x400 * 3);
741
    return *(uint32_t*)&s->dc_palette[addr];
742
}
743

    
744
static void sm501_palette_write(void *opaque,
745
                                target_phys_addr_t addr, uint32_t value)
746
{
747
    SM501State * s = (SM501State *)opaque;
748
    SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n",
749
                  (int)addr, value);
750

    
751
    /* TODO : consider BYTE/WORD access */
752
    /* TODO : consider endian */
753

    
754
    assert(0 <= addr && addr < 0x400 * 3);
755
    *(uint32_t*)&s->dc_palette[addr] = value;
756
}
757

    
758
static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr)
759
{
760
    SM501State * s = (SM501State *)opaque;
761
    uint32_t ret = 0;
762
    SM501_DPRINTF("sm501 disp ctrl regs : read addr=%x\n", (int)addr);
763

    
764
    switch(addr) {
765

    
766
    case SM501_DC_PANEL_CONTROL:
767
        ret = s->dc_panel_control;
768
        break;
769
    case SM501_DC_PANEL_PANNING_CONTROL:
770
        ret = s->dc_panel_panning_control;
771
        break;
772
    case SM501_DC_PANEL_FB_ADDR:
773
        ret = s->dc_panel_fb_addr;
774
        break;
775
    case SM501_DC_PANEL_FB_OFFSET:
776
        ret = s->dc_panel_fb_offset;
777
        break;
778
    case SM501_DC_PANEL_FB_WIDTH:
779
        ret = s->dc_panel_fb_width;
780
        break;
781
    case SM501_DC_PANEL_FB_HEIGHT:
782
        ret = s->dc_panel_fb_height;
783
        break;
784
    case SM501_DC_PANEL_TL_LOC:
785
        ret = s->dc_panel_tl_location;
786
        break;
787
    case SM501_DC_PANEL_BR_LOC:
788
        ret = s->dc_panel_br_location;
789
        break;
790

    
791
    case SM501_DC_PANEL_H_TOT:
792
        ret = s->dc_panel_h_total;
793
        break;
794
    case SM501_DC_PANEL_H_SYNC:
795
        ret = s->dc_panel_h_sync;
796
        break;
797
    case SM501_DC_PANEL_V_TOT:
798
        ret = s->dc_panel_v_total;
799
        break;
800
    case SM501_DC_PANEL_V_SYNC:
801
        ret = s->dc_panel_v_sync;
802
        break;
803

    
804
    case SM501_DC_CRT_CONTROL:
805
        ret = s->dc_crt_control;
806
        break;
807
    case SM501_DC_CRT_FB_ADDR:
808
        ret = s->dc_crt_fb_addr;
809
        break;
810
    case SM501_DC_CRT_FB_OFFSET:
811
        ret = s->dc_crt_fb_offset;
812
        break;
813
    case SM501_DC_CRT_H_TOT:
814
        ret = s->dc_crt_h_total;
815
        break;
816
    case SM501_DC_CRT_H_SYNC:
817
        ret = s->dc_crt_h_sync;
818
        break;
819
    case SM501_DC_CRT_V_TOT:
820
        ret = s->dc_crt_v_total;
821
        break;
822
    case SM501_DC_CRT_V_SYNC:
823
        ret = s->dc_crt_v_sync;
824
        break;
825

    
826
    case SM501_DC_CRT_HWC_ADDR:
827
        ret = s->dc_crt_hwc_addr;
828
        break;
829
    case SM501_DC_CRT_HWC_LOC:
830
        ret = s->dc_crt_hwc_location;
831
        break;
832
    case SM501_DC_CRT_HWC_COLOR_1_2:
833
        ret = s->dc_crt_hwc_color_1_2;
834
        break;
835
    case SM501_DC_CRT_HWC_COLOR_3:
836
        ret = s->dc_crt_hwc_color_3;
837
        break;
838

    
839
    case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
840
        ret = sm501_palette_read(opaque, addr - SM501_DC_PANEL_PALETTE);
841
        break;
842

    
843
    default:
844
        printf("sm501 disp ctrl : not implemented register read."
845
               " addr=%x\n", (int)addr);
846
        abort();
847
    }
848

    
849
    return ret;
850
}
851

    
852
static void sm501_disp_ctrl_write(void *opaque,
853
                                           target_phys_addr_t addr,
854
                                           uint32_t value)
855
{
856
    SM501State * s = (SM501State *)opaque;
857
    SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n",
858
                  addr, value);
859

    
860
    switch(addr) {
861
    case SM501_DC_PANEL_CONTROL:
862
        s->dc_panel_control = value & 0x0FFF73FF;
863
        break;
864
    case SM501_DC_PANEL_PANNING_CONTROL:
865
        s->dc_panel_panning_control = value & 0xFF3FFF3F;
866
        break;
867
    case SM501_DC_PANEL_FB_ADDR:
868
        s->dc_panel_fb_addr = value & 0x8FFFFFF0;
869
        break;
870
    case SM501_DC_PANEL_FB_OFFSET:
871
        s->dc_panel_fb_offset = value & 0x3FF03FF0;
872
        break;
873
    case SM501_DC_PANEL_FB_WIDTH:
874
        s->dc_panel_fb_width = value & 0x0FFF0FFF;
875
        break;
876
    case SM501_DC_PANEL_FB_HEIGHT:
877
        s->dc_panel_fb_height = value & 0x0FFF0FFF;
878
        break;
879
    case SM501_DC_PANEL_TL_LOC:
880
        s->dc_panel_tl_location = value & 0x07FF07FF;
881
        break;
882
    case SM501_DC_PANEL_BR_LOC:
883
        s->dc_panel_br_location = value & 0x07FF07FF;
884
        break;
885

    
886
    case SM501_DC_PANEL_H_TOT:
887
        s->dc_panel_h_total = value & 0x0FFF0FFF;
888
        break;
889
    case SM501_DC_PANEL_H_SYNC:
890
        s->dc_panel_h_sync = value & 0x00FF0FFF;
891
        break;
892
    case SM501_DC_PANEL_V_TOT:
893
        s->dc_panel_v_total = value & 0x0FFF0FFF;
894
        break;
895
    case SM501_DC_PANEL_V_SYNC:
896
        s->dc_panel_v_sync = value & 0x003F0FFF;
897
        break;
898

    
899
    case SM501_DC_PANEL_HWC_ADDR:
900
        s->dc_panel_hwc_addr = value & 0x8FFFFFF0;
901
        break;
902
    case SM501_DC_PANEL_HWC_LOC:
903
        s->dc_panel_hwc_location = value & 0x0FFF0FFF;
904
        break;
905
    case SM501_DC_PANEL_HWC_COLOR_1_2:
906
        s->dc_panel_hwc_color_1_2 = value;
907
        break;
908
    case SM501_DC_PANEL_HWC_COLOR_3:
909
        s->dc_panel_hwc_color_3 = value & 0x0000FFFF;
910
        break;
911

    
912
    case SM501_DC_CRT_CONTROL:
913
        s->dc_crt_control = value & 0x0003FFFF;
914
        break;
915
    case SM501_DC_CRT_FB_ADDR:
916
        s->dc_crt_fb_addr = value & 0x8FFFFFF0;
917
        break;
918
    case SM501_DC_CRT_FB_OFFSET:
919
        s->dc_crt_fb_offset = value & 0x3FF03FF0;
920
        break;
921
    case SM501_DC_CRT_H_TOT:
922
        s->dc_crt_h_total = value & 0x0FFF0FFF;
923
        break;
924
    case SM501_DC_CRT_H_SYNC:
925
        s->dc_crt_h_sync = value & 0x00FF0FFF;
926
        break;
927
    case SM501_DC_CRT_V_TOT:
928
        s->dc_crt_v_total = value & 0x0FFF0FFF;
929
        break;
930
    case SM501_DC_CRT_V_SYNC:
931
        s->dc_crt_v_sync = value & 0x003F0FFF;
932
        break;
933

    
934
    case SM501_DC_CRT_HWC_ADDR:
935
        s->dc_crt_hwc_addr = value & 0x8FFFFFF0;
936
        break;
937
    case SM501_DC_CRT_HWC_LOC:
938
        s->dc_crt_hwc_location = value & 0x0FFF0FFF;
939
        break;
940
    case SM501_DC_CRT_HWC_COLOR_1_2:
941
        s->dc_crt_hwc_color_1_2 = value;
942
        break;
943
    case SM501_DC_CRT_HWC_COLOR_3:
944
        s->dc_crt_hwc_color_3 = value & 0x0000FFFF;
945
        break;
946

    
947
    case SM501_DC_PANEL_PALETTE ... SM501_DC_PANEL_PALETTE + 0x400*3 - 4:
948
        sm501_palette_write(opaque, addr - SM501_DC_PANEL_PALETTE, value);
949
        break;
950

    
951
    default:
952
        printf("sm501 disp ctrl : not implemented register write."
953
               " addr=%x, val=%x\n", (int)addr, value);
954
        abort();
955
    }
956
}
957

    
958
static CPUReadMemoryFunc * const sm501_disp_ctrl_readfn[] = {
959
    NULL,
960
    NULL,
961
    &sm501_disp_ctrl_read,
962
};
963

    
964
static CPUWriteMemoryFunc * const sm501_disp_ctrl_writefn[] = {
965
    NULL,
966
    NULL,
967
    &sm501_disp_ctrl_write,
968
};
969

    
970
/* draw line functions for all console modes */
971

    
972
#include "pixel_ops.h"
973

    
974
typedef void draw_line_func(uint8_t *d, const uint8_t *s,
975
                            int width, const uint32_t *pal);
976

    
977
typedef void draw_hwc_line_func(SM501State * s, int crt, uint8_t * palette,
978
                                int c_y, uint8_t *d, int width);
979

    
980
#define DEPTH 8
981
#include "sm501_template.h"
982

    
983
#define DEPTH 15
984
#include "sm501_template.h"
985

    
986
#define BGR_FORMAT
987
#define DEPTH 15
988
#include "sm501_template.h"
989

    
990
#define DEPTH 16
991
#include "sm501_template.h"
992

    
993
#define BGR_FORMAT
994
#define DEPTH 16
995
#include "sm501_template.h"
996

    
997
#define DEPTH 32
998
#include "sm501_template.h"
999

    
1000
#define BGR_FORMAT
1001
#define DEPTH 32
1002
#include "sm501_template.h"
1003

    
1004
static draw_line_func * draw_line8_funcs[] = {
1005
    draw_line8_8,
1006
    draw_line8_15,
1007
    draw_line8_16,
1008
    draw_line8_32,
1009
    draw_line8_32bgr,
1010
    draw_line8_15bgr,
1011
    draw_line8_16bgr,
1012
};
1013

    
1014
static draw_line_func * draw_line16_funcs[] = {
1015
    draw_line16_8,
1016
    draw_line16_15,
1017
    draw_line16_16,
1018
    draw_line16_32,
1019
    draw_line16_32bgr,
1020
    draw_line16_15bgr,
1021
    draw_line16_16bgr,
1022
};
1023

    
1024
static draw_line_func * draw_line32_funcs[] = {
1025
    draw_line32_8,
1026
    draw_line32_15,
1027
    draw_line32_16,
1028
    draw_line32_32,
1029
    draw_line32_32bgr,
1030
    draw_line32_15bgr,
1031
    draw_line32_16bgr,
1032
};
1033

    
1034
static draw_hwc_line_func * draw_hwc_line_funcs[] = {
1035
    draw_hwc_line_8,
1036
    draw_hwc_line_15,
1037
    draw_hwc_line_16,
1038
    draw_hwc_line_32,
1039
    draw_hwc_line_32bgr,
1040
    draw_hwc_line_15bgr,
1041
    draw_hwc_line_16bgr,
1042
};
1043

    
1044
static inline int get_depth_index(DisplayState *s)
1045
{
1046
    switch(ds_get_bits_per_pixel(s)) {
1047
    default:
1048
    case 8:
1049
        return 0;
1050
    case 15:
1051
        return 1;
1052
    case 16:
1053
        return 2;
1054
    case 32:
1055
        if (is_surface_bgr(s->surface))
1056
            return 4;
1057
        else
1058
            return 3;
1059
    }
1060
}
1061

    
1062
static void sm501_draw_crt(SM501State * s)
1063
{
1064
    int y;
1065
    int width = (s->dc_crt_h_total & 0x00000FFF) + 1;
1066
    int height = (s->dc_crt_v_total & 0x00000FFF) + 1;
1067

    
1068
    uint8_t  * src = s->local_mem;
1069
    int src_bpp = 0;
1070
    int dst_bpp = ds_get_bytes_per_pixel(s->ds) + (ds_get_bits_per_pixel(s->ds) % 8 ? 1 : 0);
1071
    uint32_t * palette = (uint32_t *)&s->dc_palette[SM501_DC_CRT_PALETTE
1072
                                                    - SM501_DC_PANEL_PALETTE];
1073
    uint8_t hwc_palette[3 * 3];
1074
    int ds_depth_index = get_depth_index(s->ds);
1075
    draw_line_func * draw_line = NULL;
1076
    draw_hwc_line_func * draw_hwc_line = NULL;
1077
    int full_update = 0;
1078
    int y_start = -1;
1079
    int page_min = 0x7fffffff;
1080
    int page_max = -1;
1081
    ram_addr_t offset = s->local_mem_offset;
1082

    
1083
    /* choose draw_line function */
1084
    switch (s->dc_crt_control & 3) {
1085
    case SM501_DC_CRT_CONTROL_8BPP:
1086
        src_bpp = 1;
1087
        draw_line = draw_line8_funcs[ds_depth_index];
1088
        break;
1089
    case SM501_DC_CRT_CONTROL_16BPP:
1090
        src_bpp = 2;
1091
        draw_line = draw_line16_funcs[ds_depth_index];
1092
        break;
1093
    case SM501_DC_CRT_CONTROL_32BPP:
1094
        src_bpp = 4;
1095
        draw_line = draw_line32_funcs[ds_depth_index];
1096
        break;
1097
    default:
1098
        printf("sm501 draw crt : invalid DC_CRT_CONTROL=%x.\n",
1099
               s->dc_crt_control);
1100
        abort();
1101
        break;
1102
    }
1103

    
1104
    /* set up to draw hardware cursor */
1105
    if (is_hwc_enabled(s, 1)) {
1106
        int i;
1107

    
1108
        /* get cursor palette */
1109
        for (i = 0; i < 3; i++) {
1110
            uint16_t rgb565 = get_hwc_color(s, 1, i + 1);
1111
            hwc_palette[i * 3 + 0] = (rgb565 & 0xf800) >> 8; /* red */
1112
            hwc_palette[i * 3 + 1] = (rgb565 & 0x07e0) >> 3; /* green */
1113
            hwc_palette[i * 3 + 2] = (rgb565 & 0x001f) << 3; /* blue */
1114
        }
1115

    
1116
        /* choose cursor draw line function */
1117
        draw_hwc_line = draw_hwc_line_funcs[ds_depth_index];
1118
    }
1119

    
1120
    /* adjust console size */
1121
    if (s->last_width != width || s->last_height != height) {
1122
        qemu_console_resize(s->ds, width, height);
1123
        s->last_width = width;
1124
        s->last_height = height;
1125
        full_update = 1;
1126
    }
1127

    
1128
    /* draw each line according to conditions */
1129
    for (y = 0; y < height; y++) {
1130
        int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
1131
        int update = full_update || update_hwc;
1132
        ram_addr_t page0 = offset & TARGET_PAGE_MASK;
1133
        ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK;
1134
        ram_addr_t page;
1135

    
1136
        /* check dirty flags for each line */
1137
        for (page = page0; page <= page1; page += TARGET_PAGE_SIZE)
1138
            if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG))
1139
                update = 1;
1140

    
1141
        /* draw line and change status */
1142
        if (update) {
1143
            uint8_t * d = &(ds_get_data(s->ds)[y * width * dst_bpp]);
1144

    
1145
            /* draw graphics layer */
1146
            draw_line(d, src, width, palette);
1147

    
1148
            /* draw haredware cursor */
1149
            if (update_hwc) {
1150
                draw_hwc_line(s, 1, hwc_palette, y - get_hwc_y(s, 1), d, width);
1151
            }
1152

    
1153
            if (y_start < 0)
1154
                y_start = y;
1155
            if (page0 < page_min)
1156
                page_min = page0;
1157
            if (page1 > page_max)
1158
                page_max = page1;
1159
        } else {
1160
            if (y_start >= 0) {
1161
                /* flush to display */
1162
                dpy_update(s->ds, 0, y_start, width, y - y_start);
1163
                y_start = -1;
1164
            }
1165
        }
1166

    
1167
        src += width * src_bpp;
1168
        offset += width * src_bpp;
1169
    }
1170

    
1171
    /* complete flush to display */
1172
    if (y_start >= 0)
1173
        dpy_update(s->ds, 0, y_start, width, y - y_start);
1174

    
1175
    /* clear dirty flags */
1176
    if (page_max != -1)
1177
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1178
                                        VGA_DIRTY_FLAG);
1179
}
1180

    
1181
static void sm501_update_display(void *opaque)
1182
{
1183
    SM501State * s = (SM501State *)opaque;
1184

    
1185
    if (s->dc_crt_control & SM501_DC_CRT_CONTROL_ENABLE)
1186
        sm501_draw_crt(s);
1187
}
1188

    
1189
void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
1190
                CharDriverState *chr)
1191
{
1192
    SM501State * s;
1193
    int sm501_system_config_index;
1194
    int sm501_disp_ctrl_index;
1195

    
1196
    /* allocate management data region */
1197
    s = (SM501State *)qemu_mallocz(sizeof(SM501State));
1198
    s->base = base;
1199
    s->local_mem_size_index
1200
        = get_local_mem_size_index(local_mem_bytes);
1201
    SM501_DPRINTF("local mem size=%x. index=%d\n", get_local_mem_size(s),
1202
                  s->local_mem_size_index);
1203
    s->system_control = 0x00100000;
1204
    s->misc_control = 0x00001000; /* assumes SH, active=low */
1205
    s->dc_panel_control = 0x00010000;
1206
    s->dc_crt_control = 0x00010000;
1207

    
1208
    /* allocate local memory */
1209
    s->local_mem_offset = qemu_ram_alloc(local_mem_bytes);
1210
    s->local_mem = qemu_get_ram_ptr(s->local_mem_offset);
1211
    cpu_register_physical_memory(base, local_mem_bytes, s->local_mem_offset);
1212

    
1213
    /* map mmio */
1214
    sm501_system_config_index
1215
        = cpu_register_io_memory(sm501_system_config_readfn,
1216
                                 sm501_system_config_writefn, s);
1217
    cpu_register_physical_memory(base + MMIO_BASE_OFFSET,
1218
                                 0x6c, sm501_system_config_index);
1219
    sm501_disp_ctrl_index = cpu_register_io_memory(sm501_disp_ctrl_readfn,
1220
                                                   sm501_disp_ctrl_writefn, s);
1221
    cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
1222
                                 0x1000, sm501_disp_ctrl_index);
1223

    
1224
    /* bridge to usb host emulation module */
1225
    usb_ohci_init_sm501(base + MMIO_BASE_OFFSET + SM501_USB_HOST, base,
1226
                        2, -1, irq);
1227

    
1228
    /* bridge to serial emulation module */
1229
    if (chr) {
1230
#ifdef TARGET_WORDS_BIGENDIAN
1231
        serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
1232
                       NULL, /* TODO : chain irq to IRL */
1233
                       115200, chr, 1, 1);
1234
#else
1235
        serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
1236
                       NULL, /* TODO : chain irq to IRL */
1237
                       115200, chr, 1, 0);
1238
#endif
1239
    }
1240

    
1241
    /* create qemu graphic console */
1242
    s->ds = graphic_console_init(sm501_update_display, NULL,
1243
                                 NULL, NULL, s);
1244
}