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