msm: ndss: dsi: fix PLL source configuration for branch clocks

The PLL source for the DSI clocks can be specified using the
pll_src_config DTSI binding. However, this binding is optional and
whenever it is not specified, the default configuration should be
programmed based on the underlying hardware configuration. If the
hardware configuration is split-dsi, then both branches should source
from the same PLL, otherwise they should source from their corresponding
PLLs.

Change-Id: Idc1c003fede7440bad10311fe1f3bc44cc627053
Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
This commit is contained in:
Aravind Venkateswaran 2015-05-22 15:36:27 -07:00 committed by David Keitel
parent 142b8c7784
commit bd37954d5d
2 changed files with 77 additions and 23 deletions

View file

@ -59,7 +59,29 @@ static void mdss_dsi_config_clk_src(struct platform_device *pdev)
return;
}
if (!mdss_dsi_is_hw_config_dual(sdata)) {
if (mdss_dsi_is_pll_src_default(sdata)) {
/*
* Default Mapping:
* 1. dual-dsi/single-dsi:
* DSI0 <--> PLL0
* DSI1 <--> PLL1
* 2. split-dsi:
* DSI0 <--> PLL0
* DSI1 <--> PLL0
*/
sdata->byte0_parent = sdata->ext_byte0_clk;
sdata->pixel0_parent = sdata->ext_pixel0_clk;
if (mdss_dsi_is_hw_config_split(sdata)) {
sdata->byte1_parent = sdata->byte0_parent;
sdata->pixel1_parent = sdata->pixel0_parent;
} else {
sdata->byte1_parent = sdata->ext_byte1_clk;
sdata->pixel1_parent = sdata->ext_pixel1_clk;
}
pr_debug("%s: default: DSI0 <--> PLL0, DSI1 <--> %s", __func__,
mdss_dsi_is_hw_config_split(sdata) ? "PLL0" : "PLL1");
} else {
/*
* For split-dsi and single-dsi use cases, map the PLL source
* based on the pll source configuration. It is possible that
@ -72,25 +94,13 @@ static void mdss_dsi_config_clk_src(struct platform_device *pdev)
pr_debug("%s: single source: PLL0", __func__);
sdata->byte0_parent = sdata->ext_byte0_clk;
sdata->pixel0_parent = sdata->ext_pixel0_clk;
} else {
} else if (mdss_dsi_is_pll_src_pll1(sdata)) {
pr_debug("%s: single source: PLL1", __func__);
sdata->byte0_parent = sdata->ext_byte1_clk;
sdata->pixel0_parent = sdata->ext_pixel1_clk;
}
sdata->byte1_parent = sdata->byte0_parent;
sdata->pixel1_parent = sdata->pixel0_parent;
} else {
/*
* For dual-dsi use cases, map:
* DSI0 <--> PLL0
* DSI1 <--> PLL1
*/
pr_debug("%s: dual-dsi: DSI0 <--> PLL0, DSI1 <--> PLL1",
__func__);
sdata->byte0_parent = sdata->ext_byte0_clk;
sdata->byte1_parent = sdata->ext_byte1_clk;
sdata->pixel0_parent = sdata->ext_pixel0_clk;
sdata->pixel1_parent = sdata->ext_pixel1_clk;
}
return;
@ -2284,6 +2294,12 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
disable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
}
pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index);
if (index == 0)
ctrl_pdata->shared_data->dsi0_active = true;
else
ctrl_pdata->shared_data->dsi1_active = true;
return 0;
error_pan_node:
@ -2499,7 +2515,7 @@ static void mdss_dsi_parse_pll_src_cfg(struct platform_device *pdev)
const char *data;
struct dsi_shared_data *sdata = mdss_dsi_res->shared_data;
sdata->pll_src_config = PLL_SRC_0;
sdata->pll_src_config = PLL_SRC_DEFAULT;
data = of_get_property(pdev->dev.of_node, "pll-src-config", NULL);
if (data) {
if (!strcmp(data, "PLL0"))
@ -2507,11 +2523,10 @@ static void mdss_dsi_parse_pll_src_cfg(struct platform_device *pdev)
else if (!strcmp(data, "PLL1"))
sdata->pll_src_config = PLL_SRC_1;
else
pr_err("%s: invalid pll src config %s. Using PLL_SRC_0 as default\n",
pr_err("%s: invalid pll src config %s\n",
__func__, data);
} else {
pr_debug("%s: PLL src config not present. Using PLL0 by default\n",
__func__);
pr_debug("%s: PLL src config not specified\n", __func__);
}
pr_debug("%s: pll_src_config = %d", __func__, sdata->pll_src_config);
@ -2531,7 +2546,6 @@ static int mdss_dsi_validate_pll_src_config(struct dsi_shared_data *sdata)
* - For single dsi, it is not possible to source the clocks for
* DSI0 from PLL1.
*/
if (mdss_dsi_is_hw_config_split(sdata) &&
mdss_dsi_is_pll_src_pll1(sdata)) {
pr_err("%s: unsupported PLL config: using PLL1 for split-dsi\n",
@ -2540,7 +2554,21 @@ static int mdss_dsi_validate_pll_src_config(struct dsi_shared_data *sdata)
goto error;
}
/* todo: enforce remaining checks */
if (mdss_dsi_is_hw_config_dual(sdata) &&
!mdss_dsi_is_pll_src_default(sdata)) {
pr_debug("%s: pll src config not applicable for dual-dsi\n",
__func__);
sdata->pll_src_config = PLL_SRC_DEFAULT;
}
if (mdss_dsi_is_hw_config_single(sdata) &&
mdss_dsi_is_dsi0_active(sdata) &&
mdss_dsi_is_pll_src_pll1(sdata)) {
pr_err("%s: unsupported PLL config: using PLL1 for DSI1\n",
__func__);
rc = -EINVAL;
goto error;
}
error:
return rc;

View file

@ -228,6 +228,8 @@ struct dsi_shared_data {
bool timing_db_mode;
bool cmd_clk_ln_recovery_en;
bool dsi0_active;
bool dsi1_active;
/* DSI bus clocks */
struct clk *mdp_core_clk;
@ -284,6 +286,7 @@ enum mdss_dsi_hw_config {
* @PLL_SRC_1: The link clocks are sourced out of PLL1.
*/
enum mdss_dsi_pll_src_config {
PLL_SRC_DEFAULT,
PLL_SRC_0,
PLL_SRC_1,
};
@ -594,11 +597,24 @@ static inline bool mdss_dsi_is_hw_config_dual(struct dsi_shared_data *sdata)
return mdss_dsi_get_hw_config(sdata) == DUAL_DSI;
}
static inline u32 mdss_dsi_get_pll_src_config(struct dsi_shared_data *sdata)
static inline bool mdss_dsi_get_pll_src_config(struct dsi_shared_data *sdata)
{
return sdata->pll_src_config;
}
/*
* mdss_dsi_is_pll_src_default: Check if the DSI device uses default PLL src
* For single-dsi and dual-dsi configuration, PLL source need not be
* explicitly specified. In this case, the default PLL source configuration
* is assumed.
*
* @sdata: pointer to DSI shared data structure
*/
static inline bool mdss_dsi_is_pll_src_default(struct dsi_shared_data *sdata)
{
return sdata->pll_src_config == PLL_SRC_DEFAULT;
}
/*
* mdss_dsi_is_pll_src_pll0: Check if the PLL source for a DSI device is PLL0
* The function is only valid if the DSI configuration is single/split DSI.
@ -606,7 +622,7 @@ static inline u32 mdss_dsi_get_pll_src_config(struct dsi_shared_data *sdata)
*
* @sdata: pointer to DSI shared data structure
*/
static inline u32 mdss_dsi_is_pll_src_pll0(struct dsi_shared_data *sdata)
static inline bool mdss_dsi_is_pll_src_pll0(struct dsi_shared_data *sdata)
{
return sdata->pll_src_config == PLL_SRC_0;
}
@ -618,11 +634,21 @@ static inline u32 mdss_dsi_is_pll_src_pll0(struct dsi_shared_data *sdata)
*
* @sdata: pointer to DSI shared data structure
*/
static inline u32 mdss_dsi_is_pll_src_pll1(struct dsi_shared_data *sdata)
static inline bool mdss_dsi_is_pll_src_pll1(struct dsi_shared_data *sdata)
{
return sdata->pll_src_config == PLL_SRC_1;
}
static inline bool mdss_dsi_is_dsi0_active(struct dsi_shared_data *sdata)
{
return sdata->dsi0_active;
}
static inline bool mdss_dsi_is_dsi1_active(struct dsi_shared_data *sdata)
{
return sdata->dsi1_active;
}
static inline bool mdss_dsi_sync_wait_enable(struct mdss_dsi_ctrl_pdata *ctrl)
{
return ctrl->cmd_sync_wait_broadcast;