From ce31e58a95cf192b26e8d96c3d35f5caa856f219 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:04:20 +0200 Subject: Make secondary output support mandatory for Matrox G450/G550. --- drivers/video/Config.help | 49 ++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) (limited to 'drivers/video/Config.help') diff --git a/drivers/video/Config.help b/drivers/video/Config.help index 21c25f78749a..6e334b9e00ae 100644 --- a/drivers/video/Config.help +++ b/drivers/video/Config.help @@ -387,8 +387,7 @@ CONFIG_FB_MATROX Say Y here if you have a Matrox Millennium, Matrox Millennium II, Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video, - Matrox G400, G450 or G550 card in your box. At this time, support for - the G-series digital output is almost non-existant. + Matrox G400, G450 or G550 card in your box. This driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). @@ -413,7 +412,7 @@ CONFIG_FB_MATROX_MYSTIQUE packed pixel and 32 bpp packed pixel. You can also use font widths different from 8. -CONFIG_FB_MATROX_G100 +CONFIG_FB_MATROX_G450 Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based video card. If you select "Advanced lowlevel driver options", you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed @@ -423,11 +422,26 @@ CONFIG_FB_MATROX_G100 If you need support for G400 secondary head, you must first say Y to "I2C support" and "I2C bit-banging support" in the character devices section, and then to "Matrox I2C support" and "G400 second head - support" here in the framebuffer section. + support" here in the framebuffer section. G450/G550 secondary head + and digital output are supported without additional modules. + + Do not forget that second head supports only 16 and 32 bpp + packed pixels, so it is a good idea to compile them into the kernel + too. You can use only some font widths, as the driver uses generic + painting procedures (the secondary head does not use acceleration + engine). - If you have G550, you must also compile support for G450/G550 secondary - head into kernel, otherwise picture will be shown only on output you - are probably not using... +CONFIG_FB_MATROX_G100A + Say Y here if you have a Matrox G100, G200 or G400 based + video card. If you select "Advanced lowlevel driver options", you + should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed + pixel and 32 bpp packed pixel. You can also use font widths + different from 8. + + If you need support for G400 secondary head, you must first say Y to + "I2C support" and "I2C bit-banging support" in the character devices + section, and then to "Matrox I2C support" and "G400 second head + support" here in the framebuffer section. CONFIG_FB_MATROX_I2C This drivers creates I2C buses which are needed for accessing the @@ -470,27 +484,6 @@ CONFIG_FB_MATROX_MAVEN painting procedures (the secondary head does not use acceleration engine). -CONFIG_FB_MATROX_G450 - Say Y or M here if you want to use a secondary head (meaning two - monitors in parallel) on G450, or if you are using analog output - of G550. - - If you compile it as module, two modules are created, - matroxfb_crtc2.o and matroxfb_g450.o. Both modules are needed if you - want two independent display devices. - - The driver starts in monitor mode and currently does not support - output in TV modes. You must use the matroxset tool (available - at ) to swap - primary and secondary head outputs. Secondary head driver always - start in 640x480 resolution and you must use fbset to change it. - - Also do not forget that second head supports only 16 and 32 bpp - packed pixels, so it is a good idea to compile them into the kernel - too. You can use only some font widths, as the driver uses generic - painting procedures (the secondary head does not use acceleration - engine). - CONFIG_FB_MATROX_MULTIHEAD Say Y here if you have more than one (supported) Matrox device in your computer and you want to use all of them for different monitors -- cgit v1.2.3 From b0f3e5d467f5724e403dc241d622a1e6c8d18962 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:32:33 +0200 Subject: Add TV-Out support for Matrox G450/G550. Due to the hardware only secondary CRTC can be used as a source for TV output. --- drivers/video/Config.help | 9 + drivers/video/matrox/matroxfb_crtc2.c | 22 ++- drivers/video/matrox/matroxfb_crtc2.h | 2 + drivers/video/matrox/matroxfb_g450.c | 333 +++++++++++++++++++++++++++++++++- 4 files changed, 356 insertions(+), 10 deletions(-) (limited to 'drivers/video/Config.help') diff --git a/drivers/video/Config.help b/drivers/video/Config.help index 6e334b9e00ae..7a079fff6d58 100644 --- a/drivers/video/Config.help +++ b/drivers/video/Config.help @@ -425,12 +425,21 @@ CONFIG_FB_MATROX_G450 support" here in the framebuffer section. G450/G550 secondary head and digital output are supported without additional modules. + The driver starts in monitor mode. You must use the matroxset tool + (available at ) to + swap primary and secondary head outputs, or to change output mode. + Secondary head driver always start in 640x480 resolution and you + must use fbset to change it. + Do not forget that second head supports only 16 and 32 bpp packed pixels, so it is a good idea to compile them into the kernel too. You can use only some font widths, as the driver uses generic painting procedures (the secondary head does not use acceleration engine). + G450/G550 hardware can display TV picture only from secondary CRTC, + and it performs no scaling, so picture must have 525 or 625 lines. + CONFIG_FB_MATROX_G100A Say Y here if you have a Matrox G100, G200 or G400 based video card. If you select "Advanced lowlevel driver options", you diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index a4e0121fc91f..db93542f78e2 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -2,11 +2,11 @@ * * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450. * - * (c) 1998-2001 Petr Vandrovec + * (c) 1998-2002 Petr Vandrovec * * Portions Copyright (c) 2001 Matrox Graphics Inc. * - * Version: 1.62 2001/11/29 + * Version: 1.64 2002/06/10 * */ @@ -103,6 +103,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, int mode, unsigned int pos) { u_int32_t tmp; + u_int32_t datactl; MINFO_FROM(m2info->primary_dev); switch (mode) { @@ -117,12 +118,15 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, tmp = 0x00800000; break; } - tmp |= 0x00000001; /* enable CRTC2 */ + datactl = 0; if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) { if (ACCESS_FBINFO(devflags.g450dac)) { tmp |= 0x00000006; /* source from secondary pixel PLL */ - /* no vidrst */ + /* no vidrst when in monitor mode */ + if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { + tmp |= 0xC0001000; /* Enable H/V vidrst */ + } } else { tmp |= 0x00000002; /* source from VDOCLK */ tmp |= 0xC0000000; /* enable vvidrst & hvidrst */ @@ -142,6 +146,10 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, mt->VSyncEnd >>= 1; mt->VTotal >>= 1; } + if ((mt->HTotal & 7) == 2) { + datactl |= 0x00000010; + mt->HTotal &= ~7; + } tmp |= 0x10000000; /* 0x10000000 is VIDRST polarity */ mga_outl(0x3C14, ((mt->HDisplay - 8) << 16) | (mt->HTotal - 8)); mga_outl(0x3C18, ((mt->HSyncEnd - 8) << 16) | (mt->HSyncStart - 8)); @@ -155,12 +163,14 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, mga_outl(0x3C2C, pos); /* field #1 vmemory start */ mga_outl(0x3C28, pos + linelen); /* field #0 vmemory start */ linelen <<= 1; + m2info->interlaced = 1; } else { mga_outl(0x3C28, pos); /* vmemory start */ + m2info->interlaced = 0; } mga_outl(0x3C40, linelen); } - mga_outl(0x3C4C, 0); /* data control */ + mga_outl(0x3C4C, datactl); /* data control */ if (tmp & 0x02000000) { int i; @@ -208,7 +218,7 @@ static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info, linelen = var->xres_virtual * pixelsize; pos = var->yoffset * linelen + var->xoffset * pixelsize; pos += m2info->video.offbase; - if (var->vmode & FB_VMODE_INTERLACED) { + if (m2info->interlaced) { mga_outl(0x3C2C, pos); mga_outl(0x3C28, pos + linelen); } else { diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h index e625053bc679..a72ebe3ff508 100644 --- a/drivers/video/matrox/matroxfb_crtc2.h +++ b/drivers/video/matrox/matroxfb_crtc2.h @@ -29,6 +29,8 @@ struct matroxfb_dh_fb_info { int currcon; struct display* currcon_display; + + int interlaced:1; union { #ifdef FBCON_HAS_CFB16 diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index 1399947ee413..17f5f9236bf4 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -2,39 +2,363 @@ * * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450. * - * (c) 1998-2001 Petr Vandrovec + * (c) 1998-2002 Petr Vandrovec * * Portions Copyright (c) 2001 Matrox Graphics Inc. * - * Version: 1.62 2001/11/29 + * Version: 1.64 2002/06/02 * * See matroxfb_base.c for contributors. * */ -#include "matroxfb_g450.h" +#include "matroxfb_base.h" #include "matroxfb_misc.h" #include "matroxfb_DAC1064.h" #include "g450_pll.h" #include #include +#include + +static void cve2_set_reg(WPMINFO int reg, int val) { + unsigned long flags; + + matroxfb_DAC_lock_irqsave(flags); + matroxfb_DAC_out(PMINFO 0x87, reg); + matroxfb_DAC_out(PMINFO 0x88, val); + matroxfb_DAC_unlock_irqrestore(flags); +} + +struct output_desc { + unsigned int h_vis; + unsigned int h_f_porch; + unsigned int h_sync; + unsigned int h_b_porch; + unsigned long long int chromasc; + unsigned int burst; + unsigned int v_total; +}; + +static void computeRegs(WPMINFO struct mavenregs* r, struct my_timming* mt, const struct output_desc* outd) { + u_int32_t chromasc; + u_int32_t hlen; + u_int32_t hsl; + u_int32_t hbp; + u_int32_t hfp; + u_int32_t hvis; + unsigned int pixclock; + unsigned long long piic; + int mnp; + int over; + + r->regs[0x80] = 0x03; /* | 0x40 for SCART */ + + hvis = ((mt->HDisplay << 1) + 3) & ~3; + + if (hvis >= 2048) { + hvis = 2044; + } + + piic = 1000000000ULL * hvis; + do_div(piic, outd->h_vis); + + dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic); + + mnp = matroxfb_g450_setclk(PMINFO piic, M_VIDEO_PLL); + + mt->mnp = mnp; + mt->pixclock = g450_mnp2f(PMINFO mnp); + + dprintk(KERN_DEBUG "MNP=%08X\n", mnp); + + pixclock = 1000000000U / mt->pixclock; + + dprintk(KERN_DEBUG "Got %u ps pixclock\n", pixclock); + + piic = outd->chromasc; + do_div(piic, mt->pixclock); + chromasc = piic; + + dprintk(KERN_DEBUG "Chroma is %08X\n", chromasc); + + r->regs[0] = piic >> 24; + r->regs[1] = piic >> 16; + r->regs[2] = piic >> 8; + r->regs[3] = piic >> 0; + hbp = (((outd->h_b_porch + pixclock) / pixclock)) & ~1; + hfp = (((outd->h_f_porch + pixclock) / pixclock)) & ~1; + hsl = (((outd->h_sync + pixclock) / pixclock)) & ~1; + hlen = hvis + hfp + hsl + hbp; + over = hlen & 0x0F; + + dprintk(KERN_DEBUG "WL: vis=%u, hf=%u, hs=%u, hb=%u, total=%u\n", hvis, hfp, hsl, hbp, hlen); + + if (over) { + hfp -= over; + hlen -= over; + if (over <= 2) { + } else if (over < 10) { + hfp += 4; + hlen += 4; + } else { + hfp += 16; + hlen += 16; + } + } + + /* maybe cve2 has requirement 800 < hlen < 1184 */ + r->regs[0x08] = hsl; + r->regs[0x09] = (outd->burst + pixclock - 1) / pixclock; /* burst length */ + r->regs[0x0A] = hbp; + r->regs[0x2C] = hfp; + r->regs[0x31] = hvis / 8; + r->regs[0x32] = hvis & 7; + + dprintk(KERN_DEBUG "PG: vis=%04X, hf=%02X, hs=%02X, hb=%02X, total=%04X\n", hvis, hfp, hsl, hbp, hlen); + + r->regs[0x84] = 1; /* x sync point */ + r->regs[0x85] = 0; + hvis = hvis >> 1; + hlen = hlen >> 1; + + dprintk(KERN_DEBUG "hlen=%u hvis=%u\n", hlen, hvis); + + mt->interlaced = 1; + + mt->HDisplay = hvis & ~7; + mt->HSyncStart = mt->HDisplay + 8; + mt->HSyncEnd = (hlen & ~7) - 8; + mt->HTotal = hlen; + + { + int upper; + unsigned int vtotal; + unsigned int vsyncend; + unsigned int vdisplay; + + vtotal = mt->VTotal; + vsyncend = mt->VSyncEnd; + vdisplay = mt->VDisplay; + if (vtotal < outd->v_total) { + unsigned int yovr = outd->v_total - vtotal; + + vsyncend += yovr >> 1; + } else if (vtotal > outd->v_total) { + vdisplay = outd->v_total - 4; + vsyncend = outd->v_total; + } + upper = (outd->v_total - vsyncend) >> 1; /* in field lines */ + r->regs[0x17] = outd->v_total / 4; + r->regs[0x18] = outd->v_total & 3; + r->regs[0x33] = upper - 1; /* upper blanking */ + r->regs[0x82] = upper; /* y sync point */ + r->regs[0x83] = upper >> 8; + + mt->VDisplay = vdisplay; + mt->VSyncStart = outd->v_total - 2; + mt->VSyncEnd = outd->v_total; + mt->VTotal = outd->v_total; + } +} + +static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct output_desc** outd) { + static const struct output_desc paloutd = { + .h_vis = 52148148, // ps + .h_f_porch = 1407407, // ps + .h_sync = 4666667, // ps + .h_b_porch = 5777778, // ps + .chromasc = 19042247534182ULL, // 4433618.750 Hz + .burst = 2518518, // ps + .v_total = 625, + }; + static const struct output_desc ntscoutd = { + .h_vis = 52888889, // ps + .h_f_porch = 1333333, // ps + .h_sync = 4666667, // ps + .h_b_porch = 4666667, // ps + .chromasc = 15374030659475ULL, // 3579545.454 Hz + .burst = 2418418, // ps + .v_total = 525, // lines + }; + + static const struct mavenregs palregs = { { + 0x2A, 0x09, 0x8A, 0xCB, /* 00: chroma subcarrier */ + 0x00, + 0x00, /* test */ + 0xF9, /* modified by code (F9 written...) */ + 0x00, /* ? not written */ + 0x7E, /* 08 */ + 0x44, /* 09 */ + 0x9C, /* 0A */ + 0x2E, /* 0B */ + 0x21, /* 0C */ + 0x00, /* ? not written */ +// 0x3F, 0x03, /* 0E-0F */ + 0x3C, 0x03, + 0x3C, 0x03, /* 10-11 */ + 0x1A, /* 12 */ + 0x2A, /* 13 */ + 0x1C, 0x3D, 0x14, /* 14-16 */ + 0x9C, 0x01, /* 17-18 */ + 0x00, /* 19 */ + 0xFE, /* 1A */ + 0x7E, /* 1B */ + 0x60, /* 1C */ + 0x05, /* 1D */ +// 0x89, 0x03, /* 1E-1F */ + 0xAD, 0x03, +// 0x72, /* 20 */ + 0xA5, + 0x07, /* 21 */ +// 0x72, /* 22 */ + 0xA5, + 0x00, /* 23 */ + 0x00, /* 24 */ + 0x00, /* 25 */ + 0x08, /* 26 */ + 0x04, /* 27 */ + 0x00, /* 28 */ + 0x1A, /* 29 */ + 0x55, 0x01, /* 2A-2B */ + 0x26, /* 2C */ + 0x07, 0x7E, /* 2D-2E */ + 0x02, 0x54, /* 2F-30 */ + 0xB0, 0x00, /* 31-32 */ + 0x14, /* 33 */ + 0x49, /* 34 */ + 0x00, /* 35 written multiple times */ + 0x00, /* 36 not written */ + 0xA3, /* 37 */ + 0xC8, /* 38 */ + 0x22, /* 39 */ + 0x02, /* 3A */ + 0x22, /* 3B */ + 0x3F, 0x03, /* 3C-3D */ + 0x00, /* 3E written multiple times */ + 0x00, /* 3F not written */ + } }; + static struct mavenregs ntscregs = { { + 0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */ + 0x00, + 0x00, /* test */ + 0xF9, /* modified by code (F9 written...) */ + 0x00, /* ? not written */ + 0x7E, /* 08 */ + 0x43, /* 09 */ + 0x7E, /* 0A */ + 0x3D, /* 0B */ + 0x00, /* 0C */ + 0x00, /* ? not written */ + 0x41, 0x00, /* 0E-0F */ + 0x3C, 0x00, /* 10-11 */ + 0x17, /* 12 */ + 0x21, /* 13 */ + 0x1B, 0x1B, 0x24, /* 14-16 */ + 0x83, 0x01, /* 17-18 */ + 0x00, /* 19 */ + 0x0F, /* 1A */ + 0x0F, /* 1B */ + 0x60, /* 1C */ + 0x05, /* 1D */ + //0x89, 0x02, /* 1E-1F */ + 0xC0, 0x02, /* 1E-1F */ + //0x5F, /* 20 */ + 0x9C, /* 20 */ + 0x04, /* 21 */ + //0x5F, /* 22 */ + 0x9C, /* 22 */ + 0x01, /* 23 */ + 0x02, /* 24 */ + 0x00, /* 25 */ + 0x0A, /* 26 */ + 0x05, /* 27 */ + 0x00, /* 28 */ + 0x10, /* 29 */ + 0xFF, 0x03, /* 2A-2B */ + 0x24, /* 2C */ + 0x0F, 0x78, /* 2D-2E */ + 0x00, 0x00, /* 2F-30 */ + 0xB2, 0x04, /* 31-32 */ + 0x14, /* 33 */ + 0x02, /* 34 */ + 0x00, /* 35 written multiple times */ + 0x00, /* 36 not written */ + 0xA3, /* 37 */ + 0xC8, /* 38 */ + 0x15, /* 39 */ + 0x05, /* 3A */ + 0x3B, /* 3B */ + 0x3C, 0x00, /* 3C-3D */ + 0x00, /* 3E written multiple times */ + 0x00, /* never written */ + } }; + + if (norm == MATROXFB_OUTPUT_MODE_PAL) { + *data = palregs; + *outd = &paloutd; + } else { + *data = ntscregs; + *outd = &ntscoutd; + } + return; +} + +#define LR(x) cve2_set_reg(PMINFO (x), m->regs[(x)]) +static void cve2_init_TV(WPMINFO const struct mavenregs* m) { + int i; + + LR(0x80); + LR(0x82); LR(0x83); + LR(0x84); LR(0x85); + + cve2_set_reg(PMINFO 0x3E, 0x01); + + for (i = 0; i < 0x3E; i++) { + LR(i); + } + cve2_set_reg(PMINFO 0x3E, 0x00); +} static int matroxfb_g450_compute(void* md, struct my_timming* mt) { MINFO_FROM(md); - if (mt->mnp < 0) { + dprintk(KERN_DEBUG "Computing, mode=%u\n", ACCESS_FBINFO(outputs[1]).mode); + + if (mt->crtc == MATROXFB_SRC_CRTC2 && + ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { + const struct output_desc* outd; + + cve2_init_TVdata(ACCESS_FBINFO(outputs[1]).mode, &ACCESS_FBINFO(hw).maven, &outd); + computeRegs(PMINFO &ACCESS_FBINFO(hw).maven, mt, outd); + } else if (mt->mnp < 0) { /* We must program clocks before CRTC2, otherwise interlaced mode startup may fail */ mt->mnp = matroxfb_g450_setclk(PMINFO mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); mt->pixclock = g450_mnp2f(PMINFO mt->mnp); } + dprintk(KERN_DEBUG "Pixclock = %u\n", mt->pixclock); return 0; } static int matroxfb_g450_program(void* md) { + MINFO_FROM(md); + + if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { + cve2_init_TV(PMINFO &ACCESS_FBINFO(hw).maven); + } return 0; } +static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) { + switch (arg) { + case MATROXFB_OUTPUT_MODE_PAL: + case MATROXFB_OUTPUT_MODE_NTSC: + case MATROXFB_OUTPUT_MODE_MONITOR: + return 0; + } + return -EINVAL; +} + static int g450_dvi_compute(void* md, struct my_timming* mt) { MINFO_FROM(md); @@ -49,6 +373,7 @@ static struct matrox_altout matroxfb_g450_altout = { .name = "Secondary output", .compute = matroxfb_g450_compute, .program = matroxfb_g450_program, + .verifymode = matroxfb_g450_verify_mode, }; static struct matrox_altout matroxfb_g450_dvi = { -- cgit v1.2.3