symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/blizzard.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller.
       
     3  *
       
     4  * Copyright (C) 2008 Nokia Corporation
       
     5  * Written by Andrzej Zaborowski <andrew@openedhand.com>
       
     6  *
       
     7  * This program is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU General Public License as
       
     9  * published by the Free Software Foundation; either version 2 or
       
    10  * (at your option) version 3 of the License.
       
    11  *
       
    12  * This program is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    15  * GNU General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License
       
    18  * along with this program; if not, write to the Free Software
       
    19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
       
    20  * MA 02111-1307 USA
       
    21  */
       
    22 
       
    23 #include "qemu-common.h"
       
    24 #include "sysemu.h"
       
    25 #include "console.h"
       
    26 #include "devices.h"
       
    27 #include "vga_int.h"
       
    28 #include "pixel_ops.h"
       
    29 
       
    30 typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);
       
    31 
       
    32 struct blizzard_s {
       
    33     uint8_t reg;
       
    34     uint32_t addr;
       
    35     int swallow;
       
    36 
       
    37     int pll;
       
    38     int pll_range;
       
    39     int pll_ctrl;
       
    40     uint8_t pll_mode;
       
    41     uint8_t clksel;
       
    42     int memenable;
       
    43     int memrefresh;
       
    44     uint8_t timing[3];
       
    45     int priority;
       
    46 
       
    47     uint8_t lcd_config;
       
    48     int x;
       
    49     int y;
       
    50     int skipx;
       
    51     int skipy;
       
    52     uint8_t hndp;
       
    53     uint8_t vndp;
       
    54     uint8_t hsync;
       
    55     uint8_t vsync;
       
    56     uint8_t pclk;
       
    57     uint8_t u;
       
    58     uint8_t v;
       
    59     uint8_t yrc[2];
       
    60     int ix[2];
       
    61     int iy[2];
       
    62     int ox[2];
       
    63     int oy[2];
       
    64 
       
    65     int enable;
       
    66     int blank;
       
    67     int bpp;
       
    68     int invalidate;
       
    69     int mx[2];
       
    70     int my[2];
       
    71     uint8_t mode;
       
    72     uint8_t effect;
       
    73     uint8_t iformat;
       
    74     uint8_t source;
       
    75     DisplayState *state;
       
    76     blizzard_fn_t *line_fn_tab[2];
       
    77     void *fb;
       
    78 
       
    79     uint8_t hssi_config[3];
       
    80     uint8_t tv_config;
       
    81     uint8_t tv_timing[4];
       
    82     uint8_t vbi;
       
    83     uint8_t tv_x;
       
    84     uint8_t tv_y;
       
    85     uint8_t tv_test;
       
    86     uint8_t tv_filter_config;
       
    87     uint8_t tv_filter_idx;
       
    88     uint8_t tv_filter_coeff[0x20];
       
    89     uint8_t border_r;
       
    90     uint8_t border_g;
       
    91     uint8_t border_b;
       
    92     uint8_t gamma_config;
       
    93     uint8_t gamma_idx;
       
    94     uint8_t gamma_lut[0x100];
       
    95     uint8_t matrix_ena;
       
    96     uint8_t matrix_coeff[0x12];
       
    97     uint8_t matrix_r;
       
    98     uint8_t matrix_g;
       
    99     uint8_t matrix_b;
       
   100     uint8_t pm;
       
   101     uint8_t status;
       
   102     uint8_t rgbgpio_dir;
       
   103     uint8_t rgbgpio;
       
   104     uint8_t gpio_dir;
       
   105     uint8_t gpio;
       
   106     uint8_t gpio_edge[2];
       
   107     uint8_t gpio_irq;
       
   108     uint8_t gpio_pdown;
       
   109 
       
   110     struct {
       
   111         int x;
       
   112         int y;
       
   113         int dx;
       
   114         int dy;
       
   115         int len;
       
   116         int buflen;
       
   117         void *buf;
       
   118         void *data;
       
   119         uint16_t *ptr;
       
   120         int angle;
       
   121         int pitch;
       
   122         blizzard_fn_t line_fn;
       
   123     } data;
       
   124 };
       
   125 
       
   126 /* Bytes(!) per pixel */
       
   127 static const int blizzard_iformat_bpp[0x10] = {
       
   128     0,
       
   129     2,	/* RGB 5:6:5*/
       
   130     3,	/* RGB 6:6:6 mode 1 */
       
   131     3,	/* RGB 8:8:8 mode 1 */
       
   132     0, 0,
       
   133     4,	/* RGB 6:6:6 mode 2 */
       
   134     4,	/* RGB 8:8:8 mode 2 */
       
   135     0,	/* YUV 4:2:2 */
       
   136     0,	/* YUV 4:2:0 */
       
   137     0, 0, 0, 0, 0, 0,
       
   138 };
       
   139 
       
   140 static inline void blizzard_rgb2yuv(int r, int g, int b,
       
   141                 int *y, int *u, int *v)
       
   142 {
       
   143     *y = 0x10 + ((0x838 * r + 0x1022 * g + 0x322 * b) >> 13);
       
   144     *u = 0x80 + ((0xe0e * b - 0x04c1 * r - 0x94e * g) >> 13);
       
   145     *v = 0x80 + ((0xe0e * r - 0x0bc7 * g - 0x247 * b) >> 13);
       
   146 }
       
   147 
       
   148 static void blizzard_window(struct blizzard_s *s)
       
   149 {
       
   150     uint8_t *src, *dst;
       
   151     int bypp[2];
       
   152     int bypl[3];
       
   153     int y;
       
   154     blizzard_fn_t fn = s->data.line_fn;
       
   155 
       
   156     if (!fn)
       
   157         return;
       
   158     if (s->mx[0] > s->data.x)
       
   159         s->mx[0] = s->data.x;
       
   160     if (s->my[0] > s->data.y)
       
   161         s->my[0] = s->data.y;
       
   162     if (s->mx[1] < s->data.x + s->data.dx)
       
   163         s->mx[1] = s->data.x + s->data.dx;
       
   164     if (s->my[1] < s->data.y + s->data.dy)
       
   165         s->my[1] = s->data.y + s->data.dy;
       
   166 
       
   167     bypp[0] = s->bpp;
       
   168     bypp[1] = (ds_get_bits_per_pixel(s->state) + 7) >> 3;
       
   169     bypl[0] = bypp[0] * s->data.pitch;
       
   170     bypl[1] = bypp[1] * s->x;
       
   171     bypl[2] = bypp[0] * s->data.dx;
       
   172 
       
   173     src = s->data.data;
       
   174     dst = s->fb + bypl[1] * s->data.y + bypp[1] * s->data.x;
       
   175     for (y = s->data.dy; y > 0; y --, src += bypl[0], dst += bypl[1])
       
   176         fn(dst, src, bypl[2]);
       
   177 }
       
   178 
       
   179 static int blizzard_transfer_setup(struct blizzard_s *s)
       
   180 {
       
   181     if (s->source > 3 || !s->bpp ||
       
   182                     s->ix[1] < s->ix[0] || s->iy[1] < s->iy[0])
       
   183         return 0;
       
   184 
       
   185     s->data.angle = s->effect & 3;
       
   186     s->data.line_fn = s->line_fn_tab[!!s->data.angle][s->iformat];
       
   187     s->data.x = s->ix[0];
       
   188     s->data.y = s->iy[0];
       
   189     s->data.dx = s->ix[1] - s->ix[0] + 1;
       
   190     s->data.dy = s->iy[1] - s->iy[0] + 1;
       
   191     s->data.len = s->bpp * s->data.dx * s->data.dy;
       
   192     s->data.pitch = s->data.dx;
       
   193     if (s->data.len > s->data.buflen) {
       
   194         s->data.buf = qemu_realloc(s->data.buf, s->data.len);
       
   195         s->data.buflen = s->data.len;
       
   196     }
       
   197     s->data.ptr = s->data.buf;
       
   198     s->data.data = s->data.buf;
       
   199     s->data.len /= 2;
       
   200     return 1;
       
   201 }
       
   202 
       
   203 static void blizzard_reset(struct blizzard_s *s)
       
   204 {
       
   205     s->reg = 0;
       
   206     s->swallow = 0;
       
   207 
       
   208     s->pll = 9;
       
   209     s->pll_range = 1;
       
   210     s->pll_ctrl = 0x14;
       
   211     s->pll_mode = 0x32;
       
   212     s->clksel = 0x00;
       
   213     s->memenable = 0;
       
   214     s->memrefresh = 0x25c;
       
   215     s->timing[0] = 0x3f;
       
   216     s->timing[1] = 0x13;
       
   217     s->timing[2] = 0x21;
       
   218     s->priority = 0;
       
   219 
       
   220     s->lcd_config = 0x74;
       
   221     s->x = 8;
       
   222     s->y = 1;
       
   223     s->skipx = 0;
       
   224     s->skipy = 0;
       
   225     s->hndp = 3;
       
   226     s->vndp = 2;
       
   227     s->hsync = 1;
       
   228     s->vsync = 1;
       
   229     s->pclk = 0x80;
       
   230 
       
   231     s->ix[0] = 0;
       
   232     s->ix[1] = 0;
       
   233     s->iy[0] = 0;
       
   234     s->iy[1] = 0;
       
   235     s->ox[0] = 0;
       
   236     s->ox[1] = 0;
       
   237     s->oy[0] = 0;
       
   238     s->oy[1] = 0;
       
   239 
       
   240     s->yrc[0] = 0x00;
       
   241     s->yrc[1] = 0x30;
       
   242     s->u = 0;
       
   243     s->v = 0;
       
   244 
       
   245     s->iformat = 3;
       
   246     s->source = 0;
       
   247     s->bpp = blizzard_iformat_bpp[s->iformat];
       
   248 
       
   249     s->hssi_config[0] = 0x00;
       
   250     s->hssi_config[1] = 0x00;
       
   251     s->hssi_config[2] = 0x01;
       
   252     s->tv_config = 0x00;
       
   253     s->tv_timing[0] = 0x00;
       
   254     s->tv_timing[1] = 0x00;
       
   255     s->tv_timing[2] = 0x00;
       
   256     s->tv_timing[3] = 0x00;
       
   257     s->vbi = 0x10;
       
   258     s->tv_x = 0x14;
       
   259     s->tv_y = 0x03;
       
   260     s->tv_test = 0x00;
       
   261     s->tv_filter_config = 0x80;
       
   262     s->tv_filter_idx = 0x00;
       
   263     s->border_r = 0x10;
       
   264     s->border_g = 0x80;
       
   265     s->border_b = 0x80;
       
   266     s->gamma_config = 0x00;
       
   267     s->gamma_idx = 0x00;
       
   268     s->matrix_ena = 0x00;
       
   269     memset(&s->matrix_coeff, 0, sizeof(s->matrix_coeff));
       
   270     s->matrix_r = 0x00;
       
   271     s->matrix_g = 0x00;
       
   272     s->matrix_b = 0x00;
       
   273     s->pm = 0x02;
       
   274     s->status = 0x00;
       
   275     s->rgbgpio_dir = 0x00;
       
   276     s->gpio_dir = 0x00;
       
   277     s->gpio_edge[0] = 0x00;
       
   278     s->gpio_edge[1] = 0x00;
       
   279     s->gpio_irq = 0x00;
       
   280     s->gpio_pdown = 0xff;
       
   281 }
       
   282 
       
   283 static inline void blizzard_invalidate_display(void *opaque) {
       
   284     struct blizzard_s *s = (struct blizzard_s *) opaque;
       
   285 
       
   286     s->invalidate = 1;
       
   287 }
       
   288 
       
   289 static uint16_t blizzard_reg_read(void *opaque, uint8_t reg)
       
   290 {
       
   291     struct blizzard_s *s = (struct blizzard_s *) opaque;
       
   292 
       
   293     switch (reg) {
       
   294     case 0x00:	/* Revision Code */
       
   295         return 0xa5;
       
   296 
       
   297     case 0x02:	/* Configuration Readback */
       
   298         return 0x83;	/* Macrovision OK, CNF[2:0] = 3 */
       
   299 
       
   300     case 0x04:	/* PLL M-Divider */
       
   301         return (s->pll - 1) | (1 << 7);
       
   302     case 0x06:	/* PLL Lock Range Control */
       
   303         return s->pll_range;
       
   304     case 0x08:	/* PLL Lock Synthesis Control 0 */
       
   305         return s->pll_ctrl & 0xff;
       
   306     case 0x0a:	/* PLL Lock Synthesis Control 1 */
       
   307         return s->pll_ctrl >> 8;
       
   308     case 0x0c:	/* PLL Mode Control 0 */
       
   309         return s->pll_mode;
       
   310 
       
   311     case 0x0e:	/* Clock-Source Select */
       
   312         return s->clksel;
       
   313 
       
   314     case 0x10:	/* Memory Controller Activate */
       
   315     case 0x14:	/* Memory Controller Bank 0 Status Flag */
       
   316         return s->memenable;
       
   317 
       
   318     case 0x18:	/* Auto-Refresh Interval Setting 0 */
       
   319         return s->memrefresh & 0xff;
       
   320     case 0x1a:	/* Auto-Refresh Interval Setting 1 */
       
   321         return s->memrefresh >> 8;
       
   322 
       
   323     case 0x1c:	/* Power-On Sequence Timing Control */
       
   324         return s->timing[0];
       
   325     case 0x1e:	/* Timing Control 0 */
       
   326         return s->timing[1];
       
   327     case 0x20:	/* Timing Control 1 */
       
   328         return s->timing[2];
       
   329 
       
   330     case 0x24:	/* Arbitration Priority Control */
       
   331         return s->priority;
       
   332 
       
   333     case 0x28:	/* LCD Panel Configuration */
       
   334         return s->lcd_config;
       
   335 
       
   336     case 0x2a:	/* LCD Horizontal Display Width */
       
   337         return s->x >> 3;
       
   338     case 0x2c:	/* LCD Horizontal Non-display Period */
       
   339         return s->hndp;
       
   340     case 0x2e:	/* LCD Vertical Display Height 0 */
       
   341         return s->y & 0xff;
       
   342     case 0x30:	/* LCD Vertical Display Height 1 */
       
   343         return s->y >> 8;
       
   344     case 0x32:	/* LCD Vertical Non-display Period */
       
   345         return s->vndp;
       
   346     case 0x34:	/* LCD HS Pulse-width */
       
   347         return s->hsync;
       
   348     case 0x36:	/* LCd HS Pulse Start Position */
       
   349         return s->skipx >> 3;
       
   350     case 0x38:	/* LCD VS Pulse-width */
       
   351         return s->vsync;
       
   352     case 0x3a:	/* LCD VS Pulse Start Position */
       
   353         return s->skipy;
       
   354 
       
   355     case 0x3c:	/* PCLK Polarity */
       
   356         return s->pclk;
       
   357 
       
   358     case 0x3e:	/* High-speed Serial Interface Tx Configuration Port 0 */
       
   359         return s->hssi_config[0];
       
   360     case 0x40:	/* High-speed Serial Interface Tx Configuration Port 1 */
       
   361         return s->hssi_config[1];
       
   362     case 0x42:	/* High-speed Serial Interface Tx Mode */
       
   363         return s->hssi_config[2];
       
   364     case 0x44:	/* TV Display Configuration */
       
   365         return s->tv_config;
       
   366     case 0x46 ... 0x4c:	/* TV Vertical Blanking Interval Data bits */
       
   367         return s->tv_timing[(reg - 0x46) >> 1];
       
   368     case 0x4e:	/* VBI: Closed Caption / XDS Control / Status */
       
   369         return s->vbi;
       
   370     case 0x50:	/* TV Horizontal Start Position */
       
   371         return s->tv_x;
       
   372     case 0x52:	/* TV Vertical Start Position */
       
   373         return s->tv_y;
       
   374     case 0x54:	/* TV Test Pattern Setting */
       
   375         return s->tv_test;
       
   376     case 0x56:	/* TV Filter Setting */
       
   377         return s->tv_filter_config;
       
   378     case 0x58:	/* TV Filter Coefficient Index */
       
   379         return s->tv_filter_idx;
       
   380     case 0x5a:	/* TV Filter Coefficient Data */
       
   381         if (s->tv_filter_idx < 0x20)
       
   382             return s->tv_filter_coeff[s->tv_filter_idx ++];
       
   383         return 0;
       
   384 
       
   385     case 0x60:	/* Input YUV/RGB Translate Mode 0 */
       
   386         return s->yrc[0];
       
   387     case 0x62:	/* Input YUV/RGB Translate Mode 1 */
       
   388         return s->yrc[1];
       
   389     case 0x64:	/* U Data Fix */
       
   390         return s->u;
       
   391     case 0x66:	/* V Data Fix */
       
   392         return s->v;
       
   393 
       
   394     case 0x68:	/* Display Mode */
       
   395         return s->mode;
       
   396 
       
   397     case 0x6a:	/* Special Effects */
       
   398         return s->effect;
       
   399 
       
   400     case 0x6c:	/* Input Window X Start Position 0 */
       
   401         return s->ix[0] & 0xff;
       
   402     case 0x6e:	/* Input Window X Start Position 1 */
       
   403         return s->ix[0] >> 3;
       
   404     case 0x70:	/* Input Window Y Start Position 0 */
       
   405         return s->ix[0] & 0xff;
       
   406     case 0x72:	/* Input Window Y Start Position 1 */
       
   407         return s->ix[0] >> 3;
       
   408     case 0x74:	/* Input Window X End Position 0 */
       
   409         return s->ix[1] & 0xff;
       
   410     case 0x76:	/* Input Window X End Position 1 */
       
   411         return s->ix[1] >> 3;
       
   412     case 0x78:	/* Input Window Y End Position 0 */
       
   413         return s->ix[1] & 0xff;
       
   414     case 0x7a:	/* Input Window Y End Position 1 */
       
   415         return s->ix[1] >> 3;
       
   416     case 0x7c:	/* Output Window X Start Position 0 */
       
   417         return s->ox[0] & 0xff;
       
   418     case 0x7e:	/* Output Window X Start Position 1 */
       
   419         return s->ox[0] >> 3;
       
   420     case 0x80:	/* Output Window Y Start Position 0 */
       
   421         return s->oy[0] & 0xff;
       
   422     case 0x82:	/* Output Window Y Start Position 1 */
       
   423         return s->oy[0] >> 3;
       
   424     case 0x84:	/* Output Window X End Position 0 */
       
   425         return s->ox[1] & 0xff;
       
   426     case 0x86:	/* Output Window X End Position 1 */
       
   427         return s->ox[1] >> 3;
       
   428     case 0x88:	/* Output Window Y End Position 0 */
       
   429         return s->oy[1] & 0xff;
       
   430     case 0x8a:	/* Output Window Y End Position 1 */
       
   431         return s->oy[1] >> 3;
       
   432 
       
   433     case 0x8c:	/* Input Data Format */
       
   434         return s->iformat;
       
   435     case 0x8e:	/* Data Source Select */
       
   436         return s->source;
       
   437     case 0x90:	/* Display Memory Data Port */
       
   438         return 0;
       
   439 
       
   440     case 0xa8:	/* Border Color 0 */
       
   441         return s->border_r;
       
   442     case 0xaa:	/* Border Color 1 */
       
   443         return s->border_g;
       
   444     case 0xac:	/* Border Color 2 */
       
   445         return s->border_b;
       
   446 
       
   447     case 0xb4:	/* Gamma Correction Enable */
       
   448         return s->gamma_config;
       
   449     case 0xb6:	/* Gamma Correction Table Index */
       
   450         return s->gamma_idx;
       
   451     case 0xb8:	/* Gamma Correction Table Data */
       
   452         return s->gamma_lut[s->gamma_idx ++];
       
   453 
       
   454     case 0xba:	/* 3x3 Matrix Enable */
       
   455         return s->matrix_ena;
       
   456     case 0xbc ... 0xde:	/* Coefficient Registers */
       
   457         return s->matrix_coeff[(reg - 0xbc) >> 1];
       
   458     case 0xe0:	/* 3x3 Matrix Red Offset */
       
   459         return s->matrix_r;
       
   460     case 0xe2:	/* 3x3 Matrix Green Offset */
       
   461         return s->matrix_g;
       
   462     case 0xe4:	/* 3x3 Matrix Blue Offset */
       
   463         return s->matrix_b;
       
   464 
       
   465     case 0xe6:	/* Power-save */
       
   466         return s->pm;
       
   467     case 0xe8:	/* Non-display Period Control / Status */
       
   468         return s->status | (1 << 5);
       
   469     case 0xea:	/* RGB Interface Control */
       
   470         return s->rgbgpio_dir;
       
   471     case 0xec:	/* RGB Interface Status */
       
   472         return s->rgbgpio;
       
   473     case 0xee:	/* General-purpose IO Pins Configuration */
       
   474         return s->gpio_dir;
       
   475     case 0xf0:	/* General-purpose IO Pins Status / Control */
       
   476         return s->gpio;
       
   477     case 0xf2:	/* GPIO Positive Edge Interrupt Trigger */
       
   478         return s->gpio_edge[0];
       
   479     case 0xf4:	/* GPIO Negative Edge Interrupt Trigger */
       
   480         return s->gpio_edge[1];
       
   481     case 0xf6:	/* GPIO Interrupt Status */
       
   482         return s->gpio_irq;
       
   483     case 0xf8:	/* GPIO Pull-down Control */
       
   484         return s->gpio_pdown;
       
   485 
       
   486     default:
       
   487         fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg);
       
   488         return 0;
       
   489     }
       
   490 }
       
   491 
       
   492 static void blizzard_reg_write(void *opaque, uint8_t reg, uint16_t value)
       
   493 {
       
   494     struct blizzard_s *s = (struct blizzard_s *) opaque;
       
   495 
       
   496     switch (reg) {
       
   497     case 0x04:	/* PLL M-Divider */
       
   498         s->pll = (value & 0x3f) + 1;
       
   499         break;
       
   500     case 0x06:	/* PLL Lock Range Control */
       
   501         s->pll_range = value & 3;
       
   502         break;
       
   503     case 0x08:	/* PLL Lock Synthesis Control 0 */
       
   504         s->pll_ctrl &= 0xf00;
       
   505         s->pll_ctrl |= (value << 0) & 0x0ff;
       
   506         break;
       
   507     case 0x0a:	/* PLL Lock Synthesis Control 1 */
       
   508         s->pll_ctrl &= 0x0ff;
       
   509         s->pll_ctrl |= (value << 8) & 0xf00;
       
   510         break;
       
   511     case 0x0c:	/* PLL Mode Control 0 */
       
   512         s->pll_mode = value & 0x77;
       
   513         if ((value & 3) == 0 || (value & 3) == 3)
       
   514             fprintf(stderr, "%s: wrong PLL Control bits (%i)\n",
       
   515                     __FUNCTION__, value & 3);
       
   516         break;
       
   517 
       
   518     case 0x0e:	/* Clock-Source Select */
       
   519         s->clksel = value & 0xff;
       
   520         break;
       
   521 
       
   522     case 0x10:	/* Memory Controller Activate */
       
   523         s->memenable = value & 1;
       
   524         break;
       
   525     case 0x14:	/* Memory Controller Bank 0 Status Flag */
       
   526         break;
       
   527 
       
   528     case 0x18:	/* Auto-Refresh Interval Setting 0 */
       
   529         s->memrefresh &= 0xf00;
       
   530         s->memrefresh |= (value << 0) & 0x0ff;
       
   531         break;
       
   532     case 0x1a:	/* Auto-Refresh Interval Setting 1 */
       
   533         s->memrefresh &= 0x0ff;
       
   534         s->memrefresh |= (value << 8) & 0xf00;
       
   535         break;
       
   536 
       
   537     case 0x1c:	/* Power-On Sequence Timing Control */
       
   538         s->timing[0] = value & 0x7f;
       
   539         break;
       
   540     case 0x1e:	/* Timing Control 0 */
       
   541         s->timing[1] = value & 0x17;
       
   542         break;
       
   543     case 0x20:	/* Timing Control 1 */
       
   544         s->timing[2] = value & 0x35;
       
   545         break;
       
   546 
       
   547     case 0x24:	/* Arbitration Priority Control */
       
   548         s->priority = value & 1;
       
   549         break;
       
   550 
       
   551     case 0x28:	/* LCD Panel Configuration */
       
   552         s->lcd_config = value & 0xff;
       
   553         if (value & (1 << 7))
       
   554             fprintf(stderr, "%s: data swap not supported!\n", __FUNCTION__);
       
   555         break;
       
   556 
       
   557     case 0x2a:	/* LCD Horizontal Display Width */
       
   558         s->x = value << 3;
       
   559         break;
       
   560     case 0x2c:	/* LCD Horizontal Non-display Period */
       
   561         s->hndp = value & 0xff;
       
   562         break;
       
   563     case 0x2e:	/* LCD Vertical Display Height 0 */
       
   564         s->y &= 0x300;
       
   565         s->y |= (value << 0) & 0x0ff;
       
   566         break;
       
   567     case 0x30:	/* LCD Vertical Display Height 1 */
       
   568         s->y &= 0x0ff;
       
   569         s->y |= (value << 8) & 0x300;
       
   570         break;
       
   571     case 0x32:	/* LCD Vertical Non-display Period */
       
   572         s->vndp = value & 0xff;
       
   573         break;
       
   574     case 0x34:	/* LCD HS Pulse-width */
       
   575         s->hsync = value & 0xff;
       
   576         break;
       
   577     case 0x36:	/* LCD HS Pulse Start Position */
       
   578         s->skipx = value & 0xff;
       
   579         break;
       
   580     case 0x38:	/* LCD VS Pulse-width */
       
   581         s->vsync = value & 0xbf;
       
   582         break;
       
   583     case 0x3a:	/* LCD VS Pulse Start Position */
       
   584         s->skipy = value & 0xff;
       
   585         break;
       
   586 
       
   587     case 0x3c:	/* PCLK Polarity */
       
   588         s->pclk = value & 0x82;
       
   589         /* Affects calculation of s->hndp, s->hsync and s->skipx.  */
       
   590         break;
       
   591 
       
   592     case 0x3e:	/* High-speed Serial Interface Tx Configuration Port 0 */
       
   593         s->hssi_config[0] = value;
       
   594         break;
       
   595     case 0x40:	/* High-speed Serial Interface Tx Configuration Port 1 */
       
   596         s->hssi_config[1] = value;
       
   597         if (((value >> 4) & 3) == 3)
       
   598             fprintf(stderr, "%s: Illegal active-data-links value\n",
       
   599                             __FUNCTION__);
       
   600         break;
       
   601     case 0x42:	/* High-speed Serial Interface Tx Mode */
       
   602         s->hssi_config[2] = value & 0xbd;
       
   603         break;
       
   604 
       
   605     case 0x44:	/* TV Display Configuration */
       
   606         s->tv_config = value & 0xfe;
       
   607         break;
       
   608     case 0x46 ... 0x4c:	/* TV Vertical Blanking Interval Data bits 0 */
       
   609         s->tv_timing[(reg - 0x46) >> 1] = value;
       
   610         break;
       
   611     case 0x4e:	/* VBI: Closed Caption / XDS Control / Status */
       
   612         s->vbi = value;
       
   613         break;
       
   614     case 0x50:	/* TV Horizontal Start Position */
       
   615         s->tv_x = value;
       
   616         break;
       
   617     case 0x52:	/* TV Vertical Start Position */
       
   618         s->tv_y = value & 0x7f;
       
   619         break;
       
   620     case 0x54:	/* TV Test Pattern Setting */
       
   621         s->tv_test = value;
       
   622         break;
       
   623     case 0x56:	/* TV Filter Setting */
       
   624         s->tv_filter_config = value & 0xbf;
       
   625         break;
       
   626     case 0x58:	/* TV Filter Coefficient Index */
       
   627         s->tv_filter_idx = value & 0x1f;
       
   628         break;
       
   629     case 0x5a:	/* TV Filter Coefficient Data */
       
   630         if (s->tv_filter_idx < 0x20)
       
   631             s->tv_filter_coeff[s->tv_filter_idx ++] = value;
       
   632         break;
       
   633 
       
   634     case 0x60:	/* Input YUV/RGB Translate Mode 0 */
       
   635         s->yrc[0] = value & 0xb0;
       
   636         break;
       
   637     case 0x62:	/* Input YUV/RGB Translate Mode 1 */
       
   638         s->yrc[1] = value & 0x30;
       
   639         break;
       
   640     case 0x64:	/* U Data Fix */
       
   641         s->u = value & 0xff;
       
   642         break;
       
   643     case 0x66:	/* V Data Fix */
       
   644         s->v = value & 0xff;
       
   645         break;
       
   646 
       
   647     case 0x68:	/* Display Mode */
       
   648         if ((s->mode ^ value) & 3)
       
   649             s->invalidate = 1;
       
   650         s->mode = value & 0xb7;
       
   651         s->enable = value & 1;
       
   652         s->blank = (value >> 1) & 1;
       
   653         if (value & (1 << 4))
       
   654             fprintf(stderr, "%s: Macrovision enable attempt!\n", __FUNCTION__);
       
   655         break;
       
   656 
       
   657     case 0x6a:	/* Special Effects */
       
   658         s->effect = value & 0xfb;
       
   659         break;
       
   660 
       
   661     case 0x6c:	/* Input Window X Start Position 0 */
       
   662         s->ix[0] &= 0x300;
       
   663         s->ix[0] |= (value << 0) & 0x0ff;
       
   664         break;
       
   665     case 0x6e:	/* Input Window X Start Position 1 */
       
   666         s->ix[0] &= 0x0ff;
       
   667         s->ix[0] |= (value << 8) & 0x300;
       
   668         break;
       
   669     case 0x70:	/* Input Window Y Start Position 0 */
       
   670         s->iy[0] &= 0x300;
       
   671         s->iy[0] |= (value << 0) & 0x0ff;
       
   672         break;
       
   673     case 0x72:	/* Input Window Y Start Position 1 */
       
   674         s->iy[0] &= 0x0ff;
       
   675         s->iy[0] |= (value << 8) & 0x300;
       
   676         break;
       
   677     case 0x74:	/* Input Window X End Position 0 */
       
   678         s->ix[1] &= 0x300;
       
   679         s->ix[1] |= (value << 0) & 0x0ff;
       
   680         break;
       
   681     case 0x76:	/* Input Window X End Position 1 */
       
   682         s->ix[1] &= 0x0ff;
       
   683         s->ix[1] |= (value << 8) & 0x300;
       
   684         break;
       
   685     case 0x78:	/* Input Window Y End Position 0 */
       
   686         s->iy[1] &= 0x300;
       
   687         s->iy[1] |= (value << 0) & 0x0ff;
       
   688         break;
       
   689     case 0x7a:	/* Input Window Y End Position 1 */
       
   690         s->iy[1] &= 0x0ff;
       
   691         s->iy[1] |= (value << 8) & 0x300;
       
   692         break;
       
   693     case 0x7c:	/* Output Window X Start Position 0 */
       
   694         s->ox[0] &= 0x300;
       
   695         s->ox[0] |= (value << 0) & 0x0ff;
       
   696         break;
       
   697     case 0x7e:	/* Output Window X Start Position 1 */
       
   698         s->ox[0] &= 0x0ff;
       
   699         s->ox[0] |= (value << 8) & 0x300;
       
   700         break;
       
   701     case 0x80:	/* Output Window Y Start Position 0 */
       
   702         s->oy[0] &= 0x300;
       
   703         s->oy[0] |= (value << 0) & 0x0ff;
       
   704         break;
       
   705     case 0x82:	/* Output Window Y Start Position 1 */
       
   706         s->oy[0] &= 0x0ff;
       
   707         s->oy[0] |= (value << 8) & 0x300;
       
   708         break;
       
   709     case 0x84:	/* Output Window X End Position 0 */
       
   710         s->ox[1] &= 0x300;
       
   711         s->ox[1] |= (value << 0) & 0x0ff;
       
   712         break;
       
   713     case 0x86:	/* Output Window X End Position 1 */
       
   714         s->ox[1] &= 0x0ff;
       
   715         s->ox[1] |= (value << 8) & 0x300;
       
   716         break;
       
   717     case 0x88:	/* Output Window Y End Position 0 */
       
   718         s->oy[1] &= 0x300;
       
   719         s->oy[1] |= (value << 0) & 0x0ff;
       
   720         break;
       
   721     case 0x8a:	/* Output Window Y End Position 1 */
       
   722         s->oy[1] &= 0x0ff;
       
   723         s->oy[1] |= (value << 8) & 0x300;
       
   724         break;
       
   725 
       
   726     case 0x8c:	/* Input Data Format */
       
   727         s->iformat = value & 0xf;
       
   728         s->bpp = blizzard_iformat_bpp[s->iformat];
       
   729         if (!s->bpp)
       
   730             fprintf(stderr, "%s: Illegal or unsupported input format %x\n",
       
   731                             __FUNCTION__, s->iformat);
       
   732         break;
       
   733     case 0x8e:	/* Data Source Select */
       
   734         s->source = value & 7;
       
   735         /* Currently all windows will be "destructive overlays".  */
       
   736         if ((!(s->effect & (1 << 3)) && (s->ix[0] != s->ox[0] ||
       
   737                                         s->iy[0] != s->oy[0] ||
       
   738                                         s->ix[1] != s->ox[1] ||
       
   739                                         s->iy[1] != s->oy[1])) ||
       
   740                         !((s->ix[1] - s->ix[0]) & (s->iy[1] - s->iy[0]) &
       
   741                           (s->ox[1] - s->ox[0]) & (s->oy[1] - s->oy[0]) & 1))
       
   742             fprintf(stderr, "%s: Illegal input/output window positions\n",
       
   743                             __FUNCTION__);
       
   744 
       
   745         blizzard_transfer_setup(s);
       
   746         break;
       
   747 
       
   748     case 0x90:	/* Display Memory Data Port */
       
   749         if (!s->data.len && !blizzard_transfer_setup(s))
       
   750             break;
       
   751 
       
   752         *s->data.ptr ++ = value;
       
   753         if (-- s->data.len == 0)
       
   754             blizzard_window(s);
       
   755         break;
       
   756 
       
   757     case 0xa8:	/* Border Color 0 */
       
   758         s->border_r = value;
       
   759         break;
       
   760     case 0xaa:	/* Border Color 1 */
       
   761         s->border_g = value;
       
   762         break;
       
   763     case 0xac:	/* Border Color 2 */
       
   764         s->border_b = value;
       
   765         break;
       
   766 
       
   767     case 0xb4:	/* Gamma Correction Enable */
       
   768         s->gamma_config = value & 0x87;
       
   769         break;
       
   770     case 0xb6:	/* Gamma Correction Table Index */
       
   771         s->gamma_idx = value;
       
   772         break;
       
   773     case 0xb8:	/* Gamma Correction Table Data */
       
   774         s->gamma_lut[s->gamma_idx ++] = value;
       
   775         break;
       
   776 
       
   777     case 0xba:	/* 3x3 Matrix Enable */
       
   778         s->matrix_ena = value & 1;
       
   779         break;
       
   780     case 0xbc ... 0xde:	/* Coefficient Registers */
       
   781         s->matrix_coeff[(reg - 0xbc) >> 1] = value & ((reg & 2) ? 0x80 : 0xff);
       
   782         break;
       
   783     case 0xe0:	/* 3x3 Matrix Red Offset */
       
   784         s->matrix_r = value;
       
   785         break;
       
   786     case 0xe2:	/* 3x3 Matrix Green Offset */
       
   787         s->matrix_g = value;
       
   788         break;
       
   789     case 0xe4:	/* 3x3 Matrix Blue Offset */
       
   790         s->matrix_b = value;
       
   791         break;
       
   792 
       
   793     case 0xe6:	/* Power-save */
       
   794         s->pm = value & 0x83;
       
   795         if (value & s->mode & 1)
       
   796             fprintf(stderr, "%s: The display must be disabled before entering "
       
   797                             "Standby Mode\n", __FUNCTION__);
       
   798         break;
       
   799     case 0xe8:	/* Non-display Period Control / Status */
       
   800         s->status = value & 0x1b;
       
   801         break;
       
   802     case 0xea:	/* RGB Interface Control */
       
   803         s->rgbgpio_dir = value & 0x8f;
       
   804         break;
       
   805     case 0xec:	/* RGB Interface Status */
       
   806         s->rgbgpio = value & 0xcf;
       
   807         break;
       
   808     case 0xee:	/* General-purpose IO Pins Configuration */
       
   809         s->gpio_dir = value;
       
   810         break;
       
   811     case 0xf0:	/* General-purpose IO Pins Status / Control */
       
   812         s->gpio = value;
       
   813         break;
       
   814     case 0xf2:	/* GPIO Positive Edge Interrupt Trigger */
       
   815         s->gpio_edge[0] = value;
       
   816         break;
       
   817     case 0xf4:	/* GPIO Negative Edge Interrupt Trigger */
       
   818         s->gpio_edge[1] = value;
       
   819         break;
       
   820     case 0xf6:	/* GPIO Interrupt Status */
       
   821         s->gpio_irq &= value;
       
   822         break;
       
   823     case 0xf8:	/* GPIO Pull-down Control */
       
   824         s->gpio_pdown = value;
       
   825         break;
       
   826 
       
   827     default:
       
   828         fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg);
       
   829         break;
       
   830     }
       
   831 }
       
   832 
       
   833 uint16_t s1d13745_read(void *opaque, int dc)
       
   834 {
       
   835     struct blizzard_s *s = (struct blizzard_s *) opaque;
       
   836     uint16_t value = blizzard_reg_read(s, s->reg);
       
   837 
       
   838     if (s->swallow -- > 0)
       
   839         return 0;
       
   840     if (dc)
       
   841         s->reg ++;
       
   842 
       
   843     return value;
       
   844 }
       
   845 
       
   846 void s1d13745_write(void *opaque, int dc, uint16_t value)
       
   847 {
       
   848     struct blizzard_s *s = (struct blizzard_s *) opaque;
       
   849 
       
   850     if (s->swallow -- > 0)
       
   851         return;
       
   852     if (dc) {
       
   853         blizzard_reg_write(s, s->reg, value);
       
   854 
       
   855         if (s->reg != 0x90 && s->reg != 0x5a && s->reg != 0xb8)
       
   856             s->reg += 2;
       
   857     } else
       
   858         s->reg = value & 0xff;
       
   859 }
       
   860 
       
   861 void s1d13745_write_block(void *opaque, int dc,
       
   862                 void *buf, size_t len, int pitch)
       
   863 {
       
   864     struct blizzard_s *s = (struct blizzard_s *) opaque;
       
   865 
       
   866     while (len > 0) {
       
   867         if (s->reg == 0x90 && dc &&
       
   868                         (s->data.len || blizzard_transfer_setup(s)) &&
       
   869                         len >= (s->data.len << 1)) {
       
   870             len -= s->data.len << 1;
       
   871             s->data.len = 0;
       
   872             s->data.data = buf;
       
   873             if (pitch)
       
   874                 s->data.pitch = pitch;
       
   875             blizzard_window(s);
       
   876             s->data.data = s->data.buf;
       
   877             continue;
       
   878         }
       
   879 
       
   880         s1d13745_write(opaque, dc, *(uint16_t *) buf);
       
   881         len -= 2;
       
   882         buf += 2;
       
   883     }
       
   884 
       
   885     return;
       
   886 }
       
   887 
       
   888 static void blizzard_update_display(void *opaque)
       
   889 {
       
   890     struct blizzard_s *s = (struct blizzard_s *) opaque;
       
   891     int y, bypp, bypl, bwidth;
       
   892     uint8_t *src, *dst;
       
   893 
       
   894     if (!s->enable)
       
   895         return;
       
   896 
       
   897     if (s->x != ds_get_width(s->state) || s->y != ds_get_height(s->state)) {
       
   898         s->invalidate = 1;
       
   899         gui_resize_vt(s->state, s->x, s->y);
       
   900     }
       
   901 
       
   902     if (s->invalidate) {
       
   903         s->invalidate = 0;
       
   904 
       
   905         if (s->blank) {
       
   906             bypp = (ds_get_bits_per_pixel(s->state) + 7) >> 3;
       
   907             memset(ds_get_data(s->state), 0, bypp * s->x * s->y);
       
   908             return;
       
   909         }
       
   910 
       
   911         s->mx[0] = 0;
       
   912         s->mx[1] = s->x;
       
   913         s->my[0] = 0;
       
   914         s->my[1] = s->y;
       
   915     }
       
   916 
       
   917     if (s->mx[1] <= s->mx[0])
       
   918         return;
       
   919 
       
   920     bypp = (ds_get_bits_per_pixel(s->state) + 7) >> 3;
       
   921     bypl = bypp * s->x;
       
   922     bwidth = bypp * (s->mx[1] - s->mx[0]);
       
   923     y = s->my[0];
       
   924     src = s->fb + bypl * y + bypp * s->mx[0];
       
   925     dst = ds_get_data(s->state) + bypl * y + bypp * s->mx[0];
       
   926     for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
       
   927         memcpy(dst, src, bwidth);
       
   928 
       
   929     dpy_update(s->state, s->mx[0], s->my[0],
       
   930                     s->mx[1] - s->mx[0], y - s->my[0]);
       
   931 
       
   932     s->mx[0] = s->x;
       
   933     s->mx[1] = 0;
       
   934     s->my[0] = s->y;
       
   935     s->my[1] = 0;
       
   936 }
       
   937 
       
   938 static void blizzard_screen_dump(void *opaque, const char *filename) {
       
   939     struct blizzard_s *s = (struct blizzard_s *) opaque;
       
   940 
       
   941     blizzard_update_display(opaque);
       
   942     if (s && ds_get_data(s->state))
       
   943         ppm_save(filename, ds_get_data(s->state), s->x, s->y, ds_get_linesize(s->state));
       
   944 }
       
   945 
       
   946 #define DEPTH 8
       
   947 #include "blizzard_template.h"
       
   948 #define DEPTH 15
       
   949 #include "blizzard_template.h"
       
   950 #define DEPTH 16
       
   951 #include "blizzard_template.h"
       
   952 #define DEPTH 24
       
   953 #include "blizzard_template.h"
       
   954 #define DEPTH 32
       
   955 #include "blizzard_template.h"
       
   956 
       
   957 void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds)
       
   958 {
       
   959     struct blizzard_s *s = (struct blizzard_s *) qemu_mallocz(sizeof(*s));
       
   960 
       
   961     s->fb = qemu_malloc(0x180000);
       
   962 
       
   963     switch (ds_get_bits_per_pixel(s->state)) {
       
   964     case 0:
       
   965         s->line_fn_tab[0] = s->line_fn_tab[1] =
       
   966                 qemu_mallocz(sizeof(blizzard_fn_t) * 0x10);
       
   967         break;
       
   968     case 8:
       
   969         s->line_fn_tab[0] = blizzard_draw_fn_8;
       
   970         s->line_fn_tab[1] = blizzard_draw_fn_r_8;
       
   971         break;
       
   972     case 15:
       
   973         s->line_fn_tab[0] = blizzard_draw_fn_15;
       
   974         s->line_fn_tab[1] = blizzard_draw_fn_r_15;
       
   975         break;
       
   976     case 16:
       
   977         s->line_fn_tab[0] = blizzard_draw_fn_16;
       
   978         s->line_fn_tab[1] = blizzard_draw_fn_r_16;
       
   979         break;
       
   980     case 24:
       
   981         s->line_fn_tab[0] = blizzard_draw_fn_24;
       
   982         s->line_fn_tab[1] = blizzard_draw_fn_r_24;
       
   983         break;
       
   984     case 32:
       
   985         s->line_fn_tab[0] = blizzard_draw_fn_32;
       
   986         s->line_fn_tab[1] = blizzard_draw_fn_r_32;
       
   987         break;
       
   988     default:
       
   989         fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
       
   990         exit(1);
       
   991     }
       
   992 
       
   993     blizzard_reset(s);
       
   994 
       
   995     s->state = gui_get_graphic_console(NULL,
       
   996                                        blizzard_update_display,
       
   997                                        blizzard_invalidate_display,
       
   998                                        blizzard_screen_dump, s);
       
   999 
       
  1000     return s;
       
  1001 }