aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-07-15 01:44:51 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-07-15 01:44:51 -0400
commit43d2548bb2ef7e6d753f91468a746784041e522d (patch)
tree77d13fcd48fd998393abb825ec36e2b732684a73 /drivers/video
parent585583d95c5660973bc0cf64add517b040acd8a4 (diff)
parent85082fd7cbe3173198aac0eb5e85ab1edcc6352c (diff)
Merge commit '85082fd7cbe3173198aac0eb5e85ab1edcc6352c' into test-build
Manual fixup of: arch/powerpc/Kconfig
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/backlight/Kconfig7
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/pwm_bl.c185
-rw-r--r--drivers/video/fbmem.c15
-rw-r--r--drivers/video/pxafb.c44
-rw-r--r--drivers/video/sgivwfb.c3
-rw-r--r--drivers/video/xen-fbfront.c211
8 files changed, 432 insertions, 36 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e0c5f96b273d..9b887ef64ff1 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -7,7 +7,7 @@ menu "Graphics support"
7 7
8source "drivers/char/agp/Kconfig" 8source "drivers/char/agp/Kconfig"
9 9
10source "drivers/char/drm/Kconfig" 10source "drivers/gpu/drm/Kconfig"
11 11
12config VGASTATE 12config VGASTATE
13 tristate 13 tristate
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index dcd8073c2369..30bf7f2f1635 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -112,3 +112,10 @@ config BACKLIGHT_CARILLO_RANCH
112 help 112 help
113 If you have a Intel LE80578 (Carillo Ranch) say Y to enable the 113 If you have a Intel LE80578 (Carillo Ranch) say Y to enable the
114 backlight driver. 114 backlight driver.
115
116config BACKLIGHT_PWM
117 tristate "Generic PWM based Backlight Driver"
118 depends on BACKLIGHT_CLASS_DEVICE && HAVE_PWM
119 help
120 If you have a LCD backlight adjustable by PWM, say Y to enable
121 this driver.
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 33f6c7cecc73..b51a7cd12500 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
10obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o 10obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
11obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o 11obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
12obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o 12obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
13obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
new file mode 100644
index 000000000000..6338d0e2fe07
--- /dev/null
+++ b/drivers/video/backlight/pwm_bl.c
@@ -0,0 +1,185 @@
1/*
2 * linux/drivers/video/backlight/pwm_bl.c
3 *
4 * simple PWM based backlight control, board code has to setup
5 * 1) pin configuration so PWM waveforms can output
6 * 2) platform_data casts to the PWM id (0/1/2/3 on PXA)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/platform_device.h>
17#include <linux/fb.h>
18#include <linux/backlight.h>
19#include <linux/err.h>
20#include <linux/pwm.h>
21#include <linux/pwm_backlight.h>
22
23struct pwm_bl_data {
24 struct pwm_device *pwm;
25 unsigned int period;
26 int (*notify)(int brightness);
27};
28
29static int pwm_backlight_update_status(struct backlight_device *bl)
30{
31 struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
32 int brightness = bl->props.brightness;
33 int max = bl->props.max_brightness;
34
35 if (bl->props.power != FB_BLANK_UNBLANK)
36 brightness = 0;
37
38 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
39 brightness = 0;
40
41 if (pb->notify)
42 brightness = pb->notify(brightness);
43
44 if (brightness == 0) {
45 pwm_config(pb->pwm, 0, pb->period);
46 pwm_disable(pb->pwm);
47 } else {
48 pwm_config(pb->pwm, brightness * pb->period / max, pb->period);
49 pwm_enable(pb->pwm);
50 }
51 return 0;
52}
53
54static int pwm_backlight_get_brightness(struct backlight_device *bl)
55{
56 return bl->props.brightness;
57}
58
59static struct backlight_ops pwm_backlight_ops = {
60 .update_status = pwm_backlight_update_status,
61 .get_brightness = pwm_backlight_get_brightness,
62};
63
64static int pwm_backlight_probe(struct platform_device *pdev)
65{
66 struct platform_pwm_backlight_data *data = pdev->dev.platform_data;
67 struct backlight_device *bl;
68 struct pwm_bl_data *pb;
69 int ret;
70
71 if (!data)
72 return -EINVAL;
73
74 if (data->init) {
75 ret = data->init(&pdev->dev);
76 if (ret < 0)
77 return ret;
78 }
79
80 pb = kzalloc(sizeof(*pb), GFP_KERNEL);
81 if (!pb) {
82 ret = -ENOMEM;
83 goto err_alloc;
84 }
85
86 pb->period = data->pwm_period_ns;
87 pb->notify = data->notify;
88
89 pb->pwm = pwm_request(data->pwm_id, "backlight");
90 if (IS_ERR(pb->pwm)) {
91 dev_err(&pdev->dev, "unable to request PWM for backlight\n");
92 ret = PTR_ERR(pb->pwm);
93 goto err_pwm;
94 }
95
96 bl = backlight_device_register(pdev->name, &pdev->dev,
97 pb, &pwm_backlight_ops);
98 if (IS_ERR(bl)) {
99 dev_err(&pdev->dev, "failed to register backlight\n");
100 ret = PTR_ERR(bl);
101 goto err_bl;
102 }
103
104 bl->props.max_brightness = data->max_brightness;
105 bl->props.brightness = data->dft_brightness;
106 backlight_update_status(bl);
107
108 platform_set_drvdata(pdev, bl);
109 return 0;
110
111err_bl:
112 pwm_free(pb->pwm);
113err_pwm:
114 kfree(pb);
115err_alloc:
116 if (data->exit)
117 data->exit(&pdev->dev);
118 return ret;
119}
120
121static int pwm_backlight_remove(struct platform_device *pdev)
122{
123 struct platform_pwm_backlight_data *data = pdev->dev.platform_data;
124 struct backlight_device *bl = platform_get_drvdata(pdev);
125 struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
126
127 backlight_device_unregister(bl);
128 pwm_config(pb->pwm, 0, pb->period);
129 pwm_disable(pb->pwm);
130 pwm_free(pb->pwm);
131 kfree(pb);
132 if (data->exit)
133 data->exit(&pdev->dev);
134 return 0;
135}
136
137#ifdef CONFIG_PM
138static int pwm_backlight_suspend(struct platform_device *pdev,
139 pm_message_t state)
140{
141 struct backlight_device *bl = platform_get_drvdata(pdev);
142 struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
143
144 pwm_config(pb->pwm, 0, pb->period);
145 pwm_disable(pb->pwm);
146 return 0;
147}
148
149static int pwm_backlight_resume(struct platform_device *pdev)
150{
151 struct backlight_device *bl = platform_get_drvdata(pdev);
152
153 backlight_update_status(bl);
154 return 0;
155}
156#else
157#define pwm_backlight_suspend NULL
158#define pwm_backlight_resume NULL
159#endif
160
161static struct platform_driver pwm_backlight_driver = {
162 .driver = {
163 .name = "pwm-backlight",
164 .owner = THIS_MODULE,
165 },
166 .probe = pwm_backlight_probe,
167 .remove = pwm_backlight_remove,
168 .suspend = pwm_backlight_suspend,
169 .resume = pwm_backlight_resume,
170};
171
172static int __init pwm_backlight_init(void)
173{
174 return platform_driver_register(&pwm_backlight_driver);
175}
176module_init(pwm_backlight_init);
177
178static void __exit pwm_backlight_exit(void)
179{
180 platform_driver_unregister(&pwm_backlight_driver);
181}
182module_exit(pwm_backlight_exit);
183
184MODULE_DESCRIPTION("PWM based Backlight Driver");
185MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 776f7fcd2fbf..33ebdb198daf 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1326,20 +1326,27 @@ fb_open(struct inode *inode, struct file *file)
1326 1326
1327 if (fbidx >= FB_MAX) 1327 if (fbidx >= FB_MAX)
1328 return -ENODEV; 1328 return -ENODEV;
1329 lock_kernel();
1329#ifdef CONFIG_KMOD 1330#ifdef CONFIG_KMOD
1330 if (!(info = registered_fb[fbidx])) 1331 if (!(info = registered_fb[fbidx]))
1331 try_to_load(fbidx); 1332 try_to_load(fbidx);
1332#endif /* CONFIG_KMOD */ 1333#endif /* CONFIG_KMOD */
1333 if (!(info = registered_fb[fbidx])) 1334 if (!(info = registered_fb[fbidx])) {
1334 return -ENODEV; 1335 res = -ENODEV;
1335 if (!try_module_get(info->fbops->owner)) 1336 goto out;
1336 return -ENODEV; 1337 }
1338 if (!try_module_get(info->fbops->owner)) {
1339 res = -ENODEV;
1340 goto out;
1341 }
1337 file->private_data = info; 1342 file->private_data = info;
1338 if (info->fbops->fb_open) { 1343 if (info->fbops->fb_open) {
1339 res = info->fbops->fb_open(info,1); 1344 res = info->fbops->fb_open(info,1);
1340 if (res) 1345 if (res)
1341 module_put(info->fbops->owner); 1346 module_put(info->fbops->owner);
1342 } 1347 }
1348out:
1349 unlock_kernel();
1343 return res; 1350 return res;
1344} 1351}
1345 1352
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index fafe7db20d6d..d0746261c957 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1792,11 +1792,49 @@ failed:
1792 return ret; 1792 return ret;
1793} 1793}
1794 1794
1795static int __devexit pxafb_remove(struct platform_device *dev)
1796{
1797 struct pxafb_info *fbi = platform_get_drvdata(dev);
1798 struct resource *r;
1799 int irq;
1800 struct fb_info *info;
1801
1802 if (!fbi)
1803 return 0;
1804
1805 info = &fbi->fb;
1806
1807 unregister_framebuffer(info);
1808
1809 pxafb_disable_controller(fbi);
1810
1811 if (fbi->fb.cmap.len)
1812 fb_dealloc_cmap(&fbi->fb.cmap);
1813
1814 irq = platform_get_irq(dev, 0);
1815 free_irq(irq, fbi);
1816
1817 dma_free_writecombine(&dev->dev, fbi->map_size,
1818 fbi->map_cpu, fbi->map_dma);
1819
1820 iounmap(fbi->mmio_base);
1821
1822 r = platform_get_resource(dev, IORESOURCE_MEM, 0);
1823 release_mem_region(r->start, r->end - r->start + 1);
1824
1825 clk_put(fbi->clk);
1826 kfree(fbi);
1827
1828 return 0;
1829}
1830
1795static struct platform_driver pxafb_driver = { 1831static struct platform_driver pxafb_driver = {
1796 .probe = pxafb_probe, 1832 .probe = pxafb_probe,
1833 .remove = pxafb_remove,
1797 .suspend = pxafb_suspend, 1834 .suspend = pxafb_suspend,
1798 .resume = pxafb_resume, 1835 .resume = pxafb_resume,
1799 .driver = { 1836 .driver = {
1837 .owner = THIS_MODULE,
1800 .name = "pxa2xx-fb", 1838 .name = "pxa2xx-fb",
1801 }, 1839 },
1802}; 1840};
@@ -1809,7 +1847,13 @@ static int __init pxafb_init(void)
1809 return platform_driver_register(&pxafb_driver); 1847 return platform_driver_register(&pxafb_driver);
1810} 1848}
1811 1849
1850static void __exit pxafb_exit(void)
1851{
1852 platform_driver_unregister(&pxafb_driver);
1853}
1854
1812module_init(pxafb_init); 1855module_init(pxafb_init);
1856module_exit(pxafb_exit);
1813 1857
1814MODULE_DESCRIPTION("loadable framebuffer driver for PXA"); 1858MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
1815MODULE_LICENSE("GPL"); 1859MODULE_LICENSE("GPL");
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 4fb16240c04d..f5252c2552fd 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -21,8 +21,7 @@
21 21
22#include <asm/io.h> 22#include <asm/io.h>
23#include <asm/mtrr.h> 23#include <asm/mtrr.h>
24 24#include <asm/visws/sgivw.h>
25#include <setup_arch.h>
26 25
27#define INCLUDE_TIMING_TABLE_DATA 26#define INCLUDE_TIMING_TABLE_DATA
28#define DBE_REG_BASE par->regs 27#define DBE_REG_BASE par->regs
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index 619a6f8d65a2..47ed39b52f9c 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -18,6 +18,7 @@
18 * frame buffer. 18 * frame buffer.
19 */ 19 */
20 20
21#include <linux/console.h>
21#include <linux/kernel.h> 22#include <linux/kernel.h>
22#include <linux/errno.h> 23#include <linux/errno.h>
23#include <linux/fb.h> 24#include <linux/fb.h>
@@ -42,37 +43,68 @@ struct xenfb_info {
42 struct xenfb_page *page; 43 struct xenfb_page *page;
43 unsigned long *mfns; 44 unsigned long *mfns;
44 int update_wanted; /* XENFB_TYPE_UPDATE wanted */ 45 int update_wanted; /* XENFB_TYPE_UPDATE wanted */
46 int feature_resize; /* XENFB_TYPE_RESIZE ok */
47 struct xenfb_resize resize; /* protected by resize_lock */
48 int resize_dpy; /* ditto */
49 spinlock_t resize_lock;
45 50
46 struct xenbus_device *xbdev; 51 struct xenbus_device *xbdev;
47}; 52};
48 53
49static u32 xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8; 54#define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8)
50 55
56enum { KPARAM_MEM, KPARAM_WIDTH, KPARAM_HEIGHT, KPARAM_CNT };
57static int video[KPARAM_CNT] = { 2, XENFB_WIDTH, XENFB_HEIGHT };
58module_param_array(video, int, NULL, 0);
59MODULE_PARM_DESC(video,
60 "Video memory size in MB, width, height in pixels (default 2,800,600)");
61
62static void xenfb_make_preferred_console(void);
51static int xenfb_remove(struct xenbus_device *); 63static int xenfb_remove(struct xenbus_device *);
52static void xenfb_init_shared_page(struct xenfb_info *); 64static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *);
53static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *); 65static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
54static void xenfb_disconnect_backend(struct xenfb_info *); 66static void xenfb_disconnect_backend(struct xenfb_info *);
55 67
68static void xenfb_send_event(struct xenfb_info *info,
69 union xenfb_out_event *event)
70{
71 u32 prod;
72
73 prod = info->page->out_prod;
74 /* caller ensures !xenfb_queue_full() */
75 mb(); /* ensure ring space available */
76 XENFB_OUT_RING_REF(info->page, prod) = *event;
77 wmb(); /* ensure ring contents visible */
78 info->page->out_prod = prod + 1;
79
80 notify_remote_via_irq(info->irq);
81}
82
56static void xenfb_do_update(struct xenfb_info *info, 83static void xenfb_do_update(struct xenfb_info *info,
57 int x, int y, int w, int h) 84 int x, int y, int w, int h)
58{ 85{
59 union xenfb_out_event event; 86 union xenfb_out_event event;
60 u32 prod;
61 87
88 memset(&event, 0, sizeof(event));
62 event.type = XENFB_TYPE_UPDATE; 89 event.type = XENFB_TYPE_UPDATE;
63 event.update.x = x; 90 event.update.x = x;
64 event.update.y = y; 91 event.update.y = y;
65 event.update.width = w; 92 event.update.width = w;
66 event.update.height = h; 93 event.update.height = h;
67 94
68 prod = info->page->out_prod;
69 /* caller ensures !xenfb_queue_full() */ 95 /* caller ensures !xenfb_queue_full() */
70 mb(); /* ensure ring space available */ 96 xenfb_send_event(info, &event);
71 XENFB_OUT_RING_REF(info->page, prod) = event; 97}
72 wmb(); /* ensure ring contents visible */
73 info->page->out_prod = prod + 1;
74 98
75 notify_remote_via_irq(info->irq); 99static void xenfb_do_resize(struct xenfb_info *info)
100{
101 union xenfb_out_event event;
102
103 memset(&event, 0, sizeof(event));
104 event.resize = info->resize;
105
106 /* caller ensures !xenfb_queue_full() */
107 xenfb_send_event(info, &event);
76} 108}
77 109
78static int xenfb_queue_full(struct xenfb_info *info) 110static int xenfb_queue_full(struct xenfb_info *info)
@@ -84,12 +116,28 @@ static int xenfb_queue_full(struct xenfb_info *info)
84 return prod - cons == XENFB_OUT_RING_LEN; 116 return prod - cons == XENFB_OUT_RING_LEN;
85} 117}
86 118
119static void xenfb_handle_resize_dpy(struct xenfb_info *info)
120{
121 unsigned long flags;
122
123 spin_lock_irqsave(&info->resize_lock, flags);
124 if (info->resize_dpy) {
125 if (!xenfb_queue_full(info)) {
126 info->resize_dpy = 0;
127 xenfb_do_resize(info);
128 }
129 }
130 spin_unlock_irqrestore(&info->resize_lock, flags);
131}
132
87static void xenfb_refresh(struct xenfb_info *info, 133static void xenfb_refresh(struct xenfb_info *info,
88 int x1, int y1, int w, int h) 134 int x1, int y1, int w, int h)
89{ 135{
90 unsigned long flags; 136 unsigned long flags;
91 int y2 = y1 + h - 1;
92 int x2 = x1 + w - 1; 137 int x2 = x1 + w - 1;
138 int y2 = y1 + h - 1;
139
140 xenfb_handle_resize_dpy(info);
93 141
94 if (!info->update_wanted) 142 if (!info->update_wanted)
95 return; 143 return;
@@ -222,6 +270,57 @@ static ssize_t xenfb_write(struct fb_info *p, const char __user *buf,
222 return res; 270 return res;
223} 271}
224 272
273static int
274xenfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
275{
276 struct xenfb_info *xenfb_info;
277 int required_mem_len;
278
279 xenfb_info = info->par;
280
281 if (!xenfb_info->feature_resize) {
282 if (var->xres == video[KPARAM_WIDTH] &&
283 var->yres == video[KPARAM_HEIGHT] &&
284 var->bits_per_pixel == xenfb_info->page->depth) {
285 return 0;
286 }
287 return -EINVAL;
288 }
289
290 /* Can't resize past initial width and height */
291 if (var->xres > video[KPARAM_WIDTH] || var->yres > video[KPARAM_HEIGHT])
292 return -EINVAL;
293
294 required_mem_len = var->xres * var->yres * xenfb_info->page->depth / 8;
295 if (var->bits_per_pixel == xenfb_info->page->depth &&
296 var->xres <= info->fix.line_length / (XENFB_DEPTH / 8) &&
297 required_mem_len <= info->fix.smem_len) {
298 var->xres_virtual = var->xres;
299 var->yres_virtual = var->yres;
300 return 0;
301 }
302 return -EINVAL;
303}
304
305static int xenfb_set_par(struct fb_info *info)
306{
307 struct xenfb_info *xenfb_info;
308 unsigned long flags;
309
310 xenfb_info = info->par;
311
312 spin_lock_irqsave(&xenfb_info->resize_lock, flags);
313 xenfb_info->resize.type = XENFB_TYPE_RESIZE;
314 xenfb_info->resize.width = info->var.xres;
315 xenfb_info->resize.height = info->var.yres;
316 xenfb_info->resize.stride = info->fix.line_length;
317 xenfb_info->resize.depth = info->var.bits_per_pixel;
318 xenfb_info->resize.offset = 0;
319 xenfb_info->resize_dpy = 1;
320 spin_unlock_irqrestore(&xenfb_info->resize_lock, flags);
321 return 0;
322}
323
225static struct fb_ops xenfb_fb_ops = { 324static struct fb_ops xenfb_fb_ops = {
226 .owner = THIS_MODULE, 325 .owner = THIS_MODULE,
227 .fb_read = fb_sys_read, 326 .fb_read = fb_sys_read,
@@ -230,6 +329,8 @@ static struct fb_ops xenfb_fb_ops = {
230 .fb_fillrect = xenfb_fillrect, 329 .fb_fillrect = xenfb_fillrect,
231 .fb_copyarea = xenfb_copyarea, 330 .fb_copyarea = xenfb_copyarea,
232 .fb_imageblit = xenfb_imageblit, 331 .fb_imageblit = xenfb_imageblit,
332 .fb_check_var = xenfb_check_var,
333 .fb_set_par = xenfb_set_par,
233}; 334};
234 335
235static irqreturn_t xenfb_event_handler(int rq, void *dev_id) 336static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
@@ -258,6 +359,8 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
258{ 359{
259 struct xenfb_info *info; 360 struct xenfb_info *info;
260 struct fb_info *fb_info; 361 struct fb_info *fb_info;
362 int fb_size;
363 int val;
261 int ret; 364 int ret;
262 365
263 info = kzalloc(sizeof(*info), GFP_KERNEL); 366 info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -265,18 +368,35 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
265 xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure"); 368 xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
266 return -ENOMEM; 369 return -ENOMEM;
267 } 370 }
371
372 /* Limit kernel param videoram amount to what is in xenstore */
373 if (xenbus_scanf(XBT_NIL, dev->otherend, "videoram", "%d", &val) == 1) {
374 if (val < video[KPARAM_MEM])
375 video[KPARAM_MEM] = val;
376 }
377
378 /* If requested res does not fit in available memory, use default */
379 fb_size = video[KPARAM_MEM] * 1024 * 1024;
380 if (video[KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH / 8
381 > fb_size) {
382 video[KPARAM_WIDTH] = XENFB_WIDTH;
383 video[KPARAM_HEIGHT] = XENFB_HEIGHT;
384 fb_size = XENFB_DEFAULT_FB_LEN;
385 }
386
268 dev->dev.driver_data = info; 387 dev->dev.driver_data = info;
269 info->xbdev = dev; 388 info->xbdev = dev;
270 info->irq = -1; 389 info->irq = -1;
271 info->x1 = info->y1 = INT_MAX; 390 info->x1 = info->y1 = INT_MAX;
272 spin_lock_init(&info->dirty_lock); 391 spin_lock_init(&info->dirty_lock);
392 spin_lock_init(&info->resize_lock);
273 393
274 info->fb = vmalloc(xenfb_mem_len); 394 info->fb = vmalloc(fb_size);
275 if (info->fb == NULL) 395 if (info->fb == NULL)
276 goto error_nomem; 396 goto error_nomem;
277 memset(info->fb, 0, xenfb_mem_len); 397 memset(info->fb, 0, fb_size);
278 398
279 info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT; 399 info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
280 400
281 info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages); 401 info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
282 if (!info->mfns) 402 if (!info->mfns)
@@ -287,8 +407,6 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
287 if (!info->page) 407 if (!info->page)
288 goto error_nomem; 408 goto error_nomem;
289 409
290 xenfb_init_shared_page(info);
291
292 /* abusing framebuffer_alloc() to allocate pseudo_palette */ 410 /* abusing framebuffer_alloc() to allocate pseudo_palette */
293 fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL); 411 fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
294 if (fb_info == NULL) 412 if (fb_info == NULL)
@@ -301,9 +419,9 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
301 fb_info->screen_base = info->fb; 419 fb_info->screen_base = info->fb;
302 420
303 fb_info->fbops = &xenfb_fb_ops; 421 fb_info->fbops = &xenfb_fb_ops;
304 fb_info->var.xres_virtual = fb_info->var.xres = info->page->width; 422 fb_info->var.xres_virtual = fb_info->var.xres = video[KPARAM_WIDTH];
305 fb_info->var.yres_virtual = fb_info->var.yres = info->page->height; 423 fb_info->var.yres_virtual = fb_info->var.yres = video[KPARAM_HEIGHT];
306 fb_info->var.bits_per_pixel = info->page->depth; 424 fb_info->var.bits_per_pixel = XENFB_DEPTH;
307 425
308 fb_info->var.red = (struct fb_bitfield){16, 8, 0}; 426 fb_info->var.red = (struct fb_bitfield){16, 8, 0};
309 fb_info->var.green = (struct fb_bitfield){8, 8, 0}; 427 fb_info->var.green = (struct fb_bitfield){8, 8, 0};
@@ -315,9 +433,9 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
315 fb_info->var.vmode = FB_VMODE_NONINTERLACED; 433 fb_info->var.vmode = FB_VMODE_NONINTERLACED;
316 434
317 fb_info->fix.visual = FB_VISUAL_TRUECOLOR; 435 fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
318 fb_info->fix.line_length = info->page->line_length; 436 fb_info->fix.line_length = fb_info->var.xres * XENFB_DEPTH / 8;
319 fb_info->fix.smem_start = 0; 437 fb_info->fix.smem_start = 0;
320 fb_info->fix.smem_len = xenfb_mem_len; 438 fb_info->fix.smem_len = fb_size;
321 strcpy(fb_info->fix.id, "xen"); 439 strcpy(fb_info->fix.id, "xen");
322 fb_info->fix.type = FB_TYPE_PACKED_PIXELS; 440 fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
323 fb_info->fix.accel = FB_ACCEL_NONE; 441 fb_info->fix.accel = FB_ACCEL_NONE;
@@ -334,6 +452,8 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
334 fb_info->fbdefio = &xenfb_defio; 452 fb_info->fbdefio = &xenfb_defio;
335 fb_deferred_io_init(fb_info); 453 fb_deferred_io_init(fb_info);
336 454
455 xenfb_init_shared_page(info, fb_info);
456
337 ret = register_framebuffer(fb_info); 457 ret = register_framebuffer(fb_info);
338 if (ret) { 458 if (ret) {
339 fb_deferred_io_cleanup(fb_info); 459 fb_deferred_io_cleanup(fb_info);
@@ -348,6 +468,7 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
348 if (ret < 0) 468 if (ret < 0)
349 goto error; 469 goto error;
350 470
471 xenfb_make_preferred_console();
351 return 0; 472 return 0;
352 473
353 error_nomem: 474 error_nomem:
@@ -358,12 +479,34 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
358 return ret; 479 return ret;
359} 480}
360 481
482static __devinit void
483xenfb_make_preferred_console(void)
484{
485 struct console *c;
486
487 if (console_set_on_cmdline)
488 return;
489
490 acquire_console_sem();
491 for (c = console_drivers; c; c = c->next) {
492 if (!strcmp(c->name, "tty") && c->index == 0)
493 break;
494 }
495 release_console_sem();
496 if (c) {
497 unregister_console(c);
498 c->flags |= CON_CONSDEV;
499 c->flags &= ~CON_PRINTBUFFER; /* don't print again */
500 register_console(c);
501 }
502}
503
361static int xenfb_resume(struct xenbus_device *dev) 504static int xenfb_resume(struct xenbus_device *dev)
362{ 505{
363 struct xenfb_info *info = dev->dev.driver_data; 506 struct xenfb_info *info = dev->dev.driver_data;
364 507
365 xenfb_disconnect_backend(info); 508 xenfb_disconnect_backend(info);
366 xenfb_init_shared_page(info); 509 xenfb_init_shared_page(info, info->fb_info);
367 return xenfb_connect_backend(dev, info); 510 return xenfb_connect_backend(dev, info);
368} 511}
369 512
@@ -391,20 +534,23 @@ static unsigned long vmalloc_to_mfn(void *address)
391 return pfn_to_mfn(vmalloc_to_pfn(address)); 534 return pfn_to_mfn(vmalloc_to_pfn(address));
392} 535}
393 536
394static void xenfb_init_shared_page(struct xenfb_info *info) 537static void xenfb_init_shared_page(struct xenfb_info *info,
538 struct fb_info *fb_info)
395{ 539{
396 int i; 540 int i;
541 int epd = PAGE_SIZE / sizeof(info->mfns[0]);
397 542
398 for (i = 0; i < info->nr_pages; i++) 543 for (i = 0; i < info->nr_pages; i++)
399 info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE); 544 info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
400 545
401 info->page->pd[0] = vmalloc_to_mfn(info->mfns); 546 for (i = 0; i * epd < info->nr_pages; i++)
402 info->page->pd[1] = 0; 547 info->page->pd[i] = vmalloc_to_mfn(&info->mfns[i * epd]);
403 info->page->width = XENFB_WIDTH; 548
404 info->page->height = XENFB_HEIGHT; 549 info->page->width = fb_info->var.xres;
405 info->page->depth = XENFB_DEPTH; 550 info->page->height = fb_info->var.yres;
406 info->page->line_length = (info->page->depth / 8) * info->page->width; 551 info->page->depth = fb_info->var.bits_per_pixel;
407 info->page->mem_length = xenfb_mem_len; 552 info->page->line_length = fb_info->fix.line_length;
553 info->page->mem_length = fb_info->fix.smem_len;
408 info->page->in_cons = info->page->in_prod = 0; 554 info->page->in_cons = info->page->in_prod = 0;
409 info->page->out_cons = info->page->out_prod = 0; 555 info->page->out_cons = info->page->out_prod = 0;
410} 556}
@@ -504,6 +650,11 @@ InitWait:
504 val = 0; 650 val = 0;
505 if (val) 651 if (val)
506 info->update_wanted = 1; 652 info->update_wanted = 1;
653
654 if (xenbus_scanf(XBT_NIL, dev->otherend,
655 "feature-resize", "%d", &val) < 0)
656 val = 0;
657 info->feature_resize = val;
507 break; 658 break;
508 659
509 case XenbusStateClosing: 660 case XenbusStateClosing:
@@ -547,4 +698,6 @@ static void __exit xenfb_cleanup(void)
547module_init(xenfb_init); 698module_init(xenfb_init);
548module_exit(xenfb_cleanup); 699module_exit(xenfb_cleanup);
549 700
701MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");
550MODULE_LICENSE("GPL"); 702MODULE_LICENSE("GPL");
703MODULE_ALIAS("xen:vfb");