jcs's openbsd hax
openbsd
at jcs 153 lines 4.3 kB view raw
1/* $OpenBSD: simplepanel.c,v 1.6 2021/11/07 15:59:09 patrick Exp $ */ 2/* 3 * Copyright (c) 2020 Patrick Wildt <patrick@blueri.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <sys/param.h> 19#include <sys/systm.h> 20#include <sys/device.h> 21#include <sys/malloc.h> 22 23#include <machine/fdt.h> 24 25#include <dev/ofw/openfirm.h> 26#include <dev/ofw/ofw_gpio.h> 27#include <dev/ofw/ofw_misc.h> 28#include <dev/ofw/ofw_pinctrl.h> 29#include <dev/ofw/ofw_regulator.h> 30 31#include <drm/drm_modes.h> 32#include <drm/drm_panel.h> 33 34const struct drm_display_mode boe_nv140fhmn49_mode = { 35 .clock = 148500, 36 .hdisplay = 1920, 37 .hsync_start = 1920 + 48, 38 .hsync_end = 1920 + 48 + 32, 39 .htotal = 2200, 40 .vdisplay = 1080, 41 .vsync_start = 1080 + 3, 42 .vsync_end = 1080 + 3 + 5, 43 .vtotal = 1125, 44}; 45 46int simplepanel_match(struct device *, void *, void *); 47void simplepanel_attach(struct device *, struct device *, void *); 48 49struct simplepanel_softc { 50 struct device sc_dev; 51 struct device_ports sc_ports; 52 struct drm_panel sc_panel; 53 const struct drm_display_mode *sc_mode; 54}; 55 56const struct cfattach simplepanel_ca = { 57 sizeof (struct simplepanel_softc), 58 simplepanel_match, simplepanel_attach 59}; 60 61struct cfdriver simplepanel_cd = { 62 NULL, "simplepanel", DV_DULL 63}; 64 65void *simplepanel_ep_get_cookie(void *, struct endpoint *); 66int simplepanel_get_modes(struct drm_panel *, struct drm_connector *); 67 68struct drm_panel_funcs simplepanel_funcs = { 69 .get_modes = simplepanel_get_modes 70}; 71 72int 73simplepanel_match(struct device *parent, void *match, void *aux) 74{ 75 struct fdt_attach_args *faa = aux; 76 77 return (OF_is_compatible(faa->fa_node, "simple-panel") || 78 OF_is_compatible(faa->fa_node, "boe,nv140fhmn49")); 79} 80 81void 82simplepanel_attach(struct device *parent, struct device *self, void *aux) 83{ 84 struct simplepanel_softc *sc = (struct simplepanel_softc *)self; 85 struct fdt_attach_args *faa = aux; 86 uint32_t power_supply; 87 uint32_t *gpios; 88 int connector_type = DRM_MODE_CONNECTOR_Unknown; 89 int len; 90 91 pinctrl_byname(faa->fa_node, "default"); 92 93 power_supply = OF_getpropint(faa->fa_node, "power-supply", 0); 94 if (power_supply) 95 regulator_enable(power_supply); 96 97 len = OF_getproplen(faa->fa_node, "enable-gpios"); 98 if (len > 0) { 99 gpios = malloc(len, M_TEMP, M_WAITOK); 100 OF_getpropintarray(faa->fa_node, "enable-gpios", gpios, len); 101 gpio_controller_config_pin(&gpios[0], GPIO_CONFIG_OUTPUT); 102 gpio_controller_set_pin(&gpios[0], 1); 103 free(gpios, M_TEMP, len); 104 } 105 106 if (OF_is_compatible(faa->fa_node, "boe,nv140fhmn49")) { 107 sc->sc_mode = &boe_nv140fhmn49_mode; 108 connector_type = DRM_MODE_CONNECTOR_eDP; 109 } 110 111 drm_panel_init(&sc->sc_panel, self, &simplepanel_funcs, 112 connector_type); 113 drm_panel_add(&sc->sc_panel); 114 115 printf("\n"); 116 117 sc->sc_ports.dp_node = faa->fa_node; 118 sc->sc_ports.dp_cookie = sc; 119 sc->sc_ports.dp_ep_get_cookie = simplepanel_ep_get_cookie; 120 device_ports_register(&sc->sc_ports, EP_DRM_PANEL); 121} 122 123void * 124simplepanel_ep_get_cookie(void *cookie, struct endpoint *ep) 125{ 126 struct simplepanel_softc *sc = cookie; 127 return &sc->sc_panel; 128} 129 130static inline struct simplepanel_softc * 131to_simplepanel(struct drm_panel *panel) 132{ 133 return container_of(panel, struct simplepanel_softc, sc_panel); 134} 135 136int 137simplepanel_get_modes(struct drm_panel *panel, struct drm_connector *connector) 138{ 139 struct simplepanel_softc *sc = to_simplepanel(panel); 140 struct drm_display_mode *mode; 141 142 if (sc->sc_mode == NULL) 143 return 0; 144 145 mode = drm_mode_duplicate(connector->dev, sc->sc_mode); 146 if (mode == NULL) 147 return 0; 148 mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 149 150 drm_mode_set_name(mode); 151 drm_mode_probed_add(connector, mode); 152 return 1; 153}