root/drivers/video/fbdev/matrox/matroxfb_g450.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_ctrl_id
  2. get_ctrl_ptr
  3. tvo_fill_defaults
  4. cve2_get_reg
  5. cve2_set_reg
  6. cve2_set_reg10
  7. g450_compute_bwlevel
  8. g450_query_ctrl
  9. g450_set_ctrl
  10. g450_get_ctrl
  11. computeRegs
  12. cve2_init_TVdata
  13. cve2_init_TV
  14. matroxfb_g450_compute
  15. matroxfb_g450_program
  16. matroxfb_g450_verify_mode
  17. g450_dvi_compute
  18. matroxfb_g450_connect
  19. matroxfb_g450_shutdown

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *
   4  * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
   5  *
   6  * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
   7  *
   8  * Portions Copyright (c) 2001 Matrox Graphics Inc.
   9  *
  10  * Version: 1.65 2002/08/14
  11  *
  12  * See matroxfb_base.c for contributors.
  13  *
  14  */
  15 
  16 #include "matroxfb_base.h"
  17 #include "matroxfb_misc.h"
  18 #include "matroxfb_DAC1064.h"
  19 #include "g450_pll.h"
  20 #include <linux/matroxfb.h>
  21 #include <asm/div64.h>
  22 
  23 #include "matroxfb_g450.h"
  24 
  25 /* Definition of the various controls */
  26 struct mctl {
  27         struct v4l2_queryctrl desc;
  28         size_t control;
  29 };
  30 
  31 #define BLMIN   0xF3
  32 #define WLMAX   0x3FF
  33 
  34 static const struct mctl g450_controls[] =
  35 {       { { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER, 
  36           "brightness",
  37           0, WLMAX-BLMIN, 1, 370-BLMIN, 
  38           0,
  39         }, offsetof(struct matrox_fb_info, altout.tvo_params.brightness) },
  40         { { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER, 
  41           "contrast",
  42           0, 1023, 1, 127, 
  43           0,
  44         }, offsetof(struct matrox_fb_info, altout.tvo_params.contrast) },
  45         { { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
  46           "saturation",
  47           0, 255, 1, 165, 
  48           0,
  49         }, offsetof(struct matrox_fb_info, altout.tvo_params.saturation) },
  50         { { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
  51           "hue",
  52           0, 255, 1, 0, 
  53           0,
  54         }, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
  55         { { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
  56           "test output",
  57           0, 1, 1, 0, 
  58           0,
  59         }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
  60 };
  61 
  62 #define G450CTRLS ARRAY_SIZE(g450_controls)
  63 
  64 /* Return: positive number: id found
  65            -EINVAL:         id not found, return failure
  66            -ENOENT:         id not found, create fake disabled control */
  67 static int get_ctrl_id(__u32 v4l2_id) {
  68         int i;
  69 
  70         for (i = 0; i < G450CTRLS; i++) {
  71                 if (v4l2_id < g450_controls[i].desc.id) {
  72                         if (g450_controls[i].desc.id == 0x08000000) {
  73                                 return -EINVAL;
  74                         }
  75                         return -ENOENT;
  76                 }
  77                 if (v4l2_id == g450_controls[i].desc.id) {
  78                         return i;
  79                 }
  80         }
  81         return -EINVAL;
  82 }
  83 
  84 static inline int *get_ctrl_ptr(struct matrox_fb_info *minfo, unsigned int idx)
  85 {
  86         return (int*)((char*)minfo + g450_controls[idx].control);
  87 }
  88 
  89 static void tvo_fill_defaults(struct matrox_fb_info *minfo)
  90 {
  91         unsigned int i;
  92         
  93         for (i = 0; i < G450CTRLS; i++) {
  94                 *get_ctrl_ptr(minfo, i) = g450_controls[i].desc.default_value;
  95         }
  96 }
  97 
  98 static int cve2_get_reg(struct matrox_fb_info *minfo, int reg)
  99 {
 100         unsigned long flags;
 101         int val;
 102         
 103         matroxfb_DAC_lock_irqsave(flags);
 104         matroxfb_DAC_out(minfo, 0x87, reg);
 105         val = matroxfb_DAC_in(minfo, 0x88);
 106         matroxfb_DAC_unlock_irqrestore(flags);
 107         return val;
 108 }
 109 
 110 static void cve2_set_reg(struct matrox_fb_info *minfo, int reg, int val)
 111 {
 112         unsigned long flags;
 113 
 114         matroxfb_DAC_lock_irqsave(flags);
 115         matroxfb_DAC_out(minfo, 0x87, reg);
 116         matroxfb_DAC_out(minfo, 0x88, val);
 117         matroxfb_DAC_unlock_irqrestore(flags);
 118 }
 119 
 120 static void cve2_set_reg10(struct matrox_fb_info *minfo, int reg, int val)
 121 {
 122         unsigned long flags;
 123 
 124         matroxfb_DAC_lock_irqsave(flags);
 125         matroxfb_DAC_out(minfo, 0x87, reg);
 126         matroxfb_DAC_out(minfo, 0x88, val >> 2);
 127         matroxfb_DAC_out(minfo, 0x87, reg + 1);
 128         matroxfb_DAC_out(minfo, 0x88, val & 3);
 129         matroxfb_DAC_unlock_irqrestore(flags);
 130 }
 131 
 132 static void g450_compute_bwlevel(const struct matrox_fb_info *minfo, int *bl,
 133                                  int *wl)
 134 {
 135         const int b = minfo->altout.tvo_params.brightness + BLMIN;
 136         const int c = minfo->altout.tvo_params.contrast;
 137 
 138         *bl = max(b - c, BLMIN);
 139         *wl = min(b + c, WLMAX);
 140 }
 141 
 142 static int g450_query_ctrl(void* md, struct v4l2_queryctrl *p) {
 143         int i;
 144         
 145         i = get_ctrl_id(p->id);
 146         if (i >= 0) {
 147                 *p = g450_controls[i].desc;
 148                 return 0;
 149         }
 150         if (i == -ENOENT) {
 151                 static const struct v4l2_queryctrl disctrl = 
 152                         { .flags = V4L2_CTRL_FLAG_DISABLED };
 153                         
 154                 i = p->id;
 155                 *p = disctrl;
 156                 p->id = i;
 157                 sprintf(p->name, "Ctrl #%08X", i);
 158                 return 0;
 159         }
 160         return -EINVAL;
 161 }
 162 
 163 static int g450_set_ctrl(void* md, struct v4l2_control *p) {
 164         int i;
 165         struct matrox_fb_info *minfo = md;
 166         
 167         i = get_ctrl_id(p->id);
 168         if (i < 0) return -EINVAL;
 169 
 170         /*
 171          * Check if changed.
 172          */
 173         if (p->value == *get_ctrl_ptr(minfo, i)) return 0;
 174 
 175         /*
 176          * Check limits.
 177          */
 178         if (p->value > g450_controls[i].desc.maximum) return -EINVAL;
 179         if (p->value < g450_controls[i].desc.minimum) return -EINVAL;
 180 
 181         /*
 182          * Store new value.
 183          */
 184         *get_ctrl_ptr(minfo, i) = p->value;
 185 
 186         switch (p->id) {
 187                 case V4L2_CID_BRIGHTNESS:
 188                 case V4L2_CID_CONTRAST:
 189                         {
 190                                 int blacklevel, whitelevel;
 191                                 g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
 192                                 cve2_set_reg10(minfo, 0x0e, blacklevel);
 193                                 cve2_set_reg10(minfo, 0x1e, whitelevel);
 194                         }
 195                         break;
 196                 case V4L2_CID_SATURATION:
 197                         cve2_set_reg(minfo, 0x20, p->value);
 198                         cve2_set_reg(minfo, 0x22, p->value);
 199                         break;
 200                 case V4L2_CID_HUE:
 201                         cve2_set_reg(minfo, 0x25, p->value);
 202                         break;
 203                 case MATROXFB_CID_TESTOUT:
 204                         {
 205                                 unsigned char val = cve2_get_reg(minfo, 0x05);
 206                                 if (p->value) val |=  0x02;
 207                                 else          val &= ~0x02;
 208                                 cve2_set_reg(minfo, 0x05, val);
 209                         }
 210                         break;
 211         }
 212         
 213 
 214         return 0;
 215 }
 216 
 217 static int g450_get_ctrl(void* md, struct v4l2_control *p) {
 218         int i;
 219         struct matrox_fb_info *minfo = md;
 220         
 221         i = get_ctrl_id(p->id);
 222         if (i < 0) return -EINVAL;
 223         p->value = *get_ctrl_ptr(minfo, i);
 224         return 0;
 225 }
 226 
 227 struct output_desc {
 228         unsigned int    h_vis;
 229         unsigned int    h_f_porch;
 230         unsigned int    h_sync;
 231         unsigned int    h_b_porch;
 232         unsigned long long int  chromasc;
 233         unsigned int    burst;
 234         unsigned int    v_total;
 235 };
 236 
 237 static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r,
 238                         struct my_timming *mt, const struct output_desc *outd)
 239 {
 240         u_int32_t chromasc;
 241         u_int32_t hlen;
 242         u_int32_t hsl;
 243         u_int32_t hbp;
 244         u_int32_t hfp;
 245         u_int32_t hvis;
 246         unsigned int pixclock;
 247         unsigned long long piic;
 248         int mnp;
 249         int over;
 250         
 251         r->regs[0x80] = 0x03;   /* | 0x40 for SCART */
 252 
 253         hvis = ((mt->HDisplay << 1) + 3) & ~3;
 254         
 255         if (hvis >= 2048) {
 256                 hvis = 2044;
 257         }
 258         
 259         piic = 1000000000ULL * hvis;
 260         do_div(piic, outd->h_vis);
 261 
 262         dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic);
 263         
 264         mnp = matroxfb_g450_setclk(minfo, piic, M_VIDEO_PLL);
 265         
 266         mt->mnp = mnp;
 267         mt->pixclock = g450_mnp2f(minfo, mnp);
 268 
 269         dprintk(KERN_DEBUG "MNP=%08X\n", mnp);
 270 
 271         pixclock = 1000000000U / mt->pixclock;
 272 
 273         dprintk(KERN_DEBUG "Got %u ps pixclock\n", pixclock);
 274 
 275         piic = outd->chromasc;
 276         do_div(piic, mt->pixclock);
 277         chromasc = piic;
 278         
 279         dprintk(KERN_DEBUG "Chroma is %08X\n", chromasc);
 280 
 281         r->regs[0] = piic >> 24;
 282         r->regs[1] = piic >> 16;
 283         r->regs[2] = piic >>  8;
 284         r->regs[3] = piic >>  0;
 285         hbp = (((outd->h_b_porch + pixclock) / pixclock)) & ~1;
 286         hfp = (((outd->h_f_porch + pixclock) / pixclock)) & ~1;
 287         hsl = (((outd->h_sync + pixclock) / pixclock)) & ~1;
 288         hlen = hvis + hfp + hsl + hbp;
 289         over = hlen & 0x0F;
 290         
 291         dprintk(KERN_DEBUG "WL: vis=%u, hf=%u, hs=%u, hb=%u, total=%u\n", hvis, hfp, hsl, hbp, hlen);
 292 
 293         if (over) {
 294                 hfp -= over;
 295                 hlen -= over;
 296                 if (over <= 2) {
 297                 } else if (over < 10) {
 298                         hfp += 4;
 299                         hlen += 4;
 300                 } else {
 301                         hfp += 16;
 302                         hlen += 16;
 303                 }
 304         }
 305 
 306         /* maybe cve2 has requirement 800 < hlen < 1184 */
 307         r->regs[0x08] = hsl;
 308         r->regs[0x09] = (outd->burst + pixclock - 1) / pixclock;        /* burst length */
 309         r->regs[0x0A] = hbp;
 310         r->regs[0x2C] = hfp;
 311         r->regs[0x31] = hvis / 8;
 312         r->regs[0x32] = hvis & 7;
 313         
 314         dprintk(KERN_DEBUG "PG: vis=%04X, hf=%02X, hs=%02X, hb=%02X, total=%04X\n", hvis, hfp, hsl, hbp, hlen);
 315 
 316         r->regs[0x84] = 1;      /* x sync point */
 317         r->regs[0x85] = 0;
 318         hvis = hvis >> 1;
 319         hlen = hlen >> 1;
 320         
 321         dprintk(KERN_DEBUG "hlen=%u hvis=%u\n", hlen, hvis);
 322 
 323         mt->interlaced = 1;
 324 
 325         mt->HDisplay = hvis & ~7;
 326         mt->HSyncStart = mt->HDisplay + 8;
 327         mt->HSyncEnd = (hlen & ~7) - 8;
 328         mt->HTotal = hlen;
 329 
 330         {
 331                 int upper;
 332                 unsigned int vtotal;
 333                 unsigned int vsyncend;
 334                 unsigned int vdisplay;
 335                 
 336                 vtotal = mt->VTotal;
 337                 vsyncend = mt->VSyncEnd;
 338                 vdisplay = mt->VDisplay;
 339                 if (vtotal < outd->v_total) {
 340                         unsigned int yovr = outd->v_total - vtotal;
 341                         
 342                         vsyncend += yovr >> 1;
 343                 } else if (vtotal > outd->v_total) {
 344                         vdisplay = outd->v_total - 4;
 345                         vsyncend = outd->v_total;
 346                 }
 347                 upper = (outd->v_total - vsyncend) >> 1;        /* in field lines */
 348                 r->regs[0x17] = outd->v_total / 4;
 349                 r->regs[0x18] = outd->v_total & 3;
 350                 r->regs[0x33] = upper - 1;      /* upper blanking */
 351                 r->regs[0x82] = upper;          /* y sync point */
 352                 r->regs[0x83] = upper >> 8;
 353                 
 354                 mt->VDisplay = vdisplay;
 355                 mt->VSyncStart = outd->v_total - 2;
 356                 mt->VSyncEnd = outd->v_total;
 357                 mt->VTotal = outd->v_total;
 358         }
 359 }
 360 
 361 static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct output_desc** outd) {
 362         static const struct output_desc paloutd = {
 363                 .h_vis     = 52148148,  // ps
 364                 .h_f_porch =  1407407,  // ps
 365                 .h_sync    =  4666667,  // ps
 366                 .h_b_porch =  5777778,  // ps
 367                 .chromasc  = 19042247534182ULL, // 4433618.750 Hz
 368                 .burst     =  2518518,  // ps
 369                 .v_total   =      625,
 370         };
 371         static const struct output_desc ntscoutd = {
 372                 .h_vis     = 52888889,  // ps
 373                 .h_f_porch =  1333333,  // ps
 374                 .h_sync    =  4666667,  // ps
 375                 .h_b_porch =  4666667,  // ps
 376                 .chromasc  = 15374030659475ULL, // 3579545.454 Hz
 377                 .burst     =  2418418,  // ps
 378                 .v_total   =      525,  // lines
 379         };
 380 
 381         static const struct mavenregs palregs = { {
 382                 0x2A, 0x09, 0x8A, 0xCB, /* 00: chroma subcarrier */
 383                 0x00,
 384                 0x00,   /* test */
 385                 0xF9,   /* modified by code (F9 written...) */
 386                 0x00,   /* ? not written */
 387                 0x7E,   /* 08 */
 388                 0x44,   /* 09 */
 389                 0x9C,   /* 0A */
 390                 0x2E,   /* 0B */
 391                 0x21,   /* 0C */
 392                 0x00,   /* ? not written */
 393 //              0x3F, 0x03, /* 0E-0F */
 394                 0x3C, 0x03,
 395                 0x3C, 0x03, /* 10-11 */
 396                 0x1A,   /* 12 */
 397                 0x2A,   /* 13 */
 398                 0x1C, 0x3D, 0x14, /* 14-16 */
 399                 0x9C, 0x01, /* 17-18 */
 400                 0x00,   /* 19 */
 401                 0xFE,   /* 1A */
 402                 0x7E,   /* 1B */
 403                 0x60,   /* 1C */
 404                 0x05,   /* 1D */
 405 //              0x89, 0x03, /* 1E-1F */
 406                 0xAD, 0x03,
 407 //              0x72,   /* 20 */
 408                 0xA5,
 409                 0x07,   /* 21 */
 410 //              0x72,   /* 22 */
 411                 0xA5,
 412                 0x00,   /* 23 */
 413                 0x00,   /* 24 */
 414                 0x00,   /* 25 */
 415                 0x08,   /* 26 */
 416                 0x04,   /* 27 */
 417                 0x00,   /* 28 */
 418                 0x1A,   /* 29 */
 419                 0x55, 0x01, /* 2A-2B */
 420                 0x26,   /* 2C */
 421                 0x07, 0x7E, /* 2D-2E */
 422                 0x02, 0x54, /* 2F-30 */
 423                 0xB0, 0x00, /* 31-32 */
 424                 0x14,   /* 33 */
 425                 0x49,   /* 34 */
 426                 0x00,   /* 35 written multiple times */
 427                 0x00,   /* 36 not written */
 428                 0xA3,   /* 37 */
 429                 0xC8,   /* 38 */
 430                 0x22,   /* 39 */
 431                 0x02,   /* 3A */
 432                 0x22,   /* 3B */
 433                 0x3F, 0x03, /* 3C-3D */
 434                 0x00,   /* 3E written multiple times */
 435                 0x00,   /* 3F not written */
 436         } };
 437         static const struct mavenregs ntscregs = { {
 438                 0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */
 439                 0x00,
 440                 0x00,   /* test */
 441                 0xF9,   /* modified by code (F9 written...) */
 442                 0x00,   /* ? not written */
 443                 0x7E,   /* 08 */
 444                 0x43,   /* 09 */
 445                 0x7E,   /* 0A */
 446                 0x3D,   /* 0B */
 447                 0x00,   /* 0C */
 448                 0x00,   /* ? not written */
 449                 0x41, 0x00, /* 0E-0F */
 450                 0x3C, 0x00, /* 10-11 */
 451                 0x17,   /* 12 */
 452                 0x21,   /* 13 */
 453                 0x1B, 0x1B, 0x24, /* 14-16 */
 454                 0x83, 0x01, /* 17-18 */
 455                 0x00,   /* 19 */
 456                 0x0F,   /* 1A */
 457                 0x0F,   /* 1B */
 458                 0x60,   /* 1C */
 459                 0x05,   /* 1D */
 460                 //0x89, 0x02, /* 1E-1F */
 461                 0xC0, 0x02, /* 1E-1F */
 462                 //0x5F, /* 20 */
 463                 0x9C,   /* 20 */
 464                 0x04,   /* 21 */
 465                 //0x5F, /* 22 */
 466                 0x9C,   /* 22 */
 467                 0x01,   /* 23 */
 468                 0x02,   /* 24 */
 469                 0x00,   /* 25 */
 470                 0x0A,   /* 26 */
 471                 0x05,   /* 27 */
 472                 0x00,   /* 28 */
 473                 0x10,   /* 29 */
 474                 0xFF, 0x03, /* 2A-2B */
 475                 0x24,   /* 2C */
 476                 0x0F, 0x78, /* 2D-2E */
 477                 0x00, 0x00, /* 2F-30 */
 478                 0xB2, 0x04, /* 31-32 */
 479                 0x14,   /* 33 */
 480                 0x02,   /* 34 */
 481                 0x00,   /* 35 written multiple times */
 482                 0x00,   /* 36 not written */
 483                 0xA3,   /* 37 */
 484                 0xC8,   /* 38 */
 485                 0x15,   /* 39 */
 486                 0x05,   /* 3A */
 487                 0x3B,   /* 3B */
 488                 0x3C, 0x00, /* 3C-3D */
 489                 0x00,   /* 3E written multiple times */
 490                 0x00,   /* never written */
 491         } };
 492 
 493         if (norm == MATROXFB_OUTPUT_MODE_PAL) {
 494                 *data = palregs;
 495                 *outd = &paloutd;
 496         } else {
 497                 *data = ntscregs;
 498                 *outd = &ntscoutd;
 499         }
 500         return;
 501 }
 502 
 503 #define LR(x) cve2_set_reg(minfo, (x), m->regs[(x)])
 504 static void cve2_init_TV(struct matrox_fb_info *minfo,
 505                          const struct mavenregs *m)
 506 {
 507         int i;
 508 
 509         LR(0x80);
 510         LR(0x82); LR(0x83);
 511         LR(0x84); LR(0x85);
 512         
 513         cve2_set_reg(minfo, 0x3E, 0x01);
 514         
 515         for (i = 0; i < 0x3E; i++) {
 516                 LR(i);
 517         }
 518         cve2_set_reg(minfo, 0x3E, 0x00);
 519 }
 520 
 521 static int matroxfb_g450_compute(void* md, struct my_timming* mt) {
 522         struct matrox_fb_info *minfo = md;
 523 
 524         dprintk(KERN_DEBUG "Computing, mode=%u\n", minfo->outputs[1].mode);
 525 
 526         if (mt->crtc == MATROXFB_SRC_CRTC2 &&
 527             minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
 528                 const struct output_desc* outd;
 529 
 530                 cve2_init_TVdata(minfo->outputs[1].mode, &minfo->hw.maven, &outd);
 531                 {
 532                         int blacklevel, whitelevel;
 533                         g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
 534                         minfo->hw.maven.regs[0x0E] = blacklevel >> 2;
 535                         minfo->hw.maven.regs[0x0F] = blacklevel & 3;
 536                         minfo->hw.maven.regs[0x1E] = whitelevel >> 2;
 537                         minfo->hw.maven.regs[0x1F] = whitelevel & 3;
 538 
 539                         minfo->hw.maven.regs[0x20] =
 540                         minfo->hw.maven.regs[0x22] = minfo->altout.tvo_params.saturation;
 541 
 542                         minfo->hw.maven.regs[0x25] = minfo->altout.tvo_params.hue;
 543 
 544                         if (minfo->altout.tvo_params.testout) {
 545                                 minfo->hw.maven.regs[0x05] |= 0x02;
 546                         }
 547                 }
 548                 computeRegs(minfo, &minfo->hw.maven, mt, outd);
 549         } else if (mt->mnp < 0) {
 550                 /* We must program clocks before CRTC2, otherwise interlaced mode
 551                    startup may fail */
 552                 mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
 553                 mt->pixclock = g450_mnp2f(minfo, mt->mnp);
 554         }
 555         dprintk(KERN_DEBUG "Pixclock = %u\n", mt->pixclock);
 556         return 0;
 557 }
 558 
 559 static int matroxfb_g450_program(void* md) {
 560         struct matrox_fb_info *minfo = md;
 561         
 562         if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
 563                 cve2_init_TV(minfo, &minfo->hw.maven);
 564         }
 565         return 0;
 566 }
 567 
 568 static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) {
 569         switch (arg) {
 570                 case MATROXFB_OUTPUT_MODE_PAL:
 571                 case MATROXFB_OUTPUT_MODE_NTSC:
 572                 case MATROXFB_OUTPUT_MODE_MONITOR:
 573                         return 0;
 574         }
 575         return -EINVAL;
 576 }
 577 
 578 static int g450_dvi_compute(void* md, struct my_timming* mt) {
 579         struct matrox_fb_info *minfo = md;
 580 
 581         if (mt->mnp < 0) {
 582                 mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
 583                 mt->pixclock = g450_mnp2f(minfo, mt->mnp);
 584         }
 585         return 0;
 586 }
 587 
 588 static struct matrox_altout matroxfb_g450_altout = {
 589         .name           = "Secondary output",
 590         .compute        = matroxfb_g450_compute,
 591         .program        = matroxfb_g450_program,
 592         .verifymode     = matroxfb_g450_verify_mode,
 593         .getqueryctrl   = g450_query_ctrl,
 594         .getctrl        = g450_get_ctrl,
 595         .setctrl        = g450_set_ctrl,
 596 };
 597 
 598 static struct matrox_altout matroxfb_g450_dvi = {
 599         .name           = "DVI output",
 600         .compute        = g450_dvi_compute,
 601 };
 602 
 603 void matroxfb_g450_connect(struct matrox_fb_info *minfo)
 604 {
 605         if (minfo->devflags.g450dac) {
 606                 down_write(&minfo->altout.lock);
 607                 tvo_fill_defaults(minfo);
 608                 minfo->outputs[1].src = minfo->outputs[1].default_src;
 609                 minfo->outputs[1].data = minfo;
 610                 minfo->outputs[1].output = &matroxfb_g450_altout;
 611                 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
 612                 minfo->outputs[2].src = minfo->outputs[2].default_src;
 613                 minfo->outputs[2].data = minfo;
 614                 minfo->outputs[2].output = &matroxfb_g450_dvi;
 615                 minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
 616                 up_write(&minfo->altout.lock);
 617         }
 618 }
 619 
 620 void matroxfb_g450_shutdown(struct matrox_fb_info *minfo)
 621 {
 622         if (minfo->devflags.g450dac) {
 623                 down_write(&minfo->altout.lock);
 624                 minfo->outputs[1].src = MATROXFB_SRC_NONE;
 625                 minfo->outputs[1].output = NULL;
 626                 minfo->outputs[1].data = NULL;
 627                 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
 628                 minfo->outputs[2].src = MATROXFB_SRC_NONE;
 629                 minfo->outputs[2].output = NULL;
 630                 minfo->outputs[2].data = NULL;
 631                 minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
 632                 up_write(&minfo->altout.lock);
 633         }
 634 }
 635 
 636 EXPORT_SYMBOL(matroxfb_g450_connect);
 637 EXPORT_SYMBOL(matroxfb_g450_shutdown);
 638 
 639 MODULE_AUTHOR("(c) 2000-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
 640 MODULE_DESCRIPTION("Matrox G450/G550 output driver");
 641 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */