Module Name: src Committed By: jakllsch Date: Tue Dec 17 18:26:36 UTC 2019
Modified Files: src/sys/arch/arm/rockchip: rk_dwhdmi.c rk_vop.c Log Message: Move drm_encoder from rkvop(4) to the SoC-layer output pipe drivers (rk_dwhdmi). To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/rockchip/rk_dwhdmi.c \ src/sys/arch/arm/rockchip/rk_vop.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/rockchip/rk_dwhdmi.c diff -u src/sys/arch/arm/rockchip/rk_dwhdmi.c:1.3 src/sys/arch/arm/rockchip/rk_dwhdmi.c:1.4 --- src/sys/arch/arm/rockchip/rk_dwhdmi.c:1.3 Sat Nov 16 13:25:33 2019 +++ src/sys/arch/arm/rockchip/rk_dwhdmi.c Tue Dec 17 18:26:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_dwhdmi.c,v 1.3 2019/11/16 13:25:33 jmcneill Exp $ */ +/* $NetBSD: rk_dwhdmi.c,v 1.4 2019/12/17 18:26:36 jakllsch Exp $ */ /*- * Copyright (c) 2019 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_dwhdmi.c,v 1.3 2019/11/16 13:25:33 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_dwhdmi.c,v 1.4 2019/12/17 18:26:36 jakllsch Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -38,6 +38,7 @@ __KERNEL_RCSID(0, "$NetBSD: rk_dwhdmi.c, #include <sys/conf.h> #include <drm/drmP.h> +#include <drm/drm_crtc_helper.h> #include <dev/fdt/fdtvar.h> #include <dev/fdt/fdt_port.h> @@ -85,12 +86,14 @@ struct rk_dwhdmi_softc { struct fdt_device_ports sc_ports; struct drm_display_mode sc_curmode; + struct drm_encoder sc_encoder; struct syscon *sc_grf; bool sc_activated; }; #define to_rk_dwhdmi_softc(x) container_of(x, struct rk_dwhdmi_softc, sc_base) +#define to_rk_dwhdmi_encoder(x) container_of(x, struct rk_dwhdmi_softc, sc_encoder) static void rk_dwhdmi_select_input(struct rk_dwhdmi_softc *sc, u_int crtc_index) @@ -103,16 +106,69 @@ rk_dwhdmi_select_input(struct rk_dwhdmi_ syscon_unlock(sc->sc_grf); } +static bool +rk_dwhdmi_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void +rk_dwhdmi_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, struct drm_display_mode *adjusted) +{ +} + +static void +rk_dwhdmi_encoder_enable(struct drm_encoder *encoder) +{ +} + +static void +rk_dwhdmi_encoder_disable(struct drm_encoder *encoder) +{ +} + +static void +rk_dwhdmi_encoder_prepare(struct drm_encoder *encoder) +{ + struct rk_dwhdmi_softc * const sc = to_rk_dwhdmi_encoder(encoder); + const u_int crtc_index = drm_crtc_index(encoder->crtc); + + rk_dwhdmi_select_input(sc, crtc_index); +} + +static void +rk_dwhdmi_encoder_commit(struct drm_encoder *encoder) +{ +} + +static const struct drm_encoder_funcs rk_dwhdmi_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +static const struct drm_encoder_helper_funcs rk_dwhdmi_encoder_helper_funcs = { + .prepare = rk_dwhdmi_encoder_prepare, + .mode_fixup = rk_dwhdmi_encoder_mode_fixup, + .mode_set = rk_dwhdmi_encoder_mode_set, + .enable = rk_dwhdmi_encoder_enable, + .disable = rk_dwhdmi_encoder_disable, + .commit = rk_dwhdmi_encoder_commit, +}; + static int rk_dwhdmi_ep_activate(device_t dev, struct fdt_endpoint *ep, bool activate) { struct rk_dwhdmi_softc * const sc = device_private(dev); struct fdt_endpoint *in_ep = fdt_endpoint_remote(ep); struct fdt_endpoint *out_ep, *out_rep; - struct drm_encoder *encoder; - struct drm_bridge *bridge; + struct drm_crtc *crtc; int error; + if (sc->sc_activated != false) { + return 0; + } + if (!activate) return EINVAL; @@ -120,27 +176,27 @@ rk_dwhdmi_ep_activate(device_t dev, stru return EINVAL; switch (fdt_endpoint_type(in_ep)) { - case EP_DRM_ENCODER: - encoder = fdt_endpoint_get_data(in_ep); - break; - case EP_DRM_BRIDGE: - bridge = fdt_endpoint_get_data(in_ep); - encoder = bridge->encoder; + case EP_DRM_CRTC: + crtc = fdt_endpoint_get_data(in_ep); break; default: - encoder = NULL; + crtc = NULL; break; } - if (encoder == NULL) + if (crtc == NULL) return EINVAL; - if (sc->sc_activated == false) { - error = dwhdmi_bind(&sc->sc_base, encoder); - if (error != 0) - return error; - sc->sc_activated = true; - } + sc->sc_encoder.possible_crtcs = 3; // 1U << drm_crtc_index(crtc); /* XXX */ + drm_encoder_init(crtc->dev, &sc->sc_encoder, &rk_dwhdmi_encoder_funcs, + DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(&sc->sc_encoder, &rk_dwhdmi_encoder_helper_funcs); + + sc->sc_base.sc_connector.base.connector_type = DRM_MODE_CONNECTOR_HDMIA; + error = dwhdmi_bind(&sc->sc_base, &sc->sc_encoder); + if (error != 0) + return error; + sc->sc_activated = true; out_ep = fdt_endpoint_get_from_index(&sc->sc_ports, DWHDMI_PORT_OUTPUT, 0); if (out_ep != NULL) { @@ -162,17 +218,12 @@ rk_dwhdmi_ep_get_data(device_t dev, stru { struct rk_dwhdmi_softc * const sc = device_private(dev); - return &sc->sc_base.sc_bridge; + return &sc->sc_encoder; } static void rk_dwhdmi_enable(struct dwhdmi_softc *dsc) { - struct rk_dwhdmi_softc * const sc = to_rk_dwhdmi_softc(dsc); - - const u_int crtc_index = drm_crtc_index(dsc->sc_bridge.encoder->crtc); - - rk_dwhdmi_select_input(sc, crtc_index); dwhdmi_phy_enable(dsc); } @@ -301,7 +352,7 @@ rk_dwhdmi_attach(device_t parent, device sc->sc_ports.dp_ep_activate = rk_dwhdmi_ep_activate; sc->sc_ports.dp_ep_get_data = rk_dwhdmi_ep_get_data; - fdt_ports_register(&sc->sc_ports, self, phandle, EP_DRM_BRIDGE); + fdt_ports_register(&sc->sc_ports, self, phandle, EP_DRM_ENCODER); fdtbus_register_dai_controller(self, phandle, &rk_dwhdmi_dai_funcs); } Index: src/sys/arch/arm/rockchip/rk_vop.c diff -u src/sys/arch/arm/rockchip/rk_vop.c:1.3 src/sys/arch/arm/rockchip/rk_vop.c:1.4 --- src/sys/arch/arm/rockchip/rk_vop.c:1.3 Sun Dec 15 00:49:00 2019 +++ src/sys/arch/arm/rockchip/rk_vop.c Tue Dec 17 18:26:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_vop.c,v 1.3 2019/12/15 00:49:00 mrg Exp $ */ +/* $NetBSD: rk_vop.c,v 1.4 2019/12/17 18:26:36 jakllsch Exp $ */ /*- * Copyright (c) 2019 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_vop.c,v 1.3 2019/12/15 00:49:00 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_vop.c,v 1.4 2019/12/17 18:26:36 jakllsch Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -128,12 +128,6 @@ struct rk_vop_crtc { struct rk_vop_softc *sc; }; -struct rk_vop_encoder { - struct drm_encoder base; - struct rk_vop_softc *sc; - enum vop_ep_type ep_type; -}; - struct rk_vop_softc { device_t sc_dev; bus_space_tag_t sc_bst; @@ -143,7 +137,6 @@ struct rk_vop_softc { struct clk *sc_dclk; struct rk_vop_crtc sc_crtc; - struct rk_vop_encoder sc_encoder[VOP_NEP]; struct fdt_device_ports sc_ports; @@ -151,7 +144,6 @@ struct rk_vop_softc { }; #define to_rk_vop_crtc(x) container_of(x, struct rk_vop_crtc, base) -#define to_rk_vop_encoder(x) container_of(x, struct rk_vop_encoder, base) #define RD4(sc, reg) \ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) @@ -285,14 +277,19 @@ rk_vop_mode_set(struct drm_crtc *crtc, s uint32_t val; u_int lb_mode; int error; + u_int pol; + int connector_type = 0; + struct drm_connector * connector; const u_int hactive = adjusted_mode->hdisplay; const u_int hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start; const u_int hback_porch = adjusted_mode->htotal - adjusted_mode->hsync_end; + const u_int hfront_porch = adjusted_mode->hsync_start - adjusted_mode->hdisplay; const u_int vactive = adjusted_mode->vdisplay; const u_int vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start; const u_int vback_porch = adjusted_mode->vtotal - adjusted_mode->vsync_end; + const u_int vfront_porch = adjusted_mode->vsync_start - adjusted_mode->vdisplay; error = clk_set_rate(sc->sc_dclk, adjusted_mode->clock * 1000); if (error != 0) @@ -331,6 +328,73 @@ rk_vop_mode_set(struct drm_crtc *crtc, s rk_vop_mode_do_set_base(crtc, old_fb, x, y, 0); + pol = DSP_DCLK_POL; + if ((adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) != 0) + pol |= DSP_HSYNC_POL; + if ((adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) != 0) + pol |= DSP_VSYNC_POL; + + drm_for_each_connector(connector, crtc->dev) { + if ((connector->encoder) == NULL) + continue; + if (connector->encoder->crtc == crtc) { + connector_type = connector->connector_type; + break; + } + } + + switch (connector_type) { + case DRM_MODE_CONNECTOR_HDMIA: + sc->sc_conf->set_polarity(sc, VOP_EP_HDMI, pol); + break; + case DRM_MODE_CONNECTOR_eDP: + sc->sc_conf->set_polarity(sc, VOP_EP_EDP, pol); + break; + } + + val = RD4(sc, VOP_SYS_CTRL); + val &= ~VOP_STANDBY_EN; + val &= ~(MIPI_OUT_EN|EDP_OUT_EN|HDMI_OUT_EN|RGB_OUT_EN); + + switch (connector_type) { + case DRM_MODE_CONNECTOR_HDMIA: + val |= HDMI_OUT_EN; + break; + case DRM_MODE_CONNECTOR_eDP: + val |= EDP_OUT_EN; + break; + } + WR4(sc, VOP_SYS_CTRL, val); + + val = RD4(sc, VOP_DSP_CTRL0); + val &= ~DSP_OUT_MODE; + val |= __SHIFTIN(sc->sc_conf->out_mode, DSP_OUT_MODE); + WR4(sc, VOP_DSP_CTRL0, val); + + val = __SHIFTIN(hsync_len + hback_porch, DSP_HACT_ST_POST) | + __SHIFTIN(hsync_len + hback_porch + hactive, DSP_HACT_END_POST); + WR4(sc, VOP_POST_DSP_HACT_INFO, val); + + val = __SHIFTIN(hsync_len + hback_porch, DSP_HACT_ST) | + __SHIFTIN(hsync_len + hback_porch + hactive, DSP_HACT_END); + WR4(sc, VOP_DSP_HACT_ST_END, val); + + val = __SHIFTIN(hsync_len, DSP_HTOTAL) | + __SHIFTIN(hsync_len + hback_porch + hactive + hfront_porch, DSP_HS_END); + WR4(sc, VOP_DSP_HTOTAL_HS_END, val); + + val = __SHIFTIN(vsync_len + vback_porch, DSP_VACT_ST_POST) | + __SHIFTIN(vsync_len + vback_porch + vactive, DSP_VACT_END_POST); + WR4(sc, VOP_POST_DSP_VACT_INFO, val); + + val = __SHIFTIN(vsync_len + vback_porch, DSP_VACT_ST) | + __SHIFTIN(vsync_len + vback_porch + vactive, DSP_VACT_END); + WR4(sc, VOP_DSP_VACT_ST_END, val); + + val = __SHIFTIN(vsync_len, DSP_VTOTAL) | + __SHIFTIN(vsync_len + vback_porch + vactive + vfront_porch, DSP_VS_END); + WR4(sc, VOP_DSP_VTOTAL_VS_END, val); + return 0; } @@ -395,132 +459,11 @@ static const struct drm_crtc_helper_func .commit = rk_vop_commit, }; -static void -rk_vop_encoder_destroy(struct drm_encoder *encoder) -{ -} - -static const struct drm_encoder_funcs rk_vop_encoder_funcs = { - .destroy = rk_vop_encoder_destroy, -}; - -static void -rk_vop_encoder_dpms(struct drm_encoder *encoder, int mode) -{ -} - -static bool -rk_vop_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static void -rk_vop_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) -{ - struct rk_vop_encoder *rkencoder = to_rk_vop_encoder(encoder); - struct rk_vop_softc * const sc = rkencoder->sc; - uint32_t val; - u_int pol; - - const u_int hactive = adjusted_mode->hdisplay; - const u_int hfront_porch = adjusted_mode->hsync_start - adjusted_mode->hdisplay; - const u_int hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start; - const u_int hback_porch = adjusted_mode->htotal - adjusted_mode->hsync_end; - - const u_int vactive = adjusted_mode->vdisplay; - const u_int vfront_porch = adjusted_mode->vsync_start - adjusted_mode->vdisplay; - const u_int vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start; - const u_int vback_porch = adjusted_mode->vtotal - adjusted_mode->vsync_end; - - pol = DSP_DCLK_POL; - if ((adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) != 0) - pol |= DSP_HSYNC_POL; - if ((adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) != 0) - pol |= DSP_VSYNC_POL; - sc->sc_conf->set_polarity(sc, rkencoder->ep_type, pol); - - val = RD4(sc, VOP_SYS_CTRL); - val &= ~VOP_STANDBY_EN; - val &= ~(MIPI_OUT_EN|EDP_OUT_EN|HDMI_OUT_EN|RGB_OUT_EN); - switch (rkencoder->ep_type) { - case VOP_EP_MIPI: - case VOP_EP_MIPI1: - val |= MIPI_OUT_EN; - break; - case VOP_EP_EDP: - case VOP_EP_DP: - val |= EDP_OUT_EN; - break; - case VOP_EP_HDMI: - val |= HDMI_OUT_EN; - break; - default: - break; - } - WR4(sc, VOP_SYS_CTRL, val); - - val = RD4(sc, VOP_DSP_CTRL0); - val &= ~DSP_OUT_MODE; - val |= __SHIFTIN(sc->sc_conf->out_mode, DSP_OUT_MODE); - WR4(sc, VOP_DSP_CTRL0, val); - - val = __SHIFTIN(hsync_len + hback_porch, DSP_HACT_ST_POST) | - __SHIFTIN(hsync_len + hback_porch + hactive, DSP_HACT_END_POST); - WR4(sc, VOP_POST_DSP_HACT_INFO, val); - - val = __SHIFTIN(hsync_len + hback_porch, DSP_HACT_ST) | - __SHIFTIN(hsync_len + hback_porch + hactive, DSP_HACT_END); - WR4(sc, VOP_DSP_HACT_ST_END, val); - - val = __SHIFTIN(hsync_len, DSP_HTOTAL) | - __SHIFTIN(hsync_len + hback_porch + hactive + hfront_porch, DSP_HS_END); - WR4(sc, VOP_DSP_HTOTAL_HS_END, val); - - val = __SHIFTIN(vsync_len + vback_porch, DSP_VACT_ST_POST) | - __SHIFTIN(vsync_len + vback_porch + vactive, DSP_VACT_END_POST); - WR4(sc, VOP_POST_DSP_VACT_INFO, val); - - val = __SHIFTIN(vsync_len + vback_porch, DSP_VACT_ST) | - __SHIFTIN(vsync_len + vback_porch + vactive, DSP_VACT_END); - WR4(sc, VOP_DSP_VACT_ST_END, val); - - val = __SHIFTIN(vsync_len, DSP_VTOTAL) | - __SHIFTIN(vsync_len + vback_porch + vactive + vfront_porch, DSP_VS_END); - WR4(sc, VOP_DSP_VTOTAL_VS_END, val); -} - -static void -rk_vop_encoder_prepare(struct drm_encoder *encoder) -{ -} - -static void -rk_vop_encoder_commit(struct drm_encoder *encoder) -{ - struct rk_vop_encoder *rkencoder = to_rk_vop_encoder(encoder); - struct rk_vop_softc * const sc = rkencoder->sc; - - /* Commit settings */ - WR4(sc, VOP_REG_CFG_DONE, REG_LOAD_EN); -} - -static const struct drm_encoder_helper_funcs rk_vop_encoder_helper_funcs = { - .dpms = rk_vop_encoder_dpms, - .mode_fixup = rk_vop_encoder_mode_fixup, - .prepare = rk_vop_encoder_prepare, - .commit = rk_vop_encoder_commit, - .mode_set = rk_vop_encoder_mode_set, -}; - static int rk_vop_ep_activate(device_t dev, struct fdt_endpoint *ep, bool activate) { struct rk_vop_softc * const sc = device_private(dev); struct drm_device *ddev; - u_int encoder_type; if (!activate) return EINVAL; @@ -542,28 +485,11 @@ rk_vop_ep_activate(device_t dev, struct } const u_int ep_index = fdt_endpoint_index(ep); - switch (ep_index) { - case VOP_EP_MIPI: - case VOP_EP_MIPI1: - encoder_type = DRM_MODE_ENCODER_DSI; - break; - case VOP_EP_HDMI: - case VOP_EP_EDP: - case VOP_EP_DP: - encoder_type = DRM_MODE_ENCODER_TMDS; - break; - default: + if (ep_index >= VOP_NEP) { DRM_ERROR("endpoint index %d out of range\n", ep_index); return ENXIO; } - sc->sc_encoder[ep_index].sc = sc; - sc->sc_encoder[ep_index].ep_type = ep_index; - sc->sc_encoder[ep_index].base.possible_crtcs = 1 << drm_crtc_index(&sc->sc_crtc.base); - drm_encoder_init(ddev, &sc->sc_encoder[ep_index].base, &rk_vop_encoder_funcs, - encoder_type); - drm_encoder_helper_add(&sc->sc_encoder[ep_index].base, &rk_vop_encoder_helper_funcs); - return fdt_endpoint_activate(ep, activate); } @@ -571,15 +497,8 @@ static void * rk_vop_ep_get_data(device_t dev, struct fdt_endpoint *ep) { struct rk_vop_softc * const sc = device_private(dev); - const u_int ep_index = fdt_endpoint_index(ep); - - if (ep_index >= VOP_NEP) - return NULL; - - if (sc->sc_encoder[ep_index].sc == NULL) - return NULL; - return &sc->sc_encoder[ep_index].base; + return &sc->sc_crtc.base; } static int @@ -646,7 +565,7 @@ rk_vop_attach(device_t parent, device_t sc->sc_ports.dp_ep_activate = rk_vop_ep_activate; sc->sc_ports.dp_ep_get_data = rk_vop_ep_get_data; - fdt_ports_register(&sc->sc_ports, self, phandle, EP_DRM_ENCODER); + fdt_ports_register(&sc->sc_ports, self, phandle, EP_DRM_CRTC); const int port_phandle = of_find_firstchild_byname(phandle, "port"); if (port_phandle > 0)