2005-04-17 02:20:36 +04:00
/*
*
* Hardware accelerated Matrox Millennium I , II , Mystique , G100 , G200 , G400 and G450 .
*
* ( c ) 1998 - 2002 Petr Vandrovec < vandrove @ vc . cvut . cz >
*
* Portions Copyright ( c ) 2001 Matrox Graphics Inc .
*
* Version : 1.65 2002 / 08 / 14
*
* See matroxfb_base . c for contributors .
*
*/
# include "matroxfb_base.h"
# include "matroxfb_misc.h"
# include "matroxfb_DAC1064.h"
# include "g450_pll.h"
# include <linux/matroxfb.h>
# include <asm/div64.h>
2006-01-10 07:54:04 +03:00
# include "matroxfb_g450.h"
2005-04-17 02:20:36 +04:00
/* Definition of the various controls */
struct mctl {
struct v4l2_queryctrl desc ;
size_t control ;
} ;
# define BLMIN 0xF3
# define WLMAX 0x3FF
static const struct mctl g450_controls [ ] =
{ { { V4L2_CID_BRIGHTNESS , V4L2_CTRL_TYPE_INTEGER ,
" brightness " ,
0 , WLMAX - BLMIN , 1 , 370 - BLMIN ,
0 ,
} , offsetof ( struct matrox_fb_info , altout . tvo_params . brightness ) } ,
{ { V4L2_CID_CONTRAST , V4L2_CTRL_TYPE_INTEGER ,
" contrast " ,
0 , 1023 , 1 , 127 ,
0 ,
} , offsetof ( struct matrox_fb_info , altout . tvo_params . contrast ) } ,
{ { V4L2_CID_SATURATION , V4L2_CTRL_TYPE_INTEGER ,
" saturation " ,
0 , 255 , 1 , 165 ,
0 ,
} , offsetof ( struct matrox_fb_info , altout . tvo_params . saturation ) } ,
{ { V4L2_CID_HUE , V4L2_CTRL_TYPE_INTEGER ,
" hue " ,
0 , 255 , 1 , 0 ,
0 ,
} , offsetof ( struct matrox_fb_info , altout . tvo_params . hue ) } ,
{ { MATROXFB_CID_TESTOUT , V4L2_CTRL_TYPE_BOOLEAN ,
" test output " ,
0 , 1 , 1 , 0 ,
0 ,
} , offsetof ( struct matrox_fb_info , altout . tvo_params . testout ) } ,
} ;
2006-03-27 13:17:39 +04:00
# define G450CTRLS ARRAY_SIZE(g450_controls)
2005-04-17 02:20:36 +04:00
/* Return: positive number: id found
- EINVAL : id not found , return failure
- ENOENT : id not found , create fake disabled control */
static int get_ctrl_id ( __u32 v4l2_id ) {
int i ;
for ( i = 0 ; i < G450CTRLS ; i + + ) {
if ( v4l2_id < g450_controls [ i ] . desc . id ) {
if ( g450_controls [ i ] . desc . id = = 0x08000000 ) {
return - EINVAL ;
}
return - ENOENT ;
}
if ( v4l2_id = = g450_controls [ i ] . desc . id ) {
return i ;
}
}
return - EINVAL ;
}
2009-09-23 03:47:49 +04:00
static inline int * get_ctrl_ptr ( struct matrox_fb_info * minfo , unsigned int idx )
{
2009-09-23 03:47:48 +04:00
return ( int * ) ( ( char * ) minfo + g450_controls [ idx ] . control ) ;
2005-04-17 02:20:36 +04:00
}
2009-09-23 03:47:49 +04:00
static void tvo_fill_defaults ( struct matrox_fb_info * minfo )
{
2005-04-17 02:20:36 +04:00
unsigned int i ;
for ( i = 0 ; i < G450CTRLS ; i + + ) {
2009-09-23 03:47:49 +04:00
* get_ctrl_ptr ( minfo , i ) = g450_controls [ i ] . desc . default_value ;
2005-04-17 02:20:36 +04:00
}
}
2009-09-23 03:47:49 +04:00
static int cve2_get_reg ( struct matrox_fb_info * minfo , int reg )
{
2005-04-17 02:20:36 +04:00
unsigned long flags ;
int val ;
matroxfb_DAC_lock_irqsave ( flags ) ;
2009-09-23 03:47:49 +04:00
matroxfb_DAC_out ( minfo , 0x87 , reg ) ;
val = matroxfb_DAC_in ( minfo , 0x88 ) ;
2005-04-17 02:20:36 +04:00
matroxfb_DAC_unlock_irqrestore ( flags ) ;
return val ;
}
2009-09-23 03:47:49 +04:00
static void cve2_set_reg ( struct matrox_fb_info * minfo , int reg , int val )
{
2005-04-17 02:20:36 +04:00
unsigned long flags ;
matroxfb_DAC_lock_irqsave ( flags ) ;
2009-09-23 03:47:49 +04:00
matroxfb_DAC_out ( minfo , 0x87 , reg ) ;
matroxfb_DAC_out ( minfo , 0x88 , val ) ;
2005-04-17 02:20:36 +04:00
matroxfb_DAC_unlock_irqrestore ( flags ) ;
}
2009-09-23 03:47:49 +04:00
static void cve2_set_reg10 ( struct matrox_fb_info * minfo , int reg , int val )
{
2005-04-17 02:20:36 +04:00
unsigned long flags ;
matroxfb_DAC_lock_irqsave ( flags ) ;
2009-09-23 03:47:49 +04:00
matroxfb_DAC_out ( minfo , 0x87 , reg ) ;
matroxfb_DAC_out ( minfo , 0x88 , val > > 2 ) ;
matroxfb_DAC_out ( minfo , 0x87 , reg + 1 ) ;
matroxfb_DAC_out ( minfo , 0x88 , val & 3 ) ;
2005-04-17 02:20:36 +04:00
matroxfb_DAC_unlock_irqrestore ( flags ) ;
}
2009-09-23 03:47:49 +04:00
static void g450_compute_bwlevel ( const struct matrox_fb_info * minfo , int * bl ,
int * wl )
{
2009-09-23 03:47:48 +04:00
const int b = minfo - > altout . tvo_params . brightness + BLMIN ;
const int c = minfo - > altout . tvo_params . contrast ;
2005-04-17 02:20:36 +04:00
* bl = max ( b - c , BLMIN ) ;
* wl = min ( b + c , WLMAX ) ;
}
static int g450_query_ctrl ( void * md , struct v4l2_queryctrl * p ) {
int i ;
i = get_ctrl_id ( p - > id ) ;
if ( i > = 0 ) {
* p = g450_controls [ i ] . desc ;
return 0 ;
}
if ( i = = - ENOENT ) {
static const struct v4l2_queryctrl disctrl =
{ . flags = V4L2_CTRL_FLAG_DISABLED } ;
i = p - > id ;
* p = disctrl ;
p - > id = i ;
sprintf ( p - > name , " Ctrl #%08X " , i ) ;
return 0 ;
}
return - EINVAL ;
}
static int g450_set_ctrl ( void * md , struct v4l2_control * p ) {
int i ;
2009-09-23 03:47:50 +04:00
struct matrox_fb_info * minfo = md ;
2005-04-17 02:20:36 +04:00
i = get_ctrl_id ( p - > id ) ;
if ( i < 0 ) return - EINVAL ;
/*
* Check if changed .
*/
2009-09-23 03:47:49 +04:00
if ( p - > value = = * get_ctrl_ptr ( minfo , i ) ) return 0 ;
2005-04-17 02:20:36 +04:00
/*
* Check limits .
*/
if ( p - > value > g450_controls [ i ] . desc . maximum ) return - EINVAL ;
if ( p - > value < g450_controls [ i ] . desc . minimum ) return - EINVAL ;
/*
* Store new value .
*/
2009-09-23 03:47:49 +04:00
* get_ctrl_ptr ( minfo , i ) = p - > value ;
2005-04-17 02:20:36 +04:00
switch ( p - > id ) {
case V4L2_CID_BRIGHTNESS :
case V4L2_CID_CONTRAST :
{
int blacklevel , whitelevel ;
2009-09-23 03:47:49 +04:00
g450_compute_bwlevel ( minfo , & blacklevel , & whitelevel ) ;
cve2_set_reg10 ( minfo , 0x0e , blacklevel ) ;
cve2_set_reg10 ( minfo , 0x1e , whitelevel ) ;
2005-04-17 02:20:36 +04:00
}
break ;
case V4L2_CID_SATURATION :
2009-09-23 03:47:49 +04:00
cve2_set_reg ( minfo , 0x20 , p - > value ) ;
cve2_set_reg ( minfo , 0x22 , p - > value ) ;
2005-04-17 02:20:36 +04:00
break ;
case V4L2_CID_HUE :
2009-09-23 03:47:49 +04:00
cve2_set_reg ( minfo , 0x25 , p - > value ) ;
2005-04-17 02:20:36 +04:00
break ;
case MATROXFB_CID_TESTOUT :
{
2009-09-23 03:47:49 +04:00
unsigned char val = cve2_get_reg ( minfo , 0x05 ) ;
2005-04-17 02:20:36 +04:00
if ( p - > value ) val | = 0x02 ;
else val & = ~ 0x02 ;
2009-09-23 03:47:49 +04:00
cve2_set_reg ( minfo , 0x05 , val ) ;
2005-04-17 02:20:36 +04:00
}
break ;
}
return 0 ;
}
static int g450_get_ctrl ( void * md , struct v4l2_control * p ) {
int i ;
2009-09-23 03:47:50 +04:00
struct matrox_fb_info * minfo = md ;
2005-04-17 02:20:36 +04:00
i = get_ctrl_id ( p - > id ) ;
if ( i < 0 ) return - EINVAL ;
2009-09-23 03:47:49 +04:00
p - > value = * get_ctrl_ptr ( minfo , i ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
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 ;
} ;
2009-09-23 03:47:49 +04:00
static void computeRegs ( struct matrox_fb_info * minfo , struct mavenregs * r ,
struct my_timming * mt , const struct output_desc * outd )
{
2005-04-17 02:20:36 +04:00
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 ) ;
2009-09-23 03:47:49 +04:00
mnp = matroxfb_g450_setclk ( minfo , piic , M_VIDEO_PLL ) ;
2005-04-17 02:20:36 +04:00
mt - > mnp = mnp ;
2009-09-23 03:47:49 +04:00
mt - > pixclock = g450_mnp2f ( minfo , mnp ) ;
2005-04-17 02:20:36 +04:00
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 ;
}
2009-09-23 03:47:49 +04:00
# define LR(x) cve2_set_reg(minfo, (x), m->regs[(x)])
static void cve2_init_TV ( struct matrox_fb_info * minfo ,
const struct mavenregs * m )
{
2005-04-17 02:20:36 +04:00
int i ;
LR ( 0x80 ) ;
LR ( 0x82 ) ; LR ( 0x83 ) ;
LR ( 0x84 ) ; LR ( 0x85 ) ;
2009-09-23 03:47:49 +04:00
cve2_set_reg ( minfo , 0x3E , 0x01 ) ;
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < 0x3E ; i + + ) {
LR ( i ) ;
}
2009-09-23 03:47:49 +04:00
cve2_set_reg ( minfo , 0x3E , 0x00 ) ;
2005-04-17 02:20:36 +04:00
}
static int matroxfb_g450_compute ( void * md , struct my_timming * mt ) {
2009-09-23 03:47:50 +04:00
struct matrox_fb_info * minfo = md ;
2005-04-17 02:20:36 +04:00
2009-09-23 03:47:48 +04:00
dprintk ( KERN_DEBUG " Computing, mode=%u \n " , minfo - > outputs [ 1 ] . mode ) ;
2005-04-17 02:20:36 +04:00
if ( mt - > crtc = = MATROXFB_SRC_CRTC2 & &
2009-09-23 03:47:48 +04:00
minfo - > outputs [ 1 ] . mode ! = MATROXFB_OUTPUT_MODE_MONITOR ) {
2005-04-17 02:20:36 +04:00
const struct output_desc * outd ;
2009-09-23 03:47:48 +04:00
cve2_init_TVdata ( minfo - > outputs [ 1 ] . mode , & minfo - > hw . maven , & outd ) ;
2005-04-17 02:20:36 +04:00
{
int blacklevel , whitelevel ;
2009-09-23 03:47:49 +04:00
g450_compute_bwlevel ( minfo , & blacklevel , & whitelevel ) ;
2009-09-23 03:47:48 +04:00
minfo - > hw . maven . regs [ 0x0E ] = blacklevel > > 2 ;
minfo - > hw . maven . regs [ 0x0F ] = blacklevel & 3 ;
minfo - > hw . maven . regs [ 0x1E ] = whitelevel > > 2 ;
minfo - > hw . maven . regs [ 0x1F ] = whitelevel & 3 ;
2005-04-17 02:20:36 +04:00
2009-09-23 03:47:48 +04:00
minfo - > hw . maven . regs [ 0x20 ] =
minfo - > hw . maven . regs [ 0x22 ] = minfo - > altout . tvo_params . saturation ;
2005-04-17 02:20:36 +04:00
2009-09-23 03:47:48 +04:00
minfo - > hw . maven . regs [ 0x25 ] = minfo - > altout . tvo_params . hue ;
2005-04-17 02:20:36 +04:00
2009-09-23 03:47:48 +04:00
if ( minfo - > altout . tvo_params . testout ) {
minfo - > hw . maven . regs [ 0x05 ] | = 0x02 ;
2005-04-17 02:20:36 +04:00
}
}
2009-09-23 03:47:49 +04:00
computeRegs ( minfo , & minfo - > hw . maven , mt , outd ) ;
2005-04-17 02:20:36 +04:00
} else if ( mt - > mnp < 0 ) {
/* We must program clocks before CRTC2, otherwise interlaced mode
startup may fail */
2009-09-23 03:47:49 +04:00
mt - > mnp = matroxfb_g450_setclk ( minfo , mt - > pixclock , ( mt - > crtc = = MATROXFB_SRC_CRTC1 ) ? M_PIXEL_PLL_C : M_VIDEO_PLL ) ;
mt - > pixclock = g450_mnp2f ( minfo , mt - > mnp ) ;
2005-04-17 02:20:36 +04:00
}
dprintk ( KERN_DEBUG " Pixclock = %u \n " , mt - > pixclock ) ;
return 0 ;
}
static int matroxfb_g450_program ( void * md ) {
2009-09-23 03:47:50 +04:00
struct matrox_fb_info * minfo = md ;
2005-04-17 02:20:36 +04:00
2009-09-23 03:47:48 +04:00
if ( minfo - > outputs [ 1 ] . mode ! = MATROXFB_OUTPUT_MODE_MONITOR ) {
2009-09-23 03:47:49 +04:00
cve2_init_TV ( minfo , & minfo - > hw . maven ) ;
2005-04-17 02:20:36 +04:00
}
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 ) {
2009-09-23 03:47:50 +04:00
struct matrox_fb_info * minfo = md ;
2005-04-17 02:20:36 +04:00
if ( mt - > mnp < 0 ) {
2009-09-23 03:47:49 +04:00
mt - > mnp = matroxfb_g450_setclk ( minfo , mt - > pixclock , ( mt - > crtc = = MATROXFB_SRC_CRTC1 ) ? M_PIXEL_PLL_C : M_VIDEO_PLL ) ;
mt - > pixclock = g450_mnp2f ( minfo , mt - > mnp ) ;
2005-04-17 02:20:36 +04:00
}
return 0 ;
}
static struct matrox_altout matroxfb_g450_altout = {
. name = " Secondary output " ,
. compute = matroxfb_g450_compute ,
. program = matroxfb_g450_program ,
. verifymode = matroxfb_g450_verify_mode ,
. getqueryctrl = g450_query_ctrl ,
. getctrl = g450_get_ctrl ,
. setctrl = g450_set_ctrl ,
} ;
static struct matrox_altout matroxfb_g450_dvi = {
. name = " DVI output " ,
. compute = g450_dvi_compute ,
} ;
2009-09-23 03:47:49 +04:00
void matroxfb_g450_connect ( struct matrox_fb_info * minfo )
{
2009-09-23 03:47:48 +04:00
if ( minfo - > devflags . g450dac ) {
down_write ( & minfo - > altout . lock ) ;
2009-09-23 03:47:49 +04:00
tvo_fill_defaults ( minfo ) ;
2009-09-23 03:47:48 +04:00
minfo - > outputs [ 1 ] . src = minfo - > outputs [ 1 ] . default_src ;
minfo - > outputs [ 1 ] . data = minfo ;
minfo - > outputs [ 1 ] . output = & matroxfb_g450_altout ;
minfo - > outputs [ 1 ] . mode = MATROXFB_OUTPUT_MODE_MONITOR ;
minfo - > outputs [ 2 ] . src = minfo - > outputs [ 2 ] . default_src ;
minfo - > outputs [ 2 ] . data = minfo ;
minfo - > outputs [ 2 ] . output = & matroxfb_g450_dvi ;
minfo - > outputs [ 2 ] . mode = MATROXFB_OUTPUT_MODE_MONITOR ;
up_write ( & minfo - > altout . lock ) ;
2005-04-17 02:20:36 +04:00
}
}
2009-09-23 03:47:49 +04:00
void matroxfb_g450_shutdown ( struct matrox_fb_info * minfo )
{
2009-09-23 03:47:48 +04:00
if ( minfo - > devflags . g450dac ) {
down_write ( & minfo - > altout . lock ) ;
minfo - > outputs [ 1 ] . src = MATROXFB_SRC_NONE ;
minfo - > outputs [ 1 ] . output = NULL ;
minfo - > outputs [ 1 ] . data = NULL ;
minfo - > outputs [ 1 ] . mode = MATROXFB_OUTPUT_MODE_MONITOR ;
minfo - > outputs [ 2 ] . src = MATROXFB_SRC_NONE ;
minfo - > outputs [ 2 ] . output = NULL ;
minfo - > outputs [ 2 ] . data = NULL ;
minfo - > outputs [ 2 ] . mode = MATROXFB_OUTPUT_MODE_MONITOR ;
up_write ( & minfo - > altout . lock ) ;
2005-04-17 02:20:36 +04:00
}
}
EXPORT_SYMBOL ( matroxfb_g450_connect ) ;
EXPORT_SYMBOL ( matroxfb_g450_shutdown ) ;
MODULE_AUTHOR ( " (c) 2000-2002 Petr Vandrovec <vandrove@vc.cvut.cz> " ) ;
MODULE_DESCRIPTION ( " Matrox G450/G550 output driver " ) ;
MODULE_LICENSE ( " GPL " ) ;