1217044Snwhitehorn/*-
2271111Semaste * Copyright (c) 2011-2014 Nathan Whitehorn
3217044Snwhitehorn * All rights reserved.
4217044Snwhitehorn *
5217044Snwhitehorn * Redistribution and use in source and binary forms, with or without
6217044Snwhitehorn * modification, are permitted provided that the following conditions
7217044Snwhitehorn * are met:
8217044Snwhitehorn * 1. Redistributions of source code must retain the above copyright
9217044Snwhitehorn *    notice, this list of conditions and the following disclaimer.
10217044Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
11217044Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
12217044Snwhitehorn *    documentation and/or other materials provided with the distribution.
13217044Snwhitehorn *
14217044Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15217044Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16217044Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17217044Snwhitehorn * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18217044Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19217044Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20217044Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21217044Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22217044Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23217044Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24217044Snwhitehorn * SUCH DAMAGE.
25217044Snwhitehorn */
26217044Snwhitehorn
27217044Snwhitehorn#include <sys/cdefs.h>
28217044Snwhitehorn__FBSDID("$FreeBSD$");
29217044Snwhitehorn
30217044Snwhitehorn#include <sys/param.h>
31217044Snwhitehorn#include <sys/systm.h>
32217044Snwhitehorn#include <sys/kernel.h>
33217044Snwhitehorn#include <sys/sysctl.h>
34217044Snwhitehorn#include <sys/limits.h>
35217044Snwhitehorn#include <sys/conf.h>
36217044Snwhitehorn#include <sys/cons.h>
37217044Snwhitehorn#include <sys/fbio.h>
38217044Snwhitehorn
39217044Snwhitehorn#include <vm/vm.h>
40217044Snwhitehorn#include <vm/pmap.h>
41217044Snwhitehorn
42217044Snwhitehorn#include <machine/platform.h>
43217044Snwhitehorn#include <machine/pmap.h>
44217044Snwhitehorn
45271111Semaste#include <dev/vt/vt.h>
46271111Semaste#include <dev/vt/hw/fb/vt_fb.h>
47271111Semaste#include <dev/vt/colors/vt_termcolors.h>
48217044Snwhitehorn
49217044Snwhitehorn#include "ps3-hvcall.h"
50217044Snwhitehorn
51217044Snwhitehorn#define PS3FB_SIZE (4*1024*1024)
52217044Snwhitehorn
53217044Snwhitehorn#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET	0x0100
54217044Snwhitehorn#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC		0x0101
55217044Snwhitehorn#define  L1GPU_DISPLAY_SYNC_HSYNC			1
56217044Snwhitehorn#define  L1GPU_DISPLAY_SYNC_VSYNC			2
57217044Snwhitehorn#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP		0x0102
58217044Snwhitehorn
59271111Semastestatic vd_init_t ps3fb_init;
60271111Semastestatic vd_probe_t ps3fb_probe;
61217044Snwhitehornvoid ps3fb_remap(void);
62217044Snwhitehorn
63217044Snwhitehornstruct ps3fb_softc {
64271111Semaste	struct fb_info	fb_info;
65217044Snwhitehorn
66228689Snwhitehorn	uint64_t	sc_fbhandle;
67228689Snwhitehorn	uint64_t	sc_fbcontext;
68228689Snwhitehorn	uint64_t	sc_dma_control;
69228689Snwhitehorn	uint64_t	sc_driver_info;
70228689Snwhitehorn	uint64_t	sc_reports;
71228689Snwhitehorn	uint64_t	sc_reports_size;
72217044Snwhitehorn};
73217044Snwhitehorn
74271111Semastestatic struct vt_driver vt_ps3fb_driver = {
75271111Semaste	.vd_name = "ps3fb",
76271111Semaste	.vd_probe = ps3fb_probe,
77271111Semaste	.vd_init = ps3fb_init,
78271111Semaste	.vd_blank = vt_fb_blank,
79271128Semaste	.vd_bitblt_text = vt_fb_bitblt_text,
80271128Semaste	.vd_bitblt_bmp = vt_fb_bitblt_bitmap,
81271769Sdumbbell	.vd_drawrect = vt_fb_drawrect,
82271769Sdumbbell	.vd_setpixel = vt_fb_setpixel,
83271111Semaste	.vd_fb_ioctl = vt_fb_ioctl,
84271111Semaste	.vd_fb_mmap = vt_fb_mmap,
85271111Semaste	/* Better than VGA, but still generic driver. */
86271111Semaste	.vd_priority = VD_PRIORITY_GENERIC + 1,
87217044Snwhitehorn};
88217044Snwhitehorn
89271111SemasteVT_DRIVER_DECLARE(vt_ps3fb, vt_ps3fb_driver);
90217044Snwhitehornstatic struct ps3fb_softc ps3fb_softc;
91217044Snwhitehorn
92217044Snwhitehornstatic int
93271111Semasteps3fb_probe(struct vt_device *vd)
94217044Snwhitehorn{
95217044Snwhitehorn	struct ps3fb_softc *sc;
96217044Snwhitehorn	int disable;
97217044Snwhitehorn	char compatible[64];
98217044Snwhitehorn#if 0
99217044Snwhitehorn	phandle_t root;
100217044Snwhitehorn#endif
101217044Snwhitehorn
102217044Snwhitehorn	disable = 0;
103217044Snwhitehorn	TUNABLE_INT_FETCH("hw.syscons.disable", &disable);
104217044Snwhitehorn	if (disable != 0)
105217044Snwhitehorn		return (0);
106217044Snwhitehorn
107217044Snwhitehorn	sc = &ps3fb_softc;
108217044Snwhitehorn
109217044Snwhitehorn#if 0
110217044Snwhitehorn	root = OF_finddevice("/");
111217044Snwhitehorn	if (OF_getprop(root, "compatible", compatible, sizeof(compatible)) <= 0)
112217044Snwhitehorn                return (0);
113217044Snwhitehorn
114217044Snwhitehorn	if (strncmp(compatible, "sony,ps3", sizeof(compatible)) != 0)
115217044Snwhitehorn		return (0);
116217044Snwhitehorn#else
117217044Snwhitehorn	TUNABLE_STR_FETCH("hw.platform", compatible, sizeof(compatible));
118217044Snwhitehorn	if (strcmp(compatible, "ps3") != 0)
119271111Semaste		return (CN_DEAD);
120217044Snwhitehorn#endif
121217044Snwhitehorn
122271111Semaste	return (CN_INTERNAL);
123217044Snwhitehorn}
124217044Snwhitehorn
125217044Snwhitehornvoid
126217044Snwhitehornps3fb_remap(void)
127217044Snwhitehorn{
128228689Snwhitehorn	struct ps3fb_softc *sc;
129217044Snwhitehorn	vm_offset_t va, fb_paddr;
130217044Snwhitehorn
131228689Snwhitehorn	sc = &ps3fb_softc;
132228689Snwhitehorn
133217044Snwhitehorn	lv1_gpu_close();
134217044Snwhitehorn	lv1_gpu_open(0);
135217044Snwhitehorn
136217044Snwhitehorn	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET,
137217044Snwhitehorn	    0,0,0,0);
138217044Snwhitehorn	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET,
139217044Snwhitehorn	    0,0,1,0);
140217044Snwhitehorn	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
141217044Snwhitehorn	    0,L1GPU_DISPLAY_SYNC_VSYNC,0,0);
142217044Snwhitehorn	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
143217044Snwhitehorn	    1,L1GPU_DISPLAY_SYNC_VSYNC,0,0);
144271111Semaste	lv1_gpu_memory_allocate(PS3FB_SIZE, 0, 0, 0, 0, &sc->sc_fbhandle,
145271111Semaste	    &fb_paddr);
146271111Semaste	lv1_gpu_context_allocate(sc->sc_fbhandle, 0, &sc->sc_fbcontext,
147271111Semaste	    &sc->sc_dma_control, &sc->sc_driver_info, &sc->sc_reports,
148271111Semaste	    &sc->sc_reports_size);
149217044Snwhitehorn
150228689Snwhitehorn	lv1_gpu_context_attribute(sc->sc_fbcontext,
151217044Snwhitehorn	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0);
152228689Snwhitehorn	lv1_gpu_context_attribute(sc->sc_fbcontext,
153217044Snwhitehorn	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0);
154217044Snwhitehorn
155271111Semaste	sc->fb_info.fb_pbase = fb_paddr;
156217044Snwhitehorn	for (va = 0; va < PS3FB_SIZE; va += PAGE_SIZE)
157217044Snwhitehorn		pmap_kenter_attr(0x10000000 + va, fb_paddr + va,
158217044Snwhitehorn		    VM_MEMATTR_WRITE_COMBINING);
159217044Snwhitehorn}
160217044Snwhitehorn
161217044Snwhitehornstatic int
162271111Semasteps3fb_init(struct vt_device *vd)
163217044Snwhitehorn{
164217044Snwhitehorn	struct ps3fb_softc *sc;
165217044Snwhitehorn
166271111Semaste	/* Init softc */
167271111Semaste	vd->vd_softc = sc = &ps3fb_softc;
168217044Snwhitehorn
169271111Semaste	/* XXX: get from HV repository */
170271111Semaste	sc->fb_info.fb_depth = 32;
171271111Semaste	sc->fb_info.fb_height = 480;
172271111Semaste	sc->fb_info.fb_width = 720;
173271111Semaste	sc->fb_info.fb_stride = sc->fb_info.fb_width*4;
174271111Semaste	sc->fb_info.fb_size = sc->fb_info.fb_height * sc->fb_info.fb_stride;
175271111Semaste	sc->fb_info.fb_bpp = sc->fb_info.fb_stride / sc->fb_info.fb_width * 8;
176217044Snwhitehorn
177217044Snwhitehorn	/*
178271111Semaste	 * The loader puts the FB at 0x10000000, so use that for now.
179217044Snwhitehorn	 */
180217044Snwhitehorn
181271111Semaste	sc->fb_info.fb_vbase = 0x10000000;
182217044Snwhitehorn
183271111Semaste	/* 32-bit VGA palette */
184271111Semaste	vt_generate_cons_palette(sc->fb_info.fb_cmap, COLOR_FORMAT_RGB,
185271111Semaste	    255, 0, 255, 8, 255, 16);
186217044Snwhitehorn
187271111Semaste	/* Set correct graphics context */
188228689Snwhitehorn	lv1_gpu_context_attribute(sc->sc_fbcontext,
189228689Snwhitehorn	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0);
190228689Snwhitehorn	lv1_gpu_context_attribute(sc->sc_fbcontext,
191228689Snwhitehorn	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0);
192228689Snwhitehorn
193271111Semaste	vt_fb_init(vd);
194271117Semaste	sc->fb_info.fb_flags &= ~FB_FLAG_NOMMAP; /* Set wrongly by vt_fb_init */
195217044Snwhitehorn
196271111Semaste	return (CN_INTERNAL);
197217044Snwhitehorn}
198217044Snwhitehorn
199