aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/sh_mobile_lcdcfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/sh_mobile_lcdcfb.c')
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c46
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 */
57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
59 LDHAJR,
60 NR_CH_REGS };
61
62static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 56static 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
115struct sh_mobile_lcdc_priv;
116struct 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
134struct sh_mobile_lcdc_priv { 109struct 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 */
957static int sh_mobile_lcdc_notify(struct notifier_block *nb, 937static 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 &&