aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2017-01-11 11:09:50 -0500
committerBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>2017-01-11 11:09:50 -0500
commita3accfd70e166af4956a686ffcdf414702c0a13e (patch)
tree16452cb7831c0d3ac5ded55e7a3da455145e9567
parent8aac7f34369726d1a158788ae8aff3002d5eb528 (diff)
video: fbdev: simplefb: Separate clk / regulator get and enable steps
Currently when a simplefb needs both clocks and regulators and one of the regulators returns -EPROBE_DEFER when we try to get it, we end up disabling the clocks. This causes the screen to go blank; and in some cases my cause hardware state to be lost resulting in the framebuffer not working at all. This commit splits the get and enable steps and only enables clocks and regulators after successfully getting all of them, fixing the disabling of the clocks which were left enabled by the firmware setting up the simplefb. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-rw-r--r--drivers/video/fbdev/simplefb.c56
1 files changed, 40 insertions, 16 deletions
diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
index 61f799a515dc..a3c44ecf4523 100644
--- a/drivers/video/fbdev/simplefb.c
+++ b/drivers/video/fbdev/simplefb.c
@@ -180,10 +180,12 @@ static int simplefb_parse_pd(struct platform_device *pdev,
180struct simplefb_par { 180struct simplefb_par {
181 u32 palette[PSEUDO_PALETTE_SIZE]; 181 u32 palette[PSEUDO_PALETTE_SIZE];
182#if defined CONFIG_OF && defined CONFIG_COMMON_CLK 182#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
183 bool clks_enabled;
183 unsigned int clk_count; 184 unsigned int clk_count;
184 struct clk **clks; 185 struct clk **clks;
185#endif 186#endif
186#if defined CONFIG_OF && defined CONFIG_REGULATOR 187#if defined CONFIG_OF && defined CONFIG_REGULATOR
188 bool regulators_enabled;
187 u32 regulator_count; 189 u32 regulator_count;
188 struct regulator **regulators; 190 struct regulator **regulators;
189#endif 191#endif
@@ -208,12 +210,12 @@ struct simplefb_par {
208 * the fb probe will not help us much either. So just complain and carry on, 210 * the fb probe will not help us much either. So just complain and carry on,
209 * and hope that the user actually gets a working fb at the end of things. 211 * and hope that the user actually gets a working fb at the end of things.
210 */ 212 */
211static int simplefb_clocks_init(struct simplefb_par *par, 213static int simplefb_clocks_get(struct simplefb_par *par,
212 struct platform_device *pdev) 214 struct platform_device *pdev)
213{ 215{
214 struct device_node *np = pdev->dev.of_node; 216 struct device_node *np = pdev->dev.of_node;
215 struct clk *clock; 217 struct clk *clock;
216 int i, ret; 218 int i;
217 219
218 if (dev_get_platdata(&pdev->dev) || !np) 220 if (dev_get_platdata(&pdev->dev) || !np)
219 return 0; 221 return 0;
@@ -244,6 +246,14 @@ static int simplefb_clocks_init(struct simplefb_par *par,
244 par->clks[i] = clock; 246 par->clks[i] = clock;
245 } 247 }
246 248
249 return 0;
250}
251
252static void simplefb_clocks_enable(struct simplefb_par *par,
253 struct platform_device *pdev)
254{
255 int i, ret;
256
247 for (i = 0; i < par->clk_count; i++) { 257 for (i = 0; i < par->clk_count; i++) {
248 if (par->clks[i]) { 258 if (par->clks[i]) {
249 ret = clk_prepare_enable(par->clks[i]); 259 ret = clk_prepare_enable(par->clks[i]);
@@ -256,8 +266,7 @@ static int simplefb_clocks_init(struct simplefb_par *par,
256 } 266 }
257 } 267 }
258 } 268 }
259 269 par->clks_enabled = true;
260 return 0;
261} 270}
262 271
263static void simplefb_clocks_destroy(struct simplefb_par *par) 272static void simplefb_clocks_destroy(struct simplefb_par *par)
@@ -269,7 +278,8 @@ static void simplefb_clocks_destroy(struct simplefb_par *par)
269 278
270 for (i = 0; i < par->clk_count; i++) { 279 for (i = 0; i < par->clk_count; i++) {
271 if (par->clks[i]) { 280 if (par->clks[i]) {
272 clk_disable_unprepare(par->clks[i]); 281 if (par->clks_enabled)
282 clk_disable_unprepare(par->clks[i]);
273 clk_put(par->clks[i]); 283 clk_put(par->clks[i]);
274 } 284 }
275 } 285 }
@@ -277,8 +287,10 @@ static void simplefb_clocks_destroy(struct simplefb_par *par)
277 kfree(par->clks); 287 kfree(par->clks);
278} 288}
279#else 289#else
280static int simplefb_clocks_init(struct simplefb_par *par, 290static int simplefb_clocks_get(struct simplefb_par *par,
281 struct platform_device *pdev) { return 0; } 291 struct platform_device *pdev) { return 0; }
292static void simplefb_clocks_enable(struct simplefb_par *par,
293 struct platform_device *pdev) { }
282static void simplefb_clocks_destroy(struct simplefb_par *par) { } 294static void simplefb_clocks_destroy(struct simplefb_par *par) { }
283#endif 295#endif
284 296
@@ -305,14 +317,14 @@ static void simplefb_clocks_destroy(struct simplefb_par *par) { }
305 * the fb probe will not help us much either. So just complain and carry on, 317 * the fb probe will not help us much either. So just complain and carry on,
306 * and hope that the user actually gets a working fb at the end of things. 318 * and hope that the user actually gets a working fb at the end of things.
307 */ 319 */
308static int simplefb_regulators_init(struct simplefb_par *par, 320static int simplefb_regulators_get(struct simplefb_par *par,
309 struct platform_device *pdev) 321 struct platform_device *pdev)
310{ 322{
311 struct device_node *np = pdev->dev.of_node; 323 struct device_node *np = pdev->dev.of_node;
312 struct property *prop; 324 struct property *prop;
313 struct regulator *regulator; 325 struct regulator *regulator;
314 const char *p; 326 const char *p;
315 int count = 0, i = 0, ret; 327 int count = 0, i = 0;
316 328
317 if (dev_get_platdata(&pdev->dev) || !np) 329 if (dev_get_platdata(&pdev->dev) || !np)
318 return 0; 330 return 0;
@@ -354,6 +366,14 @@ static int simplefb_regulators_init(struct simplefb_par *par,
354 } 366 }
355 par->regulator_count = i; 367 par->regulator_count = i;
356 368
369 return 0;
370}
371
372static void simplefb_regulators_enable(struct simplefb_par *par,
373 struct platform_device *pdev)
374{
375 int i, ret;
376
357 /* Enable all the regulators */ 377 /* Enable all the regulators */
358 for (i = 0; i < par->regulator_count; i++) { 378 for (i = 0; i < par->regulator_count; i++) {
359 ret = regulator_enable(par->regulators[i]); 379 ret = regulator_enable(par->regulators[i]);
@@ -365,15 +385,14 @@ static int simplefb_regulators_init(struct simplefb_par *par,
365 par->regulators[i] = NULL; 385 par->regulators[i] = NULL;
366 } 386 }
367 } 387 }
368 388 par->regulators_enabled = true;
369 return 0;
370} 389}
371 390
372static void simplefb_regulators_destroy(struct simplefb_par *par) 391static void simplefb_regulators_destroy(struct simplefb_par *par)
373{ 392{
374 int i; 393 int i;
375 394
376 if (!par->regulators) 395 if (!par->regulators || !par->regulators_enabled)
377 return; 396 return;
378 397
379 for (i = 0; i < par->regulator_count; i++) 398 for (i = 0; i < par->regulator_count; i++)
@@ -381,8 +400,10 @@ static void simplefb_regulators_destroy(struct simplefb_par *par)
381 regulator_disable(par->regulators[i]); 400 regulator_disable(par->regulators[i]);
382} 401}
383#else 402#else
384static int simplefb_regulators_init(struct simplefb_par *par, 403static int simplefb_regulators_get(struct simplefb_par *par,
385 struct platform_device *pdev) { return 0; } 404 struct platform_device *pdev) { return 0; }
405static void simplefb_regulators_enable(struct simplefb_par *par,
406 struct platform_device *pdev) { }
386static void simplefb_regulators_destroy(struct simplefb_par *par) { } 407static void simplefb_regulators_destroy(struct simplefb_par *par) { }
387#endif 408#endif
388 409
@@ -453,14 +474,17 @@ static int simplefb_probe(struct platform_device *pdev)
453 } 474 }
454 info->pseudo_palette = par->palette; 475 info->pseudo_palette = par->palette;
455 476
456 ret = simplefb_clocks_init(par, pdev); 477 ret = simplefb_clocks_get(par, pdev);
457 if (ret < 0) 478 if (ret < 0)
458 goto error_unmap; 479 goto error_unmap;
459 480
460 ret = simplefb_regulators_init(par, pdev); 481 ret = simplefb_regulators_get(par, pdev);
461 if (ret < 0) 482 if (ret < 0)
462 goto error_clocks; 483 goto error_clocks;
463 484
485 simplefb_clocks_enable(par, pdev);
486 simplefb_regulators_enable(par, pdev);
487
464 dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n", 488 dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n",
465 info->fix.smem_start, info->fix.smem_len, 489 info->fix.smem_start, info->fix.smem_len,
466 info->screen_base); 490 info->screen_base);