diff options
Diffstat (limited to 'drivers/media/platform/soc_camera/soc_camera.c')
-rw-r--r-- | drivers/media/platform/soc_camera/soc_camera.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 387a232d95a4..4b8c024fc487 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c | |||
@@ -71,13 +71,23 @@ static int video_dev_create(struct soc_camera_device *icd); | |||
71 | int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, | 71 | int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, |
72 | struct v4l2_clk *clk) | 72 | struct v4l2_clk *clk) |
73 | { | 73 | { |
74 | int ret = clk ? v4l2_clk_enable(clk) : 0; | 74 | int ret; |
75 | if (ret < 0) { | 75 | bool clock_toggle; |
76 | dev_err(dev, "Cannot enable clock: %d\n", ret); | 76 | |
77 | return ret; | 77 | if (clk && (!ssdd->unbalanced_power || |
78 | !test_and_set_bit(0, &ssdd->clock_state))) { | ||
79 | ret = v4l2_clk_enable(clk); | ||
80 | if (ret < 0) { | ||
81 | dev_err(dev, "Cannot enable clock: %d\n", ret); | ||
82 | return ret; | ||
83 | } | ||
84 | clock_toggle = true; | ||
85 | } else { | ||
86 | clock_toggle = false; | ||
78 | } | 87 | } |
79 | ret = regulator_bulk_enable(ssdd->num_regulators, | 88 | |
80 | ssdd->regulators); | 89 | ret = regulator_bulk_enable(ssdd->sd_pdata.num_regulators, |
90 | ssdd->sd_pdata.regulators); | ||
81 | if (ret < 0) { | 91 | if (ret < 0) { |
82 | dev_err(dev, "Cannot enable regulators\n"); | 92 | dev_err(dev, "Cannot enable regulators\n"); |
83 | goto eregenable; | 93 | goto eregenable; |
@@ -95,10 +105,10 @@ int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, | |||
95 | return 0; | 105 | return 0; |
96 | 106 | ||
97 | epwron: | 107 | epwron: |
98 | regulator_bulk_disable(ssdd->num_regulators, | 108 | regulator_bulk_disable(ssdd->sd_pdata.num_regulators, |
99 | ssdd->regulators); | 109 | ssdd->sd_pdata.regulators); |
100 | eregenable: | 110 | eregenable: |
101 | if (clk) | 111 | if (clock_toggle) |
102 | v4l2_clk_disable(clk); | 112 | v4l2_clk_disable(clk); |
103 | 113 | ||
104 | return ret; | 114 | return ret; |
@@ -120,14 +130,14 @@ int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd | |||
120 | } | 130 | } |
121 | } | 131 | } |
122 | 132 | ||
123 | err = regulator_bulk_disable(ssdd->num_regulators, | 133 | err = regulator_bulk_disable(ssdd->sd_pdata.num_regulators, |
124 | ssdd->regulators); | 134 | ssdd->sd_pdata.regulators); |
125 | if (err < 0) { | 135 | if (err < 0) { |
126 | dev_err(dev, "Cannot disable regulators\n"); | 136 | dev_err(dev, "Cannot disable regulators\n"); |
127 | ret = ret ? : err; | 137 | ret = ret ? : err; |
128 | } | 138 | } |
129 | 139 | ||
130 | if (clk) | 140 | if (clk && (!ssdd->unbalanced_power || test_and_clear_bit(0, &ssdd->clock_state))) |
131 | v4l2_clk_disable(clk); | 141 | v4l2_clk_disable(clk); |
132 | 142 | ||
133 | return ret; | 143 | return ret; |
@@ -137,8 +147,8 @@ EXPORT_SYMBOL(soc_camera_power_off); | |||
137 | int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd) | 147 | int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd) |
138 | { | 148 | { |
139 | /* Should not have any effect in synchronous case */ | 149 | /* Should not have any effect in synchronous case */ |
140 | return devm_regulator_bulk_get(dev, ssdd->num_regulators, | 150 | return devm_regulator_bulk_get(dev, ssdd->sd_pdata.num_regulators, |
141 | ssdd->regulators); | 151 | ssdd->sd_pdata.regulators); |
142 | } | 152 | } |
143 | EXPORT_SYMBOL(soc_camera_power_init); | 153 | EXPORT_SYMBOL(soc_camera_power_init); |
144 | 154 | ||
@@ -1346,8 +1356,8 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd, | |||
1346 | * soc_camera_pdrv_probe(), make sure the subdevice driver doesn't try | 1356 | * soc_camera_pdrv_probe(), make sure the subdevice driver doesn't try |
1347 | * to allocate them again. | 1357 | * to allocate them again. |
1348 | */ | 1358 | */ |
1349 | ssdd->num_regulators = 0; | 1359 | ssdd->sd_pdata.num_regulators = 0; |
1350 | ssdd->regulators = NULL; | 1360 | ssdd->sd_pdata.regulators = NULL; |
1351 | shd->board_info->platform_data = ssdd; | 1361 | shd->board_info->platform_data = ssdd; |
1352 | 1362 | ||
1353 | snprintf(clk_name, sizeof(clk_name), "%d-%04x", | 1363 | snprintf(clk_name, sizeof(clk_name), "%d-%04x", |
@@ -2020,8 +2030,8 @@ static int soc_camera_pdrv_probe(struct platform_device *pdev) | |||
2020 | * that case regulators are attached to the I2C device and not to the | 2030 | * that case regulators are attached to the I2C device and not to the |
2021 | * camera platform device. | 2031 | * camera platform device. |
2022 | */ | 2032 | */ |
2023 | ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators, | 2033 | ret = devm_regulator_bulk_get(&pdev->dev, ssdd->sd_pdata.num_regulators, |
2024 | ssdd->regulators); | 2034 | ssdd->sd_pdata.regulators); |
2025 | if (ret < 0) | 2035 | if (ret < 0) |
2026 | return ret; | 2036 | return ret; |
2027 | 2037 | ||