tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
}
+static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct tilcdc_drm_private *priv = dev->dev_private;
+ const struct tilcdc_panel_info *info = tilcdc_crtc->info;
+ uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw;
+ struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+ struct drm_framebuffer *fb = crtc->primary->state->fb;
+
+ if (WARN_ON(!info))
+ return;
+
+ if (WARN_ON(!fb))
+ return;
+
+ pm_runtime_get_sync(dev->dev);
+
+ /* Configure the Burst Size and fifo threshold of DMA: */
+ reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770;
+ switch (info->dma_burst_sz) {
+ case 1:
+ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1);
+ break;
+ case 2:
+ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2);
+ break;
+ case 4:
+ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4);
+ break;
+ case 8:
+ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8);
+ break;
+ case 16:
+ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16);
+ break;
+ default:
+ dev_err(dev->dev, "invalid burst size\n");
+ return;
+ }
+ reg |= (info->fifo_th << 8);
+ tilcdc_write(dev, LCDC_DMA_CTRL_REG, reg);
+
+ /* Configure timings: */
+ hbp = mode->htotal - mode->hsync_end;
+ hfp = mode->hsync_start - mode->hdisplay;
+ hsw = mode->hsync_end - mode->hsync_start;
+ vbp = mode->vtotal - mode->vsync_end;
+ vfp = mode->vsync_start - mode->vdisplay;
+ vsw = mode->vsync_end - mode->vsync_start;
+
+ DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u",
+ mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw);
+
+ /* Set AC Bias Period and Number of Transitions per Interrupt: */
+ reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00;
+ reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) |
+ LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt);
+
+ /*
+ * subtract one from hfp, hbp, hsw because the hardware uses
+ * a value of 0 as 1
+ */
+ if (priv->rev == 2) {
+ /* clear bits we're going to set */
+ reg &= ~0x78000033;
+ reg |= ((hfp-1) & 0x300) >> 8;
+ reg |= ((hbp-1) & 0x300) >> 4;
+ reg |= ((hsw-1) & 0x3c0) << 21;
+ }
+ tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);
+
+ reg = (((mode->hdisplay >> 4) - 1) << 4) |
+ (((hbp-1) & 0xff) << 24) |
+ (((hfp-1) & 0xff) << 16) |
+ (((hsw-1) & 0x3f) << 10);
+ if (priv->rev == 2)
+ reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
+ tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
+
+ reg = ((mode->vdisplay - 1) & 0x3ff) |
+ ((vbp & 0xff) << 24) |
+ ((vfp & 0xff) << 16) |
+ (((vsw-1) & 0x3f) << 10);
+ tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
+
+ /*
+ * be sure to set Bit 10 for the V2 LCDC controller,
+ * otherwise limited to 1024 pixels width, stopping
+ * 1920x1080 being supported.
+ */
+ if (priv->rev == 2) {
+ if ((mode->vdisplay - 1) & 0x400) {
+ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG,
+ LCDC_LPP_B10);
+ } else {
+ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG,
+ LCDC_LPP_B10);
+ }
+ }
+
+ /* Configure display type: */
+ reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) &
+ ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
+ LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK |
+ 0x000ff000 /* Palette Loading Delay bits */);
+ reg |= LCDC_TFT_MODE; /* no monochrome/passive support */
+ if (info->tft_alt_mode)
+ reg |= LCDC_TFT_ALT_ENABLE;
+ if (priv->rev == 2) {
+ unsigned int depth, bpp;
+
+ drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
+ switch (bpp) {
+ case 16:
+ break;
+ case 32:
+ reg |= LCDC_V2_TFT_24BPP_UNPACK;
+ /* fallthrough */
+ case 24:
+ reg |= LCDC_V2_TFT_24BPP_MODE;
+ break;
+ default:
+ dev_err(dev->dev, "invalid pixel format\n");
+ return;
+ }
+ }
+ reg |= info->fdd < 12;
+ tilcdc_write(dev, LCDC_RASTER_CTRL_REG, reg);
+
+ if (info->invert_pxl_clk)
+ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
+ else
+ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
+
+ if (info->sync_ctrl)
+ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
+ else
+ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
+
+ if (info->sync_edge)
+ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
+ else
+ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
+
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
+ else
+ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
+
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
+ else
+ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
+
+ if (info->raster_order)
+ tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
+ else
+ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
+
+ drm_framebuffer_reference(fb);
+
+ set_scanout(crtc, fb);
+
+ tilcdc_crtc_update_clk(crtc);
+
+ pm_runtime_put_sync(dev->dev);
+
+ crtc->hwmode = crtc->state->adjusted_mode;
+}
+
static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
.commit = tilcdc_crtc_commit,
.mode_set = tilcdc_crtc_mode_set,
.mode_set_base = tilcdc_crtc_mode_set_base,
+ .mode_set_nofb = tilcdc_crtc_mode_set_nofb,
};
int tilcdc_crtc_max_width(struct drm_crtc *crtc)