Exemplo n.º 1
0
static int modeset_init(struct mdp5_kms *mdp5_kms)
{
	static const enum mdp5_pipe crtcs[] = {
			SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3,
	};
	static const enum mdp5_pipe pub_planes[] = {
			SSPP_VIG0, SSPP_VIG1, SSPP_VIG2, SSPP_VIG3,
	};
	struct drm_device *dev = mdp5_kms->dev;
	struct msm_drm_private *priv = dev->dev_private;
	const struct mdp5_cfg_hw *hw_cfg;
	int i, ret;

	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);

	/* register our interrupt-controller for hdmi/eDP/dsi/etc
	 * to use for irqs routed through mdp:
	 */
	ret = mdp5_irq_domain_init(mdp5_kms);
	if (ret)
		goto fail;

	/* construct CRTCs and their private planes: */
	for (i = 0; i < hw_cfg->pipe_rgb.count; i++) {
		struct drm_plane *plane;
		struct drm_crtc *crtc;

		plane = mdp5_plane_init(dev, crtcs[i], true,
				hw_cfg->pipe_rgb.base[i]);
		if (IS_ERR(plane)) {
			ret = PTR_ERR(plane);
			dev_err(dev->dev, "failed to construct plane for %s (%d)\n",
					pipe2name(crtcs[i]), ret);
			goto fail;
		}

		crtc  = mdp5_crtc_init(dev, plane, i);
		if (IS_ERR(crtc)) {
			ret = PTR_ERR(crtc);
			dev_err(dev->dev, "failed to construct crtc for %s (%d)\n",
					pipe2name(crtcs[i]), ret);
			goto fail;
		}
		priv->crtcs[priv->num_crtcs++] = crtc;
	}

	/* Construct public planes: */
	for (i = 0; i < hw_cfg->pipe_vig.count; i++) {
		struct drm_plane *plane;

		plane = mdp5_plane_init(dev, pub_planes[i], false,
				hw_cfg->pipe_vig.base[i]);
		if (IS_ERR(plane)) {
			ret = PTR_ERR(plane);
			dev_err(dev->dev, "failed to construct %s plane: %d\n",
					pipe2name(pub_planes[i]), ret);
			goto fail;
		}
	}

	/* Construct encoders and modeset initialize connector devices
	 * for each external display interface.
	 */
	for (i = 0; i < ARRAY_SIZE(hw_cfg->intfs); i++) {
		ret = modeset_init_intf(mdp5_kms, i);
		if (ret)
			goto fail;
	}

	return 0;

fail:
	return ret;
}
Exemplo n.º 2
0
static int modeset_init(struct mdp5_kms *mdp5_kms)
{
	struct drm_device *dev = mdp5_kms->dev;
	struct msm_drm_private *priv = dev->dev_private;
	const struct mdp5_cfg_hw *hw_cfg;
	unsigned int num_crtcs;
	int i, ret, pi = 0, ci = 0;
	struct drm_plane *primary[MAX_BASES] = { NULL };
	struct drm_plane *cursor[MAX_BASES] = { NULL };

	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);

	/*
	 * Construct encoders and modeset initialize connector devices
	 * for each external display interface.
	 */
	for (i = 0; i < mdp5_kms->num_intfs; i++) {
		ret = modeset_init_intf(mdp5_kms, mdp5_kms->intfs[i]);
		if (ret)
			goto fail;
	}

	/*
	 * We should ideally have less number of encoders (set up by parsing
	 * the MDP5 interfaces) than the number of layer mixers present in HW,
	 * but let's be safe here anyway
	 */
	num_crtcs = min(priv->num_encoders, mdp5_kms->num_hwmixers);

	/*
	 * Construct planes equaling the number of hw pipes, and CRTCs for the
	 * N encoders set up by the driver. The first N planes become primary
	 * planes for the CRTCs, with the remainder as overlay planes:
	 */
	for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
		struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
		struct drm_plane *plane;
		enum drm_plane_type type;

		if (i < num_crtcs)
			type = DRM_PLANE_TYPE_PRIMARY;
		else if (hwpipe->caps & MDP_PIPE_CAP_CURSOR)
			type = DRM_PLANE_TYPE_CURSOR;
		else
			type = DRM_PLANE_TYPE_OVERLAY;

		plane = mdp5_plane_init(dev, type);
		if (IS_ERR(plane)) {
			ret = PTR_ERR(plane);
			dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret);
			goto fail;
		}
		priv->planes[priv->num_planes++] = plane;

		if (type == DRM_PLANE_TYPE_PRIMARY)
			primary[pi++] = plane;
		if (type == DRM_PLANE_TYPE_CURSOR)
			cursor[ci++] = plane;
	}

	for (i = 0; i < num_crtcs; i++) {
		struct drm_crtc *crtc;

		crtc  = mdp5_crtc_init(dev, primary[i], cursor[i], i);
		if (IS_ERR(crtc)) {
			ret = PTR_ERR(crtc);
			dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
			goto fail;
		}
		priv->crtcs[priv->num_crtcs++] = crtc;
	}

	/*
	 * Now that we know the number of crtcs we've created, set the possible
	 * crtcs for the encoders
	 */
	for (i = 0; i < priv->num_encoders; i++) {
		struct drm_encoder *encoder = priv->encoders[i];

		encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
	}

	return 0;

fail:
	return ret;
}
Exemplo n.º 3
0
static int modeset_init(struct mdp5_kms *mdp5_kms)
{
	static const enum mdp5_pipe crtcs[] = {
			SSPP_RGB0, SSPP_RGB1, SSPP_RGB2,
	};
	struct drm_device *dev = mdp5_kms->dev;
	struct msm_drm_private *priv = dev->dev_private;
	struct drm_encoder *encoder;
	int i, ret;

	/* construct CRTCs: */
	for (i = 0; i < ARRAY_SIZE(crtcs); i++) {
		struct drm_plane *plane;
		struct drm_crtc *crtc;

		plane = mdp5_plane_init(dev, crtcs[i], true);
		if (IS_ERR(plane)) {
			ret = PTR_ERR(plane);
			dev_err(dev->dev, "failed to construct plane for %s (%d)\n",
					pipe2name(crtcs[i]), ret);
			goto fail;
		}

		crtc  = mdp5_crtc_init(dev, plane, i);
		if (IS_ERR(crtc)) {
			ret = PTR_ERR(crtc);
			dev_err(dev->dev, "failed to construct crtc for %s (%d)\n",
					pipe2name(crtcs[i]), ret);
			goto fail;
		}
		priv->crtcs[priv->num_crtcs++] = crtc;
	}

	/* Construct encoder for HDMI: */
	encoder = mdp5_encoder_init(dev, 3, INTF_HDMI);
	if (IS_ERR(encoder)) {
		dev_err(dev->dev, "failed to construct encoder\n");
		ret = PTR_ERR(encoder);
		goto fail;
	}

	/* NOTE: the vsync and error irq's are actually associated with
	 * the INTF/encoder.. the easiest way to deal with this (ie. what
	 * we do now) is assume a fixed relationship between crtc's and
	 * encoders.  I'm not sure if there is ever a need to more freely
	 * assign crtcs to encoders, but if there is then we need to take
	 * care of error and vblank irq's that the crtc has registered,
	 * and also update user-requested vblank_mask.
	 */
	encoder->possible_crtcs = BIT(0);
	mdp5_crtc_set_intf(priv->crtcs[0], 3, INTF_HDMI);

	priv->encoders[priv->num_encoders++] = encoder;

	/* Construct bridge/connector for HDMI: */
	mdp5_kms->hdmi = hdmi_init(dev, encoder);
	if (IS_ERR(mdp5_kms->hdmi)) {
		ret = PTR_ERR(mdp5_kms->hdmi);
		dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
		goto fail;
	}

	return 0;

fail:
	return ret;
}