1 /* 2 * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. 3 * 4 * Parts of this file were based on sources as follows: 5 * 6 * Copyright (c) 2006-2008 Intel Corporation 7 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 8 * Copyright (C) 2011 Texas Instruments 9 * 10 * This program is free software and is provided to you under the terms of the 11 * GNU General Public License version 2 as published by the Free Software 12 * Foundation, and any use by you of this program is subject to the terms of 13 * such GNU licence. 14 * 15 */ 16 17 #include <linux/amba/clcd-regs.h> 18 #include <linux/clk.h> 19 #include <linux/version.h> 20 #include <linux/dma-buf.h> 21 #include <linux/of_graph.h> 22 23 #include <drm/drmP.h> 24 #include <drm/drm_panel.h> 25 #include <drm/drm_gem_cma_helper.h> 26 #include <drm/drm_fb_cma_helper.h> 27 28 #include "pl111_drm.h" 29 30 irqreturn_t pl111_irq(int irq, void *data) 31 { 32 struct pl111_drm_dev_private *priv = data; 33 u32 irq_stat; 34 irqreturn_t status = IRQ_NONE; 35 36 irq_stat = readl(priv->regs + CLCD_PL111_MIS); 37 38 if (!irq_stat) 39 return IRQ_NONE; 40 41 if (irq_stat & CLCD_IRQ_NEXTBASE_UPDATE) { 42 drm_crtc_handle_vblank(&priv->pipe.crtc); 43 44 status = IRQ_HANDLED; 45 } 46 47 /* Clear the interrupt once done */ 48 writel(irq_stat, priv->regs + CLCD_PL111_ICR); 49 50 return status; 51 } 52 53 static u32 pl111_get_fb_offset(struct drm_plane_state *pstate) 54 { 55 struct drm_framebuffer *fb = pstate->fb; 56 struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0); 57 58 return (obj->paddr + 59 fb->offsets[0] + 60 fb->format->cpp[0] * pstate->src_x + 61 fb->pitches[0] * pstate->src_y); 62 } 63 64 static int pl111_display_check(struct drm_simple_display_pipe *pipe, 65 struct drm_plane_state *pstate, 66 struct drm_crtc_state *cstate) 67 { 68 const struct drm_display_mode *mode = &cstate->mode; 69 struct drm_framebuffer *old_fb = pipe->plane.state->fb; 70 struct drm_framebuffer *fb = pstate->fb; 71 72 if (mode->hdisplay % 16) 73 return -EINVAL; 74 75 if (fb) { 76 u32 offset = pl111_get_fb_offset(pstate); 77 78 /* FB base address must be dword aligned. */ 79 if (offset & 3) 80 return -EINVAL; 81 82 /* There's no pitch register -- the mode's hdisplay 83 * controls it. 84 */ 85 if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) 86 return -EINVAL; 87 88 /* We can't change the FB format in a flicker-free 89 * manner (and only update it during CRTC enable). 90 */ 91 if (old_fb && old_fb->format != fb->format) 92 cstate->mode_changed = true; 93 } 94 95 return 0; 96 } 97 98 static void pl111_display_enable(struct drm_simple_display_pipe *pipe, 99 struct drm_crtc_state *cstate) 100 { 101 struct drm_crtc *crtc = &pipe->crtc; 102 struct drm_plane *plane = &pipe->plane; 103 struct drm_device *drm = crtc->dev; 104 struct pl111_drm_dev_private *priv = drm->dev_private; 105 const struct drm_display_mode *mode = &cstate->mode; 106 struct drm_framebuffer *fb = plane->state->fb; 107 struct drm_connector *connector = &priv->connector.connector; 108 u32 cntl; 109 u32 ppl, hsw, hfp, hbp; 110 u32 lpp, vsw, vfp, vbp; 111 u32 cpl; 112 int ret; 113 114 ret = clk_set_rate(priv->clk, mode->clock * 1000); 115 if (ret) { 116 dev_err(drm->dev, 117 "Failed to set pixel clock rate to %d: %d\n", 118 mode->clock * 1000, ret); 119 } 120 121 clk_prepare_enable(priv->clk); 122 123 ppl = (mode->hdisplay / 16) - 1; 124 hsw = mode->hsync_end - mode->hsync_start - 1; 125 hfp = mode->hsync_start - mode->hdisplay - 1; 126 hbp = mode->htotal - mode->hsync_end - 1; 127 128 lpp = mode->vdisplay - 1; 129 vsw = mode->vsync_end - mode->vsync_start - 1; 130 vfp = mode->vsync_start - mode->vdisplay; 131 vbp = mode->vtotal - mode->vsync_end; 132 133 cpl = mode->hdisplay - 1; 134 135 writel((ppl << 2) | 136 (hsw << 8) | 137 (hfp << 16) | 138 (hbp << 24), 139 priv->regs + CLCD_TIM0); 140 writel(lpp | 141 (vsw << 10) | 142 (vfp << 16) | 143 (vbp << 24), 144 priv->regs + CLCD_TIM1); 145 /* XXX: We currently always use CLCDCLK with no divisor. We 146 * could probably reduce power consumption by using HCLK 147 * (apb_pclk) with a divisor when it gets us near our target 148 * pixel clock. 149 */ 150 writel(((mode->flags & DRM_MODE_FLAG_NHSYNC) ? TIM2_IHS : 0) | 151 ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? TIM2_IVS : 0) | 152 ((connector->display_info.bus_flags & 153 DRM_BUS_FLAG_DE_LOW) ? TIM2_IOE : 0) | 154 ((connector->display_info.bus_flags & 155 DRM_BUS_FLAG_PIXDATA_NEGEDGE) ? TIM2_IPC : 0) | 156 TIM2_BCD | 157 (cpl << 16), 158 priv->regs + CLCD_TIM2); 159 writel(0, priv->regs + CLCD_TIM3); 160 161 drm_panel_prepare(priv->connector.panel); 162 163 /* Enable and Power Up */ 164 cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDPWR | CNTL_LCDVCOMP(1); 165 166 /* Note that the the hardware's format reader takes 'r' from 167 * the low bit, while DRM formats list channels from high bit 168 * to low bit as you read left to right. 169 */ 170 switch (fb->format->format) { 171 case DRM_FORMAT_ABGR8888: 172 case DRM_FORMAT_XBGR8888: 173 cntl |= CNTL_LCDBPP24; 174 break; 175 case DRM_FORMAT_ARGB8888: 176 case DRM_FORMAT_XRGB8888: 177 cntl |= CNTL_LCDBPP24 | CNTL_BGR; 178 break; 179 case DRM_FORMAT_BGR565: 180 cntl |= CNTL_LCDBPP16_565; 181 break; 182 case DRM_FORMAT_RGB565: 183 cntl |= CNTL_LCDBPP16_565 | CNTL_BGR; 184 break; 185 case DRM_FORMAT_ABGR1555: 186 case DRM_FORMAT_XBGR1555: 187 cntl |= CNTL_LCDBPP16; 188 break; 189 case DRM_FORMAT_ARGB1555: 190 case DRM_FORMAT_XRGB1555: 191 cntl |= CNTL_LCDBPP16 | CNTL_BGR; 192 break; 193 case DRM_FORMAT_ABGR4444: 194 case DRM_FORMAT_XBGR4444: 195 cntl |= CNTL_LCDBPP16_444; 196 break; 197 case DRM_FORMAT_ARGB4444: 198 case DRM_FORMAT_XRGB4444: 199 cntl |= CNTL_LCDBPP16_444 | CNTL_BGR; 200 break; 201 default: 202 WARN_ONCE(true, "Unknown FB format 0x%08x\n", 203 fb->format->format); 204 break; 205 } 206 207 writel(cntl, priv->regs + CLCD_PL111_CNTL); 208 209 drm_panel_enable(priv->connector.panel); 210 211 drm_crtc_vblank_on(crtc); 212 } 213 214 void pl111_display_disable(struct drm_simple_display_pipe *pipe) 215 { 216 struct drm_crtc *crtc = &pipe->crtc; 217 struct drm_device *drm = crtc->dev; 218 struct pl111_drm_dev_private *priv = drm->dev_private; 219 220 drm_crtc_vblank_off(crtc); 221 222 drm_panel_disable(priv->connector.panel); 223 224 /* Disable and Power Down */ 225 writel(0, priv->regs + CLCD_PL111_CNTL); 226 227 drm_panel_unprepare(priv->connector.panel); 228 229 clk_disable_unprepare(priv->clk); 230 } 231 232 static void pl111_display_update(struct drm_simple_display_pipe *pipe, 233 struct drm_plane_state *old_pstate) 234 { 235 struct drm_crtc *crtc = &pipe->crtc; 236 struct drm_device *drm = crtc->dev; 237 struct pl111_drm_dev_private *priv = drm->dev_private; 238 struct drm_pending_vblank_event *event = crtc->state->event; 239 struct drm_plane *plane = &pipe->plane; 240 struct drm_plane_state *pstate = plane->state; 241 struct drm_framebuffer *fb = pstate->fb; 242 243 if (fb) { 244 u32 addr = pl111_get_fb_offset(pstate); 245 246 writel(addr, priv->regs + CLCD_UBAS); 247 } 248 249 if (event) { 250 crtc->state->event = NULL; 251 252 spin_lock_irq(&crtc->dev->event_lock); 253 if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) 254 drm_crtc_arm_vblank_event(crtc, event); 255 else 256 drm_crtc_send_vblank_event(crtc, event); 257 spin_unlock_irq(&crtc->dev->event_lock); 258 } 259 } 260 261 int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc) 262 { 263 struct pl111_drm_dev_private *priv = drm->dev_private; 264 265 writel(CLCD_IRQ_NEXTBASE_UPDATE, priv->regs + CLCD_PL111_IENB); 266 267 return 0; 268 } 269 270 void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc) 271 { 272 struct pl111_drm_dev_private *priv = drm->dev_private; 273 274 writel(0, priv->regs + CLCD_PL111_IENB); 275 } 276 277 static int pl111_display_prepare_fb(struct drm_simple_display_pipe *pipe, 278 struct drm_plane_state *plane_state) 279 { 280 return drm_fb_cma_prepare_fb(&pipe->plane, plane_state); 281 } 282 283 const struct drm_simple_display_pipe_funcs pl111_display_funcs = { 284 .check = pl111_display_check, 285 .enable = pl111_display_enable, 286 .disable = pl111_display_disable, 287 .update = pl111_display_update, 288 .prepare_fb = pl111_display_prepare_fb, 289 }; 290 291 int pl111_display_init(struct drm_device *drm) 292 { 293 struct pl111_drm_dev_private *priv = drm->dev_private; 294 struct device *dev = drm->dev; 295 struct device_node *endpoint; 296 u32 tft_r0b0g0[3]; 297 int ret; 298 static const u32 formats[] = { 299 DRM_FORMAT_ABGR8888, 300 DRM_FORMAT_XBGR8888, 301 DRM_FORMAT_ARGB8888, 302 DRM_FORMAT_XRGB8888, 303 DRM_FORMAT_BGR565, 304 DRM_FORMAT_RGB565, 305 DRM_FORMAT_ABGR1555, 306 DRM_FORMAT_XBGR1555, 307 DRM_FORMAT_ARGB1555, 308 DRM_FORMAT_XRGB1555, 309 DRM_FORMAT_ABGR4444, 310 DRM_FORMAT_XBGR4444, 311 DRM_FORMAT_ARGB4444, 312 DRM_FORMAT_XRGB4444, 313 }; 314 315 endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); 316 if (!endpoint) 317 return -ENODEV; 318 319 if (of_property_read_u32_array(endpoint, 320 "arm,pl11x,tft-r0g0b0-pads", 321 tft_r0b0g0, 322 ARRAY_SIZE(tft_r0b0g0)) != 0) { 323 dev_err(dev, "arm,pl11x,tft-r0g0b0-pads should be 3 ints\n"); 324 of_node_put(endpoint); 325 return -ENOENT; 326 } 327 of_node_put(endpoint); 328 329 if (tft_r0b0g0[0] != 0 || 330 tft_r0b0g0[1] != 8 || 331 tft_r0b0g0[2] != 16) { 332 dev_err(dev, "arm,pl11x,tft-r0g0b0-pads != [0,8,16] not yet supported\n"); 333 return -EINVAL; 334 } 335 336 ret = drm_simple_display_pipe_init(drm, &priv->pipe, 337 &pl111_display_funcs, 338 formats, ARRAY_SIZE(formats), 339 &priv->connector.connector); 340 if (ret) 341 return ret; 342 343 return 0; 344 } 345