drm/msm/dp: Allow sub-regions to be specified in DT
authorBjorn Andersson <bjorn.andersson@linaro.org>
Fri, 1 Oct 2021 17:44:00 +0000 (10:44 -0700)
committerRob Clark <robdclark@chromium.org>
Fri, 15 Oct 2021 23:35:39 +0000 (16:35 -0700)
Not all platforms has P0 at an offset of 0x1000 from the base address,
so add support for specifying each sub-region in DT. The code falls back
to the predefined offsets in the case that only a single reg is
specified, in order to support existing DT.

Reviewed-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Abhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/20211001174400.981707-6-bjorn.andersson@linaro.org
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
drivers/gpu/drm/msm/dp/dp_parser.c

index 1f084b2b5bd3cafed11cc6ede37d98d929a6ef9f..a431b4e7f385ed78d921cfaaa67e82afd3607ba4 100644 (file)
@@ -50,18 +50,45 @@ static int dp_parser_ctrl_res(struct dp_parser *parser)
        if (IS_ERR(dss->ahb.base))
                return PTR_ERR(dss->ahb.base);
 
-       if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) {
-               DRM_ERROR("legacy memory region not large enough\n");
-               return -EINVAL;
-       }
+       dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len);
+       if (IS_ERR(dss->aux.base)) {
+               /*
+                * The initial binding had a single reg, but in order to
+                * support variation in the sub-region sizes this was split.
+                * dp_ioremap() will fail with -EINVAL here if only a single
+                * reg is specified, so fill in the sub-region offsets and
+                * lengths based on this single region.
+                */
+               if (PTR_ERR(dss->aux.base) == -EINVAL) {
+                       if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) {
+                               DRM_ERROR("legacy memory region not large enough\n");
+                               return -EINVAL;
+                       }
+
+                       dss->ahb.len = DP_DEFAULT_AHB_SIZE;
+                       dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET;
+                       dss->aux.len = DP_DEFAULT_AUX_SIZE;
+                       dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET;
+                       dss->link.len = DP_DEFAULT_LINK_SIZE;
+                       dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET;
+                       dss->p0.len = DP_DEFAULT_P0_SIZE;
+               } else {
+                       DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base);
+                       return PTR_ERR(dss->aux.base);
+               }
+       } else {
+               dss->link.base = dp_ioremap(pdev, 2, &dss->link.len);
+               if (IS_ERR(dss->link.base)) {
+                       DRM_ERROR("unable to remap link region: %pe\n", dss->link.base);
+                       return PTR_ERR(dss->link.base);
+               }
 
-       dss->ahb.len = DP_DEFAULT_AHB_SIZE;
-       dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET;
-       dss->aux.len = DP_DEFAULT_AUX_SIZE;
-       dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET;
-       dss->link.len = DP_DEFAULT_LINK_SIZE;
-       dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET;
-       dss->p0.len = DP_DEFAULT_P0_SIZE;
+               dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len);
+               if (IS_ERR(dss->p0.base)) {
+                       DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base);
+                       return PTR_ERR(dss->p0.base);
+               }
+       }
 
        io->phy = devm_phy_get(&pdev->dev, "dp");
        if (IS_ERR(io->phy))