103479763SNathan Whitehorn /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
371e3c308SPedro F. Giffuni *
449588d0fSNathan Whitehorn * Copyright (c) 2011-2014 Nathan Whitehorn
503479763SNathan Whitehorn * All rights reserved.
603479763SNathan Whitehorn *
703479763SNathan Whitehorn * Redistribution and use in source and binary forms, with or without
803479763SNathan Whitehorn * modification, are permitted provided that the following conditions
903479763SNathan Whitehorn * are met:
1003479763SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright
1103479763SNathan Whitehorn * notice, this list of conditions and the following disclaimer.
1203479763SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright
1303479763SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the
1403479763SNathan Whitehorn * documentation and/or other materials provided with the distribution.
1503479763SNathan Whitehorn *
1603479763SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1703479763SNathan Whitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1803479763SNathan Whitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1903479763SNathan Whitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2003479763SNathan Whitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2103479763SNathan Whitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2203479763SNathan Whitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2303479763SNathan Whitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2403479763SNathan Whitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2503479763SNathan Whitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2603479763SNathan Whitehorn * SUCH DAMAGE.
2703479763SNathan Whitehorn */
2803479763SNathan Whitehorn
2903479763SNathan Whitehorn #include <sys/param.h>
3003479763SNathan Whitehorn #include <sys/systm.h>
3103479763SNathan Whitehorn #include <sys/kernel.h>
3203479763SNathan Whitehorn #include <sys/sysctl.h>
3303479763SNathan Whitehorn #include <sys/limits.h>
3403479763SNathan Whitehorn #include <sys/conf.h>
3503479763SNathan Whitehorn #include <sys/cons.h>
3603479763SNathan Whitehorn #include <sys/fbio.h>
3703479763SNathan Whitehorn
3803479763SNathan Whitehorn #include <vm/vm.h>
3903479763SNathan Whitehorn #include <vm/pmap.h>
4003479763SNathan Whitehorn
4103479763SNathan Whitehorn #include <machine/platform.h>
4203479763SNathan Whitehorn
43fd520b6eSNathan Whitehorn #include <dev/ofw/openfirm.h>
4449588d0fSNathan Whitehorn #include <dev/vt/vt.h>
4549588d0fSNathan Whitehorn #include <dev/vt/hw/fb/vt_fb.h>
4649588d0fSNathan Whitehorn #include <dev/vt/colors/vt_termcolors.h>
4703479763SNathan Whitehorn
4803479763SNathan Whitehorn #include "ps3-hvcall.h"
4903479763SNathan Whitehorn
5003479763SNathan Whitehorn #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET 0x0100
5103479763SNathan Whitehorn #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC 0x0101
5203479763SNathan Whitehorn #define L1GPU_DISPLAY_SYNC_HSYNC 1
5303479763SNathan Whitehorn #define L1GPU_DISPLAY_SYNC_VSYNC 2
5403479763SNathan Whitehorn #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP 0x0102
5503479763SNathan Whitehorn
5649588d0fSNathan Whitehorn static vd_init_t ps3fb_init;
5749588d0fSNathan Whitehorn static vd_probe_t ps3fb_probe;
5803479763SNathan Whitehorn void ps3fb_remap(void);
5903479763SNathan Whitehorn
6003479763SNathan Whitehorn struct ps3fb_softc {
6149588d0fSNathan Whitehorn struct fb_info fb_info;
62263b7901SNathan Whitehorn
63263b7901SNathan Whitehorn uint64_t sc_fbhandle;
64263b7901SNathan Whitehorn uint64_t sc_fbcontext;
65263b7901SNathan Whitehorn uint64_t sc_dma_control;
66263b7901SNathan Whitehorn uint64_t sc_driver_info;
67263b7901SNathan Whitehorn uint64_t sc_reports;
68263b7901SNathan Whitehorn uint64_t sc_reports_size;
6903479763SNathan Whitehorn };
7003479763SNathan Whitehorn
7149588d0fSNathan Whitehorn static struct vt_driver vt_ps3fb_driver = {
7249588d0fSNathan Whitehorn .vd_name = "ps3fb",
7349588d0fSNathan Whitehorn .vd_probe = ps3fb_probe,
7449588d0fSNathan Whitehorn .vd_init = ps3fb_init,
7549588d0fSNathan Whitehorn .vd_blank = vt_fb_blank,
76c285e4a5SJean-Sébastien Pédron .vd_bitblt_text = vt_fb_bitblt_text,
77631bb572SJean-Sébastien Pédron .vd_bitblt_bmp = vt_fb_bitblt_bitmap,
781365d077SJean-Sébastien Pédron .vd_drawrect = vt_fb_drawrect,
791365d077SJean-Sébastien Pédron .vd_setpixel = vt_fb_setpixel,
803ddad7daSNathan Whitehorn .vd_fb_ioctl = vt_fb_ioctl,
813ddad7daSNathan Whitehorn .vd_fb_mmap = vt_fb_mmap,
8249588d0fSNathan Whitehorn /* Better than VGA, but still generic driver. */
8349588d0fSNathan Whitehorn .vd_priority = VD_PRIORITY_GENERIC + 1,
8403479763SNathan Whitehorn };
8503479763SNathan Whitehorn
8649588d0fSNathan Whitehorn VT_DRIVER_DECLARE(vt_ps3fb, vt_ps3fb_driver);
8703479763SNathan Whitehorn static struct ps3fb_softc ps3fb_softc;
8803479763SNathan Whitehorn
8903479763SNathan Whitehorn static int
ps3fb_probe(struct vt_device * vd)9049588d0fSNathan Whitehorn ps3fb_probe(struct vt_device *vd)
9103479763SNathan Whitehorn {
9203479763SNathan Whitehorn int disable;
9303479763SNathan Whitehorn char compatible[64];
9403479763SNathan Whitehorn phandle_t root;
9503479763SNathan Whitehorn
9603479763SNathan Whitehorn disable = 0;
9703479763SNathan Whitehorn TUNABLE_INT_FETCH("hw.syscons.disable", &disable);
9803479763SNathan Whitehorn if (disable != 0)
9903479763SNathan Whitehorn return (0);
10003479763SNathan Whitehorn
101fd520b6eSNathan Whitehorn TUNABLE_STR_FETCH("hw.platform", compatible, sizeof(compatible));
102fd520b6eSNathan Whitehorn if (strcmp(compatible, "ps3") == 0)
103fd520b6eSNathan Whitehorn return (CN_INTERNAL);
104fd520b6eSNathan Whitehorn
10503479763SNathan Whitehorn root = OF_finddevice("/");
10603479763SNathan Whitehorn if (OF_getprop(root, "compatible", compatible, sizeof(compatible)) <= 0)
107fd520b6eSNathan Whitehorn return (CN_DEAD);
10803479763SNathan Whitehorn
10903479763SNathan Whitehorn if (strncmp(compatible, "sony,ps3", sizeof(compatible)) != 0)
11049588d0fSNathan Whitehorn return (CN_DEAD);
11103479763SNathan Whitehorn
11249588d0fSNathan Whitehorn return (CN_INTERNAL);
11303479763SNathan Whitehorn }
11403479763SNathan Whitehorn
11503479763SNathan Whitehorn void
ps3fb_remap(void)11603479763SNathan Whitehorn ps3fb_remap(void)
11703479763SNathan Whitehorn {
118263b7901SNathan Whitehorn struct ps3fb_softc *sc;
11903479763SNathan Whitehorn vm_offset_t va, fb_paddr;
120263b7901SNathan Whitehorn
121263b7901SNathan Whitehorn sc = &ps3fb_softc;
12203479763SNathan Whitehorn
12303479763SNathan Whitehorn lv1_gpu_close();
12403479763SNathan Whitehorn lv1_gpu_open(0);
12503479763SNathan Whitehorn
12603479763SNathan Whitehorn lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET,
12703479763SNathan Whitehorn 0,0,0,0);
12803479763SNathan Whitehorn lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET,
12903479763SNathan Whitehorn 0,0,1,0);
13003479763SNathan Whitehorn lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
13103479763SNathan Whitehorn 0,L1GPU_DISPLAY_SYNC_VSYNC,0,0);
13203479763SNathan Whitehorn lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
13303479763SNathan Whitehorn 1,L1GPU_DISPLAY_SYNC_VSYNC,0,0);
1340a9ce08bSNathan Whitehorn lv1_gpu_memory_allocate(roundup2(sc->fb_info.fb_size, 1024*1024),
1350a9ce08bSNathan Whitehorn 0, 0, 0, 0, &sc->sc_fbhandle, &fb_paddr);
13649588d0fSNathan Whitehorn lv1_gpu_context_allocate(sc->sc_fbhandle, 0, &sc->sc_fbcontext,
13749588d0fSNathan Whitehorn &sc->sc_dma_control, &sc->sc_driver_info, &sc->sc_reports,
13849588d0fSNathan Whitehorn &sc->sc_reports_size);
13903479763SNathan Whitehorn
140263b7901SNathan Whitehorn lv1_gpu_context_attribute(sc->sc_fbcontext,
14103479763SNathan Whitehorn L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0);
142263b7901SNathan Whitehorn lv1_gpu_context_attribute(sc->sc_fbcontext,
14303479763SNathan Whitehorn L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0);
14403479763SNathan Whitehorn
14549588d0fSNathan Whitehorn sc->fb_info.fb_pbase = fb_paddr;
1460a9ce08bSNathan Whitehorn for (va = 0; va < sc->fb_info.fb_size; va += PAGE_SIZE)
14703479763SNathan Whitehorn pmap_kenter_attr(0x10000000 + va, fb_paddr + va,
14803479763SNathan Whitehorn VM_MEMATTR_WRITE_COMBINING);
149f1d2752fSNathan Whitehorn sc->fb_info.fb_flags &= ~FB_FLAG_NOWRITE;
15003479763SNathan Whitehorn }
15103479763SNathan Whitehorn
15203479763SNathan Whitehorn static int
ps3fb_init(struct vt_device * vd)15349588d0fSNathan Whitehorn ps3fb_init(struct vt_device *vd)
15403479763SNathan Whitehorn {
15503479763SNathan Whitehorn struct ps3fb_softc *sc;
1565261ac0eSNathan Whitehorn char linux_video_mode[24];
1575261ac0eSNathan Whitehorn int linux_video_mode_num = 0;
15803479763SNathan Whitehorn
15949588d0fSNathan Whitehorn /* Init softc */
16049588d0fSNathan Whitehorn vd->vd_softc = sc = &ps3fb_softc;
16103479763SNathan Whitehorn
16249588d0fSNathan Whitehorn sc->fb_info.fb_depth = 32;
1635261ac0eSNathan Whitehorn sc->fb_info.fb_height = 1080;
1645261ac0eSNathan Whitehorn sc->fb_info.fb_width = 1920;
1655261ac0eSNathan Whitehorn
1665261ac0eSNathan Whitehorn /* See if the bootloader has passed a graphics mode to use */
1675261ac0eSNathan Whitehorn bzero(linux_video_mode, sizeof(linux_video_mode));
1685261ac0eSNathan Whitehorn TUNABLE_STR_FETCH("video", linux_video_mode, sizeof(linux_video_mode));
1695261ac0eSNathan Whitehorn sscanf(linux_video_mode, "ps3fb:mode:%d", &linux_video_mode_num);
1705261ac0eSNathan Whitehorn
1715261ac0eSNathan Whitehorn switch (linux_video_mode_num) {
1725261ac0eSNathan Whitehorn case 1:
1735261ac0eSNathan Whitehorn case 2:
17449588d0fSNathan Whitehorn sc->fb_info.fb_height = 480;
17549588d0fSNathan Whitehorn sc->fb_info.fb_width = 720;
1765261ac0eSNathan Whitehorn break;
1775261ac0eSNathan Whitehorn case 3:
1785261ac0eSNathan Whitehorn case 8:
1795261ac0eSNathan Whitehorn sc->fb_info.fb_height = 720;
1805261ac0eSNathan Whitehorn sc->fb_info.fb_width = 1280;
1815261ac0eSNathan Whitehorn break;
1825261ac0eSNathan Whitehorn case 4:
1835261ac0eSNathan Whitehorn case 5:
1845261ac0eSNathan Whitehorn case 9:
1855261ac0eSNathan Whitehorn case 10:
1865261ac0eSNathan Whitehorn sc->fb_info.fb_height = 1080;
1875261ac0eSNathan Whitehorn sc->fb_info.fb_width = 1920;
1885261ac0eSNathan Whitehorn break;
1895261ac0eSNathan Whitehorn case 6:
1905261ac0eSNathan Whitehorn case 7:
1915261ac0eSNathan Whitehorn sc->fb_info.fb_height = 576;
1925261ac0eSNathan Whitehorn sc->fb_info.fb_width = 720;
1935261ac0eSNathan Whitehorn break;
1945261ac0eSNathan Whitehorn case 11:
1955261ac0eSNathan Whitehorn sc->fb_info.fb_height = 768;
1965261ac0eSNathan Whitehorn sc->fb_info.fb_width = 1024;
1975261ac0eSNathan Whitehorn break;
1985261ac0eSNathan Whitehorn case 12:
1995261ac0eSNathan Whitehorn sc->fb_info.fb_height = 1024;
2005261ac0eSNathan Whitehorn sc->fb_info.fb_width = 1280;
2015261ac0eSNathan Whitehorn break;
2025261ac0eSNathan Whitehorn case 13:
2035261ac0eSNathan Whitehorn sc->fb_info.fb_height = 1200;
2045261ac0eSNathan Whitehorn sc->fb_info.fb_width = 1920;
2055261ac0eSNathan Whitehorn break;
2065261ac0eSNathan Whitehorn }
2075261ac0eSNathan Whitehorn
2085261ac0eSNathan Whitehorn /* Allow explicitly-specified values for us to override everything */
2090a9ce08bSNathan Whitehorn TUNABLE_INT_FETCH("hw.ps3fb.height", &sc->fb_info.fb_height);
2100a9ce08bSNathan Whitehorn TUNABLE_INT_FETCH("hw.ps3fb.width", &sc->fb_info.fb_width);
2115261ac0eSNathan Whitehorn
21249588d0fSNathan Whitehorn sc->fb_info.fb_stride = sc->fb_info.fb_width*4;
21349588d0fSNathan Whitehorn sc->fb_info.fb_size = sc->fb_info.fb_height * sc->fb_info.fb_stride;
21449588d0fSNathan Whitehorn sc->fb_info.fb_bpp = sc->fb_info.fb_stride / sc->fb_info.fb_width * 8;
21503479763SNathan Whitehorn
21649588d0fSNathan Whitehorn /*
217f1d2752fSNathan Whitehorn * Arbitrarily choose address for the framebuffer
21849588d0fSNathan Whitehorn */
21903479763SNathan Whitehorn
22049588d0fSNathan Whitehorn sc->fb_info.fb_vbase = 0x10000000;
221f1d2752fSNathan Whitehorn sc->fb_info.fb_flags |= FB_FLAG_NOWRITE; /* Not available yet */
222f1d2752fSNathan Whitehorn sc->fb_info.fb_cmsize = 16;
22349588d0fSNathan Whitehorn
22449588d0fSNathan Whitehorn /* 32-bit VGA palette */
225b9f3b63aSLeandro Lupori vt_config_cons_colors(&sc->fb_info, COLOR_FORMAT_RGB,
22667530f82SNathan Whitehorn 255, 16, 255, 8, 255, 0);
22749588d0fSNathan Whitehorn
22849588d0fSNathan Whitehorn /* Set correct graphics context */
229263b7901SNathan Whitehorn lv1_gpu_context_attribute(sc->sc_fbcontext,
230263b7901SNathan Whitehorn L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0);
231263b7901SNathan Whitehorn lv1_gpu_context_attribute(sc->sc_fbcontext,
232263b7901SNathan Whitehorn L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0);
233263b7901SNathan Whitehorn
23449588d0fSNathan Whitehorn vt_fb_init(vd);
23549588d0fSNathan Whitehorn
23649588d0fSNathan Whitehorn return (CN_INTERNAL);
23703479763SNathan Whitehorn }
238