Annotation of src/sys/external/bsd/drm2/drm/drmfb.c, Revision 1.9
1.9 ! riastrad 1: /* $NetBSD: drmfb.c,v 1.8 2020/06/27 13:41:44 jmcneill Exp $ */
1.1 riastrad 2:
3: /*-
4: * Copyright (c) 2014 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Taylor R. Campbell.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: */
31:
32: /*
33: * drmfb: wsdisplay support, via genfb, for any drm device. Use this
34: * if you're too lazy to write a hardware-accelerated framebuffer using
35: * wsdisplay directly.
36: *
37: * This doesn't actually do anything interesting -- just hooks up
38: * drmkms crap and genfb crap.
39: */
40:
41: #include <sys/cdefs.h>
1.9 ! riastrad 42: __KERNEL_RCSID(0, "$NetBSD: drmfb.c,v 1.8 2020/06/27 13:41:44 jmcneill Exp $");
1.1 riastrad 43:
44: #ifdef _KERNEL_OPT
45: #include "vga.h"
46: #endif
47:
48: #include <sys/types.h>
49: #include <sys/param.h>
50: #include <sys/bus.h>
51: #include <sys/device.h>
52: #include <sys/kauth.h>
53:
54: #if NVGA > 0
55: /*
56: * XXX All we really need is vga_is_console from vgavar.h, but the
57: * header files are missing their own dependencies, so we need to
58: * explicitly drag in the other crap.
59: */
60: #include <dev/ic/mc6845reg.h>
61: #include <dev/ic/pcdisplayvar.h>
62: #include <dev/ic/vgareg.h>
63: #include <dev/ic/vgavar.h>
64: #endif
65:
66: #include <dev/wsfb/genfbvar.h>
67:
68: #include <drm/drmP.h>
69: #include <drm/drm_fb_helper.h>
70: #include <drm/drmfb.h>
71:
72: static int drmfb_genfb_ioctl(void *, void *, unsigned long, void *, int,
73: struct lwp *);
74: static paddr_t drmfb_genfb_mmap(void *, void *, off_t, int);
75: static int drmfb_genfb_enable_polling(void *);
76: static int drmfb_genfb_disable_polling(void *);
77: static bool drmfb_genfb_setmode(struct genfb_softc *, int);
78:
79: static const struct genfb_mode_callback drmfb_genfb_mode_callback = {
80: .gmc_setmode = drmfb_genfb_setmode,
81: };
82:
83: int
84: drmfb_attach(struct drmfb_softc *sc, const struct drmfb_attach_args *da)
85: {
86: const struct drm_fb_helper_surface_size *const sizes = da->da_fb_sizes;
1.9 ! riastrad 87: struct drm_connector_list_iter conn_iter;
! 88: struct drm_connector *connector;
1.1 riastrad 89: const prop_dictionary_t dict = device_properties(da->da_dev);
90: #if NVGA > 0
91: struct drm_device *const dev = da->da_fb_helper->dev;
92: #endif
93: static const struct genfb_ops zero_genfb_ops;
94: struct genfb_ops genfb_ops = zero_genfb_ops;
95: enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons;
1.2 jmcneill 96: bool is_console;
1.9 ! riastrad 97: int error;
1.1 riastrad 98:
99: /* genfb requires this. */
100: KASSERTMSG((void *)&sc->sc_genfb == device_private(da->da_dev),
101: "drmfb_softc must be first member of device softc");
102:
103: sc->sc_da = *da;
104:
105: prop_dictionary_set_uint32(dict, "width", sizes->surface_width);
106: prop_dictionary_set_uint32(dict, "height", sizes->surface_height);
107: prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp);
1.3 maya 108: prop_dictionary_set_uint16(dict, "linebytes", da->da_fb_linebytes);
1.1 riastrad 109: prop_dictionary_set_uint32(dict, "address", 0); /* XXX >32-bit */
110: CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t));
111: prop_dictionary_set_uint64(dict, "virtual_address",
112: (uint64_t)(uintptr_t)da->da_fb_vaddr);
113:
114: prop_dictionary_set_uint64(dict, "mode_callback",
115: (uint64_t)(uintptr_t)&drmfb_genfb_mode_callback);
116:
1.2 jmcneill 117: if (!prop_dictionary_get_bool(dict, "is_console", &is_console)) {
118: /* XXX Whattakludge! */
1.1 riastrad 119: #if NVGA > 0
1.2 jmcneill 120: if ((da->da_params->dp_is_vga_console != NULL) &&
121: (*da->da_params->dp_is_vga_console)(dev)) {
122: what_was_cons = CONS_VGA;
123: prop_dictionary_set_bool(dict, "is_console", true);
124: vga_cndetach();
125: if (da->da_params->dp_disable_vga)
126: (*da->da_params->dp_disable_vga)(dev);
127: } else
1.1 riastrad 128: #endif
1.2 jmcneill 129: if (genfb_is_console() && genfb_is_enabled()) {
130: what_was_cons = CONS_GENFB;
131: prop_dictionary_set_bool(dict, "is_console", true);
132: } else {
133: what_was_cons = CONS_NONE;
134: prop_dictionary_set_bool(dict, "is_console", false);
135: }
1.1 riastrad 136: } else {
137: what_was_cons = CONS_NONE;
138: }
139:
1.5 jmcneill 140: /* Make the first EDID we find available to wsfb */
1.9 ! riastrad 141: drm_connector_list_iter_begin(da->da_fb_helper->dev, &conn_iter);
! 142: drm_client_for_each_connector_iter(connector, &conn_iter) {
1.5 jmcneill 143: struct drm_property_blob *edid = connector->edid_blob_ptr;
1.7 jmcneill 144: if (edid && edid->length) {
1.8 jmcneill 145: prop_dictionary_set_data(dict, "EDID", edid->data,
146: edid->length);
1.5 jmcneill 147: break;
148: }
149: }
1.9 ! riastrad 150: drm_connector_list_iter_end(&conn_iter);
1.5 jmcneill 151:
1.1 riastrad 152: sc->sc_genfb.sc_dev = sc->sc_da.da_dev;
153: genfb_init(&sc->sc_genfb);
154: genfb_ops.genfb_ioctl = drmfb_genfb_ioctl;
155: genfb_ops.genfb_mmap = drmfb_genfb_mmap;
156: genfb_ops.genfb_enable_polling = drmfb_genfb_enable_polling;
157: genfb_ops.genfb_disable_polling = drmfb_genfb_disable_polling;
158:
159: error = genfb_attach(&sc->sc_genfb, &genfb_ops);
160: if (error) {
161: aprint_error_dev(sc->sc_da.da_dev,
162: "failed to attach genfb: %d\n", error);
163: goto fail0;
164: }
165:
166: /* Success! */
167: return 0;
168:
169: fail0: KASSERT(error);
170: /* XXX Restore console... */
171: switch (what_was_cons) {
172: case CONS_VGA:
173: break;
174: case CONS_GENFB:
175: break;
176: case CONS_NONE:
177: break;
178: default:
179: break;
180: }
181: return error;
182: }
183:
184: int
185: drmfb_detach(struct drmfb_softc *sc, int flags)
186: {
187:
188: /* XXX genfb detach? */
189: return 0;
190: }
191:
192: static int
193: drmfb_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag,
194: struct lwp *l)
195: {
196: struct genfb_softc *const genfb = v;
197: struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
198: sc_genfb);
1.9 ! riastrad 199: struct drm_connector_list_iter conn_iter;
! 200: struct drm_connector *connector;
1.1 riastrad 201: int error;
202:
203: if (sc->sc_da.da_params->dp_ioctl) {
204: error = (*sc->sc_da.da_params->dp_ioctl)(sc, cmd, data, flag,
205: l);
206: if (error != EPASSTHROUGH)
207: return error;
208: }
209:
210: switch (cmd) {
211: /*
212: * Screen blanking ioctls. Not to be confused with backlight
213: * (can be disabled while stuff is still drawn on the screen),
214: * brightness, or contrast (which we don't support). Backlight
215: * and brightness are done through WSDISPLAYIO_{GET,SET}PARAM.
216: * This toggles between DPMS ON and DPMS OFF; backlight toggles
217: * between DPMS ON and DPMS SUSPEND.
218: */
219: case WSDISPLAYIO_GVIDEO: {
220: int *onp = (int *)data;
221:
222: /* XXX Can't really determine a single answer here. */
223: *onp = 1;
224: return 0;
225: }
226: case WSDISPLAYIO_SVIDEO: {
227: const int on = *(const int *)data;
228: const int dpms_mode = on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF;
229: struct drm_fb_helper *const fb_helper = sc->sc_da.da_fb_helper;
230: struct drm_device *const dev = fb_helper->dev;
231:
232: drm_modeset_lock_all(dev);
1.9 ! riastrad 233: drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
! 234: drm_client_for_each_connector_iter(connector, &conn_iter) {
1.1 riastrad 235: (*connector->funcs->dpms)(connector, dpms_mode);
236: drm_object_property_set_value(&connector->base,
237: dev->mode_config.dpms_property, dpms_mode);
238: }
1.9 ! riastrad 239: drm_connector_list_iter_end(&conn_iter);
1.1 riastrad 240: drm_modeset_unlock_all(dev);
241:
242: return 0;
243: }
244: default:
245: return EPASSTHROUGH;
246: }
247: }
248:
249: static paddr_t
250: drmfb_genfb_mmap(void *v, void *vs, off_t offset, int prot)
251: {
252: struct genfb_softc *const genfb = v;
253: struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
254: sc_genfb);
255:
256: KASSERT(0 <= offset);
257:
258: if (offset < genfb->sc_fbsize) {
259: if (sc->sc_da.da_params->dp_mmapfb == NULL)
260: return -1;
261: return (*sc->sc_da.da_params->dp_mmapfb)(sc, offset, prot);
262: } else {
263: if (kauth_authorize_machdep(kauth_cred_get(),
264: KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL)
265: != 0)
266: return -1;
267: if (sc->sc_da.da_params->dp_mmap == NULL)
268: return -1;
269: return (*sc->sc_da.da_params->dp_mmap)(sc, offset, prot);
270: }
271: }
272:
273: static int
274: drmfb_genfb_enable_polling(void *cookie)
275: {
276: struct genfb_softc *const genfb = cookie;
277: struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
278: sc_genfb);
279:
280: return drm_fb_helper_debug_enter_fb(sc->sc_da.da_fb_helper);
281: }
282:
283: static int
284: drmfb_genfb_disable_polling(void *cookie)
285: {
286: struct genfb_softc *const genfb = cookie;
287: struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
288: sc_genfb);
289:
290: return drm_fb_helper_debug_leave_fb(sc->sc_da.da_fb_helper);
291: }
292:
293: static bool
294: drmfb_genfb_setmode(struct genfb_softc *genfb, int mode)
295: {
296: struct drmfb_softc *sc = container_of(genfb, struct drmfb_softc,
297: sc_genfb);
1.4 riastrad 298: struct drm_fb_helper *fb_helper = sc->sc_da.da_fb_helper;
1.1 riastrad 299:
300: if (mode == WSDISPLAYIO_MODE_EMUL)
1.4 riastrad 301: drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
1.1 riastrad 302:
303: return true;
304: }
305:
306: bool
307: drmfb_shutdown(struct drmfb_softc *sc, int flags __unused)
308: {
309:
310: genfb_enable_polling(sc->sc_da.da_dev);
311: return true;
312: }
CVSweb <webmaster@jp.NetBSD.org>