9 * Clocks which require fiddling with the S3 registers
10 * in order to be loaded.
13 setcrt42(Vga* vga, Ctlr* ctlr, uchar index)
15 trace("%s->clock->setcrt42\n", ctlr->name);
17 vgao(MiscW, vga->misc & ~0x0C);
18 outportb(Crtx+1, 0x00);
20 vga->crt[0x42] = (vga->crt[0x42] & 0xF0)|index;
21 vgao(MiscW, vga->misc);
22 vgaxo(Crtx, 0x42, vga->crt[0x42]);
26 icd2061aload(Vga* vga, Ctlr* ctlr)
32 trace("%s->clock->icd2061aload\n", ctlr->name);
34 * The serial word to be loaded into the icd2061a is
35 * (2<<21)|(vga->i<<17)|((vga->n)<<10)|(vga->p<<7)|vga->d
36 * Always select ICD2061A REG2.
38 sdata = (2<<21)|(vga->i[0]<<17)|((vga->n[0])<<10)|(vga->p[0]<<7)|vga->d[0];
41 * The display should be already off to enable us to clock the
42 * serial data word into either MiscW or Crt42.
44 * Set the Misc register to make clock-select-out the contents of
45 * register Crt42. Must turn the sequencer off when changing bits
46 * <3:2> of Misc. Also, must set Crt42 to 0 before setting <3:2>
47 * of Misc due to a hardware glitch.
49 vgao(MiscW, vga->misc & ~0x0C);
50 crt42 = vgaxi(Crtx, 0x42) & 0xF0;
51 outportb(Crtx+1, 0x00);
53 vgaxo(Seqx, 0x00, 0x00);
54 vgao(MiscW, vga->misc|0x0C);
55 vgaxo(Seqx, 0x00, 0x03);
58 * Unlock the ICD2061A. The unlock sequence is at least 5 low-to-high
59 * transitions of CLK with DATA high, followed by a single low-to-high
60 * transition of CLK with DATA low.
61 * Using Crt42, CLK is bit0, DATA is bit 1. If we used MiscW, they'd
62 * be bits 2 and 3 respectively.
64 outportb(Crtx+1, crt42|0x00); /* -DATA|-CLK */
65 outportb(Crtx+1, crt42|0x02); /* +DATA|-CLK */
66 for(i = 0; i < 5; i++){
67 outportb(Crtx+1, crt42|0x03); /* +DATA|+CLK */
68 outportb(Crtx+1, crt42|0x02); /* +DATA|-CLK */
70 outportb(Crtx+1, crt42|0x00); /* -DATA|-CLK */
71 outportb(Crtx+1, crt42|0x01); /* -DATA|+CLK */
74 * Now write the serial data word, framed by a start-bit and a stop-bit.
75 * The data is written using a modified Manchester encoding such that a
76 * data-bit is sampled on the rising edge of CLK and the complement of
77 * the data-bit is sampled on the previous falling edge of CLK.
79 outportb(Crtx+1, crt42|0x00); /* -DATA|-CLK (start-bit) */
80 outportb(Crtx+1, crt42|0x01); /* -DATA|+CLK */
82 for(i = 0; i < 24; i++){ /* serial data word */
84 outportb(Crtx+1, crt42|0x01); /* -DATA|+CLK */
85 outportb(Crtx+1, crt42|0x00); /* -DATA|-CLK (falling edge) */
86 outportb(Crtx+1, crt42|0x02); /* +DATA|-CLK */
87 outportb(Crtx+1, crt42|0x03); /* +DATA|+CLK (rising edge) */
90 outportb(Crtx+1, crt42|0x03); /* +DATA|+CLK */
91 outportb(Crtx+1, crt42|0x02); /* +DATA|-CLK (falling edge) */
92 outportb(Crtx+1, crt42|0x00); /* -DATA|-CLK */
93 outportb(Crtx+1, crt42|0x01); /* -DATA|+CLK (rising edge) */
98 outportb(Crtx+1, crt42|0x03); /* +DATA|+CLK (stop-bit) */
99 outportb(Crtx+1, crt42|0x02); /* +DATA|-CLK */
100 outportb(Crtx+1, crt42|0x03); /* +DATA|+CLK */
103 * We always use REG2 in the ICD2061A.
105 setcrt42(vga, ctlr, 0x02);
109 ch9294load(Vga* vga, Ctlr* ctlr)
111 trace("%s->clock->ch9294load\n", ctlr->name);
113 setcrt42(vga, ctlr, vga->i[0]);
117 tvp3025load(Vga* vga, Ctlr* ctlr)
121 trace("%s->clock->tvp3025load\n", ctlr->name);
124 * Crt5C bit 5 is RS4.
125 * Clear it to select TVP3025 registers for
126 * the calls to tvp302xo().
128 crt5c = vgaxi(Crtx, 0x5C);
129 vgaxo(Crtx, 0x5C, crt5c & ~0x20);
131 tvp3020xo(0x2C, 0x00);
132 tvp3020xo(0x2D, vga->d[0]);
133 tvp3020xo(0x2D, vga->n[0]);
134 tvp3020xo(0x2D, 0x08|vga->p[0]);
136 tvp3020xo(0x2F, 0x01);
137 tvp3020xo(0x2F, 0x01);
138 tvp3020xo(0x2F, vga->p[0]);
140 if(vga->ctlr && (vga->ctlr->flag & Uenhanced))
144 vgaxo(Crtx, 0x5C, crt5c);
145 vgao(MiscW, vga->misc);
151 tvp3026load(Vga* vga, Ctlr* ctlr)
153 trace("%s->clock->tvp3026load\n", ctlr->name);
155 if((vga->misc & 0x0C) != 0x0C && vga->mode->z == 1){
156 tvp3026xo(0x1A, 0x07);
157 tvp3026xo(0x18, 0x80);
158 tvp3026xo(0x19, 0x98);
159 tvp3026xo(0x2C, 0x2A);
160 tvp3026xo(0x2F, 0x00);
161 tvp3026xo(0x2D, 0x00);
162 tvp3026xo(0x39, 0x18);
163 setcrt42(vga, ctlr, 0);
165 else if(vga->mode->z == 8){
166 tvp3026xo(0x1A, 0x05);
167 tvp3026xo(0x18, 0x80);
168 tvp3026xo(0x19, 0x4C);
169 tvp3026xo(0x2C, 0x2A);
170 tvp3026xo(0x2F, 0x00);
171 tvp3026xo(0x2D, 0x00);
173 tvp3026xo(0x2C, 0x00);
174 tvp3026xo(0x2D, 0xC0|vga->n[0]);
175 tvp3026xo(0x2D, vga->m[0] & 0x3F);
176 tvp3026xo(0x2D, 0xB0|vga->p[0]);
177 while(!(tvp3026xi(0x2D) & 0x40))
180 tvp3026xo(0x39, 0x38|vga->q[1]);
181 tvp3026xo(0x2C, 0x00);
182 tvp3026xo(0x2F, 0xC0|vga->n[1]);
183 tvp3026xo(0x2F, vga->m[1]);
184 tvp3026xo(0x2F, 0xF0|vga->p[1]);
185 while(!(tvp3026xi(0x2F) & 0x40))
188 setcrt42(vga, ctlr, 3);
196 void (*load)(Vga*, Ctlr*);
198 { "icd2061a", icd2061aload, },
199 { "ch9294", ch9294load, },
200 { "tvp3025clock", tvp3025load, },
201 { "tvp3026clock", tvp3026load, },
206 init(Vga* vga, Ctlr* ctlr)
208 char name[Namelen+1], *p;
215 * Check we know about it.
217 strncpy(name, vga->clock->name, Namelen);
219 if(p = strchr(name, '-'))
221 for(i = 0; clocks[i].name; i++){
222 if(strcmp(clocks[i].name, name) == 0)
225 if(clocks[i].name == 0)
226 error("%s: unknown clock \"%s\"\n", ctlr->name, vga->clock->name);
228 if(vga->clock->init && (vga->clock->flag & Finit) == 0)
229 (*vga->clock->init)(vga, vga->clock);
232 * If we don't already have a desired pclk,
233 * take it from the mode.
236 vga->f[0] = vga->mode->frequency;
237 if(vga->f[0] != VgaFreq0 && vga->f[0] != VgaFreq1)
244 load(Vga* vga, Ctlr* ctlr)
246 char name[Namelen+1], *p;
249 if(vga->clock == 0 || (vga->clock->flag & Fload))
252 strncpy(name, vga->clock->name, Namelen);
254 if(p = strchr(name, '-'))
257 for(i = 0; clocks[i].name; i++){
258 if(strcmp(clocks[i].name, name))
260 clocks[i].load(vga, ctlr);
261 if(strcmp(clocks[i].name, "icd2061a") == 0){
262 clocks[i].load(vga, ctlr);
263 clocks[i].load(vga, ctlr);
272 "s3clock", /* name */