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 int pl111_display_check(struct drm_simple_display_pipe *pipe, 54 struct drm_plane_state *pstate, 55 struct drm_crtc_state *cstate) 56 { 57 const struct drm_display_mode *mode = &cstate->mode; 58 struct drm_framebuffer *old_fb = pipe->plane.state->fb; 59 struct drm_framebuffer *fb = pstate->fb; 60 61 if (mode->hdisplay % 16) 62 return -EINVAL; 63 64 if (fb) { 65 u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0); 66 67 /* FB base address must be dword aligned. */ 68 if (offset & 3) 69 return -EINVAL; 70 71 /* There's no pitch register -- the mode's hdisplay 72 * controls it. 73 */ 74 if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) 75 return -EINVAL; 76 77 /* We can't change the FB format in a flicker-free 78 * manner (and only update it during CRTC enable). 79 */ 80 if (old_fb && old_fb->format != fb->format) 81 cstate->mode_changed = true; 82 } 83 84 return 0; 85 } 86 87 static void pl111_display_enable(struct drm_simple_display_pipe *pipe, 88 struct drm_crtc_state *cstate) 89 { 90 struct drm_crtc *crtc = &pipe->crtc; 91 struct drm_plane *plane = &pipe->plane; 92 struct drm_device *drm = crtc->dev; 93 struct pl111_drm_dev_private *priv = drm->dev_private; 94 const struct drm_display_mode *mode = &cstate->mode; 95 struct drm_framebuffer *fb = plane->state->fb; 96 struct drm_connector *connector = &priv->connector.connector; 97 u32 cntl; 98 u32 ppl, hsw, hfp, hbp; 99 u32 lpp, vsw, vfp, vbp; 100 u32 cpl, tim2; 101 int ret; 102 103 ret = clk_set_rate(priv->clk, mode->clock * 1000); 104 if (ret) { 105 dev_err(drm->dev, 106 "Failed to set pixel clock rate to %d: %d\n", 107 mode->clock * 1000, ret); 108 } 109 110 clk_prepare_enable(priv->clk); 111 112 ppl = (mode->hdisplay / 16) - 1; 113 hsw = mode->hsync_end - mode->hsync_start - 1; 114 hfp = mode->hsync_start - mode->hdisplay - 1; 115 hbp = mode->htotal - mode->hsync_end - 1; 116 117 lpp = mode->vdisplay - 1; 118 vsw = mode->vsync_end - mode->vsync_start - 1; 119 vfp = mode->vsync_start - mode->vdisplay; 120 vbp = mode->vtotal - mode->vsync_end; 121 122 cpl = mode->hdisplay - 1; 123 124 writel((ppl << 2) | 125 (hsw << 8) | 126 (hfp << 16) | 127 (hbp << 24), 128 priv->regs + CLCD_TIM0); 129 writel(lpp | 130 (vsw << 10) | 131 (vfp << 16) | 132 (vbp << 24), 133 priv->regs + CLCD_TIM1); 134 135 spin_lock(&priv->tim2_lock); 136 137 tim2 = readl(priv->regs + CLCD_TIM2); 138 tim2 &= (TIM2_BCD | TIM2_PCD_LO_MASK | TIM2_PCD_HI_MASK); 139 140 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 141 tim2 |= TIM2_IHS; 142 143 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 144 tim2 |= TIM2_IVS; 145 146 if (connector->display_info.bus_flags & DRM_BUS_FLAG_DE_LOW) 147 tim2 |= TIM2_IOE; 148 149 if (connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE) 150 tim2 |= TIM2_IPC; 151 152 tim2 |= cpl << 16; 153 writel(tim2, priv->regs + CLCD_TIM2); 154 spin_unlock(&priv->tim2_lock); 155 156 writel(0, priv->regs + CLCD_TIM3); 157 158 drm_panel_prepare(priv->connector.panel); 159 160 /* Enable and Power Up */ 161 cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDPWR | CNTL_LCDVCOMP(1); 162 163 /* Note that the the hardware's format reader takes 'r' from 164 * the low bit, while DRM formats list channels from high bit 165 * to low bit as you read left to right. 166 */ 167 switch (fb->format->format) { 168 case DRM_FORMAT_ABGR8888: 169 case DRM_FORMAT_XBGR8888: 170 cntl |= CNTL_LCDBPP24; 171 break; 172 case DRM_FORMAT_ARGB8888: 173 case DRM_FORMAT_XRGB8888: 174 cntl |= CNTL_LCDBPP24 | CNTL_BGR; 175 break; 176 case DRM_FORMAT_BGR565: 177 cntl |= CNTL_LCDBPP16_565; 178 break; 179 case DRM_FORMAT_RGB565: 180 cntl |= CNTL_LCDBPP16_565 | CNTL_BGR; 181 break; 182 case DRM_FORMAT_ABGR1555: 183 case DRM_FORMAT_XBGR1555: 184 cntl |= CNTL_LCDBPP16; 185 break; 186 case DRM_FORMAT_ARGB1555: 187 case DRM_FORMAT_XRGB1555: 188 cntl |= CNTL_LCDBPP16 | CNTL_BGR; 189 break; 190 case DRM_FORMAT_ABGR4444: 191 case DRM_FORMAT_XBGR4444: 192 cntl |= CNTL_LCDBPP16_444; 193 break; 194 case DRM_FORMAT_ARGB4444: 195 case DRM_FORMAT_XRGB4444: 196 cntl |= CNTL_LCDBPP16_444 | CNTL_BGR; 197 break; 198 default: 199 WARN_ONCE(true, "Unknown FB format 0x%08x\n", 200 fb->format->format); 201 break; 202 } 203 204 writel(cntl, priv->regs + CLCD_PL111_CNTL); 205 206 drm_panel_enable(priv->connector.panel); 207 208 drm_crtc_vblank_on(crtc); 209 } 210 211 void pl111_display_disable(struct drm_simple_display_pipe *pipe) 212 { 213 struct drm_crtc *crtc = &pipe->crtc; 214 struct drm_device *drm = crtc->dev; 215 struct pl111_drm_dev_private *priv = drm->dev_private; 216 217 drm_crtc_vblank_off(crtc); 218 219 drm_panel_disable(priv->connector.panel); 220 221 /* Disable and Power Down */ 222 writel(0, priv->regs + CLCD_PL111_CNTL); 223 224 drm_panel_unprepare(priv->connector.panel); 225 226 clk_disable_unprepare(priv->clk); 227 } 228 229 static void pl111_display_update(struct drm_simple_display_pipe *pipe, 230 struct drm_plane_state *old_pstate) 231 { 232 struct drm_crtc *crtc = &pipe->crtc; 233 struct drm_device *drm = crtc->dev; 234 struct pl111_drm_dev_private *priv = drm->dev_private; 235 struct drm_pending_vblank_event *event = crtc->state->event; 236 struct drm_plane *plane = &pipe->plane; 237 struct drm_plane_state *pstate = plane->state; 238 struct drm_framebuffer *fb = pstate->fb; 239 240 if (fb) { 241 u32 addr = drm_fb_cma_get_gem_addr(fb, pstate, 0); 242 243 writel(addr, priv->regs + CLCD_UBAS); 244 } 245 246 if (event) { 247 crtc->state->event = NULL; 248 249 spin_lock_irq(&crtc->dev->event_lock); 250 if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) 251 drm_crtc_arm_vblank_event(crtc, event); 252 else 253 drm_crtc_send_vblank_event(crtc, event); 254 spin_unlock_irq(&crtc->dev->event_lock); 255 } 256 } 257 258 int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc) 259 { 260 struct pl111_drm_dev_private *priv = drm->dev_private; 261 262 writel(CLCD_IRQ_NEXTBASE_UPDATE, priv->regs + CLCD_PL111_IENB); 263 264 return 0; 265 } 266 267 void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc) 268 { 269 struct pl111_drm_dev_private *priv = drm->dev_private; 270 271 writel(0, priv->regs + CLCD_PL111_IENB); 272 } 273 274 static int pl111_display_prepare_fb(struct drm_simple_display_pipe *pipe, 275 struct drm_plane_state *plane_state) 276 { 277 return drm_fb_cma_prepare_fb(&pipe->plane, plane_state); 278 } 279 280 static const struct drm_simple_display_pipe_funcs pl111_display_funcs = { 281 .check = pl111_display_check, 282 .enable = pl111_display_enable, 283 .disable = pl111_display_disable, 284 .update = pl111_display_update, 285 .prepare_fb = pl111_display_prepare_fb, 286 }; 287 288 static int pl111_clk_div_choose_div(struct clk_hw *hw, unsigned long rate, 289 unsigned long *prate, bool set_parent) 290 { 291 int best_div = 1, div; 292 struct clk_hw *parent = clk_hw_get_parent(hw); 293 unsigned long best_prate = 0; 294 unsigned long best_diff = ~0ul; 295 int max_div = (1 << (TIM2_PCD_LO_BITS + TIM2_PCD_HI_BITS)) - 1; 296 297 for (div = 1; div < max_div; div++) { 298 unsigned long this_prate, div_rate, diff; 299 300 if (set_parent) 301 this_prate = clk_hw_round_rate(parent, rate * div); 302 else 303 this_prate = *prate; 304 div_rate = DIV_ROUND_UP_ULL(this_prate, div); 305 diff = abs(rate - div_rate); 306 307 if (diff < best_diff) { 308 best_div = div; 309 best_diff = diff; 310 best_prate = this_prate; 311 } 312 } 313 314 *prate = best_prate; 315 return best_div; 316 } 317 318 static long pl111_clk_div_round_rate(struct clk_hw *hw, unsigned long rate, 319 unsigned long *prate) 320 { 321 int div = pl111_clk_div_choose_div(hw, rate, prate, true); 322 323 return DIV_ROUND_UP_ULL(*prate, div); 324 } 325 326 static unsigned long pl111_clk_div_recalc_rate(struct clk_hw *hw, 327 unsigned long prate) 328 { 329 struct pl111_drm_dev_private *priv = 330 container_of(hw, struct pl111_drm_dev_private, clk_div); 331 u32 tim2 = readl(priv->regs + CLCD_TIM2); 332 int div; 333 334 if (tim2 & TIM2_BCD) 335 return prate; 336 337 div = tim2 & TIM2_PCD_LO_MASK; 338 div |= (tim2 & TIM2_PCD_HI_MASK) >> 339 (TIM2_PCD_HI_SHIFT - TIM2_PCD_LO_BITS); 340 div += 2; 341 342 return DIV_ROUND_UP_ULL(prate, div); 343 } 344 345 static int pl111_clk_div_set_rate(struct clk_hw *hw, unsigned long rate, 346 unsigned long prate) 347 { 348 struct pl111_drm_dev_private *priv = 349 container_of(hw, struct pl111_drm_dev_private, clk_div); 350 int div = pl111_clk_div_choose_div(hw, rate, &prate, false); 351 u32 tim2; 352 353 spin_lock(&priv->tim2_lock); 354 tim2 = readl(priv->regs + CLCD_TIM2); 355 tim2 &= ~(TIM2_BCD | TIM2_PCD_LO_MASK | TIM2_PCD_HI_MASK); 356 357 if (div == 1) { 358 tim2 |= TIM2_BCD; 359 } else { 360 div -= 2; 361 tim2 |= div & TIM2_PCD_LO_MASK; 362 tim2 |= (div >> TIM2_PCD_LO_BITS) << TIM2_PCD_HI_SHIFT; 363 } 364 365 writel(tim2, priv->regs + CLCD_TIM2); 366 spin_unlock(&priv->tim2_lock); 367 368 return 0; 369 } 370 371 static const struct clk_ops pl111_clk_div_ops = { 372 .recalc_rate = pl111_clk_div_recalc_rate, 373 .round_rate = pl111_clk_div_round_rate, 374 .set_rate = pl111_clk_div_set_rate, 375 }; 376 377 static int 378 pl111_init_clock_divider(struct drm_device *drm) 379 { 380 struct pl111_drm_dev_private *priv = drm->dev_private; 381 struct clk *parent = devm_clk_get(drm->dev, "clcdclk"); 382 struct clk_hw *div = &priv->clk_div; 383 const char *parent_name; 384 struct clk_init_data init = { 385 .name = "pl111_div", 386 .ops = &pl111_clk_div_ops, 387 .parent_names = &parent_name, 388 .num_parents = 1, 389 .flags = CLK_SET_RATE_PARENT, 390 }; 391 int ret; 392 393 if (IS_ERR(parent)) { 394 dev_err(drm->dev, "CLCD: unable to get clcdclk.\n"); 395 return PTR_ERR(parent); 396 } 397 parent_name = __clk_get_name(parent); 398 399 spin_lock_init(&priv->tim2_lock); 400 div->init = &init; 401 402 ret = devm_clk_hw_register(drm->dev, div); 403 404 priv->clk = div->clk; 405 return ret; 406 } 407 408 int pl111_display_init(struct drm_device *drm) 409 { 410 struct pl111_drm_dev_private *priv = drm->dev_private; 411 struct device *dev = drm->dev; 412 struct device_node *endpoint; 413 u32 tft_r0b0g0[3]; 414 int ret; 415 static const u32 formats[] = { 416 DRM_FORMAT_ABGR8888, 417 DRM_FORMAT_XBGR8888, 418 DRM_FORMAT_ARGB8888, 419 DRM_FORMAT_XRGB8888, 420 DRM_FORMAT_BGR565, 421 DRM_FORMAT_RGB565, 422 DRM_FORMAT_ABGR1555, 423 DRM_FORMAT_XBGR1555, 424 DRM_FORMAT_ARGB1555, 425 DRM_FORMAT_XRGB1555, 426 DRM_FORMAT_ABGR4444, 427 DRM_FORMAT_XBGR4444, 428 DRM_FORMAT_ARGB4444, 429 DRM_FORMAT_XRGB4444, 430 }; 431 432 endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); 433 if (!endpoint) 434 return -ENODEV; 435 436 if (of_property_read_u32_array(endpoint, 437 "arm,pl11x,tft-r0g0b0-pads", 438 tft_r0b0g0, 439 ARRAY_SIZE(tft_r0b0g0)) != 0) { 440 dev_err(dev, "arm,pl11x,tft-r0g0b0-pads should be 3 ints\n"); 441 of_node_put(endpoint); 442 return -ENOENT; 443 } 444 of_node_put(endpoint); 445 446 if (tft_r0b0g0[0] != 0 || 447 tft_r0b0g0[1] != 8 || 448 tft_r0b0g0[2] != 16) { 449 dev_err(dev, "arm,pl11x,tft-r0g0b0-pads != [0,8,16] not yet supported\n"); 450 return -EINVAL; 451 } 452 453 ret = pl111_init_clock_divider(drm); 454 if (ret) 455 return ret; 456 457 ret = drm_simple_display_pipe_init(drm, &priv->pipe, 458 &pl111_display_funcs, 459 formats, ARRAY_SIZE(formats), 460 &priv->connector.connector); 461 if (ret) 462 return ret; 463 464 return 0; 465 } 466