Commit 15778141 authored by Dmitry Baryshkov's avatar Dmitry Baryshkov

drm/msm/dp: move all IO handling to dp_catalog

Rather than parsing the I/O addresses from dp_parser and then passing
them via a struct pointer to dp_catalog, handle I/O region parsing in
dp_catalog and drop it from dp_parser.
Signed-off-by: default avatarDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Tested-by: default avatarKuogee Hsieh <quic_khsieh@quicinc.com>
Reviewed-by: default avatarKuogee Hsieh <quic_khsieh@quicinc.com>
Patchwork: https://patchwork.freedesktop.org/patch/576108/
Link: https://lore.kernel.org/r/20240126-dp-power-parser-cleanup-v3-12-098d5f581dd3@linaro.org
parent f304bda5
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/platform_device.h>
#include <linux/rational.h> #include <linux/rational.h>
#include <drm/display/drm_dp_helper.h> #include <drm/display/drm_dp_helper.h>
#include <drm/drm_print.h> #include <drm/drm_print.h>
...@@ -53,10 +54,31 @@ ...@@ -53,10 +54,31 @@
(PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \ (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK) PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)
#define DP_DEFAULT_AHB_OFFSET 0x0000
#define DP_DEFAULT_AHB_SIZE 0x0200
#define DP_DEFAULT_AUX_OFFSET 0x0200
#define DP_DEFAULT_AUX_SIZE 0x0200
#define DP_DEFAULT_LINK_OFFSET 0x0400
#define DP_DEFAULT_LINK_SIZE 0x0C00
#define DP_DEFAULT_P0_OFFSET 0x1000
#define DP_DEFAULT_P0_SIZE 0x0400
struct dss_io_region {
size_t len;
void __iomem *base;
};
struct dss_io_data {
struct dss_io_region ahb;
struct dss_io_region aux;
struct dss_io_region link;
struct dss_io_region p0;
};
struct dp_catalog_private { struct dp_catalog_private {
struct device *dev; struct device *dev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct dp_io *io; struct dss_io_data io;
u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX]; u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX];
struct dp_catalog dp_catalog; struct dp_catalog dp_catalog;
u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX]; u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX];
...@@ -66,7 +88,7 @@ void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *d ...@@ -66,7 +88,7 @@ void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *d
{ {
struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private *catalog = container_of(dp_catalog,
struct dp_catalog_private, dp_catalog); struct dp_catalog_private, dp_catalog);
struct dss_io_data *dss = &catalog->io->dp_controller; struct dss_io_data *dss = &catalog->io;
msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb"); msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb");
msm_disp_snapshot_add_block(disp_state, dss->aux.len, dss->aux.base, "dp_aux"); msm_disp_snapshot_add_block(disp_state, dss->aux.len, dss->aux.base, "dp_aux");
...@@ -76,7 +98,7 @@ void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *d ...@@ -76,7 +98,7 @@ void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *d
static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset) static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset)
{ {
return readl_relaxed(catalog->io->dp_controller.aux.base + offset); return readl_relaxed(catalog->io.aux.base + offset);
} }
static inline void dp_write_aux(struct dp_catalog_private *catalog, static inline void dp_write_aux(struct dp_catalog_private *catalog,
...@@ -86,12 +108,12 @@ static inline void dp_write_aux(struct dp_catalog_private *catalog, ...@@ -86,12 +108,12 @@ static inline void dp_write_aux(struct dp_catalog_private *catalog,
* To make sure aux reg writes happens before any other operation, * To make sure aux reg writes happens before any other operation,
* this function uses writel() instread of writel_relaxed() * this function uses writel() instread of writel_relaxed()
*/ */
writel(data, catalog->io->dp_controller.aux.base + offset); writel(data, catalog->io.aux.base + offset);
} }
static inline u32 dp_read_ahb(const struct dp_catalog_private *catalog, u32 offset) static inline u32 dp_read_ahb(const struct dp_catalog_private *catalog, u32 offset)
{ {
return readl_relaxed(catalog->io->dp_controller.ahb.base + offset); return readl_relaxed(catalog->io.ahb.base + offset);
} }
static inline void dp_write_ahb(struct dp_catalog_private *catalog, static inline void dp_write_ahb(struct dp_catalog_private *catalog,
...@@ -101,7 +123,7 @@ static inline void dp_write_ahb(struct dp_catalog_private *catalog, ...@@ -101,7 +123,7 @@ static inline void dp_write_ahb(struct dp_catalog_private *catalog,
* To make sure phy reg writes happens before any other operation, * To make sure phy reg writes happens before any other operation,
* this function uses writel() instread of writel_relaxed() * this function uses writel() instread of writel_relaxed()
*/ */
writel(data, catalog->io->dp_controller.ahb.base + offset); writel(data, catalog->io.ahb.base + offset);
} }
static inline void dp_write_p0(struct dp_catalog_private *catalog, static inline void dp_write_p0(struct dp_catalog_private *catalog,
...@@ -111,7 +133,7 @@ static inline void dp_write_p0(struct dp_catalog_private *catalog, ...@@ -111,7 +133,7 @@ static inline void dp_write_p0(struct dp_catalog_private *catalog,
* To make sure interface reg writes happens before any other operation, * To make sure interface reg writes happens before any other operation,
* this function uses writel() instread of writel_relaxed() * this function uses writel() instread of writel_relaxed()
*/ */
writel(data, catalog->io->dp_controller.p0.base + offset); writel(data, catalog->io.p0.base + offset);
} }
static inline u32 dp_read_p0(struct dp_catalog_private *catalog, static inline u32 dp_read_p0(struct dp_catalog_private *catalog,
...@@ -121,12 +143,12 @@ static inline u32 dp_read_p0(struct dp_catalog_private *catalog, ...@@ -121,12 +143,12 @@ static inline u32 dp_read_p0(struct dp_catalog_private *catalog,
* To make sure interface reg writes happens before any other operation, * To make sure interface reg writes happens before any other operation,
* this function uses writel() instread of writel_relaxed() * this function uses writel() instread of writel_relaxed()
*/ */
return readl_relaxed(catalog->io->dp_controller.p0.base + offset); return readl_relaxed(catalog->io.p0.base + offset);
} }
static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset) static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset)
{ {
return readl_relaxed(catalog->io->dp_controller.link.base + offset); return readl_relaxed(catalog->io.link.base + offset);
} }
static inline void dp_write_link(struct dp_catalog_private *catalog, static inline void dp_write_link(struct dp_catalog_private *catalog,
...@@ -136,7 +158,7 @@ static inline void dp_write_link(struct dp_catalog_private *catalog, ...@@ -136,7 +158,7 @@ static inline void dp_write_link(struct dp_catalog_private *catalog,
* To make sure link reg writes happens before any other operation, * To make sure link reg writes happens before any other operation,
* this function uses writel() instread of writel_relaxed() * this function uses writel() instread of writel_relaxed()
*/ */
writel(data, catalog->io->dp_controller.link.base + offset); writel(data, catalog->io.link.base + offset);
} }
/* aux related catalog functions */ /* aux related catalog functions */
...@@ -248,7 +270,7 @@ int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog) ...@@ -248,7 +270,7 @@ int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog)
struct dp_catalog_private, dp_catalog); struct dp_catalog_private, dp_catalog);
/* poll for hpd connected status every 2ms and timeout after 500ms */ /* poll for hpd connected status every 2ms and timeout after 500ms */
return readl_poll_timeout(catalog->io->dp_controller.aux.base + return readl_poll_timeout(catalog->io.aux.base +
REG_DP_DP_HPD_INT_STATUS, REG_DP_DP_HPD_INT_STATUS,
state, state & DP_DP_HPD_STATE_STATUS_CONNECTED, state, state & DP_DP_HPD_STATE_STATUS_CONNECTED,
2000, 500000); 2000, 500000);
...@@ -276,7 +298,7 @@ void dp_catalog_dump_regs(struct dp_catalog *dp_catalog) ...@@ -276,7 +298,7 @@ void dp_catalog_dump_regs(struct dp_catalog *dp_catalog)
{ {
struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private *catalog = container_of(dp_catalog,
struct dp_catalog_private, dp_catalog); struct dp_catalog_private, dp_catalog);
struct dss_io_data *io = &catalog->io->dp_controller; struct dss_io_data *io = &catalog->io;
pr_info("AHB regs\n"); pr_info("AHB regs\n");
dump_regs(io->ahb.base, io->ahb.len); dump_regs(io->ahb.base, io->ahb.len);
...@@ -500,7 +522,7 @@ int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, ...@@ -500,7 +522,7 @@ int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog,
bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT;
/* Poll for mainlink ready status */ /* Poll for mainlink ready status */
ret = readx_poll_timeout(readl, catalog->io->dp_controller.link.base + ret = readx_poll_timeout(readl, catalog->io.link.base +
REG_DP_MAINLINK_READY, REG_DP_MAINLINK_READY,
data, data & bit, data, data & bit,
POLLING_SLEEP_US, POLLING_TIMEOUT_US); POLLING_SLEEP_US, POLLING_TIMEOUT_US);
...@@ -563,7 +585,7 @@ bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog) ...@@ -563,7 +585,7 @@ bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog)
struct dp_catalog_private, dp_catalog); struct dp_catalog_private, dp_catalog);
/* Poll for mainlink ready status */ /* Poll for mainlink ready status */
ret = readl_poll_timeout(catalog->io->dp_controller.link.base + ret = readl_poll_timeout(catalog->io.link.base +
REG_DP_MAINLINK_READY, REG_DP_MAINLINK_READY,
data, data & DP_MAINLINK_READY_FOR_VIDEO, data, data & DP_MAINLINK_READY_FOR_VIDEO,
POLLING_SLEEP_US, POLLING_TIMEOUT_US); POLLING_SLEEP_US, POLLING_TIMEOUT_US);
...@@ -945,21 +967,84 @@ void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog) ...@@ -945,21 +967,84 @@ void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog)
dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0); dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0);
} }
struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io) static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
{ {
struct dp_catalog_private *catalog; struct resource *res;
void __iomem *base;
base = devm_platform_get_and_ioremap_resource(pdev, idx, &res);
if (!IS_ERR(base))
*len = resource_size(res);
return base;
}
static int dp_catalog_get_io(struct dp_catalog_private *catalog)
{
struct platform_device *pdev = to_platform_device(catalog->dev);
struct dss_io_data *dss = &catalog->io;
dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len);
if (IS_ERR(dss->ahb.base))
return PTR_ERR(dss->ahb.base);
if (!io) { dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len);
DRM_ERROR("invalid input\n"); if (IS_ERR(dss->aux.base)) {
return ERR_PTR(-EINVAL); /*
* 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->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);
}
} }
return 0;
}
struct dp_catalog *dp_catalog_get(struct device *dev)
{
struct dp_catalog_private *catalog;
int ret;
catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL); catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL);
if (!catalog) if (!catalog)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
catalog->dev = dev; catalog->dev = dev;
catalog->io = io;
ret = dp_catalog_get_io(catalog);
if (ret)
return ERR_PTR(ret);
return &catalog->dp_catalog; return &catalog->dp_catalog;
} }
......
...@@ -126,7 +126,7 @@ void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, ...@@ -126,7 +126,7 @@ void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
struct drm_display_mode *drm_mode); struct drm_display_mode *drm_mode);
void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog); void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog);
struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io); struct dp_catalog *dp_catalog_get(struct device *dev);
/* DP Audio APIs */ /* DP Audio APIs */
void dp_catalog_audio_get_header(struct dp_catalog *catalog); void dp_catalog_audio_get_header(struct dp_catalog *catalog);
......
...@@ -722,7 +722,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) ...@@ -722,7 +722,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
goto error; goto error;
} }
dp->catalog = dp_catalog_get(dev, &dp->parser->io); dp->catalog = dp_catalog_get(dev);
if (IS_ERR(dp->catalog)) { if (IS_ERR(dp->catalog)) {
rc = PTR_ERR(dp->catalog); rc = PTR_ERR(dp->catalog);
DRM_ERROR("failed to initialize catalog, rc = %d\n", rc); DRM_ERROR("failed to initialize catalog, rc = %d\n", rc);
...@@ -731,7 +731,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) ...@@ -731,7 +731,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
} }
dp->aux = dp_aux_get(dev, dp->catalog, dp->aux = dp_aux_get(dev, dp->catalog,
dp->parser->io.phy, dp->parser->phy,
dp->dp_display.is_edp); dp->dp_display.is_edp);
if (IS_ERR(dp->aux)) { if (IS_ERR(dp->aux)) {
rc = PTR_ERR(dp->aux); rc = PTR_ERR(dp->aux);
...@@ -762,7 +762,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) ...@@ -762,7 +762,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
dp->ctrl = dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, dp->ctrl = dp_ctrl_get(dev, dp->link, dp->panel, dp->aux,
dp->catalog, dp->catalog,
dp->parser->io.phy); dp->parser->phy);
if (IS_ERR(dp->ctrl)) { if (IS_ERR(dp->ctrl)) {
rc = PTR_ERR(dp->ctrl); rc = PTR_ERR(dp->ctrl);
DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc);
......
...@@ -13,80 +13,13 @@ ...@@ -13,80 +13,13 @@
#include "dp_parser.h" #include "dp_parser.h"
#include "dp_reg.h" #include "dp_reg.h"
#define DP_DEFAULT_AHB_OFFSET 0x0000
#define DP_DEFAULT_AHB_SIZE 0x0200
#define DP_DEFAULT_AUX_OFFSET 0x0200
#define DP_DEFAULT_AUX_SIZE 0x0200
#define DP_DEFAULT_LINK_OFFSET 0x0400
#define DP_DEFAULT_LINK_SIZE 0x0C00
#define DP_DEFAULT_P0_OFFSET 0x1000
#define DP_DEFAULT_P0_SIZE 0x0400
static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
{
struct resource *res;
void __iomem *base;
base = devm_platform_get_and_ioremap_resource(pdev, idx, &res);
if (!IS_ERR(base))
*len = resource_size(res);
return base;
}
static int dp_parser_ctrl_res(struct dp_parser *parser) static int dp_parser_ctrl_res(struct dp_parser *parser)
{ {
struct platform_device *pdev = parser->pdev; struct platform_device *pdev = parser->pdev;
struct dp_io *io = &parser->io;
struct dss_io_data *dss = &io->dp_controller;
dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len);
if (IS_ERR(dss->ahb.base))
return PTR_ERR(dss->ahb.base);
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->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"); parser->phy = devm_phy_get(&pdev->dev, "dp");
if (IS_ERR(io->phy)) if (IS_ERR(parser->phy))
return PTR_ERR(io->phy); return PTR_ERR(parser->phy);
return 0; return 0;
} }
......
...@@ -14,37 +14,15 @@ ...@@ -14,37 +14,15 @@
#define DP_MAX_NUM_DP_LANES 4 #define DP_MAX_NUM_DP_LANES 4
#define DP_LINK_RATE_HBR2 540000 /* kbytes */ #define DP_LINK_RATE_HBR2 540000 /* kbytes */
struct dss_io_region {
size_t len;
void __iomem *base;
};
struct dss_io_data {
struct dss_io_region ahb;
struct dss_io_region aux;
struct dss_io_region link;
struct dss_io_region p0;
};
/**
* struct dp_ctrl_resource - controller's IO related data
*
* @dp_controller: Display Port controller mapped memory address
* @phy_io: phy's mapped memory address
*/
struct dp_io {
struct dss_io_data dp_controller;
struct phy *phy;
};
/** /**
* struct dp_parser - DP parser's data exposed to clients * struct dp_parser - DP parser's data exposed to clients
* *
* @pdev: platform data of the client * @pdev: platform data of the client
* @phy: PHY handle
*/ */
struct dp_parser { struct dp_parser {
struct platform_device *pdev; struct platform_device *pdev;
struct dp_io io; struct phy *phy;
u32 max_dp_lanes; u32 max_dp_lanes;
u32 max_dp_link_rate; u32 max_dp_link_rate;
struct drm_bridge *next_bridge; struct drm_bridge *next_bridge;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment