Merge "disp: msm: dp: fix disp_cc offsets for pixel clk dividers"

This commit is contained in:
qctecmdr
2021-03-02 13:25:08 -08:00
committed by Gerrit - the friendly Code Review server
8 changed files with 121 additions and 39 deletions

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/ */
@@ -123,6 +123,7 @@ struct dp_catalog_private {
struct dp_catalog dp_catalog; struct dp_catalog dp_catalog;
char exe_mode[SZ_4]; char exe_mode[SZ_4];
u32 dp_core_version;
}; };
static u32 dp_read_sw(struct dp_catalog_private *catalog, static u32 dp_read_sw(struct dp_catalog_private *catalog,
@@ -1938,6 +1939,25 @@ static void dp_catalog_ctrl_fec_config(struct dp_catalog_ctrl *ctrl,
wmb(); wmb();
} }
u32 dp_catalog_get_dp_core_version(struct dp_catalog *dp_catalog)
{
struct dp_catalog_private *catalog;
struct dp_io_data *io_data;
if (!dp_catalog) {
DP_ERR("invalid input\n");
return 0;
}
catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
if (catalog->dp_core_version)
return catalog->dp_core_version;
io_data = catalog->io.dp_ahb;
return dp_read(DP_HW_VERSION);
}
static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog, static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog,
char *name, u8 **out_buf, u32 *out_buf_len) char *name, u8 **out_buf, u32 *out_buf_len)
{ {

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/ */
#ifndef _DP_CATALOG_H_ #ifndef _DP_CATALOG_H_
@@ -336,4 +336,5 @@ struct dp_catalog_sub *dp_catalog_get_v420(struct device *dev,
struct dp_catalog_sub *dp_catalog_get_v200(struct device *dev, struct dp_catalog_sub *dp_catalog_get_v200(struct device *dev,
struct dp_catalog *catalog, struct dp_catalog_io *io); struct dp_catalog *catalog, struct dp_catalog_io *io);
u32 dp_catalog_get_dp_core_version(struct dp_catalog *dp_catalog);
#endif /* _DP_CATALOG_H_ */ #endif /* _DP_CATALOG_H_ */

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/ */
@@ -8,6 +8,15 @@
#include "dp_reg.h" #include "dp_reg.h"
#include "dp_debug.h" #include "dp_debug.h"
#define MMSS_DP_PIXEL_BASE_V130 (0x1A8)
#define MMSS_DP_PIXEL1_BASE_V130 (0x1C0)
#define MMSS_DP_PIXEL_BASE_V140 (0x1BC)
#define MMSS_DP_PIXEL1_BASE_V140 (0x1D4)
#define MMSS_DP_M_OFF (0x8)
#define MMSS_DP_N_OFF (0xC)
#define dp_catalog_get_priv_v420(x) ({ \ #define dp_catalog_get_priv_v420(x) ({ \
struct dp_catalog *catalog; \ struct dp_catalog *catalog; \
catalog = container_of(x, struct dp_catalog, x); \ catalog = container_of(x, struct dp_catalog, x); \
@@ -146,8 +155,10 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel,
u32 const nvid_fixed = 0x8000; u32 const nvid_fixed = 0x8000;
u32 const link_rate_hbr2 = 540000; u32 const link_rate_hbr2 = 540000;
u32 const link_rate_hbr3 = 810000; u32 const link_rate_hbr3 = 810000;
struct dp_catalog *dp_catalog;
struct dp_catalog_private_v420 *catalog; struct dp_catalog_private_v420 *catalog;
struct dp_io_data *io_data; struct dp_io_data *io_data;
u32 version;
if (!panel || !rate) { if (!panel || !rate) {
DP_ERR("invalid input\n"); DP_ERR("invalid input\n");
@@ -159,14 +170,27 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel,
return; return;
} }
catalog = dp_catalog_get_priv_v420(panel); dp_catalog = container_of(panel, struct dp_catalog, panel);
catalog = container_of(dp_catalog->sub, struct dp_catalog_private_v420, sub);
version = dp_catalog_get_dp_core_version(dp_catalog);
io_data = catalog->io->dp_mmss_cc; io_data = catalog->io->dp_mmss_cc;
if (panel->stream_id == DP_STREAM_1) if (version >= 0x10040000) {
reg_off = MMSS_DP_PIXEL1_M_V420 - MMSS_DP_PIXEL_M_V420; if (panel->stream_id == DP_STREAM_1)
reg_off = MMSS_DP_PIXEL1_BASE_V140;
else
reg_off = MMSS_DP_PIXEL_BASE_V140;
} else {
if (panel->stream_id == DP_STREAM_1)
reg_off = MMSS_DP_PIXEL1_BASE_V130;
else
reg_off = MMSS_DP_PIXEL_BASE_V130;
}
pixel_m = dp_read(MMSS_DP_PIXEL_M_V420 + reg_off);
pixel_n = dp_read(MMSS_DP_PIXEL_N_V420 + reg_off); pixel_m = dp_read(reg_off + MMSS_DP_M_OFF);
pixel_n = dp_read(reg_off + MMSS_DP_N_OFF);
DP_DEBUG("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n); DP_DEBUG("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
mvid = (pixel_m & 0xFFFF) * 5; mvid = (pixel_m & 0xFFFF) * 5;

View File

@@ -1950,6 +1950,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
pll_in.aux = dp->aux; pll_in.aux = dp->aux;
pll_in.parser = dp->parser; pll_in.parser = dp->parser;
pll_in.dp_core_revision = dp_catalog_get_dp_core_version(dp->catalog);
dp->pll = dp_pll_get(&pll_in); dp->pll = dp_pll_get(&pll_in);
if (IS_ERR(dp->pll)) { if (IS_ERR(dp->pll)) {

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/ */
#include <linux/err.h> #include <linux/err.h>
@@ -74,6 +74,34 @@ static void dp_pll_clock_unregister(struct dp_pll *pll)
} }
} }
int dp_pll_clock_register_helper(struct dp_pll *pll, struct dp_pll_vco_clk *clks, int num_clks)
{
int rc = 0, i = 0;
struct platform_device *pdev;
struct clk *clk;
if (!pll || !clks) {
DP_ERR("input not initialized\n");
return -EINVAL;
}
pdev = pll->pdev;
for (i = 0; i < num_clks; i++) {
clks[i].priv = pll;
clk = clk_register(&pdev->dev, &clks[i].hw);
if (IS_ERR(clk)) {
DP_ERR("%s registration failed for DP: %d\n",
clk_hw_get_name(&clks[i].hw), pll->index);
return -EINVAL;
}
pll->clk_data->clks[i] = clk;
}
return rc;
}
struct dp_pll *dp_pll_get(struct dp_pll_in *in) struct dp_pll *dp_pll_get(struct dp_pll_in *in)
{ {
int rc = 0; int rc = 0;
@@ -93,6 +121,7 @@ struct dp_pll *dp_pll_get(struct dp_pll_in *in)
pll->pdev = in->pdev; pll->pdev = in->pdev;
pll->parser = in->parser; pll->parser = in->parser;
pll->aux = in->aux; pll->aux = in->aux;
pll->dp_core_revision = in->dp_core_revision;
parser = pll->parser; parser = pll->parser;
pdev = pll->pdev; pdev = pll->pdev;

View File

@@ -80,6 +80,7 @@ struct dp_pll {
struct dp_aux *aux; struct dp_aux *aux;
struct dp_pll_io io; struct dp_pll_io io;
struct clk_onecell_data *clk_data; struct clk_onecell_data *clk_data;
u32 dp_core_revision;
int (*pll_cfg)(struct dp_pll *pll, unsigned long rate); int (*pll_cfg)(struct dp_pll *pll, unsigned long rate);
int (*pll_prepare)(struct dp_pll *pll); int (*pll_prepare)(struct dp_pll *pll);
@@ -128,8 +129,10 @@ struct dp_pll_in {
struct platform_device *pdev; struct platform_device *pdev;
struct dp_aux *aux; struct dp_aux *aux;
struct dp_parser *parser; struct dp_parser *parser;
u32 dp_core_revision;
}; };
int dp_pll_clock_register_helper(struct dp_pll *pll, struct dp_pll_vco_clk *clks, int num_clks);
struct dp_pll *dp_pll_get(struct dp_pll_in *in); struct dp_pll *dp_pll_get(struct dp_pll_in *in);
void dp_pll_put(struct dp_pll *pll); void dp_pll_put(struct dp_pll *pll);
#endif /* __DP_PLL_H */ #endif /* __DP_PLL_H */

View File

@@ -121,6 +121,8 @@
#define DP_VCO_RATE_9720MHZDIV1000 9720000UL #define DP_VCO_RATE_9720MHZDIV1000 9720000UL
#define DP_VCO_RATE_10800MHZDIV1000 10800000UL #define DP_VCO_RATE_10800MHZDIV1000 10800000UL
#define DP_PLL_NUM_CLKS 2
#define DP_5NM_C_READY BIT(0) #define DP_5NM_C_READY BIT(0)
#define DP_5NM_FREQ_DONE BIT(0) #define DP_5NM_FREQ_DONE BIT(0)
#define DP_5NM_PLL_LOCKED BIT(1) #define DP_5NM_PLL_LOCKED BIT(1)
@@ -826,17 +828,33 @@ static const struct clk_ops pll_vco_div_clk_ops = {
.set_rate = dp_pll_vco_div_clk_set_rate, .set_rate = dp_pll_vco_div_clk_set_rate,
}; };
static struct dp_pll_vco_clk dp_phy_pll_link_clk = { static struct dp_pll_vco_clk dp0_phy_pll_clks[DP_PLL_NUM_CLKS] = {
{
.hw.init = &(struct clk_init_data) { .hw.init = &(struct clk_init_data) {
.name = "dp_phy_pll_link_clk", .name = "dp0_phy_pll_link_clk",
.ops = &pll_link_clk_ops, .ops = &pll_link_clk_ops,
},
},
{
.hw.init = &(struct clk_init_data) {
.name = "dp0_phy_pll_vco_div_clk",
.ops = &pll_vco_div_clk_ops,
},
}, },
}; };
static struct dp_pll_vco_clk dp_phy_pll_vco_div_clk = { static struct dp_pll_vco_clk dp_phy_pll_clks[DP_PLL_NUM_CLKS] = {
{
.hw.init = &(struct clk_init_data) {
.name = "dp_phy_pll_link_clk",
.ops = &pll_link_clk_ops,
},
},
{
.hw.init = &(struct clk_init_data) { .hw.init = &(struct clk_init_data) {
.name = "dp_phy_pll_vco_div_clk", .name = "dp_phy_pll_vco_div_clk",
.ops = &pll_vco_div_clk_ops, .ops = &pll_vco_div_clk_ops,
},
}, },
}; };
@@ -844,9 +862,9 @@ static struct dp_pll_db dp_pdb;
int dp_pll_clock_register_5nm(struct dp_pll *pll) int dp_pll_clock_register_5nm(struct dp_pll *pll)
{ {
int rc = 0, num_clks = 2; int rc = 0;
struct platform_device *pdev; struct platform_device *pdev;
struct clk *clk; struct dp_pll_vco_clk *pll_clks;
if (!pll) { if (!pll) {
DP_ERR("pll data not initialized\n"); DP_ERR("pll data not initialized\n");
@@ -858,46 +876,36 @@ int dp_pll_clock_register_5nm(struct dp_pll *pll)
if (!pll->clk_data) if (!pll->clk_data)
return -ENOMEM; return -ENOMEM;
pll->clk_data->clks = kcalloc(num_clks, sizeof(struct clk *), pll->clk_data->clks = kcalloc(DP_PLL_NUM_CLKS, sizeof(struct clk *),
GFP_KERNEL); GFP_KERNEL);
if (!pll->clk_data->clks) { if (!pll->clk_data->clks) {
kfree(pll->clk_data); kfree(pll->clk_data);
return -ENOMEM; return -ENOMEM;
} }
pll->clk_data->clk_num = num_clks; pll->clk_data->clk_num = DP_PLL_NUM_CLKS;
pll->priv = &dp_pdb; pll->priv = &dp_pdb;
dp_pdb.pll = pll; dp_pdb.pll = pll;
dp_phy_pll_link_clk.priv = pll;
dp_phy_pll_vco_div_clk.priv = pll;
pll->pll_cfg = dp_pll_configure; pll->pll_cfg = dp_pll_configure;
pll->pll_prepare = dp_pll_prepare; pll->pll_prepare = dp_pll_prepare;
pll->pll_unprepare = dp_pll_unprepare; pll->pll_unprepare = dp_pll_unprepare;
clk = clk_register(&pdev->dev, &dp_phy_pll_link_clk.hw); if (pll->dp_core_revision >= 0x10040000)
if (IS_ERR(clk)) { pll_clks = dp0_phy_pll_clks;
DP_ERR("%s registration failed for DP: %d\n", else
clk_hw_get_name(&dp_phy_pll_link_clk.hw), pll->index); pll_clks = dp_phy_pll_clks;
rc = -EINVAL;
goto clk_reg_fail;
}
pll->clk_data->clks[0] = clk;
clk = clk_register(&pdev->dev, &dp_phy_pll_vco_div_clk.hw); rc = dp_pll_clock_register_helper(pll, pll_clks, DP_PLL_NUM_CLKS);
if (IS_ERR(clk)) { if (rc) {
DP_ERR("%s registration failed for DP: %d\n", DP_ERR("Clock register failed rc=%d\n", rc);
clk_hw_get_name(&dp_phy_pll_vco_div_clk.hw), pll->index);
rc = -EINVAL;
goto clk_reg_fail; goto clk_reg_fail;
} }
pll->clk_data->clks[1] = clk;
rc = of_clk_add_provider(pdev->dev.of_node, rc = of_clk_add_provider(pdev->dev.of_node,
of_clk_src_onecell_get, pll->clk_data); of_clk_src_onecell_get, pll->clk_data);
if (rc) { if (rc) {
DP_ERR("Clock register failed rc=%d\n", rc); DP_ERR("Clock add provider failed rc=%d\n", rc);
goto clk_reg_fail; goto clk_reg_fail;
} }

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/ */
#ifndef _DP_REG_H_ #ifndef _DP_REG_H_
@@ -398,10 +398,6 @@
#define MMSS_DP_PIXEL_N_V200 (0x0134) #define MMSS_DP_PIXEL_N_V200 (0x0134)
#define MMSS_DP_PIXEL1_M_V200 (0x0148) #define MMSS_DP_PIXEL1_M_V200 (0x0148)
#define MMSS_DP_PIXEL1_N_V200 (0x014C) #define MMSS_DP_PIXEL1_N_V200 (0x014C)
#define MMSS_DP_PIXEL_M_V420 (0x01B0)
#define MMSS_DP_PIXEL_N_V420 (0x01B4)
#define MMSS_DP_PIXEL1_M_V420 (0x01C8)
#define MMSS_DP_PIXEL1_N_V420 (0x01CC)
/* DP HDCP 1.3 registers */ /* DP HDCP 1.3 registers */
#define DP_HDCP_CTRL (0x0A0) #define DP_HDCP_CTRL (0x0A0)