forked from mirrors/linux
		
	drm/msm: add headless gpu device for imx5
This patch allows using drm/msm without qcom display hardware. It adds a amd,imageon compatible, which is used instead of qcom,adreno, but does not require a top level msm node. Signed-off-by: Jonathan Marek <jonathan@marek.ca> Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
		
							parent
							
								
									fb42b5354d
								
							
						
					
					
						commit
						e6f6d63ed1
					
				
					 4 changed files with 46 additions and 16 deletions
				
			
		| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
config DRM_MSM
 | 
					config DRM_MSM
 | 
				
			||||||
	tristate "MSM DRM"
 | 
						tristate "MSM DRM"
 | 
				
			||||||
	depends on DRM
 | 
						depends on DRM
 | 
				
			||||||
	depends on ARCH_QCOM || (ARM && COMPILE_TEST)
 | 
						depends on ARCH_QCOM || SOC_IMX5 || (ARM && COMPILE_TEST)
 | 
				
			||||||
	depends on OF && COMMON_CLK
 | 
						depends on OF && COMMON_CLK
 | 
				
			||||||
	depends on MMU
 | 
						depends on MMU
 | 
				
			||||||
	select QCOM_MDT_LOADER if ARCH_QCOM
 | 
						select QCOM_MDT_LOADER if ARCH_QCOM
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ config DRM_MSM
 | 
				
			||||||
	select DRM_PANEL
 | 
						select DRM_PANEL
 | 
				
			||||||
	select SHMEM
 | 
						select SHMEM
 | 
				
			||||||
	select TMPFS
 | 
						select TMPFS
 | 
				
			||||||
	select QCOM_SCM
 | 
						select QCOM_SCM if ARCH_QCOM
 | 
				
			||||||
	select WANT_DEV_COREDUMP
 | 
						select WANT_DEV_COREDUMP
 | 
				
			||||||
	select SND_SOC_HDMI_CODEC if SND_SOC
 | 
						select SND_SOC_HDMI_CODEC if SND_SOC
 | 
				
			||||||
	select SYNC_FILE
 | 
						select SYNC_FILE
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -271,7 +271,8 @@ static int find_chipid(struct device *dev, struct adreno_rev *rev)
 | 
				
			||||||
	if (ret == 0) {
 | 
						if (ret == 0) {
 | 
				
			||||||
		unsigned int r, patch;
 | 
							unsigned int r, patch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sscanf(compat, "qcom,adreno-%u.%u", &r, &patch) == 2) {
 | 
							if (sscanf(compat, "qcom,adreno-%u.%u", &r, &patch) == 2 ||
 | 
				
			||||||
 | 
							    sscanf(compat, "amd,imageon-%u.%u", &r, &patch) == 2) {
 | 
				
			||||||
			rev->core = r / 100;
 | 
								rev->core = r / 100;
 | 
				
			||||||
			r %= 100;
 | 
								r %= 100;
 | 
				
			||||||
			rev->major = r / 10;
 | 
								rev->major = r / 10;
 | 
				
			||||||
| 
						 | 
					@ -359,9 +360,37 @@ static const struct component_ops a3xx_ops = {
 | 
				
			||||||
		.unbind = adreno_unbind,
 | 
							.unbind = adreno_unbind,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void adreno_device_register_headless(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* on imx5, we don't have a top-level mdp/dpu node
 | 
				
			||||||
 | 
						 * this creates a dummy node for the driver for that case
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						struct platform_device_info dummy_info = {
 | 
				
			||||||
 | 
							.parent = NULL,
 | 
				
			||||||
 | 
							.name = "msm",
 | 
				
			||||||
 | 
							.id = -1,
 | 
				
			||||||
 | 
							.res = NULL,
 | 
				
			||||||
 | 
							.num_res = 0,
 | 
				
			||||||
 | 
							.data = NULL,
 | 
				
			||||||
 | 
							.size_data = 0,
 | 
				
			||||||
 | 
							.dma_mask = ~0,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						platform_device_register_full(&dummy_info);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int adreno_probe(struct platform_device *pdev)
 | 
					static int adreno_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return component_add(&pdev->dev, &a3xx_ops);
 | 
					
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = component_add(&pdev->dev, &a3xx_ops);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon"))
 | 
				
			||||||
 | 
							adreno_device_register_headless();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int adreno_remove(struct platform_device *pdev)
 | 
					static int adreno_remove(struct platform_device *pdev)
 | 
				
			||||||
| 
						 | 
					@ -373,6 +402,8 @@ static int adreno_remove(struct platform_device *pdev)
 | 
				
			||||||
static const struct of_device_id dt_match[] = {
 | 
					static const struct of_device_id dt_match[] = {
 | 
				
			||||||
	{ .compatible = "qcom,adreno" },
 | 
						{ .compatible = "qcom,adreno" },
 | 
				
			||||||
	{ .compatible = "qcom,adreno-3xx" },
 | 
						{ .compatible = "qcom,adreno-3xx" },
 | 
				
			||||||
 | 
						/* for compatibility with imx5 gpu: */
 | 
				
			||||||
 | 
						{ .compatible = "amd,imageon" },
 | 
				
			||||||
	/* for backwards compat w/ downstream kgsl DT files: */
 | 
						/* for backwards compat w/ downstream kgsl DT files: */
 | 
				
			||||||
	{ .compatible = "qcom,kgsl-3d0" },
 | 
						{ .compatible = "qcom,kgsl-3d0" },
 | 
				
			||||||
	{}
 | 
						{}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -235,7 +235,7 @@ int msm_debugfs_init(struct drm_minor *minor)
 | 
				
			||||||
	debugfs_create_file("gpu", S_IRUSR, minor->debugfs_root,
 | 
						debugfs_create_file("gpu", S_IRUSR, minor->debugfs_root,
 | 
				
			||||||
		dev, &msm_gpu_fops);
 | 
							dev, &msm_gpu_fops);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (priv->kms->funcs->debugfs_init) {
 | 
						if (priv->kms && priv->kms->funcs->debugfs_init) {
 | 
				
			||||||
		ret = priv->kms->funcs->debugfs_init(priv->kms, minor);
 | 
							ret = priv->kms->funcs->debugfs_init(priv->kms, minor);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -520,17 +520,13 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
 | 
				
			||||||
		priv->kms = kms;
 | 
							priv->kms = kms;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		kms = ERR_PTR(-ENODEV);
 | 
							/* valid only for the dummy headless case, where of_node=NULL */
 | 
				
			||||||
 | 
							WARN_ON(dev->of_node);
 | 
				
			||||||
 | 
							kms = NULL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (IS_ERR(kms)) {
 | 
						if (IS_ERR(kms)) {
 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * NOTE: once we have GPU support, having no kms should not
 | 
					 | 
				
			||||||
		 * be considered fatal.. ideally we would still support gpu
 | 
					 | 
				
			||||||
		 * and (for example) use dmabuf/prime to share buffers with
 | 
					 | 
				
			||||||
		 * imx drm driver on iMX5
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		DRM_DEV_ERROR(dev, "failed to load kms\n");
 | 
							DRM_DEV_ERROR(dev, "failed to load kms\n");
 | 
				
			||||||
		ret = PTR_ERR(kms);
 | 
							ret = PTR_ERR(kms);
 | 
				
			||||||
		priv->kms = NULL;
 | 
							priv->kms = NULL;
 | 
				
			||||||
| 
						 | 
					@ -648,7 +644,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
 | 
				
			||||||
	drm_mode_config_reset(ddev);
 | 
						drm_mode_config_reset(ddev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
 | 
					#ifdef CONFIG_DRM_FBDEV_EMULATION
 | 
				
			||||||
	if (fbdev)
 | 
						if (kms && fbdev)
 | 
				
			||||||
		priv->fbdev = msm_fbdev_init(ddev);
 | 
							priv->fbdev = msm_fbdev_init(ddev);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1332,6 +1328,7 @@ static int add_display_components(struct device *dev,
 | 
				
			||||||
static const struct of_device_id msm_gpu_match[] = {
 | 
					static const struct of_device_id msm_gpu_match[] = {
 | 
				
			||||||
	{ .compatible = "qcom,adreno" },
 | 
						{ .compatible = "qcom,adreno" },
 | 
				
			||||||
	{ .compatible = "qcom,adreno-3xx" },
 | 
						{ .compatible = "qcom,adreno-3xx" },
 | 
				
			||||||
 | 
						{ .compatible = "amd,imageon" },
 | 
				
			||||||
	{ .compatible = "qcom,kgsl-3d0" },
 | 
						{ .compatible = "qcom,kgsl-3d0" },
 | 
				
			||||||
	{ },
 | 
						{ },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -1376,9 +1373,11 @@ static int msm_pdev_probe(struct platform_device *pdev)
 | 
				
			||||||
	struct component_match *match = NULL;
 | 
						struct component_match *match = NULL;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (get_mdp_ver(pdev)) {
 | 
				
			||||||
		ret = add_display_components(&pdev->dev, &match);
 | 
							ret = add_display_components(&pdev->dev, &match);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = add_gpu_components(&pdev->dev, &match);
 | 
						ret = add_gpu_components(&pdev->dev, &match);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue