uboot/drivers/video/atmel_hlcdfb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Driver for AT91/AT32 MULTI LAYER LCD Controller
   4 *
   5 * Copyright (C) 2012 Atmel Corporation
   6 */
   7
   8#include <common.h>
   9#include <cpu_func.h>
  10#include <log.h>
  11#include <malloc.h>
  12#include <part.h>
  13#include <asm/global_data.h>
  14#include <asm/io.h>
  15#include <asm/arch/gpio.h>
  16#include <asm/arch/clk.h>
  17#include <clk.h>
  18#include <dm.h>
  19#include <fdtdec.h>
  20#include <lcd.h>
  21#include <video.h>
  22#include <wait_bit.h>
  23#include <atmel_hlcdc.h>
  24#include <linux/bug.h>
  25
  26#if defined(CONFIG_LCD_LOGO)
  27#include <bmp_logo.h>
  28#endif
  29
  30DECLARE_GLOBAL_DATA_PTR;
  31
  32#ifndef CONFIG_DM_VIDEO
  33
  34/* configurable parameters */
  35#define ATMEL_LCDC_CVAL_DEFAULT         0xc8
  36#define ATMEL_LCDC_DMA_BURST_LEN        8
  37#ifndef ATMEL_LCDC_GUARD_TIME
  38#define ATMEL_LCDC_GUARD_TIME           1
  39#endif
  40
  41#define ATMEL_LCDC_FIFO_SIZE            512
  42
  43/*
  44 * the CLUT register map as following
  45 * RCLUT(24 ~ 16), GCLUT(15 ~ 8), BCLUT(7 ~ 0)
  46 */
  47void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
  48{
  49        writel(panel_info.mmio + ATMEL_LCDC_LUT(regno),
  50               ((red << LCDC_BASECLUT_RCLUT_Pos) & LCDC_BASECLUT_RCLUT_Msk)
  51               | ((green << LCDC_BASECLUT_GCLUT_Pos) & LCDC_BASECLUT_GCLUT_Msk)
  52               | ((blue << LCDC_BASECLUT_BCLUT_Pos) & LCDC_BASECLUT_BCLUT_Msk));
  53}
  54
  55ushort *configuration_get_cmap(void)
  56{
  57#if defined(CONFIG_LCD_LOGO)
  58        return bmp_logo_palette;
  59#else
  60        return NULL;
  61#endif
  62}
  63
  64void lcd_ctrl_init(void *lcdbase)
  65{
  66        unsigned long value;
  67        struct lcd_dma_desc *desc;
  68        struct atmel_hlcd_regs *regs;
  69        int ret;
  70
  71        if (!has_lcdc())
  72                return;     /* No lcdc */
  73
  74        regs = (struct atmel_hlcd_regs *)panel_info.mmio;
  75
  76        /* Disable DISP signal */
  77        writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
  78        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
  79                                false, 1000, false);
  80        if (ret)
  81                printf("%s: %d: Timeout!\n", __func__, __LINE__);
  82        /* Disable synchronization */
  83        writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
  84        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
  85                                false, 1000, false);
  86        if (ret)
  87                printf("%s: %d: Timeout!\n", __func__, __LINE__);
  88        /* Disable pixel clock */
  89        writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
  90        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
  91                                false, 1000, false);
  92        if (ret)
  93                printf("%s: %d: Timeout!\n", __func__, __LINE__);
  94        /* Disable PWM */
  95        writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
  96        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
  97                                false, 1000, false);
  98        if (ret)
  99                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 100
 101        /* Set pixel clock */
 102        value = get_lcdc_clk_rate(0) / panel_info.vl_clk;
 103        if (get_lcdc_clk_rate(0) % panel_info.vl_clk)
 104                value++;
 105
 106        if (value < 1) {
 107                /* Using system clock as pixel clock */
 108                writel(LCDC_LCDCFG0_CLKDIV(0)
 109                        | LCDC_LCDCFG0_CGDISHCR
 110                        | LCDC_LCDCFG0_CGDISHEO
 111                        | LCDC_LCDCFG0_CGDISOVR1
 112                        | LCDC_LCDCFG0_CGDISBASE
 113                        | panel_info.vl_clk_pol
 114                        | LCDC_LCDCFG0_CLKSEL,
 115                        &regs->lcdc_lcdcfg0);
 116
 117        } else {
 118                writel(LCDC_LCDCFG0_CLKDIV(value - 2)
 119                        | LCDC_LCDCFG0_CGDISHCR
 120                        | LCDC_LCDCFG0_CGDISHEO
 121                        | LCDC_LCDCFG0_CGDISOVR1
 122                        | LCDC_LCDCFG0_CGDISBASE
 123                        | panel_info.vl_clk_pol,
 124                        &regs->lcdc_lcdcfg0);
 125        }
 126
 127        /* Initialize control register 5 */
 128        value = 0;
 129
 130        value |= panel_info.vl_sync;
 131
 132#ifndef LCD_OUTPUT_BPP
 133        /* Output is 24bpp */
 134        value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
 135#else
 136        switch (LCD_OUTPUT_BPP) {
 137        case 12:
 138                value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP;
 139                break;
 140        case 16:
 141                value |= LCDC_LCDCFG5_MODE_OUTPUT_16BPP;
 142                break;
 143        case 18:
 144                value |= LCDC_LCDCFG5_MODE_OUTPUT_18BPP;
 145                break;
 146        case 24:
 147                value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
 148                break;
 149        default:
 150                BUG();
 151                break;
 152        }
 153#endif
 154
 155        value |= LCDC_LCDCFG5_GUARDTIME(ATMEL_LCDC_GUARD_TIME);
 156        value |= (LCDC_LCDCFG5_DISPDLY | LCDC_LCDCFG5_VSPDLYS);
 157        writel(value, &regs->lcdc_lcdcfg5);
 158
 159        /* Vertical & Horizontal Timing */
 160        value = LCDC_LCDCFG1_VSPW(panel_info.vl_vsync_len - 1);
 161        value |= LCDC_LCDCFG1_HSPW(panel_info.vl_hsync_len - 1);
 162        writel(value, &regs->lcdc_lcdcfg1);
 163
 164        value = LCDC_LCDCFG2_VBPW(panel_info.vl_upper_margin);
 165        value |= LCDC_LCDCFG2_VFPW(panel_info.vl_lower_margin - 1);
 166        writel(value, &regs->lcdc_lcdcfg2);
 167
 168        value = LCDC_LCDCFG3_HBPW(panel_info.vl_left_margin - 1);
 169        value |= LCDC_LCDCFG3_HFPW(panel_info.vl_right_margin - 1);
 170        writel(value, &regs->lcdc_lcdcfg3);
 171
 172        /* Display size */
 173        value = LCDC_LCDCFG4_RPF(panel_info.vl_row - 1);
 174        value |= LCDC_LCDCFG4_PPL(panel_info.vl_col - 1);
 175        writel(value, &regs->lcdc_lcdcfg4);
 176
 177        writel(LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO,
 178               &regs->lcdc_basecfg0);
 179
 180        switch (NBITS(panel_info.vl_bpix)) {
 181        case 16:
 182                writel(LCDC_BASECFG1_RGBMODE_16BPP_RGB_565,
 183                       &regs->lcdc_basecfg1);
 184                break;
 185        case 32:
 186                writel(LCDC_BASECFG1_RGBMODE_24BPP_RGB_888,
 187                       &regs->lcdc_basecfg1);
 188                break;
 189        default:
 190                BUG();
 191                break;
 192        }
 193
 194        writel(LCDC_BASECFG2_XSTRIDE(0), &regs->lcdc_basecfg2);
 195        writel(0, &regs->lcdc_basecfg3);
 196        writel(LCDC_BASECFG4_DMA, &regs->lcdc_basecfg4);
 197
 198        /* Disable all interrupts */
 199        writel(~0UL, &regs->lcdc_lcdidr);
 200        writel(~0UL, &regs->lcdc_baseidr);
 201
 202        /* Setup the DMA descriptor, this descriptor will loop to itself */
 203        desc = (struct lcd_dma_desc *)(lcdbase - 16);
 204
 205        desc->address = (u32)lcdbase;
 206        /* Disable DMA transfer interrupt & descriptor loaded interrupt. */
 207        desc->control = LCDC_BASECTRL_ADDIEN | LCDC_BASECTRL_DSCRIEN
 208                        | LCDC_BASECTRL_DMAIEN | LCDC_BASECTRL_DFETCH;
 209        desc->next = (u32)desc;
 210
 211        /* Flush the DMA descriptor if we enabled dcache */
 212        flush_dcache_range((u32)desc, (u32)desc + sizeof(*desc));
 213
 214        writel(desc->address, &regs->lcdc_baseaddr);
 215        writel(desc->control, &regs->lcdc_basectrl);
 216        writel(desc->next, &regs->lcdc_basenext);
 217        writel(LCDC_BASECHER_CHEN | LCDC_BASECHER_UPDATEEN,
 218               &regs->lcdc_basecher);
 219
 220        /* Enable LCD */
 221        value = readl(&regs->lcdc_lcden);
 222        writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
 223        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
 224                                true, 1000, false);
 225        if (ret)
 226                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 227        value = readl(&regs->lcdc_lcden);
 228        writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
 229        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
 230                                true, 1000, false);
 231        if (ret)
 232                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 233        value = readl(&regs->lcdc_lcden);
 234        writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
 235        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
 236                                true, 1000, false);
 237        if (ret)
 238                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 239        value = readl(&regs->lcdc_lcden);
 240        writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
 241        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
 242                                true, 1000, false);
 243        if (ret)
 244                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 245
 246        /* Enable flushing if we enabled dcache */
 247        lcd_set_flush_dcache(1);
 248}
 249
 250#else
 251
 252enum {
 253        LCD_MAX_WIDTH           = 1024,
 254        LCD_MAX_HEIGHT          = 768,
 255        LCD_MAX_LOG2_BPP        = VIDEO_BPP16,
 256};
 257
 258struct atmel_hlcdc_priv {
 259        struct atmel_hlcd_regs *regs;
 260        struct display_timing timing;
 261        unsigned int vl_bpix;
 262        unsigned int output_mode;
 263        unsigned int guard_time;
 264        ulong clk_rate;
 265};
 266
 267static int at91_hlcdc_enable_clk(struct udevice *dev)
 268{
 269        struct atmel_hlcdc_priv *priv = dev_get_priv(dev);
 270        struct clk clk;
 271        ulong clk_rate;
 272        int ret;
 273
 274        ret = clk_get_by_index(dev, 0, &clk);
 275        if (ret)
 276                return -EINVAL;
 277
 278        ret = clk_enable(&clk);
 279        if (ret)
 280                return ret;
 281
 282        clk_rate = clk_get_rate(&clk);
 283        if (!clk_rate) {
 284                clk_disable(&clk);
 285                return -ENODEV;
 286        }
 287
 288        priv->clk_rate = clk_rate;
 289
 290        clk_free(&clk);
 291
 292        return 0;
 293}
 294
 295static void atmel_hlcdc_init(struct udevice *dev)
 296{
 297        struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
 298        struct atmel_hlcdc_priv *priv = dev_get_priv(dev);
 299        struct atmel_hlcd_regs *regs = priv->regs;
 300        struct display_timing *timing = &priv->timing;
 301        struct lcd_dma_desc *desc;
 302        unsigned long value, vl_clk_pol;
 303        int ret;
 304
 305        /* Disable DISP signal */
 306        writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
 307        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
 308                                false, 1000, false);
 309        if (ret)
 310                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 311        /* Disable synchronization */
 312        writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
 313        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
 314                                false, 1000, false);
 315        if (ret)
 316                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 317        /* Disable pixel clock */
 318        writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
 319        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
 320                                false, 1000, false);
 321        if (ret)
 322                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 323        /* Disable PWM */
 324        writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
 325        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
 326                                false, 1000, false);
 327        if (ret)
 328                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 329
 330        /* Set pixel clock */
 331        value = priv->clk_rate / timing->pixelclock.typ;
 332        if (priv->clk_rate % timing->pixelclock.typ)
 333                value++;
 334
 335        vl_clk_pol = 0;
 336        if (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
 337                vl_clk_pol = LCDC_LCDCFG0_CLKPOL;
 338
 339        if (value < 1) {
 340                /* Using system clock as pixel clock */
 341                writel(LCDC_LCDCFG0_CLKDIV(0)
 342                        | LCDC_LCDCFG0_CGDISHCR
 343                        | LCDC_LCDCFG0_CGDISHEO
 344                        | LCDC_LCDCFG0_CGDISOVR1
 345                        | LCDC_LCDCFG0_CGDISBASE
 346                        | vl_clk_pol
 347                        | LCDC_LCDCFG0_CLKSEL,
 348                        &regs->lcdc_lcdcfg0);
 349
 350        } else {
 351                writel(LCDC_LCDCFG0_CLKDIV(value - 2)
 352                        | LCDC_LCDCFG0_CGDISHCR
 353                        | LCDC_LCDCFG0_CGDISHEO
 354                        | LCDC_LCDCFG0_CGDISOVR1
 355                        | LCDC_LCDCFG0_CGDISBASE
 356                        | vl_clk_pol,
 357                        &regs->lcdc_lcdcfg0);
 358        }
 359
 360        /* Initialize control register 5 */
 361        value = 0;
 362
 363        if (!(timing->flags & DISPLAY_FLAGS_HSYNC_HIGH))
 364                value |= LCDC_LCDCFG5_HSPOL;
 365        if (!(timing->flags & DISPLAY_FLAGS_VSYNC_HIGH))
 366                value |= LCDC_LCDCFG5_VSPOL;
 367
 368        switch (priv->output_mode) {
 369        case 12:
 370                value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP;
 371                break;
 372        case 16:
 373                value |= LCDC_LCDCFG5_MODE_OUTPUT_16BPP;
 374                break;
 375        case 18:
 376                value |= LCDC_LCDCFG5_MODE_OUTPUT_18BPP;
 377                break;
 378        case 24:
 379                value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
 380                break;
 381        default:
 382                BUG();
 383                break;
 384        }
 385
 386        value |= LCDC_LCDCFG5_GUARDTIME(priv->guard_time);
 387        value |= (LCDC_LCDCFG5_DISPDLY | LCDC_LCDCFG5_VSPDLYS);
 388        writel(value, &regs->lcdc_lcdcfg5);
 389
 390        /* Vertical & Horizontal Timing */
 391        value = LCDC_LCDCFG1_VSPW(timing->vsync_len.typ - 1);
 392        value |= LCDC_LCDCFG1_HSPW(timing->hsync_len.typ - 1);
 393        writel(value, &regs->lcdc_lcdcfg1);
 394
 395        value = LCDC_LCDCFG2_VBPW(timing->vback_porch.typ);
 396        value |= LCDC_LCDCFG2_VFPW(timing->vfront_porch.typ - 1);
 397        writel(value, &regs->lcdc_lcdcfg2);
 398
 399        value = LCDC_LCDCFG3_HBPW(timing->hback_porch.typ - 1);
 400        value |= LCDC_LCDCFG3_HFPW(timing->hfront_porch.typ - 1);
 401        writel(value, &regs->lcdc_lcdcfg3);
 402
 403        /* Display size */
 404        value = LCDC_LCDCFG4_RPF(timing->vactive.typ - 1);
 405        value |= LCDC_LCDCFG4_PPL(timing->hactive.typ - 1);
 406        writel(value, &regs->lcdc_lcdcfg4);
 407
 408        writel(LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO,
 409               &regs->lcdc_basecfg0);
 410
 411        switch (VNBITS(priv->vl_bpix)) {
 412        case 16:
 413                writel(LCDC_BASECFG1_RGBMODE_16BPP_RGB_565,
 414                       &regs->lcdc_basecfg1);
 415                break;
 416        case 32:
 417                writel(LCDC_BASECFG1_RGBMODE_24BPP_RGB_888,
 418                       &regs->lcdc_basecfg1);
 419                break;
 420        default:
 421                BUG();
 422                break;
 423        }
 424
 425        writel(LCDC_BASECFG2_XSTRIDE(0), &regs->lcdc_basecfg2);
 426        writel(0, &regs->lcdc_basecfg3);
 427        writel(LCDC_BASECFG4_DMA, &regs->lcdc_basecfg4);
 428
 429        /* Disable all interrupts */
 430        writel(~0UL, &regs->lcdc_lcdidr);
 431        writel(~0UL, &regs->lcdc_baseidr);
 432
 433        /* Setup the DMA descriptor, this descriptor will loop to itself */
 434        desc = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*desc));
 435        if (!desc)
 436                return;
 437
 438        desc->address = (u32)uc_plat->base;
 439
 440        /* Disable DMA transfer interrupt & descriptor loaded interrupt. */
 441        desc->control = LCDC_BASECTRL_ADDIEN | LCDC_BASECTRL_DSCRIEN
 442                        | LCDC_BASECTRL_DMAIEN | LCDC_BASECTRL_DFETCH;
 443        desc->next = (u32)desc;
 444
 445        /* Flush the DMA descriptor if we enabled dcache */
 446        flush_dcache_range((u32)desc,
 447                           ALIGN(((u32)desc + sizeof(*desc)),
 448                           CONFIG_SYS_CACHELINE_SIZE));
 449
 450        writel(desc->address, &regs->lcdc_baseaddr);
 451        writel(desc->control, &regs->lcdc_basectrl);
 452        writel(desc->next, &regs->lcdc_basenext);
 453        writel(LCDC_BASECHER_CHEN | LCDC_BASECHER_UPDATEEN,
 454               &regs->lcdc_basecher);
 455
 456        /* Enable LCD */
 457        value = readl(&regs->lcdc_lcden);
 458        writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
 459        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
 460                                true, 1000, false);
 461        if (ret)
 462                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 463        value = readl(&regs->lcdc_lcden);
 464        writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
 465        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
 466                                true, 1000, false);
 467        if (ret)
 468                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 469        value = readl(&regs->lcdc_lcden);
 470        writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
 471        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
 472                                true, 1000, false);
 473        if (ret)
 474                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 475        value = readl(&regs->lcdc_lcden);
 476        writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
 477        ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
 478                                true, 1000, false);
 479        if (ret)
 480                printf("%s: %d: Timeout!\n", __func__, __LINE__);
 481}
 482
 483static int atmel_hlcdc_probe(struct udevice *dev)
 484{
 485        struct video_priv *uc_priv = dev_get_uclass_priv(dev);
 486        struct atmel_hlcdc_priv *priv = dev_get_priv(dev);
 487        int ret;
 488
 489        ret = at91_hlcdc_enable_clk(dev);
 490        if (ret)
 491                return ret;
 492
 493        atmel_hlcdc_init(dev);
 494
 495        uc_priv->xsize = priv->timing.hactive.typ;
 496        uc_priv->ysize = priv->timing.vactive.typ;
 497        uc_priv->bpix = priv->vl_bpix;
 498
 499        /* Enable flushing if we enabled dcache */
 500        video_set_flush_dcache(dev, true);
 501
 502        return 0;
 503}
 504
 505static int atmel_hlcdc_of_to_plat(struct udevice *dev)
 506{
 507        struct atmel_hlcdc_priv *priv = dev_get_priv(dev);
 508        const void *blob = gd->fdt_blob;
 509        int node = dev_of_offset(dev);
 510
 511        priv->regs = dev_read_addr_ptr(dev);
 512        if (!priv->regs) {
 513                debug("%s: No display controller address\n", __func__);
 514                return -EINVAL;
 515        }
 516
 517        if (fdtdec_decode_display_timing(blob, dev_of_offset(dev),
 518                                         0, &priv->timing)) {
 519                debug("%s: Failed to decode display timing\n", __func__);
 520                return -EINVAL;
 521        }
 522
 523        if (priv->timing.hactive.typ > LCD_MAX_WIDTH)
 524                priv->timing.hactive.typ = LCD_MAX_WIDTH;
 525
 526        if (priv->timing.vactive.typ > LCD_MAX_HEIGHT)
 527                priv->timing.vactive.typ = LCD_MAX_HEIGHT;
 528
 529        priv->vl_bpix = fdtdec_get_int(blob, node, "atmel,vl-bpix", 0);
 530        if (!priv->vl_bpix) {
 531                debug("%s: Failed to get bits per pixel\n", __func__);
 532                return -EINVAL;
 533        }
 534
 535        priv->output_mode = fdtdec_get_int(blob, node, "atmel,output-mode", 24);
 536        priv->guard_time = fdtdec_get_int(blob, node, "atmel,guard-time", 1);
 537
 538        return 0;
 539}
 540
 541static int atmel_hlcdc_bind(struct udevice *dev)
 542{
 543        struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
 544
 545        uc_plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
 546                                (1 << LCD_MAX_LOG2_BPP) / 8;
 547
 548        debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
 549
 550        return 0;
 551}
 552
 553static const struct udevice_id atmel_hlcdc_ids[] = {
 554        { .compatible = "atmel,sama5d2-hlcdc" },
 555        { .compatible = "atmel,at91sam9x5-hlcdc" },
 556        { }
 557};
 558
 559U_BOOT_DRIVER(atmel_hlcdfb) = {
 560        .name   = "atmel_hlcdfb",
 561        .id     = UCLASS_VIDEO,
 562        .of_match = atmel_hlcdc_ids,
 563        .bind   = atmel_hlcdc_bind,
 564        .probe  = atmel_hlcdc_probe,
 565        .of_to_plat = atmel_hlcdc_of_to_plat,
 566        .priv_auto      = sizeof(struct atmel_hlcdc_priv),
 567};
 568
 569#endif
 570