Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e9d9966 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'sti-drm-next-2017-02-10' of https://github.com/vinceab/linux 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
parents 13f62f54 c462c2f5
Loading
Loading
Loading
Loading
+14 −32
Original line number Diff line number Diff line
@@ -134,21 +134,6 @@ 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)
{
@@ -156,6 +141,8 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
	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");

@@ -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,
};

@@ -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;

@@ -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;

@@ -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)
+9 −78
Original line number Diff line number Diff line
@@ -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++;
	}

@@ -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,
@@ -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;
@@ -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)
@@ -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);
@@ -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;
}
+0 −6
Original line number Diff line number Diff line
@@ -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;
+47 −38
Original line number Diff line number Diff line
@@ -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;
@@ -648,17 +647,8 @@ 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");
			return -EINVAL;
		}

		/* Set and enable gdp clock */
		if (gdp->clk_pix) {
	/* Set gdp clock */
	if (mode->clock && gdp->clk_pix) {
		struct clk *clkp;
		int rate = mode->clock * 1000;
		int res;
@@ -681,12 +671,6 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane,
				  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",
@@ -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;
+6 −32
Original line number Diff line number Diff line
@@ -95,7 +95,6 @@
#define HDMI_CFG_HDCP_EN                BIT(2)
#define HDMI_CFG_ESS_NOT_OESS           BIT(3)
#define HDMI_CFG_H_SYNC_POL_NEG         BIT(4)
#define HDMI_CFG_SINK_TERM_DET_EN       BIT(5)
#define HDMI_CFG_V_SYNC_POL_NEG         BIT(6)
#define HDMI_CFG_422_EN                 BIT(8)
#define HDMI_CFG_FIFO_OVERRUN_CLR       BIT(12)
@@ -159,7 +158,6 @@ struct sti_hdmi_connector {
	struct drm_encoder *encoder;
	struct sti_hdmi *hdmi;
	struct drm_property *colorspace_property;
	struct drm_property *hdmi_mode_property;
};

#define to_sti_hdmi_connector(x) \
@@ -266,12 +264,9 @@ static void hdmi_config(struct sti_hdmi *hdmi)

	/* Select encryption type and the framing mode */
	conf |= HDMI_CFG_ESS_NOT_OESS;
	if (hdmi->hdmi_mode == HDMI_MODE_HDMI)
	if (hdmi->hdmi_monitor)
		conf |= HDMI_CFG_HDMI_NOT_DVI;

	/* Enable sink term detection */
	conf |= HDMI_CFG_SINK_TERM_DET_EN;

	/* Set Hsync polarity */
	if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) {
		DRM_DEBUG_DRIVER("H Sync Negative\n");
@@ -607,9 +602,6 @@ static void hdmi_dbg_cfg(struct seq_file *s, int val)
	tmp = val & HDMI_CFG_ESS_NOT_OESS;
	DBGFS_PRINT_STR("HDCP mode:", tmp ? "ESS enable" : "OESS enable");
	seq_puts(s, "\t\t\t\t\t");
	tmp = val & HDMI_CFG_SINK_TERM_DET_EN;
	DBGFS_PRINT_STR("Sink term detection:", tmp ? "enable" : "disable");
	seq_puts(s, "\t\t\t\t\t");
	tmp = val & HDMI_CFG_H_SYNC_POL_NEG;
	DBGFS_PRINT_STR("Hsync polarity:", tmp ? "inverted" : "normal");
	seq_puts(s, "\t\t\t\t\t");
@@ -977,6 +969,11 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
	if (!edid)
		goto fail;

	hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid);
	DRM_DEBUG_KMS("%s : %dx%d cm\n",
		      (hdmi->hdmi_monitor ? "hdmi monitor" : "dvi monitor"),
		      edid->width_cm, edid->height_cm);

	count = drm_add_edid_modes(connector, edid);
	drm_mode_connector_update_edid_property(connector, edid);
	drm_edid_to_eld(connector, edid);
@@ -1060,19 +1057,6 @@ static void sti_hdmi_connector_init_property(struct drm_device *drm_dev,
	}
	hdmi_connector->colorspace_property = prop;
	drm_object_attach_property(&connector->base, prop, hdmi->colorspace);

	/* hdmi_mode property */
	hdmi->hdmi_mode = DEFAULT_HDMI_MODE;
	prop = drm_property_create_enum(drm_dev, 0, "hdmi_mode",
					hdmi_mode_names,
					ARRAY_SIZE(hdmi_mode_names));
	if (!prop) {
		DRM_ERROR("fails to create colorspace property\n");
		return;
	}
	hdmi_connector->hdmi_mode_property = prop;
	drm_object_attach_property(&connector->base, prop, hdmi->hdmi_mode);

}

static int
@@ -1090,11 +1074,6 @@ sti_hdmi_connector_set_property(struct drm_connector *connector,
		return 0;
	}

	if (property == hdmi_connector->hdmi_mode_property) {
		hdmi->hdmi_mode = val;
		return 0;
	}

	DRM_ERROR("failed to set hdmi connector property\n");
	return -EINVAL;
}
@@ -1114,11 +1093,6 @@ sti_hdmi_connector_get_property(struct drm_connector *connector,
		return 0;
	}

	if (property == hdmi_connector->hdmi_mode_property) {
		*val = hdmi->hdmi_mode;
		return 0;
	}

	DRM_ERROR("failed to get hdmi connector property\n");
	return -EINVAL;
}
Loading