diff options
Diffstat (limited to 'chips/ims332.c')
-rw-r--r-- | chips/ims332.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/chips/ims332.c b/chips/ims332.c new file mode 100644 index 0000000..ebe6a6c --- /dev/null +++ b/chips/ims332.c @@ -0,0 +1,312 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * File: ims332.c + * Author: Alessandro Forin, Carnegie Mellon University + * Date: 1/92 + * + * Routines for the Inmos IMS-G332 Colour video controller + */ + +#include <platforms.h> + +#include <chips/ims332.h> +#include <chips/screen.h> + +#include <chips/xcfb_monitor.h> + +/* + * Generic register access + */ +typedef volatile unsigned char *ims332_padded_regmap_t; + +#ifdef MAXINE + +unsigned int +ims332_read_register(regs, regno) + unsigned char *regs; +{ + unsigned char *rptr; + register unsigned int val, v1; + + /* spec sez: */ + rptr = regs + 0x80000 + (regno << 4); + val = * ((volatile unsigned short *) rptr ); + v1 = * ((volatile unsigned short *) regs ); + + return (val & 0xffff) | ((v1 & 0xff00) << 8); +} + +ims332_write_register(regs, regno, val) + unsigned char *regs; + register unsigned int val; +{ + unsigned char *wptr; + + /* spec sez: */ + wptr = regs + 0xa0000 + (regno << 4); + * ((volatile unsigned int *)(regs)) = (val >> 8) & 0xff00; + * ((volatile unsigned short *)(wptr)) = val; +} + +#define assert_ims332_reset_bit(r) *r &= ~0x40 +#define deassert_ims332_reset_bit(r) *r |= 0x40 + +#else /*MAXINE*/ + +#define ims332_read_register(p,r) \ + ((unsigned int *)(p)) [ (r) ] +#define ims332_write_register(p,r,v) \ + ((unsigned int *)(p)) [ (r) ] = (v) + +#endif /*MAXINE*/ + + +/* + * Color map + */ +ims332_load_colormap( regs, map) + ims332_padded_regmap_t *regs; + color_map_t *map; +{ + register int i; + + for (i = 0; i < 256; i++, map++) + ims332_load_colormap_entry(regs, i, map); +} + +ims332_load_colormap_entry( regs, entry, map) + ims332_padded_regmap_t *regs; + color_map_t *map; +{ + /* ?? stop VTG */ + ims332_write_register(regs, IMS332_REG_LUT_BASE + (entry & 0xff), + (map->blue << 16) | + (map->green << 8) | + (map->red)); +} + +ims332_init_colormap( regs) + ims332_padded_regmap_t *regs; +{ + color_map_t m; + + m.red = m.green = m.blue = 0; + ims332_load_colormap_entry( regs, 0, &m); + + m.red = m.green = m.blue = 0xff; + ims332_load_colormap_entry( regs, 1, &m); + ims332_load_colormap_entry( regs, 255, &m); + + /* since we are at it, also fix cursor LUT */ + ims332_load_colormap_entry( regs, IMS332_REG_CURSOR_LUT_0, &m); + ims332_load_colormap_entry( regs, IMS332_REG_CURSOR_LUT_1, &m); + /* *we* do not use this, but the prom does */ + ims332_load_colormap_entry( regs, IMS332_REG_CURSOR_LUT_2, &m); +} + +#if 1/*debug*/ +ims332_print_colormap( regs) + ims332_padded_regmap_t *regs; +{ + register int i; + + for (i = 0; i < 256; i++) { + register unsigned int color; + + color = ims332_read_register( regs, IMS332_REG_LUT_BASE + i); + printf("%x->[x%x x%x x%x]\n", i, + (color >> 16) & 0xff, + (color >> 8) & 0xff, + color & 0xff); + } +} +#endif + +/* + * Video on/off + * + * It is unfortunate that X11 goes backward with white@0 + * and black@1. So we must stash away the zero-th entry + * and fix it while screen is off. Also must remember + * it, sigh. + */ +struct vstate { + ims332_padded_regmap_t *regs; + unsigned short off; +}; + +ims332_video_off(vstate, up) + struct vstate *vstate; + user_info_t *up; +{ + register ims332_padded_regmap_t *regs = vstate->regs; + register unsigned *save, csr; + + if (vstate->off) + return; + + /* Yes, this is awful */ + save = (unsigned *)up->dev_dep_2.gx.colormap; + + *save = ims332_read_register(regs, IMS332_REG_LUT_BASE); + + ims332_write_register(regs, IMS332_REG_LUT_BASE, 0); + + ims332_write_register( regs, IMS332_REG_COLOR_MASK, 0); + + /* cursor now */ + csr = ims332_read_register(regs, IMS332_REG_CSR_A); + csr |= IMS332_CSR_A_DISABLE_CURSOR; + ims332_write_register(regs, IMS332_REG_CSR_A, csr); + + vstate->off = 1; +} + +ims332_video_on(vstate, up) + struct vstate *vstate; + user_info_t *up; +{ + register ims332_padded_regmap_t *regs = vstate->regs; + register unsigned *save, csr; + + if (!vstate->off) + return; + + /* Like I said.. */ + save = (unsigned *)up->dev_dep_2.gx.colormap; + + ims332_write_register(regs, IMS332_REG_LUT_BASE, *save); + + ims332_write_register( regs, IMS332_REG_COLOR_MASK, 0xffffffff); + + /* cursor now */ + csr = ims332_read_register(regs, IMS332_REG_CSR_A); + csr &= ~IMS332_CSR_A_DISABLE_CURSOR; + ims332_write_register(regs, IMS332_REG_CSR_A, csr); + + vstate->off = 0; +} + +/* + * Cursor + */ +ims332_pos_cursor(regs,x,y) + ims332_padded_regmap_t *regs; + register int x,y; +{ + ims332_write_register( regs, IMS332_REG_CURSOR_LOC, + ((x & 0xfff) << 12) | (y & 0xfff) ); +} + + +ims332_cursor_color( regs, color) + ims332_padded_regmap_t *regs; + color_map_t *color; +{ + /* Bg is color[0], Fg is color[1] */ + ims332_write_register(regs, IMS332_REG_CURSOR_LUT_0, + (color->blue << 16) | + (color->green << 8) | + (color->red)); + color++; + ims332_write_register(regs, IMS332_REG_CURSOR_LUT_1, + (color->blue << 16) | + (color->green << 8) | + (color->red)); +} + +ims332_cursor_sprite( regs, cursor) + ims332_padded_regmap_t *regs; + unsigned short *cursor; +{ + register int i; + + /* We *could* cut this down a lot... */ + for (i = 0; i < 512; i++, cursor++) + ims332_write_register( regs, + IMS332_REG_CURSOR_RAM+i, *cursor); +} + +/* + * Initialization + */ +ims332_init(regs, reset, mon) + ims332_padded_regmap_t *regs; + unsigned int *reset; + xcfb_monitor_type_t mon; +{ + int shortdisplay, broadpulse, frontporch; + + assert_ims332_reset_bit(reset); + delay(1); /* specs sez 50ns.. */ + deassert_ims332_reset_bit(reset); + + /* CLOCKIN appears to receive a 6.25 Mhz clock --> PLL 12 for 75Mhz monitor */ + ims332_write_register(regs, IMS332_REG_BOOT, 12 | IMS332_BOOT_CLOCK_PLL); + + /* initialize VTG */ + ims332_write_register(regs, IMS332_REG_CSR_A, + IMS332_BPP_8 | IMS332_CSR_A_DISABLE_CURSOR); + delay(50); /* spec does not say */ + + /* datapath registers (values taken from prom's settings) */ + + frontporch = mon->line_time - (mon->half_sync * 2 + + mon->back_porch + + mon->frame_visible_width / 4); + + shortdisplay = mon->line_time / 2 - (mon->half_sync * 2 + + mon->back_porch + frontporch); + broadpulse = mon->line_time / 2 - frontporch; + + ims332_write_register( regs, IMS332_REG_HALF_SYNCH, mon->half_sync); + ims332_write_register( regs, IMS332_REG_BACK_PORCH, mon->back_porch); + ims332_write_register( regs, IMS332_REG_DISPLAY, + mon->frame_visible_width / 4); + ims332_write_register( regs, IMS332_REG_SHORT_DIS, shortdisplay); + ims332_write_register( regs, IMS332_REG_BROAD_PULSE, broadpulse); + ims332_write_register( regs, IMS332_REG_V_SYNC, mon->v_sync * 2); + ims332_write_register( regs, IMS332_REG_V_PRE_EQUALIZE, + mon->v_pre_equalize); + ims332_write_register( regs, IMS332_REG_V_POST_EQUALIZE, + mon->v_post_equalize); + ims332_write_register( regs, IMS332_REG_V_BLANK, mon->v_blank * 2); + ims332_write_register( regs, IMS332_REG_V_DISPLAY, + mon->frame_visible_height * 2); + ims332_write_register( regs, IMS332_REG_LINE_TIME, mon->line_time); + ims332_write_register( regs, IMS332_REG_LINE_START, mon->line_start); + ims332_write_register( regs, IMS332_REG_MEM_INIT, mon->mem_init); + ims332_write_register( regs, IMS332_REG_XFER_DELAY, mon->xfer_delay); + + ims332_write_register( regs, IMS332_REG_COLOR_MASK, 0xffffff); + + ims332_init_colormap( regs ); + + ims332_write_register(regs, IMS332_REG_CSR_A, + IMS332_BPP_8 | IMS332_CSR_A_DMA_DISABLE | IMS332_CSR_A_VTG_ENABLE); + +} |