diff options
Diffstat (limited to 'drivers/staging/imx-drm/imx-tve.c')
| -rw-r--r-- | drivers/staging/imx-drm/imx-tve.c | 149 | 
1 files changed, 66 insertions, 83 deletions
diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c index 33d6525cf99..c628fcdc22a 100644 --- a/drivers/staging/imx-drm/imx-tve.c +++ b/drivers/staging/imx-drm/imx-tve.c @@ -20,6 +20,7 @@  #include <linux/clk.h>  #include <linux/clk-provider.h> +#include <linux/component.h>  #include <linux/module.h>  #include <linux/i2c.h>  #include <linux/regmap.h> @@ -29,6 +30,7 @@  #include <drm/drmP.h>  #include <drm/drm_fb_helper.h>  #include <drm/drm_crtc_helper.h> +#include <video/imx-ipu-v3.h>  #include "imx-drm.h" @@ -110,11 +112,8 @@ enum {  struct imx_tve {  	struct drm_connector connector; -	struct imx_drm_connector *imx_drm_connector;  	struct drm_encoder encoder; -	struct imx_drm_encoder *imx_drm_encoder;  	struct device *dev; -	spinlock_t enable_lock;	/* serializes tve_enable/disable */  	spinlock_t lock;	/* register lock */  	bool enabled;  	int mode; @@ -146,12 +145,10 @@ __releases(&tve->lock)  static void tve_enable(struct imx_tve *tve)  { -	unsigned long flags;  	int ret; -	spin_lock_irqsave(&tve->enable_lock, flags);  	if (!tve->enabled) { -		tve->enabled = 1; +		tve->enabled = true;  		clk_prepare_enable(tve->clk);  		ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,  					 TVE_IPU_CLK_EN | TVE_EN, @@ -169,23 +166,18 @@ static void tve_enable(struct imx_tve *tve)  			     TVE_CD_SM_IEN |  			     TVE_CD_LM_IEN |  			     TVE_CD_MON_END_IEN); - -	spin_unlock_irqrestore(&tve->enable_lock, flags);  }  static void tve_disable(struct imx_tve *tve)  { -	unsigned long flags;  	int ret; -	spin_lock_irqsave(&tve->enable_lock, flags);  	if (tve->enabled) { -		tve->enabled = 0; +		tve->enabled = false;  		ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,  					 TVE_IPU_CLK_EN | TVE_EN, 0);  		clk_disable_unprepare(tve->clk);  	} -	spin_unlock_irqrestore(&tve->enable_lock, flags);  }  static int tve_setup_tvout(struct imx_tve *tve) @@ -233,11 +225,6 @@ static enum drm_connector_status imx_tve_connector_detect(  	return connector_status_connected;  } -static void imx_tve_connector_destroy(struct drm_connector *connector) -{ -	/* do not free here */ -} -  static int imx_tve_connector_get_modes(struct drm_connector *connector)  {  	struct imx_tve *tve = con_to_tve(connector); @@ -313,13 +300,11 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder)  	switch (tve->mode) {  	case TVE_MODE_VGA: -		imx_drm_crtc_panel_format_pins(encoder->crtc, -				DRM_MODE_ENCODER_DAC, IPU_PIX_FMT_GBR24, +		imx_drm_panel_format_pins(encoder, IPU_PIX_FMT_GBR24,  				tve->hsync_pin, tve->vsync_pin);  		break;  	case TVE_MODE_TVOUT: -		imx_drm_crtc_panel_format(encoder->crtc, DRM_MODE_ENCODER_TVDAC, -					  V4L2_PIX_FMT_YUV444); +		imx_drm_panel_format(encoder, V4L2_PIX_FMT_YUV444);  		break;  	}  } @@ -372,16 +357,11 @@ static void imx_tve_encoder_disable(struct drm_encoder *encoder)  	tve_disable(tve);  } -static void imx_tve_encoder_destroy(struct drm_encoder *encoder) -{ -	/* do not free here */ -} -  static struct drm_connector_funcs imx_tve_connector_funcs = {  	.dpms = drm_helper_connector_dpms,  	.fill_modes = drm_helper_probe_single_connector_modes,  	.detect = imx_tve_connector_detect, -	.destroy = imx_tve_connector_destroy, +	.destroy = imx_drm_connector_destroy,  };  static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = { @@ -391,7 +371,7 @@ static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {  };  static struct drm_encoder_funcs imx_tve_encoder_funcs = { -	.destroy = imx_tve_encoder_destroy, +	.destroy = imx_drm_encoder_destroy,  };  static struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = { @@ -511,34 +491,27 @@ static int tve_clk_init(struct imx_tve *tve, void __iomem *base)  	return 0;  } -static int imx_tve_register(struct imx_tve *tve) +static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)  { +	int encoder_type;  	int ret; -	tve->connector.funcs = &imx_tve_connector_funcs; -	tve->encoder.funcs = &imx_tve_encoder_funcs; +	encoder_type = tve->mode == TVE_MODE_VGA ? +				DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC; -	tve->encoder.encoder_type = DRM_MODE_ENCODER_NONE; -	tve->connector.connector_type = DRM_MODE_CONNECTOR_VGA; +	ret = imx_drm_encoder_parse_of(drm, &tve->encoder, +				       tve->dev->of_node); +	if (ret) +		return ret;  	drm_encoder_helper_add(&tve->encoder, &imx_tve_encoder_helper_funcs); -	ret = imx_drm_add_encoder(&tve->encoder, &tve->imx_drm_encoder, -			THIS_MODULE); -	if (ret) { -		dev_err(tve->dev, "adding encoder failed with %d\n", ret); -		return ret; -	} +	drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs, +			 encoder_type);  	drm_connector_helper_add(&tve->connector,  			&imx_tve_connector_helper_funcs); - -	ret = imx_drm_add_connector(&tve->connector, -			&tve->imx_drm_connector, THIS_MODULE); -	if (ret) { -		imx_drm_remove_encoder(tve->imx_drm_encoder); -		dev_err(tve->dev, "adding connector failed with %d\n", ret); -		return ret; -	} +	drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs, +			   DRM_MODE_CONNECTOR_VGA);  	drm_mode_connector_attach_encoder(&tve->connector, &tve->encoder); @@ -568,7 +541,7 @@ static const char *imx_tve_modes[] = {  	[TVE_MODE_VGA] = "vga",  }; -const int of_get_tve_mode(struct device_node *np) +static const int of_get_tve_mode(struct device_node *np)  {  	const char *bm;  	int ret, i; @@ -584,9 +557,11 @@ const int of_get_tve_mode(struct device_node *np)  	return -EINVAL;  } -static int imx_tve_probe(struct platform_device *pdev) +static int imx_tve_bind(struct device *dev, struct device *master, void *data)  { -	struct device_node *np = pdev->dev.of_node; +	struct platform_device *pdev = to_platform_device(dev); +	struct drm_device *drm = data; +	struct device_node *np = dev->of_node;  	struct device_node *ddc_node;  	struct imx_tve *tve;  	struct resource *res; @@ -595,15 +570,14 @@ static int imx_tve_probe(struct platform_device *pdev)  	int irq;  	int ret; -	tve = devm_kzalloc(&pdev->dev, sizeof(*tve), GFP_KERNEL); +	tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL);  	if (!tve)  		return -ENOMEM; -	tve->dev = &pdev->dev; +	tve->dev = dev;  	spin_lock_init(&tve->lock); -	spin_lock_init(&tve->enable_lock); -	ddc_node = of_parse_phandle(np, "ddc", 0); +	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);  	if (ddc_node) {  		tve->ddc = of_find_i2c_adapter_by_node(ddc_node);  		of_node_put(ddc_node); @@ -611,7 +585,7 @@ static int imx_tve_probe(struct platform_device *pdev)  	tve->mode = of_get_tve_mode(np);  	if (tve->mode != TVE_MODE_VGA) { -		dev_err(&pdev->dev, "only VGA mode supported, currently\n"); +		dev_err(dev, "only VGA mode supported, currently\n");  		return -EINVAL;  	} @@ -620,7 +594,7 @@ static int imx_tve_probe(struct platform_device *pdev)  					   &tve->hsync_pin);  		if (ret < 0) { -			dev_err(&pdev->dev, "failed to get vsync pin\n"); +			dev_err(dev, "failed to get vsync pin\n");  			return ret;  		} @@ -628,40 +602,40 @@ static int imx_tve_probe(struct platform_device *pdev)  					    &tve->vsync_pin);  		if (ret < 0) { -			dev_err(&pdev->dev, "failed to get vsync pin\n"); +			dev_err(dev, "failed to get vsync pin\n");  			return ret;  		}  	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	base = devm_ioremap_resource(&pdev->dev, res); +	base = devm_ioremap_resource(dev, res);  	if (IS_ERR(base))  		return PTR_ERR(base);  	tve_regmap_config.lock_arg = tve; -	tve->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "tve", base, +	tve->regmap = devm_regmap_init_mmio_clk(dev, "tve", base,  						&tve_regmap_config);  	if (IS_ERR(tve->regmap)) { -		dev_err(&pdev->dev, "failed to init regmap: %ld\n", +		dev_err(dev, "failed to init regmap: %ld\n",  			PTR_ERR(tve->regmap));  		return PTR_ERR(tve->regmap);  	}  	irq = platform_get_irq(pdev, 0);  	if (irq < 0) { -		dev_err(&pdev->dev, "failed to get irq\n"); +		dev_err(dev, "failed to get irq\n");  		return irq;  	} -	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, +	ret = devm_request_threaded_irq(dev, irq, NULL,  					imx_tve_irq_handler, IRQF_ONESHOT,  					"imx-tve", tve);  	if (ret < 0) { -		dev_err(&pdev->dev, "failed to request irq: %d\n", ret); +		dev_err(dev, "failed to request irq: %d\n", ret);  		return ret;  	} -	tve->dac_reg = devm_regulator_get(&pdev->dev, "dac"); +	tve->dac_reg = devm_regulator_get(dev, "dac");  	if (!IS_ERR(tve->dac_reg)) {  		regulator_set_voltage(tve->dac_reg, 2750000, 2750000);  		ret = regulator_enable(tve->dac_reg); @@ -669,17 +643,17 @@ static int imx_tve_probe(struct platform_device *pdev)  			return ret;  	} -	tve->clk = devm_clk_get(&pdev->dev, "tve"); +	tve->clk = devm_clk_get(dev, "tve");  	if (IS_ERR(tve->clk)) { -		dev_err(&pdev->dev, "failed to get high speed tve clock: %ld\n", +		dev_err(dev, "failed to get high speed tve clock: %ld\n",  			PTR_ERR(tve->clk));  		return PTR_ERR(tve->clk);  	}  	/* this is the IPU DI clock input selector, can be parented to tve_di */ -	tve->di_sel_clk = devm_clk_get(&pdev->dev, "di_sel"); +	tve->di_sel_clk = devm_clk_get(dev, "di_sel");  	if (IS_ERR(tve->di_sel_clk)) { -		dev_err(&pdev->dev, "failed to get ipu di mux clock: %ld\n", +		dev_err(dev, "failed to get ipu di mux clock: %ld\n",  			PTR_ERR(tve->di_sel_clk));  		return PTR_ERR(tve->di_sel_clk);  	} @@ -690,42 +664,51 @@ static int imx_tve_probe(struct platform_device *pdev)  	ret = regmap_read(tve->regmap, TVE_COM_CONF_REG, &val);  	if (ret < 0) { -		dev_err(&pdev->dev, "failed to read configuration register: %d\n", ret); +		dev_err(dev, "failed to read configuration register: %d\n", ret);  		return ret;  	}  	if (val != 0x00100000) { -		dev_err(&pdev->dev, "configuration register default value indicates this is not a TVEv2\n"); +		dev_err(dev, "configuration register default value indicates this is not a TVEv2\n");  		return -ENODEV; -	}; +	}  	/* disable cable detection for VGA mode */  	ret = regmap_write(tve->regmap, TVE_CD_CONT_REG, 0); -	ret = imx_tve_register(tve); +	ret = imx_tve_register(drm, tve);  	if (ret)  		return ret; -	ret = imx_drm_encoder_add_possible_crtcs(tve->imx_drm_encoder, np); - -	platform_set_drvdata(pdev, tve); +	dev_set_drvdata(dev, tve);  	return 0;  } -static int imx_tve_remove(struct platform_device *pdev) +static void imx_tve_unbind(struct device *dev, struct device *master, +	void *data)  { -	struct imx_tve *tve = platform_get_drvdata(pdev); -	struct drm_connector *connector = &tve->connector; -	struct drm_encoder *encoder = &tve->encoder; +	struct imx_tve *tve = dev_get_drvdata(dev); -	drm_mode_connector_detach_encoder(connector, encoder); - -	imx_drm_remove_connector(tve->imx_drm_connector); -	imx_drm_remove_encoder(tve->imx_drm_encoder); +	tve->connector.funcs->destroy(&tve->connector); +	tve->encoder.funcs->destroy(&tve->encoder);  	if (!IS_ERR(tve->dac_reg))  		regulator_disable(tve->dac_reg); +} + +static const struct component_ops imx_tve_ops = { +	.bind	= imx_tve_bind, +	.unbind	= imx_tve_unbind, +}; +static int imx_tve_probe(struct platform_device *pdev) +{ +	return component_add(&pdev->dev, &imx_tve_ops); +} + +static int imx_tve_remove(struct platform_device *pdev) +{ +	component_del(&pdev->dev, &imx_tve_ops);  	return 0;  }  | 
