linux/drivers/gpu/drm/mxsfb/mxsfb_kms.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2016 Marek Vasut <marex@denx.de>
   4 *
   5 * This code is based on drivers/video/fbdev/mxsfb.c :
   6 * Copyright (C) 2010 Juergen Beisert, Pengutronix
   7 * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
   8 * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
   9 */
  10
  11#include <linux/clk.h>
  12#include <linux/io.h>
  13#include <linux/iopoll.h>
  14#include <linux/pm_runtime.h>
  15#include <linux/spinlock.h>
  16
  17#include <drm/drm_atomic.h>
  18#include <drm/drm_atomic_helper.h>
  19#include <drm/drm_bridge.h>
  20#include <drm/drm_crtc.h>
  21#include <drm/drm_encoder.h>
  22#include <drm/drm_fb_cma_helper.h>
  23#include <drm/drm_fourcc.h>
  24#include <drm/drm_gem_atomic_helper.h>
  25#include <drm/drm_gem_cma_helper.h>
  26#include <drm/drm_plane.h>
  27#include <drm/drm_plane_helper.h>
  28#include <drm/drm_vblank.h>
  29
  30#include "mxsfb_drv.h"
  31#include "mxsfb_regs.h"
  32
  33/* 1 second delay should be plenty of time for block reset */
  34#define RESET_TIMEOUT           1000000
  35
  36/* -----------------------------------------------------------------------------
  37 * CRTC
  38 */
  39
  40static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
  41{
  42        return (val & mxsfb->devdata->hs_wdth_mask) <<
  43                mxsfb->devdata->hs_wdth_shift;
  44}
  45
  46/*
  47 * Setup the MXSFB registers for decoding the pixels out of the framebuffer and
  48 * outputting them on the bus.
  49 */
  50static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb,
  51                              const u32 bus_format)
  52{
  53        struct drm_device *drm = mxsfb->drm;
  54        const u32 format = mxsfb->crtc.primary->state->fb->format->format;
  55        u32 ctrl, ctrl1;
  56
  57        DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
  58                             bus_format);
  59
  60        ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
  61
  62        /* CTRL1 contains IRQ config and status bits, preserve those. */
  63        ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
  64        ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
  65
  66        switch (format) {
  67        case DRM_FORMAT_RGB565:
  68                dev_dbg(drm->dev, "Setting up RGB565 mode\n");
  69                ctrl |= CTRL_WORD_LENGTH_16;
  70                ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
  71                break;
  72        case DRM_FORMAT_XRGB8888:
  73                dev_dbg(drm->dev, "Setting up XRGB8888 mode\n");
  74                ctrl |= CTRL_WORD_LENGTH_24;
  75                /* Do not use packed pixels = one pixel per word instead. */
  76                ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
  77                break;
  78        }
  79
  80        switch (bus_format) {
  81        case MEDIA_BUS_FMT_RGB565_1X16:
  82                ctrl |= CTRL_BUS_WIDTH_16;
  83                break;
  84        case MEDIA_BUS_FMT_RGB666_1X18:
  85                ctrl |= CTRL_BUS_WIDTH_18;
  86                break;
  87        case MEDIA_BUS_FMT_RGB888_1X24:
  88                ctrl |= CTRL_BUS_WIDTH_24;
  89                break;
  90        default:
  91                dev_err(drm->dev, "Unknown media bus format %d\n", bus_format);
  92                break;
  93        }
  94
  95        writel(ctrl1, mxsfb->base + LCDC_CTRL1);
  96        writel(ctrl, mxsfb->base + LCDC_CTRL);
  97}
  98
  99static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
 100{
 101        u32 reg;
 102
 103        if (mxsfb->clk_disp_axi)
 104                clk_prepare_enable(mxsfb->clk_disp_axi);
 105        clk_prepare_enable(mxsfb->clk);
 106
 107        /* Increase number of outstanding requests on all supported IPs */
 108        if (mxsfb->devdata->has_ctrl2) {
 109                reg = readl(mxsfb->base + LCDC_V4_CTRL2);
 110                reg &= ~CTRL2_SET_OUTSTANDING_REQS_MASK;
 111                reg |= CTRL2_SET_OUTSTANDING_REQS_16;
 112                writel(reg, mxsfb->base + LCDC_V4_CTRL2);
 113        }
 114
 115        /* If it was disabled, re-enable the mode again */
 116        writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
 117
 118        /* Enable the SYNC signals first, then the DMA engine */
 119        reg = readl(mxsfb->base + LCDC_VDCTRL4);
 120        reg |= VDCTRL4_SYNC_SIGNALS_ON;
 121        writel(reg, mxsfb->base + LCDC_VDCTRL4);
 122
 123        /*
 124         * Enable recovery on underflow.
 125         *
 126         * There is some sort of corner case behavior of the controller,
 127         * which could rarely be triggered at least on i.MX6SX connected
 128         * to 800x480 DPI panel and i.MX8MM connected to DPI->DSI->LVDS
 129         * bridged 1920x1080 panel (and likely on other setups too), where
 130         * the image on the panel shifts to the right and wraps around.
 131         * This happens either when the controller is enabled on boot or
 132         * even later during run time. The condition does not correct
 133         * itself automatically, i.e. the display image remains shifted.
 134         *
 135         * It seems this problem is known and is due to sporadic underflows
 136         * of the LCDIF FIFO. While the LCDIF IP does have underflow/overflow
 137         * IRQs, neither of the IRQs trigger and neither IRQ status bit is
 138         * asserted when this condition occurs.
 139         *
 140         * All known revisions of the LCDIF IP have CTRL1 RECOVER_ON_UNDERFLOW
 141         * bit, which is described in the reference manual since i.MX23 as
 142         * "
 143         *   Set this bit to enable the LCDIF block to recover in the next
 144         *   field/frame if there was an underflow in the current field/frame.
 145         * "
 146         * Enable this bit to mitigate the sporadic underflows.
 147         */
 148        reg = readl(mxsfb->base + LCDC_CTRL1);
 149        reg |= CTRL1_RECOVER_ON_UNDERFLOW;
 150        writel(reg, mxsfb->base + LCDC_CTRL1);
 151
 152        writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
 153}
 154
 155static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 156{
 157        u32 reg;
 158
 159        /*
 160         * Even if we disable the controller here, it will still continue
 161         * until its FIFOs are running out of data
 162         */
 163        writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_CLR);
 164
 165        readl_poll_timeout(mxsfb->base + LCDC_CTRL, reg, !(reg & CTRL_RUN),
 166                           0, 1000);
 167
 168        reg = readl(mxsfb->base + LCDC_VDCTRL4);
 169        reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
 170        writel(reg, mxsfb->base + LCDC_VDCTRL4);
 171
 172        clk_disable_unprepare(mxsfb->clk);
 173        if (mxsfb->clk_disp_axi)
 174                clk_disable_unprepare(mxsfb->clk_disp_axi);
 175}
 176
 177/*
 178 * Clear the bit and poll it cleared.  This is usually called with
 179 * a reset address and mask being either SFTRST(bit 31) or CLKGATE
 180 * (bit 30).
 181 */
 182static int clear_poll_bit(void __iomem *addr, u32 mask)
 183{
 184        u32 reg;
 185
 186        writel(mask, addr + REG_CLR);
 187        return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
 188}
 189
 190static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb)
 191{
 192        int ret;
 193
 194        ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST);
 195        if (ret)
 196                return ret;
 197
 198        writel(CTRL_CLKGATE, mxsfb->base + LCDC_CTRL + REG_CLR);
 199
 200        ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST);
 201        if (ret)
 202                return ret;
 203
 204        return clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE);
 205}
 206
 207static dma_addr_t mxsfb_get_fb_paddr(struct drm_plane *plane)
 208{
 209        struct drm_framebuffer *fb = plane->state->fb;
 210        struct drm_gem_cma_object *gem;
 211
 212        if (!fb)
 213                return 0;
 214
 215        gem = drm_fb_cma_get_gem_obj(fb, 0);
 216        if (!gem)
 217                return 0;
 218
 219        return gem->paddr;
 220}
 221
 222static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb,
 223                                     const u32 bus_format)
 224{
 225        struct drm_device *drm = mxsfb->crtc.dev;
 226        struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode;
 227        u32 bus_flags = mxsfb->connector->display_info.bus_flags;
 228        u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
 229        int err;
 230
 231        /*
 232         * It seems, you can't re-program the controller if it is still
 233         * running. This may lead to shifted pictures (FIFO issue?), so
 234         * first stop the controller and drain its FIFOs.
 235         */
 236
 237        /* Mandatory eLCDIF reset as per the Reference Manual */
 238        err = mxsfb_reset_block(mxsfb);
 239        if (err)
 240                return;
 241
 242        /* Clear the FIFOs */
 243        writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
 244        readl(mxsfb->base + LCDC_CTRL1);
 245        writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 246        readl(mxsfb->base + LCDC_CTRL1);
 247
 248        if (mxsfb->devdata->has_overlay)
 249                writel(0, mxsfb->base + LCDC_AS_CTRL);
 250
 251        mxsfb_set_formats(mxsfb, bus_format);
 252
 253        clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 254
 255        if (mxsfb->bridge && mxsfb->bridge->timings)
 256                bus_flags = mxsfb->bridge->timings->input_bus_flags;
 257
 258        DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
 259                             m->crtc_clock,
 260                             (int)(clk_get_rate(mxsfb->clk) / 1000));
 261        DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n",
 262                             bus_flags);
 263        DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
 264
 265        writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
 266               TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
 267               mxsfb->base + mxsfb->devdata->transfer_count);
 268
 269        vsync_pulse_len = m->crtc_vsync_end - m->crtc_vsync_start;
 270
 271        vdctrl0 = VDCTRL0_ENABLE_PRESENT |      /* Always in DOTCLOCK mode */
 272                  VDCTRL0_VSYNC_PERIOD_UNIT |
 273                  VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
 274                  VDCTRL0_SET_VSYNC_PULSE_WIDTH(vsync_pulse_len);
 275        if (m->flags & DRM_MODE_FLAG_PHSYNC)
 276                vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
 277        if (m->flags & DRM_MODE_FLAG_PVSYNC)
 278                vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
 279        /* Make sure Data Enable is high active by default */
 280        if (!(bus_flags & DRM_BUS_FLAG_DE_LOW))
 281                vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
 282        /*
 283         * DRM_BUS_FLAG_PIXDATA_DRIVE_ defines are controller centric,
 284         * controllers VDCTRL0_DOTCLK is display centric.
 285         * Drive on positive edge       -> display samples on falling edge
 286         * DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE -> VDCTRL0_DOTCLK_ACT_FALLING
 287         */
 288        if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
 289                vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
 290
 291        writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0);
 292
 293        /* Frame length in lines. */
 294        writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1);
 295
 296        /* Line length in units of clocks or pixels. */
 297        hsync_pulse_len = m->crtc_hsync_end - m->crtc_hsync_start;
 298        writel(set_hsync_pulse_width(mxsfb, hsync_pulse_len) |
 299               VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal),
 300               mxsfb->base + LCDC_VDCTRL2);
 301
 302        writel(SET_HOR_WAIT_CNT(m->crtc_htotal - m->crtc_hsync_start) |
 303               SET_VERT_WAIT_CNT(m->crtc_vtotal - m->crtc_vsync_start),
 304               mxsfb->base + LCDC_VDCTRL3);
 305
 306        writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay),
 307               mxsfb->base + LCDC_VDCTRL4);
 308}
 309
 310static int mxsfb_crtc_atomic_check(struct drm_crtc *crtc,
 311                                   struct drm_atomic_state *state)
 312{
 313        struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
 314                                                                          crtc);
 315        bool has_primary = crtc_state->plane_mask &
 316                           drm_plane_mask(crtc->primary);
 317
 318        /* The primary plane has to be enabled when the CRTC is active. */
 319        if (crtc_state->active && !has_primary)
 320                return -EINVAL;
 321
 322        /* TODO: Is this needed ? */
 323        return drm_atomic_add_affected_planes(state, crtc);
 324}
 325
 326static void mxsfb_crtc_atomic_flush(struct drm_crtc *crtc,
 327                                    struct drm_atomic_state *state)
 328{
 329        struct drm_pending_vblank_event *event;
 330
 331        event = crtc->state->event;
 332        crtc->state->event = NULL;
 333
 334        if (!event)
 335                return;
 336
 337        spin_lock_irq(&crtc->dev->event_lock);
 338        if (drm_crtc_vblank_get(crtc) == 0)
 339                drm_crtc_arm_vblank_event(crtc, event);
 340        else
 341                drm_crtc_send_vblank_event(crtc, event);
 342        spin_unlock_irq(&crtc->dev->event_lock);
 343}
 344
 345static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
 346                                     struct drm_atomic_state *state)
 347{
 348        struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
 349        struct drm_bridge_state *bridge_state;
 350        struct drm_device *drm = mxsfb->drm;
 351        u32 bus_format = 0;
 352        dma_addr_t paddr;
 353
 354        pm_runtime_get_sync(drm->dev);
 355        mxsfb_enable_axi_clk(mxsfb);
 356
 357        drm_crtc_vblank_on(crtc);
 358
 359        /* If there is a bridge attached to the LCDIF, use its bus format */
 360        if (mxsfb->bridge) {
 361                bridge_state =
 362                        drm_atomic_get_new_bridge_state(state,
 363                                                        mxsfb->bridge);
 364                bus_format = bridge_state->input_bus_cfg.format;
 365        }
 366
 367        /* If there is no bridge, use bus format from connector */
 368        if (!bus_format && mxsfb->connector->display_info.num_bus_formats)
 369                bus_format = mxsfb->connector->display_info.bus_formats[0];
 370
 371        /* If all else fails, default to RGB888_1X24 */
 372        if (!bus_format)
 373                bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 374
 375        mxsfb_crtc_mode_set_nofb(mxsfb, bus_format);
 376
 377        /* Write cur_buf as well to avoid an initial corrupt frame */
 378        paddr = mxsfb_get_fb_paddr(crtc->primary);
 379        if (paddr) {
 380                writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf);
 381                writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
 382        }
 383
 384        mxsfb_enable_controller(mxsfb);
 385}
 386
 387static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
 388                                      struct drm_atomic_state *state)
 389{
 390        struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
 391        struct drm_device *drm = mxsfb->drm;
 392        struct drm_pending_vblank_event *event;
 393
 394        mxsfb_disable_controller(mxsfb);
 395
 396        spin_lock_irq(&drm->event_lock);
 397        event = crtc->state->event;
 398        if (event) {
 399                crtc->state->event = NULL;
 400                drm_crtc_send_vblank_event(crtc, event);
 401        }
 402        spin_unlock_irq(&drm->event_lock);
 403
 404        drm_crtc_vblank_off(crtc);
 405
 406        mxsfb_disable_axi_clk(mxsfb);
 407        pm_runtime_put_sync(drm->dev);
 408}
 409
 410static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc)
 411{
 412        struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
 413
 414        /* Clear and enable VBLANK IRQ */
 415        writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 416        writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
 417
 418        return 0;
 419}
 420
 421static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc)
 422{
 423        struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
 424
 425        /* Disable and clear VBLANK IRQ */
 426        writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 427        writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 428}
 429
 430static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = {
 431        .atomic_check = mxsfb_crtc_atomic_check,
 432        .atomic_flush = mxsfb_crtc_atomic_flush,
 433        .atomic_enable = mxsfb_crtc_atomic_enable,
 434        .atomic_disable = mxsfb_crtc_atomic_disable,
 435};
 436
 437static const struct drm_crtc_funcs mxsfb_crtc_funcs = {
 438        .reset = drm_atomic_helper_crtc_reset,
 439        .destroy = drm_crtc_cleanup,
 440        .set_config = drm_atomic_helper_set_config,
 441        .page_flip = drm_atomic_helper_page_flip,
 442        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 443        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 444        .enable_vblank = mxsfb_crtc_enable_vblank,
 445        .disable_vblank = mxsfb_crtc_disable_vblank,
 446};
 447
 448/* -----------------------------------------------------------------------------
 449 * Encoder
 450 */
 451
 452static const struct drm_encoder_funcs mxsfb_encoder_funcs = {
 453        .destroy = drm_encoder_cleanup,
 454};
 455
 456/* -----------------------------------------------------------------------------
 457 * Planes
 458 */
 459
 460static int mxsfb_plane_atomic_check(struct drm_plane *plane,
 461                                    struct drm_atomic_state *state)
 462{
 463        struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state,
 464                                                                             plane);
 465        struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
 466        struct drm_crtc_state *crtc_state;
 467
 468        crtc_state = drm_atomic_get_new_crtc_state(state,
 469                                                   &mxsfb->crtc);
 470
 471        return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
 472                                                   DRM_PLANE_HELPER_NO_SCALING,
 473                                                   DRM_PLANE_HELPER_NO_SCALING,
 474                                                   false, true);
 475}
 476
 477static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane,
 478                                              struct drm_atomic_state *state)
 479{
 480        struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
 481        dma_addr_t paddr;
 482
 483        paddr = mxsfb_get_fb_paddr(plane);
 484        if (paddr)
 485                writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
 486}
 487
 488static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
 489                                              struct drm_atomic_state *state)
 490{
 491        struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state,
 492                                                                            plane);
 493        struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
 494        struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state,
 495                                                                            plane);
 496        dma_addr_t paddr;
 497        u32 ctrl;
 498
 499        paddr = mxsfb_get_fb_paddr(plane);
 500        if (!paddr) {
 501                writel(0, mxsfb->base + LCDC_AS_CTRL);
 502                return;
 503        }
 504
 505        /*
 506         * HACK: The hardware seems to output 64 bytes of data of unknown
 507         * origin, and then to proceed with the framebuffer. Until the reason
 508         * is understood, live with the 16 initial invalid pixels on the first
 509         * line and start 64 bytes within the framebuffer.
 510         */
 511        paddr += 64;
 512
 513        writel(paddr, mxsfb->base + LCDC_AS_NEXT_BUF);
 514
 515        /*
 516         * If the plane was previously disabled, write LCDC_AS_BUF as well to
 517         * provide the first buffer.
 518         */
 519        if (!old_pstate->fb)
 520                writel(paddr, mxsfb->base + LCDC_AS_BUF);
 521
 522        ctrl = AS_CTRL_AS_ENABLE | AS_CTRL_ALPHA(255);
 523
 524        switch (new_pstate->fb->format->format) {
 525        case DRM_FORMAT_XRGB4444:
 526                ctrl |= AS_CTRL_FORMAT_RGB444 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
 527                break;
 528        case DRM_FORMAT_ARGB4444:
 529                ctrl |= AS_CTRL_FORMAT_ARGB4444 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
 530                break;
 531        case DRM_FORMAT_XRGB1555:
 532                ctrl |= AS_CTRL_FORMAT_RGB555 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
 533                break;
 534        case DRM_FORMAT_ARGB1555:
 535                ctrl |= AS_CTRL_FORMAT_ARGB1555 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
 536                break;
 537        case DRM_FORMAT_RGB565:
 538                ctrl |= AS_CTRL_FORMAT_RGB565 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
 539                break;
 540        case DRM_FORMAT_XRGB8888:
 541                ctrl |= AS_CTRL_FORMAT_RGB888 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
 542                break;
 543        case DRM_FORMAT_ARGB8888:
 544                ctrl |= AS_CTRL_FORMAT_ARGB8888 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
 545                break;
 546        }
 547
 548        writel(ctrl, mxsfb->base + LCDC_AS_CTRL);
 549}
 550
 551static bool mxsfb_format_mod_supported(struct drm_plane *plane,
 552                                       uint32_t format,
 553                                       uint64_t modifier)
 554{
 555        return modifier == DRM_FORMAT_MOD_LINEAR;
 556}
 557
 558static const struct drm_plane_helper_funcs mxsfb_plane_primary_helper_funcs = {
 559        .atomic_check = mxsfb_plane_atomic_check,
 560        .atomic_update = mxsfb_plane_primary_atomic_update,
 561};
 562
 563static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
 564        .atomic_check = mxsfb_plane_atomic_check,
 565        .atomic_update = mxsfb_plane_overlay_atomic_update,
 566};
 567
 568static const struct drm_plane_funcs mxsfb_plane_funcs = {
 569        .format_mod_supported   = mxsfb_format_mod_supported,
 570        .update_plane           = drm_atomic_helper_update_plane,
 571        .disable_plane          = drm_atomic_helper_disable_plane,
 572        .destroy                = drm_plane_cleanup,
 573        .reset                  = drm_atomic_helper_plane_reset,
 574        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
 575        .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
 576};
 577
 578static const uint32_t mxsfb_primary_plane_formats[] = {
 579        DRM_FORMAT_RGB565,
 580        DRM_FORMAT_XRGB8888,
 581};
 582
 583static const uint32_t mxsfb_overlay_plane_formats[] = {
 584        DRM_FORMAT_XRGB4444,
 585        DRM_FORMAT_ARGB4444,
 586        DRM_FORMAT_XRGB1555,
 587        DRM_FORMAT_ARGB1555,
 588        DRM_FORMAT_RGB565,
 589        DRM_FORMAT_XRGB8888,
 590        DRM_FORMAT_ARGB8888,
 591};
 592
 593static const uint64_t mxsfb_modifiers[] = {
 594        DRM_FORMAT_MOD_LINEAR,
 595        DRM_FORMAT_MOD_INVALID
 596};
 597
 598/* -----------------------------------------------------------------------------
 599 * Initialization
 600 */
 601
 602int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
 603{
 604        struct drm_encoder *encoder = &mxsfb->encoder;
 605        struct drm_crtc *crtc = &mxsfb->crtc;
 606        int ret;
 607
 608        drm_plane_helper_add(&mxsfb->planes.primary,
 609                             &mxsfb_plane_primary_helper_funcs);
 610        ret = drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1,
 611                                       &mxsfb_plane_funcs,
 612                                       mxsfb_primary_plane_formats,
 613                                       ARRAY_SIZE(mxsfb_primary_plane_formats),
 614                                       mxsfb_modifiers, DRM_PLANE_TYPE_PRIMARY,
 615                                       NULL);
 616        if (ret)
 617                return ret;
 618
 619        if (mxsfb->devdata->has_overlay) {
 620                drm_plane_helper_add(&mxsfb->planes.overlay,
 621                                     &mxsfb_plane_overlay_helper_funcs);
 622                ret = drm_universal_plane_init(mxsfb->drm,
 623                                               &mxsfb->planes.overlay, 1,
 624                                               &mxsfb_plane_funcs,
 625                                               mxsfb_overlay_plane_formats,
 626                                               ARRAY_SIZE(mxsfb_overlay_plane_formats),
 627                                               mxsfb_modifiers, DRM_PLANE_TYPE_OVERLAY,
 628                                               NULL);
 629                if (ret)
 630                        return ret;
 631        }
 632
 633        drm_crtc_helper_add(crtc, &mxsfb_crtc_helper_funcs);
 634        ret = drm_crtc_init_with_planes(mxsfb->drm, crtc,
 635                                        &mxsfb->planes.primary, NULL,
 636                                        &mxsfb_crtc_funcs, NULL);
 637        if (ret)
 638                return ret;
 639
 640        encoder->possible_crtcs = drm_crtc_mask(crtc);
 641        return drm_encoder_init(mxsfb->drm, encoder, &mxsfb_encoder_funcs,
 642                                DRM_MODE_ENCODER_NONE, NULL);
 643}
 644