diff options
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c')
| -rw-r--r-- | drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 131 | 
1 files changed, 51 insertions, 80 deletions
| diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index a75fcb113172..3eb89f1eb0e1 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -14,7 +14,6 @@  #include <linux/phy/phy-mipi-dphy.h>  #include <linux/phy/phy.h>  #include <linux/platform_device.h> -#include <linux/pm_runtime.h>  #include <linux/regmap.h>  #include <linux/regulator/consumer.h>  #include <linux/reset.h> @@ -27,7 +26,6 @@  #include <drm/drm_probe_helper.h>  #include "sun4i_crtc.h" -#include "sun4i_drv.h"  #include "sun4i_tcon.h"  #include "sun6i_mipi_dsi.h" @@ -719,13 +717,34 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)  	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;  	struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);  	struct mipi_dsi_device *device = dsi->device; -	union phy_configure_opts opts = { 0 }; +	union phy_configure_opts opts = { };  	struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;  	u16 delay; +	int err;  	DRM_DEBUG_DRIVER("Enabling DSI output\n"); -	pm_runtime_get_sync(dsi->dev); +	err = regulator_enable(dsi->regulator); +	if (err) +		dev_warn(dsi->dev, "failed to enable VCC-DSI supply: %d\n", err); + +	reset_control_deassert(dsi->reset); +	clk_prepare_enable(dsi->mod_clk); + +	/* +	 * Enable the DSI block. +	 */ +	regmap_write(dsi->regs, SUN6I_DSI_CTL_REG, SUN6I_DSI_CTL_EN); + +	regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG, +		     SUN6I_DSI_BASIC_CTL0_ECC_EN | SUN6I_DSI_BASIC_CTL0_CRC_EN); + +	regmap_write(dsi->regs, SUN6I_DSI_TRANS_START_REG, 10); +	regmap_write(dsi->regs, SUN6I_DSI_TRANS_ZERO_REG, 0); + +	sun6i_dsi_inst_init(dsi, dsi->device); + +	regmap_write(dsi->regs, SUN6I_DSI_DEBUG_DATA_REG, 0xff);  	delay = sun6i_dsi_get_video_start_delay(dsi, mode);  	regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL1_REG, @@ -749,7 +768,7 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)  	phy_configure(dsi->dphy, &opts);  	phy_power_on(dsi->dphy); -	if (!IS_ERR(dsi->panel)) +	if (dsi->panel)  		drm_panel_prepare(dsi->panel);  	/* @@ -764,7 +783,7 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)  	 * ordering on the panels I've tested it with, so I guess this  	 * will do for now, until that IP is better understood.  	 */ -	if (!IS_ERR(dsi->panel)) +	if (dsi->panel)  		drm_panel_enable(dsi->panel);  	sun6i_dsi_start(dsi, DSI_START_HSC); @@ -780,7 +799,7 @@ static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder)  	DRM_DEBUG_DRIVER("Disabling DSI output\n"); -	if (!IS_ERR(dsi->panel)) { +	if (dsi->panel) {  		drm_panel_disable(dsi->panel);  		drm_panel_unprepare(dsi->panel);  	} @@ -788,7 +807,9 @@ static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder)  	phy_power_off(dsi->dphy);  	phy_exit(dsi->dphy); -	pm_runtime_put(dsi->dev); +	clk_disable_unprepare(dsi->mod_clk); +	reset_control_assert(dsi->reset); +	regulator_disable(dsi->regulator);  }  static int sun6i_dsi_get_modes(struct drm_connector *connector) @@ -805,7 +826,10 @@ static struct drm_connector_helper_funcs sun6i_dsi_connector_helper_funcs = {  static enum drm_connector_status  sun6i_dsi_connector_detect(struct drm_connector *connector, bool force)  { -	return connector_status_connected; +	struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector); + +	return dsi->panel ? connector_status_connected : +			    connector_status_disconnected;  }  static const struct drm_connector_funcs sun6i_dsi_connector_funcs = { @@ -942,11 +966,18 @@ static int sun6i_dsi_attach(struct mipi_dsi_host *host,  			    struct mipi_dsi_device *device)  {  	struct sun6i_dsi *dsi = host_to_sun6i_dsi(host); +	struct drm_panel *panel = of_drm_find_panel(device->dev.of_node); +	if (IS_ERR(panel)) +		return PTR_ERR(panel); +	if (!dsi->drm || !dsi->drm->registered) +		return -EPROBE_DEFER; + +	dsi->panel = panel;  	dsi->device = device; -	dsi->panel = of_drm_find_panel(device->dev.of_node); -	if (IS_ERR(dsi->panel)) -		return PTR_ERR(dsi->panel); + +	drm_panel_attach(dsi->panel, &dsi->connector); +	drm_kms_helper_hotplug_event(dsi->drm);  	dev_info(host->dev, "Attached device %s\n", device->name); @@ -957,10 +988,14 @@ static int sun6i_dsi_detach(struct mipi_dsi_host *host,  			    struct mipi_dsi_device *device)  {  	struct sun6i_dsi *dsi = host_to_sun6i_dsi(host); +	struct drm_panel *panel = dsi->panel;  	dsi->panel = NULL;  	dsi->device = NULL; +	drm_panel_detach(panel); +	drm_kms_helper_hotplug_event(dsi->drm); +  	return 0;  } @@ -1022,15 +1057,9 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,  			 void *data)  {  	struct drm_device *drm = data; -	struct sun4i_drv *drv = drm->dev_private;  	struct sun6i_dsi *dsi = dev_get_drvdata(dev);  	int ret; -	if (!dsi->panel) -		return -EPROBE_DEFER; - -	dsi->drv = drv; -  	drm_encoder_helper_add(&dsi->encoder,  			       &sun6i_dsi_enc_helper_funcs);  	ret = drm_encoder_init(drm, @@ -1056,7 +1085,8 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,  	}  	drm_connector_attach_encoder(&dsi->connector, &dsi->encoder); -	drm_panel_attach(dsi->panel, &dsi->connector); + +	dsi->drm = drm;  	return 0; @@ -1070,7 +1100,7 @@ static void sun6i_dsi_unbind(struct device *dev, struct device *master,  {  	struct sun6i_dsi *dsi = dev_get_drvdata(dev); -	drm_panel_detach(dsi->panel); +	dsi->drm = NULL;  }  static const struct component_ops sun6i_dsi_ops = { @@ -1157,12 +1187,10 @@ static int sun6i_dsi_probe(struct platform_device *pdev)  		goto err_unprotect_clk;  	} -	pm_runtime_enable(dev); -  	ret = mipi_dsi_host_register(&dsi->host);  	if (ret) {  		dev_err(dev, "Couldn't register MIPI-DSI host\n"); -		goto err_pm_disable; +		goto err_unprotect_clk;  	}  	ret = component_add(&pdev->dev, &sun6i_dsi_ops); @@ -1175,8 +1203,6 @@ static int sun6i_dsi_probe(struct platform_device *pdev)  err_remove_dsi_host:  	mipi_dsi_host_unregister(&dsi->host); -err_pm_disable: -	pm_runtime_disable(dev);  err_unprotect_clk:  	clk_rate_exclusive_put(dsi->mod_clk);  err_attach_clk: @@ -1192,7 +1218,6 @@ static int sun6i_dsi_remove(struct platform_device *pdev)  	component_del(&pdev->dev, &sun6i_dsi_ops);  	mipi_dsi_host_unregister(&dsi->host); -	pm_runtime_disable(dev);  	clk_rate_exclusive_put(dsi->mod_clk);  	if (!IS_ERR(dsi->bus_clk)) @@ -1201,59 +1226,6 @@ static int sun6i_dsi_remove(struct platform_device *pdev)  	return 0;  } -static int __maybe_unused sun6i_dsi_runtime_resume(struct device *dev) -{ -	struct sun6i_dsi *dsi = dev_get_drvdata(dev); -	int err; - -	err = regulator_enable(dsi->regulator); -	if (err) { -		dev_err(dsi->dev, "failed to enable VCC-DSI supply: %d\n", err); -		return err; -	} - -	reset_control_deassert(dsi->reset); -	clk_prepare_enable(dsi->mod_clk); - -	/* -	 * Enable the DSI block. -	 * -	 * Some part of it can only be done once we get a number of -	 * lanes, see sun6i_dsi_inst_init -	 */ -	regmap_write(dsi->regs, SUN6I_DSI_CTL_REG, SUN6I_DSI_CTL_EN); - -	regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG, -		     SUN6I_DSI_BASIC_CTL0_ECC_EN | SUN6I_DSI_BASIC_CTL0_CRC_EN); - -	regmap_write(dsi->regs, SUN6I_DSI_TRANS_START_REG, 10); -	regmap_write(dsi->regs, SUN6I_DSI_TRANS_ZERO_REG, 0); - -	if (dsi->device) -		sun6i_dsi_inst_init(dsi, dsi->device); - -	regmap_write(dsi->regs, SUN6I_DSI_DEBUG_DATA_REG, 0xff); - -	return 0; -} - -static int __maybe_unused sun6i_dsi_runtime_suspend(struct device *dev) -{ -	struct sun6i_dsi *dsi = dev_get_drvdata(dev); - -	clk_disable_unprepare(dsi->mod_clk); -	reset_control_assert(dsi->reset); -	regulator_disable(dsi->regulator); - -	return 0; -} - -static const struct dev_pm_ops sun6i_dsi_pm_ops = { -	SET_RUNTIME_PM_OPS(sun6i_dsi_runtime_suspend, -			   sun6i_dsi_runtime_resume, -			   NULL) -}; -  static const struct of_device_id sun6i_dsi_of_table[] = {  	{ .compatible = "allwinner,sun6i-a31-mipi-dsi" },  	{ .compatible = "allwinner,sun50i-a64-mipi-dsi" }, @@ -1267,7 +1239,6 @@ static struct platform_driver sun6i_dsi_platform_driver = {  	.driver		= {  		.name		= "sun6i-mipi-dsi",  		.of_match_table	= sun6i_dsi_of_table, -		.pm		= &sun6i_dsi_pm_ops,  	},  };  module_platform_driver(sun6i_dsi_platform_driver); |