📄 lh79524_clcdc_driver.c
字号:
temp &= ~CLCDC_LCDCTRL_RGB;
/* Write the new value to the control register */
pregs->lcdctrl = temp;
break;
case LCD_DMA_ON_4MT:
/* Set DMA requests to start when 4 or 8 entries are
free in the CLCDC FIFOs */
if (arg == 0)
{
/* Use 8 entries */
pregs->lcdctrl &= ~CLCDC_LCDCTRL_WATERMARK;
}
else
{
/* Use 4 entries */
pregs->lcdctrl |= CLCDC_LCDCTRL_WATERMARK;
}
break;
/* Return pointer to device isr */
case LCD_GET_ISR:
/* Sanity check */
if ((void*)arg == NULL)
{
status = _ERROR;
break;
}
/* Return the driver interrupt service routine */
*(INT_32**)arg = (void*)pdev->irq_hdlr;
break;
/* Bind a callback method to be used by the timer isr */
case LCD_SET_CALLBACK:
/* Save the interrupt callback method */
pdev->callback = (PFI)arg;
break;
default:
/* Unsupported parameter */
status = _ERROR;
}
return (status);
}
/***********************************************************************
*
* Function: clcdc0_isr
*
* Purpose:
* Handle an lcd interrupt.
*
* Processing:
* See Purpose
*
* Parameters:
* None
*
* Outputs:
* None
*
* Returns:
* None
*
* Notes:
* None
*
**********************************************************************/
static void clcdc0_isr (void)
{
/* Call the default handler */
clcdc_default_isr ((INT_32)pdriver[0]);
}
/************************************************************************
*
* Function: clcdc_default_isr
*
* Purpose:
* Services the interrupt for the lcd controller.
*
* Processing:
*
* Parameters:
* None
*
* Outputs:
* None
*
* Returns:
* None
*
* Notes:
* None
*
************************************************************************/
static void clcdc_default_isr (INT_32 devid)
{
}
/***********************************************************************
* CLCDC driver private functions
**********************************************************************/
/***********************************************************************
*
* Function: lcd_initialize
*
* Purpose: Initialize the LCD controller
*
* Processing:
* Prior to resetting LCD values, disable the LCD controller. Based
* on the values in the passed LCD_PARAM_T structure, generate
* the appropriate LCD configuration words and place them in the
* correct LCD registers.
*
* Parameters:
* lcdcfgptr : A pointer to an LCD configuration data structure
*
* Outputs: None
*
* Returns: TRUE if the LCD was initialized, otherwise FALSE
*
* Notes: This driver only supports TFT and HR-TFT panel types.
*
**********************************************************************/
static BOOL_32 lcd_initialize (INT_32 devid)
{
UNS_32 tmp;
BOOL_32 init = FALSE;
LCD_PARAM_T* pcfg = NULL;
REGS_T* pregs = NULL;
TFT_REGS_T* ptft = NULL;
DRIVER_T* pdev = NULL;
UNS_32 pixel_div = 0;
/* Sanity check */
if (devid == 0)
{
/* Null pointer */
return (init);
}
/* Attach to the base address of the driver */
pdev = (DRIVER_T*)devid;
/* Bind to the clcdc regs, tft regs, and config structure */
pregs = (REGS_T*)pdev->regs;
ptft = (LCDICP_REGS_T*)pdev->tft;
pcfg = ((CLCDC_SETTINGS_T*)pdev->cfg)->lcdparam;
/* Disable the display in case it is on */
pregs->lcdctrl &= ~CLCDC_LCDCTRL_ENABLE;
/* Generate the timing 0 word */
tmp = (CLCDC_LCDTIMING0_PPL(pcfg->pixels_per_line) |
CLCDC_LCDTIMING0_HSW(pcfg->h_sync_pulse_width) |
CLCDC_LCDTIMING0_HFP(pcfg->h_front_porch) |
CLCDC_LCDTIMING0_HBP(pcfg->h_back_porch));
pregs->lcdtiming0 = tmp;
/* Generate the timing 1 word */
tmp = (CLCDC_LCDTIMING1_LPP(pcfg->lines_per_panel) |
CLCDC_LCDTIMING1_VSW(pcfg->v_sync_pulse_width) |
CLCDC_LCDTIMING1_VFP(pcfg->v_front_porch) |
CLCDC_LCDTIMING1_VBP(pcfg->v_back_porch));
pregs->lcdtiming1 = tmp;
/* Generate the timing 2 word */
tmp = CLCDC_LCDTIMING2_ACB(pcfg->ac_bias_frequency);
if (pcfg->invert_output_enable != 0)
{
tmp |= CLCDC_LCDTIMING2_IOE;
}
if (pcfg->invert_panel_clock != 0)
{
tmp |= CLCDC_LCDTIMING2_IPC;
}
if (pcfg->invert_hsync != 0)
{
tmp |= CLCDC_LCDTIMING2_IHS;
}
if (pcfg->invert_vsync != 0)
{
tmp |= CLCDC_LCDTIMING2_IVS;
}
/* Compute clocks per line based on panel type */
switch (pcfg->lcd_panel_type)
{
case MONO_4BIT:
/* Clocks per line is a quarter of pixels per line */
tmp = tmp | CLCDC_LCDTIMING2_CPL(
(pcfg->pixels_per_line / 4) - 1);
break;
case MONO_8BIT:
/* Clocks per line is an eighth of pixels per line */
tmp = tmp | CLCDC_LCDTIMING2_CPL(
(pcfg->pixels_per_line / 8) - 1);
break;
case CSTN:
/* CSTN Clocks per line (* 8 / 3) */
tmp = tmp | CLCDC_LCDTIMING2_CPL((
(pcfg->pixels_per_line * 8) / 3) - 1);
break;
case TFT:
case ADTFT:
case HRTFT:
default:
/* Clocks per line and pixels per line are the same */
tmp = tmp |
CLCDC_LCDTIMING2_CPL(pcfg->pixels_per_line - 1);
break;
}
pixel_div = (UNS_32)pdev->clcdclk / pcfg->optimal_clock;
/* Determine if 'div' or 'div + 1' is closer to desired
frequency */
if(((UNS_32)(pdev->clcdclk/pixel_div) - pcfg->optimal_clock) >
(pcfg->optimal_clock - (UNS_32)(pdev->clcdclk/(pixel_div + 1))) )
{
pixel_div += 1;
}
/* Determine pixel divider used in timing 2 word */
if (pixel_div == 0)
{
/* Pixel clock divider is 1, skip divider logic */
tmp |= CLCDC_LCDTIMING2_BCD;
}
else
{
/* Use divider logic */
tmp |= CLCDC_LCDTIMING2_PCD_LO(pixel_div);
tmp |= CLCDC_LCDTIMING2_PCD_HI(pixel_div);
}
pregs->lcdtiming2 = tmp;
/* Default with all interrupts of */
pregs->lcdintrenable = 0x00000000;
/* Setup basic control with controller disabled */
switch (pcfg->bits_per_pixel)
{
case 1:
tmp = CLCDC_LCDCTRL_BPP1;
break;
case 2:
tmp = CLCDC_LCDCTRL_BPP2;
break;
case 4:
tmp = CLCDC_LCDCTRL_BPP4;
break;
case 8:
tmp = CLCDC_LCDCTRL_BPP8;
break;
case 16:
default:
tmp = CLCDC_LCDCTRL_BPP16;
break;
}
switch (pcfg->lcd_panel_type)
{
case ADTFT:
case HRTFT:
case TFT:
tmp |= CLCDC_LCDCTRL_TFT;
break;
default:
init = FALSE;
}
tmp |= CLCDC_LCDCTRL_RGB;
pregs->lcdctrl = tmp;
/* ADTFT and HRTFT setup */
if ((pcfg->lcd_panel_type == HRTFT) ||
(pcfg->lcd_panel_type == ADTFT))
{
/* Setup HR-TFT controller 'setup' register */
tmp = LCDICP_SETUP_PPL(pcfg->pixels_per_line) |
LCDICP_SETUP_MODE_HRTFT | LCDICP_SETUP_RESERVED |
LCDICP_SETUP_EN;
ptft->lcdicp_setup = tmp;
/* Setup HR-TFT controller 'control' register */
tmp = 0x00000000;
if (pcfg->hrtft_cls_enable != 0)
{
tmp |= LCDICP_CONTROL_CLSEN;
}
if (pcfg->hrtft_sps_enable != 0)
{
tmp |= LCDICP_CONTROL_SPSEN;
}
ptft->lcdicp_control = tmp;
/* Setup HR-TFT timing 1 register */
tmp = (LCDICP_TIMING1_LPDEL(pcfg->hrtft_lp_delay) |
LCDICP_TIMING1_REVDEL(pcfg->hrtft_polarity_delay) |
LCDICP_TIMING1_PS_CLSDEL(pcfg->hrtft_lp_to_ps_delay));
ptft->lcdicp_timing1 = tmp;
/* Setup HR-TFT timing 2 register */
tmp =
(LCDICP_TIMING2_PS_CLSDEL2(
pcfg->hrtft_spl_to_cls_delay) |
LCDICP_TIMING2_SPLVALUE(pcfg->hrtft_spl_delay));
ptft->lcdicp_timing2 = tmp;
}
else
{
/* Normal display type, set HRTFT bypass mode */
tmp = LCDICP_SETUP_MODE_BYPASS;
ptft->lcdicp_setup = tmp;
}
return (init);
}
/***********************************************************************
*
* Function: lcd_iocon_init
*
* Purpose: Enable muxed LCD controller pins.
*
* Processing:
* Select LCD pins in IOCON mux control registers.
*
* Parameters:
* none
*
* Outputs: None
*
* Returns: None
*
**********************************************************************/
static void lcd_iocon_init (void)
{
UNS_32 temp = 0;
temp = (IOCON_MUX_MASK(IOCON_RES1_PL1_LCDVD15) &
IOCON_MUX_MASK(IOCON_RES1_PL0_LCDVD14));
temp &= IOCON->mux_ctl_1;
temp |= (IOCON_MUX1_LCDVD14 | IOCON_MUX1_LCDVD15);
IOCON->mux_ctl_1 = temp;
temp = (IOCON_MUX_MASK(IOCON_RES19_PE6_LCDVEEN_LCDMOD) &
IOCON_MUX_MASK(IOCON_RES19_PE4_LCDSPLEN_LCDREV) &
IOCON_MUX_MASK(IOCON_RES19_PE5_LCDVDDEN) &
IOCON_MUX_MASK(IOCON_RES19_PE3_LCDCLS));
temp &= IOCON->mux_ctl_19;
temp |= (IOCON_MUX19_LCDMOD | IOCON_MUX19_LCDVDDEN |
IOCON_MUX19_LCDREV | IOCON_MUX19_LCDCLS);
IOCON->mux_ctl_19 = temp;
temp = (IOCON_MUX_MASK(IOCON_RES20_PE2_LCDPS) &
IOCON_MUX_MASK(IOCON_RES20_PE1_LCDDCLK) &
IOCON_MUX_MASK(IOCON_RES20_PE0_LCDLP_LCDHRLP) &
IOCON_MUX_MASK(IOCON_RES20_PF7_LCDFP_LCDSPS) &
IOCON_MUX_MASK(IOCON_RES20_PF6_LCDEN_LCDSPL));
temp &= IOCON->mux_ctl_20;
temp |= (IOCON_MUX20_LCDPS | IOCON_MUX20_LCDDCLK |
IOCON_MUX20_LCDHRLP | IOCON_MUX20_LCDSPS | IOCON_MUX20_LCDSPL);
IOCON->mux_ctl_20 = temp;
temp = (IOCON_MUX_MASK(IOCON_RES21_PF5_LCDVD11) &
IOCON_MUX_MASK(IOCON_RES21_PL3_LCDVD13) &
IOCON_MUX_MASK(IOCON_RES21_PF4_LCDVD10) &
IOCON_MUX_MASK(IOCON_RES21_PL2_LCDVD12) &
IOCON_MUX_MASK(IOCON_RES21_PF3_LCDVD9) &
IOCON_MUX_MASK(IOCON_RES21_PF2_LCDVD8));
temp &= IOCON->mux_ctl_21;
temp |= (IOCON_MUX21_LCDVD11 | IOCON_MUX21_LCDVD13 |
IOCON_MUX21_LCDVD10 | IOCON_MUX21_LCDVD12 |
IOCON_MUX21_LCDVD9 | IOCON_MUX21_LCDVD8);
IOCON->mux_ctl_21 = temp;
temp = (IOCON_MUX_MASK(IOCON_RES22_PF1_LCDVD7) &
IOCON_MUX_MASK(IOCON_RES22_PF0_LCDVD6) &
IOCON_MUX_MASK(IOCON_RES22_PG7_LCDVD5) &
IOCON_MUX_MASK(IOCON_RES22_PG6_LCDVD4) &
IOCON_MUX_MASK(IOCON_RES22_PG5_LCDVD3) &
IOCON_MUX_MASK(IOCON_RES22_PG4_LCDVD2) &
IOCON_MUX_MASK(IOCON_RES22_PG3_LCDVD1) &
IOCON_MUX_MASK(IOCON_RES22_PG2_LCDVD0));
temp &= IOCON->mux_ctl_22;
temp |= (IOCON_MUX22_LCDVD7 | IOCON_MUX22_LCDVD6 |
IOCON_MUX22_LCDVD5 | IOCON_MUX22_LCDVD4 |
IOCON_MUX22_LCDVD3 | IOCON_MUX22_LCDVD2 |
IOCON_MUX22_LCDVD1 | IOCON_MUX22_LCDVD0);
IOCON->mux_ctl_22 = temp;
}
/***********************************************************************
*
* Function: lcd_iocon_init_tft
*
* Purpose: Enable muxed LCD controller pins for tft panel.
*
* Processing:
* Select LCD pins in IOCON mux control registers.
*
* Parameters:
* none
*
* Outputs: None
*
* Returns: None
*
**********************************************************************/
static void lcd_iocon_init_tft (void)
{
UNS_32 temp = 0;
temp = (IOCON_MUX_MASK(IOCON_RES1_PL1_LCDVD15) &
IOCON_MUX_MASK(IOCON_RES1_PL0_LCDVD14));
temp &= IOCON->mux_ctl_1;
temp |= (IOCON_MUX1_LCDVD14 | IOCON_MUX1_LCDVD15);
IOCON->mux_ctl_1 = temp;
temp = (IOCON_MUX_MASK(IOCON_RES19_PE6_LCDVEEN_LCDMOD) &
IOCON_MUX_MASK(IOCON_RES19_PE4_LCDSPLEN_LCDREV) &
IOCON_MUX_MASK(IOCON_RES19_PE5_LCDVDDEN) &
IOCON_MUX_MASK(IOCON_RES19_PE3_LCDCLS));
temp &= IOCON->mux_ctl_19;
temp |= (IOCON_MUX19_LCDMOD | IOCON_MUX19_LCDVDDEN |
IOCON_MUX19_LCDREV | IOCON_MUX19_LCDCLS);
IOCON->mux_ctl_19 = temp;
temp = (IOCON_MUX_MASK(IOCON_RES20_PE2_LCDPS) &
IOCON_MUX_MASK(IOCON_RES20_PE1_LCDDCLK) &
IOCON_MUX_MASK(IOCON_RES20_PE0_LCDLP_LCDHRLP) &
IOCON_MUX_MASK(IOCON_RES20_PF7_LCDFP_LCDSPS) &
IOCON_MUX_MASK(IOCON_RES20_PF6_LCDEN_LCDSPL));
temp &= IOCON->mux_ctl_20;
temp |= (IOCON_MUX20_LCDPS | IOCON_MUX20_LCDDCLK |
IOCON_MUX20_LCDLP | IOCON_MUX20_LCDFP | IOCON_MUX20_LCDEN);
IOCON->mux_ctl_20 = temp;
temp = (IOCON_MUX_MASK(IOCON_RES21_PF5_LCDVD11) &
IOCON_MUX_MASK(IOCON_RES21_PL3_LCDVD13) &
IOCON_MUX_MASK(IOCON_RES21_PF4_LCDVD10) &
IOCON_MUX_MASK(IOCON_RES21_PL2_LCDVD12) &
IOCON_MUX_MASK(IOCON_RES21_PF3_LCDVD9) &
IOCON_MUX_MASK(IOCON_RES21_PF2_LCDVD8));
temp &= IOCON->mux_ctl_21;
temp |= (IOCON_MUX21_LCDVD11 | IOCON_MUX21_LCDVD13 |
IOCON_MUX21_LCDVD10 | IOCON_MUX21_LCDVD12 |
IOCON_MUX21_LCDVD9 | IOCON_MUX21_LCDVD8);
IOCON->mux_ctl_21 = temp;
temp = (IOCON_MUX_MASK(IOCON_RES22_PF1_LCDVD7) &
IOCON_MUX_MASK(IOCON_RES22_PF0_LCDVD6) &
IOCON_MUX_MASK(IOCON_RES22_PG7_LCDVD5) &
IOCON_MUX_MASK(IOCON_RES22_PG6_LCDVD4) &
IOCON_MUX_MASK(IOCON_RES22_PG5_LCDVD3) &
IOCON_MUX_MASK(IOCON_RES22_PG4_LCDVD2) &
IOCON_MUX_MASK(IOCON_RES22_PG3_LCDVD1) &
IOCON_MUX_MASK(IOCON_RES22_PG2_LCDVD0));
temp &= IOCON->mux_ctl_22;
temp |= (IOCON_MUX22_LCDVD7 | IOCON_MUX22_LCDVD6 |
IOCON_MUX22_LCDVD5 | IOCON_MUX22_LCDVD4 |
IOCON_MUX22_LCDVD3 | IOCON_MUX22_LCDVD2 |
IOCON_MUX22_LCDVD1 | IOCON_MUX22_LCDVD0);
IOCON->mux_ctl_22 = temp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -