linux/drivers/gpu/drm/msm/edp/edp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/of_irq.h>
   7#include "edp.h"
   8
   9static irqreturn_t edp_irq(int irq, void *dev_id)
  10{
  11        struct msm_edp *edp = dev_id;
  12
  13        /* Process eDP irq */
  14        return msm_edp_ctrl_irq(edp->ctrl);
  15}
  16
  17static void edp_destroy(struct platform_device *pdev)
  18{
  19        struct msm_edp *edp = platform_get_drvdata(pdev);
  20
  21        if (!edp)
  22                return;
  23
  24        if (edp->ctrl) {
  25                msm_edp_ctrl_destroy(edp->ctrl);
  26                edp->ctrl = NULL;
  27        }
  28
  29        platform_set_drvdata(pdev, NULL);
  30}
  31
  32/* construct eDP at bind/probe time, grab all the resources. */
  33static struct msm_edp *edp_init(struct platform_device *pdev)
  34{
  35        struct msm_edp *edp = NULL;
  36        int ret;
  37
  38        if (!pdev) {
  39                pr_err("no eDP device\n");
  40                ret = -ENXIO;
  41                goto fail;
  42        }
  43
  44        edp = devm_kzalloc(&pdev->dev, sizeof(*edp), GFP_KERNEL);
  45        if (!edp) {
  46                ret = -ENOMEM;
  47                goto fail;
  48        }
  49        DBG("eDP probed=%p", edp);
  50
  51        edp->pdev = pdev;
  52        platform_set_drvdata(pdev, edp);
  53
  54        ret = msm_edp_ctrl_init(edp);
  55        if (ret)
  56                goto fail;
  57
  58        return edp;
  59
  60fail:
  61        if (edp)
  62                edp_destroy(pdev);
  63
  64        return ERR_PTR(ret);
  65}
  66
  67static int edp_bind(struct device *dev, struct device *master, void *data)
  68{
  69        struct drm_device *drm = dev_get_drvdata(master);
  70        struct msm_drm_private *priv = drm->dev_private;
  71        struct msm_edp *edp;
  72
  73        DBG("");
  74        edp = edp_init(to_platform_device(dev));
  75        if (IS_ERR(edp))
  76                return PTR_ERR(edp);
  77        priv->edp = edp;
  78
  79        return 0;
  80}
  81
  82static void edp_unbind(struct device *dev, struct device *master, void *data)
  83{
  84        struct drm_device *drm = dev_get_drvdata(master);
  85        struct msm_drm_private *priv = drm->dev_private;
  86
  87        DBG("");
  88        if (priv->edp) {
  89                edp_destroy(to_platform_device(dev));
  90                priv->edp = NULL;
  91        }
  92}
  93
  94static const struct component_ops edp_ops = {
  95                .bind   = edp_bind,
  96                .unbind = edp_unbind,
  97};
  98
  99static int edp_dev_probe(struct platform_device *pdev)
 100{
 101        DBG("");
 102        return component_add(&pdev->dev, &edp_ops);
 103}
 104
 105static int edp_dev_remove(struct platform_device *pdev)
 106{
 107        DBG("");
 108        component_del(&pdev->dev, &edp_ops);
 109        return 0;
 110}
 111
 112static const struct of_device_id dt_match[] = {
 113        { .compatible = "qcom,mdss-edp" },
 114        {}
 115};
 116
 117static struct platform_driver edp_driver = {
 118        .probe = edp_dev_probe,
 119        .remove = edp_dev_remove,
 120        .driver = {
 121                .name = "msm_edp",
 122                .of_match_table = dt_match,
 123        },
 124};
 125
 126void __init msm_edp_register(void)
 127{
 128        DBG("");
 129        platform_driver_register(&edp_driver);
 130}
 131
 132void __exit msm_edp_unregister(void)
 133{
 134        DBG("");
 135        platform_driver_unregister(&edp_driver);
 136}
 137
 138/* Second part of initialization, the drm/kms level modeset_init */
 139int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
 140                                struct drm_encoder *encoder)
 141{
 142        struct platform_device *pdev = edp->pdev;
 143        struct msm_drm_private *priv = dev->dev_private;
 144        int ret;
 145
 146        edp->encoder = encoder;
 147        edp->dev = dev;
 148
 149        edp->bridge = msm_edp_bridge_init(edp);
 150        if (IS_ERR(edp->bridge)) {
 151                ret = PTR_ERR(edp->bridge);
 152                DRM_DEV_ERROR(dev->dev, "failed to create eDP bridge: %d\n", ret);
 153                edp->bridge = NULL;
 154                goto fail;
 155        }
 156
 157        edp->connector = msm_edp_connector_init(edp);
 158        if (IS_ERR(edp->connector)) {
 159                ret = PTR_ERR(edp->connector);
 160                DRM_DEV_ERROR(dev->dev, "failed to create eDP connector: %d\n", ret);
 161                edp->connector = NULL;
 162                goto fail;
 163        }
 164
 165        edp->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
 166        if (edp->irq < 0) {
 167                ret = edp->irq;
 168                DRM_DEV_ERROR(dev->dev, "failed to get IRQ: %d\n", ret);
 169                goto fail;
 170        }
 171
 172        ret = devm_request_irq(&pdev->dev, edp->irq,
 173                        edp_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 174                        "edp_isr", edp);
 175        if (ret < 0) {
 176                DRM_DEV_ERROR(dev->dev, "failed to request IRQ%u: %d\n",
 177                                edp->irq, ret);
 178                goto fail;
 179        }
 180
 181        priv->bridges[priv->num_bridges++]       = edp->bridge;
 182        priv->connectors[priv->num_connectors++] = edp->connector;
 183
 184        return 0;
 185
 186fail:
 187        /* bridge/connector are normally destroyed by drm */
 188        if (edp->bridge) {
 189                edp_bridge_destroy(edp->bridge);
 190                edp->bridge = NULL;
 191        }
 192        if (edp->connector) {
 193                edp->connector->funcs->destroy(edp->connector);
 194                edp->connector = NULL;
 195        }
 196
 197        return ret;
 198}
 199