Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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