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:
Jonathan Marek 2018-12-04 10:16:58 -05:00 committed by Rob Clark
parent fb42b5354d
commit e6f6d63ed1
4 changed files with 46 additions and 16 deletions

View File

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

View 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" },
{} {}

View File

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

View File

@ -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;
ret = add_display_components(&pdev->dev, &match); if (get_mdp_ver(pdev)) {
if (ret) ret = add_display_components(&pdev->dev, &match);
return ret; if (ret)
return ret;
}
ret = add_gpu_components(&pdev->dev, &match); ret = add_gpu_components(&pdev->dev, &match);
if (ret) if (ret)