static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; if (amdgpu_sriov_vf(adev)) return; switch (mode) { case DRM_MODE_DPMS_ON: amdgpu_crtc->enabled = true; /* Make sure VBLANK interrupts are still enabled */ type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); amdgpu_irq_update(adev, &adev->crtc_irq, type); drm_crtc_vblank_on(crtc); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: drm_crtc_vblank_off(crtc); amdgpu_crtc->enabled = false; break; } }
void pl111_display_disable(struct drm_simple_display_pipe *pipe) { struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; u32 cntl; if (!priv->variant->broken_vblank) drm_crtc_vblank_off(crtc); /* Power Down */ cntl = readl(priv->regs + priv->ctrl); if (cntl & CNTL_LCDPWR) { cntl &= ~CNTL_LCDPWR; writel(cntl, priv->regs + priv->ctrl); } /* * We expect this delay to stabilize the contrast voltage Vee as * stipulated by the manual */ msleep(20); if (priv->variant_display_disable) priv->variant_display_disable(drm); /* Disable */ writel(0, priv->regs + priv->ctrl); clk_disable_unprepare(priv->clk); }
static void hdlcd_crtc_disable(struct drm_crtc *crtc) { struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); drm_crtc_vblank_off(crtc); hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0); clk_disable_unprepare(hdlcd->clk); }
static void omap_crtc_disable(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); DBG("%s", omap_crtc->name); drm_crtc_vblank_off(crtc); }
static void exynos_drm_crtc_disable(struct drm_crtc *crtc) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); drm_crtc_vblank_off(crtc); if (exynos_crtc->ops->disable) exynos_crtc->ops->disable(exynos_crtc); }
static void ade_crtc_disable(struct drm_crtc *crtc) { struct ade_crtc *acrtc = to_ade_crtc(crtc); struct ade_hw_ctx *ctx = acrtc->ctx; if (!acrtc->enable) return; drm_crtc_vblank_off(crtc); ade_power_down(ctx); acrtc->enable = false; }
static void ipu_fb_disable(struct ipu_crtc *ipu_crtc) { struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); if (!ipu_crtc->enabled) return; /* Stop DC channel and DI before IDMAC */ ipu_dc_disable_channel(ipu_crtc->dc); ipu_di_disable(ipu_crtc->di); ipu_plane_disable(ipu_crtc->plane[0]); ipu_dc_disable(ipu); drm_crtc_vblank_off(&ipu_crtc->base); ipu_crtc->enabled = 0; }
static void fsl_dcu_drm_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { struct drm_device *dev = crtc->dev; struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; /* always disable planes on the CRTC */ drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, true); drm_crtc_vblank_off(crtc); regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, DCU_MODE_DCU_MODE_MASK, DCU_MODE_DCU_MODE(DCU_MODE_OFF)); regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG); clk_disable_unprepare(fsl_dev->pix_clk); }
static void exynos_drm_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); drm_crtc_vblank_off(crtc); if (exynos_crtc->ops->disable) exynos_crtc->ops->disable(exynos_crtc); if (crtc->state->event && !crtc->state->active) { spin_lock_irq(&crtc->dev->event_lock); drm_crtc_send_vblank_event(crtc, crtc->state->event); spin_unlock_irq(&crtc->dev->event_lock); crtc->state->event = NULL; } }
static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) { struct drm_crtc *crtc = &rcrtc->crtc; if (!rcrtc->started) return; /* Disable all planes and wait for the change to take effect. This is * required as the DSnPR registers are updated on vblank, and no vblank * will occur once the CRTC is stopped. Disabling planes when starting * the CRTC thus wouldn't be enough as it would start scanning out * immediately from old frame buffers until the next vblank. * * This increases the CRTC stop delay, especially when multiple CRTCs * are stopped in one operation as we now wait for one vblank per CRTC. * Whether this can be improved needs to be researched. */ rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0); drm_crtc_wait_one_vblank(crtc); /* Disable vertical blanking interrupt reporting. We first need to wait * for page flip completion before stopping the CRTC as userspace * expects page flips to eventually complete. */ rcar_du_crtc_wait_page_flip(rcrtc); drm_crtc_vblank_off(crtc); /* Disable the VSP compositor. */ if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) rcar_du_vsp_disable(rcrtc); /* Select switch sync mode. This stops display operation and configures * the HSYNC and VSYNC signals as inputs. */ rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH); rcar_du_group_start_stop(rcrtc->group, false); rcrtc->started = false; }
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) { static const unsigned int mmio_offsets[] = { DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET }; struct rcar_du_device *rcdu = rgrp->dev; struct platform_device *pdev = to_platform_device(rcdu->dev); struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; struct drm_crtc *crtc = &rcrtc->crtc; unsigned int irqflags; struct clk *clk; char clk_name[9]; char *name; int irq; int ret; /* Get the CRTC clock and the optional external clock. */ if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { sprintf(clk_name, "du.%u", index); name = clk_name; } else { name = NULL; } rcrtc->clock = devm_clk_get(rcdu->dev, name); if (IS_ERR(rcrtc->clock)) { dev_err(rcdu->dev, "no clock for CRTC %u\n", index); return PTR_ERR(rcrtc->clock); } sprintf(clk_name, "dclkin.%u", index); clk = devm_clk_get(rcdu->dev, clk_name); if (!IS_ERR(clk)) { rcrtc->extclock = clk; } else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) { dev_info(rcdu->dev, "can't get external clock %u\n", index); return -EPROBE_DEFER; } init_waitqueue_head(&rcrtc->flip_wait); rcrtc->group = rgrp; rcrtc->mmio_offset = mmio_offsets[index]; rcrtc->index = index; rcrtc->enabled = false; ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, &rgrp->planes[index % 2].plane, NULL, &crtc_funcs); if (ret < 0) return ret; drm_crtc_helper_add(crtc, &crtc_helper_funcs); /* Start with vertical blanking interrupt reporting disabled. */ drm_crtc_vblank_off(crtc); /* Register the interrupt handler. */ if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { irq = platform_get_irq(pdev, index); irqflags = 0; } else { irq = platform_get_irq(pdev, 0); irqflags = IRQF_SHARED; } if (irq < 0) { dev_err(rcdu->dev, "no IRQ for CRTC %u\n", index); return irq; } ret = devm_request_irq(rcdu->dev, irq, rcar_du_crtc_irq, irqflags, dev_name(rcdu->dev), rcrtc); if (ret < 0) { dev_err(rcdu->dev, "failed to register IRQ for CRTC %u\n", index); return ret; } return 0; }
static int pdev_probe(struct platform_device *pdev) { const struct soc_device_attribute *soc; struct omap_drm_private *priv; struct drm_device *ddev; unsigned int i; int ret; DBG("%s", pdev->name); if (omapdss_is_initialized() == false) return -EPROBE_DEFER; ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) { dev_err(&pdev->dev, "Failed to set the DMA mask\n"); return ret; } omap_crtc_pre_init(); ret = omap_connect_dssdevs(); if (ret) goto err_crtc_uninit; /* Allocate and initialize the driver private structure. */ priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; goto err_disconnect_dssdevs; } priv->dispc_ops = dispc_get_ops(); soc = soc_device_match(omapdrm_soc_devices); priv->omaprev = soc ? (unsigned int)soc->data : 0; priv->wq = alloc_ordered_workqueue("omapdrm", 0); spin_lock_init(&priv->list_lock); INIT_LIST_HEAD(&priv->obj_list); /* Allocate and initialize the DRM device. */ ddev = drm_dev_alloc(&omap_drm_driver, &pdev->dev); if (IS_ERR(ddev)) { ret = PTR_ERR(ddev); goto err_free_priv; } ddev->dev_private = priv; platform_set_drvdata(pdev, ddev); /* Get memory bandwidth limits */ if (priv->dispc_ops->get_memory_bandwidth_limit) priv->max_bandwidth = priv->dispc_ops->get_memory_bandwidth_limit(); omap_gem_init(ddev); ret = omap_modeset_init(ddev); if (ret) { dev_err(&pdev->dev, "omap_modeset_init failed: ret=%d\n", ret); goto err_free_drm_dev; } /* Initialize vblank handling, start with all CRTCs disabled. */ ret = drm_vblank_init(ddev, priv->num_crtcs); if (ret) { dev_err(&pdev->dev, "could not init vblank\n"); goto err_cleanup_modeset; } for (i = 0; i < priv->num_crtcs; i++) drm_crtc_vblank_off(priv->crtcs[i]); priv->fbdev = omap_fbdev_init(ddev); drm_kms_helper_poll_init(ddev); omap_modeset_enable_external_hpd(); /* * Register the DRM device with the core and the connectors with * sysfs. */ ret = drm_dev_register(ddev, 0); if (ret) goto err_cleanup_helpers; return 0; err_cleanup_helpers: omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev); if (priv->fbdev) omap_fbdev_free(ddev); err_cleanup_modeset: drm_mode_config_cleanup(ddev); omap_drm_irq_uninstall(ddev); err_free_drm_dev: omap_gem_deinit(ddev); drm_dev_unref(ddev); err_free_priv: destroy_workqueue(priv->wq); kfree(priv); err_disconnect_dssdevs: omap_disconnect_dssdevs(); err_crtc_uninit: omap_crtc_pre_uninit(); return ret; }