diff options
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/dsi_host.c')
| -rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_host.c | 120 | 
1 files changed, 67 insertions, 53 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 649d20d29f92..de0400923303 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -15,6 +15,7 @@  #include <linux/delay.h>  #include <linux/err.h>  #include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/interrupt.h>  #include <linux/of_device.h>  #include <linux/of_gpio.h> @@ -36,35 +37,19 @@  #define DSI_6G_REG_SHIFT	4 -#define DSI_REGULATOR_MAX	8 -struct dsi_reg_entry { -	char name[32]; -	int min_voltage; -	int max_voltage; -	int enable_load; -	int disable_load; -}; - -struct dsi_reg_config { -	int num; -	struct dsi_reg_entry regs[DSI_REGULATOR_MAX]; -}; -  struct dsi_config {  	u32 major;  	u32 minor;  	u32 io_offset; -	enum msm_dsi_phy_type phy_type;  	struct dsi_reg_config reg_cfg;  };  static const struct dsi_config dsi_cfgs[] = { -	{MSM_DSI_VER_MAJOR_V2, 0, 0, MSM_DSI_PHY_UNKNOWN}, +	{MSM_DSI_VER_MAJOR_V2, 0, 0, {0,} },  	{ /* 8974 v1 */  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_0,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -79,7 +64,6 @@ static const struct dsi_config dsi_cfgs[] = {  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_1,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -94,7 +78,6 @@ static const struct dsi_config dsi_cfgs[] = {  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_1_1,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -109,7 +92,6 @@ static const struct dsi_config dsi_cfgs[] = {  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_2,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -124,7 +106,6 @@ static const struct dsi_config dsi_cfgs[] = {  		.major = MSM_DSI_VER_MAJOR_6G,  		.minor = MSM_DSI_6G_VER_MINOR_V1_3_1,  		.io_offset = DSI_6G_REG_SHIFT, -		.phy_type = MSM_DSI_PHY_28NM,  		.reg_cfg = {  			.num = 4,  			.regs = { @@ -197,7 +178,7 @@ struct msm_dsi_host {  	int id;  	void __iomem *ctrl_base; -	struct regulator_bulk_data supplies[DSI_REGULATOR_MAX]; +	struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX];  	struct clk *mdp_core_clk;  	struct clk *ahb_clk;  	struct clk *axi_clk; @@ -205,6 +186,9 @@ struct msm_dsi_host {  	struct clk *byte_clk;  	struct clk *esc_clk;  	struct clk *pixel_clk; +	struct clk *byte_clk_src; +	struct clk *pixel_clk_src; +  	u32 byte_clk_rate;  	struct gpio_desc *disp_en_gpio; @@ -273,7 +257,7 @@ static const struct dsi_config *dsi_get_config(struct msm_dsi_host *msm_host)  	u32 major = 0, minor = 0;  	gdsc_reg = regulator_get(&msm_host->pdev->dev, "gdsc"); -	if (IS_ERR_OR_NULL(gdsc_reg)) { +	if (IS_ERR(gdsc_reg)) {  		pr_err("%s: cannot get gdsc\n", __func__);  		goto fail;  	} @@ -463,6 +447,22 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)  		goto exit;  	} +	msm_host->byte_clk_src = devm_clk_get(dev, "byte_clk_src"); +	if (IS_ERR(msm_host->byte_clk_src)) { +		ret = PTR_ERR(msm_host->byte_clk_src); +		pr_err("%s: can't find byte_clk_src. ret=%d\n", __func__, ret); +		msm_host->byte_clk_src = NULL; +		goto exit; +	} + +	msm_host->pixel_clk_src = devm_clk_get(dev, "pixel_clk_src"); +	if (IS_ERR(msm_host->pixel_clk_src)) { +		ret = PTR_ERR(msm_host->pixel_clk_src); +		pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret); +		msm_host->pixel_clk_src = NULL; +		goto exit; +	} +  exit:  	return ret;  } @@ -787,6 +787,11 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,  		dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,  			DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_0123));  	} + +	if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) +		dsi_write(msm_host, REG_DSI_LANE_CTRL, +			DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST); +  	data |= DSI_CTRL_ENABLE;  	dsi_write(msm_host, REG_DSI_CTRL, data); @@ -1345,36 +1350,19 @@ static irqreturn_t dsi_host_irq(int irq, void *ptr)  static int dsi_host_init_panel_gpios(struct msm_dsi_host *msm_host,  			struct device *panel_device)  { -	int ret; - -	msm_host->disp_en_gpio = devm_gpiod_get(panel_device, -						"disp-enable"); +	msm_host->disp_en_gpio = devm_gpiod_get_optional(panel_device, +							 "disp-enable", +							 GPIOD_OUT_LOW);  	if (IS_ERR(msm_host->disp_en_gpio)) {  		DBG("cannot get disp-enable-gpios %ld",  				PTR_ERR(msm_host->disp_en_gpio)); -		msm_host->disp_en_gpio = NULL; -	} -	if (msm_host->disp_en_gpio) { -		ret = gpiod_direction_output(msm_host->disp_en_gpio, 0); -		if (ret) { -			pr_err("cannot set dir to disp-en-gpios %d\n", ret); -			return ret; -		} +		return PTR_ERR(msm_host->disp_en_gpio);  	} -	msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te"); +	msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te", GPIOD_IN);  	if (IS_ERR(msm_host->te_gpio)) {  		DBG("cannot get disp-te-gpios %ld", PTR_ERR(msm_host->te_gpio)); -		msm_host->te_gpio = NULL; -	} - -	if (msm_host->te_gpio) { -		ret = gpiod_direction_input(msm_host->te_gpio); -		if (ret) { -			pr_err("%s: cannot set dir to disp-te-gpios, %d\n", -				__func__, ret); -			return ret; -		} +		return PTR_ERR(msm_host->te_gpio);  	}  	return 0; @@ -1508,13 +1496,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)  	msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0);  	INIT_WORK(&msm_host->err_work, dsi_err_worker); -	msm_dsi->phy = msm_dsi_phy_init(pdev, msm_host->cfg->phy_type, -					msm_host->id); -	if (!msm_dsi->phy) { -		ret = -EINVAL; -		pr_err("%s: phy init failed\n", __func__); -		goto fail; -	}  	msm_dsi->host = &msm_host->base;  	msm_dsi->id = msm_host->id; @@ -1824,6 +1805,39 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 iova, u32 len)  	wmb();  } +int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, +	struct msm_dsi_pll *src_pll) +{ +	struct msm_dsi_host *msm_host = to_msm_dsi_host(host); +	struct clk *byte_clk_provider, *pixel_clk_provider; +	int ret; + +	ret = msm_dsi_pll_get_clk_provider(src_pll, +				&byte_clk_provider, &pixel_clk_provider); +	if (ret) { +		pr_info("%s: can't get provider from pll, don't set parent\n", +			__func__); +		return 0; +	} + +	ret = clk_set_parent(msm_host->byte_clk_src, byte_clk_provider); +	if (ret) { +		pr_err("%s: can't set parent to byte_clk_src. ret=%d\n", +			__func__, ret); +		goto exit; +	} + +	ret = clk_set_parent(msm_host->pixel_clk_src, pixel_clk_provider); +	if (ret) { +		pr_err("%s: can't set parent to pixel_clk_src. ret=%d\n", +			__func__, ret); +		goto exit; +	} + +exit: +	return ret; +} +  int msm_dsi_host_enable(struct mipi_dsi_host *host)  {  	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);  |