Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
864d65fb
Commit
864d65fb
authored
Dec 10, 2002
by
James Simmons
Committed by
James Simmons
Dec 10, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixes from the PPC guys. Lots of small fixes.
parent
58ff17ad
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
101 additions
and
105 deletions
+101
-105
CREDITS
CREDITS
+1
-0
MAINTAINERS
MAINTAINERS
+1
-1
drivers/video/Kconfig
drivers/video/Kconfig
+1
-1
drivers/video/aty/atyfb_base.c
drivers/video/aty/atyfb_base.c
+5
-25
drivers/video/aty128fb.c
drivers/video/aty128fb.c
+64
-36
drivers/video/console/fbcon.c
drivers/video/console/fbcon.c
+5
-2
drivers/video/controlfb.c
drivers/video/controlfb.c
+11
-26
drivers/video/fbmem.c
drivers/video/fbmem.c
+6
-8
drivers/video/tdfxfb.c
drivers/video/tdfxfb.c
+4
-2
drivers/video/vgastate.c
drivers/video/vgastate.c
+3
-4
No files found.
CREDITS
View file @
864d65fb
...
@@ -2844,6 +2844,7 @@ S: 76131 Karlsruhe
...
@@ -2844,6 +2844,7 @@ S: 76131 Karlsruhe
S: Germany
S: Germany
N: James Simmons
N: James Simmons
E: jsimmons@infradead.org
E: jsimmons@users.sf.net
E: jsimmons@users.sf.net
D: Frame buffer device maintainer
D: Frame buffer device maintainer
D: input layer developement
D: input layer developement
...
...
MAINTAINERS
View file @
864d65fb
...
@@ -644,7 +644,7 @@ S: Supported
...
@@ -644,7 +644,7 @@ S: Supported
FRAMEBUFFER LAYER
FRAMEBUFFER LAYER
P: James Simmons, Geert Uytterhoeven
P: James Simmons, Geert Uytterhoeven
M: jsimmons@
users.sf.net
, geert@linux-m68k.org
M: jsimmons@
infradead.org
, geert@linux-m68k.org
L: linux-fbdev-devel@lists.sourceforge.net
L: linux-fbdev-devel@lists.sourceforge.net
W: http://www.linux-fbdev.org
W: http://www.linux-fbdev.org
S: Supported
S: Supported
...
...
drivers/video/Kconfig
View file @
864d65fb
...
@@ -759,7 +759,7 @@ config FB_TRIDENT
...
@@ -759,7 +759,7 @@ config FB_TRIDENT
The driver is also available as a module ( = code which can be
The driver is also available as a module ( = code which can be
inserted and removed from the running kernel whenever you want). The
inserted and removed from the running kernel whenever you want). The
module will be called
riva
fb.o. If you want to compile it as a
module will be called
trident
fb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
module, say M here and read <file:Documentation/modules.txt>.
config FB_PM3
config FB_PM3
...
...
drivers/video/aty/atyfb_base.c
View file @
864d65fb
...
@@ -70,7 +70,7 @@
...
@@ -70,7 +70,7 @@
#ifdef __powerpc__
#ifdef __powerpc__
#include <asm/prom.h>
#include <asm/prom.h>
#include
<video/macmodes.h>
#include
"../macmodes.h"
#endif
#endif
#ifdef __sparc__
#ifdef __sparc__
#include <asm/pbm.h>
#include <asm/pbm.h>
...
@@ -84,9 +84,6 @@
...
@@ -84,9 +84,6 @@
#ifdef CONFIG_BOOTX_TEXT
#ifdef CONFIG_BOOTX_TEXT
#include <asm/btext.h>
#include <asm/btext.h>
#endif
#endif
#ifdef CONFIG_NVRAM
#include <linux/nvram.h>
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
#ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h>
#include <asm/backlight.h>
#endif
#endif
...
@@ -226,14 +223,9 @@ static char *mode_option __initdata = NULL;
...
@@ -226,14 +223,9 @@ static char *mode_option __initdata = NULL;
#endif
#endif
#ifdef CONFIG_PPC
#ifdef CONFIG_PPC
#ifdef CONFIG_NVRAM_NOT_DEFINED
static
int
default_vmode
__initdata
=
VMODE_NVRAM
;
static
int
default_cmode
__initdata
=
CMODE_NVRAM
;
#else
static
int
default_vmode
__initdata
=
VMODE_CHOOSE
;
static
int
default_vmode
__initdata
=
VMODE_CHOOSE
;
static
int
default_cmode
__initdata
=
CMODE_CHOOSE
;
static
int
default_cmode
__initdata
=
CMODE_CHOOSE
;
#endif
#endif
#endif
#ifdef CONFIG_ATARI
#ifdef CONFIG_ATARI
static
unsigned
int
mach64_count
__initdata
=
0
;
static
unsigned
int
mach64_count
__initdata
=
0
;
...
@@ -1412,16 +1404,16 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
...
@@ -1412,16 +1404,16 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
static
int
aty_sleep_notify
(
struct
pmu_sleep_notifier
*
self
,
int
when
)
static
int
aty_sleep_notify
(
struct
pmu_sleep_notifier
*
self
,
int
when
)
{
{
struct
fb_info
*
info
;
struct
fb_info
*
info
;
struct
atyfb_par
*
par
=
(
struct
atyfb_par
*
)
info
->
fb
.
par
;
struct
atyfb_par
*
par
;
int
result
;
int
result
;
result
=
PBOOK_SLEEP_OK
;
result
=
PBOOK_SLEEP_OK
;
for
(
info
=
first_display
;
info
!=
NULL
;
info
=
par
->
next
)
{
for
(
info
=
first_display
;
info
!=
NULL
;
info
=
par
->
next
)
{
struct
fb_fix_screeninfo
fix
;
int
nb
;
int
nb
;
nb
=
fb_display
[
fg_console
].
var
.
yres
*
info
->
fix
.
line_length
;
par
=
(
struct
atyfb_par
*
)
info
->
fb
.
par
;
nb
=
info
->
var
.
yres
*
info
->
fix
.
line_length
;
switch
(
when
)
{
switch
(
when
)
{
case
PBOOK_SLEEP_REQUEST
:
case
PBOOK_SLEEP_REQUEST
:
...
@@ -1439,7 +1431,7 @@ static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
...
@@ -1439,7 +1431,7 @@ static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
if
(
par
->
blitter_may_be_busy
)
if
(
par
->
blitter_may_be_busy
)
wait_for_idle
(
par
);
wait_for_idle
(
par
);
/* Stop accel engine (stop bus mastering) */
/* Stop accel engine (stop bus mastering) */
if
(
par
->
accel_flags
&
FB_ACCELF_TEXT
)
if
(
info
->
accel_flags
&
FB_ACCELF_TEXT
)
aty_reset_engine
(
par
);
aty_reset_engine
(
par
);
/* Backup fb content */
/* Backup fb content */
...
@@ -1844,14 +1836,6 @@ static int __init aty_init(struct fb_info *info, const char *name)
...
@@ -1844,14 +1836,6 @@ static int __init aty_init(struct fb_info *info, const char *name)
(
&
var
,
info
,
mode_option
,
8
))
(
&
var
,
info
,
mode_option
,
8
))
var
=
default_var
;
var
=
default_var
;
}
else
{
}
else
{
#ifdef CONFIG_NVRAM
if
(
default_vmode
==
VMODE_NVRAM
)
{
default_vmode
=
nvram_read_byte
(
NV_VMODE
);
if
(
default_vmode
<=
0
||
default_vmode
>
VMODE_MAX
)
default_vmode
=
VMODE_CHOOSE
;
}
#endif
if
(
default_vmode
==
VMODE_CHOOSE
)
{
if
(
default_vmode
==
VMODE_CHOOSE
)
{
if
(
M64_HAS
(
G3_PB_1024x768
))
if
(
M64_HAS
(
G3_PB_1024x768
))
/* G3 PowerBook with 1024x768 LCD */
/* G3 PowerBook with 1024x768 LCD */
...
@@ -1873,10 +1857,6 @@ static int __init aty_init(struct fb_info *info, const char *name)
...
@@ -1873,10 +1857,6 @@ static int __init aty_init(struct fb_info *info, const char *name)
if
(
default_vmode
<=
0
if
(
default_vmode
<=
0
||
default_vmode
>
VMODE_MAX
)
||
default_vmode
>
VMODE_MAX
)
default_vmode
=
VMODE_640_480_60
;
default_vmode
=
VMODE_640_480_60
;
#ifdef CONFIG_NVRAM
if
(
default_cmode
==
CMODE_NVRAM
)
default_cmode
=
nvram_read_byte
(
NV_CMODE
);
#endif
if
(
default_cmode
<
CMODE_8
if
(
default_cmode
<
CMODE_8
||
default_cmode
>
CMODE_32
)
||
default_cmode
>
CMODE_32
)
default_cmode
=
CMODE_8
;
default_cmode
=
CMODE_8
;
...
...
drivers/video/aty128fb.c
View file @
864d65fb
...
@@ -65,10 +65,7 @@
...
@@ -65,10 +65,7 @@
#ifdef CONFIG_ALL_PPC
#ifdef CONFIG_ALL_PPC
#include <asm/prom.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/pci-bridge.h>
#include <video/macmodes.h>
#include "macmodes.h"
#ifdef CONFIG_NVRAM
#include <linux/nvram.h>
#endif
#endif
#endif
#ifdef CONFIG_ADB_PMU
#ifdef CONFIG_ADB_PMU
...
@@ -285,7 +282,6 @@ struct aty128_constants {
...
@@ -285,7 +282,6 @@ struct aty128_constants {
struct
aty128_crtc
{
struct
aty128_crtc
{
u32
gen_cntl
;
u32
gen_cntl
;
u32
ext_cntl
;
u32
h_total
,
h_sync_strt_wid
;
u32
h_total
,
h_sync_strt_wid
;
u32
v_total
,
v_sync_strt_wid
;
u32
v_total
,
v_sync_strt_wid
;
u32
pitch
;
u32
pitch
;
...
@@ -326,10 +322,13 @@ struct aty128fb_par {
...
@@ -326,10 +322,13 @@ struct aty128fb_par {
unsigned
char
*
save_framebuffer
;
unsigned
char
*
save_framebuffer
;
int
pm_reg
;
int
pm_reg
;
int
crt_on
,
lcd_on
;
int
crt_on
,
lcd_on
;
struct
pci_dev
*
pdev
;
struct
fb_info
*
next
;
#endif
#endif
unsigned
char
red
[
64
];
/* see comments in aty128fb_setcolreg */
u8
red
[
32
];
/* see aty128fb_setcolreg */
unsigned
char
green
[
64
];
u8
green
[
64
];
unsigned
char
blue
[
64
];
u8
blue
[
32
];
u32
pseudo_palette
[
16
];
/* used for TRUECOLOR */
};
};
#ifdef CONFIG_PMAC_PBOOK
#ifdef CONFIG_PMAC_PBOOK
...
@@ -337,6 +336,7 @@ int aty128_sleep_notify(struct pmu_sleep_notifier *self, int when);
...
@@ -337,6 +336,7 @@ int aty128_sleep_notify(struct pmu_sleep_notifier *self, int when);
static
struct
pmu_sleep_notifier
aty128_sleep_notifier
=
{
static
struct
pmu_sleep_notifier
aty128_sleep_notifier
=
{
aty128_sleep_notify
,
SLEEP_LEVEL_VIDEO
,
aty128_sleep_notify
,
SLEEP_LEVEL_VIDEO
,
};
};
static
struct
fb_info
*
aty128_fb
=
NULL
;
#endif
#endif
#define round_div(n, d) ((n+(d/2))/d)
#define round_div(n, d) ((n+(d/2))/d)
...
@@ -1203,7 +1203,11 @@ aty128fb_set_par(struct fb_info *info)
...
@@ -1203,7 +1203,11 @@ aty128fb_set_par(struct fb_info *info)
{
{
struct
aty128fb_par
*
par
=
info
->
par
;
struct
aty128fb_par
*
par
=
info
->
par
;
u32
config
;
u32
config
;
int
err
;
if
((
err
=
aty128_decode_var
(
&
info
->
var
,
par
))
!=
0
)
return
err
;
if
(
par
->
blitter_may_be_busy
)
if
(
par
->
blitter_may_be_busy
)
wait_for_idle
(
par
);
wait_for_idle
(
par
);
...
@@ -1271,15 +1275,22 @@ static int
...
@@ -1271,15 +1275,22 @@ static int
aty128_decode_var
(
struct
fb_var_screeninfo
*
var
,
struct
aty128fb_par
*
par
)
aty128_decode_var
(
struct
fb_var_screeninfo
*
var
,
struct
aty128fb_par
*
par
)
{
{
int
err
;
int
err
;
struct
aty128_crtc
crtc
;
struct
aty128_pll
pll
;
struct
aty128_ddafifo
fifo_reg
;
if
((
err
=
aty128_var_to_crtc
(
var
,
&
par
->
crtc
,
par
)))
if
((
err
=
aty128_var_to_crtc
(
var
,
&
crtc
,
par
)))
return
err
;
return
err
;
if
((
err
=
aty128_var_to_pll
(
var
->
pixclock
,
&
p
ar
->
p
ll
,
par
)))
if
((
err
=
aty128_var_to_pll
(
var
->
pixclock
,
&
pll
,
par
)))
return
err
;
return
err
;
if
((
err
=
aty128_ddafifo
(
&
par
->
fifo_reg
,
&
par
->
pll
,
par
->
crtc
.
depth
,
par
)))
if
((
err
=
aty128_ddafifo
(
&
fifo_reg
,
&
pll
,
crtc
.
depth
,
par
)))
return
err
;
return
err
;
par
->
crtc
=
crtc
;
par
->
pll
=
pll
;
par
->
fifo_reg
=
fifo_reg
;
par
->
accel_flags
=
var
->
accel_flags
;
par
->
accel_flags
=
var
->
accel_flags
;
return
0
;
return
0
;
...
@@ -1312,12 +1323,13 @@ aty128_encode_var(struct fb_var_screeninfo *var,
...
@@ -1312,12 +1323,13 @@ aty128_encode_var(struct fb_var_screeninfo *var,
static
int
static
int
aty128fb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
aty128fb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
{
{
struct
aty128fb_par
*
par
=
info
->
par
;
struct
aty128fb_par
par
;
int
err
;
int
err
;
if
((
err
=
aty128_decode_var
(
var
,
par
))
!=
0
)
par
=
*
(
struct
aty128fb_par
*
)
info
->
par
;
if
((
err
=
aty128_decode_var
(
var
,
&
par
))
!=
0
)
return
err
;
return
err
;
aty128_encode_var
(
var
,
par
);
aty128_encode_var
(
var
,
&
par
);
return
0
;
return
0
;
}
}
...
@@ -1415,7 +1427,7 @@ aty128fb_setup(char *options)
...
@@ -1415,7 +1427,7 @@ aty128fb_setup(char *options)
}
}
#endif
#endif
#ifdef CONFIG_ALL_PPC
#ifdef CONFIG_ALL_PPC
/* vmode and cmode deprec
i
ated */
/* vmode and cmode deprecated */
if
(
!
strncmp
(
this_opt
,
"vmode:"
,
6
))
{
if
(
!
strncmp
(
this_opt
,
"vmode:"
,
6
))
{
unsigned
int
vmode
=
simple_strtoul
(
this_opt
+
6
,
NULL
,
0
);
unsigned
int
vmode
=
simple_strtoul
(
this_opt
+
6
,
NULL
,
0
);
if
(
vmode
>
0
&&
vmode
<=
VMODE_MAX
)
if
(
vmode
>
0
&&
vmode
<=
VMODE_MAX
)
...
@@ -1602,7 +1614,12 @@ aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
...
@@ -1602,7 +1614,12 @@ aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
#endif
/* CONFIG_PMAC_BACKLIGHT */
#endif
/* CONFIG_PMAC_BACKLIGHT */
#ifdef CONFIG_PMAC_PBOOK
#ifdef CONFIG_PMAC_PBOOK
par
->
pm_reg
=
pci_find_capability
(
pdev
,
PCI_CAP_ID_PM
);
par
->
pm_reg
=
pci_find_capability
(
pdev
,
PCI_CAP_ID_PM
);
pmu_register_sleep_notifier
(
&
aty128_sleep_notifier
);
if
(
aty128_fb
==
NULL
)
{
/* XXX can only put one chip to sleep */
aty128_fb
=
info
;
}
else
printk
(
KERN_WARNING
"aty128fb: can only sleep one Rage 128
\n
"
);
par
->
pdev
=
pdev
;
#endif
#endif
printk
(
KERN_INFO
"fb%d: %s frame buffer device on %s
\n
"
,
printk
(
KERN_INFO
"fb%d: %s frame buffer device on %s
\n
"
,
...
@@ -1647,8 +1664,7 @@ aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
...
@@ -1647,8 +1664,7 @@ aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
/* We have the resources. Now virtualize them */
/* We have the resources. Now virtualize them */
size
=
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
aty128fb_par
)
+
size
=
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
aty128fb_par
);
sizeof
(
u32
)
*
16
;
if
(
!
(
info
=
kmalloc
(
size
,
GFP_ATOMIC
)))
{
if
(
!
(
info
=
kmalloc
(
size
,
GFP_ATOMIC
)))
{
printk
(
KERN_ERR
"aty128fb: can't alloc fb_info_aty128
\n
"
);
printk
(
KERN_ERR
"aty128fb: can't alloc fb_info_aty128
\n
"
);
goto
err_unmap_out
;
goto
err_unmap_out
;
...
@@ -1656,9 +1672,7 @@ aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
...
@@ -1656,9 +1672,7 @@ aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
memset
(
info
,
0
,
size
);
memset
(
info
,
0
,
size
);
par
=
(
struct
aty128fb_par
*
)(
info
+
1
);
par
=
(
struct
aty128fb_par
*
)(
info
+
1
);
info
->
pseudo_palette
=
(
void
*
)
(
par
+
1
);
info
->
pseudo_palette
=
par
->
pseudo_palette
;
memset
(
info
,
0
,
sizeof
(
struct
fb_info
));
info
->
par
=
par
;
info
->
par
=
par
;
info
->
fix
=
aty128fb_fix
;
info
->
fix
=
aty128fb_fix
;
...
@@ -1758,6 +1772,10 @@ static void __devexit aty128_remove(struct pci_dev *pdev)
...
@@ -1758,6 +1772,10 @@ static void __devexit aty128_remove(struct pci_dev *pdev)
pci_resource_len
(
pdev
,
1
));
pci_resource_len
(
pdev
,
1
));
release_mem_region
(
pci_resource_start
(
pdev
,
2
),
release_mem_region
(
pci_resource_start
(
pdev
,
2
),
pci_resource_len
(
pdev
,
2
));
pci_resource_len
(
pdev
,
2
));
#ifdef CONFIG_PMAC_PBOOK
if
(
info
==
aty128_fb
)
aty128_fb
=
NULL
;
#endif
kfree
(
info
);
kfree
(
info
);
}
}
#endif
/* CONFIG_PCI */
#endif
/* CONFIG_PCI */
...
@@ -2008,7 +2026,7 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
...
@@ -2008,7 +2026,7 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
}
}
}
}
if
(
par
->
crtc
.
depth
==
16
)
{
if
(
par
->
crtc
.
depth
==
16
&&
regno
>
0
)
{
/*
/*
* With the 5-6-5 split of bits for RGB at 16 bits/pixel, we
* With the 5-6-5 split of bits for RGB at 16 bits/pixel, we
* have 32 slots for R and B values but 64 slots for G values.
* have 32 slots for R and B values but 64 slots for G values.
...
@@ -2016,12 +2034,13 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
...
@@ -2016,12 +2034,13 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* goes in a different slot, and we have to avoid disturbing
* goes in a different slot, and we have to avoid disturbing
* the other fields in the slots we touch.
* the other fields in the slots we touch.
*/
*/
par
->
red
[
regno
]
=
red
;
par
->
green
[
regno
]
=
green
;
par
->
green
[
regno
]
=
green
;
par
->
blue
[
regno
]
=
blue
;
if
(
regno
<
32
)
{
if
(
regno
>
0
&&
regno
<
32
)
par
->
red
[
regno
]
=
red
;
par
->
blue
[
regno
]
=
blue
;
aty128_st_pal
(
regno
*
8
,
red
,
par
->
green
[
regno
*
2
],
aty128_st_pal
(
regno
*
8
,
red
,
par
->
green
[
regno
*
2
],
blue
,
par
);
blue
,
par
);
}
red
=
par
->
red
[
regno
/
2
];
red
=
par
->
red
[
regno
/
2
];
blue
=
par
->
blue
[
regno
/
2
];
blue
=
par
->
blue
[
regno
/
2
];
regno
<<=
2
;
regno
<<=
2
;
...
@@ -2213,6 +2232,7 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
...
@@ -2213,6 +2232,7 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
{
{
u32
pmgt
;
u32
pmgt
;
u16
pwr_command
;
u16
pwr_command
;
struct
pci_dev
*
pdev
=
par
->
pdev
;
if
(
!
par
->
pm_reg
)
if
(
!
par
->
pm_reg
)
return
;
return
;
...
@@ -2237,17 +2257,16 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
...
@@ -2237,17 +2257,16 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
aty_st_le32
(
BUS_CNTL1
,
0x00000010
);
aty_st_le32
(
BUS_CNTL1
,
0x00000010
);
aty_st_le32
(
MEM_POWER_MISC
,
0x0c830000
);
aty_st_le32
(
MEM_POWER_MISC
,
0x0c830000
);
mdelay
(
100
);
mdelay
(
100
);
pci_read_config_word
(
p
ar
->
p
dev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
&
pwr_command
);
pci_read_config_word
(
pdev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
&
pwr_command
);
/* Switch PCI power management to D2 */
/* Switch PCI power management to D2 */
pci_write_config_word
(
p
ar
->
p
dev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
pci_write_config_word
(
pdev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
(
pwr_command
&
~
PCI_PM_CTRL_STATE_MASK
)
|
2
);
(
pwr_command
&
~
PCI_PM_CTRL_STATE_MASK
)
|
2
);
pci_read_config_word
(
p
ar
->
p
dev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
&
pwr_command
);
pci_read_config_word
(
pdev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
&
pwr_command
);
}
else
{
}
else
{
/* Switch back PCI power management to D0 */
/* Switch back PCI power management to D0 */
mdelay
(
100
);
mdelay
(
100
);
pci_write_config_word
(
par
->
pdev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
0
);
pci_write_config_word
(
pdev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
0
);
mdelay
(
100
);
pci_read_config_word
(
pdev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
&
pwr_command
);
pci_read_config_word
(
par
->
pdev
,
par
->
pm_reg
+
PCI_PM_CTRL
,
&
pwr_command
);
mdelay
(
100
);
mdelay
(
100
);
}
}
}
}
...
@@ -2259,10 +2278,13 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
...
@@ -2259,10 +2278,13 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
int
int
aty128_sleep_notify
(
struct
pmu_sleep_notifier
*
self
,
int
when
)
aty128_sleep_notify
(
struct
pmu_sleep_notifier
*
self
,
int
when
)
{
{
int
result
=
PBOOK_SLEEP_OK
,
nb
;
int
nb
;
struct
fb_info
*
info
=
info
;
/* FIXME!!! How do find which framebuffer */
struct
fb_info
*
info
=
aty128_fb
;
struct
aty128fb_par
*
par
=
info
->
par
;
struct
aty128fb_par
*
par
;
if
(
info
==
NULL
)
return
PBOOK_SLEEP_OK
;
par
=
info
->
par
;
nb
=
info
->
var
.
yres
*
info
->
fix
.
line_length
;
nb
=
info
->
var
.
yres
*
info
->
fix
.
line_length
;
switch
(
when
)
{
switch
(
when
)
{
...
@@ -2311,17 +2333,23 @@ aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
...
@@ -2311,17 +2333,23 @@ aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
aty128fb_blank
(
0
,
info
);
aty128fb_blank
(
0
,
info
);
break
;
break
;
}
}
return
result
;
return
PBOOK_SLEEP_OK
;
}
}
#endif
/* CONFIG_PMAC_PBOOK */
#endif
/* CONFIG_PMAC_PBOOK */
int
__init
aty128fb_init
(
void
)
int
__init
aty128fb_init
(
void
)
{
{
#ifdef CONFIG_PMAC_PBOOK
pmu_register_sleep_notifier
(
&
aty128_sleep_notifier
);
#endif
return
pci_module_init
(
&
aty128fb_driver
);
return
pci_module_init
(
&
aty128fb_driver
);
}
}
static
void
__exit
aty128fb_exit
(
void
)
static
void
__exit
aty128fb_exit
(
void
)
{
{
#ifdef CONFIG_PMAC_PBOOK
pmu_unregister_sleep_notifier
(
&
aty128_sleep_notifier
);
#endif
pci_unregister_driver
(
&
aty128fb_driver
);
pci_unregister_driver
(
&
aty128fb_driver
);
}
}
...
...
drivers/video/console/fbcon.c
View file @
864d65fb
...
@@ -291,7 +291,10 @@ void gen_set_disp(int con, struct fb_info *info)
...
@@ -291,7 +291,10 @@ void gen_set_disp(int con, struct fb_info *info)
struct
display
*
display
=
fb_display
+
con
;
struct
display
*
display
=
fb_display
+
con
;
display
->
can_soft_blank
=
info
->
fbops
->
fb_blank
?
1
:
0
;
display
->
can_soft_blank
=
info
->
fbops
->
fb_blank
?
1
:
0
;
display
->
scrollmode
=
SCROLL_YNOMOVE
;
if
(
info
->
var
.
accel_flags
)
display
->
scrollmode
=
SCROLL_YNOMOVE
;
else
display
->
scrollmode
=
SCROLL_YREDRAW
;
fbcon_changevar
(
con
);
fbcon_changevar
(
con
);
return
;
return
;
}
}
...
@@ -2633,7 +2636,7 @@ static void __init fbcon_set_logo(struct fb_info *info, u8 *logo, int needs_logo
...
@@ -2633,7 +2636,7 @@ static void __init fbcon_set_logo(struct fb_info *info, u8 *logo, int needs_logo
default:
default:
for
(
i
=
0
;
i
<
(
LOGO_W
*
LOGO_H
)
/
8
;
i
++
)
for
(
i
=
0
;
i
<
(
LOGO_W
*
LOGO_H
)
/
8
;
i
++
)
for
(
j
=
0
;
j
<
8
;
j
++
)
for
(
j
=
0
;
j
<
8
;
j
++
)
logo
[
i
*
2
]
=
(
linux_logo_bw
[
i
]
&
(
7
-
j
))
?
logo
[
i
*
8
+
j
]
=
(
linux_logo_bw
[
i
]
&
(
7
-
j
))
?
((
needs_logo
==
1
)
?
1
:
0
)
:
((
needs_logo
==
1
)
?
1
:
0
)
:
((
needs_logo
==
1
)
?
0
:
1
);
((
needs_logo
==
1
)
?
0
:
1
);
...
...
drivers/video/controlfb.c
View file @
864d65fb
...
@@ -22,6 +22,10 @@
...
@@ -22,6 +22,10 @@
* control.c: Console support for PowerMac "control" display adaptor.
* control.c: Console support for PowerMac "control" display adaptor.
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 1996 Paul Mackerras
*
*
* Updated to 2.5 framebuffer API by Ben Herrenschmidt
* <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>,
* and James Simmons <jsimmons@infradead.org>.
*
* This file is subject to the terms and conditions of the GNU General Public
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* License. See the file COPYING in the main directory of this archive for
* more details.
* more details.
...
@@ -50,12 +54,7 @@
...
@@ -50,12 +54,7 @@
#include <asm/pgtable.h>
#include <asm/pgtable.h>
#include <asm/btext.h>
#include <asm/btext.h>
#include <video/fbcon.h>
#include "macmodes.h"
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb32.h>
#include <video/macmodes.h>
#include "controlfb.h"
#include "controlfb.h"
struct
fb_par_control
{
struct
fb_par_control
{
...
@@ -97,7 +96,6 @@ static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninf
...
@@ -97,7 +96,6 @@ static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninf
struct
fb_info_control
{
struct
fb_info_control
{
struct
fb_info
info
;
struct
fb_info
info
;
struct
display
display
;
/* Will disappear */
struct
fb_par_control
par
;
struct
fb_par_control
par
;
u32
pseudo_palette
[
17
];
u32
pseudo_palette
[
17
];
...
@@ -119,14 +117,14 @@ struct fb_info_control {
...
@@ -119,14 +117,14 @@ struct fb_info_control {
};
};
/* control register access macro */
/* control register access macro */
#define CNTRL_REG(INFO,REG) (&(((INFO)->control_regs->
##
REG).r))
#define CNTRL_REG(INFO,REG) (&(((INFO)->control_regs->REG).r))
/******************** Prototypes for exported functions ********************/
/******************** Prototypes for exported functions ********************/
/*
/*
* struct fb_ops
* struct fb_ops
*/
*/
static
int
controlfb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
static
int
controlfb_pan_display
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
);
struct
fb_info
*
info
);
static
int
controlfb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
static
int
controlfb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
info
);
u_int
transp
,
struct
fb_info
*
info
);
...
@@ -171,11 +169,8 @@ static int default_cmode __initdata = CMODE_NVRAM;
...
@@ -171,11 +169,8 @@ static int default_cmode __initdata = CMODE_NVRAM;
static
struct
fb_ops
controlfb_ops
=
{
static
struct
fb_ops
controlfb_ops
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
fb_set_var
=
gen_set_var
,
.
fb_check_var
=
controlfb_check_var
,
.
fb_check_var
=
controlfb_check_var
,
.
fb_set_par
=
controlfb_set_par
,
.
fb_set_par
=
controlfb_set_par
,
.
fb_get_cmap
=
gen_get_cmap
,
.
fb_set_cmap
=
gen_set_cmap
,
.
fb_setcolreg
=
controlfb_setcolreg
,
.
fb_setcolreg
=
controlfb_setcolreg
,
.
fb_pan_display
=
controlfb_pan_display
,
.
fb_pan_display
=
controlfb_pan_display
,
.
fb_blank
=
controlfb_blank
,
.
fb_blank
=
controlfb_blank
,
...
@@ -265,8 +260,8 @@ static inline void set_screen_start(int xoffset, int yoffset,
...
@@ -265,8 +260,8 @@ static inline void set_screen_start(int xoffset, int yoffset,
}
}
static
int
controlfb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
static
int
controlfb_pan_display
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
struct
fb_info
*
info
)
{
{
unsigned
int
xoffset
,
hstep
;
unsigned
int
xoffset
,
hstep
;
struct
fb_info_control
*
p
=
(
struct
fb_info_control
*
)
info
;
struct
fb_info_control
*
p
=
(
struct
fb_info_control
*
)
info
;
...
@@ -483,7 +478,7 @@ static int __init init_control(struct fb_info_control *p)
...
@@ -483,7 +478,7 @@ static int __init init_control(struct fb_info_control *p)
/* Apply default var */
/* Apply default var */
p
->
info
.
var
=
var
;
p
->
info
.
var
=
var
;
var
.
activate
=
FB_ACTIVATE_NOW
;
var
.
activate
=
FB_ACTIVATE_NOW
;
rc
=
gen_set_var
(
&
var
,
-
1
,
&
p
->
info
);
rc
=
fb_set_var
(
&
var
,
&
p
->
info
);
if
(
rc
&&
(
vmode
!=
VMODE_640_480_60
||
cmode
!=
CMODE_8
))
if
(
rc
&&
(
vmode
!=
VMODE_640_480_60
||
cmode
!=
CMODE_8
))
goto
try_again
;
goto
try_again
;
...
@@ -491,7 +486,7 @@ static int __init init_control(struct fb_info_control *p)
...
@@ -491,7 +486,7 @@ static int __init init_control(struct fb_info_control *p)
if
(
register_framebuffer
(
&
p
->
info
)
<
0
)
if
(
register_framebuffer
(
&
p
->
info
)
<
0
)
return
-
ENXIO
;
return
-
ENXIO
;
printk
(
KERN_INFO
"fb%d: control display adapter
\n
"
,
GET_FB_IDX
(
p
->
info
.
node
));
printk
(
KERN_INFO
"fb%d: control display adapter
\n
"
,
minor
(
p
->
info
.
node
));
return
0
;
return
0
;
}
}
...
@@ -1015,22 +1010,12 @@ static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeni
...
@@ -1015,22 +1010,12 @@ static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeni
static
void
__init
control_init_info
(
struct
fb_info
*
info
,
struct
fb_info_control
*
p
)
static
void
__init
control_init_info
(
struct
fb_info
*
info
,
struct
fb_info_control
*
p
)
{
{
/* Fill fb_info */
/* Fill fb_info */
strcpy
(
info
->
modename
,
"control"
);
info
->
currcon
=
-
1
;
info
->
par
=
&
p
->
par
;
info
->
par
=
&
p
->
par
;
info
->
node
=
NODEV
;
info
->
node
=
NODEV
;
info
->
fbops
=
&
controlfb_ops
;
info
->
fbops
=
&
controlfb_ops
;
info
->
disp
=
&
p
->
display
;
info
->
pseudo_palette
=
p
->
pseudo_palette
;
info
->
pseudo_palette
=
p
->
pseudo_palette
;
info
->
flags
=
FBINFO_FLAG_DEFAULT
;
info
->
flags
=
FBINFO_FLAG_DEFAULT
;
strncpy
(
info
->
fontname
,
fontname
,
sizeof
(
info
->
fontname
));
info
->
fontname
[
sizeof
(
info
->
fontname
)
-
1
]
=
0
;
info
->
changevar
=
NULL
;
info
->
display_fg
=
NULL
;
info
->
screen_base
=
(
char
*
)
p
->
frame_buffer
+
CTRLFB_OFF
;
info
->
screen_base
=
(
char
*
)
p
->
frame_buffer
+
CTRLFB_OFF
;
info
->
changevar
=
NULL
;
info
->
switch_con
=
gen_switch
;
info
->
updatevar
=
gen_update_var
;
fb_alloc_cmap
(
&
info
->
cmap
,
256
,
0
);
fb_alloc_cmap
(
&
info
->
cmap
,
256
,
0
);
...
...
drivers/video/fbmem.c
View file @
864d65fb
...
@@ -466,16 +466,12 @@ int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
...
@@ -466,16 +466,12 @@ int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
int
yoffset
=
var
->
yoffset
;
int
yoffset
=
var
->
yoffset
;
int
err
;
int
err
;
if
(
xoffset
<
0
||
yoffset
<
0
||
if
(
xoffset
<
0
||
yoffset
<
0
||
!
info
->
fbops
->
fb_pan_display
||
xoffset
+
info
->
var
.
xres
>
info
->
var
.
xres_virtual
||
xoffset
+
info
->
var
.
xres
>
info
->
var
.
xres_virtual
||
yoffset
+
info
->
var
.
yres
>
info
->
var
.
yres_virtual
)
yoffset
+
info
->
var
.
yres
>
info
->
var
.
yres_virtual
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
info
->
fbops
->
fb_pan_display
)
{
if
((
err
=
info
->
fbops
->
fb_pan_display
(
var
,
info
)))
if
((
err
=
info
->
fbops
->
fb_pan_display
(
var
,
info
)))
return
err
;
return
err
;
else
return
-
EINVAL
;
}
info
->
var
.
xoffset
=
var
->
xoffset
;
info
->
var
.
xoffset
=
var
->
xoffset
;
info
->
var
.
yoffset
=
var
->
yoffset
;
info
->
var
.
yoffset
=
var
->
yoffset
;
if
(
var
->
vmode
&
FB_VMODE_YWRAP
)
if
(
var
->
vmode
&
FB_VMODE_YWRAP
)
...
@@ -571,6 +567,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
...
@@ -571,6 +567,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if
(
copy_from_user
(
&
cmap
,
(
void
*
)
arg
,
sizeof
(
cmap
)))
if
(
copy_from_user
(
&
cmap
,
(
void
*
)
arg
,
sizeof
(
cmap
)))
return
-
EFAULT
;
return
-
EFAULT
;
fb_copy_cmap
(
&
info
->
cmap
,
&
cmap
,
0
);
fb_copy_cmap
(
&
info
->
cmap
,
&
cmap
,
0
);
return
0
;
case
FBIOPAN_DISPLAY
:
case
FBIOPAN_DISPLAY
:
if
(
copy_from_user
(
&
var
,
(
void
*
)
arg
,
sizeof
(
var
)))
if
(
copy_from_user
(
&
var
,
(
void
*
)
arg
,
sizeof
(
var
)))
return
-
EFAULT
;
return
-
EFAULT
;
...
@@ -928,7 +925,8 @@ __setup("video=", video_setup);
...
@@ -928,7 +925,8 @@ __setup("video=", video_setup);
EXPORT_SYMBOL
(
register_framebuffer
);
EXPORT_SYMBOL
(
register_framebuffer
);
EXPORT_SYMBOL
(
unregister_framebuffer
);
EXPORT_SYMBOL
(
unregister_framebuffer
);
EXPORT_SYMBOL
(
registered_fb
);
EXPORT_SYMBOL
(
num_registered_fb
);
EXPORT_SYMBOL
(
num_registered_fb
);
EXPORT_SYMBOL
(
registered_fb
);
EXPORT_SYMBOL
(
fb_blank
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
drivers/video/tdfxfb.c
View file @
864d65fb
...
@@ -166,6 +166,7 @@ static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect);
...
@@ -166,6 +166,7 @@ static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect);
static
void
tdfxfb_copyarea
(
struct
fb_info
*
info
,
struct
fb_copyarea
*
area
);
static
void
tdfxfb_copyarea
(
struct
fb_info
*
info
,
struct
fb_copyarea
*
area
);
static
void
tdfxfb_imageblit
(
struct
fb_info
*
info
,
struct
fb_image
*
image
);
static
void
tdfxfb_imageblit
(
struct
fb_info
*
info
,
struct
fb_image
*
image
);
static
int
tdfxfb_cursor
(
struct
fb_info
*
info
,
struct
fb_cursor
*
cursor
);
static
int
tdfxfb_cursor
(
struct
fb_info
*
info
,
struct
fb_cursor
*
cursor
);
static
int
banshee_wait_idle
(
struct
fb_info
*
info
);
static
struct
fb_ops
tdfxfb_ops
=
{
static
struct
fb_ops
tdfxfb_ops
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
...
@@ -318,7 +319,7 @@ static inline void banshee_make_room(struct tdfx_par *par, int size)
...
@@ -318,7 +319,7 @@ static inline void banshee_make_room(struct tdfx_par *par, int size)
while
((
tdfx_inl
(
par
,
STATUS
)
&
0x1f
)
<
size
);
while
((
tdfx_inl
(
par
,
STATUS
)
&
0x1f
)
<
size
);
}
}
static
in
line
void
banshee_wait_idle
(
struct
fb_info
*
info
)
static
in
t
banshee_wait_idle
(
struct
fb_info
*
info
)
{
{
struct
tdfx_par
*
par
=
(
struct
tdfx_par
*
)
info
->
par
;
struct
tdfx_par
*
par
=
(
struct
tdfx_par
*
)
info
->
par
;
int
i
=
0
;
int
i
=
0
;
...
@@ -330,6 +331,7 @@ static inline void banshee_wait_idle(struct fb_info *info)
...
@@ -330,6 +331,7 @@ static inline void banshee_wait_idle(struct fb_info *info)
i
=
(
tdfx_inl
(
par
,
STATUS
)
&
STATUS_BUSY
)
?
0
:
i
+
1
;
i
=
(
tdfx_inl
(
par
,
STATUS
)
&
STATUS_BUSY
)
?
0
:
i
+
1
;
if
(
i
==
3
)
break
;
if
(
i
==
3
)
break
;
}
}
return
0
;
}
}
/*
/*
...
@@ -758,7 +760,7 @@ static int tdfxfb_set_par(struct fb_info *info)
...
@@ -758,7 +760,7 @@ static int tdfxfb_set_par(struct fb_info *info)
break
;
break
;
}
}
#endif
#endif
do_write_regs
(
par
,
&
reg
);
do_write_regs
(
info
,
&
reg
);
/* Now change fb_fix_screeninfo according to changes in par */
/* Now change fb_fix_screeninfo according to changes in par */
info
->
fix
.
line_length
=
info
->
var
.
xres
*
((
info
->
var
.
bits_per_pixel
+
7
)
>>
3
);
info
->
fix
.
line_length
=
info
->
var
.
xres
*
((
info
->
var
.
bits_per_pixel
+
7
)
>>
3
);
...
...
drivers/video/vgastate.c
View file @
864d65fb
...
@@ -111,7 +111,7 @@ static void save_vga_text(struct vgastate *state, caddr_t fbbase)
...
@@ -111,7 +111,7 @@ static void save_vga_text(struct vgastate *state, caddr_t fbbase)
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MODE
,
0x0
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MODE
,
0x0
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MISC
,
0x5
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MISC
,
0x5
);
for
(
i
=
0
;
i
<
8192
;
i
++
)
for
(
i
=
0
;
i
<
8192
;
i
++
)
saved
->
vga_text
[
i
]
=
vga_r
(
fbbase
+
2
*
8192
,
i
);
saved
->
vga_text
[
8192
+
i
]
=
vga_r
(
fbbase
+
2
*
8192
,
i
);
}
}
/* restore regs */
/* restore regs */
...
@@ -184,7 +184,7 @@ static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
...
@@ -184,7 +184,7 @@ static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_PLANE_READ
,
0x3
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_PLANE_READ
,
0x3
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MODE
,
0x0
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MODE
,
0x0
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MISC
,
0x5
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MISC
,
0x5
);
for
(
i
=
0
;
i
<
4
*
8192
;
i
++
)
for
(
i
=
0
;
i
<
state
->
memsize
;
i
++
)
vga_w
(
fbbase
,
i
,
saved
->
vga_font1
[
i
]);
vga_w
(
fbbase
,
i
,
saved
->
vga_font1
[
i
]);
}
}
...
@@ -204,8 +204,7 @@ static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
...
@@ -204,8 +204,7 @@ static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MODE
,
0x0
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MODE
,
0x0
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MISC
,
0x5
);
vga_wgfx
(
state
->
vgabase
,
VGA_GFX_MISC
,
0x5
);
for
(
i
=
0
;
i
<
8192
;
i
++
)
for
(
i
=
0
;
i
<
8192
;
i
++
)
vga_w
(
fbbase
+
2
*
8192
,
i
,
vga_w
(
fbbase
,
i
,
saved
->
vga_text
[
8192
+
i
]);
saved
->
vga_text
[
i
]);
}
}
/* unblank screen */
/* unblank screen */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment