gonzui


Format: Advanced Search

tkernel_2/driver/tef_em1d/screen/src/em1d512.cbare sourcepermlink (0.05 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Modified by T-Engine Forum at 2014/09/10.
   11:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   12:  *
   13:  *----------------------------------------------------------------------
   14:  */
   15: 
   16: /*
   17:         em1d512.c       screen driver
   18:         video board / chip dependent processing: EM1-D512 LCD controller
   19:  *
   20:  */
   21: #include "screen.h"
   22: #include <sys/segment.h>
   23: #include <device/videomode.h>
   24: #include <device/em1d512_iic.h>
   25: 
   26: #define ASMUBase        0xc0110000
   27: #define PLL2CTRL0       (_UW *)(ASMUBase + 0x008c)
   28: #define PLL2CTRL1       (_UW *)(ASMUBase + 0x0090)
   29: #define DIVLCDLCLK      (_UW *)(ASMUBase + 0x0130)
   30: #define PLL_STATUS      (_UW *)(ASMUBase + 0x0520)
   31: 
   32: #define LCDBase         0x40270000
   33: #define CONTROL         (_UW *)(LCDBase + 0x0000)
   34: #define QOS             (_UW *)(LCDBase + 0x0004)
   35: #define DATAREQ         (_UW *)(LCDBase + 0x0008)
   36: #define LCDOUT          (_UW *)(LCDBase + 0x0010)
   37: #define BUSSEL          (_UW *)(LCDBase + 0x0014)
   38: #define STATUS          (_UW *)(LCDBase + 0x0018)
   39: #define BACKCOLOR       (_UW *)(LCDBase + 0x001c)
   40: #define AREAADR         (_UW *)(LCDBase + 0x0020)
   41: #define HOFFSET         (_UW *)(LCDBase + 0x0024)
   42: #define IFORMAT         (_UW *)(LCDBase + 0x0028)
   43: #define RESIZE          (_UW *)(LCDBase + 0x002c)
   44: #define HTOTAL          (_UW *)(LCDBase + 0x0030)
   45: #define HAREA           (_UW *)(LCDBase + 0x0034)
   46: #define HEDGE1          (_UW *)(LCDBase + 0x0038)
   47: #define HEDGE2          (_UW *)(LCDBase + 0x003c)
   48: #define VTOTAL          (_UW *)(LCDBase + 0x0040)
   49: #define VAREA           (_UW *)(LCDBase + 0x0044)
   50: #define VEDGE1          (_UW *)(LCDBase + 0x0048)
   51: #define VEDGE2          (_UW *)(LCDBase + 0x004c)
   52: #define INTSTATUS       (_UW *)(LCDBase + 0x0060)
   53: #define INTRAWSTATUS    (_UW *)(LCDBase + 0x0064)
   54: #define INTENSET        (_UW *)(LCDBase + 0x0068)
   55: #define INTENCLR        (_UW *)(LCDBase + 0x006c)
   56: #define INTFFCLR        (_UW *)(LCDBase + 0x0070)
   57: #define FRAMECNT        (_UW *)(LCDBase + 0x0074)
   58: 
   59: #define GIOBase(x)      (0xc0050000 + 0x00000040 * (x))
   60: #define GIO_L           0x00
   61: #define GIO_H           0x01
   62: #define GIO_HH          0x02
   63: #define GIO_HHH         0x08
   64: #define GIO_OL(x)       (_UW *)(GIOBase(x) + 0x0008)
   65: #define GIO_OH(x)       (_UW *)(GIOBase(x) + 0x000c)
   66: 
   67: /* definition of LCD panel (including controller-dependent part) */
   68: typedef struct {
   69:         W      paneltype;   // panel type (if negative, this applies to all the panels)
   70:         UW     pll2ctrl0;  // to configure PLL2 clock frequency
   71:         UW     divlcdlclk; // LCD_LCLK division
   72: 
   73:         UH     hde;
   74:         UH     hrs;
   75:         UH     hre;
   76:         UH     htot;
   77:         UH     vde;
   78:         UH     vrs;
   79:         UH     vre;
   80:         UH     vtot;
   81:         B      hsync;
   82:         B      vsync;
   83: } LCDdefs;
   84: 
   85: 
   86: #define SUPPORT_MODEMAP 00020000000     // supported mode map
   87: #define DEFAULT_REQMODE DMeWVGAx16
   88: 
   89: /* LCD parameter */
   90: LOCAL   const LCDdefs     LCDparm[] = {
   91:         {
   92:                 // 800x480@@60Hz, 31.5kHz hsync (pixclk=33.3MHz)
   93:                 -1, 0x61, 0x51,               // 401.408MHz / 12
   94:                 800,  840,  968, 1056,   480,  491,  493,  525,  -1, -1
   95:         },
   96: };
   97: 
   98: /* send command to DA9052 */
   99: LOCAL   W WriteDA9052(W reg, W dat)
  100: {
  101: #define RETRY   4
  102: 
  103:         W      er, i;
  104:         UB     cmd[2];
  105: 
  106:         for (i = RETRY; i > 0; i--) {
  107:                 cmd[0] = reg << 1;
  108:                 cmd[1] = dat;
  109:                 er = em1d512_spixfer(0, cmd, cmd, sizeof(cmd));
  110:                 if (er >= E_OK) break;
  111:         }
  112: 
  113:         return er;
  114: }
  115: 
  116: /* power control of LCD panel */
  117: LOCAL   void      LCDpower(BOOL power)
  118: {
  119:         LOCAL  const UB on_cmd[] = {
  120:                 54, 0x5a,     // VLDO5: 2.5V/enable       *max 3.3V*
  121:                 70, 0x27,     // BOOST(2MHz, LED1/2 enable, controller enable)
  122:                 71, 0x4f,     // LED_CONT(LED1/2 current sink/ramp enable)
  123:                 73, 0xe1,     // LED1_CONF(12034microA)
  124:                 74, 0xe1,     // LED2_CONF(12034microA)   
  125:                 76, 0xbf,     // LED1_CONT(PWM/100%)
  126:                 77, 0xbf,     // LED2_CONT(PWM/100%)
  127:                  0, 0x00,     // (terminate)
  128:         };
  129:         LOCAL  const UB off_cmd[] = {
  130:                 77, 0x00,     // LED2_CONT(default, off)
  131:                 76, 0x00,     // LED1_CONT(default, off)
  132:                 74, 0x00,     // LED2_CONF(default, 50microA)
  133:                 73, 0x00,     // LED1_CONF(default, 50microA)
  134:                 71, 0x40,     // LED_CONT(default)
  135:                 70, 0x20,     // BOOST(default)
  136:                 54, 0x1a,     // VLDO5: 2.5V/disable
  137:                  0, 0x00,     // (terminate)
  138:         };
  139:         const UB       *cmd;
  140: 
  141:         if (!power) {
  142:                 *GIO_OH(GIO_HH) = 0x00040000; // DISP='0'
  143:                 tk_dly_tsk(10);
  144:         }
  145: 
  146:         cmd = power ? on_cmd : off_cmd;
  147:         while (*cmd) {
  148:                 WriteDA9052(*cmd, *(cmd + 1));
  149:                 cmd += 2;
  150:         }
  151:         tk_dly_tsk(10);
  152: 
  153:         if (power) {
  154:                 *GIO_OH(GIO_HH) = 0x00040004; // DISP='1'
  155:                 tk_dly_tsk(10);
  156:         }
  157: 
  158:         return;
  159: }
  160: 
  161: /* set color map (not supported) */
  162: LOCAL   void      em1_setcmap(COLOR *cmap, W index, W entries)
  163: {
  164:         /* no support, do nothing */
  165:         return;
  166: }
  167: 
  168: /* search LCD parameter */
  169: LOCAL   const LCDdefs     *find_lcdpar(void)
  170: {
  171:         W      i;
  172:         const LCDdefs  *lcd;
  173: 
  174:         for (i = 0; i < sizeof(LCDparm) / sizeof(LCDdefs); i++) {
  175:                 lcd = &LCDparm[i];
  176: 
  177:                 /* paneltype mismatch */
  178:                 if (lcd->paneltype >= 0 &&
  179:                     lcd->paneltype != Vinf.paneltype) continue;
  180: 
  181:                 /* resolution mismatch */
  182:                 if (lcd->hde != VideoHsize(Vinf.reqmode) ||
  183:                     lcd->vde != VideoVsize(Vinf.reqmode)) continue;
  184: 
  185:                 /* return parameters */
  186:                 return lcd;
  187:         }
  188: 
  189:         /* not found */
  190:         return NULL;
  191: }
  192: 
  193: /* set up PLL */
  194: LOCAL   void      pll_setup(UW pll2ctrl0, UW divlcdlclk)
  195: {
  196:         UW     imask;
  197:         W      i;
  198: 
  199:         DI(imask);
  200: 
  201:         /* halt PLL2 */
  202:         *PLL2CTRL1 = 0xff;
  203:         for (i = 0; i < 1000000 &&  (*PLL_STATUS & 0x0100); i++) WaitUsec(1);
  204: 
  205:         /* set up PLL2 clock frequency and LCD_LCLK divisor */
  206:         *PLL2CTRL0 = pll2ctrl0;
  207:         *DIVLCDLCLK = divlcdlclk;
  208: 
  209:         /* start PLL2 */
  210:         *PLL2CTRL1 = 0;
  211:         for (i = 0; i < 1000000 && !(*PLL_STATUS & 0x0100); i++) WaitUsec(1);
  212: 
  213:         EI(imask);
  214:         return;
  215: }
  216: 
  217: /* set display mode */
  218: LOCAL   void      em1_setmode(W flg)
  219: {
  220:         const LCDdefs  *lcd;
  221: 
  222:         /* search LCD parameter (if not found, do nothing) */
  223:         lcd = find_lcdpar();
  224:         if (lcd == NULL) goto fin0;
  225: 
  226:         /* display off */
  227:         *LCDOUT = 0;
  228:         LCDpower(FALSE);
  229: 
  230:         /* termination processing (if blanking only is desired) */
  231:         if (flg < 0) goto fin0;
  232: 
  233:         /* set up PLL */
  234:         pll_setup(lcd->pll2ctrl0, lcd->divlcdlclk);
  235: 
  236:         /* set up parameters */
  237:         *BUSSEL = 1;           // MEMC-LCDC mode
  238:         *QOS = 0;
  239:         *CONTROL= ((lcd->hsync < 0) ? 4 : 0) |
  240:                 ((lcd->vsync < 0) ? 2 : 0);
  241:         *BACKCOLOR = 0;                // background is black (#000000)
  242:         *AREAADR = (UW)Vinf.framebuf_addr;
  243:         *HOFFSET = Vinf.framebuf_rowb;
  244:         *IFORMAT = 1;          // RGB565
  245:         *HAREA = lcd->hde;
  246:         *HEDGE1 = lcd->hrs - lcd->hde;
  247:         *HEDGE2 = lcd->hre - lcd->hde;
  248:         *HTOTAL = lcd->htot;
  249:         *VAREA = lcd->vde;
  250:         *VEDGE1 = lcd->vrs - lcd->vde;
  251:         *VEDGE2 = lcd->vre - lcd->vde;
  252:         *VTOTAL = lcd->vtot;
  253:         *INTENCLR = ~0;                // all interrupts are disabled
  254: 
  255:         /* clear VRAM content */
  256:         if (flg) MEMSET(Vinf.f_addr, 0, Vinf.framebuf_total);
  257: 
  258:         /* display on */
  259:         LCDpower(TRUE);
  260:         *LCDOUT = 1;
  261: 
  262: fin0:
  263:         return;
  264: }
  265: 
  266: /* suspend / resume processing */
  267: LOCAL   void      em1_suspend(BOOL suspend)
  268: {
  269:         /* in the case of suspend, clear Video-RAM content */
  270:         if (suspend) MEMSET(Vinf.f_addr, 0, Vinf.framebuf_total);
  271: 
  272:         /* screen display on/off */
  273:         if (suspend) {
  274:                 *LCDOUT = 0;
  275:                 LCDpower(FALSE);
  276:         } else {
  277:                 LCDpower(TRUE);
  278:                 *LCDOUT = 1;
  279:         }
  280: 
  281:         return;
  282: }
  283: 
  284: /*
  285:         initialization processing
  286: 
  287:         return == 0:    not the target
  288:                 > 0:    target (normal)
  289:                 < 0:    target (error)
  290: 
  291:   1. Looking at Vinf.vendorid, Vinf.deviceid, Vinf.oemname[], decide whether device is the target of
  292:      the driver, and if so, set details in Vinf.chipinf[].
  293: 
  294:         PCI Config register can be accessed via Vinf.pciaddr.
  295:         Vinf.oemname - bankshift shall contain information using VESA BIOS.
  296: 
  297: 
  298:   2. If there are additional functions to augment VESA BIOS, do the following.
  299: 
  300:         only set up really supported mode map in modemap.
  301:         if curmode != reqmode, it means VESA BIOS is not supported,
  302:           we do the following Even if curmode == reqmode, when we do not use VESA BIOS,
  303:           do similar processing as below.
  304:             set reqmode to curmode
  305:             Configure values according to reqmode in the following places.
  306:                 each bit of attr            BPP_24, DACBITS_8, and LINEAR_FRAMEBUF
  307:                                 is set. (usually LINEAR_FRAMEBUF is ON )
  308:                 framebuf_addr   set physical address of framebuffer.
  309:                 framebuf_total  set the total byte counts of the framebuffer.
  310:                 framebuf_rowb   set the horizontal byte count of the framebuffer.
  311:         set mode set function to fn_setmode.
  312: 
  313:         * mode set function is executed later to really to set the mode.
  314:            at this stage of processing, VGA mode (640 x 480 16 colors)
  315:            is in effect.
  316: 
  317:   3. Depending on the available functions, set the function pointers.
  318: 
  319:         fn_setmode
  320:                 set display mode for real.
  321: 
  322:                 void (*fn_setmode)(W flg)
  323: 
  324:                 flg = 0:
  325:                         set display mode as specified by Vinf.curmode, and Vinf.vfreq, then
  326:                         clear VRAM.
  327:                         by calling setVesaMode(), we can use VESA BIOS to set
  328:                         display mode.
  329:                 flg = 1:
  330:                         switch to the vertical scan frequency specified in Vinf.vfreq.
  331:                         do not clear VRAM
  332: 
  333:                 Vinf.vfreq == 0 means using default or not configuring.
  334:                 Set the really used vertical frequency to Vinf.vfreq
  335:                 If unknown, or unsupported, set this to 0.
  336: 
  337:         fn_setcmap
  338:                 If the standard VGA color pallette is not used,
  339:                 set this to the pointer to the function that sets up the VGA color pallette.
  340: 
  341:                 void (*fn_setcmap)(COLOR *cmap, W ix, W nent)
  342: 
  343:                 Select the nent entries starting at the ix-th entry from cmap, and
  344:                 and set them into the really used color map. dac8bits == 0 means that DAC is 6 bits, !=0 means
  345:                 it has 8 bits resolution.
  346: 
  347:   4. Check whether the board is correctly configured, and if necessary,
  348:      configure PC Config registers, etc.
  349: 
  350: */
  351: EXPORT  W        EM1LCDCInit(void)
  352: {
  353:         W      fbsz, rowb, result;
  354: 
  355:         /* initailize SPI driver */
  356:         if ( (result = em1d512_iicspi_svc(TRUE)) < E_OK ) goto fin0;
  357: 
  358:         /* check modemap: if an invalid one is specified, select a useable mode. */
  359:         if (!(SUPPORT_MODEMAP & (1 << Vinf.reqmode))) {
  360:                 Vinf.reqmode = DEFAULT_REQMODE;
  361:         }
  362: 
  363:         /* set memory size to be allocated - 16 bpp assumed. */
  364:         rowb = VideoHsize(Vinf.reqmode) * 2;
  365:         fbsz = rowb * VideoVsize(Vinf.reqmode);
  366: 
  367:         Vinf.fb_width = VideoHsize(Vinf.reqmode);
  368:         Vinf.fb_height = VideoVsize(Vinf.reqmode);
  369: 
  370:         /* create framebuffer and mapping */
  371:         /* upper layer software may use slightly additional data, and so reserve such extra. */
  372:         Vinf.f_addr = getPhyMemory(fbsz + 16, &Vinf.framebuf_addr);
  373:         if (Vinf.f_addr == NULL) { result = E_NOMEM; goto fin0; }
  374: 
  375:         /* set Vinf */
  376:         STRNCPY(Vinf.chipinf, "EMMA-1 Mobile LCD Controller", L_CHIPINF);
  377:         Vinf.framebuf_total     = fbsz;
  378:         Vinf.framebuf_rowb      = rowb;
  379:         Vinf.curmode            = Vinf.reqmode;
  380:         Vinf.attr              |= (LINEAR_FRAMEBUF | DACBITS_8 |
  381:                                     NEED_FINPROC | NEED_SUSRESPROC);
  382:         Vinf.attr              &= ~BPP_24;
  383:         Vinf.fn_setcmap                 = em1_setcmap;
  384:         Vinf.fn_setmode                 = em1_setmode;
  385:         Vinf.fn_susres          = em1_suspend;
  386:         Vinf.modemap            = SUPPORT_MODEMAP;
  387: 
  388:         DP(("EM1LCDCInit(): Vinf.framebuf_addr %#x - %#x (%#x - %#x)\n",
  389:             Vinf.framebuf_addr, Vinf.framebuf_addr + Vinf.framebuf_total - 1,
  390:             Vinf.f_addr, Vinf.f_addr + Vinf.framebuf_total - 1));
  391: 
  392:         result = 1;
  393: fin0:
  394:         return result;
  395: }