ipuv3-crtc.c (12175B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * i.MX IPUv3 Graphics driver 4 * 5 * Copyright (C) 2011 Sascha Hauer, Pengutronix 6 */ 7 8#include <linux/clk.h> 9#include <linux/component.h> 10#include <linux/device.h> 11#include <linux/dma-mapping.h> 12#include <linux/errno.h> 13#include <linux/export.h> 14#include <linux/module.h> 15#include <linux/platform_device.h> 16 17#include <video/imx-ipu-v3.h> 18 19#include <drm/drm_atomic.h> 20#include <drm/drm_atomic_helper.h> 21#include <drm/drm_fb_cma_helper.h> 22#include <drm/drm_gem_cma_helper.h> 23#include <drm/drm_managed.h> 24#include <drm/drm_probe_helper.h> 25#include <drm/drm_vblank.h> 26 27#include "imx-drm.h" 28#include "ipuv3-plane.h" 29 30#define DRIVER_DESC "i.MX IPUv3 Graphics" 31 32struct ipu_crtc { 33 struct device *dev; 34 struct drm_crtc base; 35 36 /* plane[0] is the full plane, plane[1] is the partial plane */ 37 struct ipu_plane *plane[2]; 38 39 struct ipu_dc *dc; 40 struct ipu_di *di; 41 int irq; 42 struct drm_pending_vblank_event *event; 43}; 44 45static inline struct ipu_crtc *to_ipu_crtc(struct drm_crtc *crtc) 46{ 47 return container_of(crtc, struct ipu_crtc, base); 48} 49 50static void ipu_crtc_atomic_enable(struct drm_crtc *crtc, 51 struct drm_atomic_state *state) 52{ 53 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 54 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 55 56 ipu_prg_enable(ipu); 57 ipu_dc_enable(ipu); 58 ipu_dc_enable_channel(ipu_crtc->dc); 59 ipu_di_enable(ipu_crtc->di); 60} 61 62static void ipu_crtc_disable_planes(struct ipu_crtc *ipu_crtc, 63 struct drm_crtc_state *old_crtc_state) 64{ 65 bool disable_partial = false; 66 bool disable_full = false; 67 struct drm_plane *plane; 68 69 drm_atomic_crtc_state_for_each_plane(plane, old_crtc_state) { 70 if (plane == &ipu_crtc->plane[0]->base) 71 disable_full = true; 72 if (ipu_crtc->plane[1] && plane == &ipu_crtc->plane[1]->base) 73 disable_partial = true; 74 } 75 76 if (disable_partial) 77 ipu_plane_disable(ipu_crtc->plane[1], true); 78 if (disable_full) 79 ipu_plane_disable(ipu_crtc->plane[0], true); 80} 81 82static void ipu_crtc_atomic_disable(struct drm_crtc *crtc, 83 struct drm_atomic_state *state) 84{ 85 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, 86 crtc); 87 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 88 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 89 90 ipu_dc_disable_channel(ipu_crtc->dc); 91 ipu_di_disable(ipu_crtc->di); 92 /* 93 * Planes must be disabled before DC clock is removed, as otherwise the 94 * attached IDMACs will be left in undefined state, possibly hanging 95 * the IPU or even system. 96 */ 97 ipu_crtc_disable_planes(ipu_crtc, old_crtc_state); 98 ipu_dc_disable(ipu); 99 ipu_prg_disable(ipu); 100 101 drm_crtc_vblank_off(crtc); 102 103 spin_lock_irq(&crtc->dev->event_lock); 104 if (crtc->state->event && !crtc->state->active) { 105 drm_crtc_send_vblank_event(crtc, crtc->state->event); 106 crtc->state->event = NULL; 107 } 108 spin_unlock_irq(&crtc->dev->event_lock); 109} 110 111static void imx_drm_crtc_reset(struct drm_crtc *crtc) 112{ 113 struct imx_crtc_state *state; 114 115 if (crtc->state) 116 __drm_atomic_helper_crtc_destroy_state(crtc->state); 117 118 kfree(to_imx_crtc_state(crtc->state)); 119 crtc->state = NULL; 120 121 state = kzalloc(sizeof(*state), GFP_KERNEL); 122 if (state) 123 __drm_atomic_helper_crtc_reset(crtc, &state->base); 124} 125 126static struct drm_crtc_state *imx_drm_crtc_duplicate_state(struct drm_crtc *crtc) 127{ 128 struct imx_crtc_state *state; 129 130 state = kzalloc(sizeof(*state), GFP_KERNEL); 131 if (!state) 132 return NULL; 133 134 __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); 135 136 WARN_ON(state->base.crtc != crtc); 137 state->base.crtc = crtc; 138 139 return &state->base; 140} 141 142static void imx_drm_crtc_destroy_state(struct drm_crtc *crtc, 143 struct drm_crtc_state *state) 144{ 145 __drm_atomic_helper_crtc_destroy_state(state); 146 kfree(to_imx_crtc_state(state)); 147} 148 149static int ipu_enable_vblank(struct drm_crtc *crtc) 150{ 151 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 152 153 enable_irq(ipu_crtc->irq); 154 155 return 0; 156} 157 158static void ipu_disable_vblank(struct drm_crtc *crtc) 159{ 160 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 161 162 disable_irq_nosync(ipu_crtc->irq); 163} 164 165static const struct drm_crtc_funcs ipu_crtc_funcs = { 166 .set_config = drm_atomic_helper_set_config, 167 .page_flip = drm_atomic_helper_page_flip, 168 .reset = imx_drm_crtc_reset, 169 .atomic_duplicate_state = imx_drm_crtc_duplicate_state, 170 .atomic_destroy_state = imx_drm_crtc_destroy_state, 171 .enable_vblank = ipu_enable_vblank, 172 .disable_vblank = ipu_disable_vblank, 173}; 174 175static irqreturn_t ipu_irq_handler(int irq, void *dev_id) 176{ 177 struct ipu_crtc *ipu_crtc = dev_id; 178 struct drm_crtc *crtc = &ipu_crtc->base; 179 unsigned long flags; 180 int i; 181 182 drm_crtc_handle_vblank(crtc); 183 184 if (ipu_crtc->event) { 185 for (i = 0; i < ARRAY_SIZE(ipu_crtc->plane); i++) { 186 struct ipu_plane *plane = ipu_crtc->plane[i]; 187 188 if (!plane) 189 continue; 190 191 if (ipu_plane_atomic_update_pending(&plane->base)) 192 break; 193 } 194 195 if (i == ARRAY_SIZE(ipu_crtc->plane)) { 196 spin_lock_irqsave(&crtc->dev->event_lock, flags); 197 drm_crtc_send_vblank_event(crtc, ipu_crtc->event); 198 ipu_crtc->event = NULL; 199 drm_crtc_vblank_put(crtc); 200 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); 201 } 202 } 203 204 return IRQ_HANDLED; 205} 206 207static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc, 208 const struct drm_display_mode *mode, 209 struct drm_display_mode *adjusted_mode) 210{ 211 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 212 struct videomode vm; 213 int ret; 214 215 drm_display_mode_to_videomode(adjusted_mode, &vm); 216 217 ret = ipu_di_adjust_videomode(ipu_crtc->di, &vm); 218 if (ret) 219 return false; 220 221 if ((vm.vsync_len == 0) || (vm.hsync_len == 0)) 222 return false; 223 224 drm_display_mode_from_videomode(&vm, adjusted_mode); 225 226 return true; 227} 228 229static int ipu_crtc_atomic_check(struct drm_crtc *crtc, 230 struct drm_atomic_state *state) 231{ 232 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, 233 crtc); 234 u32 primary_plane_mask = drm_plane_mask(crtc->primary); 235 236 if (crtc_state->active && (primary_plane_mask & crtc_state->plane_mask) == 0) 237 return -EINVAL; 238 239 return 0; 240} 241 242static void ipu_crtc_atomic_begin(struct drm_crtc *crtc, 243 struct drm_atomic_state *state) 244{ 245 drm_crtc_vblank_on(crtc); 246} 247 248static void ipu_crtc_atomic_flush(struct drm_crtc *crtc, 249 struct drm_atomic_state *state) 250{ 251 spin_lock_irq(&crtc->dev->event_lock); 252 if (crtc->state->event) { 253 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 254 255 WARN_ON(drm_crtc_vblank_get(crtc)); 256 ipu_crtc->event = crtc->state->event; 257 crtc->state->event = NULL; 258 } 259 spin_unlock_irq(&crtc->dev->event_lock); 260} 261 262static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc) 263{ 264 struct drm_device *dev = crtc->dev; 265 struct drm_encoder *encoder; 266 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 267 struct drm_display_mode *mode = &crtc->state->adjusted_mode; 268 struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc->state); 269 struct ipu_di_signal_cfg sig_cfg = {}; 270 unsigned long encoder_types = 0; 271 272 dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, 273 mode->hdisplay); 274 dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, 275 mode->vdisplay); 276 277 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 278 if (encoder->crtc == crtc) 279 encoder_types |= BIT(encoder->encoder_type); 280 } 281 282 dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n", 283 __func__, encoder_types); 284 285 /* 286 * If we have DAC or LDB, then we need the IPU DI clock to be 287 * the same as the LDB DI clock. For TVDAC, derive the IPU DI 288 * clock from 27 MHz TVE_DI clock, but allow to divide it. 289 */ 290 if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) | 291 BIT(DRM_MODE_ENCODER_LVDS))) 292 sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT; 293 else if (encoder_types & BIT(DRM_MODE_ENCODER_TVDAC)) 294 sig_cfg.clkflags = IPU_DI_CLKMODE_EXT; 295 else 296 sig_cfg.clkflags = 0; 297 298 sig_cfg.enable_pol = !(imx_crtc_state->bus_flags & DRM_BUS_FLAG_DE_LOW); 299 /* Default to driving pixel data on negative clock edges */ 300 sig_cfg.clk_pol = !!(imx_crtc_state->bus_flags & 301 DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE); 302 sig_cfg.bus_format = imx_crtc_state->bus_format; 303 sig_cfg.v_to_h_sync = 0; 304 sig_cfg.hsync_pin = imx_crtc_state->di_hsync_pin; 305 sig_cfg.vsync_pin = imx_crtc_state->di_vsync_pin; 306 307 drm_display_mode_to_videomode(mode, &sig_cfg.mode); 308 if (!IS_ALIGNED(sig_cfg.mode.hactive, 8)) { 309 unsigned int new_hactive = ALIGN(sig_cfg.mode.hactive, 8); 310 311 dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n", 312 sig_cfg.mode.hactive, new_hactive); 313 314 sig_cfg.mode.hfront_porch = new_hactive - sig_cfg.mode.hactive; 315 sig_cfg.mode.hactive = new_hactive; 316 } 317 318 ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, 319 mode->flags & DRM_MODE_FLAG_INTERLACE, 320 imx_crtc_state->bus_format, sig_cfg.mode.hactive); 321 ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg); 322} 323 324static const struct drm_crtc_helper_funcs ipu_helper_funcs = { 325 .mode_fixup = ipu_crtc_mode_fixup, 326 .mode_set_nofb = ipu_crtc_mode_set_nofb, 327 .atomic_check = ipu_crtc_atomic_check, 328 .atomic_begin = ipu_crtc_atomic_begin, 329 .atomic_flush = ipu_crtc_atomic_flush, 330 .atomic_disable = ipu_crtc_atomic_disable, 331 .atomic_enable = ipu_crtc_atomic_enable, 332}; 333 334static void ipu_put_resources(struct drm_device *dev, void *ptr) 335{ 336 struct ipu_crtc *ipu_crtc = ptr; 337 338 if (!IS_ERR_OR_NULL(ipu_crtc->dc)) 339 ipu_dc_put(ipu_crtc->dc); 340 if (!IS_ERR_OR_NULL(ipu_crtc->di)) 341 ipu_di_put(ipu_crtc->di); 342} 343 344static int ipu_get_resources(struct drm_device *dev, struct ipu_crtc *ipu_crtc, 345 struct ipu_client_platformdata *pdata) 346{ 347 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 348 int ret; 349 350 ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc); 351 if (IS_ERR(ipu_crtc->dc)) 352 return PTR_ERR(ipu_crtc->dc); 353 354 ret = drmm_add_action_or_reset(dev, ipu_put_resources, ipu_crtc); 355 if (ret) 356 return ret; 357 358 ipu_crtc->di = ipu_di_get(ipu, pdata->di); 359 if (IS_ERR(ipu_crtc->di)) 360 return PTR_ERR(ipu_crtc->di); 361 362 return 0; 363} 364 365static int ipu_drm_bind(struct device *dev, struct device *master, void *data) 366{ 367 struct ipu_client_platformdata *pdata = dev->platform_data; 368 struct ipu_soc *ipu = dev_get_drvdata(dev->parent); 369 struct drm_device *drm = data; 370 struct ipu_plane *primary_plane; 371 struct ipu_crtc *ipu_crtc; 372 struct drm_crtc *crtc; 373 int dp = -EINVAL; 374 int ret; 375 376 if (pdata->dp >= 0) 377 dp = IPU_DP_FLOW_SYNC_BG; 378 primary_plane = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0, 379 DRM_PLANE_TYPE_PRIMARY); 380 if (IS_ERR(primary_plane)) 381 return PTR_ERR(primary_plane); 382 383 ipu_crtc = drmm_crtc_alloc_with_planes(drm, struct ipu_crtc, base, 384 &primary_plane->base, NULL, 385 &ipu_crtc_funcs, NULL); 386 if (IS_ERR(ipu_crtc)) 387 return PTR_ERR(ipu_crtc); 388 389 ipu_crtc->dev = dev; 390 ipu_crtc->plane[0] = primary_plane; 391 392 crtc = &ipu_crtc->base; 393 crtc->port = pdata->of_node; 394 drm_crtc_helper_add(crtc, &ipu_helper_funcs); 395 396 ret = ipu_get_resources(drm, ipu_crtc, pdata); 397 if (ret) { 398 dev_err(ipu_crtc->dev, "getting resources failed with %d.\n", 399 ret); 400 return ret; 401 } 402 403 /* If this crtc is using the DP, add an overlay plane */ 404 if (pdata->dp >= 0 && pdata->dma[1] > 0) { 405 ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1], 406 IPU_DP_FLOW_SYNC_FG, 407 drm_crtc_mask(&ipu_crtc->base), 408 DRM_PLANE_TYPE_OVERLAY); 409 if (IS_ERR(ipu_crtc->plane[1])) 410 ipu_crtc->plane[1] = NULL; 411 } 412 413 ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]); 414 ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0, 415 "imx_drm", ipu_crtc); 416 if (ret < 0) { 417 dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); 418 return ret; 419 } 420 /* Only enable IRQ when we actually need it to trigger work. */ 421 disable_irq(ipu_crtc->irq); 422 423 return 0; 424} 425 426static const struct component_ops ipu_crtc_ops = { 427 .bind = ipu_drm_bind, 428}; 429 430static int ipu_drm_probe(struct platform_device *pdev) 431{ 432 struct device *dev = &pdev->dev; 433 int ret; 434 435 if (!dev->platform_data) 436 return -EINVAL; 437 438 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); 439 if (ret) 440 return ret; 441 442 return component_add(dev, &ipu_crtc_ops); 443} 444 445static int ipu_drm_remove(struct platform_device *pdev) 446{ 447 component_del(&pdev->dev, &ipu_crtc_ops); 448 return 0; 449} 450 451struct platform_driver ipu_drm_driver = { 452 .driver = { 453 .name = "imx-ipuv3-crtc", 454 }, 455 .probe = ipu_drm_probe, 456 .remove = ipu_drm_remove, 457};