Commit daf389a0 authored by Petr Vandrovec's avatar Petr Vandrovec

Use arrays for holding Matrox output drivers, it is nicer and more extensible

than current solution with per-CRTC bitmaps.
parent ca5d8440
...@@ -300,7 +300,7 @@ void DAC1064_global_init(WPMINFO2) { ...@@ -300,7 +300,7 @@ void DAC1064_global_init(WPMINFO2) {
hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN; hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN;
hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL; hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL;
hw->DACreg[POS1064_XOUTPUTCONN] = 0x01; /* output #1 enabled */ hw->DACreg[POS1064_XOUTPUTCONN] = 0x01; /* output #1 enabled */
if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) { if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1) {
if (ACCESS_FBINFO(devflags.g450dac)) { if (ACCESS_FBINFO(devflags.g450dac)) {
hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL2; hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL2;
hw->DACreg[POS1064_XOUTPUTCONN] = 0x05; /* output #1 enabled; CRTC1 connected to output #2 */ hw->DACreg[POS1064_XOUTPUTCONN] = 0x05; /* output #1 enabled; CRTC1 connected to output #2 */
...@@ -308,15 +308,15 @@ void DAC1064_global_init(WPMINFO2) { ...@@ -308,15 +308,15 @@ void DAC1064_global_init(WPMINFO2) {
hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT; hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT;
hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12; hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12;
} }
} else if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { } else if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) {
hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12; hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
hw->DACreg[POS1064_XOUTPUTCONN] = 0x09; /* output #1 enabled; CRTC2 connected to output #2 */ hw->DACreg[POS1064_XOUTPUTCONN] = 0x09; /* output #1 enabled; CRTC2 connected to output #2 */
} else if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP) } else if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1)
hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12; hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
else else
hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS; hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
if ((ACCESS_FBINFO(output.ph) | ACCESS_FBINFO(output.sh)) & MATROXFB_OUTPUT_CONN_PRIMARY) if (ACCESS_FBINFO(outputs[0]).src != MATROXFB_SRC_NONE)
hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN; hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
} }
...@@ -505,6 +505,7 @@ static int m1064_compute(void* outdev, struct my_timming* m) { ...@@ -505,6 +505,7 @@ static int m1064_compute(void* outdev, struct my_timming* m) {
} }
static struct matrox_altout m1064 = { static struct matrox_altout m1064 = {
.name = "Primary output",
.compute = m1064_compute, .compute = m1064_compute,
}; };
...@@ -651,7 +652,10 @@ static int MGA1064_preinit(WPMINFO2) { ...@@ -651,7 +652,10 @@ static int MGA1064_preinit(WPMINFO2) {
ACCESS_FBINFO(features.accel.has_cacheflush) = 1; ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor; ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
ACCESS_FBINFO(primout) = &m1064; ACCESS_FBINFO(outputs[0]).output = &m1064;
ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
ACCESS_FBINFO(outputs[0]).data = MINFO;
ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
if (ACCESS_FBINFO(devflags.noinit)) if (ACCESS_FBINFO(devflags.noinit))
return 0; /* do not modify settings */ return 0; /* do not modify settings */
...@@ -835,7 +839,10 @@ static int MGAG100_preinit(WPMINFO2) { ...@@ -835,7 +839,10 @@ static int MGAG100_preinit(WPMINFO2) {
ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100 ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100
? ACCESS_FBINFO(devflags.sgram) : 1; ? ACCESS_FBINFO(devflags.sgram) : 1;
ACCESS_FBINFO(primout) = &m1064; ACCESS_FBINFO(outputs[0]).output = &m1064;
ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
ACCESS_FBINFO(outputs[0]).data = MINFO;
ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
if (ACCESS_FBINFO(devflags.g450dac)) { if (ACCESS_FBINFO(devflags.g450dac)) {
/* we must do this always, BIOS does not do it for us /* we must do this always, BIOS does not do it for us
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
* *
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
* *
* (c) 1998,1999,2000 Petr Vandrovec <vandrove@vc.cvut.cz> * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
* *
* Portions Copyright (c) 2001 Matrox Graphics Inc. * Portions Copyright (c) 2001 Matrox Graphics Inc.
* *
* Version: 1.62 2000/11/29 * Version: 1.64 2002/06/10
* *
* MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org> * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
* *
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
#include "matroxfb_Ti3026.h" #include "matroxfb_Ti3026.h"
#include "matroxfb_misc.h" #include "matroxfb_misc.h"
#include "matroxfb_accel.h" #include "matroxfb_accel.h"
#include <linux/matroxfb.h>
#ifdef CONFIG_FB_MATROX_MILLENIUM #ifdef CONFIG_FB_MATROX_MILLENIUM
#define outTi3026 matroxfb_DAC_out #define outTi3026 matroxfb_DAC_out
...@@ -811,6 +812,10 @@ static void Ti3026_reset(WPMINFO2) { ...@@ -811,6 +812,10 @@ static void Ti3026_reset(WPMINFO2) {
ti3026_ramdac_init(PMINFO2); ti3026_ramdac_init(PMINFO2);
} }
static struct matrox_altout ti3026_output = {
.name = "Primary output",
};
static int Ti3026_preinit(WPMINFO2) { static int Ti3026_preinit(WPMINFO2) {
static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960, static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960,
1024, 1152, 1280, 1600, 1664, 1920, 1024, 1152, 1280, 1600, 1664, 1920,
...@@ -829,6 +834,11 @@ static int Ti3026_preinit(WPMINFO2) { ...@@ -829,6 +834,11 @@ static int Ti3026_preinit(WPMINFO2) {
ACCESS_FBINFO(capable.vxres) = isMilleniumII(MINFO)?vxres_mill2:vxres_mill1; ACCESS_FBINFO(capable.vxres) = isMilleniumII(MINFO)?vxres_mill2:vxres_mill1;
ACCESS_FBINFO(cursor.timer.function) = matroxfb_ti3026_flashcursor; ACCESS_FBINFO(cursor.timer.function) = matroxfb_ti3026_flashcursor;
ACCESS_FBINFO(outputs[0]).data = MINFO;
ACCESS_FBINFO(outputs[0]).output = &ti3026_output;
ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
if (ACCESS_FBINFO(devflags.noinit)) if (ACCESS_FBINFO(devflags.noinit))
return 0; return 0;
/* preserve VGA I/O, BIOS and PPC */ /* preserve VGA I/O, BIOS and PPC */
......
This diff is collapsed.
...@@ -396,12 +396,17 @@ struct matrox_accel_data { ...@@ -396,12 +396,17 @@ struct matrox_accel_data {
}; };
struct matrox_altout { struct matrox_altout {
const char *name;
int (*compute)(void* altout_dev, struct my_timming* input); int (*compute)(void* altout_dev, struct my_timming* input);
int (*program)(void* altout_dev); int (*program)(void* altout_dev);
int (*start)(void* altout_dev); int (*start)(void* altout_dev);
int (*verifymode)(void* altout_dev, u_int32_t mode); int (*verifymode)(void* altout_dev, u_int32_t mode);
}; };
#define MATROXFB_SRC_NONE 0
#define MATROXFB_SRC_CRTC1 1
#define MATROXFB_SRC_CRTC2 2
enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 }; enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 };
struct matrox_bios { struct matrox_bios {
...@@ -435,22 +440,20 @@ struct matrox_fb_info { ...@@ -435,22 +440,20 @@ struct matrox_fb_info {
struct pci_dev* pcidev; struct pci_dev* pcidev;
struct {
u_int32_t all;
u_int32_t ph;
u_int32_t sh;
} output;
struct matrox_altout* primout;
struct { struct {
struct fb_info* info; struct fb_info* info;
struct rw_semaphore lock; struct rw_semaphore lock;
} crtc2; } crtc2;
struct { struct {
struct rw_semaphore lock;
} altout;
#define MATROXFB_MAX_OUTPUTS 3
struct {
unsigned int src;
struct matrox_altout* output; struct matrox_altout* output;
void* device; void* data;
struct rw_semaphore lock;
unsigned int mode; unsigned int mode;
} altout; } outputs[MATROXFB_MAX_OUTPUTS];
#define MATROXFB_MAX_FB_DRIVERS 5 #define MATROXFB_MAX_FB_DRIVERS 5
struct matroxfb_driver* (drivers[MATROXFB_MAX_FB_DRIVERS]); struct matroxfb_driver* (drivers[MATROXFB_MAX_FB_DRIVERS]);
...@@ -539,6 +542,7 @@ struct matrox_fb_info { ...@@ -539,6 +542,7 @@ struct matrox_fb_info {
int memtype; int memtype;
int g450dac; int g450dac;
int dfp_type; int dfp_type;
int panellink; /* G400 DFP possible (not G450/G550) */
int dualhead; int dualhead;
unsigned int fbResource; unsigned int fbResource;
} devflags; } devflags;
......
...@@ -118,25 +118,22 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, ...@@ -118,25 +118,22 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
break; break;
} }
if (ACCESS_FBINFO(output.sh)) { tmp |= 0x00000001; /* enable CRTC2 */
tmp |= 0x00000001; /* enable CRTC2 */ if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) {
if (ACCESS_FBINFO(devflags.g450dac)) {
if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { tmp |= 0x00000006; /* source from secondary pixel PLL */
if (ACCESS_FBINFO(devflags.g450dac)) { /* no vidrst */
tmp |= 0x00000006; /* source from secondary pixel PLL */ } else {
/* no vidrst */ tmp |= 0x00000002; /* source from VDOCLK */
} else { tmp |= 0xC0000000; /* enable vvidrst & hvidrst */
tmp |= 0x00000002; /* source from VDOCLK */ /* MGA TVO is our clock source */
tmp |= 0xC0000000; /* enable vvidrst & hvidrst */
/* MGA TVO is our clock source */
}
} else if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) {
tmp |= 0x00000004; /* source from pixclock */
/* PIXPLL is our clock source */
} }
} else if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) {
if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) tmp |= 0x00000004; /* source from pixclock */
tmp |= 0x00100000; /* connect CRTC2 to DAC */ /* PIXPLL is our clock source */
}
if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) {
tmp |= 0x00100000; /* connect CRTC2 to DAC */
} }
if (mt->interlaced) { if (mt->interlaced) {
tmp |= 0x02000000; /* interlaced, second field is bigger, as G450 apparently ignores it */ tmp |= 0x02000000; /* interlaced, second field is bigger, as G450 apparently ignores it */
...@@ -172,6 +169,12 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, ...@@ -172,6 +169,12 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
mga_outl(0x3C4C, 0); /* data control */ mga_outl(0x3C4C, 0); /* data control */
} }
static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) {
MINFO_FROM(m2info->primary_dev);
mga_outl(0x3C10, 0x00000004); /* disable CRTC2, CRTC1->DAC1, PLL as clock source */
}
static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info, static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info,
struct display* p) { struct display* p) {
/* no acceleration for secondary head... */ /* no acceleration for secondary head... */
...@@ -411,6 +414,8 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, ...@@ -411,6 +414,8 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
if (con == m2info->fbcon.currcon) { if (con == m2info->fbcon.currcon) {
struct my_timming mt; struct my_timming mt;
unsigned int pos; unsigned int pos;
int out;
int cnt;
matroxfb_var2my(var, &mt); matroxfb_var2my(var, &mt);
/* CRTC2 delay */ /* CRTC2 delay */
...@@ -418,39 +423,38 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, ...@@ -418,39 +423,38 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
pos = (var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel >> 3; pos = (var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel >> 3;
pos += m2info->video.offbase; pos += m2info->video.offbase;
DAC1064_global_init(PMINFO2); cnt = 0;
if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) { down_read(&ACCESS_FBINFO(altout).lock);
if (ACCESS_FBINFO(primout) && ACCESS_FBINFO(primout)->compute) for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
ACCESS_FBINFO(primout)->compute(MINFO, &mt); if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) {
cnt++;
if (ACCESS_FBINFO(outputs[out]).output->compute) {
ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt);
}
}
} }
if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { up_read(&ACCESS_FBINFO(altout).lock);
down_read(&ACCESS_FBINFO(altout.lock)); if (cnt) {
if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.output)->compute) matroxfb_dh_restore(m2info, &mt, p, mode, pos);
ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt); } else {
up_read(&ACCESS_FBINFO(altout.lock)); matroxfb_dh_disable(m2info);
} }
matroxfb_dh_restore(m2info, &mt, p, mode, pos); DAC1064_global_init(PMINFO2);
DAC1064_global_restore(PMINFO2); DAC1064_global_restore(PMINFO2);
if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) { down_read(&ACCESS_FBINFO(altout).lock);
if (ACCESS_FBINFO(primout) && ACCESS_FBINFO(primout)->program) for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
ACCESS_FBINFO(primout)->program(MINFO); if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 &&
} ACCESS_FBINFO(outputs[out]).output->program) {
if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data);
down_read(&ACCESS_FBINFO(altout.lock)); }
if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.output)->program)
ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device));
up_read(&ACCESS_FBINFO(altout.lock));
}
if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) {
if (ACCESS_FBINFO(primout) && ACCESS_FBINFO(primout)->start)
ACCESS_FBINFO(primout)->start(MINFO);
} }
if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 &&
if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.output)->start) ACCESS_FBINFO(outputs[out]).output->start) {
ACCESS_FBINFO(altout.output)->start(ACCESS_FBINFO(altout.device)); ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data);
up_read(&ACCESS_FBINFO(altout.lock)); }
} }
up_read(&ACCESS_FBINFO(altout).lock);
matroxfb_dh_cfbX_init(m2info, p); matroxfb_dh_cfbX_init(m2info, p);
my_install_cmap(m2info); my_install_cmap(m2info);
} }
...@@ -563,38 +567,84 @@ static int matroxfb_dh_ioctl(struct inode* inode, ...@@ -563,38 +567,84 @@ static int matroxfb_dh_ioctl(struct inode* inode,
case MATROXFB_SET_OUTPUT_CONNECTION: case MATROXFB_SET_OUTPUT_CONNECTION:
{ {
u_int32_t tmp; u_int32_t tmp;
int out;
int changes;
if (get_user(tmp, (u_int32_t*)arg)) if (get_user(tmp, (u_int32_t*)arg))
return -EFAULT; return -EFAULT;
if (tmp & ~ACCESS_FBINFO(output.all)) for (out = 0; out < 32; out++) {
return -EINVAL; if (tmp & (1 << out)) {
if (tmp & ACCESS_FBINFO(output.ph)) if (out >= MATROXFB_MAX_OUTPUTS)
return -EINVAL; return -ENXIO;
if (tmp & MATROXFB_OUTPUT_CONN_DFP) if (!ACCESS_FBINFO(outputs[out]).output)
return -EINVAL; return -ENXIO;
if ((ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP) && tmp) switch (ACCESS_FBINFO(outputs[out]).src) {
return -EINVAL; case MATROXFB_SRC_NONE:
if (tmp == ACCESS_FBINFO(output.sh)) case MATROXFB_SRC_CRTC2:
break;
default:
return -EBUSY;
}
}
}
if (ACCESS_FBINFO(devflags.panellink)) {
if (tmp & MATROXFB_OUTPUT_CONN_DFP)
return -EINVAL;
if ((ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) && tmp)
return -EBUSY;
}
changes = 0;
for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
if (tmp & (1 << out)) {
if (ACCESS_FBINFO(outputs[out]).src != MATROXFB_SRC_CRTC2) {
changes = 1;
ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_CRTC2;
}
} else if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) {
changes = 1;
ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_NONE;
}
}
if (!changes)
return 0; return 0;
ACCESS_FBINFO(output.sh) = tmp;
matroxfb_dh_switch(m2info->fbcon.currcon, info); matroxfb_dh_switch(m2info->fbcon.currcon, info);
return 0; return 0;
} }
case MATROXFB_GET_OUTPUT_CONNECTION: case MATROXFB_GET_OUTPUT_CONNECTION:
{ {
if (put_user(ACCESS_FBINFO(output.sh), (u_int32_t*)arg)) u_int32_t conn = 0;
int out;
for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) {
conn |= 1 << out;
}
}
if (put_user(conn, (u_int32_t*)arg))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case MATROXFB_GET_AVAILABLE_OUTPUTS: case MATROXFB_GET_AVAILABLE_OUTPUTS:
{ {
u_int32_t tmp; u_int32_t tmp = 0;
int out;
/* we do not support DFP from CRTC2 */
tmp = ACCESS_FBINFO(output.all) & ~ACCESS_FBINFO(output.ph) & ~MATROXFB_OUTPUT_CONN_DFP; for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
/* CRTC1 in DFP mode disables CRTC2 at all (I know, I'm lazy) */ if (ACCESS_FBINFO(outputs[out]).output) {
if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP) switch (ACCESS_FBINFO(outputs[out]).src) {
tmp = 0; case MATROXFB_SRC_NONE:
case MATROXFB_SRC_CRTC2:
tmp |= 1 << out;
break;
}
}
}
if (ACCESS_FBINFO(devflags.panellink)) {
tmp &= ~MATROXFB_OUTPUT_CONN_DFP;
if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) {
tmp = 0;
}
}
if (put_user(tmp, (u_int32_t*)arg)) if (put_user(tmp, (u_int32_t*)arg))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -730,11 +780,10 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) { ...@@ -730,11 +780,10 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
/* /*
* If we have unused output, connect CRTC2 to it... * If we have unused output, connect CRTC2 to it...
*/ */
if ((ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_SECONDARY) && if (ACCESS_FBINFO(outputs[1]).output &&
!(ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) && ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_NONE &&
!(ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP)) { ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_NONE) {
ACCESS_FBINFO(output.sh) |= MATROXFB_OUTPUT_CONN_SECONDARY; ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_CRTC2;
ACCESS_FBINFO(output.sh) &= ~MATROXFB_OUTPUT_CONN_DFP;
} }
matroxfb_dh_set_var(&matroxfb_dh_defined, -2, &m2info->fbcon); matroxfb_dh_set_var(&matroxfb_dh_defined, -2, &m2info->fbcon);
...@@ -839,7 +888,7 @@ static void matroxfb_crtc2_exit(void) { ...@@ -839,7 +888,7 @@ static void matroxfb_crtc2_exit(void) {
matroxfb_unregister_driver(&crtc2); matroxfb_unregister_driver(&crtc2);
} }
MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>"); MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_DESCRIPTION("Matrox G400 CRTC2 driver"); MODULE_DESCRIPTION("Matrox G400 CRTC2 driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(matroxfb_crtc2_init); module_init(matroxfb_crtc2_init);
......
...@@ -34,30 +34,31 @@ static int matroxfb_g450_program(void* md) { ...@@ -34,30 +34,31 @@ static int matroxfb_g450_program(void* md) {
} }
static struct matrox_altout matroxfb_g450_altout = { static struct matrox_altout matroxfb_g450_altout = {
.name = "Secondary output",
.compute = matroxfb_g450_compute, .compute = matroxfb_g450_compute,
.program = matroxfb_g450_program, .program = matroxfb_g450_program,
}; };
void matroxfb_g450_connect(WPMINFO2) { void matroxfb_g450_connect(WPMINFO2) {
/* hardware is not G450... */ if (ACCESS_FBINFO(devflags.g450dac)) {
if (!ACCESS_FBINFO(devflags.g450dac)) down_write(&ACCESS_FBINFO(altout.lock));
return; ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_CRTC1;
down_write(&ACCESS_FBINFO(altout.lock)); ACCESS_FBINFO(outputs[1]).data = MINFO;
ACCESS_FBINFO(altout.device) = MINFO; ACCESS_FBINFO(outputs[1]).output = &matroxfb_g450_altout;
ACCESS_FBINFO(altout.output) = &matroxfb_g450_altout; ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
up_write(&ACCESS_FBINFO(altout.lock)); up_write(&ACCESS_FBINFO(altout.lock));
ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY; }
matroxfb_switch(ACCESS_FBINFO(fbcon.currcon), (struct fb_info*)MINFO);
} }
void matroxfb_g450_shutdown(WPMINFO2) { void matroxfb_g450_shutdown(WPMINFO2) {
ACCESS_FBINFO(output.all) &= ~MATROXFB_OUTPUT_CONN_SECONDARY; if (ACCESS_FBINFO(devflags.g450dac)) {
ACCESS_FBINFO(output.ph) &= ~MATROXFB_OUTPUT_CONN_SECONDARY; down_write(&ACCESS_FBINFO(altout.lock));
ACCESS_FBINFO(output.sh) &= ~MATROXFB_OUTPUT_CONN_SECONDARY; ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE;
down_write(&ACCESS_FBINFO(altout.lock)); ACCESS_FBINFO(outputs[1]).output = NULL;
ACCESS_FBINFO(altout.device) = NULL; ACCESS_FBINFO(outputs[1]).data = NULL;
ACCESS_FBINFO(altout.output) = NULL; ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
up_write(&ACCESS_FBINFO(altout.lock)); up_write(&ACCESS_FBINFO(altout.lock));
}
} }
EXPORT_SYMBOL(matroxfb_g450_connect); EXPORT_SYMBOL(matroxfb_g450_connect);
......
...@@ -327,7 +327,7 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat ...@@ -327,7 +327,7 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat
}, MODE_NTSC, 525, 60 }; }, MODE_NTSC, 525, 60 };
MINFO_FROM(md->primary_head); MINFO_FROM(md->primary_head);
if (ACCESS_FBINFO(altout.mode) == MODE_PAL) if (ACCESS_FBINFO(outputs[1]).mode == MODE_PAL)
*data = palregs; *data = palregs;
else else
*data = ntscregs; *data = ntscregs;
...@@ -585,7 +585,7 @@ static inline int maven_compute_timming(struct maven_data* md, ...@@ -585,7 +585,7 @@ static inline int maven_compute_timming(struct maven_data* md,
unsigned int a, bv, c; unsigned int a, bv, c;
MINFO_FROM(md->primary_head); MINFO_FROM(md->primary_head);
m->mode = ACCESS_FBINFO(altout.mode); m->mode = ACCESS_FBINFO(outputs[1]).mode;
if (MODE_TV(m->mode)) { if (MODE_TV(m->mode)) {
unsigned int lmargin; unsigned int lmargin;
unsigned int umargin; unsigned int umargin;
...@@ -893,6 +893,7 @@ static int maven_out_verify_mode(void* md, u_int32_t arg) { ...@@ -893,6 +893,7 @@ static int maven_out_verify_mode(void* md, u_int32_t arg) {
} }
static struct matrox_altout maven_altout = { static struct matrox_altout maven_altout = {
.name = "Secondary output",
.compute = maven_out_compute, .compute = maven_out_compute,
.program = maven_out_program, .program = maven_out_program,
.start = maven_out_start, .start = maven_out_start,
...@@ -904,14 +905,14 @@ static int maven_init_client(struct i2c_client* clnt) { ...@@ -904,14 +905,14 @@ static int maven_init_client(struct i2c_client* clnt) {
struct maven_data* md = clnt->data; struct maven_data* md = clnt->data;
MINFO_FROM(((struct i2c_bit_adapter*)a)->minfo); MINFO_FROM(((struct i2c_bit_adapter*)a)->minfo);
ACCESS_FBINFO(altout.mode) = MODE_MONITOR;
md->primary_head = MINFO; md->primary_head = MINFO;
md->client = clnt; md->client = clnt;
down_write(&ACCESS_FBINFO(altout.lock)); down_write(&ACCESS_FBINFO(altout.lock));
ACCESS_FBINFO(altout.device) = md; ACCESS_FBINFO(outputs[1]).output = &maven_altout;
ACCESS_FBINFO(altout.output) = &maven_altout; ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE;
ACCESS_FBINFO(outputs[1]).data = md;
ACCESS_FBINFO(outputs[1]).mode = MODE_MONITOR;
up_write(&ACCESS_FBINFO(altout.lock)); up_write(&ACCESS_FBINFO(altout.lock));
ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY;
if (maven_get_reg(clnt, 0xB2) < 0x14) { if (maven_get_reg(clnt, 0xB2) < 0x14) {
md->version = MGATVO_B; md->version = MGATVO_B;
} else { } else {
...@@ -924,13 +925,14 @@ static int maven_shutdown_client(struct i2c_client* clnt) { ...@@ -924,13 +925,14 @@ static int maven_shutdown_client(struct i2c_client* clnt) {
struct maven_data* md = clnt->data; struct maven_data* md = clnt->data;
if (md->primary_head) { if (md->primary_head) {
md->primary_head->output.all &= ~MATROXFB_OUTPUT_CONN_SECONDARY; MINFO_FROM(md->primary_head);
md->primary_head->output.ph &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
md->primary_head->output.sh &= ~MATROXFB_OUTPUT_CONN_SECONDARY; down_write(&ACCESS_FBINFO(altout.lock));
down_write(&md->primary_head->altout.lock); ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE;
md->primary_head->altout.device = NULL; ACCESS_FBINFO(outputs[1]).output = NULL;
md->primary_head->altout.output = NULL; ACCESS_FBINFO(outputs[1]).data = NULL;
up_write(&md->primary_head->altout.lock); ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
up_write(&ACCESS_FBINFO(altout.lock));
md->primary_head = NULL; md->primary_head = NULL;
} }
return 0; return 0;
......
...@@ -360,7 +360,8 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p) { ...@@ -360,7 +360,8 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p) {
((hd & 0x100) >> 7) | /* blanking */ ((hd & 0x100) >> 7) | /* blanking */
((hs & 0x100) >> 6) | /* sync start */ ((hs & 0x100) >> 6) | /* sync start */
(hbe & 0x040); /* end hor. blanking */ (hbe & 0x040); /* end hor. blanking */
if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) /* FIXME: Enable vidrst only on G400, and only if TV-out is used */
if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1)
hw->CRTCEXT[1] |= 0x88; /* enable horizontal and vertical vidrst */ hw->CRTCEXT[1] |= 0x88; /* enable horizontal and vertical vidrst */
hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) | hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) |
((vd & 0x400) >> 8) | /* disp end */ ((vd & 0x400) >> 8) | /* disp end */
......
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