Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "pxa255_LCD.h"
  2. #include "mem.h"
  3.  
  4.  
  5.  
  6. #define LCD_IMAGE               "LCD.bmp"
  7. #define UNMASKABLE_INTS         0x7C8E
  8.  
  9.  
  10. static void pxa255lcdPrvUpdateInts(Pxa255lcd* lcd){
  11.        
  12.         UInt16 ints = lcd->lcsr & lcd->intMask;
  13.        
  14.         if((ints && !lcd->intWasPending) || (!ints && lcd->intWasPending)){
  15.                        
  16.                 lcd->intWasPending = !!ints;
  17.                 pxa255icInt(lcd->ic, PXA255_I_LCD, !!ints);
  18.         }
  19. }
  20.  
  21. static Boolean pxa255lcdPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
  22.  
  23.         Pxa255lcd* lcd = userData;
  24.         UInt32 val = 0;
  25.         UInt16 v16;
  26.        
  27.         if(size != 4) {
  28.                 err_str(__FILE__ ": Unexpected ");
  29.         //      err_str(write ? "write" : "read");
  30.         //      err_str(" of ");
  31.         //      err_dec(size);
  32.         //      err_str(" bytes to 0x");
  33.         //      err_hex(pa);
  34.         //      err_str("\r\n");
  35.                 return true;            //we do not support non-word accesses
  36.         }
  37.        
  38.         pa = (pa - PXA255_LCD_BASE) >> 2;
  39.        
  40.         if(write){
  41.                 val = *(UInt32*)buf;
  42.                
  43.                 switch(pa){
  44.                         case 0:
  45.                                 if((lcd->lccr0 ^ val) & 0x0001){                //something changed about enablement - handle it
  46.                                        
  47.                                         lcd->enbChanged = 1;
  48.                                 }
  49.                                 lcd->lccr0 = val;
  50.                                 //recalc intMask
  51.                                 v16 = UNMASKABLE_INTS;
  52.                                 if(val & 0x00200000UL){ //output fifo underrun
  53.                                         v16 |= 0x0040;
  54.                                 }
  55.                                 if(val & 0x00100000UL){ //branch int
  56.                                         v16 |= 0x0200;
  57.                                 }
  58.                                 if(val & 0x00000400UL){ //quick disable
  59.                                         v16 |= 0x0001;
  60.                                 }
  61.                                 if(val & 0x00000040UL){ //end of frame
  62.                                         v16 |= 0x0080;
  63.                                 }
  64.                                 if(val & 0x00000020UL){ //input fifo underrun
  65.                                         v16 |= 0x0030;
  66.                                 }
  67.                                 if(val & 0x00000010UL){ //start of frame
  68.                                         v16 |= 0x0002;
  69.                                 }
  70.                                 lcd->intMask = v16;
  71.                                 pxa255lcdPrvUpdateInts(lcd);
  72.                                 break;
  73.                        
  74.                         case 1:
  75.                                 lcd->lccr1 = val;
  76.                                 break;
  77.                        
  78.                         case 2:
  79.                                 lcd->lccr2 = val;
  80.                                 break;
  81.                        
  82.                         case 3:
  83.                                 lcd->lccr3 = val;
  84.                                 break;
  85.                        
  86.                         case 8:
  87.                                 lcd->fbr0 = val;
  88.                                 break;
  89.                        
  90.                         case 9:
  91.                                 lcd->fbr1 = val;
  92.                                 break;
  93.                        
  94.                         case 14:
  95.                                 lcd->lcsr &=~ val;
  96.                                 pxa255lcdPrvUpdateInts(lcd);
  97.                                 break;
  98.                        
  99.                         case 15:
  100.                                 lcd->liicr = val;
  101.                                 break;
  102.                        
  103.                         case 16:
  104.                                 lcd->trgbr = val;
  105.                                 break;
  106.                        
  107.                         case 17:
  108.                                 lcd->tcr = val;
  109.                                 break;
  110.                        
  111.                         case 128:
  112.                                 lcd->fdadr0 = val;
  113.                                 break;
  114.                        
  115.                         case 132:
  116.                                 lcd->fdadr1 = val;
  117.                                 break;
  118.                 }
  119.         }
  120.         else{
  121.                 switch(pa){
  122.                         case 0:
  123.                                 val = lcd->lccr0;
  124.                                 break;
  125.                        
  126.                         case 1:
  127.                                 val = lcd->lccr1;
  128.                                 break;
  129.                        
  130.                         case 2:
  131.                                 val = lcd->lccr2;
  132.                                 break;
  133.                        
  134.                         case 3:
  135.                                 val = lcd->lccr3;
  136.                                 break;
  137.                        
  138.                         case 8:
  139.                                 val = lcd->fbr0;
  140.                                 break;
  141.                        
  142.                         case 9:
  143.                                 val = lcd->fbr1;
  144.                                 break;
  145.                        
  146.                         case 14:
  147.                                 val = lcd->lcsr;
  148.                                 break;
  149.                        
  150.                         case 15:
  151.                                 val = lcd->liicr;
  152.                                 break;
  153.                        
  154.                         case 16:
  155.                                 val = lcd->trgbr;
  156.                                 break;
  157.                        
  158.                         case 17:
  159.                                 val = lcd->tcr;
  160.                                 break;
  161.                        
  162.                         case 128:
  163.                                 val = lcd->fdadr0;
  164.                                 break;
  165.                        
  166.                         case 129:
  167.                                 val = lcd->fsadr0;
  168.                                 break;
  169.                        
  170.                         case 130:
  171.                                 val = lcd->fidr0;
  172.                                 break;
  173.                        
  174.                         case 131:
  175.                                 val = lcd->ldcmd0;
  176.                                 break;
  177.                        
  178.                         case 132:
  179.                                 val = lcd->fdadr1;
  180.                                 break;
  181.                        
  182.                         case 133:
  183.                                 val = lcd->fsadr1;
  184.                                 break;
  185.                        
  186.                         case 134:
  187.                                 val = lcd->fidr1;
  188.                                 break;
  189.                        
  190.                         case 135:
  191.                                 val = lcd->ldcmd1;
  192.                                 break;
  193.                 }
  194.                 *(UInt32*)buf = val;
  195.         }
  196.        
  197.         return true;
  198. }
  199.  
  200. static UInt32 pxa255PrvGetWord(Pxa255lcd* lcd, UInt32 addr){
  201.        
  202.         UInt32 v;
  203.        
  204.         if(!memAccess(lcd->mem, addr, 4, false, &v)) return 0;
  205.        
  206.         return v;
  207. }
  208.  
  209. static void pxa255LcdPrvDma(Pxa255lcd* lcd, void* dest, UInt32 addr, UInt32 len){
  210.  
  211.         UInt32 t;
  212.         UInt8* d = dest;
  213.  
  214.         //we assume aligntment here both on part of dest and of addr
  215.  
  216.         while(len){
  217.                
  218.                 t = pxa255PrvGetWord(lcd, addr);
  219.                 if(len--) *d++ = t;
  220.                 if(len--) *d++ = t >> 8;
  221.                 if(len--) *d++ = t >> 16;
  222.                 if(len--) *d++ = t >> 24;
  223.                 addr += 4;
  224.         }
  225. }
  226.  
  227. #ifndef EMBEDDED
  228.         #include <stdio.h>
  229.        
  230.         static _INLINE_ void pxa255LcdScreenDataPixel(Pxa255lcd* lcd, UInt8* buf){
  231.        
  232.                 UInt8 r, g, b;
  233.                 const UInt32 W = 640;
  234.                 const UInt32 H = 480;
  235.                
  236.                 b = buf[0] << 3;
  237.                 r = buf[1] & 0xF8;
  238.                 g = (buf[1] << 5) | ((buf[0] >> 3) & 0x1C);
  239.                
  240.                 {
  241.                         static UInt32 pn = 0;
  242.                         static FILE* bmp = NULL;
  243.                        
  244.                         if(pn == 0){
  245.                                 bmp = fopen(LCD_IMAGE, "w+b");
  246.                                 if(bmp){
  247.                                        
  248.                                         const UInt32 off = 56;
  249.                                         const UInt32 sz = 320 * 320 * 3 + off;
  250.                                         #define LE32(x) ((int)((x) & 0xFF)), ((int)(((x) >> 8) & 0xFF)), ((int)(((x) >> 16) & 0xFF)), ((int)((x) >> 24))
  251.                                         #define LE16(x) ((int)((x) & 0xFF)), ((int)(((x) >> 8) & 0xFF))
  252.                                        
  253.                                         fprintf(bmp, "BM%c%c%c%c%c%c%c%c%c%c%c%c", LE32(sz), LE16(0), LE16(0), LE32(off));      //bitmap file header
  254.                                         fprintf(bmp, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", LE32(40), LE32(W), LE32(-H), LE16(1), LE16(24), LE32(0), LE32(W * H * 3), LE32(2835), LE32(2835), LE32(0), LE32(0)); //BITMAPCOREHEADER
  255.                                         fprintf(bmp, "%c%c",0 ,0); //spacer to align bmp data to 4 bytes
  256.                                        
  257.                                         #undef LE32
  258.                                 }
  259.                         }
  260.                         if(bmp){
  261.                        
  262.                                 fprintf(bmp, "%c%c%c", b, g, r);
  263.                         }
  264.                         pn++;
  265.                         if(pn == W * H){
  266.                                 pn = 0;
  267.                                 if(bmp){
  268.                                        
  269.                                         fclose(bmp);
  270.                                         bmp = NULL;
  271.                                 }
  272.                         }
  273.                 }
  274.         }
  275.  
  276.         #ifndef PXA255_LCD_SUPPORTS_PALLETES
  277.         static void pxa255LcdSetFakePal(UInt8* buf, UInt8 bpp, UInt8 val){
  278.        
  279.                 while(bpp++ < 8) val = (val << 1) | (val & 1);  //sign extend up (weird but works)
  280.                
  281.                 buf[1] = (val & 0xF8) | (val >> 3);
  282.                 buf[0] = ((val & 0xFC) << 5) | val >> 3;
  283.         }
  284.         #endif
  285.        
  286.         static void pxa255LcdScreenDataDma(Pxa255lcd* lcd, UInt32 addr/*PA*/, UInt32 len){
  287.                
  288.                 UInt8 data[4];
  289.                 UInt32 i, j;
  290.                 void* ptr;
  291.         #ifndef PXA255_LCD_SUPPORTS_PALLETES
  292.                 UInt8 val[2];
  293.         #endif
  294.                
  295.                 len /= 4;
  296.                 while(len--){
  297.                         pxa255LcdPrvDma(lcd, data, addr, 4);
  298.                         addr += 4;
  299.                        
  300.                         switch((lcd->lccr3 >> 24) & 7){
  301.                                
  302.                                 case 0:         //1BPP
  303.                                        
  304.                                 #ifdef PXA255_LCD_SUPPORTS_PALLETES
  305.                                         ptr = lcd->palette + ((data[i] >> j) & 1) * 2;
  306.                                 #else
  307.                                         ptr = val;
  308.                                         pxa255LcdSetFakePal(val, 1, (data[i] >> j) & 1);
  309.                                 #endif
  310.                                         for(i = 0; i < 4; i += 1) for(j = 0; j < 8; j += 1) pxa255LcdScreenDataPixel(lcd, ptr);
  311.                                         break;
  312.                                
  313.                                 case 1:         //2BPP
  314.                                        
  315.                                 #ifdef PXA255_LCD_SUPPORTS_PALLETES
  316.                                         ptr = lcd->palette + ((data[i] >> j) & 3) * 2;
  317.                                 #else
  318.                                         ptr = val;
  319.                                         pxa255LcdSetFakePal(val, 2, (data[i] >> j) & 3);
  320.                                 #endif
  321.                                         for(i = 0; i < 4; i += 1) for(j = 0; j < 8; j += 2) pxa255LcdScreenDataPixel(lcd, ptr);
  322.                                         break;
  323.                                
  324.                                 case 2:         //4BPP
  325.                                        
  326.                                 #ifdef PXA255_LCD_SUPPORTS_PALLETES
  327.                                         ptr = lcd->palette + ((data[i] >> j) & 15) * 2;
  328.                                 #else
  329.                                         ptr = val;
  330.                                         pxa255LcdSetFakePal(val, 4, (data[i] >> j) & 15);
  331.                                 #endif
  332.                                         for(i = 0; i < 4; i += 1) for(j = 0; j < 8; j += 4) pxa255LcdScreenDataPixel(lcd, ptr);
  333.                                         break;
  334.                                
  335.                                 case 3:         //8BPP
  336.                                        
  337.                                 #ifdef PXA255_LCD_SUPPORTS_PALLETES
  338.                                         ptr = lcd->palette + (data[i] * 2);
  339.                                 #else
  340.                                         ptr = val;
  341.                                         pxa255LcdSetFakePal(val, 8, data[i]);
  342.                                 #endif
  343.                                         for(i = 0; i < 4; i += 1) pxa255LcdScreenDataPixel(lcd, ptr);
  344.                                         break;
  345.                                
  346.                                 case 4:         //16BPP
  347.                                        
  348.                                         for(i = 0; i < 4; i +=2 ) pxa255LcdScreenDataPixel(lcd, data + i);
  349.                                         break;
  350.                                
  351.                                 default:
  352.                                        
  353.                                         ;//BAD
  354.                         }
  355.                 }
  356.         }
  357. #else
  358.         static void pxa255LcdScreenDataDma(Pxa255lcd* lcd, UInt32 addr/*PA*/, UInt32 len){
  359.        
  360.                 //nothing      
  361.         }
  362. #endif
  363.  
  364. void pxa255lcdFrame(Pxa255lcd* lcd){
  365.         //every other call starts a frame, the others end one [this generates spacing between interrupts so as to not confuse guest OS]
  366.        
  367.         if(lcd->enbChanged){
  368.                
  369.                 if(lcd->lccr0 & 0x0001){        //just got enabled
  370.                        
  371.                         //TODO: perhaps check settings?
  372.                 }
  373.                 else{                           // we just got quick disabled - kill current frame and do no more
  374.                
  375.                         lcd->lcsr |= 0x0080;    //quick disable happened
  376.                         lcd->state = LCD_STATE_IDLE;
  377.                 }
  378.                 lcd->enbChanged = false;                       
  379.         }
  380.        
  381.         if(lcd->lccr0 & 0x0001){                        //enabled - do a frame
  382.                
  383.                 UInt32 descrAddr, len;
  384.                
  385.                 switch(lcd->state){
  386.                        
  387.                         case LCD_STATE_IDLE:
  388.                                
  389.                                 if(lcd->fbr0 & 1){      //branch
  390.                                        
  391.                                         lcd->fbr0 &=~ 1UL;
  392.                                         if(lcd->fbr0 & 2) lcd->lcsr |= 0x0200;
  393.                                         descrAddr = lcd->fbr0 &~ 0xFUL;
  394.                                 } else descrAddr = lcd->fdadr0;
  395.                                 lcd->fdadr0 = pxa255PrvGetWord(lcd, descrAddr + 0);
  396.                                 lcd->fsadr0 = pxa255PrvGetWord(lcd, descrAddr + 4);
  397.                                 lcd->fidr0  = pxa255PrvGetWord(lcd, descrAddr + 8);
  398.                                 lcd->ldcmd0 = pxa255PrvGetWord(lcd, descrAddr + 12);
  399.                        
  400.                                 lcd->state = LCD_STATE_DMA_0_START;
  401.                                 break;
  402.                        
  403.                         case LCD_STATE_DMA_0_START:
  404.                                
  405.                                 if(lcd->ldcmd0 & 0x00400000UL) lcd->lcsr |= 0x0002;     //set SOF is DMA 0 started
  406.                                 len = lcd->ldcmd0 & 0x000FFFFFUL;
  407.                                
  408.                                 if(lcd->ldcmd0 & 0x04000000UL){ //pallette data
  409.                                        
  410.                                         #ifdef PXA255_LCD_SUPPORTS_PALLETES    
  411.                                                 if(len > sizeof(lcd->palette)){
  412.                                                        
  413.                                                         len = sizeof(lcd->palette);
  414.                                                        
  415.                                                         pxa255LcdPrvDma(lcd, lcd->palette, lcd->fsadr0, len);
  416.                                                 }              
  417.                                         #endif
  418.                                 }
  419.                                 else{
  420.                                        
  421.                                         lcd->frameNum++;
  422.                                         if(!(lcd->frameNum & 63)) pxa255LcdScreenDataDma(lcd, lcd->fsadr0, len);
  423.                                 }
  424.                                
  425.                                 lcd->state = LCD_STATE_DMA_0_END;
  426.                                 break;
  427.                                
  428.                         case LCD_STATE_DMA_0_END:
  429.                                
  430.                                 if(lcd->ldcmd0 & 0x00200000UL) lcd->lcsr |= 0x0100;     //set EOF is DMA 0 finished
  431.                                 lcd->state = LCD_STATE_IDLE;
  432.                                 break;
  433.                 }
  434.         }
  435.         pxa255lcdPrvUpdateInts(lcd);
  436. }
  437.  
  438.  
  439. Boolean pxa255lcdInit(Pxa255lcd* lcd, ArmMem* physMem, Pxa255ic* ic){
  440.        
  441.        
  442.         __mem_zero(lcd, sizeof(Pxa255lcd));
  443.        
  444.         lcd->ic = ic;
  445.         lcd->mem = physMem;
  446.         lcd->intMask = UNMASKABLE_INTS;
  447.        
  448.         return memRegionAdd(physMem, PXA255_LCD_BASE, PXA255_LCD_SIZE, pxa255lcdPrvMemAccessF, lcd);
  449. }
  450.  
  451.  
  452.  
  453.  
  454.  
  455.