Annotation of qemu/hw/blizzard.c, revision 1.1

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

unix.superglobalmegacorp.com

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