Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/of_gpio.h>
0007 #include <linux/phy/phy.h>
0008 
0009 #include <drm/drm_of.h>
0010 #include <drm/drm_print.h>
0011 #include <drm/drm_bridge.h>
0012 
0013 #include "dp_parser.h"
0014 #include "dp_reg.h"
0015 
0016 #define DP_DEFAULT_AHB_OFFSET   0x0000
0017 #define DP_DEFAULT_AHB_SIZE 0x0200
0018 #define DP_DEFAULT_AUX_OFFSET   0x0200
0019 #define DP_DEFAULT_AUX_SIZE 0x0200
0020 #define DP_DEFAULT_LINK_OFFSET  0x0400
0021 #define DP_DEFAULT_LINK_SIZE    0x0C00
0022 #define DP_DEFAULT_P0_OFFSET    0x1000
0023 #define DP_DEFAULT_P0_SIZE  0x0400
0024 
0025 static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
0026 {
0027     struct resource *res;
0028     void __iomem *base;
0029 
0030     base = devm_platform_get_and_ioremap_resource(pdev, idx, &res);
0031     if (!IS_ERR(base))
0032         *len = resource_size(res);
0033 
0034     return base;
0035 }
0036 
0037 static int dp_parser_ctrl_res(struct dp_parser *parser)
0038 {
0039     struct platform_device *pdev = parser->pdev;
0040     struct dp_io *io = &parser->io;
0041     struct dss_io_data *dss = &io->dp_controller;
0042 
0043     dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len);
0044     if (IS_ERR(dss->ahb.base))
0045         return PTR_ERR(dss->ahb.base);
0046 
0047     dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len);
0048     if (IS_ERR(dss->aux.base)) {
0049         /*
0050          * The initial binding had a single reg, but in order to
0051          * support variation in the sub-region sizes this was split.
0052          * dp_ioremap() will fail with -EINVAL here if only a single
0053          * reg is specified, so fill in the sub-region offsets and
0054          * lengths based on this single region.
0055          */
0056         if (PTR_ERR(dss->aux.base) == -EINVAL) {
0057             if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) {
0058                 DRM_ERROR("legacy memory region not large enough\n");
0059                 return -EINVAL;
0060             }
0061 
0062             dss->ahb.len = DP_DEFAULT_AHB_SIZE;
0063             dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET;
0064             dss->aux.len = DP_DEFAULT_AUX_SIZE;
0065             dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET;
0066             dss->link.len = DP_DEFAULT_LINK_SIZE;
0067             dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET;
0068             dss->p0.len = DP_DEFAULT_P0_SIZE;
0069         } else {
0070             DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base);
0071             return PTR_ERR(dss->aux.base);
0072         }
0073     } else {
0074         dss->link.base = dp_ioremap(pdev, 2, &dss->link.len);
0075         if (IS_ERR(dss->link.base)) {
0076             DRM_ERROR("unable to remap link region: %pe\n", dss->link.base);
0077             return PTR_ERR(dss->link.base);
0078         }
0079 
0080         dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len);
0081         if (IS_ERR(dss->p0.base)) {
0082             DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base);
0083             return PTR_ERR(dss->p0.base);
0084         }
0085     }
0086 
0087     io->phy = devm_phy_get(&pdev->dev, "dp");
0088     if (IS_ERR(io->phy))
0089         return PTR_ERR(io->phy);
0090 
0091     return 0;
0092 }
0093 
0094 static int dp_parser_misc(struct dp_parser *parser)
0095 {
0096     struct device_node *of_node = parser->pdev->dev.of_node;
0097     int len;
0098 
0099     len = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES);
0100     if (len < 0) {
0101         DRM_WARN("Invalid property \"data-lanes\", default max DP lanes = %d\n",
0102              DP_MAX_NUM_DP_LANES);
0103         len = DP_MAX_NUM_DP_LANES;
0104     }
0105 
0106     parser->max_dp_lanes = len;
0107     return 0;
0108 }
0109 
0110 static inline bool dp_parser_check_prefix(const char *clk_prefix,
0111                         const char *clk_name)
0112 {
0113     return !strncmp(clk_prefix, clk_name, strlen(clk_prefix));
0114 }
0115 
0116 static int dp_parser_init_clk_data(struct dp_parser *parser)
0117 {
0118     int num_clk, i, rc;
0119     int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
0120     const char *clk_name;
0121     struct device *dev = &parser->pdev->dev;
0122     struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
0123     struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
0124     struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
0125 
0126     num_clk = of_property_count_strings(dev->of_node, "clock-names");
0127     if (num_clk <= 0) {
0128         DRM_ERROR("no clocks are defined\n");
0129         return -EINVAL;
0130     }
0131 
0132     for (i = 0; i < num_clk; i++) {
0133         rc = of_property_read_string_index(dev->of_node,
0134                 "clock-names", i, &clk_name);
0135         if (rc < 0)
0136             return rc;
0137 
0138         if (dp_parser_check_prefix("core", clk_name))
0139             core_clk_count++;
0140 
0141         if (dp_parser_check_prefix("ctrl", clk_name))
0142             ctrl_clk_count++;
0143 
0144         if (dp_parser_check_prefix("stream", clk_name))
0145             stream_clk_count++;
0146     }
0147 
0148     /* Initialize the CORE power module */
0149     if (core_clk_count == 0) {
0150         DRM_ERROR("no core clocks are defined\n");
0151         return -EINVAL;
0152     }
0153 
0154     core_power->num_clk = core_clk_count;
0155     core_power->clocks = devm_kcalloc(dev,
0156             core_power->num_clk, sizeof(struct clk_bulk_data),
0157             GFP_KERNEL);
0158     if (!core_power->clocks)
0159         return -ENOMEM;
0160 
0161     /* Initialize the CTRL power module */
0162     if (ctrl_clk_count == 0) {
0163         DRM_ERROR("no ctrl clocks are defined\n");
0164         return -EINVAL;
0165     }
0166 
0167     ctrl_power->num_clk = ctrl_clk_count;
0168     ctrl_power->clocks = devm_kcalloc(dev,
0169             ctrl_power->num_clk, sizeof(struct clk_bulk_data),
0170             GFP_KERNEL);
0171     if (!ctrl_power->clocks) {
0172         ctrl_power->num_clk = 0;
0173         return -ENOMEM;
0174     }
0175 
0176     /* Initialize the STREAM power module */
0177     if (stream_clk_count == 0) {
0178         DRM_ERROR("no stream (pixel) clocks are defined\n");
0179         return -EINVAL;
0180     }
0181 
0182     stream_power->num_clk = stream_clk_count;
0183     stream_power->clocks = devm_kcalloc(dev,
0184             stream_power->num_clk, sizeof(struct clk_bulk_data),
0185             GFP_KERNEL);
0186     if (!stream_power->clocks) {
0187         stream_power->num_clk = 0;
0188         return -ENOMEM;
0189     }
0190 
0191     return 0;
0192 }
0193 
0194 static int dp_parser_clock(struct dp_parser *parser)
0195 {
0196     int rc = 0, i = 0;
0197     int num_clk = 0;
0198     int core_clk_index = 0, ctrl_clk_index = 0, stream_clk_index = 0;
0199     int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
0200     const char *clk_name;
0201     struct device *dev = &parser->pdev->dev;
0202     struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
0203     struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
0204     struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
0205 
0206     rc =  dp_parser_init_clk_data(parser);
0207     if (rc) {
0208         DRM_ERROR("failed to initialize power data %d\n", rc);
0209         return -EINVAL;
0210     }
0211 
0212     core_clk_count = core_power->num_clk;
0213     ctrl_clk_count = ctrl_power->num_clk;
0214     stream_clk_count = stream_power->num_clk;
0215 
0216     num_clk = core_clk_count + ctrl_clk_count + stream_clk_count;
0217 
0218     for (i = 0; i < num_clk; i++) {
0219         rc = of_property_read_string_index(dev->of_node, "clock-names",
0220                 i, &clk_name);
0221         if (rc) {
0222             DRM_ERROR("error reading clock-names %d\n", rc);
0223             return rc;
0224         }
0225         if (dp_parser_check_prefix("core", clk_name) &&
0226                 core_clk_index < core_clk_count) {
0227             core_power->clocks[core_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL);
0228             core_clk_index++;
0229         } else if (dp_parser_check_prefix("stream", clk_name) &&
0230                 stream_clk_index < stream_clk_count) {
0231             stream_power->clocks[stream_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL);
0232             stream_clk_index++;
0233         } else if (dp_parser_check_prefix("ctrl", clk_name) &&
0234                ctrl_clk_index < ctrl_clk_count) {
0235             ctrl_power->clocks[ctrl_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL);
0236             ctrl_clk_index++;
0237         }
0238     }
0239 
0240     return 0;
0241 }
0242 
0243 int dp_parser_find_next_bridge(struct dp_parser *parser)
0244 {
0245     struct device *dev = &parser->pdev->dev;
0246     struct drm_bridge *bridge;
0247 
0248     bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
0249     if (IS_ERR(bridge))
0250         return PTR_ERR(bridge);
0251 
0252     parser->next_bridge = bridge;
0253 
0254     return 0;
0255 }
0256 
0257 static int dp_parser_parse(struct dp_parser *parser)
0258 {
0259     int rc = 0;
0260 
0261     if (!parser) {
0262         DRM_ERROR("invalid input\n");
0263         return -EINVAL;
0264     }
0265 
0266     rc = dp_parser_ctrl_res(parser);
0267     if (rc)
0268         return rc;
0269 
0270     rc = dp_parser_misc(parser);
0271     if (rc)
0272         return rc;
0273 
0274     rc = dp_parser_clock(parser);
0275     if (rc)
0276         return rc;
0277 
0278     return 0;
0279 }
0280 
0281 struct dp_parser *dp_parser_get(struct platform_device *pdev)
0282 {
0283     struct dp_parser *parser;
0284 
0285     parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL);
0286     if (!parser)
0287         return ERR_PTR(-ENOMEM);
0288 
0289     parser->parse = dp_parser_parse;
0290     parser->pdev = pdev;
0291 
0292     return parser;
0293 }