[PATCH] drm/msm: Refactor msm drm driver to be able to support module

Jilai Wang jilaiw at codeaurora.org
Thu Mar 12 10:01:38 PDT 2015


Each HW component's driver such as HDMI/eDP/DSI should be able to
compiled as a module which allows user to prevent this part of code
to be compiled if not needed.

Signed-off-by: Jilai Wang <jilaiw at codeaurora.org>
---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 13 +++++--
 drivers/gpu/drm/msm/edp/edp.c              | 31 +++++++++++++----
 drivers/gpu/drm/msm/edp/edp.h              |  1 +
 drivers/gpu/drm/msm/hdmi/hdmi.c            | 35 +++++++++++++++----
 drivers/gpu/drm/msm/hdmi/hdmi.h            |  1 +
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c    |  3 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c    | 56 +++++++++++++++---------------
 drivers/gpu/drm/msm/msm_drv.c              |  6 ----
 drivers/gpu/drm/msm/msm_drv.h              | 29 ++++++++--------
 drivers/gpu/drm/msm/msm_gpu.h              |  2 --
 10 files changed, 110 insertions(+), 67 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index be83dee..ff7d743 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -287,12 +287,19 @@ static struct platform_driver adreno_driver = {
 	},
 };
 
-void __init adreno_register(void)
+static int __init adreno_register(void)
 {
-	platform_driver_register(&adreno_driver);
+	return platform_driver_register(&adreno_driver);
 }
 
-void __exit adreno_unregister(void)
+static void __exit adreno_unregister(void)
 {
 	platform_driver_unregister(&adreno_driver);
 }
+
+module_init(adreno_register);
+module_exit(adreno_unregister);
+
+MODULE_AUTHOR("Rob Clark <robdclark at gmail.com");
+MODULE_DESCRIPTION("MSM Adreno Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
index 0940e84..3fc3f28 100644
--- a/drivers/gpu/drm/msm/edp/edp.c
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -14,6 +14,9 @@
 #include <linux/of_irq.h>
 #include "edp.h"
 
+static int msm_edp_modeset_init(struct msm_drm_sub_dev *base,
+	struct drm_device *dev);
+
 static irqreturn_t edp_irq(int irq, void *dev_id)
 {
 	struct msm_edp *edp = dev_id;
@@ -63,6 +66,8 @@ static struct msm_edp *edp_init(struct platform_device *pdev)
 	if (ret)
 		goto fail;
 
+	edp->base.modeset_init = msm_edp_modeset_init;
+
 	return edp;
 
 fail:
@@ -82,7 +87,8 @@ static int edp_bind(struct device *dev, struct device *master, void *data)
 	edp = edp_init(to_platform_device(dev));
 	if (IS_ERR(edp))
 		return PTR_ERR(edp);
-	priv->edp = edp;
+
+	priv->edp = &edp->base;
 
 	return 0;
 }
@@ -131,26 +137,32 @@ static struct platform_driver edp_driver = {
 	},
 };
 
-void __init msm_edp_register(void)
+static int __init msm_edp_register(void)
 {
 	DBG("");
-	platform_driver_register(&edp_driver);
+	return platform_driver_register(&edp_driver);
 }
 
-void __exit msm_edp_unregister(void)
+static void __exit msm_edp_unregister(void)
 {
 	DBG("");
 	platform_driver_unregister(&edp_driver);
 }
 
 /* Second part of initialization, the drm/kms level modeset_init */
-int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
-				struct drm_encoder *encoder)
+static int msm_edp_modeset_init(struct msm_drm_sub_dev *base,
+	struct drm_device *dev)
 {
+	struct msm_edp *edp = container_of(base, struct msm_edp, base);
 	struct platform_device *pdev = edp->pdev;
 	struct msm_drm_private *priv = dev->dev_private;
+	struct drm_encoder *encoder;
 	int ret;
 
+	if (WARN_ON(base->num_encoders != 1))
+		return -EINVAL;
+
+	encoder = base->encoders[0];
 	edp->encoder = encoder;
 	edp->dev = dev;
 
@@ -206,3 +218,10 @@ fail:
 
 	return ret;
 }
+
+module_init(msm_edp_register);
+module_exit(msm_edp_unregister);
+
+MODULE_AUTHOR("Hai Li <hali at codeaurora.org");
+MODULE_DESCRIPTION("MSM eDP Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/msm/edp/edp.h b/drivers/gpu/drm/msm/edp/edp.h
index ba5bedd..00eff68 100644
--- a/drivers/gpu/drm/msm/edp/edp.h
+++ b/drivers/gpu/drm/msm/edp/edp.h
@@ -31,6 +31,7 @@ struct edp_aux;
 struct edp_phy;
 
 struct msm_edp {
+	struct msm_drm_sub_dev base;
 	struct drm_device *dev;
 	struct platform_device *pdev;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 9a8a825..1aa3f7b 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -19,6 +19,9 @@
 #include <linux/of_irq.h>
 #include "hdmi.h"
 
+static int hdmi_modeset_init(struct msm_drm_sub_dev *base,
+		struct drm_device *dev);
+
 void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
 {
 	uint32_t ctrl = 0;
@@ -197,6 +200,8 @@ static struct hdmi *hdmi_init(struct platform_device *pdev)
 		goto fail;
 	}
 
+	hdmi->base.modeset_init = hdmi_modeset_init;
+
 	return hdmi;
 
 fail:
@@ -214,13 +219,19 @@ fail:
  * should be handled in hdmi_init() so that failure happens from
  * hdmi sub-device's probe.
  */
-int hdmi_modeset_init(struct hdmi *hdmi,
-		struct drm_device *dev, struct drm_encoder *encoder)
+static int hdmi_modeset_init(struct msm_drm_sub_dev *base,
+		struct drm_device *dev)
 {
+	struct hdmi *hdmi = container_of(base, struct hdmi, base);
 	struct msm_drm_private *priv = dev->dev_private;
 	struct platform_device *pdev = hdmi->pdev;
+	struct drm_encoder *encoder;
 	int ret;
 
+	if (WARN_ON(base->num_encoders != 1))
+		return -EINVAL;
+
+	encoder = base->encoders[0];
 	hdmi->dev = dev;
 	hdmi->encoder = encoder;
 
@@ -439,7 +450,8 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
 	hdmi = hdmi_init(to_platform_device(dev));
 	if (IS_ERR(hdmi))
 		return PTR_ERR(hdmi);
-	priv->hdmi = hdmi;
+
+	priv->hdmi = &hdmi->base;
 
 	return 0;
 }
@@ -449,8 +461,10 @@ static void hdmi_unbind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct msm_drm_private *priv = drm->dev_private;
+
 	if (priv->hdmi) {
-		hdmi_destroy(priv->hdmi);
+		struct hdmi *hdmi = container_of(priv->hdmi, struct hdmi, base);
+		hdmi_destroy(hdmi);
 		priv->hdmi = NULL;
 	}
 }
@@ -480,12 +494,19 @@ static struct platform_driver hdmi_driver = {
 	},
 };
 
-void __init hdmi_register(void)
+static int __init hdmi_register(void)
 {
-	platform_driver_register(&hdmi_driver);
+	return platform_driver_register(&hdmi_driver);
 }
 
-void __exit hdmi_unregister(void)
+static void __exit hdmi_unregister(void)
 {
 	platform_driver_unregister(&hdmi_driver);
 }
+
+module_init(hdmi_register);
+module_exit(hdmi_unregister);
+
+MODULE_AUTHOR("Rob Clark <robdclark at gmail.com");
+MODULE_DESCRIPTION("MSM HDMI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 68fdfb3..a1d4595 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -38,6 +38,7 @@ struct hdmi_audio {
 };
 
 struct hdmi {
+	struct msm_drm_sub_dev base;
 	struct drm_device *dev;
 	struct platform_device *pdev;
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index 24c38d4..02426ba 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -370,7 +370,8 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
 
 	if (priv->hdmi) {
 		/* Construct bridge/connector for HDMI: */
-		ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
+		priv->hdmi->encoders[priv->hdmi->num_encoders++] = encoder;
+		ret = priv->hdmi->modeset_init(priv->hdmi, dev);
 		if (ret) {
 			dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
 			goto fail;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 84168bf..ae336ec 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark at gmail.com>
  *
@@ -166,8 +166,9 @@ int mdp5_enable(struct mdp5_kms *mdp5_kms)
 	return 0;
 }
 
-static int construct_encoder(struct mdp5_kms *mdp5_kms,
-		enum mdp5_intf_type intf_type, int intf_num)
+static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms,
+		enum mdp5_intf_type intf_type, int intf_num,
+		enum mdp5_intf_mode intf_mode)
 {
 	struct drm_device *dev = mdp5_kms->dev;
 	struct msm_drm_private *priv = dev->dev_private;
@@ -175,33 +176,19 @@ static int construct_encoder(struct mdp5_kms *mdp5_kms,
 	struct mdp5_interface intf = {
 			.num	= intf_num,
 			.type	= intf_type,
-			.mode	= MDP5_INTF_MODE_NONE,
+			.mode	= intf_mode,
 	};
-	int ret = 0;
 
 	encoder = mdp5_encoder_init(dev, &intf);
 	if (IS_ERR(encoder)) {
-		ret = PTR_ERR(encoder);
-		dev_err(dev->dev, "failed to construct encoder: %d\n", ret);
-		return ret;
+		dev_err(dev->dev, "failed to construct encoder\n");
+		return encoder;
 	}
 
 	encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
 	priv->encoders[priv->num_encoders++] = encoder;
 
-	if (intf_type == INTF_HDMI) {
-		ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
-		if (ret)
-			dev_err(dev->dev, "failed to init HDMI: %d\n", ret);
-
-	} else if (intf_type == INTF_eDP) {
-		/* Construct bridge/connector for eDP: */
-		ret = msm_edp_modeset_init(priv->edp, dev, encoder);
-		if (ret)
-			dev_err(dev->dev, "failed to init eDP: %d\n", ret);
-	}
-
-	return ret;
+	return encoder;
 }
 
 static int modeset_init(struct mdp5_kms *mdp5_kms)
@@ -267,26 +254,39 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 	/* Construct external display interfaces' encoders: */
 	for (i = 0; i < ARRAY_SIZE(hw_cfg->intfs); i++) {
 		enum mdp5_intf_type intf_type = hw_cfg->intfs[i];
+		enum mdp5_intf_mode intf_mode = MDP5_INTF_MODE_NONE;
+		struct msm_drm_sub_dev *sub_dev;
+		struct drm_encoder *encoder;
 
 		switch (intf_type) {
 		case INTF_DISABLED:
+			sub_dev = NULL;
 			break;
 		case INTF_eDP:
-			if (priv->edp)
-				ret = construct_encoder(mdp5_kms, INTF_eDP, i);
+			sub_dev = priv->edp;
 			break;
 		case INTF_HDMI:
-			if (priv->hdmi)
-				ret = construct_encoder(mdp5_kms, INTF_HDMI, i);
+			sub_dev = priv->hdmi;
 			break;
 		default:
 			dev_err(dev->dev, "unknown intf: %d\n", intf_type);
 			ret = -EINVAL;
-			break;
+			goto fail;
 		}
 
-		if (ret)
-			goto fail;
+		if (sub_dev) {
+			encoder = construct_encoder(mdp5_kms, intf_type,
+							i, intf_mode);
+			if (IS_ERR(encoder)) {
+				ret = PTR_ERR(encoder);
+				goto fail;
+			}
+
+			sub_dev->encoders[sub_dev->num_encoders++] = encoder;
+			ret = sub_dev->modeset_init(sub_dev, dev);
+			if (ret)
+				goto fail;
+		}
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index a72ed0a..7b21bed 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1032,9 +1032,6 @@ static struct platform_driver msm_platform_driver = {
 static int __init msm_drm_register(void)
 {
 	DBG("init");
-	msm_edp_register();
-	hdmi_register();
-	adreno_register();
 	return platform_driver_register(&msm_platform_driver);
 }
 
@@ -1042,9 +1039,6 @@ static void __exit msm_drm_unregister(void)
 {
 	DBG("fini");
 	platform_driver_unregister(&msm_platform_driver);
-	hdmi_unregister();
-	adreno_unregister();
-	msm_edp_unregister();
 }
 
 module_init(msm_drm_register);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 9e8d441..690d891 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -64,6 +64,19 @@ struct msm_file_private {
 	int dummy;
 };
 
+/* A base data structure for all MDP sub devices */
+struct msm_drm_sub_dev {
+	/*
+	 * the encoders can be used by sub dev,
+	 * must be set before modeset_init
+	 */
+	unsigned int num_encoders;
+	struct drm_encoder *encoders[8];
+
+	int (*modeset_init)(struct msm_drm_sub_dev *base,
+		struct drm_device *dev);
+};
+
 struct msm_drm_private {
 
 	struct msm_kms *kms;
@@ -74,13 +87,13 @@ struct msm_drm_private {
 	/* possibly this should be in the kms component, but it is
 	 * shared by both mdp4 and mdp5..
 	 */
-	struct hdmi *hdmi;
+	struct msm_drm_sub_dev *hdmi;
 
 	/* eDP is for mdp5 only, but kms has not been created
 	 * when edp_bind() and edp_init() are called. Here is the only
 	 * place to keep the edp instance.
 	 */
-	struct msm_edp *edp;
+	struct msm_drm_sub_dev *edp;
 
 	/* when we have more than one 'msm_gpu' these need to be an array: */
 	struct msm_gpu *gpu;
@@ -224,18 +237,6 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
 
 struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev);
 
-struct hdmi;
-int hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev,
-		struct drm_encoder *encoder);
-void __init hdmi_register(void);
-void __exit hdmi_unregister(void);
-
-struct msm_edp;
-void __init msm_edp_register(void);
-void __exit msm_edp_unregister(void);
-int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
-		struct drm_encoder *encoder);
-
 #ifdef CONFIG_DEBUG_FS
 void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m);
 void msm_gem_describe_objects(struct list_head *list, struct seq_file *m);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index fd1e4b4..ab853bf 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -167,7 +167,5 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 void msm_gpu_cleanup(struct msm_gpu *gpu);
 
 struct msm_gpu *adreno_load_gpu(struct drm_device *dev);
-void __init adreno_register(void);
-void __exit adreno_unregister(void);
 
 #endif /* __MSM_GPU_H__ */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



More information about the dri-devel mailing list