[PATCH 27/31] video: omap: enable LCD clock domain through DM API

The patch enables/disables the LCD domain clock when the device is probed/removed.
To get the LCD domain clock, the device tree had to be changed. In the Beaglebone device tree of the most recent Linux kernels, the LCD controller node is the child of a node that the documentation explains to be an interconnect module with one or more devices connected to it, which manages, among other things, even the clocks.
target-module@e000 { /* 0x4830e000, ap 72 4a.0 */ compatible = "ti,sysc-omap4", "ti,sysc"; reg = <0xe000 0x4>, <0xe054 0x4>; reg-names = "rev", "sysc"; ti,sysc-midle = <SYSC_IDLE_FORCE>, <SYSC_IDLE_NO>, <SYSC_IDLE_SMART>; ti,sysc-sidle = <SYSC_IDLE_FORCE>, <SYSC_IDLE_NO>, <SYSC_IDLE_SMART>; /* Domains (P, C): per_pwrdm, lcdc_clkdm */ clocks = <&lcdc_clkctrl AM3_LCDC_LCDC_CLKCTRL 0>; clock-names = "fck"; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe000 0x1000>;
lcdc: lcdc@0 { compatible = "ti,am33xx-tilcdc"; reg = <0x0 0x1000>; interrupts = <36>; status = "disabled"; }; };
This shows that the domain clock reference is missing in the U-Boot device tree and that replicating the most recent kernels structure in U-Boot is now to be avoided. Since the LCD controller node is not the child of any interconnection node in the current device tree, I added the domain clock reference inside the LCD controller node. I think getting the domain clock from the device tree and using the driver model API is still an improvement. In the future, when possible, we can move the domain clock in the interconnection module created for the LCD controller node.
Signed-off-by: Dario Binacchi dariobin@libero.it ---
arch/arm/dts/am33xx.dtsi | 3 +++ arch/arm/mach-omap2/am33xx/clock_am33xx.c | 2 +- drivers/video/am335x-fb.c | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/am33xx.dtsi b/arch/arm/dts/am33xx.dtsi index fa7492a9b6..2e123aab87 100644 --- a/arch/arm/dts/am33xx.dtsi +++ b/arch/arm/dts/am33xx.dtsi @@ -946,6 +946,9 @@ reg = <0x4830e000 0x1000>; interrupts = <36>; ti,hwmods = "lcdc"; + clocks = <&l4_per_clkctrl AM3_LCDC_CLKCTRL 0>; + clock-names = "fck"; + status = "disabled"; };
diff --git a/arch/arm/mach-omap2/am33xx/clock_am33xx.c b/arch/arm/mach-omap2/am33xx/clock_am33xx.c index 2427933c8b..cf71192360 100644 --- a/arch/arm/mach-omap2/am33xx/clock_am33xx.c +++ b/arch/arm/mach-omap2/am33xx/clock_am33xx.c @@ -226,7 +226,7 @@ void enable_basic_clocks(void) &cmper->usb0clkctrl, &cmper->emiffwclkctrl, &cmper->emifclkctrl, -#if CONFIG_IS_ENABLED(AM335X_LCD) +#if CONFIG_IS_ENABLED(AM335X_LCD) && !CONFIG_IS_ENABLED(DM_VIDEO) &cmper->lcdclkctrl, &cmper->lcdcclkstctrl, #endif diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c index dc959baa27..104f7891cc 100644 --- a/drivers/video/am335x-fb.c +++ b/drivers/video/am335x-fb.c @@ -12,6 +12,7 @@ * - starts output DMA from gd->fb_base buffer */ #include <common.h> +#include <clk.h> #include <dm.h> #include <lcd.h> #include <log.h> @@ -335,14 +336,17 @@ enum {
struct am335x_fb_priv { struct am335x_lcdhw *regs; + struct clk clkdm; };
static int am335x_fb_remove(struct udevice *dev) { struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + struct am335x_fb_priv *priv = dev_get_priv(dev);
uc_plat->base -= 0x20; uc_plat->size += 0x20; + clk_release_all(&priv->clkdm, 1); return 0; }
@@ -416,6 +420,18 @@ static int am335x_fb_probe(struct udevice *dev) return -EINVAL; }
+ err = clk_get_by_name(dev, "fck", &priv->clkdm); + if (err) { + dev_err(dev, "%s: failed to get clock domain\n", __func__); + return err; + } + + err = clk_enable(&priv->clkdm); + if (err) { + dev_err(dev, "%s: failed to enable clock domain\n", __func__); + return err; + } + am335x_fb_set_pixel_clk_rate(regs, timing.pixelclock.typ);
/* clock source for LCDC from dispPLL M2 */

The patch configures the display DPLL using the functions provided by the driver model API for the clock. The device tree contains everything needed to get the DPLL clock. The round rate function developed for calculating the DPLL multiplier and divisor and the platform routines for accessing the DPLL registers are removed from the LCD driver code because they are implemented inside the DPLL clock driver.
Signed-off-by: Dario Binacchi dariobin@libero.it ---
drivers/video/am335x-fb.c | 127 ++++++++++++++++++++++++++++++-------- 1 file changed, 101 insertions(+), 26 deletions(-)
diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c index 104f7891cc..021da5de3c 100644 --- a/drivers/video/am335x-fb.c +++ b/drivers/video/am335x-fb.c @@ -113,6 +113,27 @@ struct am335x_lcdhw { unsigned int clkc_reset; /* 0x70 */ };
+DECLARE_GLOBAL_DATA_PTR; + +#if !CONFIG_IS_ENABLED(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) & GENMASK(25, 20)) + +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; + return *line_length * panel_info.vl_row + 0x20; +} + struct dpll_data { unsigned long rounded_rate; u16 rounded_m; @@ -120,8 +141,6 @@ struct dpll_data { u8 rounded_div; };
-DECLARE_GLOBAL_DATA_PTR; - /** * am335x_dpll_round_rate() - Round a target rate for an OMAP DPLL * @@ -200,25 +219,6 @@ static ulong am335x_fb_set_pixel_clk_rate(struct am335x_lcdhw *regs, ulong rate) return round_rate; }
-#if !CONFIG_IS_ENABLED(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) & GENMASK(25, 20)) - -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; - return *line_length * panel_info.vl_row + 0x20; -} - int am335xfb_init(struct am335x_lcdpanel *panel) { u32 raster_ctrl = 0; @@ -337,8 +337,49 @@ enum { struct am335x_fb_priv { struct am335x_lcdhw *regs; struct clk clkdm; + struct clk gclk; + struct clk dpll_m2_clk; };
+static ulong tilcdc_set_pixel_clk_rate(struct udevice *dev, ulong rate) +{ + struct am335x_fb_priv *priv = dev_get_priv(dev); + struct am335x_lcdhw *regs = priv->regs; + ulong mult_rate, mult_round_rate, best_err, err; + u32 v; + int div, i; + + best_err = rate; + div = 0; + for (i = 2; i <= 255; i++) { + mult_rate = rate * i; + mult_round_rate = clk_round_rate(&priv->gclk, mult_rate); + if (IS_ERR_VALUE(mult_round_rate)) + return mult_round_rate; + + err = mult_rate - mult_round_rate; + if (err < best_err) { + best_err = err; + div = i; + if (err == 0) + break; + } + } + + if (div == 0) { + dev_err(dev, "failed to find a divisor\n"); + return -EFAULT; + } + + mult_rate = clk_set_rate(&priv->gclk, rate * div); + v = readl(®s->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK; + v |= LCDC_CTRL_CLK_DIVISOR(div); + writel(v, ®s->ctrl); + rate = mult_rate / div; + dev_dbg(dev, "rate=%ld, div=%d, err=%ld\n", rate, div, err); + return rate; +} + static int am335x_fb_remove(struct udevice *dev) { struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); @@ -346,6 +387,8 @@ static int am335x_fb_remove(struct udevice *dev)
uc_plat->base -= 0x20; uc_plat->size += 0x20; + clk_release_all(&priv->gclk, 1); + clk_release_all(&priv->dpll_m2_clk, 1); clk_release_all(&priv->clkdm, 1); return 0; } @@ -356,10 +399,10 @@ 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 udevice *panel; + struct udevice *panel, *clk_dev; struct tilcdc_panel_info info; struct display_timing timing; - struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL; + ulong rate; u32 reg; int err;
@@ -432,10 +475,42 @@ static int am335x_fb_probe(struct udevice *dev) return err; }
- am335x_fb_set_pixel_clk_rate(regs, timing.pixelclock.typ); + err = uclass_get_device_by_name(UCLASS_CLK, "lcd_gclk@534", &clk_dev); + if (err) { + dev_err(dev, "failed to get lcd_gclk device\n"); + return err; + } + + err = clk_request(clk_dev, &priv->gclk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + }
- /* clock source for LCDC from dispPLL M2 */ - writel(0, &cmdpll->clklcdcpixelclk); + rate = tilcdc_set_pixel_clk_rate(dev, timing.pixelclock.typ); + if (IS_ERR_VALUE(rate)) { + dev_err(dev, "failed to set pixel clock rate\n"); + return rate; + } + + err = uclass_get_device_by_name(UCLASS_CLK, "dpll_disp_m2_ck@4a4", &clk_dev); + if (err) { + dev_err(dev, "failed to get dpll_disp_m2 clock device\n"); + return err; + } + + err = clk_request(clk_dev, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + } + + err = clk_set_parent(&priv->gclk, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to set %s clock as %s's parent\n", + priv->dpll_m2_clk.dev->name, priv->gclk.dev->name); + return err; + }
/* palette default entry */ memset((void *)uc_plat->base, 0, 0x20);

The schedule for deprecating the features of the pre-driver-model puts 2019.17 as the deadline for the video subsystem. Furthermore, the latest patches applied to the am335x-fb.c module have decreased the amount of code shared with the pre-driver-model implementation. Splitting the two implementations into two modules improves the readability of the code and will make it easier to drop the pre-driver-model code. I have not created a header file with the data structures and the constants for accessing the LCD controller registers, but I preferred to keep them inside the two c modules. This is a code replication until the pre-driver-model version is dropped.
Signed-off-by: Dario Binacchi dariobin@libero.it ---
drivers/video/Makefile | 5 +- drivers/video/am335x-fb.c | 350 ---------------------------- drivers/video/am335x-fb.h | 35 --- drivers/video/tilcdc-panel.c | 2 +- drivers/video/tilcdc-panel.h | 2 +- drivers/video/tilcdc.c | 438 +++++++++++++++++++++++++++++++++++ drivers/video/tilcdc.h | 38 +++ 7 files changed, 481 insertions(+), 389 deletions(-) create mode 100644 drivers/video/tilcdc.c create mode 100644 drivers/video/tilcdc.h
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 132a63ecea..29f3434f7c 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -16,7 +16,9 @@ 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 +obj-$(CONFIG_AM335X_LCD) += tilcdc.o tilcdc-panel.o +else +obj-$(CONFIG_AM335X_LCD) += am335x-fb.o endif
obj-${CONFIG_EXYNOS_FB} += exynos/ @@ -24,7 +26,6 @@ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-${CONFIG_VIDEO_STM32} += stm32/ obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
-obj-$(CONFIG_AM335X_LCD) += am335x-fb.o obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o obj-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c index 021da5de3c..eb9d692035 100644 --- a/drivers/video/am335x-fb.c +++ b/drivers/video/am335x-fb.c @@ -12,22 +12,15 @@ * - starts output DMA from gd->fb_base buffer */ #include <common.h> -#include <clk.h> -#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> #include <asm/arch/omap.h> #include <asm/arch/sys_proto.h> #include <asm/io.h> -#include <asm/utils.h> #include <linux/delay.h> -#include <linux/err.h> #include "am335x-fb.h" -#include "tilcdc-panel.h"
#define LCDC_FMAX 200000000
@@ -115,8 +108,6 @@ struct am335x_lcdhw {
DECLARE_GLOBAL_DATA_PTR;
-#if !CONFIG_IS_ENABLED(DM_VIDEO) - #if !defined(LCD_CNTL_BASE) #error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!" #endif @@ -323,344 +314,3 @@ 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, -}; - -struct am335x_fb_priv { - struct am335x_lcdhw *regs; - struct clk clkdm; - struct clk gclk; - struct clk dpll_m2_clk; -}; - -static ulong tilcdc_set_pixel_clk_rate(struct udevice *dev, ulong rate) -{ - struct am335x_fb_priv *priv = dev_get_priv(dev); - struct am335x_lcdhw *regs = priv->regs; - ulong mult_rate, mult_round_rate, best_err, err; - u32 v; - int div, i; - - best_err = rate; - div = 0; - for (i = 2; i <= 255; i++) { - mult_rate = rate * i; - mult_round_rate = clk_round_rate(&priv->gclk, mult_rate); - if (IS_ERR_VALUE(mult_round_rate)) - return mult_round_rate; - - err = mult_rate - mult_round_rate; - if (err < best_err) { - best_err = err; - div = i; - if (err == 0) - break; - } - } - - if (div == 0) { - dev_err(dev, "failed to find a divisor\n"); - return -EFAULT; - } - - mult_rate = clk_set_rate(&priv->gclk, rate * div); - v = readl(®s->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK; - v |= LCDC_CTRL_CLK_DIVISOR(div); - writel(v, ®s->ctrl); - rate = mult_rate / div; - dev_dbg(dev, "rate=%ld, div=%d, err=%ld\n", rate, div, err); - return rate; -} - -static int am335x_fb_remove(struct udevice *dev) -{ - struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); - struct am335x_fb_priv *priv = dev_get_priv(dev); - - uc_plat->base -= 0x20; - uc_plat->size += 0x20; - clk_release_all(&priv->gclk, 1); - clk_release_all(&priv->dpll_m2_clk, 1); - clk_release_all(&priv->clkdm, 1); - 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 udevice *panel, *clk_dev; - struct tilcdc_panel_info info; - struct display_timing timing; - ulong rate; - u32 reg; - int err; - - /* Before relocation we don't need to do anything */ - if (!(gd->flags & GD_FLG_RELOC)) - return 0; - - 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; - } - - err = clk_get_by_name(dev, "fck", &priv->clkdm); - if (err) { - dev_err(dev, "%s: failed to get clock domain\n", __func__); - return err; - } - - err = clk_enable(&priv->clkdm); - if (err) { - dev_err(dev, "%s: failed to enable clock domain\n", __func__); - return err; - } - - err = uclass_get_device_by_name(UCLASS_CLK, "lcd_gclk@534", &clk_dev); - if (err) { - dev_err(dev, "failed to get lcd_gclk device\n"); - return err; - } - - err = clk_request(clk_dev, &priv->gclk); - if (err) { - dev_err(dev, "failed to get %s clock\n", clk_dev->name); - return err; - } - - rate = tilcdc_set_pixel_clk_rate(dev, timing.pixelclock.typ); - if (IS_ERR_VALUE(rate)) { - dev_err(dev, "failed to set pixel clock rate\n"); - return rate; - } - - err = uclass_get_device_by_name(UCLASS_CLK, "dpll_disp_m2_ck@4a4", &clk_dev); - if (err) { - dev_err(dev, "failed to get dpll_disp_m2 clock device\n"); - return err; - } - - err = clk_request(clk_dev, &priv->dpll_m2_clk); - if (err) { - dev_err(dev, "failed to get %s clock\n", clk_dev->name); - return err; - } - - err = clk_set_parent(&priv->gclk, &priv->dpll_m2_clk); - if (err) { - dev_err(dev, "failed to set %s clock as %s's parent\n", - priv->dpll_m2_clk.dev->name, priv->gclk.dev->name); - return err; - } - - /* palette default entry */ - memset((void *)uc_plat->base, 0, 0x20); - *(unsigned int *)uc_plat->base = 0x4000; - /* point fb behind palette */ - uc_plat->base += 0x20; - uc_plat->size -= 0x20; - - writel(LCDC_CLKC_ENABLE_CORECLKEN | LCDC_CLKC_ENABLE_LIDDCLKEN | - LCDC_CLKC_ENABLE_DMACLKEN, ®s->clkc_enable); - writel(0, ®s->raster_ctrl); - - reg = readl(®s->ctrl) & LCDC_CTRL_CLK_DIVISOR_MASK; - reg |= LCDC_CTRL_RASTER_MODE; - writel(reg, ®s->ctrl); - - writel(uc_plat->base, ®s->lcddma_fb0_base); - writel(uc_plat->base + FBSIZE(timing, info), - ®s->lcddma_fb0_ceiling); - writel(uc_plat->base, ®s->lcddma_fb1_base); - writel(uc_plat->base + FBSIZE(timing, info), - ®s->lcddma_fb1_ceiling); - - 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; - case 2: - reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_2); - break; - case 4: - reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_4); - break; - case 8: - reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_8); - break; - case 16: - reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16); - break; - } - - writel(reg, ®s->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), - ®s->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), - ®s->raster_timing1); - - 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) - reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT; - - if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW) - reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT; - - if (info.invert_pxl_clk) - reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT; - - if (info.sync_edge) - reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL; - - if (info.sync_ctrl) - reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL; - - writel(reg, ®s->raster_timing2); - - reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE | - LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(info.fdd); - - if (info.tft_alt_mode) - reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE; - - if (info.bpp == 24) - reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE; - else if (info.bpp == 32) - reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE | - LCDC_RASTER_CTRL_TFT_24BPP_UNPACK; - - if (info.raster_order) - reg |= LCDC_RASTER_CTRL_DATA_ORDER; - - writel(reg, ®s->raster_ctrl); - - uc_priv->xsize = timing.hactive.typ; - uc_priv->ysize = timing.vactive.typ; - uc_priv->bpix = log_2_n_round_up(info.bpp); - - err = panel_enable_backlight(panel); - if (err) { - dev_err(dev, "failed to enable panel backlight\n"); - return err; - } - - return 0; -} - -static int am335x_fb_ofdata_to_platdata(struct udevice *dev) -{ - struct am335x_fb_priv *priv = dev_get_priv(dev); - - 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; - } - - dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs); - return 0; -} - -static int am335x_fb_bind(struct udevice *dev) -{ - struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); - - uc_plat->size = ((LCD_MAX_WIDTH * LCD_MAX_HEIGHT * - (1 << LCD_MAX_LOG2_BPP)) >> 3) + 0x20; - - dev_dbg(dev, "frame buffer size 0x%x\n", uc_plat->size); - return 0; -} - -static const struct udevice_id am335x_fb_ids[] = { - { .compatible = "ti,am33xx-tilcdc" }, - { } -}; - -U_BOOT_DRIVER(am335x_fb) = { - .name = "am335x_fb", - .id = UCLASS_VIDEO, - .of_match = am335x_fb_ids, - .bind = am335x_fb_bind, - .ofdata_to_platdata = am335x_fb_ofdata_to_platdata, - .probe = am335x_fb_probe, - .remove = am335x_fb_remove, - .priv_auto_alloc_size = sizeof(struct am335x_fb_priv), -}; - -#endif /* CONFIG_DM_VIDEO */ diff --git a/drivers/video/am335x-fb.h b/drivers/video/am335x-fb.h index 4952dd96e9..ad9b015e09 100644 --- a/drivers/video/am335x-fb.h +++ b/drivers/video/am335x-fb.h @@ -7,8 +7,6 @@ #ifndef AM335X_FB_H #define AM335X_FB_H
-#if !CONFIG_IS_ENABLED(DM_VIDEO) - #define HSVS_CONTROL BIT(25) /* * 0 = lcd_lp and lcd_fp are driven on * opposite edges of pixel clock than @@ -70,37 +68,4 @@ 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 index 911e9b4c73..930523bf5e 100644 --- a/drivers/video/tilcdc-panel.c +++ b/drivers/video/tilcdc-panel.c @@ -14,7 +14,7 @@ #include <panel.h> #include <asm/gpio.h> #include <linux/err.h> -#include "am335x-fb.h" +#include "tilcdc.h"
struct tilcdc_panel_priv { struct tilcdc_panel_info info; diff --git a/drivers/video/tilcdc-panel.h b/drivers/video/tilcdc-panel.h index 6b40731304..6bcfbf8a8b 100644 --- a/drivers/video/tilcdc-panel.h +++ b/drivers/video/tilcdc-panel.h @@ -6,7 +6,7 @@ #ifndef _TILCDC_PANEL_H #define _TILCDC_PANEL_H
-#include "am335x-fb.h" +#include "tilcdc.h"
int tilcdc_panel_get_display_info(struct udevice *dev, struct tilcdc_panel_info *info); diff --git a/drivers/video/tilcdc.c b/drivers/video/tilcdc.c new file mode 100644 index 0000000000..32de3c9edc --- /dev/null +++ b/drivers/video/tilcdc.c @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Dario Binacchi dariobin@libero.it + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <lcd.h> +#include <log.h> +#include <panel.h> +#include <video.h> +#include <asm/io.h> +#include <asm/utils.h> +#include "tilcdc.h" +#include "tilcdc-panel.h" + +#define LCDC_FMAX 200000000 + +/* LCD Control Register */ +#define LCDC_CTRL_CLK_DIVISOR_MASK GENMASK(15, 8) +#define LCDC_CTRL_RASTER_MODE BIT(0) +#define LCDC_CTRL_CLK_DIVISOR(x) (((x) & GENMASK(7, 0)) << 8) +/* LCD Clock Enable Register */ +#define LCDC_CLKC_ENABLE_CORECLKEN BIT(0) +#define LCDC_CLKC_ENABLE_LIDDCLKEN BIT(1) +#define LCDC_CLKC_ENABLE_DMACLKEN BIT(2) +/* LCD DMA Control Register */ +#define LCDC_DMA_CTRL_BURST_SIZE(x) (((x) & GENMASK(2, 0)) << 4) +#define LCDC_DMA_CTRL_BURST_1 0x0 +#define LCDC_DMA_CTRL_BURST_2 0x1 +#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) & GENMASK(2, 0)) << 8) +/* LCD Timing_0 Register */ +#define LCDC_RASTER_TIMING_0_HORMSB(x) ((((x) - 1) & BIT(10)) >> 7) +#define LCDC_RASTER_TIMING_0_HORLSB(x) (((((x) >> 4) - 1) & GENMASK(5, 0)) << 4) +#define LCDC_RASTER_TIMING_0_HSWLSB(x) ((((x) - 1) & GENMASK(5, 0)) << 10) +#define LCDC_RASTER_TIMING_0_HFPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 16) +#define LCDC_RASTER_TIMING_0_HBPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 24) +/* LCD Timing_1 Register */ +#define LCDC_RASTER_TIMING_1_VERLSB(x) (((x) - 1) & GENMASK(9, 0)) +#define LCDC_RASTER_TIMING_1_VSW(x) ((((x) - 1) & GENMASK(5, 0)) << 10) +#define LCDC_RASTER_TIMING_1_VFP(x) (((x) & GENMASK(7, 0)) << 16) +#define LCDC_RASTER_TIMING_1_VBP(x) (((x) & GENMASK(7, 0)) << 24) +/* LCD Timing_2 Register */ +#define LCDC_RASTER_TIMING_2_HFPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 8) +#define LCDC_RASTER_TIMING_2_HBPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 4) +#define LCDC_RASTER_TIMING_2_ACB(x) (((x) & GENMASK(7, 0)) << 8) +#define LCDC_RASTER_TIMING_2_ACBI(x) (((x) & GENMASK(3, 0)) << 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) & BIT(10)) << 16) +#define LCDC_RASTER_TIMING_2_HSWMSB(x) ((((x) - 1) & GENMASK(9, 6)) << 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) & GENMASK(7, 0)) << 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) + +enum { + LCDC_MAX_WIDTH = 2048, + LCDC_MAX_HEIGHT = 2048, + LCDC_MAX_LOG2_BPP = VIDEO_BPP32, +}; + +struct tilcdc_regs { + u32 pid; + u32 ctrl; + u32 gap0; + u32 lidd_ctrl; + u32 lidd_cs0_conf; + u32 lidd_cs0_addr; + u32 lidd_cs0_data; + u32 lidd_cs1_conf; + u32 lidd_cs1_addr; + u32 lidd_cs1_data; + u32 raster_ctrl; + u32 raster_timing0; + u32 raster_timing1; + u32 raster_timing2; + u32 raster_subpanel; + u32 raster_subpanel2; + u32 lcddma_ctrl; + u32 lcddma_fb0_base; + u32 lcddma_fb0_ceiling; + u32 lcddma_fb1_base; + u32 lcddma_fb1_ceiling; + u32 sysconfig; + u32 irqstatus_raw; + u32 irqstatus; + u32 irqenable_set; + u32 irqenable_clear; + u32 gap1; + u32 clkc_enable; + u32 clkc_reset; +}; + +struct tilcdc_priv { + struct tilcdc_regs *regs; + struct clk clkdm; + struct clk gclk; + struct clk dpll_m2_clk; +}; + +DECLARE_GLOBAL_DATA_PTR; + +static ulong tilcdc_set_pixel_clk_rate(struct udevice *dev, ulong rate) +{ + struct tilcdc_priv *priv = dev_get_priv(dev); + struct tilcdc_regs *regs = priv->regs; + ulong mult_rate, mult_round_rate, best_err, err; + u32 v; + int div, i; + + best_err = rate; + div = 0; + for (i = 2; i <= 255; i++) { + mult_rate = rate * i; + mult_round_rate = clk_round_rate(&priv->gclk, mult_rate); + if (IS_ERR_VALUE(mult_round_rate)) + return mult_round_rate; + + err = mult_rate - mult_round_rate; + if (err < best_err) { + best_err = err; + div = i; + if (err == 0) + break; + } + } + + if (div == 0) { + dev_err(dev, "failed to find a divisor\n"); + return -EFAULT; + } + + mult_rate = clk_set_rate(&priv->gclk, rate * div); + v = readl(®s->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK; + v |= LCDC_CTRL_CLK_DIVISOR(div); + writel(v, ®s->ctrl); + rate = mult_rate / div; + dev_dbg(dev, "rate=%ld, div=%d, err=%ld\n", rate, div, err); + return rate; +} + +static int tilcdc_remove(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + struct tilcdc_priv *priv = dev_get_priv(dev); + + uc_plat->base -= 0x20; + uc_plat->size += 0x20; + clk_release_all(&priv->gclk, 1); + clk_release_all(&priv->dpll_m2_clk, 1); + clk_release_all(&priv->clkdm, 1); + return 0; +} + +static int tilcdc_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 tilcdc_priv *priv = dev_get_priv(dev); + struct tilcdc_regs *regs = priv->regs; + struct udevice *panel, *clk_dev; + struct tilcdc_panel_info info; + struct display_timing timing; + ulong rate; + u32 reg; + int err; + + /* Before relocation we don't need to do anything */ + if (!(gd->flags & GD_FLG_RELOC)) + return 0; + + 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 > LCDC_MAX_WIDTH) + timing.hactive.typ = LCDC_MAX_WIDTH; + + if (timing.vactive.typ > LCDC_MAX_HEIGHT) + timing.vactive.typ = LCDC_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; + } + + err = clk_get_by_name(dev, "fck", &priv->clkdm); + if (err) { + dev_err(dev, "%s: failed to get clock domain\n", __func__); + return err; + } + + err = clk_enable(&priv->clkdm); + if (err) { + dev_err(dev, "%s: failed to enable clock domain\n", __func__); + return err; + } + + err = uclass_get_device_by_name(UCLASS_CLK, "lcd_gclk@534", &clk_dev); + if (err) { + dev_err(dev, "failed to get lcd_gclk device\n"); + return err; + } + + err = clk_request(clk_dev, &priv->gclk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + } + + rate = tilcdc_set_pixel_clk_rate(dev, timing.pixelclock.typ); + if (IS_ERR_VALUE(rate)) { + dev_err(dev, "failed to set pixel clock rate\n"); + return rate; + } + + err = uclass_get_device_by_name(UCLASS_CLK, "dpll_disp_m2_ck@4a4", + &clk_dev); + if (err) { + dev_err(dev, "failed to get dpll_disp_m2 clock device\n"); + return err; + } + + err = clk_request(clk_dev, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + } + + err = clk_set_parent(&priv->gclk, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to set %s clock as %s's parent\n", + priv->dpll_m2_clk.dev->name, priv->gclk.dev->name); + return err; + } + + /* palette default entry */ + memset((void *)uc_plat->base, 0, 0x20); + *(unsigned int *)uc_plat->base = 0x4000; + /* point fb behind palette */ + uc_plat->base += 0x20; + uc_plat->size -= 0x20; + + writel(LCDC_CLKC_ENABLE_CORECLKEN | LCDC_CLKC_ENABLE_LIDDCLKEN | + LCDC_CLKC_ENABLE_DMACLKEN, ®s->clkc_enable); + writel(0, ®s->raster_ctrl); + + reg = readl(®s->ctrl) & LCDC_CTRL_CLK_DIVISOR_MASK; + reg |= LCDC_CTRL_RASTER_MODE; + writel(reg, ®s->ctrl); + + reg = (timing.hactive.typ * timing.vactive.typ * info.bpp) >> 3; + reg += uc_plat->base; + writel(uc_plat->base, ®s->lcddma_fb0_base); + writel(reg, ®s->lcddma_fb0_ceiling); + writel(uc_plat->base, ®s->lcddma_fb1_base); + writel(reg, ®s->lcddma_fb1_ceiling); + + 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; + case 2: + reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_2); + break; + case 4: + reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_4); + break; + case 8: + reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_8); + break; + case 16: + reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16); + break; + } + + writel(reg, ®s->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), + ®s->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), + ®s->raster_timing1); + + 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) + reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT; + + if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW) + reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT; + + if (info.invert_pxl_clk) + reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT; + + if (info.sync_edge) + reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL; + + if (info.sync_ctrl) + reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL; + + writel(reg, ®s->raster_timing2); + + reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE | + LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(info.fdd); + + if (info.tft_alt_mode) + reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE; + + if (info.bpp == 24) + reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE; + else if (info.bpp == 32) + reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE | + LCDC_RASTER_CTRL_TFT_24BPP_UNPACK; + + if (info.raster_order) + reg |= LCDC_RASTER_CTRL_DATA_ORDER; + + writel(reg, ®s->raster_ctrl); + + uc_priv->xsize = timing.hactive.typ; + uc_priv->ysize = timing.vactive.typ; + uc_priv->bpix = log_2_n_round_up(info.bpp); + + err = panel_enable_backlight(panel); + if (err) { + dev_err(dev, "failed to enable panel backlight\n"); + return err; + } + + return 0; +} + +static int tilcdc_ofdata_to_platdata(struct udevice *dev) +{ + struct tilcdc_priv *priv = dev_get_priv(dev); + + priv->regs = (struct tilcdc_regs *)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; + } + + dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs); + return 0; +} + +static int tilcdc_bind(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + + uc_plat->size = ((LCDC_MAX_WIDTH * LCDC_MAX_HEIGHT * + (1 << LCDC_MAX_LOG2_BPP)) >> 3) + 0x20; + + dev_dbg(dev, "frame buffer size 0x%x\n", uc_plat->size); + return 0; +} + +static const struct udevice_id tilcdc_ids[] = { + {.compatible = "ti,am33xx-tilcdc"}, + {} +}; + +U_BOOT_DRIVER(tilcdc) = { + .name = "tilcdc", + .id = UCLASS_VIDEO, + .of_match = tilcdc_ids, + .bind = tilcdc_bind, + .ofdata_to_platdata = tilcdc_ofdata_to_platdata, + .probe = tilcdc_probe, + .remove = tilcdc_remove, + .priv_auto_alloc_size = sizeof(struct tilcdc_priv) +}; diff --git a/drivers/video/tilcdc.h b/drivers/video/tilcdc.h new file mode 100644 index 0000000000..2645921df6 --- /dev/null +++ b/drivers/video/tilcdc.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Dario Binacchi dariobin@libero.it + */ + +#ifndef _TILCDC_H +#define _TILCDC_H + +/** + * 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 /* _TILCDC_H */

Add drivers/video/ti/ folder and move all TI's code in this folder for better maintenance.
Signed-off-by: Dario Binacchi dariobin@libero.it ---
drivers/video/Kconfig | 5 +---- drivers/video/Makefile | 4 +--- drivers/video/ti/Kconfig | 8 ++++++++ drivers/video/ti/Makefile | 10 ++++++++++ drivers/video/{ => ti}/am335x-fb.c | 0 drivers/video/{ => ti}/am335x-fb.h | 0 drivers/video/{ => ti}/tilcdc-panel.c | 0 drivers/video/{ => ti}/tilcdc-panel.h | 0 drivers/video/{ => ti}/tilcdc.c | 0 drivers/video/{ => ti}/tilcdc.h | 0 10 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 drivers/video/ti/Kconfig create mode 100644 drivers/video/ti/Makefile rename drivers/video/{ => ti}/am335x-fb.c (100%) rename drivers/video/{ => ti}/am335x-fb.h (100%) rename drivers/video/{ => ti}/tilcdc-panel.c (100%) rename drivers/video/{ => ti}/tilcdc-panel.h (100%) rename drivers/video/{ => ti}/tilcdc.c (100%) rename drivers/video/{ => ti}/tilcdc.h (100%)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e2e1f9c476..31a6d84e20 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -546,10 +546,7 @@ config ATMEL_HLCD help HLCDC supports video output to an attached LCD panel.
-config AM335X_LCD - bool "Enable AM335x video support" - help - Supports video output to an attached LCD panel. +source "drivers/video/ti/Kconfig"
config LOGICORE_DP_TX bool "Enable Logicore DP TX driver" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 29f3434f7c..38e181a779 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -16,15 +16,13 @@ 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.o tilcdc-panel.o -else -obj-$(CONFIG_AM335X_LCD) += am335x-fb.o endif
obj-${CONFIG_EXYNOS_FB} += exynos/ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-${CONFIG_VIDEO_STM32} += stm32/ obj-${CONFIG_VIDEO_TEGRA124} += tegra124/ +obj-${CONFIG_AM335X_LCD} += ti/
obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o diff --git a/drivers/video/ti/Kconfig b/drivers/video/ti/Kconfig new file mode 100644 index 0000000000..3081e9e8c0 --- /dev/null +++ b/drivers/video/ti/Kconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Dario Binacchi dariobin@libero.it +# +config AM335X_LCD + bool "Enable AM335x video support" + help + Supports video output to an attached LCD panel. diff --git a/drivers/video/ti/Makefile b/drivers/video/ti/Makefile new file mode 100644 index 0000000000..f0410debf4 --- /dev/null +++ b/drivers/video/ti/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Dario Binacchi dariobin@libero.it +# + +ifdef CONFIG_DM +obj-$(CONFIG_AM335X_LCD) += tilcdc.o tilcdc-panel.o +else +obj-$(CONFIG_AM335X_LCD) += am335x-fb.o +endif diff --git a/drivers/video/am335x-fb.c b/drivers/video/ti/am335x-fb.c similarity index 100% rename from drivers/video/am335x-fb.c rename to drivers/video/ti/am335x-fb.c diff --git a/drivers/video/am335x-fb.h b/drivers/video/ti/am335x-fb.h similarity index 100% rename from drivers/video/am335x-fb.h rename to drivers/video/ti/am335x-fb.h diff --git a/drivers/video/tilcdc-panel.c b/drivers/video/ti/tilcdc-panel.c similarity index 100% rename from drivers/video/tilcdc-panel.c rename to drivers/video/ti/tilcdc-panel.c diff --git a/drivers/video/tilcdc-panel.h b/drivers/video/ti/tilcdc-panel.h similarity index 100% rename from drivers/video/tilcdc-panel.h rename to drivers/video/ti/tilcdc-panel.h diff --git a/drivers/video/tilcdc.c b/drivers/video/ti/tilcdc.c similarity index 100% rename from drivers/video/tilcdc.c rename to drivers/video/ti/tilcdc.c diff --git a/drivers/video/tilcdc.h b/drivers/video/ti/tilcdc.h similarity index 100% rename from drivers/video/tilcdc.h rename to drivers/video/ti/tilcdc.h

With support for other clock drivers, the potentially supported CDCE913 device can no longer be probed without specifying its DT node name.
Signed-off-by: Dario Binacchi dariobin@libero.it
---
board/ti/am335x/board.c | 2 +- board/ti/am43xx/board.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index 984cc5e3ba..e1f64859cf 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -879,7 +879,7 @@ int board_late_init(void) }
/* Just probe the potentially supported cdce913 device */ - uclass_get_device(UCLASS_CLK, 0, &dev); + uclass_get_device_by_name(UCLASS_CLK, "cdce913@65", &dev);
return 0; } diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index de49590031..62ed37cb48 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -744,7 +744,7 @@ int board_late_init(void) #endif
/* Just probe the potentially supported cdce913 device */ - uclass_get_device(UCLASS_CLK, 0, &dev); + uclass_get_device_by_name(UCLASS_CLK, "cdce913@65", &dev);
return 0; }
participants (1)
-
Dario Binacchi