1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
From aded2e51a7a2113dae6431c858df1d95fb312851 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
Date: Wed, 13 Feb 2008 19:34:08 +0300
Subject: [PATCH] modeswitching
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
arch/arm/mach-pxa/tosa.c | 33 +++++++++++++++++++++++++++++++-
drivers/mfd/tc6393xb.c | 2 +-
drivers/video/backlight/tosa_bl.c | 38 +++++++++++++++++++++++++++++++++---
drivers/video/tmiofb.c | 8 +++---
include/asm-arm/arch-pxa/tosa.h | 2 +
include/linux/mfd/tc6393xb.h | 2 +-
include/linux/mfd/tmio.h | 2 +-
7 files changed, 75 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 94c9915..6631de2 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -455,9 +455,40 @@ static struct fb_videomode tosa_tc6393xb_lcd_mode[] = {
}
};
+static DEFINE_SPINLOCK(tosa_lcd_mode_lock);
+
+static const struct fb_videomode *tosa_lcd_mode = &tosa_tc6393xb_lcd_mode[0];
+
+static int tosa_lcd_set_mode(struct platform_device *fb_dev,
+ const struct fb_videomode *mode)
+{
+ int rc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tosa_lcd_mode_lock, flags);
+ rc = tc6393xb_lcd_mode(fb_dev, mode);
+ if (!rc)
+ tosa_lcd_mode = mode;
+ spin_unlock_irqrestore(&tosa_lcd_mode_lock, flags);
+
+ return rc;
+}
+
+const struct fb_videomode *tosa_lcd_get_mode(void)
+{
+ unsigned long flags;
+ const struct fb_videomode *mode;
+
+ spin_lock_irqsave(&tosa_lcd_mode_lock, flags);
+ mode = tosa_lcd_mode;
+ spin_unlock_irqrestore(&tosa_lcd_mode_lock, flags);
+
+ return mode;
+}
+
static struct tmio_fb_data tosa_tc6393xb_fb_config = {
.lcd_set_power = tc6393xb_lcd_set_power,
- .lcd_mode = tc6393xb_lcd_mode,
+ .lcd_mode = tosa_lcd_set_mode,
.num_modes = ARRAY_SIZE(tosa_tc6393xb_lcd_mode),
.modes = &tosa_tc6393xb_lcd_mode[0],
};
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 9001687..21190f3 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -196,7 +196,7 @@ int tc6393xb_lcd_set_power(struct platform_device *fb, bool on)
EXPORT_SYMBOL(tc6393xb_lcd_set_power);
int tc6393xb_lcd_mode(struct platform_device *fb_dev,
- struct fb_videomode *mode) {
+ const struct fb_videomode *mode) {
struct tc6393xb *tc6393xb =
platform_get_drvdata(to_platform_device(fb_dev->dev.parent));
struct tc6393xb_scr __iomem *scr = tc6393xb->scr;
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 9ef0bfb..45fc6ae 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -48,6 +48,9 @@ struct tosa_bl_data {
struct ssp_dev nssp_dev;
struct ssp_state nssp_state;
+ /* listen for mode changes */
+ struct notifier_block fb_notif;
+
struct backlight_device *bl_dev;
};
@@ -103,14 +106,19 @@ static void tosa_lcd_tg_init(struct tosa_bl_data *data)
pxa_nssp_output(data, TG_GPOSR,0x02); /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */
}
-static void tosa_lcd_tg_on(struct tosa_bl_data *data/*, const struct fb_videomode *mode*/)
+static void tosa_lcd_tg_on(struct tosa_bl_data *data)
{
- const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
+ const struct fb_videomode *mode = tosa_lcd_get_mode();
+
+ int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
+
+ if (mode->yres == 640)
+ value |= TG_REG0_VQV;
tosa_lcd_tg_init(data);
- dev_dbg(&data->bl_dev->dev, "tosa_lcd_on\n");
- pxa_nssp_output(data, TG_PNLCTL, value | (/*mode->yres == 320 ? 0 : */ TG_REG0_VQV));
+ dev_dbg(&data->bl_dev->dev, "tosa_lcd_on: %04x (%d)\n", value, mode->yres);
+ pxa_nssp_output(data, TG_PNLCTL, value);
/* TG LCD pannel power up */
pxa_nssp_output(data, TG_PINICTL,0x4);
@@ -173,6 +181,20 @@ static struct backlight_ops tosa_bl_ops = {
.update_status = tosa_bl_update_status,
};
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *_data)
+{
+ struct tosa_bl_data *bl_data =
+ container_of(self, struct tosa_bl_data, fb_notif);
+
+ if (event != FB_EVENT_MODE_CHANGE && event != FB_EVENT_MODE_CHANGE_ALL)
+ return 0;
+
+ tosa_bl_update_status(bl_data->bl_dev);
+
+ return 0;
+}
+
static int tosa_bl_detect_client(struct i2c_adapter *adapter, int address,
int kind)
{
@@ -238,9 +260,15 @@ static int tosa_bl_detect_client(struct i2c_adapter *adapter, int address,
data->bl_dev->props.power = FB_BLANK_UNBLANK;
backlight_update_status(data->bl_dev);
+ data->fb_notif.notifier_call = fb_notifier_callback;
+ err = fb_register_client(&data->fb_notif);
+ if (err)
+ goto err_fb_register;
return 0;
+err_fb_register:
+ backlight_device_unregister(data->bl_dev);
err_bl_register:
tosa_set_backlight(data, 0);
tosa_lcd_tg_off(data);
@@ -265,6 +293,8 @@ static int tosa_bl_detach_client(struct i2c_client *client)
int err = 0;
struct tosa_bl_data *data = i2c_get_clientdata(client);
+ fb_unregister_client(&data->fb_notif);
+
backlight_device_unregister(data->bl_dev);
tosa_set_backlight(data, 0);
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
index 958ee8a..cc75df9 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/tmiofb.c
@@ -618,17 +618,17 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int tmiofb_set_par(struct fb_info *info)
{
-/* struct fb_var_screeninfo *var = &info->var;
+ struct fb_var_screeninfo *var = &info->var;
struct fb_videomode *mode;
mode = tmiofb_find_mode(info, var);
if (!mode)
return -EINVAL;
- if (info->mode == mode)
- return 0;
+/* if (info->mode == mode)
+ return 0;*/
- info->mode = mode; */
+ info->mode = mode;
info->fix.line_length = info->mode->xres * 2;
tmiofb_hw_mode(to_platform_device(info->device));
diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h
index 410fa9a..624c636 100644
--- a/include/asm-arm/arch-pxa/tosa.h
+++ b/include/asm-arm/arch-pxa/tosa.h
@@ -230,4 +230,6 @@ extern struct platform_device tosascoop_device;
#define TOSA_KEY_MAIL KEY_MAIL
#endif
+const struct fb_videomode *tosa_lcd_get_mode(void);
+
#endif /* _ASM_ARCH_TOSA_H_ */
diff --git a/include/linux/mfd/tc6393xb.h b/include/linux/mfd/tc6393xb.h
index 97c4c7c..8ab9e91 100644
--- a/include/linux/mfd/tc6393xb.h
+++ b/include/linux/mfd/tc6393xb.h
@@ -53,7 +53,7 @@ struct tc6393xb_platform_data {
extern int tc6393xb_lcd_set_power(struct platform_device *fb_dev, bool on);
extern int tc6393xb_lcd_mode(struct platform_device *fb_dev,
- struct fb_videomode *mode);
+ const struct fb_videomode *mode);
/*
* Relative to irq_base
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index b6d4aac..fe7ff2d 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -19,7 +19,7 @@ struct tmio_fb_data {
int (*lcd_set_power)(struct platform_device *fb_dev,
bool on);
int (*lcd_mode)(struct platform_device *fb_dev,
- struct fb_videomode *mode);
+ const struct fb_videomode *mode);
int num_modes;
struct fb_videomode *modes;
};
--
1.5.4.1
|