On Mon, Apr 11, 2016 at 07:46:31PM +0300, Jyri Sarha wrote: > Add tilcdc_crtc_mode_set_nofb(). The mode_set_nofb() semantics do not > fit well to LCDC, because of the mandatory framebuffer. However, when > the primary plane is required in the check phase, it and the > framebuffer can be found from the atomic state struct. > > Signed-off-by: Jyri Sarha <jsarha@xxxxxx> Yeah, if your hw always requires a primary plane then 2 bits needed: a) make sure in the crtc's atomic_check it's there and set b) just use the hooks whoever you want to. Atomic allows planes to be entirely independent of the display pipeline, but doesn't require it really. -Daniel > --- > drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 172 +++++++++++++++++++++++++++++++++++ > 1 file changed, 172 insertions(+) > > diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c > index 919c901..35f5682 100644 > --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c > +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c > @@ -310,6 +310,177 @@ static void tilcdc_crtc_commit(struct drm_crtc *crtc) > 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, > @@ -526,6 +697,7 @@ static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = { > .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) > -- > 1.9.1 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel