On 07/01/2015 04:36 PM, Daniel Vetter wrote: > On Wed, Jul 01, 2015 at 04:21:55PM +0800, Mark Zhang wrote: >> This HACK adds a workqueue to refresh the display periodically. >> This is used just for testing. > > ->dirty is the drm hook you're looking for, it's meant to flush out any > frontbuffer rendering. Generic kms clients using the dumb buffers (e.g. > fedora boot splash) use this already. > Oh... I did a grep in drm source and are you talking about "drm_framebuffer_funcs->dirty"? Yeah, that should work for me.. but that requires userspace sending IOCTL to trigger, right? Honestly I'm lazy so I created this HACK so that I don't need userspace to test. > And of course you need to upload a new frame every time an (atomic) flip > happens too, but I guess you have that already. No need at all for a > periodic upload hack like this. > Yep. Thanks Daniel. Mark > Cheers, Daniel > >> >> Signed-off-by: Mark Zhang <markz@xxxxxxxxxx> >> --- >> drivers/gpu/drm/tegra/dc.c | 37 +++++++++++++++++++++++++++++++++++++ >> drivers/gpu/drm/tegra/drm.h | 1 + >> 2 files changed, 38 insertions(+) >> >> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c >> index 24a91613c4f5..4381691c73f7 100644 >> --- a/drivers/gpu/drm/tegra/dc.c >> +++ b/drivers/gpu/drm/tegra/dc.c >> @@ -1296,6 +1296,8 @@ static void tegra_crtc_mode_set_nofb(struct drm_crtc *crtc) >> value &= ~DISP_CTRL_MODE_MASK; >> value |= DISP_CTRL_MODE_NC_DISPLAY; >> tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); >> + >> + schedule_work(&dc->one_shot_trigger); >> } else { >> value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); >> value &= ~DISP_CTRL_MODE_MASK; >> @@ -1958,6 +1960,40 @@ static void tegra_dc_one_shot_work(struct work_struct *work) >> drm_modeset_unlock_all(drm); >> } >> >> +static void tegra_dc_one_shot_trigger(struct work_struct *work) >> +{ >> + struct tegra_dc *dc; >> + struct drm_connector *connector; >> + struct drm_device *drm; >> + unsigned long update_mask = GENERAL_ACT_REQ | NC_HOST_TRIG; >> + static int first_trigger = 1; >> + >> + dc = container_of(work, struct tegra_dc, one_shot_trigger); >> + drm = dc->base.dev; >> + msleep(5000); >> + >> + if (first_trigger) { >> + dev_info(dc->dev, "First one-shot triggered.\n"); >> + tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL); >> + first_trigger = 0; >> + schedule_work(&dc->one_shot_trigger); >> + return; >> + } >> + >> + dev_info(dc->dev, "one-shot: Wakeup dc/dsi/panel.\n"); >> + drm_modeset_lock_all(drm); >> + list_for_each_entry(connector, &drm->mode_config.connector_list, head) { >> + if (connector->funcs->dpms) >> + connector->funcs->dpms(connector, >> + DRM_MODE_DPMS_STANDBY); >> + } >> + drm_modeset_unlock_all(drm); >> + >> + /* Trigger the one-shot */ >> + tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL); >> + schedule_work(&dc->one_shot_trigger); >> +} >> + >> static int tegra_dc_probe(struct platform_device *pdev) >> { >> unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; >> @@ -1977,6 +2013,7 @@ static int tegra_dc_probe(struct platform_device *pdev) >> spin_lock_init(&dc->lock); >> INIT_LIST_HEAD(&dc->list); >> INIT_WORK(&dc->one_shot_work, tegra_dc_one_shot_work); >> + INIT_WORK(&dc->one_shot_trigger, tegra_dc_one_shot_trigger); >> dc->dev = &pdev->dev; >> dc->soc = id->data; >> >> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h >> index 00daf427c831..5d606cacb098 100644 >> --- a/drivers/gpu/drm/tegra/drm.h >> +++ b/drivers/gpu/drm/tegra/drm.h >> @@ -132,6 +132,7 @@ struct tegra_dc { >> struct drm_pending_vblank_event *event; >> >> struct work_struct one_shot_work; >> + struct work_struct one_shot_trigger; >> >> const struct tegra_dc_soc_info *soc; >> >> -- >> 1.7.9.5 >> > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel