root/drivers/gpu/drm/mxsfb/mxsfb_crtc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_hsync_pulse_width
  2. mxsfb_set_pixel_fmt
  3. mxsfb_set_bus_fmt
  4. mxsfb_enable_controller
  5. mxsfb_disable_controller
  6. clear_poll_bit
  7. mxsfb_reset_block
  8. mxsfb_get_fb_paddr
  9. mxsfb_crtc_mode_set_nofb
  10. mxsfb_crtc_enable
  11. mxsfb_crtc_disable
  12. mxsfb_plane_atomic_update

   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/iopoll.h>
  13 #include <linux/of_graph.h>
  14 #include <linux/platform_data/simplefb.h>
  15 
  16 #include <video/videomode.h>
  17 
  18 #include <drm/drm_atomic_helper.h>
  19 #include <drm/drm_crtc.h>
  20 #include <drm/drm_fb_cma_helper.h>
  21 #include <drm/drm_fb_helper.h>
  22 #include <drm/drm_gem_cma_helper.h>
  23 #include <drm/drm_of.h>
  24 #include <drm/drm_plane_helper.h>
  25 #include <drm/drm_probe_helper.h>
  26 #include <drm/drm_simple_kms_helper.h>
  27 #include <drm/drm_vblank.h>
  28 
  29 #include "mxsfb_drv.h"
  30 #include "mxsfb_regs.h"
  31 
  32 #define MXS_SET_ADDR            0x4
  33 #define MXS_CLR_ADDR            0x8
  34 #define MODULE_CLKGATE          BIT(30)
  35 #define MODULE_SFTRST           BIT(31)
  36 /* 1 second delay should be plenty of time for block reset */
  37 #define RESET_TIMEOUT           1000000
  38 
  39 static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
  40 {
  41         return (val & mxsfb->devdata->hs_wdth_mask) <<
  42                 mxsfb->devdata->hs_wdth_shift;
  43 }
  44 
  45 /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
  46 static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
  47 {
  48         struct drm_crtc *crtc = &mxsfb->pipe.crtc;
  49         struct drm_device *drm = crtc->dev;
  50         const u32 format = crtc->primary->state->fb->format->format;
  51         u32 ctrl, ctrl1;
  52 
  53         ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
  54 
  55         /*
  56          * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
  57          * match the selected mode here. This differs from the original
  58          * MXSFB driver, which had the option to configure the bus width
  59          * to arbitrary value. This limitation should not pose an issue.
  60          */
  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_SET_WORD_LENGTH(0);
  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_SET_WORD_LENGTH(3);
  75                 /* Do not use packed pixels = one pixel per word instead. */
  76                 ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
  77                 break;
  78         default:
  79                 dev_err(drm->dev, "Unhandled pixel format %08x\n", format);
  80                 return -EINVAL;
  81         }
  82 
  83         writel(ctrl1, mxsfb->base + LCDC_CTRL1);
  84         writel(ctrl, mxsfb->base + LCDC_CTRL);
  85 
  86         return 0;
  87 }
  88 
  89 static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
  90 {
  91         struct drm_crtc *crtc = &mxsfb->pipe.crtc;
  92         struct drm_device *drm = crtc->dev;
  93         u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
  94         u32 reg;
  95 
  96         reg = readl(mxsfb->base + LCDC_CTRL);
  97 
  98         if (mxsfb->connector.display_info.num_bus_formats)
  99                 bus_format = mxsfb->connector.display_info.bus_formats[0];
 100 
 101         reg &= ~CTRL_BUS_WIDTH_MASK;
 102         switch (bus_format) {
 103         case MEDIA_BUS_FMT_RGB565_1X16:
 104                 reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT);
 105                 break;
 106         case MEDIA_BUS_FMT_RGB666_1X18:
 107                 reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_18BIT);
 108                 break;
 109         case MEDIA_BUS_FMT_RGB888_1X24:
 110                 reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
 111                 break;
 112         default:
 113                 dev_err(drm->dev, "Unknown media bus format %d\n", bus_format);
 114                 break;
 115         }
 116         writel(reg, mxsfb->base + LCDC_CTRL);
 117 }
 118 
 119 static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
 120 {
 121         u32 reg;
 122 
 123         if (mxsfb->clk_disp_axi)
 124                 clk_prepare_enable(mxsfb->clk_disp_axi);
 125         clk_prepare_enable(mxsfb->clk);
 126 
 127         /* If it was disabled, re-enable the mode again */
 128         writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
 129 
 130         /* Enable the SYNC signals first, then the DMA engine */
 131         reg = readl(mxsfb->base + LCDC_VDCTRL4);
 132         reg |= VDCTRL4_SYNC_SIGNALS_ON;
 133         writel(reg, mxsfb->base + LCDC_VDCTRL4);
 134 
 135         writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
 136 }
 137 
 138 static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 139 {
 140         u32 reg;
 141 
 142         /*
 143          * Even if we disable the controller here, it will still continue
 144          * until its FIFOs are running out of data
 145          */
 146         writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_CLR);
 147 
 148         readl_poll_timeout(mxsfb->base + LCDC_CTRL, reg, !(reg & CTRL_RUN),
 149                            0, 1000);
 150 
 151         reg = readl(mxsfb->base + LCDC_VDCTRL4);
 152         reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
 153         writel(reg, mxsfb->base + LCDC_VDCTRL4);
 154 
 155         clk_disable_unprepare(mxsfb->clk);
 156         if (mxsfb->clk_disp_axi)
 157                 clk_disable_unprepare(mxsfb->clk_disp_axi);
 158 }
 159 
 160 /*
 161  * Clear the bit and poll it cleared.  This is usually called with
 162  * a reset address and mask being either SFTRST(bit 31) or CLKGATE
 163  * (bit 30).
 164  */
 165 static int clear_poll_bit(void __iomem *addr, u32 mask)
 166 {
 167         u32 reg;
 168 
 169         writel(mask, addr + MXS_CLR_ADDR);
 170         return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
 171 }
 172 
 173 static int mxsfb_reset_block(void __iomem *reset_addr)
 174 {
 175         int ret;
 176 
 177         ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
 178         if (ret)
 179                 return ret;
 180 
 181         writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
 182 
 183         ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
 184         if (ret)
 185                 return ret;
 186 
 187         return clear_poll_bit(reset_addr, MODULE_CLKGATE);
 188 }
 189 
 190 static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
 191 {
 192         struct drm_framebuffer *fb = mxsfb->pipe.plane.state->fb;
 193         struct drm_gem_cma_object *gem;
 194 
 195         if (!fb)
 196                 return 0;
 197 
 198         gem = drm_fb_cma_get_gem_obj(fb, 0);
 199         if (!gem)
 200                 return 0;
 201 
 202         return gem->paddr;
 203 }
 204 
 205 static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 206 {
 207         struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
 208         const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
 209         u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
 210         int err;
 211 
 212         /*
 213          * It seems, you can't re-program the controller if it is still
 214          * running. This may lead to shifted pictures (FIFO issue?), so
 215          * first stop the controller and drain its FIFOs.
 216          */
 217 
 218         /* Mandatory eLCDIF reset as per the Reference Manual */
 219         err = mxsfb_reset_block(mxsfb->base);
 220         if (err)
 221                 return;
 222 
 223         /* Clear the FIFOs */
 224         writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
 225 
 226         err = mxsfb_set_pixel_fmt(mxsfb);
 227         if (err)
 228                 return;
 229 
 230         clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 231 
 232         writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
 233                TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
 234                mxsfb->base + mxsfb->devdata->transfer_count);
 235 
 236         vsync_pulse_len = m->crtc_vsync_end - m->crtc_vsync_start;
 237 
 238         vdctrl0 = VDCTRL0_ENABLE_PRESENT |      /* Always in DOTCLOCK mode */
 239                   VDCTRL0_VSYNC_PERIOD_UNIT |
 240                   VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
 241                   VDCTRL0_SET_VSYNC_PULSE_WIDTH(vsync_pulse_len);
 242         if (m->flags & DRM_MODE_FLAG_PHSYNC)
 243                 vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
 244         if (m->flags & DRM_MODE_FLAG_PVSYNC)
 245                 vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
 246         /* Make sure Data Enable is high active by default */
 247         if (!(bus_flags & DRM_BUS_FLAG_DE_LOW))
 248                 vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
 249         /*
 250          * DRM_BUS_FLAG_PIXDATA_DRIVE_ defines are controller centric,
 251          * controllers VDCTRL0_DOTCLK is display centric.
 252          * Drive on positive edge       -> display samples on falling edge
 253          * DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE -> VDCTRL0_DOTCLK_ACT_FALLING
 254          */
 255         if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
 256                 vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
 257 
 258         writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0);
 259 
 260         mxsfb_set_bus_fmt(mxsfb);
 261 
 262         /* Frame length in lines. */
 263         writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1);
 264 
 265         /* Line length in units of clocks or pixels. */
 266         hsync_pulse_len = m->crtc_hsync_end - m->crtc_hsync_start;
 267         writel(set_hsync_pulse_width(mxsfb, hsync_pulse_len) |
 268                VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal),
 269                mxsfb->base + LCDC_VDCTRL2);
 270 
 271         writel(SET_HOR_WAIT_CNT(m->crtc_htotal - m->crtc_hsync_start) |
 272                SET_VERT_WAIT_CNT(m->crtc_vtotal - m->crtc_vsync_start),
 273                mxsfb->base + LCDC_VDCTRL3);
 274 
 275         writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay),
 276                mxsfb->base + LCDC_VDCTRL4);
 277 }
 278 
 279 void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 280 {
 281         dma_addr_t paddr;
 282 
 283         mxsfb_enable_axi_clk(mxsfb);
 284         mxsfb_crtc_mode_set_nofb(mxsfb);
 285 
 286         /* Write cur_buf as well to avoid an initial corrupt frame */
 287         paddr = mxsfb_get_fb_paddr(mxsfb);
 288         if (paddr) {
 289                 writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf);
 290                 writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
 291         }
 292 
 293         mxsfb_enable_controller(mxsfb);
 294 }
 295 
 296 void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
 297 {
 298         mxsfb_disable_controller(mxsfb);
 299         mxsfb_disable_axi_clk(mxsfb);
 300 }
 301 
 302 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
 303                                struct drm_plane_state *state)
 304 {
 305         struct drm_simple_display_pipe *pipe = &mxsfb->pipe;
 306         struct drm_crtc *crtc = &pipe->crtc;
 307         struct drm_pending_vblank_event *event;
 308         dma_addr_t paddr;
 309 
 310         spin_lock_irq(&crtc->dev->event_lock);
 311         event = crtc->state->event;
 312         if (event) {
 313                 crtc->state->event = NULL;
 314 
 315                 if (drm_crtc_vblank_get(crtc) == 0) {
 316                         drm_crtc_arm_vblank_event(crtc, event);
 317                 } else {
 318                         drm_crtc_send_vblank_event(crtc, event);
 319                 }
 320         }
 321         spin_unlock_irq(&crtc->dev->event_lock);
 322 
 323         paddr = mxsfb_get_fb_paddr(mxsfb);
 324         if (paddr) {
 325                 mxsfb_enable_axi_clk(mxsfb);
 326                 writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
 327                 mxsfb_disable_axi_clk(mxsfb);
 328         }
 329 }

/* [<][>][^][v][top][bottom][index][help] */