1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it> 4 */ 5 6#include <common.h> 7#include <clk.h> 8#include <dm.h> 9#include <dm/device_compat.h> 10#include <log.h> 11#include <panel.h> 12#include <video.h> 13#include <asm/global_data.h> 14#include <asm/io.h> 15#include <asm/utils.h> 16#include "tilcdc.h" 17#include "tilcdc-panel.h" 18 19#define LCDC_FMAX 200000000 20 21/* LCD Control Register */ 22#define LCDC_CTRL_CLK_DIVISOR_MASK GENMASK(15, 8) 23#define LCDC_CTRL_RASTER_MODE BIT(0) 24#define LCDC_CTRL_CLK_DIVISOR(x) (((x) & GENMASK(7, 0)) << 8) 25/* LCD Clock Enable Register */ 26#define LCDC_CLKC_ENABLE_CORECLKEN BIT(0) 27#define LCDC_CLKC_ENABLE_LIDDCLKEN BIT(1) 28#define LCDC_CLKC_ENABLE_DMACLKEN BIT(2) 29/* LCD DMA Control Register */ 30#define LCDC_DMA_CTRL_BURST_SIZE(x) (((x) & GENMASK(2, 0)) << 4) 31#define LCDC_DMA_CTRL_BURST_1 0x0 32#define LCDC_DMA_CTRL_BURST_2 0x1 33#define LCDC_DMA_CTRL_BURST_4 0x2 34#define LCDC_DMA_CTRL_BURST_8 0x3 35#define LCDC_DMA_CTRL_BURST_16 0x4 36#define LCDC_DMA_CTRL_FIFO_TH(x) (((x) & GENMASK(2, 0)) << 8) 37/* LCD Timing_0 Register */ 38#define LCDC_RASTER_TIMING_0_HORMSB(x) ((((x) - 1) & BIT(10)) >> 7) 39#define LCDC_RASTER_TIMING_0_HORLSB(x) (((((x) >> 4) - 1) & GENMASK(5, 0)) << 4) 40#define LCDC_RASTER_TIMING_0_HSWLSB(x) ((((x) - 1) & GENMASK(5, 0)) << 10) 41#define LCDC_RASTER_TIMING_0_HFPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 16) 42#define LCDC_RASTER_TIMING_0_HBPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 24) 43/* LCD Timing_1 Register */ 44#define LCDC_RASTER_TIMING_1_VERLSB(x) (((x) - 1) & GENMASK(9, 0)) 45#define LCDC_RASTER_TIMING_1_VSW(x) ((((x) - 1) & GENMASK(5, 0)) << 10) 46#define LCDC_RASTER_TIMING_1_VFP(x) (((x) & GENMASK(7, 0)) << 16) 47#define LCDC_RASTER_TIMING_1_VBP(x) (((x) & GENMASK(7, 0)) << 24) 48/* LCD Timing_2 Register */ 49#define LCDC_RASTER_TIMING_2_HFPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 8) 50#define LCDC_RASTER_TIMING_2_HBPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 4) 51#define LCDC_RASTER_TIMING_2_ACB(x) (((x) & GENMASK(7, 0)) << 8) 52#define LCDC_RASTER_TIMING_2_ACBI(x) (((x) & GENMASK(3, 0)) << 16) 53#define LCDC_RASTER_TIMING_2_VSYNC_INVERT BIT(20) 54#define LCDC_RASTER_TIMING_2_HSYNC_INVERT BIT(21) 55#define LCDC_RASTER_TIMING_2_PXCLK_INVERT BIT(22) 56#define LCDC_RASTER_TIMING_2_DE_INVERT BIT(23) 57#define LCDC_RASTER_TIMING_2_HSVS_RISEFALL BIT(24) 58#define LCDC_RASTER_TIMING_2_HSVS_CONTROL BIT(25) 59#define LCDC_RASTER_TIMING_2_VERMSB(x) ((((x) - 1) & BIT(10)) << 16) 60#define LCDC_RASTER_TIMING_2_HSWMSB(x) ((((x) - 1) & GENMASK(9, 6)) << 21) 61/* LCD Raster Ctrl Register */ 62#define LCDC_RASTER_CTRL_ENABLE BIT(0) 63#define LCDC_RASTER_CTRL_TFT_MODE BIT(7) 64#define LCDC_RASTER_CTRL_DATA_ORDER BIT(8) 65#define LCDC_RASTER_CTRL_REQDLY(x) (((x) & GENMASK(7, 0)) << 12) 66#define LCDC_RASTER_CTRL_PALMODE_RAWDATA (0x02 << 20) 67#define LCDC_RASTER_CTRL_TFT_ALT_ENABLE BIT(23) 68#define LCDC_RASTER_CTRL_TFT_24BPP_MODE BIT(25) 69#define LCDC_RASTER_CTRL_TFT_24BPP_UNPACK BIT(26) 70 71enum { 72 LCDC_MAX_WIDTH = 2048, 73 LCDC_MAX_HEIGHT = 2048, 74 LCDC_MAX_LOG2_BPP = VIDEO_BPP32, 75}; 76 77struct tilcdc_regs { 78 u32 pid; 79 u32 ctrl; 80 u32 gap0; 81 u32 lidd_ctrl; 82 u32 lidd_cs0_conf; 83 u32 lidd_cs0_addr; 84 u32 lidd_cs0_data; 85 u32 lidd_cs1_conf; 86 u32 lidd_cs1_addr; 87 u32 lidd_cs1_data; 88 u32 raster_ctrl; 89 u32 raster_timing0; 90 u32 raster_timing1; 91 u32 raster_timing2; 92 u32 raster_subpanel; 93 u32 raster_subpanel2; 94 u32 lcddma_ctrl; 95 u32 lcddma_fb0_base; 96 u32 lcddma_fb0_ceiling; 97 u32 lcddma_fb1_base; 98 u32 lcddma_fb1_ceiling; 99 u32 sysconfig; 100 u32 irqstatus_raw; 101 u32 irqstatus; 102 u32 irqenable_set; 103 u32 irqenable_clear; 104 u32 gap1; 105 u32 clkc_enable; 106 u32 clkc_reset; 107}; 108 109struct tilcdc_priv { 110 struct tilcdc_regs *regs; 111 struct clk gclk; 112 struct clk dpll_m2_clk; 113}; 114 115DECLARE_GLOBAL_DATA_PTR; 116 117static ulong tilcdc_set_pixel_clk_rate(struct udevice *dev, ulong rate) 118{ 119 struct tilcdc_priv *priv = dev_get_priv(dev); 120 struct tilcdc_regs *regs = priv->regs; 121 ulong mult_rate, mult_round_rate, best_err, err; 122 u32 v; 123 int div, i; 124 125 best_err = rate; 126 div = 0; 127 for (i = 2; i <= 255; i++) { 128 mult_rate = rate * i; 129 mult_round_rate = clk_round_rate(&priv->gclk, mult_rate); 130 if (IS_ERR_VALUE(mult_round_rate)) 131 return mult_round_rate; 132 133 err = mult_rate - mult_round_rate; 134 if (err < best_err) { 135 best_err = err; 136 div = i; 137 if (err == 0) 138 break; 139 } 140 } 141 142 if (div == 0) { 143 dev_err(dev, "failed to find a divisor\n"); 144 return -EFAULT; 145 } 146 147 mult_rate = clk_set_rate(&priv->gclk, rate * div); 148 v = readl(®s->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK; 149 v |= LCDC_CTRL_CLK_DIVISOR(div); 150 writel(v, ®s->ctrl); 151 rate = mult_rate / div; 152 dev_dbg(dev, "rate=%ld, div=%d, err=%ld\n", rate, div, err); 153 return rate; 154} 155 156static int tilcdc_remove(struct udevice *dev) 157{ 158 struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); 159 struct tilcdc_priv *priv = dev_get_priv(dev); 160 161 uc_plat->base -= 0x20; 162 uc_plat->size += 0x20; 163 clk_release_all(&priv->gclk, 1); 164 clk_release_all(&priv->dpll_m2_clk, 1); 165 return 0; 166} 167 168static int tilcdc_probe(struct udevice *dev) 169{ 170 struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); 171 struct video_priv *uc_priv = dev_get_uclass_priv(dev); 172 struct tilcdc_priv *priv = dev_get_priv(dev); 173 struct tilcdc_regs *regs = priv->regs; 174 struct udevice *panel, *clk_dev; 175 struct tilcdc_panel_info info; 176 struct display_timing timing; 177 ulong rate; 178 u32 reg; 179 int err; 180 181 /* Before relocation we don't need to do anything */ 182 if (!(gd->flags & GD_FLG_RELOC)) 183 return 0; 184 185 err = uclass_get_device(UCLASS_PANEL, 0, &panel); 186 if (err) { 187 dev_err(dev, "failed to get panel\n"); 188 return err; 189 } 190 191 err = panel_get_display_timing(panel, &timing); 192 if (err) { 193 dev_err(dev, "failed to get display timing\n"); 194 return err; 195 } 196 197 if (timing.pixelclock.typ > (LCDC_FMAX / 2)) { 198 dev_err(dev, "invalid display clock-frequency: %d Hz\n", 199 timing.pixelclock.typ); 200 return -EINVAL; 201 } 202 203 if (timing.hactive.typ > LCDC_MAX_WIDTH) 204 timing.hactive.typ = LCDC_MAX_WIDTH; 205 206 if (timing.vactive.typ > LCDC_MAX_HEIGHT) 207 timing.vactive.typ = LCDC_MAX_HEIGHT; 208 209 err = tilcdc_panel_get_display_info(panel, &info); 210 if (err) { 211 dev_err(dev, "failed to get panel info\n"); 212 return err; 213 } 214 215 switch (info.bpp) { 216 case 16: 217 case 24: 218 case 32: 219 break; 220 default: 221 dev_err(dev, "invalid seting, bpp: %d\n", info.bpp); 222 return -EINVAL; 223 } 224 225 switch (info.dma_burst_sz) { 226 case 1: 227 case 2: 228 case 4: 229 case 8: 230 case 16: 231 break; 232 default: 233 dev_err(dev, "invalid setting, dma-burst-sz: %d\n", 234 info.dma_burst_sz); 235 return -EINVAL; 236 } 237 238 err = uclass_get_device_by_name(UCLASS_CLK, "lcd_gclk@534", &clk_dev); 239 if (err) { 240 dev_err(dev, "failed to get lcd_gclk device\n"); 241 return err; 242 } 243 244 err = clk_request(clk_dev, &priv->gclk); 245 if (err) { 246 dev_err(dev, "failed to get %s clock\n", clk_dev->name); 247 return err; 248 } 249 250 rate = tilcdc_set_pixel_clk_rate(dev, timing.pixelclock.typ); 251 if (IS_ERR_VALUE(rate)) { 252 dev_err(dev, "failed to set pixel clock rate\n"); 253 return rate; 254 } 255 256 err = uclass_get_device_by_name(UCLASS_CLK, "dpll_disp_m2_ck@4a4", 257 &clk_dev); 258 if (err) { 259 dev_err(dev, "failed to get dpll_disp_m2 clock device\n"); 260 return err; 261 } 262 263 err = clk_request(clk_dev, &priv->dpll_m2_clk); 264 if (err) { 265 dev_err(dev, "failed to get %s clock\n", clk_dev->name); 266 return err; 267 } 268 269 err = clk_set_parent(&priv->gclk, &priv->dpll_m2_clk); 270 if (err) { 271 dev_err(dev, "failed to set %s clock as %s's parent\n", 272 priv->dpll_m2_clk.dev->name, priv->gclk.dev->name); 273 return err; 274 } 275 276 /* palette default entry */ 277 memset((void *)uc_plat->base, 0, 0x20); 278 *(unsigned int *)uc_plat->base = 0x4000; 279 /* point fb behind palette */ 280 uc_plat->base += 0x20; 281 uc_plat->size -= 0x20; 282 283 writel(LCDC_CLKC_ENABLE_CORECLKEN | LCDC_CLKC_ENABLE_LIDDCLKEN | 284 LCDC_CLKC_ENABLE_DMACLKEN, ®s->clkc_enable); 285 writel(0, ®s->raster_ctrl); 286 287 reg = readl(®s->ctrl) & LCDC_CTRL_CLK_DIVISOR_MASK; 288 reg |= LCDC_CTRL_RASTER_MODE; 289 writel(reg, ®s->ctrl); 290 291 reg = (timing.hactive.typ * timing.vactive.typ * info.bpp) >> 3; 292 reg += uc_plat->base; 293 writel(uc_plat->base, ®s->lcddma_fb0_base); 294 writel(reg, ®s->lcddma_fb0_ceiling); 295 writel(uc_plat->base, ®s->lcddma_fb1_base); 296 writel(reg, ®s->lcddma_fb1_ceiling); 297 298 reg = LCDC_DMA_CTRL_FIFO_TH(info.fifo_th); 299 switch (info.dma_burst_sz) { 300 case 1: 301 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_1); 302 break; 303 case 2: 304 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_2); 305 break; 306 case 4: 307 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_4); 308 break; 309 case 8: 310 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_8); 311 break; 312 case 16: 313 reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16); 314 break; 315 } 316 317 writel(reg, ®s->lcddma_ctrl); 318 319 writel(LCDC_RASTER_TIMING_0_HORLSB(timing.hactive.typ) | 320 LCDC_RASTER_TIMING_0_HORMSB(timing.hactive.typ) | 321 LCDC_RASTER_TIMING_0_HFPLSB(timing.hfront_porch.typ) | 322 LCDC_RASTER_TIMING_0_HBPLSB(timing.hback_porch.typ) | 323 LCDC_RASTER_TIMING_0_HSWLSB(timing.hsync_len.typ), 324 ®s->raster_timing0); 325 326 writel(LCDC_RASTER_TIMING_1_VBP(timing.vback_porch.typ) | 327 LCDC_RASTER_TIMING_1_VFP(timing.vfront_porch.typ) | 328 LCDC_RASTER_TIMING_1_VSW(timing.vsync_len.typ) | 329 LCDC_RASTER_TIMING_1_VERLSB(timing.vactive.typ), 330 ®s->raster_timing1); 331 332 reg = LCDC_RASTER_TIMING_2_ACB(info.ac_bias) | 333 LCDC_RASTER_TIMING_2_ACBI(info.ac_bias_intrpt) | 334 LCDC_RASTER_TIMING_2_HSWMSB(timing.hsync_len.typ) | 335 LCDC_RASTER_TIMING_2_VERMSB(timing.vactive.typ) | 336 LCDC_RASTER_TIMING_2_HBPMSB(timing.hback_porch.typ) | 337 LCDC_RASTER_TIMING_2_HFPMSB(timing.hfront_porch.typ); 338 339 if (timing.flags & DISPLAY_FLAGS_VSYNC_LOW) 340 reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT; 341 342 if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW) 343 reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT; 344 345 if (info.invert_pxl_clk) 346 reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT; 347 348 if (info.sync_edge) 349 reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL; 350 351 if (info.sync_ctrl) 352 reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL; 353 354 writel(reg, ®s->raster_timing2); 355 356 reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE | 357 LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(info.fdd); 358 359 if (info.tft_alt_mode) 360 reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE; 361 362 if (info.bpp == 24) 363 reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE; 364 else if (info.bpp == 32) 365 reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE | 366 LCDC_RASTER_CTRL_TFT_24BPP_UNPACK; 367 368 if (info.raster_order) 369 reg |= LCDC_RASTER_CTRL_DATA_ORDER; 370 371 writel(reg, ®s->raster_ctrl); 372 373 uc_priv->xsize = timing.hactive.typ; 374 uc_priv->ysize = timing.vactive.typ; 375 uc_priv->bpix = log_2_n_round_up(info.bpp); 376 377 err = panel_enable_backlight(panel); 378 if (err) { 379 dev_err(dev, "failed to enable panel backlight\n"); 380 return err; 381 } 382 383 return 0; 384} 385 386static int tilcdc_of_to_plat(struct udevice *dev) 387{ 388 struct tilcdc_priv *priv = dev_get_priv(dev); 389 390 priv->regs = dev_read_addr_ptr(dev); 391 if (!priv->regs) { 392 dev_err(dev, "failed to get base address\n"); 393 return -EINVAL; 394 } 395 396 dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs); 397 return 0; 398} 399 400static int tilcdc_bind(struct udevice *dev) 401{ 402 struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); 403 404 uc_plat->size = ((LCDC_MAX_WIDTH * LCDC_MAX_HEIGHT * 405 (1 << LCDC_MAX_LOG2_BPP)) >> 3) + 0x20; 406 407 dev_dbg(dev, "frame buffer size 0x%x\n", uc_plat->size); 408 return 0; 409} 410 411static const struct udevice_id tilcdc_ids[] = { 412 {.compatible = "ti,am33xx-tilcdc"}, 413 {} 414}; 415 416U_BOOT_DRIVER(tilcdc) = { 417 .name = "tilcdc", 418 .id = UCLASS_VIDEO, 419 .of_match = tilcdc_ids, 420 .bind = tilcdc_bind, 421 .of_to_plat = tilcdc_of_to_plat, 422 .probe = tilcdc_probe, 423 .remove = tilcdc_remove, 424 .priv_auto = sizeof(struct tilcdc_priv) 425}; 426