This file defines a useful set of functions for the LCD controller on AVR32AP devices.
$Name$
Definition in file lcdc.c.
#include "lcdc.h"
Go to the source code of this file.
Functions | |
| int | lcdc_init (lcdc_conf_t *lcdc_conf) |
| Configures the LCD module. | |
| int lcdc_init | ( | lcdc_conf_t * | lcdc_conf | ) |
Configures the LCD module.
| lcdc_conf | Pointer to LCD controller configuration structure |
| 0 | = success | |
| -1 | = invalid argument |
Definition at line 60 of file lcdc.c.
References lcdc_conf_t::burst_length, lcdc_conf_t::clkmod, lcdc_conf_t::ctrst_ena, lcdc_conf_t::ctrst_pol, lcdc_conf_t::ctrst_ps, lcdc_conf_t::ctrstval, lcdc_conf_t::distype, lcdc_conf_t::dmabaddr1, lcdc_conf_t::dmabaddr2, DUAL_SCAN, lcdc_conf_t::frame_rate, lcdc_conf_t::guard_time, lcdc_conf_t::hbp, lcdc_conf_t::hfp, lcdc_conf_t::hpw, IF_WIDTH16, IF_WIDTH4, IF_WIDTH8, lcdc_conf_t::ifwidth, lcdc_conf_t::invclk, lcdc_conf_t::invdval, lcdc_conf_t::invframe, lcdc_conf_t::invline, lcdc_conf_t::invvd, lcdc_conf_t::lcdcclock, lcdc_conf_t::memor, lcdc_conf_t::mmode, lcdc_conf_t::mval, lcdc_conf_t::pixelsize, lcdc_conf_t::scanmod, lcdc_conf_t::set2dmode, SINGLE_SCAN, STN_COLOR, STN_MONO, TFT, lcdc_conf_t::vbp, lcdc_conf_t::vfp, lcdc_conf_t::vhdly, lcdc_conf_t::virtual_xres, lcdc_conf_t::vpw, lcdc_conf_t::xres, and lcdc_conf_t::yres.
Referenced by main().
00061 { 00062 volatile avr32_lcdc_t *plcdc = &AVR32_LCDC; 00063 unsigned char valid_data_lines = 0; 00064 unsigned char pixel_size = 0; 00065 unsigned char clkval = 0; 00066 unsigned int pixel_clock_theo = 0; 00067 unsigned short lineval, hozval; 00068 00069 00070 /* Turn off LCD Controller (core first then DMA) */ 00071 plcdc->pwrcon &= ~(1 << AVR32_LCDC_PWRCON_PWR_OFFSET); 00072 plcdc->dmacon &= ~(1 << AVR32_LCDC_DMACON_DMAEN_OFFSET); 00073 00074 /* LCDFRCFG */ 00075 if(lcdc_conf->distype != TFT){ 00076 switch(lcdc_conf->scanmod){ 00077 case SINGLE_SCAN: 00078 switch(lcdc_conf->ifwidth){ 00079 case IF_WIDTH4: 00080 valid_data_lines = 4; 00081 break; 00082 case IF_WIDTH8: 00083 valid_data_lines = 8; 00084 break; 00085 default: 00086 return -1; 00087 } 00088 00089 case DUAL_SCAN: 00090 switch(lcdc_conf->ifwidth){ 00091 case IF_WIDTH8: 00092 valid_data_lines = 4; 00093 break; 00094 case IF_WIDTH16: 00095 valid_data_lines = 8; 00096 break; 00097 default: 00098 return -1; 00099 } 00100 default: 00101 return -1; 00102 } 00103 } 00104 00105 lineval = lcdc_conf->yres - 1; 00106 switch(lcdc_conf->distype){ 00107 case STN_MONO: 00108 hozval = (lcdc_conf->xres / valid_data_lines) - 1; 00109 break; 00110 case STN_COLOR: 00111 hozval = (lcdc_conf->xres * 3 / valid_data_lines) - 1; 00112 break; 00113 case TFT: 00114 hozval = lcdc_conf->xres - 1; 00115 break; 00116 default: 00117 return -1; 00118 } 00119 plcdc->lcdfrmcfg = (lineval & AVR32_LCDC_LINEVAL_MASK) | 00120 ((hozval << AVR32_LCDC_HOZVAL) & AVR32_LCDC_HOZVAL_MASK); 00121 00122 00123 /* Calculation of theoretical pixel clock */ 00124 switch(lcdc_conf->distype){ 00125 case STN_MONO: 00126 pixel_clock_theo = lcdc_conf->frame_rate * lcdc_conf->xres * lcdc_conf->yres / valid_data_lines; 00127 break; 00128 case STN_COLOR: 00129 pixel_clock_theo = lcdc_conf->frame_rate * lcdc_conf->xres * lcdc_conf->yres * 3 / valid_data_lines; 00130 break; 00131 case TFT: 00132 pixel_clock_theo = lcdc_conf->frame_rate * lcdc_conf->xres * lcdc_conf->yres; 00133 break; 00134 default: 00135 return -1; 00136 } 00137 clkval = (lcdc_conf->lcdcclock / (2 * pixel_clock_theo)); 00138 if (clkval == 0) { 00139 plcdc->lcdcon1 = 1; /* bypass pixel clock */ 00140 } else { 00141 plcdc->lcdcon1 = ((clkval - 1) << AVR32_LCDC_LCDCON1_CLKVAL) & AVR32_LCDC_LCDCON1_CLKVAL_MASK; 00142 } 00143 00144 /* LCDCON2 */ 00145 switch(lcdc_conf->pixelsize){ 00146 case 1: pixel_size = 0;break; 00147 case 2: pixel_size = 1;break; 00148 case 4: pixel_size = 2;break; 00149 case 8: pixel_size = 3;break; 00150 case 16: pixel_size = 4;break; 00151 case 24: pixel_size = 5;break; 00152 case 32: pixel_size = 6;break; 00153 default: 00154 return -1; 00155 } 00156 plcdc->lcdcon2 = (lcdc_conf->distype & AVR32_LCDC_LCDCON2_DISTYPE_MASK) | 00157 ((lcdc_conf->scanmod << AVR32_LCDC_LCDCON2_SCANMOD) & AVR32_LCDC_LCDCON2_SCANMOD_MASK) | 00158 ((lcdc_conf->ifwidth << AVR32_LCDC_LCDCON2_IFWIDTH) & AVR32_LCDC_LCDCON2_IFWIDTH_MASK) | 00159 ((lcdc_conf->invvd << AVR32_LCDC_LCDCON2_INVVD) & AVR32_LCDC_LCDCON2_INVVD_MASK) | 00160 ((lcdc_conf->invframe << AVR32_LCDC_LCDCON2_INVFRAME) & AVR32_LCDC_LCDCON2_INVFRAME_MASK) | 00161 ((pixel_size << AVR32_LCDC_LCDCON2_PIXELSIZE) & AVR32_LCDC_LCDCON2_PIXELSIZE_MASK) | 00162 ((lcdc_conf->invline << AVR32_LCDC_LCDCON2_INVLINE) & AVR32_LCDC_LCDCON2_INVLINE_MASK) | 00163 ((lcdc_conf->invclk << AVR32_LCDC_LCDCON2_INVCLK) & AVR32_LCDC_LCDCON2_INVCLK_MASK) | 00164 ((lcdc_conf->invdval << AVR32_LCDC_LCDCON2_INVDVAL) & AVR32_LCDC_LCDCON2_INVDVAL_MASK) | 00165 ((lcdc_conf->clkmod << AVR32_LCDC_LCDCON2_CLKMOD) & AVR32_LCDC_LCDCON2_CLKMOD_MASK) | 00166 ((lcdc_conf->memor << AVR32_LCDC_LCDCON2_MEMOR) & AVR32_LCDC_LCDCON2_MEMOR_MASK); 00167 00168 /* Timings */ 00169 plcdc->lcdtim1 = (lcdc_conf->vfp & AVR32_LCDC_LCDTIM1_VFP_MASK) | 00170 ((lcdc_conf->vbp << AVR32_LCDC_LCDTIM1_VBP) & AVR32_LCDC_LCDTIM1_VBP_MASK) | 00171 (((lcdc_conf->vpw - 1) << AVR32_LCDC_LCDTIM1_VPW) & AVR32_LCDC_LCDTIM1_VPW_MASK) | 00172 ((lcdc_conf->vhdly << AVR32_LCDC_LCDTIM1_VHDLY) & AVR32_LCDC_LCDTIM1_VHDLY_MASK); 00173 00174 plcdc->lcdtim2 = (lcdc_conf->hbp & AVR32_LCDC_HBP_MASK) | 00175 (((lcdc_conf->hpw - 1) << AVR32_LCDC_LCDTIM2_HPW) & AVR32_LCDC_LCDTIM2_HPW_MASK) | 00176 ((lcdc_conf->hfp << AVR32_LCDC_LCDTIM2_HFP) & AVR32_LCDC_LCDTIM2_HFP_MASK); 00177 00178 /* Interrupts */ 00179 plcdc->idr = 0xFFFFFFFF; 00180 00181 /* Toggle rate */ 00182 plcdc->lcdmval = (lcdc_conf->mval & AVR32_LCDC_LCDMVAL_MVAL_MASK) | 00183 ((lcdc_conf->mmode << AVR32_LCDC_LCDMVAL_MMODE_OFFSET) & AVR32_LCDC_LCDMVAL_MMODE_MASK); 00184 00185 /* Contrast */ 00186 plcdc->contrast_val = lcdc_conf->ctrstval; 00187 plcdc->contrast_ctr = (lcdc_conf->ctrst_ps & AVR32_LCDC_CONTRAST_CTR_PS_MASK) | 00188 ((lcdc_conf->ctrst_pol << AVR32_LCDC_CONTRAST_CTR_POL_OFFSET) & AVR32_LCDC_CONTRAST_CTR_POL_MASK) | 00189 ((lcdc_conf->ctrst_ena << AVR32_LCDC_CONTRAST_CTR_ENA_OFFSET) & AVR32_LCDC_CONTRAST_CTR_ENA_MASK); 00190 00191 /* Setup FIFO */ 00192 int lcd_fifo_size = lcdc_conf->scanmod ? 256 : 512; 00193 plcdc->lcdfifo = lcd_fifo_size - (2 * lcdc_conf->burst_length + 3); 00194 00195 /* DMA base address */ 00196 plcdc->dmabaddr1 = lcdc_conf->dmabaddr1; 00197 if(lcdc_conf->scanmod == DUAL_SCAN){ 00198 plcdc->dmabaddr2 = lcdc_conf->dmabaddr2; 00199 } 00200 /* DMA frame configuration 00201 * The frame size is measured in words 00202 */ 00203 plcdc->dmafrmcfg = ((((lcdc_conf->xres * lcdc_conf->yres * lcdc_conf->pixelsize) + 31 )/ 32) & AVR32_LCDC_DMAFRMCFG_FRMSIZE_MASK) | 00204 (((lcdc_conf->burst_length - 1) << AVR32_LCDC_DMAFRMCFG_BRSTLEN) & AVR32_LCDC_DMAFRMCFG_BRSTLEN_MASK); 00205 00206 /* 2D configuration */ 00207 if(lcdc_conf->set2dmode){ 00208 /* Assumed is that the frame starts at a word boundary -> no pixel offset needed */ 00209 plcdc->dma2dcfg = ((lcdc_conf->virtual_xres - lcdc_conf->xres) * (lcdc_conf->pixelsize / 8)) & AVR32_LCDC_DMA2DCFG_ADDRINC_MASK; 00210 } 00211 00212 /* wait for DMA engine to become idle */ 00213 while (plcdc->dmacon & AVR32_LCDC_DMACON_DMABUSY); 00214 00215 /* and enable DMA with updated configuration */ 00216 if(lcdc_conf->set2dmode){ 00217 plcdc->dmacon = (1 << AVR32_LCDC_DMACON_DMAEN_OFFSET) | 00218 (1 << AVR32_LCDC_DMACON_DMAUPDT_OFFSET) | 00219 (1 << AVR32_LCDC_DMACON_DMA2DEN_OFFSET); 00220 } 00221 else{ 00222 plcdc->dmacon = (1 << AVR32_LCDC_DMACON_DMAEN_OFFSET) | 00223 (1 << AVR32_LCDC_DMACON_DMAUPDT_OFFSET); 00224 } 00225 /* enable LCD */ 00226 plcdc->pwrcon |= (lcdc_conf->guard_time << AVR32_LCDC_PWRCON_GUARD_TIME_OFFSET) & AVR32_LCDC_PWRCON_GUARD_TIME_MASK; 00227 00228 /* Wait for the LCDC core to become idle and enable it */ 00229 while (plcdc->PWRCON.busy == 1); 00230 plcdc->PWRCON.pwr = 1; 00231 00232 return 0; 00233 }
1.5.3-20071008