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

Commit f46e699c authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'imx-drm-fixes-2015-12-01' of git://git.pengutronix.de/git/pza/linux into drm-fixes

imx-drm crtc, plane, parallel panel, and TV encoder fixes

- Use drm_crtc_send_vblank_event to fix per crtc vblank handling
- Move the crtc device of_node assignment out of the ipuv3-crtc driver into
  ipu-common code, where the devices are created.
- Fix parallel display support with simple-panels
- Remove some unused fields and superfluous checks
- Switch to universal planes and add error handling for primary plane creation
- Fix module autoload for TV encoder driver

* tag 'imx-drm-fixes-2015-12-01' of git://git.pengutronix.de/git/pza/linux:
  drm: imx: imx-tve: Fix module autoload for OF platform driver
  drm: imx: convert to drm_crtc_send_vblank_event()
  GPU-DRM-IMX: Delete an unnecessary check before drm_fbdev_cma_restore_mode()
  drm/imx: Remove of_node assignment from ipuv3-crtc driver probe
  gpu: ipu-v3: Assign of_node of child platform devices to corresponding ports
  gpu: ipu-v3: Remove reg_offset field
  gpu: ipu-v3: drop unused dmfc field from client platform data
  drm/imx: parallel-display: allow to determine bus format from the connected panel
  drm/imx: ipuv3-crtc: Return error if ipu_plane_init() fails for primary plane
  drm/imx: switch to universal planes
parents 00b83070 5e4789d3
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ static void imx_drm_driver_lastclose(struct drm_device *drm)
#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
	struct imx_drm_device *imxdrm = drm->dev_private;

	if (imxdrm->fbhelper)
	drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
#endif
}
@@ -340,7 +339,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
 * imx_drm_add_crtc - add a new crtc
 */
int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
		struct imx_drm_crtc **new_crtc,
		struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
		const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
		struct device_node *port)
{
@@ -379,7 +378,7 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
	drm_crtc_helper_add(crtc,
			imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);

	drm_crtc_init(drm, crtc,
	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
			imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);

	return 0;
+2 −1
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ struct drm_display_mode;
struct drm_encoder;
struct drm_fbdev_cma;
struct drm_framebuffer;
struct drm_plane;
struct imx_drm_crtc;
struct platform_device;

@@ -24,7 +25,7 @@ struct imx_drm_crtc_helper_funcs {
};

int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
		struct imx_drm_crtc **new_crtc,
		struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
		const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
		struct device_node *port);
int imx_drm_remove_crtc(struct imx_drm_crtc *);
+1 −0
Original line number Diff line number Diff line
@@ -721,6 +721,7 @@ static const struct of_device_id imx_tve_dt_ids[] = {
	{ .compatible = "fsl,imx53-tve", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_tve_dt_ids);

static struct platform_driver imx_tve_driver = {
	.probe		= imx_tve_probe,
+17 −46
Original line number Diff line number Diff line
@@ -212,7 +212,8 @@ static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc)

	spin_lock_irqsave(&drm->event_lock, flags);
	if (ipu_crtc->page_flip_event)
		drm_send_vblank_event(drm, -1, ipu_crtc->page_flip_event);
		drm_crtc_send_vblank_event(&ipu_crtc->base,
					   ipu_crtc->page_flip_event);
	ipu_crtc->page_flip_event = NULL;
	imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc);
	spin_unlock_irqrestore(&drm->event_lock, flags);
@@ -349,7 +350,6 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
	int dp = -EINVAL;
	int ret;
	int id;

	ret = ipu_get_resources(ipu_crtc, pdata);
	if (ret) {
@@ -358,18 +358,23 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
		return ret;
	}

	if (pdata->dp >= 0)
		dp = IPU_DP_FLOW_SYNC_BG;
	ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
					    DRM_PLANE_TYPE_PRIMARY);
	if (IS_ERR(ipu_crtc->plane[0])) {
		ret = PTR_ERR(ipu_crtc->plane[0]);
		goto err_put_resources;
	}

	ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
			&ipu_crtc_helper_funcs, ipu_crtc->dev->of_node);
			&ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs,
			ipu_crtc->dev->of_node);
	if (ret) {
		dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
		goto err_put_resources;
	}

	if (pdata->dp >= 0)
		dp = IPU_DP_FLOW_SYNC_BG;
	id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
	ipu_crtc->plane[0] = ipu_plane_init(ipu_crtc->base.dev, ipu,
					    pdata->dma[0], dp, BIT(id), true);
	ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
	if (ret) {
		dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
@@ -379,10 +384,10 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,

	/* If this crtc is using the DP, add an overlay plane */
	if (pdata->dp >= 0 && pdata->dma[1] > 0) {
		ipu_crtc->plane[1] = ipu_plane_init(ipu_crtc->base.dev, ipu,
						    pdata->dma[1],
		ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1],
						IPU_DP_FLOW_SYNC_FG,
						    BIT(id), false);
						drm_crtc_mask(&ipu_crtc->base),
						DRM_PLANE_TYPE_OVERLAY);
		if (IS_ERR(ipu_crtc->plane[1]))
			ipu_crtc->plane[1] = NULL;
	}
@@ -407,28 +412,6 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
	return ret;
}

static struct device_node *ipu_drm_get_port_by_id(struct device_node *parent,
						  int port_id)
{
	struct device_node *port;
	int id, ret;

	port = of_get_child_by_name(parent, "port");
	while (port) {
		ret = of_property_read_u32(port, "reg", &id);
		if (!ret && id == port_id)
			return port;

		do {
			port = of_get_next_child(parent, port);
			if (!port)
				return NULL;
		} while (of_node_cmp(port->name, "port"));
	}

	return NULL;
}

static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
{
	struct ipu_client_platformdata *pdata = dev->platform_data;
@@ -470,23 +453,11 @@ static const struct component_ops ipu_crtc_ops = {
static int ipu_drm_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct ipu_client_platformdata *pdata = dev->platform_data;
	int ret;

	if (!dev->platform_data)
		return -EINVAL;

	if (!dev->of_node) {
		/* Associate crtc device with the corresponding DI port node */
		dev->of_node = ipu_drm_get_port_by_id(dev->parent->of_node,
						      pdata->di + 2);
		if (!dev->of_node) {
			dev_err(dev, "missing port@%d node in %s\n",
				pdata->di + 2, dev->parent->of_node->full_name);
			return -ENODEV;
		}
	}

	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
	if (ret)
		return ret;
+4 −5
Original line number Diff line number Diff line
@@ -381,7 +381,7 @@ static struct drm_plane_funcs ipu_plane_funcs = {

struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
				 int dma, int dp, unsigned int possible_crtcs,
				 bool priv)
				 enum drm_plane_type type)
{
	struct ipu_plane *ipu_plane;
	int ret;
@@ -399,10 +399,9 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
	ipu_plane->dma = dma;
	ipu_plane->dp_flow = dp;

	ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs,
	ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
				       &ipu_plane_funcs, ipu_plane_formats,
			     ARRAY_SIZE(ipu_plane_formats),
			     priv);
				       ARRAY_SIZE(ipu_plane_formats), type);
	if (ret) {
		DRM_ERROR("failed to initialize plane\n");
		kfree(ipu_plane);
Loading