On 10/02/20 12:17 AM, Dario Binacchi wrote:
> Update the driver to support the device tree and the driver model.
> Timings and panel parameters are now loaded from the device tree.
> 
> The DM code replaces the am335x_lcdpanel structure with
> tilcdc_panel_info taken from the linux kernel, as well the management
> of additional parameters not covered in the legacy code. In addition,
> the am335x_lcdpanel structure contains parameters and operations that
> were probably a requirement of the board for which this driver was
> developed and which, however, were not developed in the linux kernel.
> All this led to rewrite th DM controller initialization code, except

Nice..!!

> for the pixel clock setting that is executed in a function created in a
> previous patch with code taken from the legacy am335xfb_init.
> 
> The patch has been tested on a custom board with the following DT
> configuration:
> 
>       panel {
>               compatible = "ti,tilcdc,panel";
>               pinctrl-names = "default";
>               pinctrl-0 = <&lcd_enable_pins>;
>               enable-gpios = <&gpio0 31 0>;
>               backlight = <&backlight>;
>               status = "okay";
>               u-boot,dm-pre-reloc;
>               panel-info {
>                       ac-bias           = <255>;
>                       ac-bias-intrpt    = <0>;
>                       dma-burst-sz      = <16>;
>                       bpp               = <16>;
>                       fdd               = <0x80>;
>                       sync-edge         = <0>;
>                       sync-ctrl         = <1>;
>                       raster-order      = <0>;
>                       fifo-th           = <0>;
>               };
>               display-timings {
>                       native-mode = <&timing0>;
>                       timing0: 800x480 {
>                               hactive         = <800>;
>                               vactive         = <480>;
>                               hback-porch     = <46>;
>                               hfront-porch    = <210>;
>                               hsync-len       = <20>;
>                               vback-porch     = <23>;
>                               vfront-porch    = <22>;
>                               vsync-len       = <10>;
>                               clock-frequency = <33000000>;
>                               hsync-active    = <0>;
>                               vsync-active    = <0>;
>                       };
>               };
>       };

Are these bindings same as Linux kernel?

> 
> Signed-off-by: Dario Binacchi <dario...@libero.it>
> Tested-by: Dario Binacchi <dario...@libero.it>
> ---
> 
>  drivers/video/am335x-fb.c | 346 ++++++++++++++++++++++++++++++++++++--
>  drivers/video/am335x-fb.h |   4 +
>  2 files changed, 340 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c
> index e53c1d276e..e8bd9c6464 100644
> --- a/drivers/video/am335x-fb.c
> +++ b/drivers/video/am335x-fb.c
> @@ -2,6 +2,7 @@
>  /*
>   * Copyright (C) 2013-2018 Hannes Schmelzer <oe5...@oevsv.at>
>   * B&R Industrial Automation GmbH - http://www.br-automation.com
> + * Copyright (C) 2020 Dario Binacchi <dario...@libero.it>
>   *
>   * minimal framebuffer driver for TI's AM335x SoC to be compatible with
>   * Wolfgang Denk's LCD-Framework (CONFIG_LCD, common/lcd.c)
> @@ -11,19 +12,18 @@
>   * - starts output DMA from gd->fb_base buffer
>   */
>  #include <common.h>
> +#include <dm.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 <asm/utils.h>
>  #include <linux/err.h>
>  #include <lcd.h>
> +#include <video.h>
>  #include "am335x-fb.h"
>  
> -#if !defined(LCD_CNTL_BASE)
> -#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!"
> -#endif
> -
>  #define LCDC_FMAX                            200000000
>  
>  /* LCD Control Register */
> @@ -41,6 +41,7 @@
>  #define LCDC_DMA_CTRL_BURST_4                        0x2
>  #define LCDC_DMA_CTRL_BURST_8                        0x3
>  #define LCDC_DMA_CTRL_BURST_16                       0x4
> +#define LCDC_DMA_CTRL_FIFO_TH(x)             (((x) & 0x07) << 8)
>  /* LCD Timing_0 Register */
>  #define LCDC_RASTER_TIMING_0_HORMSB(x)               (((((x) >> 4) - 1) & 
> 0x40) >> 4)
>  #define LCDC_RASTER_TIMING_0_HORLSB(x)               (((((x) >> 4) - 1) & 
> 0x3F) << 4)
> @@ -55,19 +56,26 @@
>  /* LCD Timing_2 Register */
>  #define LCDC_RASTER_TIMING_2_HFPMSB(x)               ((((x) - 1) & 0x300) >> 
> 8)
>  #define LCDC_RASTER_TIMING_2_HBPMSB(x)               ((((x) - 1) & 0x300) >> 
> 4)
> -#define LCDC_RASTER_TIMING_2_INVMASK(x)              ((x) & 0x3F00000)
> +#define LCDC_RASTER_TIMING_2_ACB(x)          (((x) & 0xFF) << 8)
> +#define LCDC_RASTER_TIMING_2_ACBI(x)         (((x) & 0x0F) << 16)
> +#define LCDC_RASTER_TIMING_2_VSYNC_INVERT    BIT(20)
> +#define LCDC_RASTER_TIMING_2_HSYNC_INVERT    BIT(21)
> +#define LCDC_RASTER_TIMING_2_PXCLK_INVERT    BIT(22)
> +#define LCDC_RASTER_TIMING_2_DE_INVERT               BIT(23)
> +#define LCDC_RASTER_TIMING_2_HSVS_RISEFALL   BIT(24)
> +#define LCDC_RASTER_TIMING_2_HSVS_CONTROL    BIT(25)
>  #define LCDC_RASTER_TIMING_2_VERMSB(x)               ((((x) - 1) & 0x400) << 
> 16)
>  #define LCDC_RASTER_TIMING_2_HSWMSB(x)               ((((x) - 1) & 0x3C0) << 
> 21)
>  /* LCD Raster Ctrl Register */
>  #define LCDC_RASTER_CTRL_ENABLE                      BIT(0)
>  #define LCDC_RASTER_CTRL_TFT_MODE            BIT(7)
> +#define LCDC_RASTER_CTRL_DATA_ORDER          BIT(8)
> +#define LCDC_RASTER_CTRL_REQDLY(x)           (((x) & 0xFF) << 12)
>  #define LCDC_RASTER_CTRL_PALMODE_RAWDATA     (0x02 << 20)
> +#define LCDC_RASTER_CTRL_TFT_ALT_ENABLE              BIT(23)
>  #define LCDC_RASTER_CTRL_TFT_24BPP_MODE              BIT(25)
>  #define LCDC_RASTER_CTRL_TFT_24BPP_UNPACK    BIT(26)
>  
> -/* Macro definitions */
> -#define FBSIZE(x)    ((x->hactive * x->vactive * x->bpp) >> 3)
> -
>  struct am335x_lcdhw {
>       unsigned int            pid;                    /* 0x00 */
>       unsigned int            ctrl;                   /* 0x04 */
> @@ -107,8 +115,6 @@ struct dpll_data {
>       u8 rounded_div;
>  };
>  
> -static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE;
> -
>  DECLARE_GLOBAL_DATA_PTR;
>  
>  /**
> @@ -189,6 +195,19 @@ static ulong am335x_fb_set_pixel_clk_rate(struct 
> am335x_lcdhw *regs, ulong rate)
>       return round_rate;
>  }
>  
> +#if !defined(CONFIG_DM_VIDEO)
> +
> +#if !defined(LCD_CNTL_BASE)
> +#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!"
> +#endif
> +
> +/* Macro definitions */
> +#define FBSIZE(x)    (((x)->hactive * (x)->vactive * (x)->bpp) >> 3)
> +
> +#define LCDC_RASTER_TIMING_2_INVMASK(x)              ((x) & 0x3F00000)
> +
> +static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE;
> +
>  int lcd_get_size(int *line_length)
>  {
>       *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
> @@ -299,3 +318,310 @@ int am335xfb_init(struct am335x_lcdpanel *panel)
>  
>       return 0;
>  }
> +
> +#else /* CONFIG_DM_VIDEO */
> +
> +#define FBSIZE(t, p) (((t)->hactive.typ * (t)->vactive.typ * (p)->bpp) >> 3)
> +
> +enum {
> +     LCD_MAX_WIDTH           = 2048,
> +     LCD_MAX_HEIGHT          = 2048,
> +     LCD_MAX_LOG2_BPP        = VIDEO_BPP32,
> +};
> +
> +/**
> + * tilcdc_panel_info: Panel parameters
> + *
> + * @ac_bias: AC Bias Pin Frequency
> + * @ac_bias_intrpt: AC Bias Pin Transitions per Interrupt
> + * @dma_burst_sz: DMA burst size
> + * @bpp: Bits per pixel
> + * @fdd: FIFO DMA Request Delay
> + * @tft_alt_mode: TFT Alternative Signal Mapping (Only for active)
> + * @invert_pxl_clk: Invert pixel clock
> + * @sync_edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling
> + * @sync_ctrl: Horizontal and Vertical Sync: Control: 0=ignore
> + * @raster_order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most
> + * @fifo_th: DMA FIFO threshold
> + */
> +struct tilcdc_panel_info {
> +     u32 ac_bias;
> +     u32 ac_bias_intrpt;
> +     u32 dma_burst_sz;
> +     u32 bpp;
> +     u32 fdd;
> +     bool tft_alt_mode;
> +     bool invert_pxl_clk;
> +     u32 sync_edge;
> +     u32 sync_ctrl;
> +     u32 raster_order;
> +     u32 fifo_th;
> +};
> +
> +struct am335x_fb_priv {
> +     struct am335x_lcdhw *regs;
> +     struct tilcdc_panel_info panel;
> +     struct display_timing timing;
> +};
> +
> +static int am335x_fb_remove(struct udevice *dev)
> +{
> +     struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
> +
> +     uc_plat->base -= 0x20;
> +     uc_plat->size += 0x20;
> +     return 0;
> +}
> +
> +static int am335x_fb_probe(struct udevice *dev)
> +{
> +     struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
> +     struct video_priv *uc_priv = dev_get_uclass_priv(dev);
> +     struct am335x_fb_priv *priv = dev_get_priv(dev);
> +     struct am335x_lcdhw *regs = priv->regs;
> +     struct tilcdc_panel_info *panel = &priv->panel;
> +     struct display_timing *timing = &priv->timing;
> +     struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
> +     struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
> +     u32 *const clk_domains[] = { 0 };
> +     u32 *const clk_modules[] = {
> +             &cmper->lcdclkctrl,
> +             &cmper->lcdcclkstctrl,
> +             0
> +     };
> +     u32 reg;
> +
> +     /* Before relocation we don't need to do anything */
> +     if (!(gd->flags & GD_FLG_RELOC))
> +             return 0;
> +
> +     do_enable_clocks(clk_domains, clk_modules, 1);

You are using an api specific to SoC. This driver will fail to build if
ARCH_OMAP2PLUS is not selected. Can you move this clock enabling sequence to
arch/arm/mach-omap2/?

Also can you create a Kconfig symbol for CONFIG_AM335X_LCD?

Thanks and regards,
Lokesh

Reply via email to