linux/drivers/gpu/drm/msm/dp/dp_parser.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/of_gpio.h>
   7#include <linux/phy/phy.h>
   8
   9#include <drm/drm_print.h>
  10
  11#include "dp_parser.h"
  12#include "dp_reg.h"
  13
  14static const struct dp_regulator_cfg sdm845_dp_reg_cfg = {
  15        .num = 2,
  16        .regs = {
  17                {"vdda-1p2", 21800, 4 },        /* 1.2 V */
  18                {"vdda-0p9", 36000, 32 },       /* 0.9 V */
  19        },
  20};
  21
  22static int msm_dss_ioremap(struct platform_device *pdev,
  23                                struct dss_io_data *io_data)
  24{
  25        struct resource *res = NULL;
  26
  27        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  28        if (!res) {
  29                DRM_ERROR("%pS->%s: msm_dss_get_res failed\n",
  30                        __builtin_return_address(0), __func__);
  31                return -ENODEV;
  32        }
  33
  34        io_data->len = (u32)resource_size(res);
  35        io_data->base = ioremap(res->start, io_data->len);
  36        if (!io_data->base) {
  37                DRM_ERROR("%pS->%s: ioremap failed\n",
  38                        __builtin_return_address(0), __func__);
  39                return -EIO;
  40        }
  41
  42        return 0;
  43}
  44
  45static void msm_dss_iounmap(struct dss_io_data *io_data)
  46{
  47        if (io_data->base) {
  48                iounmap(io_data->base);
  49                io_data->base = NULL;
  50        }
  51        io_data->len = 0;
  52}
  53
  54static void dp_parser_unmap_io_resources(struct dp_parser *parser)
  55{
  56        struct dp_io *io = &parser->io;
  57
  58        msm_dss_iounmap(&io->dp_controller);
  59}
  60
  61static int dp_parser_ctrl_res(struct dp_parser *parser)
  62{
  63        int rc = 0;
  64        struct platform_device *pdev = parser->pdev;
  65        struct dp_io *io = &parser->io;
  66
  67        rc = msm_dss_ioremap(pdev, &io->dp_controller);
  68        if (rc) {
  69                DRM_ERROR("unable to remap dp io resources, rc=%d\n", rc);
  70                goto err;
  71        }
  72
  73        io->phy = devm_phy_get(&pdev->dev, "dp");
  74        if (IS_ERR(io->phy)) {
  75                rc = PTR_ERR(io->phy);
  76                goto err;
  77        }
  78
  79        return 0;
  80err:
  81        dp_parser_unmap_io_resources(parser);
  82        return rc;
  83}
  84
  85static int dp_parser_misc(struct dp_parser *parser)
  86{
  87        struct device_node *of_node = parser->pdev->dev.of_node;
  88        int len = 0;
  89        const char *data_lane_property = "data-lanes";
  90
  91        len = of_property_count_elems_of_size(of_node,
  92                         data_lane_property, sizeof(u32));
  93        if (len < 0) {
  94                DRM_WARN("Invalid property %s, default max DP lanes = %d\n",
  95                                data_lane_property, DP_MAX_NUM_DP_LANES);
  96                len = DP_MAX_NUM_DP_LANES;
  97        }
  98
  99        parser->max_dp_lanes = len;
 100        return 0;
 101}
 102
 103static inline bool dp_parser_check_prefix(const char *clk_prefix,
 104                                                const char *clk_name)
 105{
 106        return !strncmp(clk_prefix, clk_name, strlen(clk_prefix));
 107}
 108
 109static int dp_parser_init_clk_data(struct dp_parser *parser)
 110{
 111        int num_clk, i, rc;
 112        int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
 113        const char *clk_name;
 114        struct device *dev = &parser->pdev->dev;
 115        struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
 116        struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
 117        struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
 118
 119        num_clk = of_property_count_strings(dev->of_node, "clock-names");
 120        if (num_clk <= 0) {
 121                DRM_ERROR("no clocks are defined\n");
 122                return -EINVAL;
 123        }
 124
 125        for (i = 0; i < num_clk; i++) {
 126                rc = of_property_read_string_index(dev->of_node,
 127                                "clock-names", i, &clk_name);
 128                if (rc < 0)
 129                        return rc;
 130
 131                if (dp_parser_check_prefix("core", clk_name))
 132                        core_clk_count++;
 133
 134                if (dp_parser_check_prefix("ctrl", clk_name))
 135                        ctrl_clk_count++;
 136
 137                if (dp_parser_check_prefix("stream", clk_name))
 138                        stream_clk_count++;
 139        }
 140
 141        /* Initialize the CORE power module */
 142        if (core_clk_count == 0) {
 143                DRM_ERROR("no core clocks are defined\n");
 144                return -EINVAL;
 145        }
 146
 147        core_power->num_clk = core_clk_count;
 148        core_power->clk_config = devm_kzalloc(dev,
 149                        sizeof(struct dss_clk) * core_power->num_clk,
 150                        GFP_KERNEL);
 151        if (!core_power->clk_config)
 152                return -EINVAL;
 153
 154        /* Initialize the CTRL power module */
 155        if (ctrl_clk_count == 0) {
 156                DRM_ERROR("no ctrl clocks are defined\n");
 157                return -EINVAL;
 158        }
 159
 160        ctrl_power->num_clk = ctrl_clk_count;
 161        ctrl_power->clk_config = devm_kzalloc(dev,
 162                        sizeof(struct dss_clk) * ctrl_power->num_clk,
 163                        GFP_KERNEL);
 164        if (!ctrl_power->clk_config) {
 165                ctrl_power->num_clk = 0;
 166                return -EINVAL;
 167        }
 168
 169        /* Initialize the STREAM power module */
 170        if (stream_clk_count == 0) {
 171                DRM_ERROR("no stream (pixel) clocks are defined\n");
 172                return -EINVAL;
 173        }
 174
 175        stream_power->num_clk = stream_clk_count;
 176        stream_power->clk_config = devm_kzalloc(dev,
 177                        sizeof(struct dss_clk) * stream_power->num_clk,
 178                        GFP_KERNEL);
 179        if (!stream_power->clk_config) {
 180                stream_power->num_clk = 0;
 181                return -EINVAL;
 182        }
 183
 184        return 0;
 185}
 186
 187static int dp_parser_clock(struct dp_parser *parser)
 188{
 189        int rc = 0, i = 0;
 190        int num_clk = 0;
 191        int core_clk_index = 0, ctrl_clk_index = 0, stream_clk_index = 0;
 192        int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
 193        const char *clk_name;
 194        struct device *dev = &parser->pdev->dev;
 195        struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
 196        struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
 197        struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
 198
 199        rc =  dp_parser_init_clk_data(parser);
 200        if (rc) {
 201                DRM_ERROR("failed to initialize power data %d\n", rc);
 202                return -EINVAL;
 203        }
 204
 205        core_clk_count = core_power->num_clk;
 206        ctrl_clk_count = ctrl_power->num_clk;
 207        stream_clk_count = stream_power->num_clk;
 208
 209        num_clk = core_clk_count + ctrl_clk_count + stream_clk_count;
 210
 211        for (i = 0; i < num_clk; i++) {
 212                rc = of_property_read_string_index(dev->of_node, "clock-names",
 213                                i, &clk_name);
 214                if (rc) {
 215                        DRM_ERROR("error reading clock-names %d\n", rc);
 216                        return rc;
 217                }
 218                if (dp_parser_check_prefix("core", clk_name) &&
 219                                core_clk_index < core_clk_count) {
 220                        struct dss_clk *clk =
 221                                &core_power->clk_config[core_clk_index];
 222                        strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
 223                        clk->type = DSS_CLK_AHB;
 224                        core_clk_index++;
 225                } else if (dp_parser_check_prefix("stream", clk_name) &&
 226                                stream_clk_index < stream_clk_count) {
 227                        struct dss_clk *clk =
 228                                &stream_power->clk_config[stream_clk_index];
 229                        strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
 230                        clk->type = DSS_CLK_PCLK;
 231                        stream_clk_index++;
 232                } else if (dp_parser_check_prefix("ctrl", clk_name) &&
 233                           ctrl_clk_index < ctrl_clk_count) {
 234                        struct dss_clk *clk =
 235                                &ctrl_power->clk_config[ctrl_clk_index];
 236                        strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
 237                        ctrl_clk_index++;
 238                        if (dp_parser_check_prefix("ctrl_link", clk_name) ||
 239                            dp_parser_check_prefix("stream_pixel", clk_name))
 240                                clk->type = DSS_CLK_PCLK;
 241                        else
 242                                clk->type = DSS_CLK_AHB;
 243                }
 244        }
 245
 246        DRM_DEBUG_DP("clock parsing successful\n");
 247
 248        return 0;
 249}
 250
 251static int dp_parser_parse(struct dp_parser *parser)
 252{
 253        int rc = 0;
 254
 255        if (!parser) {
 256                DRM_ERROR("invalid input\n");
 257                return -EINVAL;
 258        }
 259
 260        rc = dp_parser_ctrl_res(parser);
 261        if (rc)
 262                return rc;
 263
 264        rc = dp_parser_misc(parser);
 265        if (rc)
 266                return rc;
 267
 268        rc = dp_parser_clock(parser);
 269        if (rc)
 270                return rc;
 271
 272        /* Map the corresponding regulator information according to
 273         * version. Currently, since we only have one supported platform,
 274         * mapping the regulator directly.
 275         */
 276        parser->regulator_cfg = &sdm845_dp_reg_cfg;
 277
 278        return 0;
 279}
 280
 281struct dp_parser *dp_parser_get(struct platform_device *pdev)
 282{
 283        struct dp_parser *parser;
 284
 285        parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL);
 286        if (!parser)
 287                return ERR_PTR(-ENOMEM);
 288
 289        parser->parse = dp_parser_parse;
 290        parser->pdev = pdev;
 291
 292        return parser;
 293}
 294