Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Hans de Goede and committed by
Bartlomiej Zolnierkiewicz
a3accfd7 8aac7f34

+40 -16
+40 -16
drivers/video/fbdev/simplefb.c
··· 180 180 struct simplefb_par { 181 181 u32 palette[PSEUDO_PALETTE_SIZE]; 182 182 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK 183 + bool clks_enabled; 183 184 unsigned int clk_count; 184 185 struct clk **clks; 185 186 #endif 186 187 #if defined CONFIG_OF && defined CONFIG_REGULATOR 188 + bool regulators_enabled; 187 189 u32 regulator_count; 188 190 struct regulator **regulators; 189 191 #endif ··· 210 208 * the fb probe will not help us much either. So just complain and carry on, 211 209 * and hope that the user actually gets a working fb at the end of things. 212 210 */ 213 - static int simplefb_clocks_init(struct simplefb_par *par, 214 - struct platform_device *pdev) 211 + static int simplefb_clocks_get(struct simplefb_par *par, 212 + struct platform_device *pdev) 215 213 { 216 214 struct device_node *np = pdev->dev.of_node; 217 215 struct clk *clock; 218 - int i, ret; 216 + int i; 219 217 220 218 if (dev_get_platdata(&pdev->dev) || !np) 221 219 return 0; ··· 246 244 par->clks[i] = clock; 247 245 } 248 246 247 + return 0; 248 + } 249 + 250 + static void simplefb_clocks_enable(struct simplefb_par *par, 251 + struct platform_device *pdev) 252 + { 253 + int i, ret; 254 + 249 255 for (i = 0; i < par->clk_count; i++) { 250 256 if (par->clks[i]) { 251 257 ret = clk_prepare_enable(par->clks[i]); ··· 266 256 } 267 257 } 268 258 } 269 - 270 - return 0; 259 + par->clks_enabled = true; 271 260 } 272 261 273 262 static void simplefb_clocks_destroy(struct simplefb_par *par) ··· 278 269 279 270 for (i = 0; i < par->clk_count; i++) { 280 271 if (par->clks[i]) { 281 - clk_disable_unprepare(par->clks[i]); 272 + if (par->clks_enabled) 273 + clk_disable_unprepare(par->clks[i]); 282 274 clk_put(par->clks[i]); 283 275 } 284 276 } ··· 287 277 kfree(par->clks); 288 278 } 289 279 #else 290 - static int simplefb_clocks_init(struct simplefb_par *par, 280 + static int simplefb_clocks_get(struct simplefb_par *par, 291 281 struct platform_device *pdev) { return 0; } 282 + static void simplefb_clocks_enable(struct simplefb_par *par, 283 + struct platform_device *pdev) { } 292 284 static void simplefb_clocks_destroy(struct simplefb_par *par) { } 293 285 #endif 294 286 ··· 317 305 * the fb probe will not help us much either. So just complain and carry on, 318 306 * and hope that the user actually gets a working fb at the end of things. 319 307 */ 320 - static int simplefb_regulators_init(struct simplefb_par *par, 321 - struct platform_device *pdev) 308 + static int simplefb_regulators_get(struct simplefb_par *par, 309 + struct platform_device *pdev) 322 310 { 323 311 struct device_node *np = pdev->dev.of_node; 324 312 struct property *prop; 325 313 struct regulator *regulator; 326 314 const char *p; 327 - int count = 0, i = 0, ret; 315 + int count = 0, i = 0; 328 316 329 317 if (dev_get_platdata(&pdev->dev) || !np) 330 318 return 0; ··· 366 354 } 367 355 par->regulator_count = i; 368 356 357 + return 0; 358 + } 359 + 360 + static void simplefb_regulators_enable(struct simplefb_par *par, 361 + struct platform_device *pdev) 362 + { 363 + int i, ret; 364 + 369 365 /* Enable all the regulators */ 370 366 for (i = 0; i < par->regulator_count; i++) { 371 367 ret = regulator_enable(par->regulators[i]); ··· 385 365 par->regulators[i] = NULL; 386 366 } 387 367 } 388 - 389 - return 0; 368 + par->regulators_enabled = true; 390 369 } 391 370 392 371 static void simplefb_regulators_destroy(struct simplefb_par *par) 393 372 { 394 373 int i; 395 374 396 - if (!par->regulators) 375 + if (!par->regulators || !par->regulators_enabled) 397 376 return; 398 377 399 378 for (i = 0; i < par->regulator_count; i++) ··· 400 381 regulator_disable(par->regulators[i]); 401 382 } 402 383 #else 403 - static int simplefb_regulators_init(struct simplefb_par *par, 384 + static int simplefb_regulators_get(struct simplefb_par *par, 404 385 struct platform_device *pdev) { return 0; } 386 + static void simplefb_regulators_enable(struct simplefb_par *par, 387 + struct platform_device *pdev) { } 405 388 static void simplefb_regulators_destroy(struct simplefb_par *par) { } 406 389 #endif 407 390 ··· 474 453 } 475 454 info->pseudo_palette = par->palette; 476 455 477 - ret = simplefb_clocks_init(par, pdev); 456 + ret = simplefb_clocks_get(par, pdev); 478 457 if (ret < 0) 479 458 goto error_unmap; 480 459 481 - ret = simplefb_regulators_init(par, pdev); 460 + ret = simplefb_regulators_get(par, pdev); 482 461 if (ret < 0) 483 462 goto error_clocks; 463 + 464 + simplefb_clocks_enable(par, pdev); 465 + simplefb_regulators_enable(par, pdev); 484 466 485 467 dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n", 486 468 info->fix.smem_start, info->fix.smem_len,