From 87dac71d6d6bb1ee639f7db663dae59bc6db72b5 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:20 -0500 Subject: video: da8xx-fb: fb_check_var enhancement Check whether "struct fb_var_screeninfo" fields are sane, if not update it to be within allowed limits. If user sends down buggy "var" values, this will bring those within allowable limits. And fb_set_par is not supposed to change "var" values, fb_check_var has to ensure that values are proper. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 0810939936f4..d00dd173e3af 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -888,6 +888,9 @@ static int fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { int err = 0; + struct da8xx_fb_par *par = info->par; + int bpp = var->bits_per_pixel >> 3; + unsigned long line_size = var->xres_virtual * bpp; if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1) return -EINVAL; @@ -955,6 +958,21 @@ static int fb_check_var(struct fb_var_screeninfo *var, var->green.msb_right = 0; var->blue.msb_right = 0; var->transp.msb_right = 0; + + if (line_size * var->yres_virtual > par->vram_size) + var->yres_virtual = par->vram_size / line_size; + + if (var->yres > var->yres_virtual) + var->yres = var->yres_virtual; + + if (var->xres > var->xres_virtual) + var->xres = var->xres_virtual; + + if (var->xres + var->xoffset > var->xres_virtual) + var->xoffset = var->xres_virtual - var->xres; + if (var->yres + var->yoffset > var->yres_virtual) + var->yoffset = var->yres_virtual - var->yres; + return err; } -- cgit v1.2.3 From 39c87d45b24231619440c83376a415a759130360 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:21 -0500 Subject: video: da8xx-fb: simplify lcd_reset lcd_reset function doesn't require any arguement, remove it. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index d00dd173e3af..52977b14425f 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -681,7 +681,7 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, } #undef CNVT_TOHW -static void lcd_reset(struct da8xx_fb_par *par) +static void da8xx_fb_lcd_reset(void) { /* Disable the Raster if previously Enabled */ lcd_disable_raster(false); @@ -721,7 +721,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, u32 bpp; int ret = 0; - lcd_reset(par); + da8xx_fb_lcd_reset(); /* Calculate the divider */ lcd_calc_clk_divider(par); -- cgit v1.2.3 From b866458b12f95ffff908b4bcc2be338705facc1d Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:22 -0500 Subject: video: da8xx-fb: use modedb helper to update var modedb structure is now used to store panel information, run modedb helper over it for initial update of "var" information instead of equating each fields. While at it, remove redundant update of bits_per_pixel. Note: pixclock is overridden with proper value using an existing code as currently modedb is having it in Hz instead of ps, this would be fixed in a later change and this overide would be removed. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 52977b14425f..a1f65444b580 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -1329,6 +1329,8 @@ static int fb_probe(struct platform_device *device) par->panel_power_ctrl(1); } + fb_videomode_to_var(&da8xx_fb_var, lcdc_info); + if (lcd_init(par, lcd_cfg, lcdc_info) < 0) { dev_err(&device->dev, "lcd_init failed\n"); ret = -EFAULT; @@ -1381,25 +1383,9 @@ static int fb_probe(struct platform_device *device) goto err_release_pl_mem; } - /* Initialize par */ - da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; - - da8xx_fb_var.xres = lcdc_info->xres; - da8xx_fb_var.xres_virtual = lcdc_info->xres; - - da8xx_fb_var.yres = lcdc_info->yres; - da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS; - da8xx_fb_var.grayscale = lcd_cfg->panel_shade == MONOCHROME ? 1 : 0; da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; - - da8xx_fb_var.hsync_len = lcdc_info->hsync_len; - da8xx_fb_var.vsync_len = lcdc_info->vsync_len; - da8xx_fb_var.right_margin = lcdc_info->right_margin; - da8xx_fb_var.left_margin = lcdc_info->left_margin; - da8xx_fb_var.lower_margin = lcdc_info->lower_margin; - da8xx_fb_var.upper_margin = lcdc_info->upper_margin; da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par); /* Initialize fbinfo */ -- cgit v1.2.3 From be0f6dbca39036213893d8b83a7779d96844c144 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:23 -0500 Subject: video: da8xx-fb: remove unneeded "var" initialization modedb helper now updates "var" information based on the detected panel, remove the unnecessary initialization. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index a1f65444b580..18834faabc33 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -131,10 +131,6 @@ #define WSI_TIMEOUT 50 #define PALETTE_SIZE 256 -#define LEFT_MARGIN 64 -#define RIGHT_MARGIN 64 -#define UPPER_MARGIN 32 -#define LOWER_MARGIN 32 static void __iomem *da8xx_fb_reg_base; static struct resource *lcdc_regs; @@ -184,23 +180,7 @@ struct da8xx_fb_par { u32 pseudo_palette[16]; }; -/* Variable Screen Information */ -static struct fb_var_screeninfo da8xx_fb_var = { - .xoffset = 0, - .yoffset = 0, - .transp = {0, 0, 0}, - .nonstd = 0, - .activate = 0, - .height = -1, - .width = -1, - .accel_flags = 0, - .left_margin = LEFT_MARGIN, - .right_margin = RIGHT_MARGIN, - .upper_margin = UPPER_MARGIN, - .lower_margin = LOWER_MARGIN, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED -}; +static struct fb_var_screeninfo da8xx_fb_var; static struct fb_fix_screeninfo da8xx_fb_fix = { .id = "DA8xx FB Drv", -- cgit v1.2.3 From b6dbe8e4d578997711097c77fb4538c00a541b62 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:24 -0500 Subject: video: da8xx-fb: store current display information store current videomode and controller data so that reconfiguring can be done easily. Reconfiguring would be required in fb_set_par, which is going to be added soon. If these details are not stored, the work probe does to retrieve these information would have to repeated at the place of reconfiguring and modifying platform data would be necessary to handle controller data changes like bpp. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 18834faabc33..d060f14b888d 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -178,6 +178,8 @@ struct da8xx_fb_par { #endif void (*panel_power_ctrl)(int); u32 pseudo_palette[16]; + struct fb_videomode mode; + struct lcd_ctrl_config cfg; }; static struct fb_var_screeninfo da8xx_fb_var; @@ -1310,6 +1312,8 @@ static int fb_probe(struct platform_device *device) } fb_videomode_to_var(&da8xx_fb_var, lcdc_info); + fb_var_to_videomode(&par->mode, &da8xx_fb_var); + par->cfg = *lcd_cfg; if (lcd_init(par, lcd_cfg, lcdc_info) < 0) { dev_err(&device->dev, "lcd_init failed\n"); -- cgit v1.2.3 From 44f627ae6967dbb0555ab75bcf737bfe8fa2d844 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:25 -0500 Subject: video: da8xx-fb: store clk rate even if !CPUFREQ store lcd clk rate always, i.e. irrespective of whether CPUFREQ is enabled or not. This can be used to get clk rate directly instead of enquiring with clock framework with clk handle every time. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index d060f14b888d..f1d88ac986da 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -174,8 +174,8 @@ struct da8xx_fb_par { unsigned int which_dma_channel_done; #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; - unsigned int lcd_fck_rate; #endif + unsigned int lcd_fck_rate; void (*panel_power_ctrl)(int); u32 pseudo_palette[16]; struct fb_videomode mode; @@ -1302,9 +1302,7 @@ static int fb_probe(struct platform_device *device) par = da8xx_fb_info->par; par->lcdc_clk = fb_clk; -#ifdef CONFIG_CPU_FREQ par->lcd_fck_rate = clk_get_rate(fb_clk); -#endif par->pxl_clk = lcdc_info->pixclock; if (fb_pdata->panel_power_ctrl) { par->panel_power_ctrl = fb_pdata->panel_power_ctrl; -- cgit v1.2.3 From a6a799f8a83cf018d8d352b0b5bfc9b8bbcdda3c Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Mon, 5 Aug 2013 17:02:26 -0500 Subject: video: da8xx-fb: pix clk and clk div handling cleanup Based on original patch by: Afzal Mohammed Use the new modedb field to store pix clk. Reorganize existing clock divider functions with names now corresponding to what they do, add common function prefix. Fix existing panel modedb pixclock to be in ps instead of Hz. This needed a change in the way clock divider is calculated. As modedb pixclock information is now in ps, override on "var" pixclock over modedb to var conversion is removed. v2: Changed pixel clock configuration to use KHZ2PICOS macro Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 48 ++++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index f1d88ac986da..0fac1a0c8e55 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -160,7 +160,6 @@ struct da8xx_fb_par { struct clk *lcdc_clk; int irq; unsigned int palette_sz; - unsigned int pxl_clk; int blank; wait_queue_head_t vsync_wait; int vsync_flag; @@ -201,7 +200,7 @@ static struct fb_videomode known_lcd_panels[] = { .name = "Sharp_LCD035Q3DG01", .xres = 320, .yres = 240, - .pixclock = 4608000, + .pixclock = KHZ2PICOS(4607), .left_margin = 6, .right_margin = 8, .upper_margin = 2, @@ -216,7 +215,7 @@ static struct fb_videomode known_lcd_panels[] = { .name = "Sharp_LK043T1DG01", .xres = 480, .yres = 272, - .pixclock = 7833600, + .pixclock = KHZ2PICOS(7833), .left_margin = 2, .right_margin = 2, .upper_margin = 2, @@ -231,7 +230,7 @@ static struct fb_videomode known_lcd_panels[] = { .name = "SP10Q010", .xres = 320, .yres = 240, - .pixclock = 7833600, + .pixclock = KHZ2PICOS(7833), .left_margin = 10, .right_margin = 10, .upper_margin = 10, @@ -680,13 +679,14 @@ static void da8xx_fb_lcd_reset(void) } } -static void lcd_calc_clk_divider(struct da8xx_fb_par *par) +static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par, + unsigned pixclock) { - unsigned int lcd_clk, div; - - lcd_clk = clk_get_rate(par->lcdc_clk); - div = lcd_clk / par->pxl_clk; + return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000); +} +static inline void da8xx_fb_config_clk_divider(unsigned div) +{ /* Configure the LCD clock divisor. */ lcdc_write(LCD_CLK_DIVISOR(div) | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); @@ -694,7 +694,14 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par) if (lcd_revision == LCD_VERSION_2) lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); +} + +static inline void da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par, + struct fb_videomode *mode) +{ + unsigned div = da8xx_fb_calc_clk_divider(par, mode->pixclock); + da8xx_fb_config_clk_divider(div); } static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, @@ -705,8 +712,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, da8xx_fb_lcd_reset(); - /* Calculate the divider */ - lcd_calc_clk_divider(par); + da8xx_fb_calc_config_clk_divider(par, panel); if (panel->sync & FB_SYNC_CLK_INVERT) lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | @@ -969,7 +975,7 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb, if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) { par->lcd_fck_rate = clk_get_rate(par->lcdc_clk); lcd_disable_raster(true); - lcd_calc_clk_divider(par); + da8xx_fb_calc_config_clk_divider(par, &par->mode); if (par->blank == FB_BLANK_UNBLANK) lcd_enable_raster(); } @@ -1195,22 +1201,6 @@ static struct fb_ops da8xx_fb_ops = { .fb_blank = cfb_blank, }; -/* Calculate and return pixel clock period in pico seconds */ -static unsigned int da8xxfb_pixel_clk_period(struct da8xx_fb_par *par) -{ - unsigned int lcd_clk, div; - unsigned int configured_pix_clk; - unsigned long long pix_clk_period_picosec = 1000000000000ULL; - - lcd_clk = clk_get_rate(par->lcdc_clk); - div = lcd_clk / par->pxl_clk; - configured_pix_clk = (lcd_clk / div); - - do_div(pix_clk_period_picosec, configured_pix_clk); - - return pix_clk_period_picosec; -} - static int fb_probe(struct platform_device *device) { struct da8xx_lcdc_platform_data *fb_pdata = @@ -1303,7 +1293,6 @@ static int fb_probe(struct platform_device *device) par = da8xx_fb_info->par; par->lcdc_clk = fb_clk; par->lcd_fck_rate = clk_get_rate(fb_clk); - par->pxl_clk = lcdc_info->pixclock; if (fb_pdata->panel_power_ctrl) { par->panel_power_ctrl = fb_pdata->panel_power_ctrl; par->panel_power_ctrl(1); @@ -1368,7 +1357,6 @@ static int fb_probe(struct platform_device *device) da8xx_fb_var.grayscale = lcd_cfg->panel_shade == MONOCHROME ? 1 : 0; da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; - da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par); /* Initialize fbinfo */ da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; -- cgit v1.2.3 From dbe8e48a3c70531b3befb11035dec30aec48c450 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:27 -0500 Subject: video: da8xx-fb: store struct device * store struct device pointer so that dev_dbg/err can be used outside of probe. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 0fac1a0c8e55..7db109733fa1 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -150,6 +150,7 @@ static inline void lcdc_write(unsigned int val, unsigned int addr) } struct da8xx_fb_par { + struct device *dev; resource_size_t p_palette_base; unsigned char *v_palette_base; dma_addr_t vram_phys; @@ -1291,6 +1292,7 @@ static int fb_probe(struct platform_device *device) } par = da8xx_fb_info->par; + par->dev = &device->dev; par->lcdc_clk = fb_clk; par->lcd_fck_rate = clk_get_rate(fb_clk); if (fb_pdata->panel_power_ctrl) { -- cgit v1.2.3 From 404fdfe7f428c6425a13e96d0b56537eb67e08c5 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:28 -0500 Subject: video: da8xx-fb: report correct pixclock Update "var" pixclock with the value that is configurable in hardware. This lets user know the actual pixclock. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 7db109733fa1..8d737305a43b 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -686,6 +686,15 @@ static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par, return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000); } +static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par, + unsigned pixclock) +{ + unsigned div; + + div = da8xx_fb_calc_clk_divider(par, pixclock); + return KHZ2PICOS(par->lcd_fck_rate / (1000 * div)); +} + static inline void da8xx_fb_config_clk_divider(unsigned div) { /* Configure the LCD clock divisor. */ @@ -962,6 +971,8 @@ static int fb_check_var(struct fb_var_screeninfo *var, if (var->yres + var->yoffset > var->yres_virtual) var->yoffset = var->yres_virtual - var->yres; + var->pixclock = da8xx_fb_round_clk(par, var->pixclock); + return err; } -- cgit v1.2.3 From fe8c98f06b5eec94d318cd4761e7673fb5e3c662 Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Mon, 5 Aug 2013 17:02:29 -0500 Subject: video: da8xx-fb: fb_set_par support v1: original from Afzal Mohammed fb_set_par helps in runtime configuration of lcd controller like changing resolution, pixel clock etc. (eg. using fbset utility) Reconfigure lcd controller based on information passed by framework. Enable raster back if it was already enabled. As fb_set_par would get invoked indirectly from probe via fb_set_var, remove existing lcdc initialization in probe and do lcdc reset in probe so that reset happens only at the begining. v2: changes from Darren Etheridge remove unnecessary conditional branch where we attempt to disable something that we already checked to see if it was disabled. Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 58 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 11 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 8d737305a43b..6beb88d7b7d7 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -243,6 +243,11 @@ static struct fb_videomode known_lcd_panels[] = { }, }; +static inline bool da8xx_fb_is_raster_enabled(void) +{ + return !!(lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE); +} + /* Enable the Raster Engine of the LCD Controller */ static inline void lcd_enable_raster(void) { @@ -665,9 +670,6 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, static void da8xx_fb_lcd_reset(void) { - /* Disable the Raster if previously Enabled */ - lcd_disable_raster(false); - /* DMA has to be disabled */ lcdc_write(0, LCD_DMA_CTRL_REG); lcdc_write(0, LCD_RASTER_CTRL_REG); @@ -720,8 +722,6 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, u32 bpp; int ret = 0; - da8xx_fb_lcd_reset(); - da8xx_fb_calc_config_clk_divider(par, panel); if (panel->sync & FB_SYNC_CLK_INVERT) @@ -1201,9 +1201,50 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var, return ret; } +static int da8xxfb_set_par(struct fb_info *info) +{ + struct da8xx_fb_par *par = info->par; + int ret; + bool raster = da8xx_fb_is_raster_enabled(); + + if (raster) + lcd_disable_raster(true); + + fb_var_to_videomode(&par->mode, &info->var); + + par->cfg.bpp = info->var.bits_per_pixel; + + info->fix.visual = (par->cfg.bpp <= 8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + info->fix.line_length = (par->mode.xres * par->cfg.bpp) / 8; + + ret = lcd_init(par, &par->cfg, &par->mode); + if (ret < 0) { + dev_err(par->dev, "lcd init failed\n"); + return ret; + } + + par->dma_start = info->fix.smem_start + + info->var.yoffset * info->fix.line_length + + info->var.xoffset * info->var.bits_per_pixel / 8; + par->dma_end = par->dma_start + + info->var.yres * info->fix.line_length - 1; + + lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); + lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); + lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); + lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); + + if (raster) + lcd_enable_raster(); + + return 0; +} + static struct fb_ops da8xx_fb_ops = { .owner = THIS_MODULE, .fb_check_var = fb_check_var, + .fb_set_par = da8xxfb_set_par, .fb_setcolreg = fb_setcolreg, .fb_pan_display = da8xx_pan_display, .fb_ioctl = fb_ioctl, @@ -1312,14 +1353,9 @@ static int fb_probe(struct platform_device *device) } fb_videomode_to_var(&da8xx_fb_var, lcdc_info); - fb_var_to_videomode(&par->mode, &da8xx_fb_var); par->cfg = *lcd_cfg; - if (lcd_init(par, lcd_cfg, lcdc_info) < 0) { - dev_err(&device->dev, "lcd_init failed\n"); - ret = -EFAULT; - goto err_release_fb; - } + da8xx_fb_lcd_reset(); /* allocate frame buffer */ par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp; -- cgit v1.2.3 From 26e7164537380479bf96e852df6ab42ebe50e836 Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Mon, 5 Aug 2013 17:02:30 -0500 Subject: video: da8xx-fb: improve readability of code Change the lcd_disable_raster funtion from using a bool to an enum as the function is very confusing with the current api. This helps make it clearer what the parameter is really doing. Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 24 +++++++++++++----------- include/video/da8xx-fb.h | 5 +++++ 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 6beb88d7b7d7..93753828eb08 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -271,7 +271,8 @@ static inline void lcd_enable_raster(void) } /* Disable the Raster Engine of the LCD Controller */ -static inline void lcd_disable_raster(bool wait_for_frame_done) +static inline void lcd_disable_raster(enum da8xx_frame_complete + wait_for_frame_done) { u32 reg; int ret; @@ -283,7 +284,8 @@ static inline void lcd_disable_raster(bool wait_for_frame_done) /* return if already disabled */ return; - if ((wait_for_frame_done == true) && (lcd_revision == LCD_VERSION_2)) { + if ((wait_for_frame_done == DA8XX_FRAME_WAIT) && + (lcd_revision == LCD_VERSION_2)) { frame_done_flag = 0; ret = wait_event_interruptible_timeout(frame_done_wq, frame_done_flag != 0, @@ -771,7 +773,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) u32 stat = lcdc_read(LCD_MASKED_STAT_REG); if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { - lcd_disable_raster(false); + lcd_disable_raster(DA8XX_FRAME_NOWAIT); lcdc_write(stat, LCD_MASKED_STAT_REG); lcd_enable_raster(); } else if (stat & LCD_PL_LOAD_DONE) { @@ -781,7 +783,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) * interrupt via the following write to the status register. If * this is done after then one gets multiple PL done interrupts. */ - lcd_disable_raster(false); + lcd_disable_raster(DA8XX_FRAME_NOWAIT); lcdc_write(stat, LCD_MASKED_STAT_REG); @@ -834,7 +836,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) u32 reg_ras; if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { - lcd_disable_raster(false); + lcd_disable_raster(DA8XX_FRAME_NOWAIT); lcdc_write(stat, LCD_STAT_REG); lcd_enable_raster(); } else if (stat & LCD_PL_LOAD_DONE) { @@ -844,7 +846,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) * interrupt via the following write to the status register. If * this is done after then one gets multiple PL done interrupts. */ - lcd_disable_raster(false); + lcd_disable_raster(DA8XX_FRAME_NOWAIT); lcdc_write(stat, LCD_STAT_REG); @@ -986,7 +988,7 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb, if (val == CPUFREQ_POSTCHANGE) { if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) { par->lcd_fck_rate = clk_get_rate(par->lcdc_clk); - lcd_disable_raster(true); + lcd_disable_raster(DA8XX_FRAME_WAIT); da8xx_fb_calc_config_clk_divider(par, &par->mode); if (par->blank == FB_BLANK_UNBLANK) lcd_enable_raster(); @@ -1024,7 +1026,7 @@ static int fb_remove(struct platform_device *dev) if (par->panel_power_ctrl) par->panel_power_ctrl(0); - lcd_disable_raster(true); + lcd_disable_raster(DA8XX_FRAME_WAIT); lcdc_write(0, LCD_RASTER_CTRL_REG); /* disable DMA */ @@ -1140,7 +1142,7 @@ static int cfb_blank(int blank, struct fb_info *info) if (par->panel_power_ctrl) par->panel_power_ctrl(0); - lcd_disable_raster(true); + lcd_disable_raster(DA8XX_FRAME_WAIT); break; default: ret = -EINVAL; @@ -1208,7 +1210,7 @@ static int da8xxfb_set_par(struct fb_info *info) bool raster = da8xx_fb_is_raster_enabled(); if (raster) - lcd_disable_raster(true); + lcd_disable_raster(DA8XX_FRAME_WAIT); fb_var_to_videomode(&par->mode, &info->var); @@ -1569,7 +1571,7 @@ static int fb_suspend(struct platform_device *dev, pm_message_t state) par->panel_power_ctrl(0); fb_set_suspend(info, 1); - lcd_disable_raster(true); + lcd_disable_raster(DA8XX_FRAME_WAIT); lcd_context_save(); pm_runtime_put_sync(&dev->dev); console_unlock(); diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h index f88825928dd1..efed3c3383d6 100644 --- a/include/video/da8xx-fb.h +++ b/include/video/da8xx-fb.h @@ -23,6 +23,11 @@ enum raster_load_mode { LOAD_PALETTE, }; +enum da8xx_frame_complete { + DA8XX_FRAME_WAIT, + DA8XX_FRAME_NOWAIT, +}; + struct da8xx_lcdc_platform_data { const char manu_name[10]; void *controller_data; -- cgit v1.2.3 From fa8a00cc732fbd890bb4ac5af237ac6774c9545b Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Mon, 5 Aug 2013 17:02:31 -0500 Subject: video: da8xx-fb: fix 24bpp raster configuration Based on original patch by: Manjunathappa, Prakash and Afzal Mohammed Set only LCD_V2_TFT_24BPP_MODE bit for 24bpp and LCD_V2_TFT_24BPP_UNPACK bit along with LCD_V2_TFT_24BPP_MODE for 32bpp configuration. Patch is tested on am335x-evm for 24bpp and da850-evm for 16bpp configurations. v2: removes confusing fall through in case statement for pixel depth configuration. Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 93753828eb08..893aefe25478 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -554,10 +554,11 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, break; case 24: reg |= LCD_V2_TFT_24BPP_MODE; + break; case 32: + reg |= LCD_V2_TFT_24BPP_MODE; reg |= LCD_V2_TFT_24BPP_UNPACK; break; - case 8: par->palette_sz = 256 * 2; break; -- cgit v1.2.3 From e4008e2240605a64d595f3b9e070bfaf5a6950ff Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:32 -0500 Subject: video: da8xx-fb: enable sync lost intr for v2 ip The interrupt handler explicitly has code that handles the sync lost interrupt. However the sync lost interrupt is never actually being enabled in the LCD controller, therefore this interrupt code path is not being exercised. This fix simply enables the generation of the sync lost interrupt by the LCD controller so it can be dealt with appropriately by the interrupt handler. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 893aefe25478..8384455164d7 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -320,7 +320,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | LCD_V2_END_OF_FRAME0_INT_ENA | LCD_V2_END_OF_FRAME1_INT_ENA | - LCD_FRAME_DONE; + LCD_FRAME_DONE | LCD_SYNC_LOST; lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); } reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; -- cgit v1.2.3 From c45757f0f2c7655ae838e0f500c99794bdd6f33a Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Mon, 5 Aug 2013 17:02:33 -0500 Subject: video: da8xx-fb: use devres Replace existing resource handling in the driver with managed device resource. v2: implement some changes as recommended by Prabhakar Lad Signed-off-by: Lad, Prabhakar Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 8384455164d7..c620a32e5ac9 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -133,7 +133,6 @@ #define PALETTE_SIZE 256 static void __iomem *da8xx_fb_reg_base; -static struct resource *lcdc_regs; static unsigned int lcd_revision; static irq_handler_t lcdc_irq_handler; static wait_queue_head_t frame_done_wq; @@ -1039,12 +1038,9 @@ static int fb_remove(struct platform_device *dev) par->p_palette_base); dma_free_coherent(NULL, par->vram_size, par->vram_virt, par->vram_phys); - free_irq(par->irq, par); pm_runtime_put_sync(&dev->dev); pm_runtime_disable(&dev->dev); framebuffer_release(info); - iounmap(da8xx_fb_reg_base); - release_mem_region(lcdc_regs->start, resource_size(lcdc_regs)); } return 0; @@ -1261,12 +1257,12 @@ static int fb_probe(struct platform_device *device) { struct da8xx_lcdc_platform_data *fb_pdata = device->dev.platform_data; + static struct resource *lcdc_regs; struct lcd_ctrl_config *lcd_cfg; struct fb_videomode *lcdc_info; struct fb_info *da8xx_fb_info; struct clk *fb_clk = NULL; struct da8xx_fb_par *par; - resource_size_t len; int ret, i; unsigned long ulcm; @@ -1276,29 +1272,14 @@ static int fb_probe(struct platform_device *device) } lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); - if (!lcdc_regs) { - dev_err(&device->dev, - "Can not get memory resource for LCD controller\n"); - return -ENOENT; - } - - len = resource_size(lcdc_regs); - - lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name); - if (!lcdc_regs) - return -EBUSY; + da8xx_fb_reg_base = devm_ioremap_resource(&device->dev, lcdc_regs); + if (IS_ERR(da8xx_fb_reg_base)) + return PTR_ERR(da8xx_fb_reg_base); - da8xx_fb_reg_base = ioremap(lcdc_regs->start, len); - if (!da8xx_fb_reg_base) { - ret = -EBUSY; - goto err_request_mem; - } - - fb_clk = clk_get(&device->dev, "fck"); + fb_clk = devm_clk_get(&device->dev, "fck"); if (IS_ERR(fb_clk)) { dev_err(&device->dev, "Can not get device clock\n"); - ret = -ENODEV; - goto err_ioremap; + return PTR_ERR(fb_clk); } pm_runtime_enable(&device->dev); @@ -1459,8 +1440,8 @@ static int fb_probe(struct platform_device *device) lcdc_irq_handler = lcdc_irq_handler_rev02; } - ret = request_irq(par->irq, lcdc_irq_handler, 0, - DRIVER_NAME, par); + ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0, + DRIVER_NAME, par); if (ret) goto irq_freq; return 0; @@ -1489,12 +1470,6 @@ err_pm_runtime_disable: pm_runtime_put_sync(&device->dev); pm_runtime_disable(&device->dev); -err_ioremap: - iounmap(da8xx_fb_reg_base); - -err_request_mem: - release_mem_region(lcdc_regs->start, len); - return ret; } -- cgit v1.2.3 From 3a58101da20b409984e608811bc2dd828f1e8c96 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:34 -0500 Subject: video: da8xx-fb: ensure non-null cfg in pdata Ensure that platform data contains pointer for lcd_ctrl_config. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index c620a32e5ac9..dec27777a931 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -1319,6 +1319,11 @@ static int fb_probe(struct platform_device *device) lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; + if (!lcd_cfg) { + ret = -EINVAL; + goto err_pm_runtime_disable; + } + da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), &device->dev); if (!da8xx_fb_info) { -- cgit v1.2.3 From 2bdff0680f00ef4d2448b8d20d61a3554b368c24 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 5 Aug 2013 17:02:35 -0500 Subject: video: da8xx-fb: reorganize panel detection Move panel detection to a separate function, this helps in readability as well as makes DT support cleaner. Signed-off-by: Afzal Mohammed Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index dec27777a931..d8b295ab85f5 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -1253,6 +1253,27 @@ static struct fb_ops da8xx_fb_ops = { .fb_blank = cfb_blank, }; +static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev) +{ + struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data; + struct fb_videomode *lcdc_info; + int i; + + for (i = 0, lcdc_info = known_lcd_panels; + i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) { + if (strcmp(fb_pdata->type, lcdc_info->name) == 0) + break; + } + + if (i == ARRAY_SIZE(known_lcd_panels)) { + dev_err(&dev->dev, "no panel found\n"); + return NULL; + } + dev_info(&dev->dev, "found %s panel\n", lcdc_info->name); + + return lcdc_info; +} + static int fb_probe(struct platform_device *device) { struct da8xx_lcdc_platform_data *fb_pdata = @@ -1263,7 +1284,7 @@ static int fb_probe(struct platform_device *device) struct fb_info *da8xx_fb_info; struct clk *fb_clk = NULL; struct da8xx_fb_par *par; - int ret, i; + int ret; unsigned long ulcm; if (fb_pdata == NULL) { @@ -1271,6 +1292,10 @@ static int fb_probe(struct platform_device *device) return -ENOENT; } + lcdc_info = da8xx_fb_get_videomode(device); + if (lcdc_info == NULL) + return -ENODEV; + lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); da8xx_fb_reg_base = devm_ioremap_resource(&device->dev, lcdc_regs); if (IS_ERR(da8xx_fb_reg_base)) @@ -1302,21 +1327,6 @@ static int fb_probe(struct platform_device *device) break; } - for (i = 0, lcdc_info = known_lcd_panels; - i < ARRAY_SIZE(known_lcd_panels); - i++, lcdc_info++) { - if (strcmp(fb_pdata->type, lcdc_info->name) == 0) - break; - } - - if (i == ARRAY_SIZE(known_lcd_panels)) { - dev_err(&device->dev, "GLCD: No valid panel found\n"); - ret = -ENODEV; - goto err_pm_runtime_disable; - } else - dev_info(&device->dev, "GLCD: Found %s panel\n", - fb_pdata->type); - lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; if (!lcd_cfg) { -- cgit v1.2.3 From 2dfa77a2010fc65de131ef7f7454844df9182735 Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Mon, 5 Aug 2013 17:02:36 -0500 Subject: video: da8xx-fb: set upstream clock rate (if reqd) Based on original patch by: Afzal Mohammed LCDC IP has a clock divider to adjust pixel clock, this limits pixel clock range to fck/255 - fck/2(fck - rate of input clock to LCDC IP). In the case of AM335x, where this IP is present, default fck is not sufficient to provide normal pixel clock rates, hence rendering this driver unusable on AM335x. If input clock too is configurable, allowable range of pixel clock would increase. Here initially it is checked whether with present fck, divider in IP could be configured to obtain required rate, if not, fck is adjusted. This makes it usable on AM335x. Note: Another solution would be to model an inherited basic clock divider of CCF, an advantage would be a better possible resolution for pixel clk. And trying to instantiate a CCF clock would mean that to be consistent, 3 bits being turned on to enable clocks of LCDC IP would have to be modeled as gate clocks. Now that would bring in a total of 4 clocks, including necessity to create a new inherited divider clock, and that mean a branch of clock tree would be present in LCDC driver. This would add complexity to LCDC driver bringing in considerable amount of clock handling code, and this would not bring in much advantage for existing use cases other than providing a higher resolution of pixel clock. And existing use cases work without relying on clock modeling. Another fact is that out of the two platform's using this driver DaVinci is not yet converted to CCF. In future if higher resolution of pixel clock is required, and probably after DaVinci is CCF'ed, modeling clock nodes inside driver may be considered. v2: purely cosmetic changes to try and clarify what variables are being used for in the clock rate / divider calculations Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 85 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 20 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index d8b295ab85f5..dfe757254e26 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -132,6 +132,9 @@ #define WSI_TIMEOUT 50 #define PALETTE_SIZE 256 +#define CLK_MIN_DIV 2 +#define CLK_MAX_DIV 255 + static void __iomem *da8xx_fb_reg_base; static unsigned int lcd_revision; static irq_handler_t lcdc_irq_handler; @@ -684,38 +687,76 @@ static void da8xx_fb_lcd_reset(void) } } -static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par, - unsigned pixclock) -{ - return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000); -} - -static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par, - unsigned pixclock) +static int da8xx_fb_config_clk_divider(struct da8xx_fb_par *par, + unsigned lcdc_clk_div, + unsigned lcdc_clk_rate) { - unsigned div; + int ret; - div = da8xx_fb_calc_clk_divider(par, pixclock); - return KHZ2PICOS(par->lcd_fck_rate / (1000 * div)); -} + if (par->lcd_fck_rate != lcdc_clk_rate) { + ret = clk_set_rate(par->lcdc_clk, lcdc_clk_rate); + if (IS_ERR_VALUE(ret)) { + dev_err(par->dev, + "unable to set clock rate at %u\n", + lcdc_clk_rate); + return ret; + } + par->lcd_fck_rate = clk_get_rate(par->lcdc_clk); + } -static inline void da8xx_fb_config_clk_divider(unsigned div) -{ /* Configure the LCD clock divisor. */ - lcdc_write(LCD_CLK_DIVISOR(div) | + lcdc_write(LCD_CLK_DIVISOR(lcdc_clk_div) | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); if (lcd_revision == LCD_VERSION_2) lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); + + return 0; +} + +static unsigned int da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par, + unsigned pixclock, + unsigned *lcdc_clk_rate) +{ + unsigned lcdc_clk_div; + + pixclock = PICOS2KHZ(pixclock) * 1000; + + *lcdc_clk_rate = par->lcd_fck_rate; + + if (pixclock < (*lcdc_clk_rate / CLK_MAX_DIV)) { + *lcdc_clk_rate = clk_round_rate(par->lcdc_clk, + pixclock * CLK_MAX_DIV); + lcdc_clk_div = CLK_MAX_DIV; + } else if (pixclock > (*lcdc_clk_rate / CLK_MIN_DIV)) { + *lcdc_clk_rate = clk_round_rate(par->lcdc_clk, + pixclock * CLK_MIN_DIV); + lcdc_clk_div = CLK_MIN_DIV; + } else { + lcdc_clk_div = *lcdc_clk_rate / pixclock; + } + + return lcdc_clk_div; } -static inline void da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par, - struct fb_videomode *mode) +static int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par, + struct fb_videomode *mode) { - unsigned div = da8xx_fb_calc_clk_divider(par, mode->pixclock); + unsigned lcdc_clk_rate; + unsigned lcdc_clk_div = da8xx_fb_calc_clk_divider(par, mode->pixclock, + &lcdc_clk_rate); - da8xx_fb_config_clk_divider(div); + return da8xx_fb_config_clk_divider(par, lcdc_clk_div, lcdc_clk_rate); +} + +static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par, + unsigned pixclock) +{ + unsigned lcdc_clk_div, lcdc_clk_rate; + + lcdc_clk_div = da8xx_fb_calc_clk_divider(par, pixclock, &lcdc_clk_rate); + return KHZ2PICOS(lcdc_clk_rate / (1000 * lcdc_clk_div)); } static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, @@ -724,7 +765,11 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, u32 bpp; int ret = 0; - da8xx_fb_calc_config_clk_divider(par, panel); + ret = da8xx_fb_calc_config_clk_divider(par, panel); + if (IS_ERR_VALUE(ret)) { + dev_err(par->dev, "unable to configure clock\n"); + return ret; + } if (panel->sync & FB_SYNC_CLK_INVERT) lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | -- cgit v1.2.3 From 0715c72d03ea9297ce6fac5a46fc85618cd4a4ce Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Mon, 5 Aug 2013 17:02:37 -0500 Subject: video: da8xx-fb: make clock naming consistent Clean up the code, so that the names of the various clock variables are consistent to it is clear what variable is associated with what clock. Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index dfe757254e26..8c0ca11ad4b3 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -177,7 +177,7 @@ struct da8xx_fb_par { #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; #endif - unsigned int lcd_fck_rate; + unsigned int lcdc_clk_rate; void (*panel_power_ctrl)(int); u32 pseudo_palette[16]; struct fb_videomode mode; @@ -693,7 +693,7 @@ static int da8xx_fb_config_clk_divider(struct da8xx_fb_par *par, { int ret; - if (par->lcd_fck_rate != lcdc_clk_rate) { + if (par->lcdc_clk_rate != lcdc_clk_rate) { ret = clk_set_rate(par->lcdc_clk, lcdc_clk_rate); if (IS_ERR_VALUE(ret)) { dev_err(par->dev, @@ -701,7 +701,7 @@ static int da8xx_fb_config_clk_divider(struct da8xx_fb_par *par, lcdc_clk_rate); return ret; } - par->lcd_fck_rate = clk_get_rate(par->lcdc_clk); + par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); } /* Configure the LCD clock divisor. */ @@ -723,7 +723,7 @@ static unsigned int da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par, pixclock = PICOS2KHZ(pixclock) * 1000; - *lcdc_clk_rate = par->lcd_fck_rate; + *lcdc_clk_rate = par->lcdc_clk_rate; if (pixclock < (*lcdc_clk_rate / CLK_MAX_DIV)) { *lcdc_clk_rate = clk_round_rate(par->lcdc_clk, @@ -1031,8 +1031,8 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb, par = container_of(nb, struct da8xx_fb_par, freq_transition); if (val == CPUFREQ_POSTCHANGE) { - if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) { - par->lcd_fck_rate = clk_get_rate(par->lcdc_clk); + if (par->lcdc_clk_rate != clk_get_rate(par->lcdc_clk)) { + par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); lcd_disable_raster(DA8XX_FRAME_WAIT); da8xx_fb_calc_config_clk_divider(par, &par->mode); if (par->blank == FB_BLANK_UNBLANK) @@ -1327,8 +1327,8 @@ static int fb_probe(struct platform_device *device) struct lcd_ctrl_config *lcd_cfg; struct fb_videomode *lcdc_info; struct fb_info *da8xx_fb_info; - struct clk *fb_clk = NULL; struct da8xx_fb_par *par; + struct clk *tmp_lcdc_clk; int ret; unsigned long ulcm; @@ -1346,10 +1346,10 @@ static int fb_probe(struct platform_device *device) if (IS_ERR(da8xx_fb_reg_base)) return PTR_ERR(da8xx_fb_reg_base); - fb_clk = devm_clk_get(&device->dev, "fck"); - if (IS_ERR(fb_clk)) { + tmp_lcdc_clk = devm_clk_get(&device->dev, "fck"); + if (IS_ERR(tmp_lcdc_clk)) { dev_err(&device->dev, "Can not get device clock\n"); - return PTR_ERR(fb_clk); + return PTR_ERR(tmp_lcdc_clk); } pm_runtime_enable(&device->dev); @@ -1389,8 +1389,8 @@ static int fb_probe(struct platform_device *device) par = da8xx_fb_info->par; par->dev = &device->dev; - par->lcdc_clk = fb_clk; - par->lcd_fck_rate = clk_get_rate(fb_clk); + par->lcdc_clk = tmp_lcdc_clk; + par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); if (fb_pdata->panel_power_ctrl) { par->panel_power_ctrl = fb_pdata->panel_power_ctrl; par->panel_power_ctrl(1); -- cgit v1.2.3 From a9cd67c8bc16f9729116e387057fdd915fc33bcb Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Mon, 5 Aug 2013 17:02:38 -0500 Subject: video: da8xx-fb: let compiler decide what to inline Remove use of explicit inline compiler directive and let the compiler make the decision as per Documentation/CodingStyle. Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/da8xx-fb.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 8c0ca11ad4b3..ea9771f98301 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -141,12 +141,12 @@ static irq_handler_t lcdc_irq_handler; static wait_queue_head_t frame_done_wq; static int frame_done_flag; -static inline unsigned int lcdc_read(unsigned int addr) +static unsigned int lcdc_read(unsigned int addr) { return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr)); } -static inline void lcdc_write(unsigned int val, unsigned int addr) +static void lcdc_write(unsigned int val, unsigned int addr) { __raw_writel(val, da8xx_fb_reg_base + (addr)); } @@ -245,13 +245,13 @@ static struct fb_videomode known_lcd_panels[] = { }, }; -static inline bool da8xx_fb_is_raster_enabled(void) +static bool da8xx_fb_is_raster_enabled(void) { return !!(lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE); } /* Enable the Raster Engine of the LCD Controller */ -static inline void lcd_enable_raster(void) +static void lcd_enable_raster(void) { u32 reg; @@ -273,8 +273,7 @@ static inline void lcd_enable_raster(void) } /* Disable the Raster Engine of the LCD Controller */ -static inline void lcd_disable_raster(enum da8xx_frame_complete - wait_for_frame_done) +static void lcd_disable_raster(enum da8xx_frame_complete wait_for_frame_done) { u32 reg; int ret; @@ -750,7 +749,7 @@ static int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par, return da8xx_fb_config_clk_divider(par, lcdc_clk_div, lcdc_clk_rate); } -static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par, +static unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par, unsigned pixclock) { unsigned lcdc_clk_div, lcdc_clk_rate; @@ -1043,7 +1042,7 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb, return 0; } -static inline int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par) +static int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par) { par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition; @@ -1051,7 +1050,7 @@ static inline int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par) CPUFREQ_TRANSITION_NOTIFIER); } -static inline void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) +static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) { cpufreq_unregister_notifier(&par->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); -- cgit v1.2.3 From 979778ffdbb5686c78f9045947e5f870c496fd0f Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Mon, 5 Aug 2013 17:02:39 -0500 Subject: video: da8xx-fb: adding am33xx as dependency Updating Kconfig to allow am33xx to include lcdc fbdev driver including some extra dependencies needed by device tree mods. v2: must add FB_MODE_HELPERS as VIDEOMODE_HELPERS alone doesn't get the correct functions from fbmon.c built in. Signed-off-by: Darren Etheridge Signed-off-by: Tomi Valkeinen --- drivers/video/Kconfig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4cf1e1dd5621..0c10b0bf430d 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2228,15 +2228,17 @@ config FB_SH7760 panels <= 320 pixel horizontal resolution. config FB_DA8XX - tristate "DA8xx/OMAP-L1xx Framebuffer support" - depends on FB && ARCH_DAVINCI_DA8XX + tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support" + depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select FB_CFB_REV_PIXELS_IN_BYTE + select FB_MODE_HELPERS + select VIDEOMODE_HELPERS ---help--- This is the frame buffer device driver for the TI LCD controller - found on DA8xx/OMAP-L1xx SoCs. + found on DA8xx/OMAP-L1xx/AM335x SoCs. If unsure, say N. config FB_VIRTUAL -- cgit v1.2.3