|
4 | 4 | */ |
5 | 5 |
|
6 | 6 | #include <linux/clk.h> |
| 7 | +#include <linux/delay.h> |
7 | 8 | #include <linux/irq.h> |
8 | 9 | #include <linux/irqchip.h> |
9 | 10 | #include <linux/irqdesc.h> |
10 | 11 | #include <linux/irqchip/chained_irq.h> |
11 | 12 | #include <linux/pm_runtime.h> |
| 13 | +#include <linux/reset.h> |
12 | 14 |
|
13 | 15 | #include "msm_drv.h" |
14 | 16 | #include "msm_kms.h" |
@@ -193,6 +195,32 @@ static void msm_mdss_destroy(struct msm_mdss *msm_mdss) |
193 | 195 | irq_set_chained_handler_and_data(irq, NULL, NULL); |
194 | 196 | } |
195 | 197 |
|
| 198 | +static int msm_mdss_reset(struct device *dev) |
| 199 | +{ |
| 200 | + struct reset_control *reset; |
| 201 | + |
| 202 | + reset = reset_control_get_optional_exclusive(dev, NULL); |
| 203 | + if (!reset) { |
| 204 | + /* Optional reset not specified */ |
| 205 | + return 0; |
| 206 | + } else if (IS_ERR(reset)) { |
| 207 | + return dev_err_probe(dev, PTR_ERR(reset), |
| 208 | + "failed to acquire mdss reset\n"); |
| 209 | + } |
| 210 | + |
| 211 | + reset_control_assert(reset); |
| 212 | + /* |
| 213 | + * Tests indicate that reset has to be held for some period of time, |
| 214 | + * make it one frame in a typical system |
| 215 | + */ |
| 216 | + msleep(20); |
| 217 | + reset_control_deassert(reset); |
| 218 | + |
| 219 | + reset_control_put(reset); |
| 220 | + |
| 221 | + return 0; |
| 222 | +} |
| 223 | + |
196 | 224 | /* |
197 | 225 | * MDP5 MDSS uses at most three specified clocks. |
198 | 226 | */ |
@@ -229,6 +257,10 @@ static struct msm_mdss *msm_mdss_init(struct platform_device *pdev, bool is_mdp5 |
229 | 257 | int ret; |
230 | 258 | int irq; |
231 | 259 |
|
| 260 | + ret = msm_mdss_reset(&pdev->dev); |
| 261 | + if (ret) |
| 262 | + return ERR_PTR(ret); |
| 263 | + |
232 | 264 | msm_mdss = devm_kzalloc(&pdev->dev, sizeof(*msm_mdss), GFP_KERNEL); |
233 | 265 | if (!msm_mdss) |
234 | 266 | return ERR_PTR(-ENOMEM); |
|
0 commit comments