video: omap: add panel driver
authorDario Binacchi <dariobin@libero.it>
Tue, 29 Dec 2020 23:16:27 +0000 (00:16 +0100)
committerLokesh Vutla <lokeshvutla@ti.com>
Tue, 12 Jan 2021 05:28:27 +0000 (10:58 +0530)
The previous version of am335x-fb.c contained the functionalities of two
drivers that this patch has split. It was a video type driver that used
the same registration compatible string that now registers a panel type
driver. The proof of this is that two compatible strings were referred
to within the same driver.
There are now two drivers, each with its own compatible string,
functions and API.
Furthermore, the panel driver, in addition to decoding the display
timings, is now also able to manage the backlight.

Signed-off-by: Dario Binacchi <dariobin@libero.it>
Reviewed-by: Simon Glass <sjg@chromium.org>
16 files changed:
arch/arm/dts/am335x-brppt1-mmc.dts
arch/arm/dts/am335x-brppt1-nand.dts
arch/arm/dts/am335x-brppt1-spi.dts
arch/arm/dts/am335x-brsmarc1.dts
arch/arm/dts/am335x-brxre1.dts
arch/arm/dts/am335x-evm-u-boot.dtsi
arch/arm/dts/am335x-evmsk-u-boot.dtsi
arch/arm/dts/am335x-guardian-u-boot.dtsi
arch/arm/dts/am335x-pdu001-u-boot.dtsi
arch/arm/dts/am335x-pxm50-u-boot.dtsi
arch/arm/dts/am335x-rut-u-boot.dtsi
drivers/video/Makefile
drivers/video/am335x-fb.c
drivers/video/am335x-fb.h
drivers/video/tilcdc-panel.c [new file with mode: 0644]
drivers/video/tilcdc-panel.h [new file with mode: 0644]

index 6f919711f0a0676cfe66cffbd8e4930c74e70958..bd2f6c2e3e1bfab197ad192333c7d481642f6af3 100644 (file)
@@ -53,8 +53,6 @@
                bkl-pwm = <&pwmbacklight>;
                bkl-tps = <&tps_bl>;
 
-               u-boot,dm-pre-reloc;
-
                panel-info {
                        ac-bias         = <255>;
                        ac-bias-intrpt  = <0>;
        status = "okay";
 };
 
-&lcdc {
-       status = "disabled";
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                               status = "disabled";
+                       };
+               };
+       };
 };
 
 &elm {
index 9d4340f5914189f1d347dc9a731019887e57e3ab..67c609739fc6687f763e3ccfc8c0b43bd6d151e9 100644 (file)
@@ -53,8 +53,6 @@
                bkl-pwm = <&pwmbacklight>;
                bkl-tps = <&tps_bl>;
 
-               u-boot,dm-pre-reloc;
-
                panel-info {
                        ac-bias         = <255>;
                        ac-bias-intrpt  = <0>;
        status = "disabled";
 };
 
-&lcdc {
-       status = "disabled";
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                               status = "disabled";
+                       };
+               };
+       };
 };
 
 &elm {
index c078af8fbae97af657b8f367314f69f47df7ccc6..ce3dce204d6cce2eacb8cdb34711f480de732c4a 100644 (file)
@@ -54,8 +54,6 @@
                bkl-pwm = <&pwmbacklight>;
                bkl-tps = <&tps_bl>;
 
-               u-boot,dm-pre-reloc;
-
                panel-info {
                        ac-bias         = <255>;
                        ac-bias-intrpt  = <0>;
        status = "okay";
 };
 
-&lcdc {
-       status = "disabled";
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                               status = "disabled";
+                       };
+               };
+       };
 };
 
 &elm {
index 7e9516e8f885ac9e3a2fea2811cb8edc5aea3b27..25cdb1116485a3a315b3245b6fba60557adcc851 100644 (file)
@@ -59,7 +59,6 @@
                /*backlight = <&tps_bl>; */
                compatible = "ti,tilcdc,panel";
                status = "okay";
-               u-boot,dm-pre-reloc;
 
                panel-info {
                        ac-bias         = <255>;
        status = "okay";
 };
 
-&lcdc {
-       status = "okay";
-       ti,no-reset-on-init;
-       ti,no-idle-on-init;
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                               status = "okay";
+                               ti,no-reset-on-init;
+                               ti,no-idle-on-init;
+                       };
+               };
+       };
 };
 
 &elm {
index 6091a12fb7077d4582c4a7a63842b9efd57f34d2..485c8e3613de98e6bf3e8fc914f8c659c0d2083f 100644 (file)
@@ -79,8 +79,6 @@
 
                backlight = <&tps_bl>;
 
-               u-boot,dm-pre-reloc;
-
                panel-info {
                        ac-bias         = <255>;
                        ac-bias-intrpt  = <0>;
        status = "okay";
 };
 
-&lcdc {
-       status = "okay";
-       ti,no-reset-on-init;
-       ti,no-idle-on-init;
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                               status = "okay";
+                               ti,no-reset-on-init;
+                               ti,no-idle-on-init;
+                       };
+               };
+       };
 };
 
 &elm {
index 400a1d2cecba8a6a7f2d1abb4707903833222d61..4cf5f9928d5875cae51a1959cd839ec18cedfb09 100644 (file)
@@ -5,13 +5,20 @@
 
 #include "am33xx-u-boot.dtsi"
 
-/ {
-       panel {
-               u-boot,dm-pre-reloc;
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                       };
+               };
        };
 };
 
-
 &mmc3 {
        status = "disabled";
 };
index 96798330b1f4f5bea8e5eecfacfe7185d8516381..1003f4d31adc31ef122300837582a2bda1138372 100644 (file)
@@ -7,8 +7,16 @@
 
 #include "am33xx-u-boot.dtsi"
 
-/ {
-       panel {
-               u-boot,dm-pre-reloc;
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                       };
+               };
        };
 };
index c866ce83f30111d117f2e6f977f807198902147a..986f58e6648938a5afe9d84ac65f78bcd558bf0d 100644 (file)
        ocp {
                u-boot,dm-pre-reloc;
        };
-
-       panel {
-               u-boot,dm-pre-reloc;
-       };
 };
 
 &l4_wkup {
        u-boot,dm-pre-reloc;
 };
 
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                       };
+               };
+       };
+};
+
 &mmc1 {
        u-boot,dm-pre-reloc;
 };
index 4f4fc411f915f89fbb4373b9d7bed179559a39ad..686a152fd9d9791ede1906373663a368ba3f140a 100644 (file)
@@ -9,16 +9,26 @@
        ocp {
                u-boot,dm-pre-reloc;
        };
-
-       panel {
-               u-boot,dm-pre-reloc;
-       };
 };
 
 &l4_wkup {
        u-boot,dm-pre-reloc;
 };
 
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                       };
+               };
+       };
+};
+
 &scm {
        u-boot,dm-pre-reloc;
 };
index 65ed948c58524f2acb876c695f55c5927022c041..e5af9fdf893b149a0226577e253d88f533088332 100644 (file)
@@ -7,8 +7,16 @@
 
 #include "am33xx-u-boot.dtsi"
 
-/ {
-       panel {
-               u-boot,dm-pre-reloc;
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                       };
+               };
        };
 };
index b16f75a7647b4b83441b4d066f5a4b663882a5db..a38c2dc60723a3de4635b8f42b742815a0f82c78 100644 (file)
@@ -7,8 +7,16 @@
 
 #include "am33xx-u-boot.dtsi"
 
-/ {
-       panel {
-               u-boot,dm-pre-reloc;
+&l4_per {
+
+       segment@300000 {
+
+               target-module@e000 {
+                       u-boot,dm-pre-reloc;
+
+                       lcdc: lcdc@0 {
+                               u-boot,dm-pre-reloc;
+                       };
+               };
        };
 };
index 9db96aa891a3603d50fc00d7662583756aa13568..4629f28cbb8a5c3ec0b73b6a5f7ab6f15bbc2ab5 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o
 obj-$(CONFIG_DM_VIDEO) += video_bmp.o
 obj-$(CONFIG_PANEL) += panel-uclass.o
 obj-$(CONFIG_SIMPLE_PANEL) += simple_panel.o
+obj-$(CONFIG_AM335X_LCD) += tilcdc-panel.o
 endif
 
 obj-${CONFIG_EXYNOS_FB} += exynos/
index e99a9185a2ad71368bf2c82cdfa4721905a976b4..a3464ae6a0548c8e58be81f8a112af5d4c3af1e8 100644 (file)
@@ -15,6 +15,7 @@
 #include <dm.h>
 #include <lcd.h>
 #include <log.h>
+#include <panel.h>
 #include <video.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/hardware.h>
@@ -25,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include "am335x-fb.h"
+#include "tilcdc-panel.h"
 
 #define LCDC_FMAX                              200000000
 
@@ -323,7 +325,7 @@ int am335xfb_init(struct am335x_lcdpanel *panel)
 
 #else /* CONFIG_DM_VIDEO */
 
-#define FBSIZE(t, p)   (((t)->hactive.typ * (t)->vactive.typ * (p)->bpp) >> 3)
+#define FBSIZE(t, p)   (((t).hactive.typ * (t).vactive.typ * (p).bpp) >> 3)
 
 enum {
        LCD_MAX_WIDTH           = 2048,
@@ -331,39 +333,8 @@ enum {
        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)
@@ -381,16 +352,71 @@ static int am335x_fb_probe(struct udevice *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 udevice *panel;
+       struct tilcdc_panel_info info;
+       struct display_timing timing;
        struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
        u32 reg;
+       int err;
 
        /* Before relocation we don't need to do anything */
        if (!(gd->flags & GD_FLG_RELOC))
                return 0;
 
-       am335x_fb_set_pixel_clk_rate(regs, timing->pixelclock.typ);
+       err = uclass_get_device(UCLASS_PANEL, 0, &panel);
+       if (err) {
+               dev_err(dev, "failed to get panel\n");
+               return err;
+       }
+
+       err = panel_get_display_timing(panel, &timing);
+       if (err) {
+               dev_err(dev, "failed to get display timing\n");
+               return err;
+       }
+
+       if (timing.pixelclock.typ > (LCDC_FMAX / 2)) {
+               dev_err(dev, "invalid display clock-frequency: %d Hz\n",
+                       timing.pixelclock.typ);
+               return -EINVAL;
+       }
+
+       if (timing.hactive.typ > LCD_MAX_WIDTH)
+               timing.hactive.typ = LCD_MAX_WIDTH;
+
+       if (timing.vactive.typ > LCD_MAX_HEIGHT)
+               timing.vactive.typ = LCD_MAX_HEIGHT;
+
+       err = tilcdc_panel_get_display_info(panel, &info);
+       if (err) {
+               dev_err(dev, "failed to get panel info\n");
+               return err;
+       }
+
+       switch (info.bpp) {
+       case 16:
+       case 24:
+       case 32:
+               break;
+       default:
+               dev_err(dev, "invalid seting, bpp: %d\n", info.bpp);
+               return -EINVAL;
+       }
+
+       switch (info.dma_burst_sz) {
+       case 1:
+       case 2:
+       case 4:
+       case 8:
+       case 16:
+               break;
+       default:
+               dev_err(dev, "invalid setting, dma-burst-sz: %d\n",
+                       info.dma_burst_sz);
+               return -EINVAL;
+       }
+
+       am335x_fb_set_pixel_clk_rate(regs, timing.pixelclock.typ);
 
        /* clock source for LCDC from dispPLL M2 */
        writel(0, &cmdpll->clklcdcpixelclk);
@@ -411,14 +437,14 @@ static int am335x_fb_probe(struct udevice *dev)
        writel(reg, &regs->ctrl);
 
        writel(uc_plat->base, &regs->lcddma_fb0_base);
-       writel(uc_plat->base + FBSIZE(timing, panel),
+       writel(uc_plat->base + FBSIZE(timing, info),
               &regs->lcddma_fb0_ceiling);
        writel(uc_plat->base, &regs->lcddma_fb1_base);
-       writel(uc_plat->base + FBSIZE(timing, panel),
+       writel(uc_plat->base + FBSIZE(timing, info),
               &regs->lcddma_fb1_ceiling);
 
-       reg = LCDC_DMA_CTRL_FIFO_TH(panel->fifo_th);
-       switch (panel->dma_burst_sz) {
+       reg = LCDC_DMA_CTRL_FIFO_TH(info.fifo_th);
+       switch (info.dma_burst_sz) {
        case 1:
                reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_1);
                break;
@@ -438,155 +464,84 @@ static int am335x_fb_probe(struct udevice *dev)
 
        writel(reg, &regs->lcddma_ctrl);
 
-       writel(LCDC_RASTER_TIMING_0_HORLSB(timing->hactive.typ) |
-              LCDC_RASTER_TIMING_0_HORMSB(timing->hactive.typ) |
-              LCDC_RASTER_TIMING_0_HFPLSB(timing->hfront_porch.typ) |
-              LCDC_RASTER_TIMING_0_HBPLSB(timing->hback_porch.typ) |
-              LCDC_RASTER_TIMING_0_HSWLSB(timing->hsync_len.typ),
+       writel(LCDC_RASTER_TIMING_0_HORLSB(timing.hactive.typ) |
+              LCDC_RASTER_TIMING_0_HORMSB(timing.hactive.typ) |
+              LCDC_RASTER_TIMING_0_HFPLSB(timing.hfront_porch.typ) |
+              LCDC_RASTER_TIMING_0_HBPLSB(timing.hback_porch.typ) |
+              LCDC_RASTER_TIMING_0_HSWLSB(timing.hsync_len.typ),
               &regs->raster_timing0);
 
-       writel(LCDC_RASTER_TIMING_1_VBP(timing->vback_porch.typ) |
-              LCDC_RASTER_TIMING_1_VFP(timing->vfront_porch.typ) |
-              LCDC_RASTER_TIMING_1_VSW(timing->vsync_len.typ) |
-              LCDC_RASTER_TIMING_1_VERLSB(timing->vactive.typ),
+       writel(LCDC_RASTER_TIMING_1_VBP(timing.vback_porch.typ) |
+              LCDC_RASTER_TIMING_1_VFP(timing.vfront_porch.typ) |
+              LCDC_RASTER_TIMING_1_VSW(timing.vsync_len.typ) |
+              LCDC_RASTER_TIMING_1_VERLSB(timing.vactive.typ),
               &regs->raster_timing1);
 
-       reg = LCDC_RASTER_TIMING_2_ACB(panel->ac_bias) |
-               LCDC_RASTER_TIMING_2_ACBI(panel->ac_bias_intrpt) |
-               LCDC_RASTER_TIMING_2_HSWMSB(timing->hsync_len.typ) |
-               LCDC_RASTER_TIMING_2_VERMSB(timing->vactive.typ) |
-               LCDC_RASTER_TIMING_2_HBPMSB(timing->hback_porch.typ) |
-               LCDC_RASTER_TIMING_2_HFPMSB(timing->hfront_porch.typ);
+       reg = LCDC_RASTER_TIMING_2_ACB(info.ac_bias) |
+               LCDC_RASTER_TIMING_2_ACBI(info.ac_bias_intrpt) |
+               LCDC_RASTER_TIMING_2_HSWMSB(timing.hsync_len.typ) |
+               LCDC_RASTER_TIMING_2_VERMSB(timing.vactive.typ) |
+               LCDC_RASTER_TIMING_2_HBPMSB(timing.hback_porch.typ) |
+               LCDC_RASTER_TIMING_2_HFPMSB(timing.hfront_porch.typ);
 
-       if (timing->flags & DISPLAY_FLAGS_VSYNC_LOW)
+       if (timing.flags & DISPLAY_FLAGS_VSYNC_LOW)
                reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT;
 
-       if (timing->flags & DISPLAY_FLAGS_HSYNC_LOW)
+       if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW)
                reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT;
 
-       if (panel->invert_pxl_clk)
+       if (info.invert_pxl_clk)
                reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT;
 
-       if (panel->sync_edge)
+       if (info.sync_edge)
                reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL;
 
-       if (panel->sync_ctrl)
+       if (info.sync_ctrl)
                reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL;
 
        writel(reg, &regs->raster_timing2);
 
        reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE |
-               LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(panel->fdd);
+               LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(info.fdd);
 
-       if (panel->tft_alt_mode)
+       if (info.tft_alt_mode)
                reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE;
 
-       if (panel->bpp == 24)
+       if (info.bpp == 24)
                reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE;
-       else if (panel->bpp == 32)
+       else if (info.bpp == 32)
                reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE |
                        LCDC_RASTER_CTRL_TFT_24BPP_UNPACK;
 
-       if (panel->raster_order)
+       if (info.raster_order)
                reg |= LCDC_RASTER_CTRL_DATA_ORDER;
 
        writel(reg, &regs->raster_ctrl);
 
-       uc_priv->xsize = timing->hactive.typ;
-       uc_priv->ysize = timing->vactive.typ;
-       uc_priv->bpix = log_2_n_round_up(panel->bpp);
-       return 0;
-}
-
-static int am335x_fb_of_to_plat(struct udevice *dev)
-{
-       struct am335x_fb_priv *priv = dev_get_priv(dev);
-       struct tilcdc_panel_info *panel = &priv->panel;
-       struct display_timing *timing = &priv->timing;
-       ofnode node;
-       int err;
+       uc_priv->xsize = timing.hactive.typ;
+       uc_priv->ysize = timing.vactive.typ;
+       uc_priv->bpix = log_2_n_round_up(info.bpp);
 
-       node = ofnode_by_compatible(ofnode_null(), "ti,am33xx-tilcdc");
-       if (!ofnode_valid(node)) {
-               dev_err(dev, "missing 'ti,am33xx-tilcdc' node\n");
-               return -ENXIO;
-       }
-
-       priv->regs = (struct am335x_lcdhw *)ofnode_get_addr(node);
-       dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs);
-
-       err = ofnode_decode_display_timing(dev_ofnode(dev), 0, timing);
+       err = panel_enable_backlight(panel);
        if (err) {
-               dev_err(dev, "failed to get display timing\n");
+               dev_err(dev, "failed to enable panel backlight\n");
                return err;
        }
 
-       if (timing->pixelclock.typ > (LCDC_FMAX / 2)) {
-               dev_err(dev, "invalid display clock-frequency: %d Hz\n",
-                       timing->pixelclock.typ);
-               return -EINVAL;
-       }
-
-       if (timing->hactive.typ > LCD_MAX_WIDTH)
-               timing->hactive.typ = LCD_MAX_WIDTH;
-
-       if (timing->vactive.typ > LCD_MAX_HEIGHT)
-               timing->vactive.typ = LCD_MAX_HEIGHT;
-
-       node = ofnode_find_subnode(dev_ofnode(dev), "panel-info");
-       if (!ofnode_valid(node)) {
-               dev_err(dev, "missing 'panel-info' node\n");
-               return -ENXIO;
-       }
-
-       err |= ofnode_read_u32(node, "ac-bias", &panel->ac_bias);
-       err |= ofnode_read_u32(node, "ac-bias-intrpt", &panel->ac_bias_intrpt);
-       err |= ofnode_read_u32(node, "dma-burst-sz", &panel->dma_burst_sz);
-       err |= ofnode_read_u32(node, "bpp", &panel->bpp);
-       err |= ofnode_read_u32(node, "fdd", &panel->fdd);
-       err |= ofnode_read_u32(node, "sync-edge", &panel->sync_edge);
-       err |= ofnode_read_u32(node, "sync-ctrl", &panel->sync_ctrl);
-       err |= ofnode_read_u32(node, "raster-order", &panel->raster_order);
-       err |= ofnode_read_u32(node, "fifo-th", &panel->fifo_th);
-       if (err) {
-               dev_err(dev, "failed to get panel info\n");
-               return err;
-       }
+       return 0;
+}
 
-       switch (panel->bpp) {
-       case 16:
-       case 24:
-       case 32:
-               break;
-       default:
-               dev_err(dev, "invalid seting, bpp: %d\n", panel->bpp);
-               return -EINVAL;
-       }
+static int am335x_fb_ofdata_to_platdata(struct udevice *dev)
+{
+       struct am335x_fb_priv *priv = dev_get_priv(dev);
 
-       switch (panel->dma_burst_sz) {
-       case 1:
-       case 2:
-       case 4:
-       case 8:
-       case 16:
-               break;
-       default:
-               dev_err(dev, "invalid setting, dma-burst-sz: %d\n",
-                       panel->dma_burst_sz);
+       priv->regs = (struct am335x_lcdhw *)dev_read_addr(dev);
+       if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) {
+               dev_err(dev, "failed to get base address\n");
                return -EINVAL;
        }
 
-       /* optional */
-       panel->tft_alt_mode = ofnode_read_bool(node, "tft-alt-mode");
-       panel->invert_pxl_clk = ofnode_read_bool(node, "invert-pxl-clk");
-
-       dev_dbg(dev, "LCD: %dx%d, bpp=%d, clk=%d Hz\n", timing->hactive.typ,
-               timing->vactive.typ, panel->bpp, timing->pixelclock.typ);
-       dev_dbg(dev, "     hbp=%d, hfp=%d, hsw=%d\n", timing->hback_porch.typ,
-               timing->hfront_porch.typ, timing->hsync_len.typ);
-       dev_dbg(dev, "     vbp=%d, vfp=%d, vsw=%d\n", timing->vback_porch.typ,
-               timing->vfront_porch.typ, timing->vsync_len.typ);
-
+       dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs);
        return 0;
 }
 
@@ -602,7 +557,7 @@ static int am335x_fb_bind(struct udevice *dev)
 }
 
 static const struct udevice_id am335x_fb_ids[] = {
-       { .compatible = "ti,tilcdc,panel" },
+       { .compatible = "ti,am33xx-tilcdc" },
        { }
 };
 
index c9f92bc3895dd9baf6ad1493bd3cd6c15d31e851..4952dd96e9b0827ff5360f051cde1efb0e8c4bca 100644 (file)
@@ -70,6 +70,37 @@ struct am335x_lcdpanel {
 
 int am335xfb_init(struct am335x_lcdpanel *panel);
 
+#else /* CONFIG_DM_VIDEO */
+
+/**
+ * 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;
+};
+
 #endif  /* CONFIG_DM_VIDEO */
 
 #endif  /* AM335X_FB_H */
diff --git a/drivers/video/tilcdc-panel.c b/drivers/video/tilcdc-panel.c
new file mode 100644 (file)
index 0000000..84303a6
--- /dev/null
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * OMAP panel support
+ *
+ * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
+ */
+
+#include <common.h>
+#include <backlight.h>
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <log.h>
+#include <panel.h>
+#include <asm/gpio.h>
+#include <linux/err.h>
+#include "am335x-fb.h"
+
+struct tilcdc_panel_priv {
+       struct tilcdc_panel_info info;
+       struct display_timing timing;
+       struct udevice *backlight;
+       struct gpio_desc enable;
+};
+
+static int tilcdc_panel_enable_backlight(struct udevice *dev)
+{
+       struct tilcdc_panel_priv *priv = dev_get_priv(dev);
+
+       if (dm_gpio_is_valid(&priv->enable))
+               dm_gpio_set_value(&priv->enable, 1);
+
+       if (priv->backlight)
+               return backlight_enable(priv->backlight);
+
+       return 0;
+}
+
+static int tilcdc_panel_set_backlight(struct udevice *dev, int percent)
+{
+       struct tilcdc_panel_priv *priv = dev_get_priv(dev);
+
+       if (dm_gpio_is_valid(&priv->enable))
+               dm_gpio_set_value(&priv->enable, 1);
+
+       if (priv->backlight)
+               return backlight_set_brightness(priv->backlight, percent);
+
+       return 0;
+}
+
+int tilcdc_panel_get_display_info(struct udevice *dev,
+                                 struct tilcdc_panel_info *info)
+{
+       struct tilcdc_panel_priv *priv = dev_get_priv(dev);
+
+       memcpy(info, &priv->info, sizeof(*info));
+       return 0;
+}
+
+static int tilcdc_panel_get_display_timing(struct udevice *dev,
+                                          struct display_timing *timing)
+{
+       struct tilcdc_panel_priv *priv = dev_get_priv(dev);
+
+       memcpy(timing, &priv->timing, sizeof(*timing));
+       return 0;
+}
+
+static int tilcdc_panel_remove(struct udevice *dev)
+{
+       struct tilcdc_panel_priv *priv = dev_get_priv(dev);
+
+       if (dm_gpio_is_valid(&priv->enable))
+               dm_gpio_free(dev, &priv->enable);
+
+       return 0;
+}
+
+static int tilcdc_panel_probe(struct udevice *dev)
+{
+       struct tilcdc_panel_priv *priv = dev_get_priv(dev);
+       int err;
+
+       err = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+                                          "backlight", &priv->backlight);
+       if (err)
+               dev_warn(dev, "failed to get backlight\n");
+
+       err = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable,
+                                  GPIOD_IS_OUT);
+       if (err) {
+               dev_warn(dev, "failed to get enable GPIO\n");
+               if (err != -ENOENT)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int tilcdc_panel_of_to_plat(struct udevice *dev)
+{
+       struct tilcdc_panel_priv *priv = dev_get_priv(dev);
+       ofnode node;
+       int err;
+
+       err = ofnode_decode_display_timing(dev_ofnode(dev), 0, &priv->timing);
+       if (err) {
+               dev_err(dev, "failed to get display timing\n");
+               return err;
+       }
+
+       node = dev_read_subnode(dev, "panel-info");
+       if (!ofnode_valid(node)) {
+               dev_err(dev, "missing 'panel-info' node\n");
+               return -ENXIO;
+       }
+
+       err |= ofnode_read_u32(node, "ac-bias", &priv->info.ac_bias);
+       err |= ofnode_read_u32(node, "ac-bias-intrpt",
+                              &priv->info.ac_bias_intrpt);
+       err |= ofnode_read_u32(node, "dma-burst-sz", &priv->info.dma_burst_sz);
+       err |= ofnode_read_u32(node, "bpp", &priv->info.bpp);
+       err |= ofnode_read_u32(node, "fdd", &priv->info.fdd);
+       err |= ofnode_read_u32(node, "sync-edge", &priv->info.sync_edge);
+       err |= ofnode_read_u32(node, "sync-ctrl", &priv->info.sync_ctrl);
+       err |= ofnode_read_u32(node, "raster-order", &priv->info.raster_order);
+       err |= ofnode_read_u32(node, "fifo-th", &priv->info.fifo_th);
+       if (err) {
+               dev_err(dev, "failed to get panel info\n");
+               return err;
+       }
+
+       /* optional */
+       priv->info.tft_alt_mode = ofnode_read_bool(node, "tft-alt-mode");
+       priv->info.invert_pxl_clk = ofnode_read_bool(node, "invert-pxl-clk");
+
+       dev_dbg(dev, "LCD: %dx%d, bpp=%d, clk=%d Hz\n",
+               priv->timing.hactive.typ, priv->timing.vactive.typ,
+               priv->info.bpp, priv->timing.pixelclock.typ);
+       dev_dbg(dev, "     hbp=%d, hfp=%d, hsw=%d\n",
+               priv->timing.hback_porch.typ, priv->timing.hfront_porch.typ,
+               priv->timing.hsync_len.typ);
+       dev_dbg(dev, "     vbp=%d, vfp=%d, vsw=%d\n",
+               priv->timing.vback_porch.typ, priv->timing.vfront_porch.typ,
+               priv->timing.vsync_len.typ);
+
+       return 0;
+}
+
+static const struct panel_ops tilcdc_panel_ops = {
+       .enable_backlight = tilcdc_panel_enable_backlight,
+       .set_backlight = tilcdc_panel_set_backlight,
+       .get_display_timing = tilcdc_panel_get_display_timing,
+};
+
+static const struct udevice_id tilcdc_panel_ids[] = {
+       {.compatible = "ti,tilcdc,panel"},
+       {}
+};
+
+U_BOOT_DRIVER(tilcdc_panel) = {
+       .name = "tilcdc_panel",
+       .id = UCLASS_PANEL,
+       .of_match = tilcdc_panel_ids,
+       .ops = &tilcdc_panel_ops,
+       .ofdata_to_platdata = tilcdc_panel_of_to_plat,
+       .probe = tilcdc_panel_probe,
+       .remove = tilcdc_panel_remove,
+       .priv_auto = sizeof(struct tilcdc_panel_priv),
+};
diff --git a/drivers/video/tilcdc-panel.h b/drivers/video/tilcdc-panel.h
new file mode 100644 (file)
index 0000000..6b40731
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
+ */
+
+#ifndef _TILCDC_PANEL_H
+#define _TILCDC_PANEL_H
+
+#include "am335x-fb.h"
+
+int tilcdc_panel_get_display_info(struct udevice *dev,
+                                 struct tilcdc_panel_info *info);
+
+#endif /* _TILCDC_PANEL_H */