- Main Page
- Related Pages
- Data Structures
- Files

# lcdc.c

Go to the documentation of this file.

    00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
    00018 /* Copyright (C) 2006-2008, Atmel Corporation All rights reserved.
    00019  *
    00020  * Redistribution and use in source and binary forms, with or without
    00021  * modification, are permitted provided that the following conditions are met:
    00022  *
    00023  * 1. Redistributions of source code must retain the above copyright notice,
    00024  * this list of conditions and the following disclaimer.
    00025  *
    00026  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00027  * this list of conditions and the following disclaimer in the documentation
    00028  * and/or other materials provided with the distribution.
    00029  *
    00030  * 3. The name of ATMEL may not be used to endorse or promote products derived
    00031  * from this software without specific prior written permission.
    00032  *
    00033  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
    00034  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00035  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
    00036  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00037  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00038  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00039  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00040  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00041  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00042  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00043  */
    00044
    00045 #include "lcdc.h"
    00046 #include "print_funcs.h"
    00047
    00057 int lcdc_init(lcdc_conf_t* lcdc_conf)
    00058 {
    00059   volatile avr32_lcdc_t *plcdc = &AVR32_LCDC;
    00060   unsigned char valid_data_lines = 0;
    00061   unsigned char pixel_size = 0;
    00062   unsigned char clkval = 0;
    00063   unsigned int pixel_clock_theo = 0;
    00064   unsigned short lineval, hozval;
    00065
    00066   /* Turn off LCD Controller (core first then DMA) */
    00067   plcdc->pwrcon &= ~(1 << AVR32_LCDC_PWRCON_PWR_OFFSET);
    00068   plcdc->dmacon &= ~(1 << AVR32_LCDC_DMACON_DMAEN_OFFSET);
    00069
    00070   /* LCDFRCFG */
    00071   if(lcdc_conf->distype != LCDC_TFT){
    00072     switch(lcdc_conf->scanmod){
    00073     case LCDC_SINGLE_SCAN:
    00074       switch(lcdc_conf->ifwidth){
    00075       case LCDC_IF_WIDTH4:
    00076         valid_data_lines = 4;
    00077         break;
    00078       case LCDC_IF_WIDTH8:
    00079         valid_data_lines = 8;
    00080         break;
    00081       default:
    00082         return -1;
    00083     }
    00084
    00085     case LCDC_DUAL_SCAN:
    00086       switch(lcdc_conf->ifwidth){
    00087       case LCDC_IF_WIDTH8:
    00088         valid_data_lines = 4;
    00089         break;
    00090       case LCDC_IF_WIDTH16:
    00091         valid_data_lines = 8;
    00092         break;
    00093       default:
    00094         return -1;
    00095       }
    00096     default:
    00097       return -1;
    00098     }
    00099   }
    00100
    00101   lineval = lcdc_conf->yres - 1;
    00102   switch(lcdc_conf->distype){
    00103   case LCDC_STN_MONO:
    00104     hozval = (lcdc_conf->xres / valid_data_lines) - 1;
    00105     break;
    00106   case LCDC_STN_COLOR:
    00107     hozval = (lcdc_conf->xres * 3 / valid_data_lines) - 1;
    00108     break;
    00109   case LCDC_TFT:
    00110     hozval = lcdc_conf->xres - 1;
    00111     break;
    00112   default:
    00113     return -1;
    00114   }
    00115   plcdc->lcdfrmcfg = (lineval & AVR32_LCDC_LINEVAL_MASK) |
    00116       ((hozval << AVR32_LCDC_HOZVAL) & AVR32_LCDC_HOZVAL_MASK);
    00117
    00118   /* Calculation of theoretical pixel clock */
    00119   switch(lcdc_conf->distype){
    00120     case LCDC_STN_MONO:
    00121       pixel_clock_theo = lcdc_conf->frame_rate * lcdc_conf->xres * lcdc_conf->yres / valid_data_lines;
    00122       break;
    00123     case LCDC_STN_COLOR:
    00124       pixel_clock_theo = lcdc_conf->frame_rate * lcdc_conf->xres * lcdc_conf->yres * 3 / valid_data_lines;
    00125       break;
    00126     case LCDC_TFT:
    00127       pixel_clock_theo = lcdc_conf->frame_rate * lcdc_conf->xres * lcdc_conf->yres;
    00128       break;
    00129     default:
    00130       return -1;
    00131   }
    00132   clkval = (lcdc_conf->lcdcclock / (2 * pixel_clock_theo));
    00133   if (clkval == 0) {
    00134     plcdc->lcdcon1 = 1; /* bypass pixel clock */
    00135   } else {
    00136     plcdc->lcdcon1 = ((clkval - 1) << AVR32_LCDC_LCDCON1_CLKVAL) & AVR32_LCDC_LCDCON1_CLKVAL_MASK;
    00137   }
    00138
    00139   /* LCDCON2 */
    00140   switch(lcdc_conf->pixelsize){
    00141     case 1: pixel_size = 0;break;
    00142     case 2: pixel_size = 1;break;
    00143     case 4: pixel_size = 2;break;
    00144     case 8: pixel_size = 3;break;
    00145     case 16: pixel_size = 4;break;
    00146     case 24: pixel_size = 5;break;
    00147     case 32: pixel_size = 6;break;
    00148     default:
    00149       return -1;
    00150   }
    00151   plcdc->lcdcon2 = (lcdc_conf->distype & AVR32_LCDC_LCDCON2_DISTYPE_MASK) |
    00152       ((lcdc_conf->scanmod << AVR32_LCDC_LCDCON2_SCANMOD) & AVR32_LCDC_LCDCON2_SCANMOD_MASK) |
    00153       ((lcdc_conf->ifwidth << AVR32_LCDC_LCDCON2_IFWIDTH) & AVR32_LCDC_LCDCON2_IFWIDTH_MASK) |
    00154       ((lcdc_conf->invvd << AVR32_LCDC_LCDCON2_INVVD) & AVR32_LCDC_LCDCON2_INVVD_MASK) |
    00155       ((lcdc_conf->invframe << AVR32_LCDC_LCDCON2_INVFRAME) & AVR32_LCDC_LCDCON2_INVFRAME_MASK) |
    00156       ((pixel_size << AVR32_LCDC_LCDCON2_PIXELSIZE) & AVR32_LCDC_LCDCON2_PIXELSIZE_MASK) |
    00157       ((lcdc_conf->invline << AVR32_LCDC_LCDCON2_INVLINE) & AVR32_LCDC_LCDCON2_INVLINE_MASK) |
    00158       ((lcdc_conf->invclk << AVR32_LCDC_LCDCON2_INVCLK) & AVR32_LCDC_LCDCON2_INVCLK_MASK) |
    00159       ((lcdc_conf->invdval << AVR32_LCDC_LCDCON2_INVDVAL) & AVR32_LCDC_LCDCON2_INVDVAL_MASK) |
    00160       ((lcdc_conf->clkmod << AVR32_LCDC_LCDCON2_CLKMOD) & AVR32_LCDC_LCDCON2_CLKMOD_MASK) |
    00161       ((lcdc_conf->memor << AVR32_LCDC_LCDCON2_MEMOR) & AVR32_LCDC_LCDCON2_MEMOR_MASK);
    00162
    00163   /* Timings */
    00164   plcdc->lcdtim1 = (lcdc_conf->vfp & AVR32_LCDC_LCDTIM1_VFP_MASK) |
    00165       ((lcdc_conf->vbp << AVR32_LCDC_LCDTIM1_VBP) & AVR32_LCDC_LCDTIM1_VBP_MASK) |
    00166       (((lcdc_conf->vpw - 1) << AVR32_LCDC_LCDTIM1_VPW) & AVR32_LCDC_LCDTIM1_VPW_MASK) |
    00167       ((lcdc_conf->vhdly << AVR32_LCDC_LCDTIM1_VHDLY) & AVR32_LCDC_LCDTIM1_VHDLY_MASK);
    00168
    00169   plcdc->lcdtim2 = (lcdc_conf->hbp & AVR32_LCDC_HBP_MASK) |
    00170       (((lcdc_conf->hpw - 1) << AVR32_LCDC_LCDTIM2_HPW) & AVR32_LCDC_LCDTIM2_HPW_MASK) |
    00171       ((lcdc_conf->hfp << AVR32_LCDC_LCDTIM2_HFP) & AVR32_LCDC_LCDTIM2_HFP_MASK);
    00172
    00173   /* Interrupts */
    00174   plcdc->idr = 0xFFFFFFFF;
    00175
    00176   /* Toggle rate */
    00177   plcdc->lcdmval = (lcdc_conf->mval & AVR32_LCDC_LCDMVAL_MVAL_MASK) |
    00178       ((lcdc_conf->mmode << AVR32_LCDC_LCDMVAL_MMODE_OFFSET) & AVR32_LCDC_LCDMVAL_MMODE_MASK);
    00179
    00180   /* Contrast */
    00181   plcdc->contrast_val = lcdc_conf->ctrstval;
    00182   plcdc->contrast_ctr = (lcdc_conf->ctrst_ps & AVR32_LCDC_CONTRAST_CTR_PS_MASK) |
    00183       ((lcdc_conf->ctrst_pol << AVR32_LCDC_CONTRAST_CTR_POL_OFFSET) & AVR32_LCDC_CONTRAST_CTR_POL_MASK) |
    00184       ((lcdc_conf->ctrst_ena << AVR32_LCDC_CONTRAST_CTR_ENA_OFFSET) & AVR32_LCDC_CONTRAST_CTR_ENA_MASK);
    00185
    00186   /* Setup FIFO */
    00187   int lcd_fifo_size = lcdc_conf->scanmod ? 256 : 512;
    00188   plcdc->lcdfifo = lcd_fifo_size - (2 * lcdc_conf->burst_length + 3);
    00189
    00190   /* DMA base address */
    00191   plcdc->dmabaddr1 = lcdc_conf->dmabaddr1;
    00192   if(lcdc_conf->scanmod == LCDC_DUAL_SCAN){
    00193     plcdc->dmabaddr2 = lcdc_conf->dmabaddr2;
    00194   }
    00195   /* DMA frame configuration
    00196   * The frame size is measured in words
    00197   */
    00198   plcdc->dmafrmcfg = ((((lcdc_conf->xres * lcdc_conf->yres * lcdc_conf->pixelsize) + 31 )/ 32) & AVR32_LCDC_DMAFRMCFG_FRMSIZE_MASK) |
    00199       (((lcdc_conf->burst_length - 1) << AVR32_LCDC_DMAFRMCFG_BRSTLEN) & AVR32_LCDC_DMAFRMCFG_BRSTLEN_MASK);
    00200
    00201   /* 2D configuration */
    00202   if(lcdc_conf->set2dmode){
    00203     /* Assumed is that the frame starts at a word boundary -> no pixel offset needed */
    00204     plcdc->dma2dcfg = ((lcdc_conf->virtual_xres - lcdc_conf->xres) * (lcdc_conf->pixelsize / 8)) & AVR32_LCDC_DMA2DCFG_ADDRINC_MASK;
    00205   }
    00206
    00207   /* wait for DMA engine to become idle */
    00208   while (plcdc->dmacon & AVR32_LCDC_DMACON_DMABUSY);
    00209
    00210   /* and enable DMA with updated configuration */
    00211   if(lcdc_conf->set2dmode){
    00212     plcdc->dmacon = (1 << AVR32_LCDC_DMACON_DMAEN_OFFSET) |
    00213       (1 << AVR32_LCDC_DMACON_DMAUPDT_OFFSET) |
    00214       (1 << AVR32_LCDC_DMACON_DMA2DEN_OFFSET);
    00215   }
    00216   else{
    00217     plcdc->dmacon = (1 << AVR32_LCDC_DMACON_DMAEN_OFFSET) |
    00218       (1 << AVR32_LCDC_DMACON_DMAUPDT_OFFSET);
    00219   }
    00220   /* enable LCD */
    00221   plcdc->pwrcon |= (lcdc_conf->guard_time << AVR32_LCDC_PWRCON_GUARD_TIME_OFFSET) & AVR32_LCDC_PWRCON_GUARD_TIME_MASK;
    00222
    00223   /* Wait for the LCDC core to become idle and enable it */
    00224   while (plcdc->PWRCON.busy == 1);
    00225   plcdc->PWRCON.pwr = 1;
    00226
    00227   return 0;
    00228 }