diff options
Diffstat (limited to 'drivers/video/sh_mobile_lcdcfb.c')
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.c | 46 |
1 files changed, 15 insertions, 31 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index ddd6c4669bd7..29d7ce7e7a1c 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/fb.h> | ||
16 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
17 | #include <linux/pm_runtime.h> | 16 | #include <linux/pm_runtime.h> |
18 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
@@ -24,7 +23,8 @@ | |||
24 | #include <video/sh_mobile_lcdc.h> | 23 | #include <video/sh_mobile_lcdc.h> |
25 | #include <asm/atomic.h> | 24 | #include <asm/atomic.h> |
26 | 25 | ||
27 | #define PALETTE_NR 16 | 26 | #include "sh_mobile_lcdcfb.h" |
27 | |||
28 | #define SIDE_B_OFFSET 0x1000 | 28 | #define SIDE_B_OFFSET 0x1000 |
29 | #define MIRROR_OFFSET 0x2000 | 29 | #define MIRROR_OFFSET 0x2000 |
30 | 30 | ||
@@ -53,12 +53,6 @@ static int lcdc_shared_regs[] = { | |||
53 | }; | 53 | }; |
54 | #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) | 54 | #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) |
55 | 55 | ||
56 | /* per-channel registers */ | ||
57 | enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, | ||
58 | LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR, | ||
59 | LDHAJR, | ||
60 | NR_CH_REGS }; | ||
61 | |||
62 | static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { | 56 | static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { |
63 | [LDDCKPAT1R] = 0x400, | 57 | [LDDCKPAT1R] = 0x400, |
64 | [LDDCKPAT2R] = 0x404, | 58 | [LDDCKPAT2R] = 0x404, |
@@ -112,25 +106,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { | |||
112 | #define LDRCNTR_MRC 0x00000001 | 106 | #define LDRCNTR_MRC 0x00000001 |
113 | #define LDSR_MRS 0x00000100 | 107 | #define LDSR_MRS 0x00000100 |
114 | 108 | ||
115 | struct sh_mobile_lcdc_priv; | ||
116 | struct sh_mobile_lcdc_chan { | ||
117 | struct sh_mobile_lcdc_priv *lcdc; | ||
118 | unsigned long *reg_offs; | ||
119 | unsigned long ldmt1r_value; | ||
120 | unsigned long enabled; /* ME and SE in LDCNT2R */ | ||
121 | struct sh_mobile_lcdc_chan_cfg cfg; | ||
122 | u32 pseudo_palette[PALETTE_NR]; | ||
123 | unsigned long saved_ch_regs[NR_CH_REGS]; | ||
124 | struct fb_info *info; | ||
125 | dma_addr_t dma_handle; | ||
126 | struct fb_deferred_io defio; | ||
127 | struct scatterlist *sglist; | ||
128 | unsigned long frame_end; | ||
129 | unsigned long pan_offset; | ||
130 | wait_queue_head_t frame_end_wait; | ||
131 | struct completion vsync_completion; | ||
132 | }; | ||
133 | |||
134 | struct sh_mobile_lcdc_priv { | 109 | struct sh_mobile_lcdc_priv { |
135 | void __iomem *base; | 110 | void __iomem *base; |
136 | int irq; | 111 | int irq; |
@@ -589,8 +564,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
589 | continue; | 564 | continue; |
590 | 565 | ||
591 | board_cfg = &ch->cfg.board_cfg; | 566 | board_cfg = &ch->cfg.board_cfg; |
592 | if (board_cfg->display_on) | 567 | if (try_module_get(board_cfg->owner) && board_cfg->display_on) { |
593 | board_cfg->display_on(board_cfg->board_data, ch->info); | 568 | board_cfg->display_on(board_cfg->board_data, ch->info); |
569 | module_put(board_cfg->owner); | ||
570 | } | ||
594 | } | 571 | } |
595 | 572 | ||
596 | return 0; | 573 | return 0; |
@@ -622,8 +599,10 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) | |||
622 | } | 599 | } |
623 | 600 | ||
624 | board_cfg = &ch->cfg.board_cfg; | 601 | board_cfg = &ch->cfg.board_cfg; |
625 | if (board_cfg->display_off) | 602 | if (try_module_get(board_cfg->owner) && board_cfg->display_off) { |
626 | board_cfg->display_off(board_cfg->board_data); | 603 | board_cfg->display_off(board_cfg->board_data); |
604 | module_put(board_cfg->owner); | ||
605 | } | ||
627 | } | 606 | } |
628 | 607 | ||
629 | /* stop the lcdc */ | 608 | /* stop the lcdc */ |
@@ -954,6 +933,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { | |||
954 | .runtime_resume = sh_mobile_lcdc_runtime_resume, | 933 | .runtime_resume = sh_mobile_lcdc_runtime_resume, |
955 | }; | 934 | }; |
956 | 935 | ||
936 | /* locking: called with info->lock held */ | ||
957 | static int sh_mobile_lcdc_notify(struct notifier_block *nb, | 937 | static int sh_mobile_lcdc_notify(struct notifier_block *nb, |
958 | unsigned long action, void *data) | 938 | unsigned long action, void *data) |
959 | { | 939 | { |
@@ -971,16 +951,20 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, | |||
971 | 951 | ||
972 | switch(action) { | 952 | switch(action) { |
973 | case FB_EVENT_SUSPEND: | 953 | case FB_EVENT_SUSPEND: |
974 | if (board_cfg->display_off) | 954 | if (try_module_get(board_cfg->owner) && board_cfg->display_off) { |
975 | board_cfg->display_off(board_cfg->board_data); | 955 | board_cfg->display_off(board_cfg->board_data); |
956 | module_put(board_cfg->owner); | ||
957 | } | ||
976 | pm_runtime_put(info->device); | 958 | pm_runtime_put(info->device); |
977 | break; | 959 | break; |
978 | case FB_EVENT_RESUME: | 960 | case FB_EVENT_RESUME: |
979 | var = &info->var; | 961 | var = &info->var; |
980 | 962 | ||
981 | /* HDMI must be enabled before LCDC configuration */ | 963 | /* HDMI must be enabled before LCDC configuration */ |
982 | if (board_cfg->display_on) | 964 | if (try_module_get(board_cfg->owner) && board_cfg->display_on) { |
983 | board_cfg->display_on(board_cfg->board_data, ch->info); | 965 | board_cfg->display_on(board_cfg->board_data, ch->info); |
966 | module_put(board_cfg->owner); | ||
967 | } | ||
984 | 968 | ||
985 | /* Check if the new display is not in our modelist */ | 969 | /* Check if the new display is not in our modelist */ |
986 | if (ch->info->modelist.next && | 970 | if (ch->info->modelist.next && |