Home | History | Annotate | Download | only in stm32
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2017-2018 STMicroelectronics - All Rights Reserved
      4  * Author(s): Philippe Cornu <philippe.cornu (at) st.com> for STMicroelectronics.
      5  *	      Yannick Fertre <yannick.fertre (at) st.com> for STMicroelectronics.
      6  */
      7 
      8 #include <common.h>
      9 #include <clk.h>
     10 #include <dm.h>
     11 #include <panel.h>
     12 #include <reset.h>
     13 #include <video.h>
     14 #include <asm/io.h>
     15 #include <asm/arch/gpio.h>
     16 #include <dm/device-internal.h>
     17 
     18 DECLARE_GLOBAL_DATA_PTR;
     19 
     20 struct stm32_ltdc_priv {
     21 	void __iomem *regs;
     22 	struct display_timing timing;
     23 	enum video_log2_bpp l2bpp;
     24 	u32 bg_col_argb;
     25 	u32 crop_x, crop_y, crop_w, crop_h;
     26 	u32 alpha;
     27 };
     28 
     29 /* LTDC main registers */
     30 #define LTDC_IDR	0x00	/* IDentification */
     31 #define LTDC_LCR	0x04	/* Layer Count */
     32 #define LTDC_SSCR	0x08	/* Synchronization Size Configuration */
     33 #define LTDC_BPCR	0x0C	/* Back Porch Configuration */
     34 #define LTDC_AWCR	0x10	/* Active Width Configuration */
     35 #define LTDC_TWCR	0x14	/* Total Width Configuration */
     36 #define LTDC_GCR	0x18	/* Global Control */
     37 #define LTDC_GC1R	0x1C	/* Global Configuration 1 */
     38 #define LTDC_GC2R	0x20	/* Global Configuration 2 */
     39 #define LTDC_SRCR	0x24	/* Shadow Reload Configuration */
     40 #define LTDC_GACR	0x28	/* GAmma Correction */
     41 #define LTDC_BCCR	0x2C	/* Background Color Configuration */
     42 #define LTDC_IER	0x34	/* Interrupt Enable */
     43 #define LTDC_ISR	0x38	/* Interrupt Status */
     44 #define LTDC_ICR	0x3C	/* Interrupt Clear */
     45 #define LTDC_LIPCR	0x40	/* Line Interrupt Position Conf. */
     46 #define LTDC_CPSR	0x44	/* Current Position Status */
     47 #define LTDC_CDSR	0x48	/* Current Display Status */
     48 
     49 /* LTDC layer 1 registers */
     50 #define LTDC_L1LC1R	0x80	/* L1 Layer Configuration 1 */
     51 #define LTDC_L1LC2R	0x84	/* L1 Layer Configuration 2 */
     52 #define LTDC_L1CR	0x84	/* L1 Control */
     53 #define LTDC_L1WHPCR	0x88	/* L1 Window Hor Position Config */
     54 #define LTDC_L1WVPCR	0x8C	/* L1 Window Vert Position Config */
     55 #define LTDC_L1CKCR	0x90	/* L1 Color Keying Configuration */
     56 #define LTDC_L1PFCR	0x94	/* L1 Pixel Format Configuration */
     57 #define LTDC_L1CACR	0x98	/* L1 Constant Alpha Config */
     58 #define LTDC_L1DCCR	0x9C	/* L1 Default Color Configuration */
     59 #define LTDC_L1BFCR	0xA0	/* L1 Blend Factors Configuration */
     60 #define LTDC_L1FBBCR	0xA4	/* L1 FrameBuffer Bus Control */
     61 #define LTDC_L1AFBCR	0xA8	/* L1 AuxFB Control */
     62 #define LTDC_L1CFBAR	0xAC	/* L1 Color FrameBuffer Address */
     63 #define LTDC_L1CFBLR	0xB0	/* L1 Color FrameBuffer Length */
     64 #define LTDC_L1CFBLNR	0xB4	/* L1 Color FrameBuffer Line Nb */
     65 #define LTDC_L1AFBAR	0xB8	/* L1 AuxFB Address */
     66 #define LTDC_L1AFBLR	0xBC	/* L1 AuxFB Length */
     67 #define LTDC_L1AFBLNR	0xC0	/* L1 AuxFB Line Number */
     68 #define LTDC_L1CLUTWR	0xC4	/* L1 CLUT Write */
     69 
     70 /* Bit definitions */
     71 #define SSCR_VSH	GENMASK(10, 0)	/* Vertical Synchronization Height */
     72 #define SSCR_HSW	GENMASK(27, 16)	/* Horizontal Synchronization Width */
     73 
     74 #define BPCR_AVBP	GENMASK(10, 0)	/* Accumulated Vertical Back Porch */
     75 #define BPCR_AHBP	GENMASK(27, 16)	/* Accumulated Horizontal Back Porch */
     76 
     77 #define AWCR_AAH	GENMASK(10, 0)	/* Accumulated Active Height */
     78 #define AWCR_AAW	GENMASK(27, 16)	/* Accumulated Active Width */
     79 
     80 #define TWCR_TOTALH	GENMASK(10, 0)	/* TOTAL Height */
     81 #define TWCR_TOTALW	GENMASK(27, 16)	/* TOTAL Width */
     82 
     83 #define GCR_LTDCEN	BIT(0)		/* LTDC ENable */
     84 #define GCR_DEN		BIT(16)		/* Dither ENable */
     85 #define GCR_PCPOL	BIT(28)		/* Pixel Clock POLarity-Inverted */
     86 #define GCR_DEPOL	BIT(29)		/* Data Enable POLarity-High */
     87 #define GCR_VSPOL	BIT(30)		/* Vertical Synchro POLarity-High */
     88 #define GCR_HSPOL	BIT(31)		/* Horizontal Synchro POLarity-High */
     89 
     90 #define GC1R_WBCH	GENMASK(3, 0)	/* Width of Blue CHannel output */
     91 #define GC1R_WGCH	GENMASK(7, 4)	/* Width of Green Channel output */
     92 #define GC1R_WRCH	GENMASK(11, 8)	/* Width of Red Channel output */
     93 #define GC1R_PBEN	BIT(12)		/* Precise Blending ENable */
     94 #define GC1R_DT		GENMASK(15, 14)	/* Dithering Technique */
     95 #define GC1R_GCT	GENMASK(19, 17)	/* Gamma Correction Technique */
     96 #define GC1R_SHREN	BIT(21)		/* SHadow Registers ENabled */
     97 #define GC1R_BCP	BIT(22)		/* Background Colour Programmable */
     98 #define GC1R_BBEN	BIT(23)		/* Background Blending ENabled */
     99 #define GC1R_LNIP	BIT(24)		/* Line Number IRQ Position */
    100 #define GC1R_TP		BIT(25)		/* Timing Programmable */
    101 #define GC1R_IPP	BIT(26)		/* IRQ Polarity Programmable */
    102 #define GC1R_SPP	BIT(27)		/* Sync Polarity Programmable */
    103 #define GC1R_DWP	BIT(28)		/* Dither Width Programmable */
    104 #define GC1R_STREN	BIT(29)		/* STatus Registers ENabled */
    105 #define GC1R_BMEN	BIT(31)		/* Blind Mode ENabled */
    106 
    107 #define GC2R_EDCA	BIT(0)		/* External Display Control Ability  */
    108 #define GC2R_STSAEN	BIT(1)		/* Slave Timing Sync Ability ENabled */
    109 #define GC2R_DVAEN	BIT(2)		/* Dual-View Ability ENabled */
    110 #define GC2R_DPAEN	BIT(3)		/* Dual-Port Ability ENabled */
    111 #define GC2R_BW		GENMASK(6, 4)	/* Bus Width (log2 of nb of bytes) */
    112 #define GC2R_EDCEN	BIT(7)		/* External Display Control ENabled */
    113 
    114 #define SRCR_IMR	BIT(0)		/* IMmediate Reload */
    115 #define SRCR_VBR	BIT(1)		/* Vertical Blanking Reload */
    116 
    117 #define LXCR_LEN	BIT(0)		/* Layer ENable */
    118 #define LXCR_COLKEN	BIT(1)		/* Color Keying Enable */
    119 #define LXCR_CLUTEN	BIT(4)		/* Color Look-Up Table ENable */
    120 
    121 #define LXWHPCR_WHSTPOS	GENMASK(11, 0)	/* Window Horizontal StarT POSition */
    122 #define LXWHPCR_WHSPPOS	GENMASK(27, 16)	/* Window Horizontal StoP POSition */
    123 
    124 #define LXWVPCR_WVSTPOS	GENMASK(10, 0)	/* Window Vertical StarT POSition */
    125 #define LXWVPCR_WVSPPOS	GENMASK(26, 16)	/* Window Vertical StoP POSition */
    126 
    127 #define LXPFCR_PF	GENMASK(2, 0)	/* Pixel Format */
    128 
    129 #define LXCACR_CONSTA	GENMASK(7, 0)	/* CONSTant Alpha */
    130 
    131 #define LXBFCR_BF2	GENMASK(2, 0)	/* Blending Factor 2 */
    132 #define LXBFCR_BF1	GENMASK(10, 8)	/* Blending Factor 1 */
    133 
    134 #define LXCFBLR_CFBLL	GENMASK(12, 0)	/* Color Frame Buffer Line Length */
    135 #define LXCFBLR_CFBP	GENMASK(28, 16)	/* Color Frame Buffer Pitch in bytes */
    136 
    137 #define LXCFBLNR_CFBLN	GENMASK(10, 0)	/* Color Frame Buffer Line Number */
    138 
    139 #define BF1_PAXCA	0x600		/* Pixel Alpha x Constant Alpha */
    140 #define BF1_CA		0x400		/* Constant Alpha */
    141 #define BF2_1PAXCA	0x007		/* 1 - (Pixel Alpha x Constant Alpha) */
    142 #define BF2_1CA		0x005		/* 1 - Constant Alpha */
    143 
    144 enum stm32_ltdc_pix_fmt {
    145 	PF_ARGB8888 = 0,
    146 	PF_RGB888,
    147 	PF_RGB565,
    148 	PF_ARGB1555,
    149 	PF_ARGB4444,
    150 	PF_L8,
    151 	PF_AL44,
    152 	PF_AL88
    153 };
    154 
    155 /* TODO add more color format support */
    156 static u32 stm32_ltdc_get_pixel_format(enum video_log2_bpp l2bpp)
    157 {
    158 	enum stm32_ltdc_pix_fmt pf;
    159 
    160 	switch (l2bpp) {
    161 	case VIDEO_BPP16:
    162 		pf = PF_RGB565;
    163 		break;
    164 
    165 	case VIDEO_BPP32:
    166 		pf = PF_ARGB8888;
    167 		break;
    168 
    169 	case VIDEO_BPP8:
    170 		pf = PF_L8;
    171 		break;
    172 
    173 	case VIDEO_BPP1:
    174 	case VIDEO_BPP2:
    175 	case VIDEO_BPP4:
    176 	default:
    177 		debug("%s: warning %dbpp not supported yet, %dbpp instead\n",
    178 		      __func__, VNBITS(l2bpp), VNBITS(VIDEO_BPP16));
    179 		pf = PF_RGB565;
    180 		break;
    181 	}
    182 
    183 	debug("%s: %d bpp -> ltdc pf %d\n", __func__, VNBITS(l2bpp), pf);
    184 
    185 	return (u32)pf;
    186 }
    187 
    188 static bool has_alpha(u32 fmt)
    189 {
    190 	switch (fmt) {
    191 	case PF_ARGB8888:
    192 	case PF_ARGB1555:
    193 	case PF_ARGB4444:
    194 	case PF_AL44:
    195 	case PF_AL88:
    196 		return true;
    197 	case PF_RGB888:
    198 	case PF_RGB565:
    199 	case PF_L8:
    200 	default:
    201 		return false;
    202 	}
    203 }
    204 
    205 static void stm32_ltdc_enable(struct stm32_ltdc_priv *priv)
    206 {
    207 	/* Reload configuration immediately & enable LTDC */
    208 	setbits_le32(priv->regs + LTDC_SRCR, SRCR_IMR);
    209 	setbits_le32(priv->regs + LTDC_GCR, GCR_LTDCEN);
    210 }
    211 
    212 static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv)
    213 {
    214 	void __iomem *regs = priv->regs;
    215 	struct display_timing *timing = &priv->timing;
    216 	u32 hsync, vsync, acc_hbp, acc_vbp, acc_act_w, acc_act_h;
    217 	u32 total_w, total_h;
    218 	u32 val;
    219 
    220 	/* Convert video timings to ltdc timings */
    221 	hsync = timing->hsync_len.typ - 1;
    222 	vsync = timing->vsync_len.typ - 1;
    223 	acc_hbp = hsync + timing->hback_porch.typ;
    224 	acc_vbp = vsync + timing->vback_porch.typ;
    225 	acc_act_w = acc_hbp + timing->hactive.typ;
    226 	acc_act_h = acc_vbp + timing->vactive.typ;
    227 	total_w = acc_act_w + timing->hfront_porch.typ;
    228 	total_h = acc_act_h + timing->vfront_porch.typ;
    229 
    230 	/* Synchronization sizes */
    231 	val = (hsync << 16) | vsync;
    232 	clrsetbits_le32(regs + LTDC_SSCR, SSCR_VSH | SSCR_HSW, val);
    233 
    234 	/* Accumulated back porch */
    235 	val = (acc_hbp << 16) | acc_vbp;
    236 	clrsetbits_le32(regs + LTDC_BPCR, BPCR_AVBP | BPCR_AHBP, val);
    237 
    238 	/* Accumulated active width */
    239 	val = (acc_act_w << 16) | acc_act_h;
    240 	clrsetbits_le32(regs + LTDC_AWCR, AWCR_AAW | AWCR_AAH, val);
    241 
    242 	/* Total width & height */
    243 	val = (total_w << 16) | total_h;
    244 	clrsetbits_le32(regs + LTDC_TWCR, TWCR_TOTALH | TWCR_TOTALW, val);
    245 
    246 	setbits_le32(regs + LTDC_LIPCR, acc_act_h + 1);
    247 
    248 	/* Signal polarities */
    249 	val = 0;
    250 	debug("%s: timing->flags 0x%08x\n", __func__, timing->flags);
    251 	if (timing->flags & DISPLAY_FLAGS_HSYNC_HIGH)
    252 		val |= GCR_HSPOL;
    253 	if (timing->flags & DISPLAY_FLAGS_VSYNC_HIGH)
    254 		val |= GCR_VSPOL;
    255 	if (timing->flags & DISPLAY_FLAGS_DE_HIGH)
    256 		val |= GCR_DEPOL;
    257 	if (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
    258 		val |= GCR_PCPOL;
    259 	clrsetbits_le32(regs + LTDC_GCR,
    260 			GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val);
    261 
    262 	/* Overall background color */
    263 	writel(priv->bg_col_argb, priv->regs + LTDC_BCCR);
    264 }
    265 
    266 static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr)
    267 {
    268 	void __iomem *regs = priv->regs;
    269 	u32 x0, x1, y0, y1;
    270 	u32 pitch_in_bytes;
    271 	u32 line_length;
    272 	u32 bus_width;
    273 	u32 val, tmp, bpp;
    274 	u32 format;
    275 
    276 	x0 = priv->crop_x;
    277 	x1 = priv->crop_x + priv->crop_w - 1;
    278 	y0 = priv->crop_y;
    279 	y1 = priv->crop_y + priv->crop_h - 1;
    280 
    281 	/* Horizontal start and stop position */
    282 	tmp = (readl(regs + LTDC_BPCR) & BPCR_AHBP) >> 16;
    283 	val = ((x1 + 1 + tmp) << 16) + (x0 + 1 + tmp);
    284 	clrsetbits_le32(regs + LTDC_L1WHPCR, LXWHPCR_WHSTPOS | LXWHPCR_WHSPPOS,
    285 			val);
    286 
    287 	/* Vertical start & stop position */
    288 	tmp = readl(regs + LTDC_BPCR) & BPCR_AVBP;
    289 	val = ((y1 + 1 + tmp) << 16) + (y0 + 1 + tmp);
    290 	clrsetbits_le32(regs + LTDC_L1WVPCR, LXWVPCR_WVSTPOS | LXWVPCR_WVSPPOS,
    291 			val);
    292 
    293 	/* Layer background color */
    294 	writel(priv->bg_col_argb, regs + LTDC_L1DCCR);
    295 
    296 	/* Color frame buffer pitch in bytes & line length */
    297 	bpp = VNBITS(priv->l2bpp);
    298 	pitch_in_bytes = priv->crop_w * (bpp >> 3);
    299 	bus_width = 8 << ((readl(regs + LTDC_GC2R) & GC2R_BW) >> 4);
    300 	line_length = ((bpp >> 3) * priv->crop_w) + (bus_width >> 3) - 1;
    301 	val = (pitch_in_bytes << 16) | line_length;
    302 	clrsetbits_le32(regs + LTDC_L1CFBLR, LXCFBLR_CFBLL | LXCFBLR_CFBP, val);
    303 
    304 	/* Pixel format */
    305 	format = stm32_ltdc_get_pixel_format(priv->l2bpp);
    306 	clrsetbits_le32(regs + LTDC_L1PFCR, LXPFCR_PF, format);
    307 
    308 	/* Constant alpha value */
    309 	clrsetbits_le32(regs + LTDC_L1CACR, LXCACR_CONSTA, priv->alpha);
    310 
    311 	/* Specifies the blending factors : with or without pixel alpha */
    312 	/* Manage hw-specific capabilities */
    313 	val = has_alpha(format) ? BF1_PAXCA | BF2_1PAXCA : BF1_CA | BF2_1CA;
    314 
    315 	/* Blending factors */
    316 	clrsetbits_le32(regs + LTDC_L1BFCR, LXBFCR_BF2 | LXBFCR_BF1, val);
    317 
    318 	/* Frame buffer line number */
    319 	clrsetbits_le32(regs + LTDC_L1CFBLNR, LXCFBLNR_CFBLN, priv->crop_h);
    320 
    321 	/* Frame buffer address */
    322 	writel(fb_addr, regs + LTDC_L1CFBAR);
    323 
    324 	/* Enable layer 1 */
    325 	setbits_le32(priv->regs + LTDC_L1CR, LXCR_LEN);
    326 }
    327 
    328 static int stm32_ltdc_probe(struct udevice *dev)
    329 {
    330 	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
    331 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
    332 	struct stm32_ltdc_priv *priv = dev_get_priv(dev);
    333 	struct udevice *panel;
    334 	struct clk pclk;
    335 	struct reset_ctl rst;
    336 	int rate, ret;
    337 
    338 	priv->regs = (void *)dev_read_addr(dev);
    339 	if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) {
    340 		debug("%s: ltdc dt register address error\n", __func__);
    341 		return -EINVAL;
    342 	}
    343 
    344 	ret = clk_get_by_index(dev, 0, &pclk);
    345 	if (ret) {
    346 		debug("%s: peripheral clock get error %d\n", __func__, ret);
    347 		return ret;
    348 	}
    349 
    350 	ret = clk_enable(&pclk);
    351 	if (ret) {
    352 		debug("%s: peripheral clock enable error %d\n",
    353 		      __func__, ret);
    354 		return ret;
    355 	}
    356 
    357 	ret = reset_get_by_index(dev, 0, &rst);
    358 	if (ret) {
    359 		debug("%s: missing ltdc hardware reset\n", __func__);
    360 		return -ENODEV;
    361 	}
    362 
    363 	/* Reset */
    364 	reset_deassert(&rst);
    365 
    366 	ret = uclass_first_device(UCLASS_PANEL, &panel);
    367 	if (ret) {
    368 		debug("%s: panel device error %d\n", __func__, ret);
    369 		return ret;
    370 	}
    371 
    372 	ret = panel_enable_backlight(panel);
    373 	if (ret) {
    374 		debug("%s: panel %s enable backlight error %d\n",
    375 		      __func__, panel->name, ret);
    376 		return ret;
    377 	}
    378 
    379 	ret = fdtdec_decode_display_timing(gd->fdt_blob,
    380 					   dev_of_offset(dev), 0,
    381 					   &priv->timing);
    382 	if (ret) {
    383 		debug("%s: decode display timing error %d\n",
    384 		      __func__, ret);
    385 		return -EINVAL;
    386 	}
    387 
    388 	rate = clk_set_rate(&pclk, priv->timing.pixelclock.typ);
    389 	if (rate < 0) {
    390 		debug("%s: fail to set pixel clock %d hz %d hz\n",
    391 		      __func__, priv->timing.pixelclock.typ, rate);
    392 		return rate;
    393 	}
    394 
    395 	debug("%s: Set pixel clock req %d hz get %d hz\n", __func__,
    396 	      priv->timing.pixelclock.typ, rate);
    397 
    398 	/* TODO Below parameters are hard-coded for the moment... */
    399 	priv->l2bpp = VIDEO_BPP16;
    400 	priv->bg_col_argb = 0xFFFFFFFF; /* white no transparency */
    401 	priv->crop_x = 0;
    402 	priv->crop_y = 0;
    403 	priv->crop_w = priv->timing.hactive.typ;
    404 	priv->crop_h = priv->timing.vactive.typ;
    405 	priv->alpha = 0xFF;
    406 
    407 	debug("%s: %dx%d %dbpp frame buffer at 0x%lx\n", __func__,
    408 	      priv->timing.hactive.typ, priv->timing.vactive.typ,
    409 	      VNBITS(priv->l2bpp), uc_plat->base);
    410 	debug("%s: crop %d,%d %dx%d bg 0x%08x alpha %d\n", __func__,
    411 	      priv->crop_x, priv->crop_y, priv->crop_w, priv->crop_h,
    412 	      priv->bg_col_argb, priv->alpha);
    413 
    414 	/* Configure & start LTDC */
    415 	stm32_ltdc_set_mode(priv);
    416 	stm32_ltdc_set_layer1(priv, uc_plat->base);
    417 	stm32_ltdc_enable(priv);
    418 
    419 	uc_priv->xsize = priv->timing.hactive.typ;
    420 	uc_priv->ysize = priv->timing.vactive.typ;
    421 	uc_priv->bpix = priv->l2bpp;
    422 
    423 	video_set_flush_dcache(dev, true);
    424 
    425 	return 0;
    426 }
    427 
    428 static int stm32_ltdc_bind(struct udevice *dev)
    429 {
    430 	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
    431 
    432 	uc_plat->size = CONFIG_VIDEO_STM32_MAX_XRES *
    433 			CONFIG_VIDEO_STM32_MAX_YRES *
    434 			(CONFIG_VIDEO_STM32_MAX_BPP >> 3);
    435 	debug("%s: frame buffer max size %d bytes\n", __func__, uc_plat->size);
    436 
    437 	return 0;
    438 }
    439 
    440 static const struct udevice_id stm32_ltdc_ids[] = {
    441 	{ .compatible = "st,stm32-ltdc" },
    442 	{ }
    443 };
    444 
    445 U_BOOT_DRIVER(stm32_ltdc) = {
    446 	.name			= "stm32_display",
    447 	.id			= UCLASS_VIDEO,
    448 	.of_match		= stm32_ltdc_ids,
    449 	.probe			= stm32_ltdc_probe,
    450 	.bind			= stm32_ltdc_bind,
    451 	.priv_auto_alloc_size	= sizeof(struct stm32_ltdc_priv),
    452 };
    453