ps3_syscons.c revision 270411
1191783Srmacklem/*-
2191783Srmacklem * Copyright (c) 2011-2014 Nathan Whitehorn
3191783Srmacklem * All rights reserved.
4191783Srmacklem *
5191783Srmacklem * Redistribution and use in source and binary forms, with or without
6191783Srmacklem * modification, are permitted provided that the following conditions
7191783Srmacklem * are met:
8191783Srmacklem * 1. Redistributions of source code must retain the above copyright
9191783Srmacklem *    notice, this list of conditions and the following disclaimer.
10191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright
11191783Srmacklem *    notice, this list of conditions and the following disclaimer in the
12191783Srmacklem *    documentation and/or other materials provided with the distribution.
13191783Srmacklem *
14191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15191783Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17191783Srmacklem * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24191783Srmacklem * SUCH DAMAGE.
25191783Srmacklem */
26191783Srmacklem
27191783Srmacklem#include <sys/cdefs.h>
28191783Srmacklem__FBSDID("$FreeBSD: head/sys/powerpc/ps3/ps3_syscons.c 270411 2014-08-23 15:00:47Z dumbbell $");
29191783Srmacklem
30191783Srmacklem#include <sys/param.h>
31191783Srmacklem#include <sys/systm.h>
32191783Srmacklem#include <sys/kernel.h>
33191783Srmacklem#include <sys/sysctl.h>
34191783Srmacklem#include <sys/limits.h>
35191783Srmacklem#include <sys/conf.h>
36191783Srmacklem#include <sys/cons.h>
37191783Srmacklem#include <sys/fbio.h>
38191783Srmacklem
39191783Srmacklem#include <vm/vm.h>
40191783Srmacklem#include <vm/pmap.h>
41191783Srmacklem
42221523Smav#include <machine/platform.h>
43191783Srmacklem#include <machine/pmap.h>
44191783Srmacklem
45191783Srmacklem#include <dev/vt/vt.h>
46191783Srmacklem#include <dev/vt/hw/fb/vt_fb.h>
47191783Srmacklem#include <dev/vt/colors/vt_termcolors.h>
48191783Srmacklem
49191783Srmacklem#include "ps3-hvcall.h"
50191783Srmacklem
51191783Srmacklem#define PS3FB_SIZE (4*1024*1024)
52191783Srmacklem
53191783Srmacklem#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET	0x0100
54191783Srmacklem#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC		0x0101
55191783Srmacklem#define  L1GPU_DISPLAY_SYNC_HSYNC			1
56191783Srmacklem#define  L1GPU_DISPLAY_SYNC_VSYNC			2
57191783Srmacklem#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP		0x0102
58191783Srmacklem
59220739Srmacklemstatic vd_init_t ps3fb_init;
60191783Srmacklemstatic vd_probe_t ps3fb_probe;
61191783Srmacklemvoid ps3fb_remap(void);
62191783Srmacklem
63191783Srmacklemstruct ps3fb_softc {
64191783Srmacklem	struct fb_info	fb_info;
65191783Srmacklem
66191783Srmacklem	uint64_t	sc_fbhandle;
67191783Srmacklem	uint64_t	sc_fbcontext;
68191783Srmacklem	uint64_t	sc_dma_control;
69191783Srmacklem	uint64_t	sc_driver_info;
70191783Srmacklem	uint64_t	sc_reports;
71191783Srmacklem	uint64_t	sc_reports_size;
72191783Srmacklem};
73191783Srmacklem
74220683Srmacklemstatic struct vt_driver vt_ps3fb_driver = {
75220683Srmacklem	.vd_name = "ps3fb",
76220683Srmacklem	.vd_probe = ps3fb_probe,
77191783Srmacklem	.vd_init = ps3fb_init,
78191783Srmacklem	.vd_blank = vt_fb_blank,
79191783Srmacklem	.vd_bitblt_text = vt_fb_bitblt_text,
80191783Srmacklem	.vd_fb_ioctl = vt_fb_ioctl,
81191783Srmacklem	.vd_fb_mmap = vt_fb_mmap,
82191783Srmacklem	/* Better than VGA, but still generic driver. */
83191783Srmacklem	.vd_priority = VD_PRIORITY_GENERIC + 1,
84191783Srmacklem};
85191783Srmacklem
86191783SrmacklemVT_DRIVER_DECLARE(vt_ps3fb, vt_ps3fb_driver);
87191783Srmacklemstatic struct ps3fb_softc ps3fb_softc;
88191783Srmacklem
89191783Srmacklemstatic int
90191783Srmacklemps3fb_probe(struct vt_device *vd)
91191783Srmacklem{
92191783Srmacklem	struct ps3fb_softc *sc;
93191783Srmacklem	int disable;
94191783Srmacklem	char compatible[64];
95191783Srmacklem#if 0
96191783Srmacklem	phandle_t root;
97191783Srmacklem#endif
98191783Srmacklem
99191783Srmacklem	disable = 0;
100191783Srmacklem	TUNABLE_INT_FETCH("hw.syscons.disable", &disable);
101191783Srmacklem	if (disable != 0)
102191783Srmacklem		return (0);
103191783Srmacklem
104191783Srmacklem	sc = &ps3fb_softc;
105191783Srmacklem
106191783Srmacklem#if 0
107191783Srmacklem	root = OF_finddevice("/");
108191783Srmacklem	if (OF_getprop(root, "compatible", compatible, sizeof(compatible)) <= 0)
109191783Srmacklem                return (0);
110191783Srmacklem
111191783Srmacklem	if (strncmp(compatible, "sony,ps3", sizeof(compatible)) != 0)
112191783Srmacklem		return (0);
113191783Srmacklem#else
114191783Srmacklem	TUNABLE_STR_FETCH("hw.platform", compatible, sizeof(compatible));
115191783Srmacklem	if (strcmp(compatible, "ps3") != 0)
116191783Srmacklem		return (CN_DEAD);
117191783Srmacklem#endif
118191783Srmacklem
119191783Srmacklem	return (CN_INTERNAL);
120191783Srmacklem}
121191783Srmacklem
122191783Srmacklemvoid
123191783Srmacklemps3fb_remap(void)
124191783Srmacklem{
125191783Srmacklem	struct ps3fb_softc *sc;
126191783Srmacklem	vm_offset_t va, fb_paddr;
127191783Srmacklem
128191783Srmacklem	sc = &ps3fb_softc;
129191783Srmacklem
130191783Srmacklem	lv1_gpu_close();
131191783Srmacklem	lv1_gpu_open(0);
132191783Srmacklem
133191783Srmacklem	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET,
134191783Srmacklem	    0,0,0,0);
135191783Srmacklem	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET,
136191783Srmacklem	    0,0,1,0);
137191783Srmacklem	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
138191783Srmacklem	    0,L1GPU_DISPLAY_SYNC_VSYNC,0,0);
139191783Srmacklem	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
140191783Srmacklem	    1,L1GPU_DISPLAY_SYNC_VSYNC,0,0);
141191783Srmacklem	lv1_gpu_memory_allocate(PS3FB_SIZE, 0, 0, 0, 0, &sc->sc_fbhandle,
142191783Srmacklem	    &fb_paddr);
143191783Srmacklem	lv1_gpu_context_allocate(sc->sc_fbhandle, 0, &sc->sc_fbcontext,
144191783Srmacklem	    &sc->sc_dma_control, &sc->sc_driver_info, &sc->sc_reports,
145191783Srmacklem	    &sc->sc_reports_size);
146191783Srmacklem
147191783Srmacklem	lv1_gpu_context_attribute(sc->sc_fbcontext,
148191783Srmacklem	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0);
149191783Srmacklem	lv1_gpu_context_attribute(sc->sc_fbcontext,
150191783Srmacklem	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0);
151191783Srmacklem
152191783Srmacklem	sc->fb_info.fb_pbase = fb_paddr;
153191783Srmacklem	for (va = 0; va < PS3FB_SIZE; va += PAGE_SIZE)
154191783Srmacklem		pmap_kenter_attr(0x10000000 + va, fb_paddr + va,
155191783Srmacklem		    VM_MEMATTR_WRITE_COMBINING);
156191783Srmacklem}
157191783Srmacklem
158191783Srmacklemstatic int
159191783Srmacklemps3fb_init(struct vt_device *vd)
160191783Srmacklem{
161191783Srmacklem	struct ps3fb_softc *sc;
162192000Srmacklem
163191783Srmacklem	/* Init softc */
164191783Srmacklem	vd->vd_softc = sc = &ps3fb_softc;
165191783Srmacklem
166191783Srmacklem	/* XXX: get from HV repository */
167191783Srmacklem	sc->fb_info.fb_depth = 32;
168191783Srmacklem	sc->fb_info.fb_height = 480;
169191783Srmacklem	sc->fb_info.fb_width = 720;
170191783Srmacklem	sc->fb_info.fb_stride = sc->fb_info.fb_width*4;
171191783Srmacklem	sc->fb_info.fb_size = sc->fb_info.fb_height * sc->fb_info.fb_stride;
172191783Srmacklem	sc->fb_info.fb_bpp = sc->fb_info.fb_stride / sc->fb_info.fb_width * 8;
173191783Srmacklem
174191783Srmacklem	/*
175191783Srmacklem	 * The loader puts the FB at 0x10000000, so use that for now.
176191783Srmacklem	 */
177191783Srmacklem
178191783Srmacklem	sc->fb_info.fb_vbase = 0x10000000;
179191783Srmacklem
180191783Srmacklem	/* 32-bit VGA palette */
181191783Srmacklem	vt_generate_cons_palette(sc->fb_info.fb_cmap, COLOR_FORMAT_RGB,
182191783Srmacklem	    255, 0, 255, 8, 255, 16);
183191783Srmacklem
184191783Srmacklem	/* Set correct graphics context */
185191783Srmacklem	lv1_gpu_context_attribute(sc->sc_fbcontext,
186191783Srmacklem	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0);
187191783Srmacklem	lv1_gpu_context_attribute(sc->sc_fbcontext,
188191783Srmacklem	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0);
189191783Srmacklem
190191783Srmacklem	vt_fb_init(vd);
191191783Srmacklem	sc->fb_info.fb_flags &= ~FB_FLAG_NOMMAP; /* Set wrongly by vt_fb_init */
192191783Srmacklem
193191783Srmacklem	return (CN_INTERNAL);
194191783Srmacklem}
195191783Srmacklem
196191783Srmacklem