Skip to content

Commit

Permalink
Merge tag 'sti-drm-next-2017-02-10' of https://github.com/vinceab/linux
Browse files Browse the repository at this point in the history
… into drm-next

- remove deprecated stih416 chip functionnalities
- fix issues met around gdp panes
- fix STI driver unbind procedure
- DVI/HDMI mode is automatically detected
- allow fps statisitics resetting

* tag 'sti-drm-next-2017-02-10' of https://github.com/vinceab/linux:
  drm/sti: debug fps reset
  drm/sti: hdmi: automatically check DVI/HDMI mode
  drm/sti: unbind all components while driver cleanup
  drm/sti: do not post GDP command if no update
  drm/sti: do not set gdp pixel clock rate if mode is not set
  drm/sti: enable gdp pixel clock in atomic_update
  drm/sti: remove deprecated legacy vtg slave
  drm/sti: remove deprecated sink_term config
  drm/sti: do not check hw scaling if mode is not set
  drm/sti: Fix up crtc_state->event handling
  drm/sti: use atomic_helper for commit
  • Loading branch information
Dave Airlie committed Feb 16, 2017
2 parents 13f62f5 + c462c2f commit 1e9d996
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 250 deletions.
46 changes: 14 additions & 32 deletions drivers/gpu/drm/sti/sti_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,28 +134,15 @@ sti_crtc_mode_set_nofb(struct drm_crtc *crtc)
sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
}

static void sti_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct sti_mixer *mixer = to_sti_mixer(crtc);

if (crtc->state->event) {
crtc->state->event->pipe = drm_crtc_index(crtc);

WARN_ON(drm_crtc_vblank_get(crtc) != 0);

mixer->pending_event = crtc->state->event;
crtc->state->event = NULL;
}
}

static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct drm_device *drm_dev = crtc->dev;
struct sti_mixer *mixer = to_sti_mixer(crtc);
struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
struct drm_plane *p;
struct drm_pending_vblank_event *event;
unsigned long flags;

DRM_DEBUG_DRIVER("\n");

Expand Down Expand Up @@ -220,13 +207,24 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
break;
}
}

event = crtc->state->event;
if (event) {
crtc->state->event = NULL;

spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (drm_crtc_vblank_get(crtc) == 0)
drm_crtc_arm_vblank_event(crtc, event);
else
drm_crtc_send_vblank_event(crtc, event);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
}
}

static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
.enable = sti_crtc_enable,
.disable = sti_crtc_disabling,
.mode_set_nofb = sti_crtc_mode_set_nofb,
.atomic_begin = sti_crtc_atomic_begin,
.atomic_flush = sti_crtc_atomic_flush,
};

Expand All @@ -250,7 +248,6 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,
struct sti_compositor *compo;
struct drm_crtc *crtc = data;
struct sti_mixer *mixer;
unsigned long flags;
struct sti_private *priv;
unsigned int pipe;

Expand All @@ -267,14 +264,6 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,

drm_crtc_handle_vblank(crtc);

spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (mixer->pending_event) {
drm_crtc_send_vblank_event(crtc, mixer->pending_event);
drm_crtc_vblank_put(crtc);
mixer->pending_event = NULL;
}
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);

if (mixer->status == STI_MIXER_DISABLING) {
struct drm_plane *p;

Expand Down Expand Up @@ -317,19 +306,12 @@ void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
struct sti_private *priv = drm_dev->dev_private;
struct sti_compositor *compo = priv->compo;
struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe];
struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
struct sti_vtg *vtg = compo->vtg[pipe];

DRM_DEBUG_DRIVER("\n");

if (sti_vtg_unregister_client(vtg, vtg_vblank_nb))
DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");

/* free the resources of the pending requests */
if (compo->mixer[pipe]->pending_event) {
drm_crtc_vblank_put(crtc);
compo->mixer[pipe]->pending_event = NULL;
}
}

static int sti_crtc_late_register(struct drm_crtc *crtc)
Expand Down
87 changes: 9 additions & 78 deletions drivers/gpu/drm/sti/sti_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ static int sti_drm_fps_set(void *data, u64 val)
list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
struct sti_plane *plane = to_sti_plane(p);

memset(&plane->fps_info, 0, sizeof(plane->fps_info));
plane->fps_info.output = (val >> i) & 1;

i++;
}

Expand Down Expand Up @@ -115,50 +117,13 @@ static int sti_drm_dbg_init(struct drm_minor *minor)
return ret;
}

static void sti_atomic_schedule(struct sti_private *private,
struct drm_atomic_state *state)
{
private->commit.state = state;
schedule_work(&private->commit.work);
}

static void sti_atomic_complete(struct sti_private *private,
struct drm_atomic_state *state)
{
struct drm_device *drm = private->drm_dev;

/*
* Everything below can be run asynchronously without the need to grab
* any modeset locks at all under one condition: It must be guaranteed
* that the asynchronous work has either been cancelled (if the driver
* supports it, which at least requires that the framebuffers get
* cleaned up with drm_atomic_helper_cleanup_planes()) or completed
* before the new state gets committed on the software side with
* drm_atomic_helper_swap_state().
*
* This scheme allows new atomic state updates to be prepared and
* checked in parallel to the asynchronous completion of the previous
* update. Which is important since compositors need to figure out the
* composition of the next frame right after having submitted the
* current layout.
*/

drm_atomic_helper_commit_modeset_disables(drm, state);
drm_atomic_helper_commit_planes(drm, state, 0);
drm_atomic_helper_commit_modeset_enables(drm, state);

drm_atomic_helper_wait_for_vblanks(drm, state);

drm_atomic_helper_cleanup_planes(drm, state);
drm_atomic_state_put(state);
}

static void sti_atomic_work(struct work_struct *work)
static void sti_drm_dbg_cleanup(struct drm_minor *minor)
{
struct sti_private *private = container_of(work,
struct sti_private, commit.work);
drm_debugfs_remove_files(sti_drm_dbg_list,
ARRAY_SIZE(sti_drm_dbg_list), minor);

sti_atomic_complete(private, private->commit.state);
drm_debugfs_remove_files((struct drm_info_list *)&sti_drm_fps_fops,
1, minor);
}

static int sti_atomic_check(struct drm_device *dev,
Expand All @@ -181,38 +146,6 @@ static int sti_atomic_check(struct drm_device *dev,
return ret;
}

static int sti_atomic_commit(struct drm_device *drm,
struct drm_atomic_state *state, bool nonblock)
{
struct sti_private *private = drm->dev_private;
int err;

err = drm_atomic_helper_prepare_planes(drm, state);
if (err)
return err;

/* serialize outstanding nonblocking commits */
mutex_lock(&private->commit.lock);
flush_work(&private->commit.work);

/*
* This is the point of no return - everything below never fails except
* when the hw goes bonghits. Which means we can commit the new state on
* the software side now.
*/

drm_atomic_helper_swap_state(state, true);

drm_atomic_state_get(state);
if (nonblock)
sti_atomic_schedule(private, state);
else
sti_atomic_complete(private, state);

mutex_unlock(&private->commit.lock);
return 0;
}

static void sti_output_poll_changed(struct drm_device *ddev)
{
struct sti_private *private = ddev->dev_private;
Expand All @@ -224,7 +157,7 @@ static const struct drm_mode_config_funcs sti_mode_config_funcs = {
.fb_create = drm_fb_cma_create,
.output_poll_changed = sti_output_poll_changed,
.atomic_check = sti_atomic_check,
.atomic_commit = sti_atomic_commit,
.atomic_commit = drm_atomic_helper_commit,
};

static void sti_mode_config_init(struct drm_device *dev)
Expand Down Expand Up @@ -304,9 +237,6 @@ static int sti_init(struct drm_device *ddev)
dev_set_drvdata(ddev->dev, ddev);
private->drm_dev = ddev;

mutex_init(&private->commit.lock);
INIT_WORK(&private->commit.work, sti_atomic_work);

drm_mode_config_init(ddev);

sti_mode_config_init(ddev);
Expand All @@ -327,6 +257,7 @@ static void sti_cleanup(struct drm_device *ddev)

drm_kms_helper_poll_fini(ddev);
drm_vblank_cleanup(ddev);
component_unbind_all(ddev->dev, ddev);
kfree(private);
ddev->dev_private = NULL;
}
Expand Down
6 changes: 0 additions & 6 deletions drivers/gpu/drm/sti/sti_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ struct sti_private {
struct drm_property *plane_zorder_property;
struct drm_device *drm_dev;
struct drm_fbdev_cma *fbdev;

struct {
struct drm_atomic_state *state;
struct work_struct work;
struct mutex lock;
} commit;
};

extern struct platform_driver sti_tvout_driver;
Expand Down
85 changes: 47 additions & 38 deletions drivers/gpu/drm/sti/sti_gdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,6 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane,
struct sti_plane *plane = to_sti_plane(drm_plane);
struct sti_gdp *gdp = to_sti_gdp(plane);
struct drm_crtc *crtc = state->crtc;
struct sti_compositor *compo = dev_get_drvdata(gdp->dev);
struct drm_framebuffer *fb = state->fb;
struct drm_crtc_state *crtc_state;
struct sti_mixer *mixer;
Expand Down Expand Up @@ -648,45 +647,30 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane,
return -EINVAL;
}

if (!gdp->vtg) {
/* Register gdp callback */
gdp->vtg = compo->vtg[mixer->id];
if (sti_vtg_register_client(gdp->vtg,
&gdp->vtg_field_nb, crtc)) {
DRM_ERROR("Cannot register VTG notifier\n");
/* Set gdp clock */
if (mode->clock && gdp->clk_pix) {
struct clk *clkp;
int rate = mode->clock * 1000;
int res;

/*
* According to the mixer used, the gdp pixel clock
* should have a different parent clock.
*/
if (mixer->id == STI_MIXER_MAIN)
clkp = gdp->clk_main_parent;
else
clkp = gdp->clk_aux_parent;

if (clkp)
clk_set_parent(gdp->clk_pix, clkp);

res = clk_set_rate(gdp->clk_pix, rate);
if (res < 0) {
DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
rate);
return -EINVAL;
}

/* Set and enable gdp clock */
if (gdp->clk_pix) {
struct clk *clkp;
int rate = mode->clock * 1000;
int res;

/*
* According to the mixer used, the gdp pixel clock
* should have a different parent clock.
*/
if (mixer->id == STI_MIXER_MAIN)
clkp = gdp->clk_main_parent;
else
clkp = gdp->clk_aux_parent;

if (clkp)
clk_set_parent(gdp->clk_pix, clkp);

res = clk_set_rate(gdp->clk_pix, rate);
if (res < 0) {
DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
rate);
return -EINVAL;
}

if (clk_prepare_enable(gdp->clk_pix)) {
DRM_ERROR("Failed to prepare/enable gdp\n");
return -EINVAL;
}
}
}

DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
Expand Down Expand Up @@ -724,6 +708,31 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
if (!crtc || !fb)
return;

if ((oldstate->fb == state->fb) &&
(oldstate->crtc_x == state->crtc_x) &&
(oldstate->crtc_y == state->crtc_y) &&
(oldstate->crtc_w == state->crtc_w) &&
(oldstate->crtc_h == state->crtc_h) &&
(oldstate->src_x == state->src_x) &&
(oldstate->src_y == state->src_y) &&
(oldstate->src_w == state->src_w) &&
(oldstate->src_h == state->src_h)) {
/* No change since last update, do not post cmd */
DRM_DEBUG_DRIVER("No change, not posting cmd\n");
plane->status = STI_PLANE_UPDATED;
return;
}

if (!gdp->vtg) {
struct sti_compositor *compo = dev_get_drvdata(gdp->dev);
struct sti_mixer *mixer = to_sti_mixer(crtc);

/* Register gdp callback */
gdp->vtg = compo->vtg[mixer->id];
sti_vtg_register_client(gdp->vtg, &gdp->vtg_field_nb, crtc);
clk_prepare_enable(gdp->clk_pix);
}

mode = &crtc->mode;
dst_x = state->crtc_x;
dst_y = state->crtc_y;
Expand Down
Loading

0 comments on commit 1e9d996

Please sign in to comment.