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.13-rc2 448 lines 12 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 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 309 ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, 310 mode->flags & DRM_MODE_FLAG_INTERLACE, 311 imx_crtc_state->bus_format, mode->hdisplay); 312 ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg); 313} 314 315static const struct drm_crtc_helper_funcs ipu_helper_funcs = { 316 .mode_fixup = ipu_crtc_mode_fixup, 317 .mode_set_nofb = ipu_crtc_mode_set_nofb, 318 .atomic_check = ipu_crtc_atomic_check, 319 .atomic_begin = ipu_crtc_atomic_begin, 320 .atomic_flush = ipu_crtc_atomic_flush, 321 .atomic_disable = ipu_crtc_atomic_disable, 322 .atomic_enable = ipu_crtc_atomic_enable, 323}; 324 325static void ipu_put_resources(struct drm_device *dev, void *ptr) 326{ 327 struct ipu_crtc *ipu_crtc = ptr; 328 329 if (!IS_ERR_OR_NULL(ipu_crtc->dc)) 330 ipu_dc_put(ipu_crtc->dc); 331 if (!IS_ERR_OR_NULL(ipu_crtc->di)) 332 ipu_di_put(ipu_crtc->di); 333} 334 335static int ipu_get_resources(struct drm_device *dev, struct ipu_crtc *ipu_crtc, 336 struct ipu_client_platformdata *pdata) 337{ 338 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 339 int ret; 340 341 ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc); 342 if (IS_ERR(ipu_crtc->dc)) 343 return PTR_ERR(ipu_crtc->dc); 344 345 ret = drmm_add_action_or_reset(dev, ipu_put_resources, ipu_crtc); 346 if (ret) 347 return ret; 348 349 ipu_crtc->di = ipu_di_get(ipu, pdata->di); 350 if (IS_ERR(ipu_crtc->di)) 351 return PTR_ERR(ipu_crtc->di); 352 353 return 0; 354} 355 356static int ipu_drm_bind(struct device *dev, struct device *master, void *data) 357{ 358 struct ipu_client_platformdata *pdata = dev->platform_data; 359 struct ipu_soc *ipu = dev_get_drvdata(dev->parent); 360 struct drm_device *drm = data; 361 struct ipu_plane *primary_plane; 362 struct ipu_crtc *ipu_crtc; 363 struct drm_crtc *crtc; 364 int dp = -EINVAL; 365 int ret; 366 367 if (pdata->dp >= 0) 368 dp = IPU_DP_FLOW_SYNC_BG; 369 primary_plane = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0, 370 DRM_PLANE_TYPE_PRIMARY); 371 if (IS_ERR(primary_plane)) 372 return PTR_ERR(primary_plane); 373 374 ipu_crtc = drmm_crtc_alloc_with_planes(drm, struct ipu_crtc, base, 375 &primary_plane->base, NULL, 376 &ipu_crtc_funcs, NULL); 377 if (IS_ERR(ipu_crtc)) 378 return PTR_ERR(ipu_crtc); 379 380 ipu_crtc->dev = dev; 381 ipu_crtc->plane[0] = primary_plane; 382 383 crtc = &ipu_crtc->base; 384 crtc->port = pdata->of_node; 385 drm_crtc_helper_add(crtc, &ipu_helper_funcs); 386 387 ret = ipu_get_resources(drm, ipu_crtc, pdata); 388 if (ret) { 389 dev_err(ipu_crtc->dev, "getting resources failed with %d.\n", 390 ret); 391 return ret; 392 } 393 394 /* If this crtc is using the DP, add an overlay plane */ 395 if (pdata->dp >= 0 && pdata->dma[1] > 0) { 396 ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1], 397 IPU_DP_FLOW_SYNC_FG, 398 drm_crtc_mask(&ipu_crtc->base), 399 DRM_PLANE_TYPE_OVERLAY); 400 if (IS_ERR(ipu_crtc->plane[1])) 401 ipu_crtc->plane[1] = NULL; 402 } 403 404 ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]); 405 ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0, 406 "imx_drm", ipu_crtc); 407 if (ret < 0) { 408 dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); 409 return ret; 410 } 411 /* Only enable IRQ when we actually need it to trigger work. */ 412 disable_irq(ipu_crtc->irq); 413 414 return 0; 415} 416 417static const struct component_ops ipu_crtc_ops = { 418 .bind = ipu_drm_bind, 419}; 420 421static int ipu_drm_probe(struct platform_device *pdev) 422{ 423 struct device *dev = &pdev->dev; 424 int ret; 425 426 if (!dev->platform_data) 427 return -EINVAL; 428 429 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); 430 if (ret) 431 return ret; 432 433 return component_add(dev, &ipu_crtc_ops); 434} 435 436static int ipu_drm_remove(struct platform_device *pdev) 437{ 438 component_del(&pdev->dev, &ipu_crtc_ops); 439 return 0; 440} 441 442struct platform_driver ipu_drm_driver = { 443 .driver = { 444 .name = "imx-ipuv3-crtc", 445 }, 446 .probe = ipu_drm_probe, 447 .remove = ipu_drm_remove, 448};