1 // SPDX-License-Identifier: GPL-2.0+ 2 // Copyright 2018 IBM Corporation 3 4 #include <linux/clk.h> 5 #include <linux/reset.h> 6 #include <linux/regmap.h> 7 8 #include <drm/drm_crtc_helper.h> 9 #include <drm/drm_device.h> 10 #include <drm/drm_fb_dma_helper.h> 11 #include <drm/drm_fourcc.h> 12 #include <drm/drm_framebuffer.h> 13 #include <drm/drm_gem_atomic_helper.h> 14 #include <drm/drm_gem_dma_helper.h> 15 #include <drm/drm_panel.h> 16 #include <drm/drm_simple_kms_helper.h> 17 #include <drm/drm_vblank.h> 18 19 #include "aspeed_gfx.h" 20 21 static struct aspeed_gfx * 22 drm_pipe_to_aspeed_gfx(struct drm_simple_display_pipe *pipe) 23 { 24 return container_of(pipe, struct aspeed_gfx, pipe); 25 } 26 27 static int aspeed_gfx_set_pixel_fmt(struct aspeed_gfx *priv, u32 *bpp) 28 { 29 struct drm_crtc *crtc = &priv->pipe.crtc; 30 struct drm_device *drm = crtc->dev; 31 const u32 format = crtc->primary->state->fb->format->format; 32 u32 ctrl1; 33 34 ctrl1 = readl(priv->base + CRT_CTRL1); 35 ctrl1 &= ~CRT_CTRL_COLOR_MASK; 36 37 switch (format) { 38 case DRM_FORMAT_RGB565: 39 dev_dbg(drm->dev, "Setting up RGB565 mode\n"); 40 ctrl1 |= CRT_CTRL_COLOR_RGB565; 41 *bpp = 16; 42 break; 43 case DRM_FORMAT_XRGB8888: 44 dev_dbg(drm->dev, "Setting up XRGB8888 mode\n"); 45 ctrl1 |= CRT_CTRL_COLOR_XRGB8888; 46 *bpp = 32; 47 break; 48 default: 49 dev_err(drm->dev, "Unhandled pixel format %08x\n", format); 50 return -EINVAL; 51 } 52 53 writel(ctrl1, priv->base + CRT_CTRL1); 54 55 return 0; 56 } 57 58 static void aspeed_gfx_enable_controller(struct aspeed_gfx *priv) 59 { 60 u32 ctrl1 = readl(priv->base + CRT_CTRL1); 61 u32 ctrl2 = readl(priv->base + CRT_CTRL2); 62 63 /* Set DAC source for display output to Graphics CRT (GFX) */ 64 regmap_update_bits(priv->scu, priv->dac_reg, BIT(16), BIT(16)); 65 66 writel(ctrl1 | CRT_CTRL_EN, priv->base + CRT_CTRL1); 67 writel(ctrl2 | CRT_CTRL_DAC_EN, priv->base + CRT_CTRL2); 68 } 69 70 static void aspeed_gfx_disable_controller(struct aspeed_gfx *priv) 71 { 72 u32 ctrl1 = readl(priv->base + CRT_CTRL1); 73 u32 ctrl2 = readl(priv->base + CRT_CTRL2); 74 75 writel(ctrl1 & ~CRT_CTRL_EN, priv->base + CRT_CTRL1); 76 writel(ctrl2 & ~CRT_CTRL_DAC_EN, priv->base + CRT_CTRL2); 77 78 regmap_update_bits(priv->scu, priv->dac_reg, BIT(16), 0); 79 } 80 81 static void aspeed_gfx_crtc_mode_set_nofb(struct aspeed_gfx *priv) 82 { 83 struct drm_display_mode *m = &priv->pipe.crtc.state->adjusted_mode; 84 u32 ctrl1, d_offset, t_count, bpp; 85 int err; 86 87 err = aspeed_gfx_set_pixel_fmt(priv, &bpp); 88 if (err) 89 return; 90 91 #if 0 92 /* TODO: we have only been able to test with the 40MHz USB clock. The 93 * clock is fixed, so we cannot adjust it here. */ 94 clk_set_rate(priv->pixel_clk, m->crtc_clock * 1000); 95 #endif 96 97 ctrl1 = readl(priv->base + CRT_CTRL1); 98 ctrl1 &= ~(CRT_CTRL_INTERLACED | 99 CRT_CTRL_HSYNC_NEGATIVE | 100 CRT_CTRL_VSYNC_NEGATIVE); 101 102 if (m->flags & DRM_MODE_FLAG_INTERLACE) 103 ctrl1 |= CRT_CTRL_INTERLACED; 104 105 if (!(m->flags & DRM_MODE_FLAG_PHSYNC)) 106 ctrl1 |= CRT_CTRL_HSYNC_NEGATIVE; 107 108 if (!(m->flags & DRM_MODE_FLAG_PVSYNC)) 109 ctrl1 |= CRT_CTRL_VSYNC_NEGATIVE; 110 111 writel(ctrl1, priv->base + CRT_CTRL1); 112 113 /* Horizontal timing */ 114 writel(CRT_H_TOTAL(m->htotal - 1) | CRT_H_DE(m->hdisplay - 1), 115 priv->base + CRT_HORIZ0); 116 writel(CRT_H_RS_START(m->hsync_start - 1) | CRT_H_RS_END(m->hsync_end), 117 priv->base + CRT_HORIZ1); 118 119 120 /* Vertical timing */ 121 writel(CRT_V_TOTAL(m->vtotal - 1) | CRT_V_DE(m->vdisplay - 1), 122 priv->base + CRT_VERT0); 123 writel(CRT_V_RS_START(m->vsync_start) | CRT_V_RS_END(m->vsync_end), 124 priv->base + CRT_VERT1); 125 126 /* 127 * Display Offset: address difference between consecutive scan lines 128 * Terminal Count: memory size of one scan line 129 */ 130 d_offset = m->hdisplay * bpp / 8; 131 t_count = DIV_ROUND_UP(m->hdisplay * bpp, priv->scan_line_max); 132 133 writel(CRT_DISP_OFFSET(d_offset) | CRT_TERM_COUNT(t_count), 134 priv->base + CRT_OFFSET); 135 136 /* 137 * Threshold: FIFO thresholds of refill and stop (16 byte chunks 138 * per line, rounded up) 139 */ 140 writel(priv->throd_val, priv->base + CRT_THROD); 141 } 142 143 static void aspeed_gfx_pipe_enable(struct drm_simple_display_pipe *pipe, 144 struct drm_crtc_state *crtc_state, 145 struct drm_plane_state *plane_state) 146 { 147 struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); 148 struct drm_crtc *crtc = &pipe->crtc; 149 150 aspeed_gfx_crtc_mode_set_nofb(priv); 151 aspeed_gfx_enable_controller(priv); 152 drm_crtc_vblank_on(crtc); 153 } 154 155 static void aspeed_gfx_pipe_disable(struct drm_simple_display_pipe *pipe) 156 { 157 struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); 158 struct drm_crtc *crtc = &pipe->crtc; 159 160 drm_crtc_vblank_off(crtc); 161 aspeed_gfx_disable_controller(priv); 162 } 163 164 static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe, 165 struct drm_plane_state *plane_state) 166 { 167 struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); 168 struct drm_crtc *crtc = &pipe->crtc; 169 struct drm_framebuffer *fb = pipe->plane.state->fb; 170 struct drm_pending_vblank_event *event; 171 struct drm_gem_dma_object *gem; 172 173 spin_lock_irq(&crtc->dev->event_lock); 174 event = crtc->state->event; 175 if (event) { 176 crtc->state->event = NULL; 177 178 if (drm_crtc_vblank_get(crtc) == 0) 179 drm_crtc_arm_vblank_event(crtc, event); 180 else 181 drm_crtc_send_vblank_event(crtc, event); 182 } 183 spin_unlock_irq(&crtc->dev->event_lock); 184 185 if (!fb) 186 return; 187 188 gem = drm_fb_dma_get_gem_obj(fb, 0); 189 if (!gem) 190 return; 191 writel(gem->dma_addr, priv->base + CRT_ADDR); 192 } 193 194 static int aspeed_gfx_enable_vblank(struct drm_simple_display_pipe *pipe) 195 { 196 struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); 197 u32 reg = readl(priv->base + CRT_CTRL1); 198 199 /* Clear pending VBLANK IRQ */ 200 writel(reg | CRT_CTRL_VERTICAL_INTR_STS, priv->base + CRT_CTRL1); 201 202 reg |= CRT_CTRL_VERTICAL_INTR_EN; 203 writel(reg, priv->base + CRT_CTRL1); 204 205 return 0; 206 } 207 208 static void aspeed_gfx_disable_vblank(struct drm_simple_display_pipe *pipe) 209 { 210 struct aspeed_gfx *priv = drm_pipe_to_aspeed_gfx(pipe); 211 u32 reg = readl(priv->base + CRT_CTRL1); 212 213 reg &= ~CRT_CTRL_VERTICAL_INTR_EN; 214 writel(reg, priv->base + CRT_CTRL1); 215 216 /* Clear pending VBLANK IRQ */ 217 writel(reg | CRT_CTRL_VERTICAL_INTR_STS, priv->base + CRT_CTRL1); 218 } 219 220 static const struct drm_simple_display_pipe_funcs aspeed_gfx_funcs = { 221 .enable = aspeed_gfx_pipe_enable, 222 .disable = aspeed_gfx_pipe_disable, 223 .update = aspeed_gfx_pipe_update, 224 .enable_vblank = aspeed_gfx_enable_vblank, 225 .disable_vblank = aspeed_gfx_disable_vblank, 226 }; 227 228 static const uint32_t aspeed_gfx_formats[] = { 229 DRM_FORMAT_XRGB8888, 230 DRM_FORMAT_RGB565, 231 }; 232 233 int aspeed_gfx_create_pipe(struct drm_device *drm) 234 { 235 struct aspeed_gfx *priv = to_aspeed_gfx(drm); 236 237 return drm_simple_display_pipe_init(drm, &priv->pipe, &aspeed_gfx_funcs, 238 aspeed_gfx_formats, 239 ARRAY_SIZE(aspeed_gfx_formats), 240 NULL, 241 &priv->connector); 242 } 243