root/drivers/gpu/drm/msm/hdmi/hdmi_phy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. msm_hdmi_phy_resource_init
  2. msm_hdmi_phy_resource_enable
  3. msm_hdmi_phy_resource_disable
  4. msm_hdmi_phy_powerup
  5. msm_hdmi_phy_powerdown
  6. msm_hdmi_phy_pll_init
  7. msm_hdmi_phy_probe
  8. msm_hdmi_phy_remove
  9. msm_hdmi_phy_driver_register
  10. msm_hdmi_phy_driver_unregister

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
   4  */
   5 
   6 #include <linux/of_device.h>
   7 
   8 #include "hdmi.h"
   9 
  10 static int msm_hdmi_phy_resource_init(struct hdmi_phy *phy)
  11 {
  12         struct hdmi_phy_cfg *cfg = phy->cfg;
  13         struct device *dev = &phy->pdev->dev;
  14         int i, ret;
  15 
  16         phy->regs = devm_kcalloc(dev, cfg->num_regs, sizeof(phy->regs[0]),
  17                                  GFP_KERNEL);
  18         if (!phy->regs)
  19                 return -ENOMEM;
  20 
  21         phy->clks = devm_kcalloc(dev, cfg->num_clks, sizeof(phy->clks[0]),
  22                                  GFP_KERNEL);
  23         if (!phy->clks)
  24                 return -ENOMEM;
  25 
  26         for (i = 0; i < cfg->num_regs; i++) {
  27                 struct regulator *reg;
  28 
  29                 reg = devm_regulator_get(dev, cfg->reg_names[i]);
  30                 if (IS_ERR(reg)) {
  31                         ret = PTR_ERR(reg);
  32                         DRM_DEV_ERROR(dev, "failed to get phy regulator: %s (%d)\n",
  33                                 cfg->reg_names[i], ret);
  34                         return ret;
  35                 }
  36 
  37                 phy->regs[i] = reg;
  38         }
  39 
  40         for (i = 0; i < cfg->num_clks; i++) {
  41                 struct clk *clk;
  42 
  43                 clk = msm_clk_get(phy->pdev, cfg->clk_names[i]);
  44                 if (IS_ERR(clk)) {
  45                         ret = PTR_ERR(clk);
  46                         DRM_DEV_ERROR(dev, "failed to get phy clock: %s (%d)\n",
  47                                 cfg->clk_names[i], ret);
  48                         return ret;
  49                 }
  50 
  51                 phy->clks[i] = clk;
  52         }
  53 
  54         return 0;
  55 }
  56 
  57 int msm_hdmi_phy_resource_enable(struct hdmi_phy *phy)
  58 {
  59         struct hdmi_phy_cfg *cfg = phy->cfg;
  60         struct device *dev = &phy->pdev->dev;
  61         int i, ret = 0;
  62 
  63         pm_runtime_get_sync(dev);
  64 
  65         for (i = 0; i < cfg->num_regs; i++) {
  66                 ret = regulator_enable(phy->regs[i]);
  67                 if (ret)
  68                         DRM_DEV_ERROR(dev, "failed to enable regulator: %s (%d)\n",
  69                                 cfg->reg_names[i], ret);
  70         }
  71 
  72         for (i = 0; i < cfg->num_clks; i++) {
  73                 ret = clk_prepare_enable(phy->clks[i]);
  74                 if (ret)
  75                         DRM_DEV_ERROR(dev, "failed to enable clock: %s (%d)\n",
  76                                 cfg->clk_names[i], ret);
  77         }
  78 
  79         return ret;
  80 }
  81 
  82 void msm_hdmi_phy_resource_disable(struct hdmi_phy *phy)
  83 {
  84         struct hdmi_phy_cfg *cfg = phy->cfg;
  85         struct device *dev = &phy->pdev->dev;
  86         int i;
  87 
  88         for (i = cfg->num_clks - 1; i >= 0; i--)
  89                 clk_disable_unprepare(phy->clks[i]);
  90 
  91         for (i = cfg->num_regs - 1; i >= 0; i--)
  92                 regulator_disable(phy->regs[i]);
  93 
  94         pm_runtime_put_sync(dev);
  95 }
  96 
  97 void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long int pixclock)
  98 {
  99         if (!phy || !phy->cfg->powerup)
 100                 return;
 101 
 102         phy->cfg->powerup(phy, pixclock);
 103 }
 104 
 105 void msm_hdmi_phy_powerdown(struct hdmi_phy *phy)
 106 {
 107         if (!phy || !phy->cfg->powerdown)
 108                 return;
 109 
 110         phy->cfg->powerdown(phy);
 111 }
 112 
 113 static int msm_hdmi_phy_pll_init(struct platform_device *pdev,
 114                              enum hdmi_phy_type type)
 115 {
 116         int ret;
 117 
 118         switch (type) {
 119         case MSM_HDMI_PHY_8960:
 120                 ret = msm_hdmi_pll_8960_init(pdev);
 121                 break;
 122         case MSM_HDMI_PHY_8996:
 123                 ret = msm_hdmi_pll_8996_init(pdev);
 124                 break;
 125         /*
 126          * we don't have PLL support for these, don't report an error for now
 127          */
 128         case MSM_HDMI_PHY_8x60:
 129         case MSM_HDMI_PHY_8x74:
 130         default:
 131                 ret = 0;
 132                 break;
 133         }
 134 
 135         return ret;
 136 }
 137 
 138 static int msm_hdmi_phy_probe(struct platform_device *pdev)
 139 {
 140         struct device *dev = &pdev->dev;
 141         struct hdmi_phy *phy;
 142         int ret;
 143 
 144         phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
 145         if (!phy)
 146                 return -ENODEV;
 147 
 148         phy->cfg = (struct hdmi_phy_cfg *)of_device_get_match_data(dev);
 149         if (!phy->cfg)
 150                 return -ENODEV;
 151 
 152         phy->mmio = msm_ioremap(pdev, "hdmi_phy", "HDMI_PHY");
 153         if (IS_ERR(phy->mmio)) {
 154                 DRM_DEV_ERROR(dev, "%s: failed to map phy base\n", __func__);
 155                 return -ENOMEM;
 156         }
 157 
 158         phy->pdev = pdev;
 159 
 160         ret = msm_hdmi_phy_resource_init(phy);
 161         if (ret)
 162                 return ret;
 163 
 164         pm_runtime_enable(&pdev->dev);
 165 
 166         ret = msm_hdmi_phy_resource_enable(phy);
 167         if (ret)
 168                 return ret;
 169 
 170         ret = msm_hdmi_phy_pll_init(pdev, phy->cfg->type);
 171         if (ret) {
 172                 DRM_DEV_ERROR(dev, "couldn't init PLL\n");
 173                 msm_hdmi_phy_resource_disable(phy);
 174                 return ret;
 175         }
 176 
 177         msm_hdmi_phy_resource_disable(phy);
 178 
 179         platform_set_drvdata(pdev, phy);
 180 
 181         return 0;
 182 }
 183 
 184 static int msm_hdmi_phy_remove(struct platform_device *pdev)
 185 {
 186         pm_runtime_disable(&pdev->dev);
 187 
 188         return 0;
 189 }
 190 
 191 static const struct of_device_id msm_hdmi_phy_dt_match[] = {
 192         { .compatible = "qcom,hdmi-phy-8660",
 193           .data = &msm_hdmi_phy_8x60_cfg },
 194         { .compatible = "qcom,hdmi-phy-8960",
 195           .data = &msm_hdmi_phy_8960_cfg },
 196         { .compatible = "qcom,hdmi-phy-8974",
 197           .data = &msm_hdmi_phy_8x74_cfg },
 198         { .compatible = "qcom,hdmi-phy-8084",
 199           .data = &msm_hdmi_phy_8x74_cfg },
 200         { .compatible = "qcom,hdmi-phy-8996",
 201           .data = &msm_hdmi_phy_8996_cfg },
 202         {}
 203 };
 204 
 205 static struct platform_driver msm_hdmi_phy_platform_driver = {
 206         .probe      = msm_hdmi_phy_probe,
 207         .remove     = msm_hdmi_phy_remove,
 208         .driver     = {
 209                 .name   = "msm_hdmi_phy",
 210                 .of_match_table = msm_hdmi_phy_dt_match,
 211         },
 212 };
 213 
 214 void __init msm_hdmi_phy_driver_register(void)
 215 {
 216         platform_driver_register(&msm_hdmi_phy_platform_driver);
 217 }
 218 
 219 void __exit msm_hdmi_phy_driver_unregister(void)
 220 {
 221         platform_driver_unregister(&msm_hdmi_phy_platform_driver);
 222 }

/* [<][>][^][v][top][bottom][index][help] */