Subversion Repositories shark

Rev

Rev 54 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
54 pj 1
/*
2
 * IBMRGB52x.c:
3
 *
4
 * RAMDAC definitions for IBM's RGB52x PaletteDAC.
5
 *
6
 * Portion of this file is derived from XFree86's source code.
7
 * [insert XFree86's copyright here].
8
 */
9
 
10
#include <stdio.h>
11
#include "libvga.h"
12
 
13
#include "timing.h"
14
#include "vgaregs.h"
15
#include "driver.h"             /* for __svgalib_driver_report */
16
#include "ramdac.h"
17
 
18
#include "IBMRGB52x.h"
19
 
20
#define IBMRGB52x_STATESIZE     0x101
21
 
22
static int IBMRGB52x_dacspeed = 170000;         /* assuming 170MHz DAC */
23
static int IBMRGB52x_fref = 16000;      /* assuming 16MHz refclock */
24
static int IBMRGB52x_clk = 2;   /* use clock 2 */
25
 
26
#ifdef INCLUDE_IBMRGB52x_DAC_TEST
27
/*
28
 * s3IBMRGB_Probe() from XFree86.
29
 *
30
 * returns 0x01xx for 525, 0x02xx for 524/528, where xx = revision.
31
 */
32
static int IBMRGB52x_probe(void)
33
{
34
    unsigned char CR43, CR55, dac[3], lut[6];
35
    unsigned char ilow, ihigh, id, rev, id2, rev2;
36
    int i, j;
37
    int ret = 0;
38
 
39
    port_out(0x43, 0x3D4);
40
    CR43 = port_in(0x3D5);
41
    port_out(CR43 & ~0x02, 0x3D5);
42
 
43
    port_out(0x55, 0x3D4);
44
    CR55 = port_in(0x3D5);
45
    port_out(CR55 & ~0x03, 0x3D5);
46
 
47
    /* save DAC and first LUT entries */
48
    for (i = 0; i < 3; i++)
49
        dac[i] = port_in(IBMRGB_PIXEL_MASK + i);
50
    for (i = j = 0; i < 2; i++) {
51
        port_out(i, IBMRGB_READ_ADDR);
52
        lut[j++] = port_in(IBMRGB_RAMDAC_DATA);
53
        lut[j++] = port_in(IBMRGB_RAMDAC_DATA);
54
        lut[j++] = port_in(IBMRGB_RAMDAC_DATA);
55
    }
56
 
57
    port_out(0x55, 0x3D4);
58
    port_out((CR55 & ~0x03) | 0x01, 0x3D5);     /* set RS2 */
59
 
60
    /* read ID and revision */
61
    ilow = port_in(IBMRGB_INDEX_LOW);
62
    ihigh = port_in(IBMRGB_INDEX_HIGH);
63
    port_out(0, IBMRGB_INDEX_HIGH);     /* index high */
64
    port_out(IBMRGB_rev, IBMRGB_INDEX_LOW);
65
    rev = port_in(IBMRGB_INDEX_DATA);
66
    port_out(IBMRGB_id, IBMRGB_INDEX_LOW);
67
    id = port_in(IBMRGB_INDEX_DATA);
68
 
69
    /* known IDs:  
70
       1 = RGB525
71
       2 = RGB524, RGB528
72
     */
73
 
74
    if (id >= 1 && id <= 2) {
75
        /* check if ID and revision are read only */
76
        port_out(IBMRGB_rev, IBMRGB_INDEX_LOW);
77
        port_out(~rev, IBMRGB_INDEX_DATA);
78
        port_out(IBMRGB_id, IBMRGB_INDEX_LOW);
79
        port_out(~id, IBMRGB_INDEX_DATA);
80
        port_out(IBMRGB_rev, IBMRGB_INDEX_LOW);
81
        rev2 = port_in(IBMRGB_INDEX_DATA);
82
        port_out(IBMRGB_id, IBMRGB_INDEX_LOW);
83
        id2 = port_in(IBMRGB_INDEX_DATA);
84
 
85
        if (id == id2 && rev == rev2) {         /* IBM RGB52x found */
86
            ret = (id << 8) | rev;
87
        } else {
88
            port_out(IBMRGB_rev, IBMRGB_INDEX_LOW);
89
            port_out(rev, IBMRGB_INDEX_DATA);
90
            port_out(IBMRGB_id, IBMRGB_INDEX_LOW);
91
            port_out(id, IBMRGB_INDEX_DATA);
92
        }
93
    }
94
    port_out(ilow, IBMRGB_INDEX_LOW);
95
    port_out(ihigh, IBMRGB_INDEX_HIGH);
96
 
97
    port_out(0x55, 0x3D4);
98
    port_out(CR55 & ~0x03, 0x3D5);      /* reset RS2 */
99
 
100
    /* restore DAC and first LUT entries */
101
    for (i = j = 0; i < 2; i++) {
102
        port_out(i, IBMRGB_WRITE_ADDR);
103
        port_out(lut[j++], IBMRGB_RAMDAC_DATA);
104
        port_out(lut[j++], IBMRGB_RAMDAC_DATA);
105
        port_out(lut[j++], IBMRGB_RAMDAC_DATA);
106
    }
107
    for (i = 0; i < 3; i++)
108
        port_out(dac[i], IBMRGB_PIXEL_MASK + i);
109
 
110
    port_out(0x43, 0x3D4);
111
    port_out(CR43, 0x3D5);
112
    port_out(0x55, 0x3D4);
113
    port_out(CR55, 0x3D5);
114
 
115
    return ret;
116
}
117
#else
118
#define IBMRGB52x_probe 0
119
#endif
120
 
121
#ifdef INCLUDE_IBMRGB52x_DAC
122
static void IBMRGBSetClock(long freq, int clk, long dacspeed, long fref,
123
                      int *best_m_out, int *best_n_out, int *best_df_out)
124
{
125
    volatile double ffreq, fdacspeed, ffref;
126
    volatile int df, n, m, max_n, min_df;
127
    volatile int best_m = 69, best_n = 17, best_df = 0;
128
    volatile double diff, mindiff;
129
 
130
#define FREQ_MIN   16250        /* 1000 * (0+65) / 4 */
131
#define FREQ_MAX  dacspeed
132
 
133
    if (freq < FREQ_MIN)
134
        ffreq = FREQ_MIN / 1000.0;
135
    else if (freq > FREQ_MAX)
136
        ffreq = FREQ_MAX / 1000.0;
137
    else
138
        ffreq = freq / 1000.0;
139
 
140
    fdacspeed = dacspeed / 1e3;
141
    ffref = fref / 1e3;
142
 
143
    ffreq /= ffref;
144
    ffreq *= 16;
145
    mindiff = ffreq;
146
 
147
    if (freq <= dacspeed / 4)
148
        min_df = 0;
149
    else if (freq <= dacspeed / 2)
150
        min_df = 1;
151
    else
152
        min_df = 2;
153
 
154
    for (df = 0; df < 4; df++) {
155
        ffreq /= 2;
156
        mindiff /= 2;
157
        if (df < min_df)
158
            continue;
159
 
160
        /* the remaining formula is  ffreq = (m+65) / n */
161
 
162
        if (df < 3)
163
            max_n = fref / 1000 / 2;
164
        else
165
            max_n = fref / 1000;
166
        if (max_n > 31)
167
            max_n = 31;
168
 
169
        for (n = 2; n <= max_n; n++) {
170
            m = (int) (ffreq * n + 0.5) - 65;
171
            if (m < 0)
172
                m = 0;
173
            else if (m > 63)
174
                m = 63;
175
 
176
            diff = (m + 65.0) / n - ffreq;
177
            if (diff < 0)
178
                diff = -diff;
179
 
180
            if (diff < mindiff) {
181
                mindiff = diff;
182
                best_n = n;
183
                best_m = m;
184
                best_df = df;
185
            }
186
        }
187
    }
188
 
189
#ifdef DEBUG
81 giacomo 190
    cprintf("clk %d, setting to %f, m 0x%02x %d, n 0x%02x %d, df %d\n", clk,
54 pj 191
           ((best_m + 65.0) / best_n) / (8 >> best_df) * ffref,
192
           best_m, best_m, best_n, best_n, best_df);
193
#endif
194
    *best_m_out = best_m;
195
    *best_n_out = best_n;
196
    *best_df_out = best_df;
197
}
198
 
199
static void IBMRGB52x_init(void)
200
{
201
    unsigned char tmp, CR55;
202
#ifdef INCLUDE_IBMRGB52x_DAC_TEST
203
    int idrev;
204
 
205
    idrev = IBMRGB52x_probe();
206
    if (__svgalib_driver_report)
81 giacomo 207
        cprintf("svgalib: Using IBM RGB 52%d PaletteDAC, revision %d.\n",
54 pj 208
               (idrev >> 8) == 1 ? 5 : 4,
209
               idrev & 0xff);
210
#else
211
    if (__svgalib_driver_report)
81 giacomo 212
        cprintf("svgalib: Using IBM RGB 52x PaletteDAC.\n");
54 pj 213
#endif
214
    /* set RS2 */
215
    port_out(0x55, 0x3D4);
216
    CR55 = port_in(0x3D5) & 0xFC;
217
    port_out(CR55 | 0x01, 0x3D5);
218
 
219
    tmp = port_in(IBMRGB_INDEX_CONTROL);
220
    port_out(tmp & ~0x01, IBMRGB_INDEX_CONTROL);        /* turn off auto-increment */
221
    port_out(0, IBMRGB_INDEX_HIGH);     /* reset index high */
222
 
223
    __svgalib_outCR(0x55, CR55);
224
}
225
 
226
static int IBMRGB52x_match_programmable_clock(int desiredclock)
227
{
228
    int m, n, df;
229
 
230
    IBMRGBSetClock(desiredclock, IBMRGB52x_clk, IBMRGB52x_dacspeed,
231
                   IBMRGB52x_fref, &m, &n, &df);
232
 
233
    return ((m + 65.0) / n) / (8 >> df) * IBMRGB52x_fref;
234
}
235
 
236
static void IBMRGB52x_initialize_clock_state(unsigned char *regs, int freq)
237
{
238
    int m, n, df;
239
 
240
    IBMRGBSetClock(freq, IBMRGB52x_clk, IBMRGB52x_dacspeed,
241
                   IBMRGB52x_fref, &m, &n, &df);
242
 
243
    if (__svgalib_driver_report)
81 giacomo 244
        cprintf("clk %d, setting to %.3f, m 0x%02x %d, n 0x%02x %d, df %d\n",
54 pj 245
               IBMRGB52x_clk, ((m + 65.0) / n) / (8 >> df) * IBMRGB52x_fref / 1000,
246
               m, m, n, n, df);
247
 
248
    regs[IBMRGB_misc_clock] |= 0x01;
249
    regs[IBMRGB_m0 + 2 * IBMRGB52x_clk] = (df << 6) | (m & 0x3f);
250
    regs[IBMRGB_n0 + 2 * IBMRGB52x_clk] = n;
251
    regs[IBMRGB_pll_ctrl2] &= 0xf0;
252
    regs[IBMRGB_pll_ctrl2] |= IBMRGB52x_clk;
253
    regs[IBMRGB_pll_ctrl1] &= 0xf8;
254
    regs[IBMRGB_pll_ctrl1] |= 0x03;
255
}
256
 
257
static void IBMRGB52x_savestate(unsigned char *regs)
258
{
259
    int i;
260
    unsigned char tmp;
261
 
262
    /* set RS2 */
263
    port_out(0x55, 0x3D4);
264
    tmp = port_in(0x3D5) & 0xFC;
265
    port_out(tmp | 0x01, 0x3D5);
266
 
267
    for (i = 0; i < 0x100; i++) {
268
        port_out(i, IBMRGB_INDEX_LOW);  /* high index is set to 0 */
269
        regs[i] = port_in(IBMRGB_INDEX_DATA);
270
    }
271
    regs[0x100] = __svgalib_inCR(0x22);
272
 
273
    __svgalib_outCR(0x55, tmp);
274
}
275
 
276
/* SL: not complete, need more work for 525. */
277
static void IBMRGB52x_restorestate(const unsigned char *regs)
278
{
279
    int i;
280
    unsigned char tmp;
281
 
282
    /* set RS2 */
283
    port_out(0x55, 0x3D4);
284
    tmp = port_in(0x3D5) & 0xFC;
285
    port_out(tmp | 0x01, 0x3D5);
286
 
287
    for (i = 0; i < 0x100; i++) {
288
        port_out(i, IBMRGB_INDEX_LOW);  /* high index is set to 0 */
289
        port_out(regs[i], IBMRGB_INDEX_DATA);
290
    }
291
    __svgalib_outCR(0x22, regs[0x100]);
292
 
293
    __svgalib_outCR(0x55, tmp);
294
}
295
 
296
static int IBMRGB52x_map_clock(int bpp, int pixelclock)
297
{
298
    return pixelclock;
299
}
300
 
301
static int IBMRGB52x_map_horizontal_crtc(int bpp, int pixelclock, int htiming)
302
{
303
#ifdef PIXEL_MULTIPLEXING
304
    switch (bpp) {
305
    case 4:
306
        break;
307
    case 8:
308
        return htiming / 2;
309
    case 16:
310
        break;
311
    case 24:
312
        return htiming * 3 / 2;
313
    case 32:
314
        return htiming * 2;
315
    }
316
#endif
317
    return htiming;
318
}
319
 
320
static void IBMRGB52x_initializestate(unsigned char *regs, int bpp, int colormode,
321
                                      int pixelclock)
322
{
323
    unsigned char tmp;
324
 
325
    regs[IBMRGB_misc_clock] = (regs[IBMRGB_misc_clock] & 0xf0) | 0x03;
326
    regs[IBMRGB_sync] = 0;
327
    regs[IBMRGB_hsync_pos] = 0;
328
    regs[IBMRGB_pwr_mgmt] = 0;
329
    regs[IBMRGB_dac_op] &= ~0x08;       /* no sync on green */
330
    regs[IBMRGB_dac_op] |= 0x02;        /* fast slew */
331
    regs[IBMRGB_pal_ctrl] = 0;
332
    regs[IBMRGB_misc1] &= ~0x43;
333
    regs[IBMRGB_misc1] |= 1;
334
#ifdef PIXEL_MULTIPLEXING
335
    if (bpp >= 8)
336
        regs[IBMRGB_misc2] = 0x43;      /* use SID bus? 0x47 for DAC_8_BIT */
337
#endif
338
    tmp = __svgalib_inCR(0x22);
339
    if (bpp <= 8)               /* and 968 */
340
        __svgalib_outCR(0x22, tmp | 0x08);
341
    else
342
        __svgalib_outCR(0x22, tmp & ~0x08);
343
 
344
    regs[IBMRGB_pix_fmt] &= ~0x07;
345
    switch (bpp) {
346
    case 4:
347
    case 8:
348
        regs[IBMRGB_pix_fmt] |= 0x03;
349
        regs[IBMRGB_8bpp] = 0x00;
350
        break;
351
    case 15:
352
        regs[IBMRGB_pix_fmt] |= 0x04;
353
        regs[IBMRGB_16bpp] = 0x02;
354
        break;
355
    case 16:
356
        regs[IBMRGB_pix_fmt] |= 0x04;
357
        regs[IBMRGB_16bpp] = 0x00;
358
        break;
359
    case 24:
360
        regs[IBMRGB_pix_fmt] |= 0x05;   /* SL: guess */
361
        regs[IBMRGB_24bpp] = 0x00;
362
        break;
363
    case 32:
364
        regs[IBMRGB_pix_fmt] |= 0x06;
365
        regs[IBMRGB_32bpp] = 0x00;
366
        break;
367
    }
368
    IBMRGB52x_initialize_clock_state(regs,
369
                                   IBMRGB52x_map_clock(bpp, pixelclock));
370
}
371
 
372
static void IBMRGB52x_qualify_cardspecs(CardSpecs * cardspecs, int dacspeed)
373
{
374
    IBMRGB52x_dacspeed = __svgalib_setDacSpeed(dacspeed, 170000);       /* 220 MHz version exist also */
375
    cardspecs->maxPixelClock4bpp = IBMRGB52x_dacspeed;
376
    cardspecs->maxPixelClock8bpp = IBMRGB52x_dacspeed;
377
#ifdef PIXEL_MULTIPLEXING
378
    cardspecs->maxPixelClock16bpp = IBMRGB52x_dacspeed;
379
    cardspecs->maxPixelClock24bpp = IBMRGB52x_dacspeed * 3 / 2;
380
    cardspecs->maxPixelClock32bpp = IBMRGB52x_dacspeed / 2;
381
#else
382
    cardspecs->maxPixelClock16bpp = 0;
383
    cardspecs->maxPixelClock24bpp = 0;
384
    cardspecs->maxPixelClock32bpp = 0;
385
#endif
386
    cardspecs->mapClock = IBMRGB52x_map_clock;
387
    cardspecs->matchProgrammableClock = IBMRGB52x_match_programmable_clock;
388
    cardspecs->mapHorizontalCrtc = IBMRGB52x_map_horizontal_crtc;
389
    cardspecs->flags |= CLOCK_PROGRAMMABLE;
390
}
391
 
392
DacMethods __svgalib_IBMRGB52x_methods =
393
{
394
    IBMRGB52x,
395
    "IBM RGB 52x PaletteDAC",
396
    DAC_HAS_PROGRAMMABLE_CLOCKS,
397
    IBMRGB52x_probe,
398
    IBMRGB52x_init,
399
    IBMRGB52x_qualify_cardspecs,
400
    IBMRGB52x_savestate,
401
    IBMRGB52x_restorestate,
402
    IBMRGB52x_initializestate,
403
    IBMRGB52x_STATESIZE
404
};
405
#endif