The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/igsfb_subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: igsfb_subr.c,v 1.15 2018/09/03 16:29:31 riastradh Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2002 Valeriy E. Ushakov
    5  *               2009 Michael Lorenz
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 /*
   32  * Integraphics Systems IGA 168x and CyberPro series.
   33  */
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: igsfb_subr.c,v 1.15 2018/09/03 16:29:31 riastradh Exp $");
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/device.h>
   41 
   42 #include <sys/bus.h>
   43 
   44 #include <dev/wscons/wsdisplayvar.h>
   45 #include <dev/wscons/wsconsio.h>
   46 #include <dev/rasops/rasops.h>
   47 #include <dev/wscons/wsdisplay_vconsvar.h>
   48 
   49 #include <dev/ic/igsfbreg.h>
   50 #include <dev/ic/igsfbvar.h>
   51 
   52 #ifdef IGSFB_DEBUG
   53 #define DPRINTF printf
   54 #else
   55 #define DPRINTF while (0) printf
   56 #endif
   57 
   58 static void     igsfb_init_seq(struct igsfb_devconfig *);
   59 static void     igsfb_init_crtc(struct igsfb_devconfig *);
   60 static void     igsfb_init_grfx(struct igsfb_devconfig *);
   61 static void     igsfb_init_attr(struct igsfb_devconfig *);
   62 static void     igsfb_init_ext(struct igsfb_devconfig *);
   63 static void     igsfb_init_dac(struct igsfb_devconfig *);
   64 
   65 static void     igsfb_freq_latch(struct igsfb_devconfig *);
   66 static void     igsfb_video_on(struct igsfb_devconfig *);
   67 static void     igsfb_calc_pll(int, int *, int *, int *, int, int, int, int);
   68 
   69 
   70 
   71 /*
   72  * Enable chip.
   73  */
   74 int
   75 igsfb_enable(bus_space_tag_t iot, bus_addr_t iobase, int ioflags)
   76 {
   77         bus_space_handle_t vdoh;
   78         bus_space_handle_t vseh;
   79         bus_space_handle_t regh;
   80         int ret;
   81 
   82         ret = bus_space_map(iot, iobase + IGS_VDO, 1, ioflags, &vdoh);
   83         if (ret != 0) {
   84                 printf("unable to map VDO register\n");
   85                 goto out0;
   86         }
   87 
   88         ret = bus_space_map(iot, iobase + IGS_VSE, 1, ioflags, &vseh);
   89         if (ret != 0) {
   90                 printf("unable to map VSE register\n");
   91                 goto out1;
   92         }
   93 
   94         ret = bus_space_map(iot, iobase + IGS_REG_BASE, IGS_REG_SIZE, ioflags,
   95                             &regh);
   96         if (ret != 0) {
   97                 printf("unable to map I/O registers\n");
   98                 goto out2;
   99         }
  100 
  101         /*
  102          * Start decoding i/o space accesses.
  103          */
  104         bus_space_write_1(iot, vdoh, 0, IGS_VDO_ENABLE | IGS_VDO_SETUP);
  105         bus_space_write_1(iot, vseh, 0, IGS_VSE_ENABLE);
  106         bus_space_write_1(iot, vdoh, 0, IGS_VDO_ENABLE);
  107 
  108         /*
  109          * Start decoding memory space accesses (XXX: move out of here?
  110          * we program this register in igsfb_init_ext).
  111          * While here, enable coprocessor and select IGS_COP_BASE_B.
  112          */
  113         igs_ext_write(iot, regh, IGS_EXT_BIU_MISC_CTL,
  114                       (IGS_EXT_BIU_LINEAREN
  115                        | IGS_EXT_BIU_COPREN | IGS_EXT_BIU_COPASELB));
  116 
  117         bus_space_unmap(iot, regh, IGS_REG_SIZE);
  118   out2: bus_space_unmap(iot, vseh, 1);
  119   out1: bus_space_unmap(iot, vdoh, 1);
  120   out0: return ret;
  121 }
  122 
  123 
  124 /*
  125  * Init sequencer.
  126  * This is common for all video modes.
  127  */
  128 static void
  129 igsfb_init_seq(struct igsfb_devconfig *dc)
  130 {
  131         bus_space_tag_t iot = dc->dc_iot;
  132         bus_space_handle_t ioh = dc->dc_ioh;
  133 
  134         /* start messing with sequencer */
  135         igs_seq_write(iot, ioh, IGS_SEQ_RESET, 0);
  136 
  137         igs_seq_write(iot, ioh, 1, 0x01); /* 8 dot clock */
  138         igs_seq_write(iot, ioh, 2, 0x0f); /* enable all maps */
  139         igs_seq_write(iot, ioh, 3, 0x00); /* character generator */
  140         igs_seq_write(iot, ioh, 4, 0x0e); /* memory mode */
  141 
  142         /* this selects color mode among other things */
  143         bus_space_write_1(iot, ioh, IGS_MISC_OUTPUT_W, 0xef);
  144 
  145         /* normal sequencer operation */
  146         igs_seq_write(iot, ioh, IGS_SEQ_RESET,
  147                       IGS_SEQ_RESET_SYNC | IGS_SEQ_RESET_ASYNC);
  148 }
  149 
  150 
  151 /*
  152  * Init CRTC to 640x480 8bpp at 60Hz
  153  */
  154 static void
  155 igsfb_init_crtc(struct igsfb_devconfig *dc)
  156 {
  157         bus_space_tag_t iot = dc->dc_iot;
  158         bus_space_handle_t ioh = dc->dc_ioh;
  159 
  160         igs_crtc_write(iot, ioh, 0x00, 0x5f);
  161         igs_crtc_write(iot, ioh, 0x01, 0x4f);
  162         igs_crtc_write(iot, ioh, 0x02, 0x50);
  163         igs_crtc_write(iot, ioh, 0x03, 0x80);
  164         igs_crtc_write(iot, ioh, 0x04, 0x52);
  165         igs_crtc_write(iot, ioh, 0x05, 0x9d);
  166         igs_crtc_write(iot, ioh, 0x06, 0x0b);
  167         igs_crtc_write(iot, ioh, 0x07, 0x3e);
  168 
  169         /* next block is almost constant, only bit 6 in reg 9 differs */
  170         igs_crtc_write(iot, ioh, 0x08, 0x00);
  171         igs_crtc_write(iot, ioh, 0x09, 0x40); /* <- either 0x40 or 0x60 */
  172         igs_crtc_write(iot, ioh, 0x0a, 0x00);
  173         igs_crtc_write(iot, ioh, 0x0b, 0x00);
  174         igs_crtc_write(iot, ioh, 0x0c, 0x00);
  175         igs_crtc_write(iot, ioh, 0x0d, 0x00);
  176         igs_crtc_write(iot, ioh, 0x0e, 0x00);
  177         igs_crtc_write(iot, ioh, 0x0f, 0x00);
  178 
  179         igs_crtc_write(iot, ioh, 0x10, 0xe9);
  180         igs_crtc_write(iot, ioh, 0x11, 0x8b);
  181         igs_crtc_write(iot, ioh, 0x12, 0xdf);
  182         igs_crtc_write(iot, ioh, 0x13, 0x50);
  183         igs_crtc_write(iot, ioh, 0x14, 0x00);
  184         igs_crtc_write(iot, ioh, 0x15, 0xe6);
  185         igs_crtc_write(iot, ioh, 0x16, 0x04);
  186         igs_crtc_write(iot, ioh, 0x17, 0xc3);
  187 
  188         igs_crtc_write(iot, ioh, 0x18, 0xff);
  189 }
  190 
  191 
  192 /*
  193  * Init graphics controller.
  194  * This is common for all video modes.
  195  */
  196 static void
  197 igsfb_init_grfx(struct igsfb_devconfig *dc)
  198 {
  199         bus_space_tag_t iot = dc->dc_iot;
  200         bus_space_handle_t ioh = dc->dc_ioh;
  201 
  202         igs_grfx_write(iot, ioh, 0, 0x00);
  203         igs_grfx_write(iot, ioh, 1, 0x00);
  204         igs_grfx_write(iot, ioh, 2, 0x00);
  205         igs_grfx_write(iot, ioh, 3, 0x00);
  206         igs_grfx_write(iot, ioh, 4, 0x00);
  207         igs_grfx_write(iot, ioh, 5, 0x60); /* SRMODE, MODE256 */
  208         igs_grfx_write(iot, ioh, 6, 0x05); /* 64k @ a0000, GRAPHICS */
  209         igs_grfx_write(iot, ioh, 7, 0x0f); /* color compare all */
  210         igs_grfx_write(iot, ioh, 8, 0xff); /* bitmask = all bits mutable */
  211 }
  212 
  213 
  214 /*
  215  * Init attribute controller.
  216  * This is common for all video modes.
  217  */
  218 static void
  219 igsfb_init_attr(struct igsfb_devconfig *dc)
  220 {
  221         bus_space_tag_t iot = dc->dc_iot;
  222         bus_space_handle_t ioh = dc->dc_ioh;
  223         int i;
  224 
  225         igs_attr_flip_flop(iot, ioh);   /* reset attr flip-flop to address */
  226 
  227         for (i = 0; i < 16; ++i)        /* crt palette */
  228                 igs_attr_write(iot, ioh, i, i);
  229 
  230         igs_attr_write(iot, ioh, 0x10, 0x01); /* select graphic mode */
  231         igs_attr_write(iot, ioh, 0x11, 0x00); /* crt overscan color */
  232         igs_attr_write(iot, ioh, 0x12, 0x0f); /* color plane enable */
  233         igs_attr_write(iot, ioh, 0x13, 0x00);
  234         igs_attr_write(iot, ioh, 0x14, 0x00);
  235 }
  236 
  237 
  238 /*
  239  * When done with ATTR controller, call this to unblank the screen.
  240  */
  241 static void
  242 igsfb_video_on(struct igsfb_devconfig *dc)
  243 {
  244         bus_space_tag_t iot = dc->dc_iot;
  245         bus_space_handle_t ioh = dc->dc_ioh;
  246 
  247         igs_attr_flip_flop(iot, ioh);
  248         bus_space_write_1(iot, ioh, IGS_ATTR_IDX, 0x20);
  249         bus_space_write_1(iot, ioh, IGS_ATTR_IDX, 0x20);
  250 }
  251 
  252 
  253 /*
  254  * Latch VCLK (b0/b1) and MCLK (b2/b3) values.
  255  */
  256 static void
  257 igsfb_freq_latch(struct igsfb_devconfig *dc)
  258 {
  259         bus_space_tag_t iot = dc->dc_iot;
  260         bus_space_handle_t ioh = dc->dc_ioh;
  261 
  262         bus_space_write_1(iot, ioh, IGS_EXT_IDX, 0xb9);
  263         bus_space_write_1(iot, ioh, IGS_EXT_PORT, 0x80);
  264         bus_space_write_1(iot, ioh, IGS_EXT_PORT, 0x00);
  265 }
  266 
  267 
  268 static void
  269 igsfb_init_ext(struct igsfb_devconfig *dc)
  270 {
  271         bus_space_tag_t iot = dc->dc_iot;
  272         bus_space_handle_t ioh = dc->dc_ioh;
  273         int is_cyberpro = (dc->dc_id >= 0x2000);
  274 
  275         igs_ext_write(iot, ioh, 0x10, 0x10); /* IGS_EXT_START_ADDR enable */
  276         igs_ext_write(iot, ioh, 0x12, 0x00); /* IGS_EXT_IRQ_CTL disable  */
  277         igs_ext_write(iot, ioh, 0x13, 0x00); /* MBZ for normal operation */
  278 
  279         igs_ext_write(iot, ioh, 0x31, 0x00); /* segment write ptr */
  280         igs_ext_write(iot, ioh, 0x32, 0x00); /* segment read ptr */
  281 
  282         /* IGS_EXT_BIU_MISC_CTL: linearen, copren, copaselb, segon */
  283         igs_ext_write(iot, ioh, 0x33, 0x1d);
  284 
  285         /* sprite location */
  286         igs_ext_write(iot, ioh, 0x50, 0x00);
  287         igs_ext_write(iot, ioh, 0x51, 0x00);
  288         igs_ext_write(iot, ioh, 0x52, 0x00);
  289         igs_ext_write(iot, ioh, 0x53, 0x00);
  290         igs_ext_write(iot, ioh, 0x54, 0x00);
  291         igs_ext_write(iot, ioh, 0x55, 0x00);
  292         igs_ext_write(iot, ioh, 0x56, 0x00); /* sprite control */
  293 
  294         /* IGS_EXT_GRFX_MODE */
  295         igs_ext_write(iot, ioh, 0x57, 0x01); /* raster fb */
  296 
  297         /* overscan R/G/B */
  298         igs_ext_write(iot, ioh, 0x58, 0x00);
  299         igs_ext_write(iot, ioh, 0x59, 0x00);
  300         igs_ext_write(iot, ioh, 0x5A, 0x00);
  301 
  302         /*
  303          * Video memory size &c.  We rely on firmware to program
  304          * BUS_CTL(30), MEM_CTL1(71), MEM_CTL2(72) appropriately.
  305          */
  306 
  307         /* ext memory ctl0 */
  308         igs_ext_write(iot, ioh, 0x70, 0x0B); /* enable fifo, seq */
  309 
  310         /* ext hidden ctl1 */
  311         igs_ext_write(iot, ioh, 0x73, 0x30); /* XXX: krups: 0x20 */
  312 
  313         /* ext fifo control */
  314         igs_ext_write(iot, ioh, 0x74, 0x10); /* XXX: krups: 0x1b */
  315         igs_ext_write(iot, ioh, 0x75, 0x10); /* XXX: krups: 0x1e */
  316 
  317         igs_ext_write(iot, ioh, 0x76, 0x00); /* ext seq. */
  318         igs_ext_write(iot, ioh, 0x7A, 0xC8); /* ext. hidden ctl */
  319 
  320         /* ext graphics ctl: GCEXTPATH.  krups 1, nettrom 1, docs 3 */
  321         igs_ext_write(iot, ioh, 0x90, 0x01);
  322 
  323         if (is_cyberpro)        /* select normal vclk/mclk registers */
  324             igs_ext_write(iot, ioh, 0xBF, 0x00);
  325 
  326         igs_ext_write(iot, ioh, 0xB0, 0xD2); /* VCLK = 25.175MHz */
  327         igs_ext_write(iot, ioh, 0xB1, 0xD3);
  328         igs_ext_write(iot, ioh, 0xB2, 0xDB); /* MCLK = 75MHz*/
  329         igs_ext_write(iot, ioh, 0xB3, 0x54);
  330         igsfb_freq_latch(dc);
  331 
  332         if (is_cyberpro)
  333             igs_ext_write(iot, ioh, 0xF8, 0x04); /* XXX: ??? */
  334 
  335         /* 640x480 8bpp at 60Hz */
  336         igs_ext_write(iot, ioh, 0x11, 0x00);
  337         igs_ext_write(iot, ioh, 0x77, 0x01); /* 8bpp, indexed */
  338         igs_ext_write(iot, ioh, 0x14, 0x51);
  339         igs_ext_write(iot, ioh, 0x15, 0x00);
  340 }
  341 
  342 
  343 static void
  344 igsfb_init_dac(struct igsfb_devconfig *dc)
  345 {
  346         bus_space_tag_t iot = dc->dc_iot;
  347         bus_space_handle_t ioh = dc->dc_ioh;
  348         uint8_t reg;
  349 
  350         /* RAMDAC address 2 select */
  351         reg = igs_ext_read(iot, ioh, IGS_EXT_SPRITE_CTL);
  352         igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL,
  353                       reg | IGS_EXT_SPRITE_DAC_PEL);
  354 
  355         /* VREFEN, DAC8 */
  356         bus_space_write_1(iot, ioh, IGS_DAC_CMD, 0x06);
  357 
  358         /* restore */
  359         igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, reg);
  360 
  361         bus_space_write_1(iot, ioh, IGS_PEL_MASK, 0xff);
  362 }
  363 
  364 
  365 void
  366 igsfb_1024x768_8bpp_60Hz(struct igsfb_devconfig *dc)
  367 {
  368         bus_space_tag_t iot = dc->dc_iot;
  369         bus_space_handle_t ioh = dc->dc_ioh;
  370 
  371         igs_crtc_write(iot, ioh, 0x11, 0x00); /* write enable CRTC 0..7 */
  372 
  373         igs_crtc_write(iot, ioh, 0x00, 0xa3);
  374         igs_crtc_write(iot, ioh, 0x01, 0x7f);
  375         igs_crtc_write(iot, ioh, 0x02, 0x7f); /* krups: 80 */
  376         igs_crtc_write(iot, ioh, 0x03, 0x85); /* krups: 84 */
  377         igs_crtc_write(iot, ioh, 0x04, 0x84); /* krups: 88 */
  378         igs_crtc_write(iot, ioh, 0x05, 0x95); /* krups: 99 */
  379         igs_crtc_write(iot, ioh, 0x06, 0x24);
  380         igs_crtc_write(iot, ioh, 0x07, 0xfd);
  381 
  382         /* next block is almost constant, only bit 6 in reg 9 differs */
  383         igs_crtc_write(iot, ioh, 0x08, 0x00);
  384         igs_crtc_write(iot, ioh, 0x09, 0x60); /* <- either 0x40 or 0x60 */
  385         igs_crtc_write(iot, ioh, 0x0a, 0x00);
  386         igs_crtc_write(iot, ioh, 0x0b, 0x00);
  387         igs_crtc_write(iot, ioh, 0x0c, 0x00);
  388         igs_crtc_write(iot, ioh, 0x0d, 0x00);
  389         igs_crtc_write(iot, ioh, 0x0e, 0x00);
  390         igs_crtc_write(iot, ioh, 0x0f, 0x00);
  391 
  392         igs_crtc_write(iot, ioh, 0x10, 0x06);
  393         igs_crtc_write(iot, ioh, 0x11, 0x8c);
  394         igs_crtc_write(iot, ioh, 0x12, 0xff);
  395         igs_crtc_write(iot, ioh, 0x13, 0x80); /* depends on BPP */
  396         igs_crtc_write(iot, ioh, 0x14, 0x0f);
  397         igs_crtc_write(iot, ioh, 0x15, 0x02);
  398         igs_crtc_write(iot, ioh, 0x16, 0x21);
  399         igs_crtc_write(iot, ioh, 0x17, 0xe3);
  400         igs_crtc_write(iot, ioh, 0x18, 0xff);
  401 
  402         igs_ext_write(iot, ioh, 0xB0, 0xE2); /* VCLK */
  403         igs_ext_write(iot, ioh, 0xB1, 0x58);
  404 #if 1
  405         /* XXX: hmm, krups does this */
  406         igs_ext_write(iot, ioh, 0xB2, 0xE2); /* MCLK */
  407         igs_ext_write(iot, ioh, 0xB3, 0x58);
  408 #endif
  409         igsfb_freq_latch(dc);
  410 
  411         igs_ext_write(iot, ioh, 0x11, 0x00);
  412         igs_ext_write(iot, ioh, 0x77, 0x01); /* 8bpp, indexed */
  413         igs_ext_write(iot, ioh, 0x14, 0x81);
  414         igs_ext_write(iot, ioh, 0x15, 0x00);
  415 
  416         dc->dc_width = 1024;
  417         dc->dc_height = 768;
  418         dc->dc_depth = 8;
  419         dc->dc_stride = dc->dc_width;
  420 }
  421 
  422 
  423 /*
  424  * igs-video-init from krups prom
  425  */
  426 void
  427 igsfb_hw_setup(struct igsfb_devconfig *dc)
  428 {
  429         const struct videomode *mode = NULL;
  430         int i, size, d;
  431 
  432         igsfb_init_seq(dc);
  433         igsfb_init_crtc(dc);
  434         igsfb_init_attr(dc);
  435         igsfb_init_grfx(dc);
  436         igsfb_init_ext(dc);
  437         igsfb_init_dac(dc);
  438 
  439         for (i = 0; i < videomode_count; i++) {
  440                 if (strcmp(dc->dc_modestring, videomode_list[i].name) == 0)
  441                         break;
  442         }
  443 
  444         if (i < videomode_count) {
  445                 size = videomode_list[i].hdisplay * videomode_list[i].vdisplay;
  446                 /* found a mode, now let's see if we can display it */
  447                 if ((videomode_list[i].dot_clock <= IGS_MAX_CLOCK) &&
  448                     (videomode_list[i].hdisplay <= 2048) &&
  449                     (videomode_list[i].hdisplay >= 320) &&
  450                     (videomode_list[i].vdisplay <= 2048) &&
  451                     (videomode_list[i].vdisplay >= 200) &&
  452                     (size <= (dc->dc_memsz - 0x1000))) {
  453                         mode = &videomode_list[i];
  454                         /*
  455                          * now let's see which maximum depth we can support
  456                          * in that mode
  457                          */
  458                         d = (dc->dc_vmemsz - 0x1000) / size;
  459                         if (d >= 4) {
  460                                 dc->dc_maxdepth = 32;
  461                         } else if (d >= 2) {
  462                                 dc->dc_maxdepth = 16;
  463                         } else
  464                                 dc->dc_maxdepth = 8;
  465                 }
  466         }
  467         dc->dc_mode = mode;
  468 
  469         if (mode != NULL) {
  470                 igsfb_set_mode(dc, mode, 8);
  471         } else {
  472                 igsfb_1024x768_8bpp_60Hz(dc);
  473                 dc->dc_maxdepth = 8;
  474         }
  475 
  476         igsfb_video_on(dc);
  477 }
  478 
  479 void
  480 igsfb_set_mode(struct igsfb_devconfig *dc, const struct videomode *mode,
  481     int depth)
  482 {
  483         bus_space_tag_t iot = dc->dc_iot;
  484         bus_space_handle_t ioh = dc->dc_ioh;
  485         int i, m, n, p, hoffset, bytes_per_pixel, memfetch;
  486         int vsync_start, hsync_start, vsync_end, hsync_end;
  487         int vblank_start, vblank_end, hblank_start, hblank_end;
  488         int croffset;
  489         uint8_t vclk1, vclk2, vclk3, overflow, reg, seq_mode;
  490 
  491         switch (depth) {
  492                 case 8:
  493                         seq_mode = IGS_EXT_SEQ_8BPP;
  494                         break;
  495                 case 15:
  496                         seq_mode = IGS_EXT_SEQ_15BPP; /* 5-5-5 */
  497                         break;
  498                 case 16:
  499                         seq_mode = IGS_EXT_SEQ_16BPP; /* 5-6-5 */
  500                         break;
  501                 case 24:
  502                         seq_mode = IGS_EXT_SEQ_24BPP; /* 8-8-8 */
  503                         break;
  504                 case 32:
  505                         seq_mode = IGS_EXT_SEQ_32BPP;
  506                         break;
  507                 default:
  508                         aprint_error("igsfb: unsupported depth (%d), reverting"
  509                                      " to 8 bit\n", depth);
  510                         depth = 8;
  511                         seq_mode = IGS_EXT_SEQ_8BPP;
  512         }
  513         bytes_per_pixel = howmany(depth, NBBY);
  514 
  515         hoffset = (mode->hdisplay >> 3) * bytes_per_pixel;
  516         memfetch = hoffset + 1;
  517         overflow = (((mode->vtotal - 2) & 0x400) >> 10) | 
  518             (((mode->vdisplay -1) & 0x400) >> 9) |
  519             ((mode->vsync_start & 0x400) >> 8) |
  520             ((mode->vsync_start & 0x400) >> 7) |
  521             0x10; 
  522 
  523         /* RAMDAC address 2 select */
  524         reg = igs_ext_read(iot, ioh, IGS_EXT_SPRITE_CTL);
  525         igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL,
  526                       reg | IGS_EXT_SPRITE_DAC_PEL);
  527 
  528         if (depth == 8) {
  529                 /* palette mode */
  530                 bus_space_write_1(dc->dc_iot, dc->dc_ioh, IGS_DAC_CMD, 0x06);
  531         } else {
  532                 /* bypass palette */
  533                 bus_space_write_1(dc->dc_iot, dc->dc_ioh, IGS_DAC_CMD, 0x16);
  534         }
  535         /* restore */
  536         igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, reg);
  537 
  538         bus_space_write_1(iot, ioh, IGS_PEL_MASK, 0xff);
  539 
  540         igs_crtc_write(iot, ioh, 0x11, 0x00); /* write enable CRTC 0..7 */
  541 
  542         hsync_start = mode->hsync_start;
  543         hsync_end = mode->hsync_end;
  544 
  545         hblank_start = uimin(mode->hsync_start, mode->hdisplay);
  546         hblank_end = hsync_end;
  547         if ((hblank_end - hblank_start) >= 63 * 8) {
  548 
  549                 /*
  550                  * H Blanking size must be < 63*8. Same remark as above.
  551                  */
  552                 hblank_start = hblank_end - 63 * 8;
  553         }
  554 
  555         vblank_start = uimin(mode->vsync_start, mode->vdisplay);
  556         vblank_end = mode->vsync_end;
  557 
  558         vsync_start = mode->vsync_start;
  559         vsync_end = mode->vsync_end;
  560         igs_crtc_write(iot, ioh, 0x00, (mode->htotal >> 3) - 5);
  561         igs_crtc_write(iot, ioh, 0x01, (mode->hdisplay >> 3) - 1);
  562         igs_crtc_write(iot, ioh, 0x02, (hblank_start >> 3) - 1);
  563         igs_crtc_write(iot, ioh, 0x03, 0x80 | (((hblank_end >> 3) - 1) & 0x1f));
  564         igs_crtc_write(iot, ioh, 0x04, hsync_start >> 3);
  565         igs_crtc_write(iot, ioh, 0x05, ((((hblank_end >> 3) - 1)  & 0x20) << 2) 
  566             | ((hsync_end >> 3) & 0x1f));
  567         igs_crtc_write(iot, ioh, 0x06, (mode->vtotal - 2) & 0xff);
  568         igs_crtc_write(iot, ioh, 0x07, 
  569             ((vsync_start & 0x200) >> 2) |
  570             (((mode->vdisplay - 1) & 0x200) >> 3) |
  571             (((mode->vtotal - 2) & 0x200) >> 4) |
  572             0x10 |
  573             (((vblank_start - 1) & 0x100) >> 5) |
  574             ((vsync_start  & 0x100) >> 6) |
  575             (((mode->vdisplay - 1)  & 0x100) >> 7) |
  576             ((mode->vtotal  & 0x100) >> 8));
  577 
  578         igs_crtc_write(iot, ioh, 0x08, 0x00);
  579         igs_crtc_write(iot, ioh, 0x09, 0x40 | 
  580             (((vblank_start - 1) & 0x200) >> 4));
  581         igs_crtc_write(iot, ioh, 0x0a, 0x00);
  582         igs_crtc_write(iot, ioh, 0x0b, 0x00);
  583         igs_crtc_write(iot, ioh, 0x0c, 0x00);
  584         igs_crtc_write(iot, ioh, 0x0d, 0x00);
  585         igs_crtc_write(iot, ioh, 0x0e, 0x00);
  586         igs_crtc_write(iot, ioh, 0x0f, 0x00);
  587 
  588         igs_crtc_write(iot, ioh, 0x10, vsync_start & 0xff);
  589         igs_crtc_write(iot, ioh, 0x11, (vsync_end & 0x0f) | 0x20);
  590         igs_crtc_write(iot, ioh, 0x12, (mode->vdisplay - 1) & 0xff);
  591         igs_crtc_write(iot, ioh, 0x13, hoffset & 0xff);
  592         igs_crtc_write(iot, ioh, 0x14, 0x0f);
  593         igs_crtc_write(iot, ioh, 0x15, (vblank_start - 1) & 0xff);
  594         igs_crtc_write(iot, ioh, 0x16, (vblank_end - 1) & 0xff);
  595         igs_crtc_write(iot, ioh, 0x17, 0xe3);
  596         igs_crtc_write(iot, ioh, 0x18, 0xff);
  597 
  598         for (i = 0; i < 0x10; i++)      
  599                 igs_attr_write(iot, ioh, i, i);
  600         
  601         igs_attr_write(iot, ioh, 0x10, 0x01);
  602         igs_attr_write(iot, ioh, 0x11, 0x00);
  603         igs_attr_write(iot, ioh, 0x12, 0x0f);
  604         igs_attr_write(iot, ioh, 0x13, 0x00);
  605 
  606         igs_grfx_write(iot, ioh, 0x00, 0x00);
  607         igs_grfx_write(iot, ioh, 0x01, 0x00);
  608         igs_grfx_write(iot, ioh, 0x02, 0x00);
  609         igs_grfx_write(iot, ioh, 0x03, 0x00);
  610         igs_grfx_write(iot, ioh, 0x04, 0x00);
  611         igs_grfx_write(iot, ioh, 0x05, 0x60);
  612         igs_grfx_write(iot, ioh, 0x06, 0x05);
  613         igs_grfx_write(iot, ioh, 0x07, 0x0f);
  614         igs_grfx_write(iot, ioh, 0x08, 0xff);
  615 
  616         /* crank up memory clock to 95MHz - needed for higher resolutions */
  617         igs_ext_write(iot, ioh, IGS_EXT_MCLK0, 0x91);
  618         igs_ext_write(iot, ioh, IGS_EXT_MCLK1, 0x6a);
  619         igsfb_freq_latch(dc);
  620 
  621         igs_ext_write(iot, ioh, IGS_EXT_VOVFL, overflow);
  622         igs_ext_write(iot, ioh, IGS_EXT_SEQ_MISC, seq_mode);
  623         igs_ext_write(iot, ioh, 0x14, memfetch & 0xff);
  624         igs_ext_write(iot, ioh, 0x15,
  625             ((memfetch & 0x300) >> 8) | ((hoffset & 0x300) >> 4));
  626 
  627         /* finally set the dot clock */
  628         igsfb_calc_pll(mode->dot_clock, &m, &n, &p, 2047, 255, 7, IGS_MIN_VCO);
  629         DPRINTF("m: %x, n: %x, p: %x\n", m, n, p);
  630         vclk1 = m & 0xff;
  631         vclk2 = (n & 0x1f) | ((p << 6) & 0xc0) |
  632             (mode->dot_clock > 180000 ? 0x20 : 0);
  633         vclk3 = ((m >> 8) & 0x7) | ((n >> 2) & 0x38) | ((p << 4) & 0x40);
  634         DPRINTF("clk: %02x %02x %02x\n", vclk1, vclk2, vclk3);
  635         igs_ext_write(iot, ioh, IGS_EXT_VCLK0, vclk1);
  636         igs_ext_write(iot, ioh, IGS_EXT_VCLK1, vclk2);
  637         igs_ext_write(iot, ioh, 0xBA, vclk3);
  638         igsfb_freq_latch(dc);
  639         DPRINTF("clock: %d\n", IGS_CLOCK(m, n, p));
  640 
  641         if (dc->dc_id > 0x2000) {
  642                 /* we have a blitter, so configure it as well */
  643                 bus_space_write_1(dc->dc_iot, dc->dc_coph, IGS_COP_MAP_FMT_REG,
  644                     bytes_per_pixel - 1);
  645                 bus_space_write_2(dc->dc_iot, dc->dc_coph,
  646                     IGS_COP_SRC_MAP_WIDTH_REG, dc->dc_width - 1);
  647                 bus_space_write_2(dc->dc_iot, dc->dc_coph,
  648                     IGS_COP_DST_MAP_WIDTH_REG, dc->dc_width - 1);
  649         }
  650 
  651         /* re-init the cursor data address too */
  652         croffset = dc->dc_vmemsz - IGS_CURSOR_DATA_SIZE;
  653         croffset >>= 10;        /* bytes -> kilobytes */
  654         igs_ext_write(dc->dc_iot, dc->dc_ioh,
  655                       IGS_EXT_SPRITE_DATA_LO, croffset & 0xff);
  656         igs_ext_write(dc->dc_iot, dc->dc_ioh,
  657                       IGS_EXT_SPRITE_DATA_HI, (croffset >> 8) & 0xf);
  658 
  659         dc->dc_width = mode->hdisplay;
  660         dc->dc_height = mode->vdisplay;
  661         dc->dc_depth = depth;
  662         dc->dc_stride = dc->dc_width * howmany(depth, NBBY);
  663 
  664         igsfb_video_on(dc);
  665 }
  666 
  667 
  668 static void
  669 igsfb_calc_pll(int target, int *Mp, int *Np, int *Pp, int maxM, int maxN,
  670     int maxP, int minVco)
  671 {
  672     int     M, N, P, bestM = 0, bestN = 0;
  673     int     f_vco, f_out;
  674     int     err, besterr;
  675 
  676     /*
  677      * Compute correct P value to keep VCO in range
  678      */
  679     for (P = 0; P <= maxP; P++)
  680     {
  681         f_vco = target * IGS_SCALE(P);
  682         if (f_vco >= minVco)
  683             break;
  684     }
  685 
  686     /* M = f_out / f_ref * ((N + 1) * IGS_SCALE(P)); */
  687     besterr = target;
  688     for (N = 1; N <= maxN; N++)
  689     {
  690         M = ((target * (N + 1) * IGS_SCALE(P) + (IGS_CLOCK_REF/2)) + 
  691             IGS_CLOCK_REF/2) / IGS_CLOCK_REF - 1;
  692         if (0 <= M && M <= maxM)
  693         {
  694             f_out = IGS_CLOCK(M,N,P);
  695             err = target - f_out;
  696             if (err < 0)
  697                 err = -err;
  698             if (err < besterr)
  699             {
  700                 besterr = err;
  701                 bestM = M;
  702                 bestN = N;
  703             }
  704         }
  705     }
  706     *Mp = bestM;
  707     *Np = bestN;
  708     *Pp = P;
  709 }

Cache object: c6b317037dd15a496d4e09b6b414d725


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.