103479763SNathan Whitehorn /*- 249588d0fSNathan Whitehorn * Copyright (c) 2011-2014 Nathan Whitehorn 303479763SNathan Whitehorn * All rights reserved. 403479763SNathan Whitehorn * 503479763SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 603479763SNathan Whitehorn * modification, are permitted provided that the following conditions 703479763SNathan Whitehorn * are met: 803479763SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 903479763SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 1003479763SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 1103479763SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 1203479763SNathan Whitehorn * documentation and/or other materials provided with the distribution. 1303479763SNathan Whitehorn * 1403479763SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1503479763SNathan Whitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1603479763SNathan Whitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1703479763SNathan Whitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1803479763SNathan Whitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1903479763SNathan Whitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2003479763SNathan Whitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2103479763SNathan Whitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2203479763SNathan Whitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2303479763SNathan Whitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2403479763SNathan Whitehorn * SUCH DAMAGE. 2503479763SNathan Whitehorn */ 2603479763SNathan Whitehorn 2703479763SNathan Whitehorn #include <sys/cdefs.h> 2803479763SNathan Whitehorn __FBSDID("$FreeBSD$"); 2903479763SNathan Whitehorn 3003479763SNathan Whitehorn #include <sys/param.h> 3103479763SNathan Whitehorn #include <sys/systm.h> 3203479763SNathan Whitehorn #include <sys/kernel.h> 3303479763SNathan Whitehorn #include <sys/sysctl.h> 3403479763SNathan Whitehorn #include <sys/limits.h> 3503479763SNathan Whitehorn #include <sys/conf.h> 3603479763SNathan Whitehorn #include <sys/cons.h> 3703479763SNathan Whitehorn #include <sys/fbio.h> 3803479763SNathan Whitehorn 3903479763SNathan Whitehorn #include <vm/vm.h> 4003479763SNathan Whitehorn #include <vm/pmap.h> 4103479763SNathan Whitehorn 4203479763SNathan Whitehorn #include <machine/platform.h> 4303479763SNathan Whitehorn #include <machine/pmap.h> 4403479763SNathan Whitehorn 45fd520b6eSNathan Whitehorn #include <dev/ofw/openfirm.h> 4649588d0fSNathan Whitehorn #include <dev/vt/vt.h> 4749588d0fSNathan Whitehorn #include <dev/vt/hw/fb/vt_fb.h> 4849588d0fSNathan Whitehorn #include <dev/vt/colors/vt_termcolors.h> 4903479763SNathan Whitehorn 5003479763SNathan Whitehorn #include "ps3-hvcall.h" 5103479763SNathan Whitehorn 5203479763SNathan Whitehorn #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET 0x0100 5303479763SNathan Whitehorn #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC 0x0101 5403479763SNathan Whitehorn #define L1GPU_DISPLAY_SYNC_HSYNC 1 5503479763SNathan Whitehorn #define L1GPU_DISPLAY_SYNC_VSYNC 2 5603479763SNathan Whitehorn #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP 0x0102 5703479763SNathan Whitehorn 5849588d0fSNathan Whitehorn static vd_init_t ps3fb_init; 5949588d0fSNathan Whitehorn static vd_probe_t ps3fb_probe; 6003479763SNathan Whitehorn void ps3fb_remap(void); 6103479763SNathan Whitehorn 6203479763SNathan Whitehorn struct ps3fb_softc { 6349588d0fSNathan Whitehorn struct fb_info fb_info; 64263b7901SNathan Whitehorn 65263b7901SNathan Whitehorn uint64_t sc_fbhandle; 66263b7901SNathan Whitehorn uint64_t sc_fbcontext; 67263b7901SNathan Whitehorn uint64_t sc_dma_control; 68263b7901SNathan Whitehorn uint64_t sc_driver_info; 69263b7901SNathan Whitehorn uint64_t sc_reports; 70263b7901SNathan Whitehorn uint64_t sc_reports_size; 7103479763SNathan Whitehorn }; 7203479763SNathan Whitehorn 7349588d0fSNathan Whitehorn static struct vt_driver vt_ps3fb_driver = { 7449588d0fSNathan Whitehorn .vd_name = "ps3fb", 7549588d0fSNathan Whitehorn .vd_probe = ps3fb_probe, 7649588d0fSNathan Whitehorn .vd_init = ps3fb_init, 7749588d0fSNathan Whitehorn .vd_blank = vt_fb_blank, 78c285e4a5SJean-Sébastien Pédron .vd_bitblt_text = vt_fb_bitblt_text, 79631bb572SJean-Sébastien Pédron .vd_bitblt_bmp = vt_fb_bitblt_bitmap, 801365d077SJean-Sébastien Pédron .vd_drawrect = vt_fb_drawrect, 811365d077SJean-Sébastien Pédron .vd_setpixel = vt_fb_setpixel, 823ddad7daSNathan Whitehorn .vd_fb_ioctl = vt_fb_ioctl, 833ddad7daSNathan Whitehorn .vd_fb_mmap = vt_fb_mmap, 8449588d0fSNathan Whitehorn /* Better than VGA, but still generic driver. */ 8549588d0fSNathan Whitehorn .vd_priority = VD_PRIORITY_GENERIC + 1, 8603479763SNathan Whitehorn }; 8703479763SNathan Whitehorn 8849588d0fSNathan Whitehorn VT_DRIVER_DECLARE(vt_ps3fb, vt_ps3fb_driver); 8903479763SNathan Whitehorn static struct ps3fb_softc ps3fb_softc; 9003479763SNathan Whitehorn 9103479763SNathan Whitehorn static int 9249588d0fSNathan Whitehorn ps3fb_probe(struct vt_device *vd) 9303479763SNathan Whitehorn { 9403479763SNathan Whitehorn struct ps3fb_softc *sc; 9503479763SNathan Whitehorn int disable; 9603479763SNathan Whitehorn char compatible[64]; 9703479763SNathan Whitehorn phandle_t root; 9803479763SNathan Whitehorn 9903479763SNathan Whitehorn disable = 0; 10003479763SNathan Whitehorn TUNABLE_INT_FETCH("hw.syscons.disable", &disable); 10103479763SNathan Whitehorn if (disable != 0) 10203479763SNathan Whitehorn return (0); 10303479763SNathan Whitehorn 10403479763SNathan Whitehorn sc = &ps3fb_softc; 10503479763SNathan Whitehorn 106fd520b6eSNathan Whitehorn TUNABLE_STR_FETCH("hw.platform", compatible, sizeof(compatible)); 107fd520b6eSNathan Whitehorn if (strcmp(compatible, "ps3") == 0) 108fd520b6eSNathan Whitehorn return (CN_INTERNAL); 109fd520b6eSNathan Whitehorn 11003479763SNathan Whitehorn root = OF_finddevice("/"); 11103479763SNathan Whitehorn if (OF_getprop(root, "compatible", compatible, sizeof(compatible)) <= 0) 112fd520b6eSNathan Whitehorn return (CN_DEAD); 11303479763SNathan Whitehorn 11403479763SNathan Whitehorn if (strncmp(compatible, "sony,ps3", sizeof(compatible)) != 0) 11549588d0fSNathan Whitehorn return (CN_DEAD); 11603479763SNathan Whitehorn 11749588d0fSNathan Whitehorn return (CN_INTERNAL); 11803479763SNathan Whitehorn } 11903479763SNathan Whitehorn 12003479763SNathan Whitehorn void 12103479763SNathan Whitehorn ps3fb_remap(void) 12203479763SNathan Whitehorn { 123263b7901SNathan Whitehorn struct ps3fb_softc *sc; 12403479763SNathan Whitehorn vm_offset_t va, fb_paddr; 125263b7901SNathan Whitehorn 126263b7901SNathan Whitehorn sc = &ps3fb_softc; 12703479763SNathan Whitehorn 12803479763SNathan Whitehorn lv1_gpu_close(); 12903479763SNathan Whitehorn lv1_gpu_open(0); 13003479763SNathan Whitehorn 13103479763SNathan Whitehorn lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET, 13203479763SNathan Whitehorn 0,0,0,0); 13303479763SNathan Whitehorn lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET, 13403479763SNathan Whitehorn 0,0,1,0); 13503479763SNathan Whitehorn lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, 13603479763SNathan Whitehorn 0,L1GPU_DISPLAY_SYNC_VSYNC,0,0); 13703479763SNathan Whitehorn lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, 13803479763SNathan Whitehorn 1,L1GPU_DISPLAY_SYNC_VSYNC,0,0); 1390a9ce08bSNathan Whitehorn lv1_gpu_memory_allocate(roundup2(sc->fb_info.fb_size, 1024*1024), 1400a9ce08bSNathan Whitehorn 0, 0, 0, 0, &sc->sc_fbhandle, &fb_paddr); 14149588d0fSNathan Whitehorn lv1_gpu_context_allocate(sc->sc_fbhandle, 0, &sc->sc_fbcontext, 14249588d0fSNathan Whitehorn &sc->sc_dma_control, &sc->sc_driver_info, &sc->sc_reports, 14349588d0fSNathan Whitehorn &sc->sc_reports_size); 14403479763SNathan Whitehorn 145263b7901SNathan Whitehorn lv1_gpu_context_attribute(sc->sc_fbcontext, 14603479763SNathan Whitehorn L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0); 147263b7901SNathan Whitehorn lv1_gpu_context_attribute(sc->sc_fbcontext, 14803479763SNathan Whitehorn L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0); 14903479763SNathan Whitehorn 15049588d0fSNathan Whitehorn sc->fb_info.fb_pbase = fb_paddr; 1510a9ce08bSNathan Whitehorn for (va = 0; va < sc->fb_info.fb_size; va += PAGE_SIZE) 15203479763SNathan Whitehorn pmap_kenter_attr(0x10000000 + va, fb_paddr + va, 15303479763SNathan Whitehorn VM_MEMATTR_WRITE_COMBINING); 154f1d2752fSNathan Whitehorn sc->fb_info.fb_flags &= ~FB_FLAG_NOWRITE; 15503479763SNathan Whitehorn } 15603479763SNathan Whitehorn 15703479763SNathan Whitehorn static int 15849588d0fSNathan Whitehorn ps3fb_init(struct vt_device *vd) 15903479763SNathan Whitehorn { 16003479763SNathan Whitehorn struct ps3fb_softc *sc; 16103479763SNathan Whitehorn 16249588d0fSNathan Whitehorn /* Init softc */ 16349588d0fSNathan Whitehorn vd->vd_softc = sc = &ps3fb_softc; 16403479763SNathan Whitehorn 16549588d0fSNathan Whitehorn /* XXX: get from HV repository */ 16649588d0fSNathan Whitehorn sc->fb_info.fb_depth = 32; 16749588d0fSNathan Whitehorn sc->fb_info.fb_height = 480; 16849588d0fSNathan Whitehorn sc->fb_info.fb_width = 720; 1690a9ce08bSNathan Whitehorn TUNABLE_INT_FETCH("hw.ps3fb.height", &sc->fb_info.fb_height); 1700a9ce08bSNathan Whitehorn TUNABLE_INT_FETCH("hw.ps3fb.width", &sc->fb_info.fb_width); 17149588d0fSNathan Whitehorn sc->fb_info.fb_stride = sc->fb_info.fb_width*4; 17249588d0fSNathan Whitehorn sc->fb_info.fb_size = sc->fb_info.fb_height * sc->fb_info.fb_stride; 17349588d0fSNathan Whitehorn sc->fb_info.fb_bpp = sc->fb_info.fb_stride / sc->fb_info.fb_width * 8; 17403479763SNathan Whitehorn 17549588d0fSNathan Whitehorn /* 176f1d2752fSNathan Whitehorn * Arbitrarily choose address for the framebuffer 17749588d0fSNathan Whitehorn */ 17803479763SNathan Whitehorn 17949588d0fSNathan Whitehorn sc->fb_info.fb_vbase = 0x10000000; 180f1d2752fSNathan Whitehorn sc->fb_info.fb_flags |= FB_FLAG_NOWRITE; /* Not available yet */ 181f1d2752fSNathan Whitehorn sc->fb_info.fb_cmsize = 16; 18249588d0fSNathan Whitehorn 18349588d0fSNathan Whitehorn /* 32-bit VGA palette */ 184ca885fdfSJean-Sébastien Pédron vt_generate_cons_palette(sc->fb_info.fb_cmap, COLOR_FORMAT_RGB, 185ca885fdfSJean-Sébastien Pédron 255, 0, 255, 8, 255, 16); 18649588d0fSNathan Whitehorn 18749588d0fSNathan Whitehorn /* Set correct graphics context */ 188263b7901SNathan Whitehorn lv1_gpu_context_attribute(sc->sc_fbcontext, 189263b7901SNathan Whitehorn L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0); 190263b7901SNathan Whitehorn lv1_gpu_context_attribute(sc->sc_fbcontext, 191263b7901SNathan Whitehorn L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0); 192263b7901SNathan Whitehorn 19349588d0fSNathan Whitehorn vt_fb_init(vd); 1949ed297c8SNathan Whitehorn sc->fb_info.fb_flags &= ~FB_FLAG_NOMMAP; /* Set wrongly by vt_fb_init */ 19549588d0fSNathan Whitehorn 19649588d0fSNathan Whitehorn return (CN_INTERNAL); 19703479763SNathan Whitehorn } 19803479763SNathan Whitehorn 199