Mon Feb 5 23:48:35 2024 UTC (117d)
wiifb: Misc fixes.

Add a 16-pixel border on the top and bottom of the FB, and fix an error
path to properly blink the slot LED when the current video mode is not
supported.


(jmcneill)
diff -r1.5 -r1.6 src/sys/arch/evbppc/wii/dev/wiifb.c

cvs diff -r1.5 -r1.6 src/sys/arch/evbppc/wii/dev/wiifb.c (expand / switch to unified diff)

--- src/sys/arch/evbppc/wii/dev/wiifb.c 2024/01/27 17:44:37 1.5
+++ src/sys/arch/evbppc/wii/dev/wiifb.c 2024/02/05 23:48:35 1.6
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: wiifb.c,v 1.5 2024/01/27 17:44:37 hgutch Exp $ */ 1/* $NetBSD: wiifb.c,v 1.6 2024/02/05 23:48:35 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2024 Jared McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2024 Jared McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -17,43 +17,50 @@ @@ -17,43 +17,50 @@
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: wiifb.c,v 1.5 2024/01/27 17:44:37 hgutch Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: wiifb.c,v 1.6 2024/02/05 23:48:35 jmcneill Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/bus.h> 33#include <sys/bus.h>
34#include <sys/device.h> 34#include <sys/device.h>
35#include <sys/systm.h> 35#include <sys/systm.h>
36 36
37#include <machine/wii.h> 37#include <machine/wii.h>
38 38
39#include <dev/videomode/videomode.h> 39#include <dev/videomode/videomode.h>
40#include <dev/wsfb/genfbvar.h> 40#include <dev/wsfb/genfbvar.h>
41 41
42#include "mainbus.h" 42#include "mainbus.h"
43#include "vireg.h" 43#include "vireg.h"
44#include "viio.h" 44#include "viio.h"
45 45
46#define WIIFB_ERROR_BLINK_INTERVAL 1000000 46#define WIIFB_ERROR_BLINK_INTERVAL 1000000
 47
 48#define WIIFB_TOP_BOTTOM_BORDER 16
 49#define WIIFB_EFFECTIVE_START(p, w) \
 50 ((uintptr_t)(p) + WIIFB_TOP_BOTTOM_BORDER * (w) * 2)
 51#define WIIFB_EFFECTIVE_HEIGHT(h) \
 52 ((h) - WIIFB_TOP_BOTTOM_BORDER * 2)
 53
47 54
48struct wiifb_mode { 55struct wiifb_mode {
49 const char * name; 56 const char * name;
50 u_int width; 57 u_int width;
51 u_int height; 58 u_int height;
52 u_int lines; 59 u_int lines;
53}; 60};
54 61
55static uint32_t wiifb_devcmap[16] = { 62static uint32_t wiifb_devcmap[16] = {
56 0x00800080, /* Black */ 63 0x00800080, /* Black */
57 0x1dff1d6b, /* Blue */ 64 0x1dff1d6b, /* Blue */
58 0x4b554b4a, /* Green */ 65 0x4b554b4a, /* Green */
59 0x80808080, /* Cyan */ 66 0x80808080, /* Cyan */
@@ -141,46 +148,59 @@ static int @@ -141,46 +148,59 @@ static int
141wiifb_match(device_t parent, cfdata_t cf, void *aux) 148wiifb_match(device_t parent, cfdata_t cf, void *aux)
142{ 149{
143 struct mainbus_attach_args *maa = aux; 150 struct mainbus_attach_args *maa = aux;
144 151
145 return strcmp(maa->maa_name, "genfb") == 0; 152 return strcmp(maa->maa_name, "genfb") == 0;
146} 153}
147 154
148static void 155static void
149wiifb_attach(device_t parent, device_t self, void *aux) 156wiifb_attach(device_t parent, device_t self, void *aux)
150{ 157{
151 struct wiifb_softc *sc = device_private(self); 158 struct wiifb_softc *sc = device_private(self);
152 prop_dictionary_t dict = device_properties(self); 159 prop_dictionary_t dict = device_properties(self);
153 struct mainbus_attach_args *maa = aux; 160 struct mainbus_attach_args *maa = aux;
 161 u_int offset;
 162 uint32_t *p;
154 int error; 163 int error;
155 164
156 sc->sc_gen.sc_dev = self; 165 sc->sc_gen.sc_dev = self;
157 sc->sc_bst = maa->maa_bst; 166 sc->sc_bst = maa->maa_bst;
158 error = bus_space_map(sc->sc_bst, maa->maa_addr, VI_SIZE, 0, 167 error = bus_space_map(sc->sc_bst, maa->maa_addr, VI_SIZE, 0,
159 &sc->sc_bsh); 168 &sc->sc_bsh);
160 if (error != 0) { 169 if (error != 0) {
161 panic("couldn't map registers"); 170 panic("couldn't map registers");
162 } 171 }
163 sc->sc_bits = mapiodev(XFB_START, XFB_SIZE, true); 172 sc->sc_bits = mapiodev(XFB_START, XFB_SIZE, true);
164 173
 174 /*
 175 * Paint the entire FB black. Use 4-byte accesses as the Wii will
 176 * ignore 1- and 2- byte writes to uncached memory.
 177 */
 178 for (p = sc->sc_bits, offset = 0;
 179 offset < XFB_SIZE;
 180 offset += 4, p++) {
 181 *p = 0x00800080;
 182 }
 183
165 wiifb_init(sc); 184 wiifb_init(sc);
166 wiifb_set_mode(sc, sc->sc_format, sc->sc_interlaced); 185 wiifb_set_mode(sc, sc->sc_format, sc->sc_interlaced);
167 186
168 prop_dictionary_set_uint32(dict, "width", sc->sc_curmode->width); 187 prop_dictionary_set_uint32(dict, "width", sc->sc_curmode->width);
169 prop_dictionary_set_uint32(dict, "height", sc->sc_curmode->height); 188 prop_dictionary_set_uint32(dict, "height",
 189 WIIFB_EFFECTIVE_HEIGHT(sc->sc_curmode->height));
170 prop_dictionary_set_uint8(dict, "depth", 16); 190 prop_dictionary_set_uint8(dict, "depth", 16);
171 prop_dictionary_set_uint32(dict, "address", XFB_START); 191 prop_dictionary_set_uint32(dict, "address", XFB_START);
172 prop_dictionary_set_uint32(dict, "virtual_address", 192 prop_dictionary_set_uint32(dict, "virtual_address",
173 (uintptr_t)sc->sc_bits); 193 WIIFB_EFFECTIVE_START(sc->sc_bits, sc->sc_curmode->width));
174 prop_dictionary_set_uint64(dict, "devcmap", (uintptr_t)wiifb_devcmap); 194 prop_dictionary_set_uint64(dict, "devcmap", (uintptr_t)wiifb_devcmap);
175 195
176 genfb_init(&sc->sc_gen); 196 genfb_init(&sc->sc_gen);
177 197
178 aprint_naive("\n"); 198 aprint_naive("\n");
179 aprint_normal(": %s\n", sc->sc_curmode->name); 199 aprint_normal(": %s\n", sc->sc_curmode->name);
180 200
181 genfb_cnattach(); 201 genfb_cnattach();
182 prop_dictionary_set_bool(dict, "is_console", true); 202 prop_dictionary_set_bool(dict, "is_console", true);
183 genfb_attach(&sc->sc_gen, &wiifb_ops); 203 genfb_attach(&sc->sc_gen, &wiifb_ops);
184} 204}
185 205
186static void 206static void
@@ -202,32 +222,26 @@ wiifb_init(struct wiifb_softc *sc) @@ -202,32 +222,26 @@ wiifb_init(struct wiifb_softc *sc)
202 222
203 /* Reset video interface. */ 223 /* Reset video interface. */
204 WR2(sc, VI_DCR, dcr | VI_DCR_RST); 224 WR2(sc, VI_DCR, dcr | VI_DCR_RST);
205 WR2(sc, VI_DCR, dcr & ~VI_DCR_RST); 225 WR2(sc, VI_DCR, dcr & ~VI_DCR_RST);
206} 226}
207 227
208static void 228static void
209wiifb_set_mode(struct wiifb_softc *sc, uint8_t format, bool interlaced) 229wiifb_set_mode(struct wiifb_softc *sc, uint8_t format, bool interlaced)
210{ 230{
211 u_int modeidx; 231 u_int modeidx;
212 u_int strides, reads; 232 u_int strides, reads;
213 233
214 modeidx = WIIFB_MODE_INDEX(format, interlaced); 234 modeidx = WIIFB_MODE_INDEX(format, interlaced);
215 if (modeidx >= WIIFB_NMODES || wiifb_modes[modeidx].name == NULL) { 
216 panic("Unsupported format (0x%x) / interlaced (%d) settings", 
217 sc->sc_format, sc->sc_interlaced); 
218 } 
219 sc->sc_curmode = &wiifb_modes[modeidx]; 
220 
221 if (modeidx == WIIFB_MODE_INDEX(VI_DCR_FMT_NTSC, 1)) { 235 if (modeidx == WIIFB_MODE_INDEX(VI_DCR_FMT_NTSC, 1)) {
222 /* NTSC 480i Magic numbers from YAGCD. */ 236 /* NTSC 480i Magic numbers from YAGCD. */
223 WR2(sc, VI_VTR, 0x0f06); 237 WR2(sc, VI_VTR, 0x0f06);
224 WR4(sc, VI_HTR0, 0x476901AD); 238 WR4(sc, VI_HTR0, 0x476901AD);
225 WR4(sc, VI_HTR1, 0x02EA5140); 239 WR4(sc, VI_HTR1, 0x02EA5140);
226 WR4(sc, VI_VTO, 0x00030018); 240 WR4(sc, VI_VTO, 0x00030018);
227 WR4(sc, VI_VTE, 0x00020019); 241 WR4(sc, VI_VTE, 0x00020019);
228 WR4(sc, VI_BBOI, 0x410C410C); 242 WR4(sc, VI_BBOI, 0x410C410C);
229 WR4(sc, VI_BBEI, 0x40ED40ED); 243 WR4(sc, VI_BBEI, 0x40ED40ED);
230 } else if (modeidx == WIIFB_MODE_INDEX(VI_DCR_FMT_NTSC, 0)) { 244 } else if (modeidx == WIIFB_MODE_INDEX(VI_DCR_FMT_NTSC, 0)) {
231 /* NTSC 480p */ 245 /* NTSC 480p */
232 WR2(sc, VI_VTR, 0x1e0c); 246 WR2(sc, VI_VTR, 0x1e0c);
233 WR4(sc, VI_HTR0, 0x476901ad); 247 WR4(sc, VI_HTR0, 0x476901ad);
@@ -243,26 +257,32 @@ wiifb_set_mode(struct wiifb_softc *sc, u @@ -243,26 +257,32 @@ wiifb_set_mode(struct wiifb_softc *sc, u
243 WR4(sc, VI_HTR1, 0x02f85640); 257 WR4(sc, VI_HTR1, 0x02f85640);
244 WR4(sc, VI_VTO, 0x00010023); 258 WR4(sc, VI_VTO, 0x00010023);
245 WR4(sc, VI_VTE, 0x00000024); 259 WR4(sc, VI_VTE, 0x00000024);
246 WR4(sc, VI_BBOI, 0x4d2b4d6d); 260 WR4(sc, VI_BBOI, 0x4d2b4d6d);
247 WR4(sc, VI_BBEI, 0x4d8a4d4c); 261 WR4(sc, VI_BBEI, 0x4d8a4d4c);
248 } else { 262 } else {
249 /* 263 /*
250 * Display mode is not supported. Blink the slot LED to 264 * Display mode is not supported. Blink the slot LED to
251 * indicate failure. 265 * indicate failure.
252 */ 266 */
253 wii_slot_led_blink(WIIFB_ERROR_BLINK_INTERVAL); 267 wii_slot_led_blink(WIIFB_ERROR_BLINK_INTERVAL);
254 } 268 }
255 269
 270 if (modeidx >= WIIFB_NMODES || wiifb_modes[modeidx].name == NULL) {
 271 panic("Unsupported format (0x%x) / interlaced (%d) settings",
 272 sc->sc_format, sc->sc_interlaced);
 273 }
 274 sc->sc_curmode = &wiifb_modes[modeidx];
 275
256 /* Picture configuration */ 276 /* Picture configuration */
257 strides = (sc->sc_curmode->width * 2) / (interlaced ? 16 : 32); 277 strides = (sc->sc_curmode->width * 2) / (interlaced ? 16 : 32);
258 reads = (sc->sc_curmode->width * 2) / 32; 278 reads = (sc->sc_curmode->width * 2) / 32;
259 WR2(sc, VI_PICCONF, 279 WR2(sc, VI_PICCONF,
260 __SHIFTIN(strides, VI_PICCONF_STRIDES) | 280 __SHIFTIN(strides, VI_PICCONF_STRIDES) |
261 __SHIFTIN(reads, VI_PICCONF_READS)); 281 __SHIFTIN(reads, VI_PICCONF_READS));
262 282
263 /* Horizontal scaler configuration */ 283 /* Horizontal scaler configuration */
264 if (interlaced) { 284 if (interlaced) {
265 WR2(sc, VI_HSR, __SHIFTIN(256, VI_HSR_STP)); 285 WR2(sc, VI_HSR, __SHIFTIN(256, VI_HSR_STP));
266 } else { 286 } else {
267 WR2(sc, VI_HSR, __SHIFTIN(244, VI_HSR_STP) | VI_HSR_HS_EN); 287 WR2(sc, VI_HSR, __SHIFTIN(244, VI_HSR_STP) | VI_HSR_HS_EN);
268 } 288 }
@@ -312,31 +332,32 @@ wiifb_ioctl(void *v, void *vs, u_long cm @@ -312,31 +332,32 @@ wiifb_ioctl(void *v, void *vs, u_long cm
312 *(u_int *)data = WSDISPLAY_TYPE_HOLLYWOOD; 332 *(u_int *)data = WSDISPLAY_TYPE_HOLLYWOOD;
313 return 0; 333 return 0;
314 case WSDISPLAYIO_GET_BUSID: 334 case WSDISPLAYIO_GET_BUSID:
315 busid = data; 335 busid = data;
316 busid->bus_type = WSDISPLAYIO_BUS_SOC; 336 busid->bus_type = WSDISPLAYIO_BUS_SOC;
317 return 0; 337 return 0;
318 case WSDISPLAYIO_GET_FBINFO: 338 case WSDISPLAYIO_GET_FBINFO:
319 fbi = data; 339 fbi = data;
320 /* 340 /*
321 * rasops info does not match the pixel encoding due to our 341 * rasops info does not match the pixel encoding due to our
322 * devcmap, so fill out fbinfo manually instead of relying 342 * devcmap, so fill out fbinfo manually instead of relying
323 * on wsdisplayio_get_fbinfo. 343 * on wsdisplayio_get_fbinfo.
324 */ 344 */
325 fbi->fbi_fbsize = XFB_SIZE; 
326 fbi->fbi_fboffset = 0; 345 fbi->fbi_fboffset = 0;
327 fbi->fbi_width = sc->sc_curmode->width; 346 fbi->fbi_width = sc->sc_curmode->width;
328 fbi->fbi_height = sc->sc_curmode->height; 347 fbi->fbi_height =
 348 WIIFB_EFFECTIVE_HEIGHT(sc->sc_curmode->height);
329 fbi->fbi_stride = fbi->fbi_width * 2; 349 fbi->fbi_stride = fbi->fbi_width * 2;
 350 fbi->fbi_fbsize = fbi->fbi_height * fbi->fbi_stride;
330 fbi->fbi_bitsperpixel = 16; 351 fbi->fbi_bitsperpixel = 16;
331 fbi->fbi_pixeltype = WSFB_YUY2; 352 fbi->fbi_pixeltype = WSFB_YUY2;
332 fbi->fbi_flags = WSFB_VRAM_IS_RAM; 353 fbi->fbi_flags = WSFB_VRAM_IS_RAM;
333 return 0; 354 return 0;
334 355
335 case WSDISPLAYIO_SVIDEO: 356 case WSDISPLAYIO_SVIDEO:
336 video = *(u_int *)data; 357 video = *(u_int *)data;
337 switch (video) { 358 switch (video) {
338 case WSDISPLAYIO_VIDEO_OFF: 359 case WSDISPLAYIO_VIDEO_OFF:
339 out32(HW_VIDIM, __SHIFTIN(7, VIDIM_Y) | 360 out32(HW_VIDIM, __SHIFTIN(7, VIDIM_Y) |
340 __SHIFTIN(7, VIDIM_C) | 361 __SHIFTIN(7, VIDIM_C) |
341 VIDIM_E); 362 VIDIM_E);
342 return 0; 363 return 0;
@@ -374,21 +395,27 @@ wiifb_ioctl(void *v, void *vs, u_long cm @@ -374,21 +395,27 @@ wiifb_ioctl(void *v, void *vs, u_long cm
374 default: 395 default:
375 return EINVAL; 396 return EINVAL;
376 } 397 }
377 return 0; 398 return 0;
378 } 399 }
379 400
380 return EPASSTHROUGH; 401 return EPASSTHROUGH;
381} 402}
382 403
383static paddr_t 404static paddr_t
384wiifb_mmap(void *v, void *vs, off_t off, int prot) 405wiifb_mmap(void *v, void *vs, off_t off, int prot)
385{ 406{
386 struct wiifb_softc *sc = v; 407 struct wiifb_softc *sc = v;
 408 bus_addr_t start;
 409 bus_size_t size;
 410
 411 start = WIIFB_EFFECTIVE_START(XFB_START, sc->sc_curmode->width);
 412 size = WIIFB_EFFECTIVE_HEIGHT(sc->sc_curmode->height) *
 413 sc->sc_curmode->width * 2;
387 414
388 if (off < 0 || off >= XFB_SIZE) { 415 if (off < 0 || off >= size) {
389 return -1; 416 return -1;
390 } 417 }
391 418
392 return bus_space_mmap(sc->sc_bst, XFB_START, off, prot, 419 return bus_space_mmap(sc->sc_bst, start, off, prot,
393 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE); 420 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE);
394} 421}