diff options
Diffstat (limited to 'drivers/media/platform/exynos4-is/mipi-csis.c')
| -rw-r--r-- | drivers/media/platform/exynos4-is/mipi-csis.c | 74 | 
1 files changed, 31 insertions, 43 deletions
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index 0914230b42d..ae54ef5f535 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -20,14 +20,15 @@  #include <linux/memory.h>  #include <linux/module.h>  #include <linux/of.h> -#include <linux/platform_data/mipi-csis.h> +#include <linux/of_graph.h> +#include <linux/phy/phy.h>  #include <linux/platform_device.h>  #include <linux/pm_runtime.h>  #include <linux/regulator/consumer.h>  #include <linux/slab.h>  #include <linux/spinlock.h>  #include <linux/videodev2.h> -#include <media/s5p_fimc.h> +#include <media/exynos-fimc.h>  #include <media/v4l2-of.h>  #include <media/v4l2-subdev.h> @@ -90,7 +91,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");  #define S5PCSIS_INTSRC_ODD_BEFORE	(1 << 29)  #define S5PCSIS_INTSRC_ODD_AFTER	(1 << 28)  #define S5PCSIS_INTSRC_ODD		(0x3 << 28) -#define S5PCSIS_INTSRC_NON_IMAGE_DATA	(0xff << 28) +#define S5PCSIS_INTSRC_NON_IMAGE_DATA	(0xf << 28)  #define S5PCSIS_INTSRC_FRAME_START	(1 << 27)  #define S5PCSIS_INTSRC_FRAME_END	(1 << 26)  #define S5PCSIS_INTSRC_ERR_SOT_HS	(0xf << 12) @@ -180,6 +181,7 @@ struct csis_drvdata {   * @sd: v4l2_subdev associated with CSIS device instance   * @index: the hardware instance index   * @pdev: CSIS platform device + * @phy: pointer to the CSIS generic PHY   * @regs: mmaped I/O registers memory   * @supplies: CSIS regulator supplies   * @clock: CSIS clocks @@ -203,6 +205,7 @@ struct csis_state {  	struct v4l2_subdev sd;  	u8 index;  	struct platform_device *pdev; +	struct phy *phy;  	void __iomem *regs;  	struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];  	struct clk *clock[NUM_CSIS_CLOCKS]; @@ -726,26 +729,6 @@ static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static int s5pcsis_get_platform_data(struct platform_device *pdev, -				     struct csis_state *state) -{ -	struct s5p_platform_mipi_csis *pdata = pdev->dev.platform_data; - -	if (pdata == NULL) { -		dev_err(&pdev->dev, "Platform data not specified\n"); -		return -EINVAL; -	} - -	state->clk_frequency = pdata->clk_rate; -	state->num_lanes = pdata->lanes; -	state->hs_settle = pdata->hs_settle; -	state->index = max(0, pdev->id); -	state->max_num_lanes = state->index ? CSIS1_MAX_LANES : -					      CSIS0_MAX_LANES; -	return 0; -} - -#ifdef CONFIG_OF  static int s5pcsis_parse_dt(struct platform_device *pdev,  			    struct csis_state *state)  { @@ -759,7 +742,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev,  				 &state->max_num_lanes))  		return -EINVAL; -	node = v4l2_of_get_next_endpoint(node, NULL); +	node = of_graph_get_next_endpoint(node, NULL);  	if (!node) {  		dev_err(&pdev->dev, "No port node at %s\n",  				pdev->dev.of_node->full_name); @@ -768,7 +751,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev,  	/* Get port node and validate MIPI-CSI channel id. */  	v4l2_of_parse_endpoint(node, &endpoint); -	state->index = endpoint.port - FIMC_INPUT_MIPI_CSI2_0; +	state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0;  	if (state->index < 0 || state->index >= CSIS_MAX_ENTITIES)  		return -ENXIO; @@ -779,14 +762,12 @@ static int s5pcsis_parse_dt(struct platform_device *pdev,  					"samsung,csis-wclk");  	state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes; -  	of_node_put(node); +  	return 0;  } -#else -#define s5pcsis_parse_dt(pdev, state) (-ENOSYS) -#endif +static int s5pcsis_pm_resume(struct device *dev, bool runtime);  static const struct of_device_id s5pcsis_of_match[];  static int s5pcsis_probe(struct platform_device *pdev) @@ -807,19 +788,14 @@ static int s5pcsis_probe(struct platform_device *pdev)  	spin_lock_init(&state->slock);  	state->pdev = pdev; -	if (dev->of_node) { -		of_id = of_match_node(s5pcsis_of_match, dev->of_node); -		if (WARN_ON(of_id == NULL)) -			return -EINVAL; - -		drv_data = of_id->data; -		state->interrupt_mask = drv_data->interrupt_mask; +	of_id = of_match_node(s5pcsis_of_match, dev->of_node); +	if (WARN_ON(of_id == NULL)) +		return -EINVAL; -		ret = s5pcsis_parse_dt(pdev, state); -	} else { -		ret = s5pcsis_get_platform_data(pdev, state); -	} +	drv_data = of_id->data; +	state->interrupt_mask = drv_data->interrupt_mask; +	ret = s5pcsis_parse_dt(pdev, state);  	if (ret < 0)  		return ret; @@ -829,6 +805,10 @@ static int s5pcsis_probe(struct platform_device *pdev)  		return -EINVAL;  	} +	state->phy = devm_phy_get(dev, "csis"); +	if (IS_ERR(state->phy)) +		return PTR_ERR(state->phy); +  	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	state->regs = devm_ioremap_resource(dev, mem_res);  	if (IS_ERR(state->regs)) @@ -895,13 +875,21 @@ static int s5pcsis_probe(struct platform_device *pdev)  	/* .. and a pointer to the subdev. */  	platform_set_drvdata(pdev, &state->sd);  	memcpy(state->events, s5pcsis_events, sizeof(state->events)); +  	pm_runtime_enable(dev); +	if (!pm_runtime_enabled(dev)) { +		ret = s5pcsis_pm_resume(dev, true); +		if (ret < 0) +			goto e_m_ent; +	}  	dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n",  		 state->num_lanes, state->hs_settle, state->wclk_ext,  		 state->clk_frequency);  	return 0; +e_m_ent: +	media_entity_cleanup(&state->sd.entity);  e_clkdis:  	clk_disable(state->clock[CSIS_CLK_MUX]);  e_clkput: @@ -922,7 +910,7 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)  	mutex_lock(&state->lock);  	if (state->flags & ST_POWERED) {  		s5pcsis_stop_stream(state); -		ret = s5p_csis_phy_enable(state->index, false); +		ret = phy_power_off(state->phy);  		if (ret)  			goto unlock;  		ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES, @@ -958,7 +946,7 @@ static int s5pcsis_pm_resume(struct device *dev, bool runtime)  					    state->supplies);  		if (ret)  			goto unlock; -		ret = s5p_csis_phy_enable(state->index, true); +		ret = phy_power_on(state->phy);  		if (!ret) {  			state->flags |= ST_POWERED;  		} else { @@ -1007,7 +995,7 @@ static int s5pcsis_remove(struct platform_device *pdev)  	struct csis_state *state = sd_to_csis_state(sd);  	pm_runtime_disable(&pdev->dev); -	s5pcsis_pm_suspend(&pdev->dev, false); +	s5pcsis_pm_suspend(&pdev->dev, true);  	clk_disable(state->clock[CSIS_CLK_MUX]);  	pm_runtime_set_suspended(&pdev->dev);  	s5pcsis_clk_put(state);  | 
