Skip to content

Commit a43b933

Browse files
atseanpauldaeinki
authored andcommitted
drm/exynos: Clean up FIMD power on/off routines
This patch separates the fimd_activate function into poweron/poweroff functions to be more consistent with the other drivers in exynos drm. It also properly cleans up after failures in poweron. The functions have also been shuffled around such that they are all in the same spot in the file and poweron/poweroff can be called from the dpms function. Signed-off-by: Sean Paul <[email protected]> Signed-off-by: Inki Dae <[email protected]>
1 parent 12f5ad6 commit a43b933

File tree

1 file changed

+134
-111
lines changed

1 file changed

+134
-111
lines changed

drivers/gpu/drm/exynos/exynos_drm_fimd.c

Lines changed: 134 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,12 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
519519

520520
win_data = &ctx->win_data[win];
521521

522+
/* If suspended, enable this on resume */
523+
if (ctx->suspended) {
524+
win_data->resume = true;
525+
return;
526+
}
527+
522528
/*
523529
* SHADOWCON/PRTCON register is used for enabling timing.
524530
*
@@ -660,6 +666,129 @@ static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
660666
win_data->enabled = false;
661667
}
662668

669+
static void fimd_clear_win(struct fimd_context *ctx, int win)
670+
{
671+
writel(0, ctx->regs + WINCON(win));
672+
writel(0, ctx->regs + VIDOSD_A(win));
673+
writel(0, ctx->regs + VIDOSD_B(win));
674+
writel(0, ctx->regs + VIDOSD_C(win));
675+
676+
if (win == 1 || win == 2)
677+
writel(0, ctx->regs + VIDOSD_D(win));
678+
679+
fimd_shadow_protect_win(ctx, win, false);
680+
}
681+
682+
static void fimd_window_suspend(struct exynos_drm_manager *mgr)
683+
{
684+
struct fimd_context *ctx = mgr->ctx;
685+
struct fimd_win_data *win_data;
686+
int i;
687+
688+
for (i = 0; i < WINDOWS_NR; i++) {
689+
win_data = &ctx->win_data[i];
690+
win_data->resume = win_data->enabled;
691+
if (win_data->enabled)
692+
fimd_win_disable(mgr, i);
693+
}
694+
fimd_wait_for_vblank(mgr);
695+
}
696+
697+
static void fimd_window_resume(struct exynos_drm_manager *mgr)
698+
{
699+
struct fimd_context *ctx = mgr->ctx;
700+
struct fimd_win_data *win_data;
701+
int i;
702+
703+
for (i = 0; i < WINDOWS_NR; i++) {
704+
win_data = &ctx->win_data[i];
705+
win_data->enabled = win_data->resume;
706+
win_data->resume = false;
707+
}
708+
}
709+
710+
static void fimd_apply(struct exynos_drm_manager *mgr)
711+
{
712+
struct fimd_context *ctx = mgr->ctx;
713+
struct fimd_win_data *win_data;
714+
int i;
715+
716+
for (i = 0; i < WINDOWS_NR; i++) {
717+
win_data = &ctx->win_data[i];
718+
if (win_data->enabled)
719+
fimd_win_commit(mgr, i);
720+
}
721+
722+
fimd_commit(mgr);
723+
}
724+
725+
static int fimd_poweron(struct exynos_drm_manager *mgr)
726+
{
727+
struct fimd_context *ctx = mgr->ctx;
728+
int ret;
729+
730+
if (!ctx->suspended)
731+
return 0;
732+
733+
ctx->suspended = false;
734+
735+
ret = clk_prepare_enable(ctx->bus_clk);
736+
if (ret < 0) {
737+
DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
738+
goto bus_clk_err;
739+
}
740+
741+
ret = clk_prepare_enable(ctx->lcd_clk);
742+
if (ret < 0) {
743+
DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
744+
goto lcd_clk_err;
745+
}
746+
747+
/* if vblank was enabled status, enable it again. */
748+
if (test_and_clear_bit(0, &ctx->irq_flags)) {
749+
ret = fimd_enable_vblank(mgr);
750+
if (ret) {
751+
DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
752+
goto enable_vblank_err;
753+
}
754+
}
755+
756+
fimd_window_resume(mgr);
757+
758+
fimd_apply(mgr);
759+
760+
return 0;
761+
762+
enable_vblank_err:
763+
clk_disable_unprepare(ctx->lcd_clk);
764+
lcd_clk_err:
765+
clk_disable_unprepare(ctx->bus_clk);
766+
bus_clk_err:
767+
ctx->suspended = true;
768+
return ret;
769+
}
770+
771+
static int fimd_poweroff(struct exynos_drm_manager *mgr)
772+
{
773+
struct fimd_context *ctx = mgr->ctx;
774+
775+
if (ctx->suspended)
776+
return 0;
777+
778+
/*
779+
* We need to make sure that all windows are disabled before we
780+
* suspend that connector. Otherwise we might try to scan from
781+
* a destroyed buffer later.
782+
*/
783+
fimd_window_suspend(mgr);
784+
785+
clk_disable_unprepare(ctx->lcd_clk);
786+
clk_disable_unprepare(ctx->bus_clk);
787+
788+
ctx->suspended = true;
789+
return 0;
790+
}
791+
663792
static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
664793
{
665794
struct fimd_context *ctx = mgr->ctx;
@@ -736,113 +865,6 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
736865
return IRQ_HANDLED;
737866
}
738867

739-
static void fimd_clear_win(struct fimd_context *ctx, int win)
740-
{
741-
writel(0, ctx->regs + WINCON(win));
742-
writel(0, ctx->regs + VIDOSD_A(win));
743-
writel(0, ctx->regs + VIDOSD_B(win));
744-
writel(0, ctx->regs + VIDOSD_C(win));
745-
746-
if (win == 1 || win == 2)
747-
writel(0, ctx->regs + VIDOSD_D(win));
748-
749-
fimd_shadow_protect_win(ctx, win, false);
750-
}
751-
752-
static int fimd_clock(struct fimd_context *ctx, bool enable)
753-
{
754-
if (enable) {
755-
int ret;
756-
757-
ret = clk_prepare_enable(ctx->bus_clk);
758-
if (ret < 0)
759-
return ret;
760-
761-
ret = clk_prepare_enable(ctx->lcd_clk);
762-
if (ret < 0) {
763-
clk_disable_unprepare(ctx->bus_clk);
764-
return ret;
765-
}
766-
} else {
767-
clk_disable_unprepare(ctx->lcd_clk);
768-
clk_disable_unprepare(ctx->bus_clk);
769-
}
770-
771-
return 0;
772-
}
773-
774-
static void fimd_window_suspend(struct exynos_drm_manager *mgr)
775-
{
776-
struct fimd_context *ctx = mgr->ctx;
777-
struct fimd_win_data *win_data;
778-
int i;
779-
780-
for (i = 0; i < WINDOWS_NR; i++) {
781-
win_data = &ctx->win_data[i];
782-
win_data->resume = win_data->enabled;
783-
fimd_win_disable(mgr, i);
784-
}
785-
fimd_wait_for_vblank(mgr);
786-
}
787-
788-
static void fimd_window_resume(struct exynos_drm_manager *mgr)
789-
{
790-
struct fimd_context *ctx = mgr->ctx;
791-
struct fimd_win_data *win_data;
792-
int i;
793-
794-
for (i = 0; i < WINDOWS_NR; i++) {
795-
win_data = &ctx->win_data[i];
796-
win_data->enabled = win_data->resume;
797-
win_data->resume = false;
798-
}
799-
}
800-
801-
static void fimd_apply(struct exynos_drm_manager *mgr)
802-
{
803-
struct fimd_context *ctx = mgr->ctx;
804-
struct fimd_win_data *win_data;
805-
int i;
806-
807-
for (i = 0; i < WINDOWS_NR; i++) {
808-
win_data = &ctx->win_data[i];
809-
if (win_data->enabled)
810-
fimd_win_commit(mgr, i);
811-
}
812-
813-
fimd_commit(mgr);
814-
}
815-
816-
static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
817-
{
818-
struct fimd_context *ctx = mgr->ctx;
819-
820-
if (enable) {
821-
int ret;
822-
823-
ret = fimd_clock(ctx, true);
824-
if (ret < 0)
825-
return ret;
826-
827-
ctx->suspended = false;
828-
829-
/* if vblank was enabled status, enable it again. */
830-
if (test_and_clear_bit(0, &ctx->irq_flags))
831-
fimd_enable_vblank(mgr);
832-
833-
fimd_window_resume(mgr);
834-
835-
fimd_apply(mgr);
836-
} else {
837-
fimd_window_suspend(mgr);
838-
839-
fimd_clock(ctx, false);
840-
ctx->suspended = true;
841-
}
842-
843-
return 0;
844-
}
845-
846868
static int fimd_probe(struct platform_device *pdev)
847869
{
848870
struct device *dev = &pdev->dev;
@@ -859,6 +881,7 @@ static int fimd_probe(struct platform_device *pdev)
859881
return -ENOMEM;
860882

861883
ctx->dev = dev;
884+
ctx->suspended = true;
862885

863886
if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
864887
ctx->vidcon1 |= VIDCON1_INV_VDEN;
@@ -945,7 +968,7 @@ static int fimd_suspend(struct device *dev)
945968
* because the usage_count of pm runtime is more than 1.
946969
*/
947970
if (!pm_runtime_suspended(dev))
948-
return fimd_activate(mgr, false);
971+
return fimd_poweroff(mgr);
949972

950973
return 0;
951974
}
@@ -962,7 +985,7 @@ static int fimd_resume(struct device *dev)
962985
if (pm_runtime_suspended(dev))
963986
return 0;
964987

965-
return fimd_activate(mgr, true);
988+
return fimd_poweron(mgr);
966989
}
967990
#endif
968991

@@ -971,14 +994,14 @@ static int fimd_runtime_suspend(struct device *dev)
971994
{
972995
struct exynos_drm_manager *mgr = get_fimd_manager(dev);
973996

974-
return fimd_activate(mgr, false);
997+
return fimd_poweroff(mgr);
975998
}
976999

9771000
static int fimd_runtime_resume(struct device *dev)
9781001
{
9791002
struct exynos_drm_manager *mgr = get_fimd_manager(dev);
9801003

981-
return fimd_activate(mgr, true);
1004+
return fimd_poweron(mgr);
9821005
}
9831006
#endif
9841007

0 commit comments

Comments
 (0)