aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_fimd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fimd.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c117
1 files changed, 92 insertions, 25 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 58d50e368a58..a32837951dd2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -57,6 +57,18 @@
57 57
58#define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev)) 58#define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev))
59 59
60struct fimd_driver_data {
61 unsigned int timing_base;
62};
63
64struct fimd_driver_data exynos4_fimd_driver_data = {
65 .timing_base = 0x0,
66};
67
68struct fimd_driver_data exynos5_fimd_driver_data = {
69 .timing_base = 0x20000,
70};
71
60struct fimd_win_data { 72struct fimd_win_data {
61 unsigned int offset_x; 73 unsigned int offset_x;
62 unsigned int offset_y; 74 unsigned int offset_y;
@@ -91,6 +103,13 @@ struct fimd_context {
91 struct exynos_drm_panel_info *panel; 103 struct exynos_drm_panel_info *panel;
92}; 104};
93 105
106static inline struct fimd_driver_data *drm_fimd_get_driver_data(
107 struct platform_device *pdev)
108{
109 return (struct fimd_driver_data *)
110 platform_get_device_id(pdev)->driver_data;
111}
112
94static bool fimd_display_is_connected(struct device *dev) 113static bool fimd_display_is_connected(struct device *dev)
95{ 114{
96 DRM_DEBUG_KMS("%s\n", __FILE__); 115 DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -194,32 +213,35 @@ static void fimd_commit(struct device *dev)
194 struct fimd_context *ctx = get_fimd_context(dev); 213 struct fimd_context *ctx = get_fimd_context(dev);
195 struct exynos_drm_panel_info *panel = ctx->panel; 214 struct exynos_drm_panel_info *panel = ctx->panel;
196 struct fb_videomode *timing = &panel->timing; 215 struct fb_videomode *timing = &panel->timing;
216 struct fimd_driver_data *driver_data;
217 struct platform_device *pdev = to_platform_device(dev);
197 u32 val; 218 u32 val;
198 219
220 driver_data = drm_fimd_get_driver_data(pdev);
199 if (ctx->suspended) 221 if (ctx->suspended)
200 return; 222 return;
201 223
202 DRM_DEBUG_KMS("%s\n", __FILE__); 224 DRM_DEBUG_KMS("%s\n", __FILE__);
203 225
204 /* setup polarity values from machine code. */ 226 /* setup polarity values from machine code. */
205 writel(ctx->vidcon1, ctx->regs + VIDCON1); 227 writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
206 228
207 /* setup vertical timing values. */ 229 /* setup vertical timing values. */
208 val = VIDTCON0_VBPD(timing->upper_margin - 1) | 230 val = VIDTCON0_VBPD(timing->upper_margin - 1) |
209 VIDTCON0_VFPD(timing->lower_margin - 1) | 231 VIDTCON0_VFPD(timing->lower_margin - 1) |
210 VIDTCON0_VSPW(timing->vsync_len - 1); 232 VIDTCON0_VSPW(timing->vsync_len - 1);
211 writel(val, ctx->regs + VIDTCON0); 233 writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
212 234
213 /* setup horizontal timing values. */ 235 /* setup horizontal timing values. */
214 val = VIDTCON1_HBPD(timing->left_margin - 1) | 236 val = VIDTCON1_HBPD(timing->left_margin - 1) |
215 VIDTCON1_HFPD(timing->right_margin - 1) | 237 VIDTCON1_HFPD(timing->right_margin - 1) |
216 VIDTCON1_HSPW(timing->hsync_len - 1); 238 VIDTCON1_HSPW(timing->hsync_len - 1);
217 writel(val, ctx->regs + VIDTCON1); 239 writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
218 240
219 /* setup horizontal and vertical display size. */ 241 /* setup horizontal and vertical display size. */
220 val = VIDTCON2_LINEVAL(timing->yres - 1) | 242 val = VIDTCON2_LINEVAL(timing->yres - 1) |
221 VIDTCON2_HOZVAL(timing->xres - 1); 243 VIDTCON2_HOZVAL(timing->xres - 1);
222 writel(val, ctx->regs + VIDTCON2); 244 writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
223 245
224 /* setup clock source, clock divider, enable dma. */ 246 /* setup clock source, clock divider, enable dma. */
225 val = ctx->vidcon0; 247 val = ctx->vidcon0;
@@ -570,10 +592,22 @@ static void fimd_win_disable(struct device *dev, int zpos)
570 win_data->enabled = false; 592 win_data->enabled = false;
571} 593}
572 594
595static void fimd_wait_for_vblank(struct device *dev)
596{
597 struct fimd_context *ctx = get_fimd_context(dev);
598 int ret;
599
600 ret = wait_for((__raw_readl(ctx->regs + VIDCON1) &
601 VIDCON1_VSTATUS_VSYNC), 50);
602 if (ret < 0)
603 DRM_DEBUG_KMS("vblank wait timed out.\n");
604}
605
573static struct exynos_drm_overlay_ops fimd_overlay_ops = { 606static struct exynos_drm_overlay_ops fimd_overlay_ops = {
574 .mode_set = fimd_win_mode_set, 607 .mode_set = fimd_win_mode_set,
575 .commit = fimd_win_commit, 608 .commit = fimd_win_commit,
576 .disable = fimd_win_disable, 609 .disable = fimd_win_disable,
610 .wait_for_vblank = fimd_wait_for_vblank,
577}; 611};
578 612
579static struct exynos_drm_manager fimd_manager = { 613static struct exynos_drm_manager fimd_manager = {
@@ -678,7 +712,7 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
678 return 0; 712 return 0;
679} 713}
680 714
681static void fimd_subdrv_remove(struct drm_device *drm_dev) 715static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
682{ 716{
683 DRM_DEBUG_KMS("%s\n", __FILE__); 717 DRM_DEBUG_KMS("%s\n", __FILE__);
684 718
@@ -747,16 +781,10 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
747 writel(val, ctx->regs + SHADOWCON); 781 writel(val, ctx->regs + SHADOWCON);
748} 782}
749 783
750static int fimd_power_on(struct fimd_context *ctx, bool enable) 784static int fimd_clock(struct fimd_context *ctx, bool enable)
751{ 785{
752 struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
753 struct device *dev = subdrv->dev;
754
755 DRM_DEBUG_KMS("%s\n", __FILE__); 786 DRM_DEBUG_KMS("%s\n", __FILE__);
756 787
757 if (enable != false && enable != true)
758 return -EINVAL;
759
760 if (enable) { 788 if (enable) {
761 int ret; 789 int ret;
762 790
@@ -769,18 +797,31 @@ static int fimd_power_on(struct fimd_context *ctx, bool enable)
769 clk_disable(ctx->bus_clk); 797 clk_disable(ctx->bus_clk);
770 return ret; 798 return ret;
771 } 799 }
800 } else {
801 clk_disable(ctx->lcd_clk);
802 clk_disable(ctx->bus_clk);
803 }
804
805 return 0;
806}
807
808static int fimd_activate(struct fimd_context *ctx, bool enable)
809{
810 if (enable) {
811 int ret;
812 struct device *dev = ctx->subdrv.dev;
813
814 ret = fimd_clock(ctx, true);
815 if (ret < 0)
816 return ret;
772 817
773 ctx->suspended = false; 818 ctx->suspended = false;
774 819
775 /* if vblank was enabled status, enable it again. */ 820 /* if vblank was enabled status, enable it again. */
776 if (test_and_clear_bit(0, &ctx->irq_flags)) 821 if (test_and_clear_bit(0, &ctx->irq_flags))
777 fimd_enable_vblank(dev); 822 fimd_enable_vblank(dev);
778
779 fimd_apply(dev);
780 } else { 823 } else {
781 clk_disable(ctx->lcd_clk); 824 fimd_clock(ctx, false);
782 clk_disable(ctx->bus_clk);
783
784 ctx->suspended = true; 825 ctx->suspended = true;
785 } 826 }
786 827
@@ -930,15 +971,15 @@ static int fimd_suspend(struct device *dev)
930{ 971{
931 struct fimd_context *ctx = get_fimd_context(dev); 972 struct fimd_context *ctx = get_fimd_context(dev);
932 973
933 if (pm_runtime_suspended(dev))
934 return 0;
935
936 /* 974 /*
937 * do not use pm_runtime_suspend(). if pm_runtime_suspend() is 975 * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
938 * called here, an error would be returned by that interface 976 * called here, an error would be returned by that interface
939 * because the usage_count of pm runtime is more than 1. 977 * because the usage_count of pm runtime is more than 1.
940 */ 978 */
941 return fimd_power_on(ctx, false); 979 if (!pm_runtime_suspended(dev))
980 return fimd_activate(ctx, false);
981
982 return 0;
942} 983}
943 984
944static int fimd_resume(struct device *dev) 985static int fimd_resume(struct device *dev)
@@ -950,8 +991,21 @@ static int fimd_resume(struct device *dev)
950 * of pm runtime would still be 1 so in this case, fimd driver 991 * of pm runtime would still be 1 so in this case, fimd driver
951 * should be on directly not drawing on pm runtime interface. 992 * should be on directly not drawing on pm runtime interface.
952 */ 993 */
953 if (!pm_runtime_suspended(dev)) 994 if (pm_runtime_suspended(dev)) {
954 return fimd_power_on(ctx, true); 995 int ret;
996
997 ret = fimd_activate(ctx, true);
998 if (ret < 0)
999 return ret;
1000
1001 /*
1002 * in case of dpms on(standby), fimd_apply function will
1003 * be called by encoder's dpms callback to update fimd's
1004 * registers but in case of sleep wakeup, it's not.
1005 * so fimd_apply function should be called at here.
1006 */
1007 fimd_apply(dev);
1008 }
955 1009
956 return 0; 1010 return 0;
957} 1011}
@@ -964,7 +1018,7 @@ static int fimd_runtime_suspend(struct device *dev)
964 1018
965 DRM_DEBUG_KMS("%s\n", __FILE__); 1019 DRM_DEBUG_KMS("%s\n", __FILE__);
966 1020
967 return fimd_power_on(ctx, false); 1021 return fimd_activate(ctx, false);
968} 1022}
969 1023
970static int fimd_runtime_resume(struct device *dev) 1024static int fimd_runtime_resume(struct device *dev)
@@ -973,10 +1027,22 @@ static int fimd_runtime_resume(struct device *dev)
973 1027
974 DRM_DEBUG_KMS("%s\n", __FILE__); 1028 DRM_DEBUG_KMS("%s\n", __FILE__);
975 1029
976 return fimd_power_on(ctx, true); 1030 return fimd_activate(ctx, true);
977} 1031}
978#endif 1032#endif
979 1033
1034static struct platform_device_id fimd_driver_ids[] = {
1035 {
1036 .name = "exynos4-fb",
1037 .driver_data = (unsigned long)&exynos4_fimd_driver_data,
1038 }, {
1039 .name = "exynos5-fb",
1040 .driver_data = (unsigned long)&exynos5_fimd_driver_data,
1041 },
1042 {},
1043};
1044MODULE_DEVICE_TABLE(platform, fimd_driver_ids);
1045
980static const struct dev_pm_ops fimd_pm_ops = { 1046static const struct dev_pm_ops fimd_pm_ops = {
981 SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume) 1047 SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
982 SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL) 1048 SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
@@ -985,6 +1051,7 @@ static const struct dev_pm_ops fimd_pm_ops = {
985struct platform_driver fimd_driver = { 1051struct platform_driver fimd_driver = {
986 .probe = fimd_probe, 1052 .probe = fimd_probe,
987 .remove = __devexit_p(fimd_remove), 1053 .remove = __devexit_p(fimd_remove),
1054 .id_table = fimd_driver_ids,
988 .driver = { 1055 .driver = {
989 .name = "exynos4-fb", 1056 .name = "exynos4-fb",
990 .owner = THIS_MODULE, 1057 .owner = THIS_MODULE,