@ -12,7 +12,11 @@
* SPDX - License - Identifier : GPL - 2.0 +
*/
# include <common.h>
# include <asm/io.h>
# include <asm/arch/hardware.h>
# include <asm/arch/omap.h>
# include <asm/arch/clock.h>
# include <asm/arch/sys_proto.h>
# include <lcd.h>
# include "am335x-fb.h"
@ -20,6 +24,7 @@
# error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!"
# endif
# define LCDC_FMAX 200000000
/* LCD Control Register */
# define LCD_CLK_DIVISOR(x) ((x) << 8)
@ -96,6 +101,7 @@ struct am335x_lcdhw {
} ;
static struct am335x_lcdhw * lcdhw = ( void * ) LCD_CNTL_BASE ;
DECLARE_GLOBAL_DATA_PTR ;
int lcd_get_size ( int * line_length )
@ -108,6 +114,11 @@ int am335xfb_init(struct am335x_lcdpanel *panel)
{
u32 raster_ctrl = 0 ;
struct cm_dpll * const cmdpll = ( struct cm_dpll * ) CM_DPLL ;
struct dpll_params dpll_disp = { 1 , 0 , 1 , - 1 , - 1 , - 1 , - 1 } ;
unsigned int m , n , d , best_d = 2 ;
int err = 0 , err_r = 0 ;
if ( gd - > fb_base = = 0 ) {
printf ( " ERROR: no valid fb_base stored in GLOBAL_DATA_PTR! \n " ) ;
return - 1 ;
@ -132,14 +143,51 @@ int am335xfb_init(struct am335x_lcdpanel *panel)
return - 1 ;
}
/* check given clock-frequency */
if ( panel - > pxl_clk > ( LCDC_FMAX / 2 ) ) {
pr_err ( " am335x-fb: requested pxl-clk: %d not supported! \n " ,
panel - > pxl_clk ) ;
return - 1 ;
}
debug ( " setting up LCD-Controller for %dx%dx%d (hfp=%d,hbp=%d,hsw=%d / " ,
panel - > hactive , panel - > vactive , panel - > bpp ,
panel - > hfp , panel - > hbp , panel - > hsw ) ;
debug ( " vfp=%d,vbp=%d,vsw=%d / clk-div=%d) \n " ,
panel - > vfp , panel - > vfp , panel - > vsw , panel - > pxl_clk_div ) ;
debug ( " vfp=%d,vbp=%d,vsw=%d / clk=%d) \n " ,
panel - > vfp , panel - > vfp , panel - > vsw , panel - > pxl_clk ) ;
debug ( " using frambuffer at 0x%08x with size %d. \n " ,
( unsigned int ) gd - > fb_base , FBSIZE ( panel ) ) ;
/* setup display pll for requested clock frequency */
err = panel - > pxl_clk ;
err_r = err ;
for ( d = 2 ; d < 255 ; d + + ) {
for ( m = 2 ; m < 2047 ; m + + ) {
if ( ( V_OSCK * m ) < ( panel - > pxl_clk * d ) )
continue ;
n = ( V_OSCK * m ) / ( panel - > pxl_clk * d ) ;
if ( n > 127 )
break ;
if ( ( ( V_OSCK * m ) / n ) > LCDC_FMAX )
break ;
err = abs ( ( V_OSCK * m ) / n / d - panel - > pxl_clk ) ;
if ( err < err_r ) {
err_r = err ;
dpll_disp . m = m ;
dpll_disp . n = n ;
best_d = d ;
}
}
}
debug ( " %s: PLL: best error %d Hz (M %d, N %d, DISP %d) \n " ,
__func__ , err_r , dpll_disp . m , dpll_disp . n , best_d ) ;
do_setup_dpll ( & dpll_disp_regs , & dpll_disp ) ;
/* clock source for LCDC from dispPLL M2 */
writel ( 0x0 , & cmdpll - > clklcdcpixelclk ) ;
/* palette default entry */
memset ( ( void * ) gd - > fb_base , 0 , 0x20 ) ;
* ( unsigned int * ) gd - > fb_base = 0x4000 ;
@ -154,7 +202,7 @@ int am335xfb_init(struct am335x_lcdpanel *panel)
mdelay ( panel - > pup_delay ) ;
lcdhw - > clkc_enable = LCD_CORECLKEN | LCD_LIDDCLKEN | LCD_DMACLKEN ;
lcdhw - > raster_ctrl = 0 ;
lcdhw - > ctrl = LCD_CLK_DIVISOR ( panel - > pxl_clk_div ) | LCD_RASTER_MODE ;
lcdhw - > ctrl = LCD_CLK_DIVISOR ( best_d ) | LCD_RASTER_MODE ;
lcdhw - > lcddma_fb0_base = gd - > fb_base ;
lcdhw - > lcddma_fb0_ceiling = gd - > fb_base + FBSIZE ( panel ) ;
lcdhw - > lcddma_fb1_base = gd - > fb_base ;