Commit c14c4ecf authored by James Simmons's avatar James Simmons

Final updtes to the GTF code. Now the code can gnerate GTF timings regardless...

Final updtes to the GTF code. Now the code can gnerate GTF timings regardless of the validity of info->monospecs.

[ATYFB] Updates to the aty driver.
parent bac36c17
......@@ -79,6 +79,7 @@ struct atyfb_par {
u8 ram_type;
u8 mem_refresh_rate;
u8 blitter_may_be_busy;
u32 accel_flags;
#ifdef __sparc__
struct pci_mmap_map *mmap_map;
u8 mmaped;
......
......@@ -173,9 +173,6 @@ static int aty_var_to_crtc(const struct fb_info *info,
struct crtc *crtc);
static int aty_crtc_to_var(const struct crtc *crtc,
struct fb_var_screeninfo *var);
static int atyfb_encode_var(struct fb_var_screeninfo *var,
const struct atyfb_par *par,
const struct fb_info *info);
static void set_off_pitch(struct atyfb_par *par,
const struct fb_info *info);
#ifdef CONFIG_PPC
......@@ -772,11 +769,17 @@ static int aty_crtc_to_var(const struct crtc *crtc,
static int atyfb_set_par(struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
int accelmode;
struct fb_var_screeninfo *var = &info->var;
u8 tmp;
u32 i;
int err;
accelmode = info->var.accel_flags; /* hack */
if ((err = aty_var_to_crtc(info, var, &par->crtc)) ||
(err = par->pll_ops->var_to_pll(info, var->pixclock,
var->bits_per_pixel, &par->pll)))
return err;
par->accel_flags = var->accel_flags; /* hack */
if (par->blitter_may_be_busy)
wait_for_idle(par);
......@@ -786,13 +789,14 @@ static int atyfb_set_par(struct fb_info *info)
/* better call aty_StrobeClock ?? */
aty_st_8(CLOCK_CNTL + par->clk_wr_offset, CLOCK_STROBE, par);
par->dac_ops->set_dac(info, &par->pll, info->var.bits_per_pixel, accelmode);
par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel,
par->accel_flags);
par->pll_ops->set_pll(info, &par->pll);
if (!M64_HAS(INTEGRATED)) {
/* Don't forget MEM_CNTL */
i = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
switch (info->var.bits_per_pixel) {
switch (var->bits_per_pixel) {
case 8:
i |= 0x02000000;
break;
......@@ -808,7 +812,7 @@ static int atyfb_set_par(struct fb_info *info)
i = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
if (!M64_HAS(MAGIC_POSTDIV))
i |= par->mem_refresh_rate << 20;
switch (info->var.bits_per_pixel) {
switch (var->bits_per_pixel) {
case 8:
case 24:
i |= 0x00000000;
......@@ -841,20 +845,20 @@ static int atyfb_set_par(struct fb_info *info)
}
aty_st_8(DAC_MASK, 0xff, par);
info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel/8;
info->fix.visual = info->var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8;
info->fix.visual = var->bits_per_pixel <= 8 ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
/* Initialize the graphics engine */
if (info->var.accel_flags & FB_ACCELF_TEXT)
if (par->accel_flags & FB_ACCELF_TEXT)
aty_init_engine(par, info);
#ifdef CONFIG_BOOTX_TEXT
btext_update_display(info->fix.smem_start,
(((par->crtc.h_tot_disp >> 16) & 0xff) +
1) * 8,
(((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
info->var.bits_per_pixel,
par->crtc.vxres * info->var.bits_per_pixel / 8);
var->bits_per_pixel,
par->crtc.vxres * var->bits_per_pixel / 8);
#endif /* CONFIG_BOOTX_TEXT */
return 0;
}
......@@ -863,41 +867,24 @@ static int atyfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
struct crtc crtc;
union aty_pll pll;
int err;
if ((err = aty_var_to_crtc(info, var, &par->crtc)) ||
(err =
par->pll_ops->var_to_pll(info, var->pixclock, var->bits_per_pixel,
&par->pll)))
if ((err = aty_var_to_crtc(info, var, &crtc)) ||
(err = par->pll_ops->var_to_pll(info, var->pixclock,
var->bits_per_pixel, &pll)))
return err;
#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
return -EINVAL;
#endif
atyfb_encode_var(var, par, info);
return 0;
}
static int atyfb_encode_var(struct fb_var_screeninfo *var,
const struct atyfb_par *par,
const struct fb_info *info)
{
int err;
memset(var, 0, sizeof(struct fb_var_screeninfo));
if ((err = aty_crtc_to_var(&par->crtc, var)))
return err;
var->pixclock = par->pll_ops->pll_to_var(info, &par->pll);
var->height = -1;
var->width = -1;
aty_crtc_to_var(&crtc, var);
var->pixclock = par->pll_ops->pll_to_var(info, &pll);
return 0;
}
static void set_off_pitch(struct atyfb_par *par,
const struct fb_info *info)
{
......@@ -1409,7 +1396,7 @@ static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
for (info = first_display; info != NULL; info = par->next) {
int nb;
par = (struct atyfb_par *) info->fb.par;
par = (struct atyfb_par *) info->par;
nb = info->var.yres * info->fix.line_length;
switch (when) {
......@@ -1428,7 +1415,7 @@ static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
if (par->blitter_may_be_busy)
wait_for_idle(par);
/* Stop accel engine (stop bus mastering) */
if (info->accel_flags & FB_ACCELF_TEXT)
if (par->accel_flags & FB_ACCELF_TEXT)
aty_reset_engine(par);
/* Backup fb content */
......@@ -2305,9 +2292,7 @@ int __init atyfb_init(void)
#ifdef CONFIG_PMAC_PBOOK
if (first_display == NULL)
pmu_register_sleep_notifier
(&aty_sleep_notifier);
/* FIXME info->next = first_display; */
pmu_register_sleep_notifier(&aty_sleep_notifier);
default_par->next = first_display;
#endif
}
......@@ -2345,7 +2330,7 @@ int __init atyfb_init(void)
info->fix.smem_start = info->screen_base; /* Fake! */
default_par->ati_regbase = (unsigned long)ioremap(phys_guiregbase[m64_num],
0x10000) + 0xFC00ul;
info->fix.mmio_start = par->ati_regbase; /* Fake! */
info->fix.mmio_start = default_par->ati_regbase; /* Fake! */
aty_st_le32(CLOCK_CNTL, 0x12345678, default_par);
clock_r = aty_ld_le32(CLOCK_CNTL, default_par);
......@@ -2543,6 +2528,7 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
int i, scale;
u32 *pal = info->pseudo_palette;
if (regno > 255)
return 1;
......@@ -2569,17 +2555,14 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if (regno < 16)
switch (info->var.bits_per_pixel) {
case 16:
((u16 *) (info->pseudo_palette))[regno] =
(regno << 10) | (regno << 5) | regno;
pal[regno] = (regno << 10) | (regno << 5) | regno;
break;
case 24:
((u32 *) (info->pseudo_palette))[regno] =
(regno << 16) | (regno << 8) | regno;
pal[regno] = (regno << 16) | (regno << 8) | regno;
break;
case 32:
i = (regno << 8) | regno;
((u32 *) (info->pseudo_palette))[regno] =
(i << 16) | i;
pal[regno] = (i << 16) | i;
break;
}
return 0;
......
......@@ -179,6 +179,12 @@ void atyfb_copyarea(struct fb_info *info, struct fb_copyarea *area)
if (!area->width || !area->height)
return;
if (!par->accel_flags) {
if (par->blitter_may_be_busy)
wait_for_idle(par);
cfb_copyarea(info, area);
return;
}
pitch_value = info->var.xres_virtual;
if (info->var.bits_per_pixel == 24) {
......@@ -216,6 +222,12 @@ void atyfb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
if (!rect->width || !rect->height)
return;
if (!par->accel_flags) {
if (par->blitter_may_be_busy)
wait_for_idle(par);
cfb_fillrect(info, rect);
return;
}
rect->color |= (rect->color << 8);
rect->color |= (rect->color << 16);
......
......@@ -511,6 +511,9 @@ static void fb_timings_dclk(struct __fb_timings *timings)
* refresh rate. Otherwise, it will calculate timings based on
* the flag and accompanying value.
*
* If FB_IGNOREMON bit is set in @flags, monitor specs will be
* ignored and @var will be filled with the calculated timings.
*
* All calculations are based on the VESA GTF Spreadsheet
* available at VESA's public ftp (http://www.vesa.org).
*
......@@ -527,22 +530,27 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
{
struct __fb_timings timings;
u32 interlace = 1, dscan = 1;
u32 hfmin, hfmax, vfmin, vfmax;
u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
/*
* If monspecs are invalid, use values that are enough
* for 640x480@60
*/
if ((!info->monspecs.hfmax && !info->monspecs.vfmax) ||
if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
!info->monspecs.dclkmax ||
info->monspecs.hfmax < info->monspecs.hfmin ||
info->monspecs.vfmax < info->monspecs.vfmin) {
info->monspecs.vfmax < info->monspecs.vfmin ||
info->monspecs.dclkmax < info->monspecs.dclkmin) {
hfmin = 29000; hfmax = 30000;
vfmin = 60; vfmax = 60;
dclkmin = 0; dclkmax = 25000000;
} else {
hfmin = info->monspecs.hfmin;
hfmax = info->monspecs.hfmax;
vfmin = info->monspecs.vfmin;
vfmax = info->monspecs.vfmax;
dclkmin = info->monspecs.dclkmin;
dclkmax = info->monspecs.dclkmax;
}
memset(&timings, 0, sizeof(struct __fb_timings));
......@@ -557,8 +565,8 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
dscan = 2;
}
switch (flags) {
case 0: /* maximize refresh rate */
switch (flags & ~FB_IGNOREMON) {
case FB_MAXTIMINGS: /* maximize refresh rate */
timings.hfreq = hfmax;
fb_timings_hfreq(&timings);
if (timings.vfreq > vfmax) {
......@@ -566,15 +574,15 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
fb_timings_vfreq(&timings);
}
break;
case 1: /* vrefresh driven */
case FB_VSYNCTIMINGS: /* vrefresh driven */
timings.vfreq = val;
fb_timings_vfreq(&timings);
break;
case 2: /* hsync driven */
case FB_HSYNCTIMINGS: /* hsync driven */
timings.hfreq = val;
fb_timings_hfreq(&timings);
break;
case 3: /* pixelclock driven */
case FB_DCLKTIMINGS: /* pixelclock driven */
timings.dclk = PICOS2KHZ(val) * 1000;
fb_timings_dclk(&timings);
break;
......@@ -583,11 +591,12 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
}
if (timings.vfreq < vfmin || timings.vfreq > vfmax ||
timings.hfreq < hfmin || timings.hfreq > hfmax)
if (!(flags & FB_IGNOREMON) &&
(timings.vfreq < vfmin || timings.vfreq > vfmax ||
timings.hfreq < hfmin || timings.hfreq > hfmax ||
timings.dclk < dclkmin || timings.dclk > dclkmax))
return -EINVAL;
var->pixclock = KHZ2PICOS(timings.dclk/1000);
var->hsync_len = (timings.htotal * 8)/100;
var->right_margin = (timings.hblank/2) - var->hsync_len;
......@@ -616,22 +625,27 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
int fb_validate_mode(struct fb_var_screeninfo *var, struct fb_info *info)
{
u32 hfreq, vfreq, htotal, vtotal, pixclock;
u32 hfmin, hfmax, vfmin, vfmax;
u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
/*
* If monspecs are invalid, use values that are enough
* for 640x480@60
*/
if ((!info->monspecs.hfmax && !info->monspecs.vfmax) ||
if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
!info->monspecs.dclkmax ||
info->monspecs.hfmax < info->monspecs.hfmin ||
info->monspecs.vfmax < info->monspecs.vfmin) {
info->monspecs.vfmax < info->monspecs.vfmin ||
info->monspecs.dclkmax < info->monspecs.dclkmin) {
hfmin = 29000; hfmax = 30000;
vfmin = 60; vfmax = 60;
dclkmin = 0; dclkmax = 25000000;
} else {
hfmin = info->monspecs.hfmin;
hfmax = info->monspecs.hfmax;
vfmin = info->monspecs.vfmin;
vfmax = info->monspecs.vfmax;
dclkmin = info->monspecs.dclkmin;
dclkmax = info->monspecs.dclkmax;
}
if (!var->pixclock)
......
......@@ -240,6 +240,9 @@ struct fb_monspecs {
__u32 hfmax; /* hfreq upper limit (Hz) */
__u16 vfmin; /* vfreq lower limit (Hz) */
__u16 vfmax; /* vfreq upper limit (Hz) */
__u32 dclkmin; /* pixelclock lower limit (Hz) */
__u32 dclkmax; /* pixelclock upper limit (Hz) */
unsigned gtf : 1; /* supports GTF */
unsigned dpms : 1; /* supports DPMS */
};
......@@ -466,6 +469,12 @@ extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
/* drivers/video/fbmon.c */
#define FB_MAXTIMINGS 0
#define FB_VSYNCTIMINGS 1
#define FB_HSYNCTIMINGS 2
#define FB_DCLKTIMINGS 3
#define FB_IGNOREMON 0x100
extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
const struct fb_info *fb_info);
extern int fbmon_dpms(const struct fb_info *fb_info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment