tx3912video.c revision 1.4 1 /* $NetBSD: tx3912video.c,v 1.4 1999/12/23 16:56:16 uch Exp $ */
2
3 /*
4 * Copyright (c) 1999, by UCHIYAMA Yasushi
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. The name of the developer may NOT be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28 #include "opt_tx39_debug.h"
29 #include "fb.h"
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/device.h>
34 #include <sys/extent.h>
35
36 #include <machine/bus.h>
37 #include <machine/bootinfo.h> /* bootinfo */
38
39 #include <hpcmips/tx/tx39var.h>
40 #include <hpcmips/tx/tx3912videovar.h>
41 #include <hpcmips/tx/tx3912videoreg.h>
42
43 #if NFB > 0
44 #include <dev/rcons/raster.h>
45 #include <dev/wscons/wsdisplayvar.h>
46 #include <arch/hpcmips/dev/fbvar.h>
47 #endif
48
49 void tx3912video_framebuffer_init __P((tx_chipset_tag_t, u_int32_t,
50 u_int32_t));
51 int tx3912video_framebuffer_alloc __P((tx_chipset_tag_t, u_int32_t,
52 int, int, int, u_int32_t*,
53 u_int32_t*));
54 void tx3912video_reset __P((tx_chipset_tag_t));
55 void tx3912video_resolution_init __P((tx_chipset_tag_t, int, int));
56 int tx3912video_fbdepth __P((tx_chipset_tag_t, int));
57
58 static u_int32_t framebuffer, framebuffersize;
59
60 int tx3912video_match __P((struct device*, struct cfdata*, void*));
61 void tx3912video_attach __P((struct device*, struct device*, void*));
62 int tx3912video_print __P((void*, const char*));
63
64 struct tx3912video_softc {
65 struct device sc_dev;
66 u_int32_t sc_fbaddr;
67 u_int32_t sc_fbsize;
68 };
69
70 struct fb_attach_args {
71 const char *fba_name;
72 };
73
74 struct cfattach tx3912video_ca = {
75 sizeof(struct tx3912video_softc), tx3912video_match,
76 tx3912video_attach
77 };
78
79 int
80 tx3912video_match(parent, cf, aux)
81 struct device *parent;
82 struct cfdata *cf;
83 void *aux;
84 {
85 return 1;
86 }
87
88 void
89 tx3912video_attach(parent, self, aux)
90 struct device *parent;
91 struct device *self;
92 void *aux;
93 {
94 struct txsim_attach_args *ta = aux;
95 struct tx3912video_softc *sc = (void*)self;
96 tx_chipset_tag_t tc = ta->ta_tc;
97 struct fb_attach_args fba;
98 txreg_t reg;
99
100 printf("\n");
101 sc->sc_fbaddr = framebuffer;
102 sc->sc_fbsize = framebuffersize;
103 printf("TMPR3912 video module [");
104 tx3912video_fbdepth(tc, 1);
105 printf("] frame buffer: 0x%08x-0x%08x", sc->sc_fbaddr,
106 sc->sc_fbaddr + sc->sc_fbsize);
107
108 if (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) {
109 printf("disabled.");
110 reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
111 reg &= ~(TX3912_VIDEOCTRL1_DISPON |
112 TX3912_VIDEOCTRL1_ENVID);
113 tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
114 }
115 printf("\n");
116
117 /* Attach frame buffer device */
118 #if NFB > 0
119 if (!(bootinfo->bi_cnuse & BI_CNUSE_SERIAL)) {
120 if (fb_cnattach(0, 0, 0, 0)) {
121 panic("tx3912video_attach: can't init fb console");
122 }
123 }
124 fba.fba_name = "fb";
125 config_found(self, &fba, tx3912video_print);
126 #endif
127 }
128
129 int
130 tx3912video_print(aux, pnp)
131 void *aux;
132 const char *pnp;
133 {
134 return pnp ? QUIET : UNCONF;
135 }
136
137 int
138 tx3912video_init(tc, fb_start, fb_width, fb_height, fb_addr, fb_size,
139 fb_line_bytes)
140 tx_chipset_tag_t tc;
141 u_int32_t fb_start; /* Physical address */
142 int fb_width, fb_height;
143 u_int32_t *fb_addr, *fb_size;
144 int *fb_line_bytes;
145 {
146 u_int32_t addr, size;
147 int fb_depth;
148
149 /* Inquire bit depth */
150 fb_depth = tx3912video_fbdepth(tc, 0);
151
152 /* Allocate framebuffer area */
153 if (tx3912video_framebuffer_alloc(tc, fb_start, fb_width, fb_height,
154 fb_depth, &addr, &size)) {
155 return 1;
156 }
157 #if notyet
158 tx3912video_resolution_init(tc, fb_width, fb_height);
159 #else
160 /* Use Windows CE setting. */
161 #endif
162 /* Set DMA transfer address to VID module */
163 tx3912video_framebuffer_init(tc, addr, size);
164
165 /* Syncronize framebuffer addr to frame signal */
166 tx3912video_reset(tc);
167
168 *fb_line_bytes = (fb_width * fb_depth) / 8;
169 *fb_addr = addr; /* Phsical address */
170 *fb_size = size;
171
172 return 0;
173 }
174
175 int
176 tx3912video_framebuffer_alloc(tc, start, h, v, depth, fb_addr, fb_size)
177 tx_chipset_tag_t tc;
178 u_int32_t start;
179 int h, v, depth;
180 u_int32_t *fb_addr, *fb_size;
181 {
182 struct extent_fixed ex_fixed[2];
183 struct extent *ex;
184 u_long addr, size;
185 int err;
186
187 /* Calcurate frame buffer size */
188 size = (h * v * depth) / 8;
189
190 /* Allocate V-RAM area */
191 if (!(ex = extent_create("Frame buffer address", start,
192 start + TX3912_FRAMEBUFFER_MAX,
193 0, (caddr_t)ex_fixed, sizeof ex_fixed,
194 EX_NOWAIT))) {
195 return 1;
196 }
197 if((err = extent_alloc_subregion(ex, start, start + size, size,
198 TX3912_FRAMEBUFFER_ALIGNMENT,
199 TX3912_FRAMEBUFFER_BOUNDARY,
200 EX_FAST|EX_NOWAIT, &addr))) {
201 return 1;
202 }
203 framebuffer = addr;
204 framebuffersize = size;
205 *fb_addr = addr;
206 *fb_size = size;
207
208 return 0;
209 }
210
211 void
212 tx3912video_framebuffer_init(tc, fb_addr, fb_size)
213 tx_chipset_tag_t tc;
214 u_int32_t fb_addr, fb_size;
215 {
216 u_int32_t reg, vaddr, bank, base;
217
218 /* XXX currently I don't set DFVAL, so force DF signal toggled on
219 * XXX each frame. */
220 reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
221 reg &= ~TX3912_VIDEOCTRL1_DFMODE;
222 tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
223
224 /* Set DMA transfer start and end address */
225
226 bank = TX3912_VIDEOCTRL3_VIDBANK(fb_addr);
227 base = TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr);
228 reg = TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank);
229 /* Upper address counter */
230 reg = TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg, base);
231 tx_conf_write(tc, TX3912_VIDEOCTRL3_REG, reg);
232
233 /* Lower address counter */
234 base = TX3912_VIDEOCTRL4_VIDBASELO(fb_addr + fb_size);
235 reg = TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base);
236
237 /* Set DF-signal rate */
238 reg = TX3912_VIDEOCTRL4_DFVAL_SET(reg, 0); /* XXX not yet*/
239
240 /* Set VIDDONE signal delay after FRAME signal */
241 /* XXX not yet*/
242 tx_conf_write(tc, TX3912_VIDEOCTRL4_REG, reg);
243
244 /* Clear frame buffer */
245 vaddr = MIPS_PHYS_TO_KSEG1(fb_addr);
246 bzero((void*)vaddr, fb_size);
247 }
248
249 void
250 tx3912video_resolution_init(tc, h, v)
251 tx_chipset_tag_t tc;
252 int h;
253 int v;
254 {
255 u_int32_t reg, val;
256 int split, bit8, horzval, lineval;
257
258 reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
259 split = reg & TX3912_VIDEOCTRL1_DISPSPLIT;
260 bit8 = (TX3912_VIDEOCTRL1_BITSEL(reg) ==
261 TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR);
262 val = TX3912_VIDEOCTRL1_BITSEL(reg);
263
264 if ((val == TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR) &&
265 !split) {
266 /* (LCD horizontal pixels / 8bit) * RGB - 1 */
267 horzval = (h / 8) * 3 - 1;
268 } else {
269 horzval = h / 4 - 1;
270 }
271 lineval = (split ? v / 2 : v) - 1;
272
273 /* Video rate */
274 /* XXX
275 * probably This value should be determined from DFINT and LCDINT
276 */
277 reg = TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval + 1);
278 /* Horizontal size of LCD */
279 reg = TX3912_VIDEOCTRL2_HORZVAL_SET(reg, horzval);
280 /* # of lines for the LCD */
281 reg = TX3912_VIDEOCTRL2_LINEVAL_SET(reg, lineval);
282
283 tx_conf_write(tc, TX3912_VIDEOCTRL2_REG, reg);
284 }
285
286 int
287 tx3912video_fbdepth(tc, verbose)
288 tx_chipset_tag_t tc;
289 int verbose;
290 {
291 u_int32_t reg, val;
292
293 reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
294 val = TX3912_VIDEOCTRL1_BITSEL(reg);
295 switch (val) {
296 case TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR:
297 if (verbose)
298 printf("8bit color");
299 return 8;
300 case TX3912_VIDEOCTRL1_BITSEL_4BITGREYSCALE:
301 if (verbose)
302 printf("4bit greyscale");
303 return 4;
304 case TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE:
305 if (verbose)
306 printf("2bit greyscale");
307 return 2;
308 case TX3912_VIDEOCTRL1_BITSEL_MONOCHROME:
309 if (verbose)
310 printf("monochrome");
311 return 1;
312 }
313 return 0;
314 }
315
316 void
317 tx3912video_reset(tc)
318 tx_chipset_tag_t tc;
319 {
320 u_int32_t reg;
321
322 reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
323
324 /* Disable video logic at end of this frame */
325 reg |= TX3912_VIDEOCTRL1_ENFREEZEFRAME;
326 tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
327
328 /* Wait for end of frame */
329 delay(300 * 1000);
330
331 /* Make sure to disable video logic */
332 reg &= ~TX3912_VIDEOCTRL1_ENVID;
333 tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
334
335 delay(1000);
336
337 /* Enable video logic again */
338 reg &= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME;
339 reg |= TX3912_VIDEOCTRL1_ENVID;
340 tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
341
342 delay(1000);
343 }
344
345
346