1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Ingenic JZ47xx KMS driver 4 // 5 // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net> 6 7 #include "ingenic-drm.h" 8 9 #include <linux/component.h> 10 #include <linux/clk.h> 11 #include <linux/dma-mapping.h> 12 #include <linux/module.h> 13 #include <linux/mutex.h> 14 #include <linux/of_device.h> 15 #include <linux/of_reserved_mem.h> 16 #include <linux/platform_device.h> 17 #include <linux/regmap.h> 18 19 #include <drm/drm_atomic.h> 20 #include <drm/drm_atomic_helper.h> 21 #include <drm/drm_bridge.h> 22 #include <drm/drm_color_mgmt.h> 23 #include <drm/drm_crtc.h> 24 #include <drm/drm_crtc_helper.h> 25 #include <drm/drm_drv.h> 26 #include <drm/drm_gem_cma_helper.h> 27 #include <drm/drm_fb_cma_helper.h> 28 #include <drm/drm_fb_helper.h> 29 #include <drm/drm_fourcc.h> 30 #include <drm/drm_gem_framebuffer_helper.h> 31 #include <drm/drm_irq.h> 32 #include <drm/drm_managed.h> 33 #include <drm/drm_of.h> 34 #include <drm/drm_panel.h> 35 #include <drm/drm_plane.h> 36 #include <drm/drm_plane_helper.h> 37 #include <drm/drm_probe_helper.h> 38 #include <drm/drm_simple_kms_helper.h> 39 #include <drm/drm_vblank.h> 40 41 struct ingenic_dma_hwdesc { 42 u32 next; 43 u32 addr; 44 u32 id; 45 u32 cmd; 46 } __aligned(16); 47 48 struct ingenic_dma_hwdescs { 49 struct ingenic_dma_hwdesc hwdesc_f0; 50 struct ingenic_dma_hwdesc hwdesc_f1; 51 struct ingenic_dma_hwdesc hwdesc_pal; 52 u16 palette[256] __aligned(16); 53 }; 54 55 struct jz_soc_info { 56 bool needs_dev_clk; 57 bool has_osd; 58 unsigned int max_width, max_height; 59 const u32 *formats_f0, *formats_f1; 60 unsigned int num_formats_f0, num_formats_f1; 61 }; 62 63 struct ingenic_drm { 64 struct drm_device drm; 65 /* 66 * f1 (aka. foreground1) is our primary plane, on top of which 67 * f0 (aka. foreground0) can be overlayed. Z-order is fixed in 68 * hardware and cannot be changed. 69 */ 70 struct drm_plane f0, f1, *ipu_plane; 71 struct drm_crtc crtc; 72 73 struct device *dev; 74 struct regmap *map; 75 struct clk *lcd_clk, *pix_clk; 76 const struct jz_soc_info *soc_info; 77 78 struct ingenic_dma_hwdescs *dma_hwdescs; 79 dma_addr_t dma_hwdescs_phys; 80 81 bool panel_is_sharp; 82 bool no_vblank; 83 84 /* 85 * clk_mutex is used to synchronize the pixel clock rate update with 86 * the VBLANK. When the pixel clock's parent clock needs to be updated, 87 * clock_nb's notifier function will lock the mutex, then wait until the 88 * next VBLANK. At that point, the parent clock's rate can be updated, 89 * and the mutex is then unlocked. If an atomic commit happens in the 90 * meantime, it will lock on the mutex, effectively waiting until the 91 * clock update process finishes. Finally, the pixel clock's rate will 92 * be recomputed when the mutex has been released, in the pending atomic 93 * commit, or a future one. 94 */ 95 struct mutex clk_mutex; 96 bool update_clk_rate; 97 struct notifier_block clock_nb; 98 }; 99 100 static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg) 101 { 102 switch (reg) { 103 case JZ_REG_LCD_IID: 104 case JZ_REG_LCD_SA0: 105 case JZ_REG_LCD_FID0: 106 case JZ_REG_LCD_CMD0: 107 case JZ_REG_LCD_SA1: 108 case JZ_REG_LCD_FID1: 109 case JZ_REG_LCD_CMD1: 110 return false; 111 default: 112 return true; 113 } 114 } 115 116 static const struct regmap_config ingenic_drm_regmap_config = { 117 .reg_bits = 32, 118 .val_bits = 32, 119 .reg_stride = 4, 120 121 .max_register = JZ_REG_LCD_SIZE1, 122 .writeable_reg = ingenic_drm_writeable_reg, 123 }; 124 125 static inline struct ingenic_drm *drm_device_get_priv(struct drm_device *drm) 126 { 127 return container_of(drm, struct ingenic_drm, drm); 128 } 129 130 static inline struct ingenic_drm *drm_crtc_get_priv(struct drm_crtc *crtc) 131 { 132 return container_of(crtc, struct ingenic_drm, crtc); 133 } 134 135 static inline struct ingenic_drm *drm_nb_get_priv(struct notifier_block *nb) 136 { 137 return container_of(nb, struct ingenic_drm, clock_nb); 138 } 139 140 static int ingenic_drm_update_pixclk(struct notifier_block *nb, 141 unsigned long action, 142 void *data) 143 { 144 struct ingenic_drm *priv = drm_nb_get_priv(nb); 145 146 switch (action) { 147 case PRE_RATE_CHANGE: 148 mutex_lock(&priv->clk_mutex); 149 priv->update_clk_rate = true; 150 drm_crtc_wait_one_vblank(&priv->crtc); 151 return NOTIFY_OK; 152 default: 153 mutex_unlock(&priv->clk_mutex); 154 return NOTIFY_OK; 155 } 156 } 157 158 static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, 159 struct drm_atomic_state *state) 160 { 161 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 162 163 regmap_write(priv->map, JZ_REG_LCD_STATE, 0); 164 165 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, 166 JZ_LCD_CTRL_ENABLE | JZ_LCD_CTRL_DISABLE, 167 JZ_LCD_CTRL_ENABLE); 168 169 drm_crtc_vblank_on(crtc); 170 } 171 172 static void ingenic_drm_crtc_atomic_disable(struct drm_crtc *crtc, 173 struct drm_atomic_state *state) 174 { 175 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 176 unsigned int var; 177 178 drm_crtc_vblank_off(crtc); 179 180 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, 181 JZ_LCD_CTRL_DISABLE, JZ_LCD_CTRL_DISABLE); 182 183 regmap_read_poll_timeout(priv->map, JZ_REG_LCD_STATE, var, 184 var & JZ_LCD_STATE_DISABLED, 185 1000, 0); 186 } 187 188 static void ingenic_drm_crtc_update_timings(struct ingenic_drm *priv, 189 struct drm_display_mode *mode) 190 { 191 unsigned int vpe, vds, vde, vt, hpe, hds, hde, ht; 192 193 vpe = mode->vsync_end - mode->vsync_start; 194 vds = mode->vtotal - mode->vsync_start; 195 vde = vds + mode->vdisplay; 196 vt = vde + mode->vsync_start - mode->vdisplay; 197 198 hpe = mode->hsync_end - mode->hsync_start; 199 hds = mode->htotal - mode->hsync_start; 200 hde = hds + mode->hdisplay; 201 ht = hde + mode->hsync_start - mode->hdisplay; 202 203 regmap_write(priv->map, JZ_REG_LCD_VSYNC, 204 0 << JZ_LCD_VSYNC_VPS_OFFSET | 205 vpe << JZ_LCD_VSYNC_VPE_OFFSET); 206 207 regmap_write(priv->map, JZ_REG_LCD_HSYNC, 208 0 << JZ_LCD_HSYNC_HPS_OFFSET | 209 hpe << JZ_LCD_HSYNC_HPE_OFFSET); 210 211 regmap_write(priv->map, JZ_REG_LCD_VAT, 212 ht << JZ_LCD_VAT_HT_OFFSET | 213 vt << JZ_LCD_VAT_VT_OFFSET); 214 215 regmap_write(priv->map, JZ_REG_LCD_DAH, 216 hds << JZ_LCD_DAH_HDS_OFFSET | 217 hde << JZ_LCD_DAH_HDE_OFFSET); 218 regmap_write(priv->map, JZ_REG_LCD_DAV, 219 vds << JZ_LCD_DAV_VDS_OFFSET | 220 vde << JZ_LCD_DAV_VDE_OFFSET); 221 222 if (priv->panel_is_sharp) { 223 regmap_write(priv->map, JZ_REG_LCD_PS, hde << 16 | (hde + 1)); 224 regmap_write(priv->map, JZ_REG_LCD_CLS, hde << 16 | (hde + 1)); 225 regmap_write(priv->map, JZ_REG_LCD_SPL, hpe << 16 | (hpe + 1)); 226 regmap_write(priv->map, JZ_REG_LCD_REV, mode->htotal << 16); 227 } 228 229 regmap_set_bits(priv->map, JZ_REG_LCD_CTRL, 230 JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16); 231 232 /* 233 * IPU restart - specify how much time the LCDC will wait before 234 * transferring a new frame from the IPU. The value is the one 235 * suggested in the programming manual. 236 */ 237 regmap_write(priv->map, JZ_REG_LCD_IPUR, JZ_LCD_IPUR_IPUREN | 238 (ht * vpe / 3) << JZ_LCD_IPUR_IPUR_LSB); 239 } 240 241 static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc, 242 struct drm_crtc_state *state) 243 { 244 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 245 struct drm_plane_state *f1_state, *f0_state, *ipu_state = NULL; 246 247 if (state->gamma_lut && 248 drm_color_lut_size(state->gamma_lut) != ARRAY_SIZE(priv->dma_hwdescs->palette)) { 249 dev_dbg(priv->dev, "Invalid palette size\n"); 250 return -EINVAL; 251 } 252 253 if (drm_atomic_crtc_needs_modeset(state) && priv->soc_info->has_osd) { 254 f1_state = drm_atomic_get_plane_state(state->state, &priv->f1); 255 if (IS_ERR(f1_state)) 256 return PTR_ERR(f1_state); 257 258 f0_state = drm_atomic_get_plane_state(state->state, &priv->f0); 259 if (IS_ERR(f0_state)) 260 return PTR_ERR(f0_state); 261 262 if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && priv->ipu_plane) { 263 ipu_state = drm_atomic_get_plane_state(state->state, priv->ipu_plane); 264 if (IS_ERR(ipu_state)) 265 return PTR_ERR(ipu_state); 266 267 /* IPU and F1 planes cannot be enabled at the same time. */ 268 if (f1_state->fb && ipu_state->fb) { 269 dev_dbg(priv->dev, "Cannot enable both F1 and IPU\n"); 270 return -EINVAL; 271 } 272 } 273 274 /* If all the planes are disabled, we won't get a VBLANK IRQ */ 275 priv->no_vblank = !f1_state->fb && !f0_state->fb && 276 !(ipu_state && ipu_state->fb); 277 } 278 279 return 0; 280 } 281 282 static enum drm_mode_status 283 ingenic_drm_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) 284 { 285 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 286 long rate; 287 288 if (mode->hdisplay > priv->soc_info->max_width) 289 return MODE_BAD_HVALUE; 290 if (mode->vdisplay > priv->soc_info->max_height) 291 return MODE_BAD_VVALUE; 292 293 rate = clk_round_rate(priv->pix_clk, mode->clock * 1000); 294 if (rate < 0) 295 return MODE_CLOCK_RANGE; 296 297 return MODE_OK; 298 } 299 300 static void ingenic_drm_crtc_atomic_begin(struct drm_crtc *crtc, 301 struct drm_crtc_state *oldstate) 302 { 303 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 304 u32 ctrl = 0; 305 306 if (priv->soc_info->has_osd && 307 drm_atomic_crtc_needs_modeset(crtc->state)) { 308 /* 309 * If IPU plane is enabled, enable IPU as source for the F1 310 * plane; otherwise use regular DMA. 311 */ 312 if (priv->ipu_plane && priv->ipu_plane->state->fb) 313 ctrl |= JZ_LCD_OSDCTRL_IPU; 314 315 regmap_update_bits(priv->map, JZ_REG_LCD_OSDCTRL, 316 JZ_LCD_OSDCTRL_IPU, ctrl); 317 } 318 } 319 320 static void ingenic_drm_crtc_atomic_flush(struct drm_crtc *crtc, 321 struct drm_crtc_state *oldstate) 322 { 323 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 324 struct drm_crtc_state *state = crtc->state; 325 struct drm_pending_vblank_event *event = state->event; 326 327 if (drm_atomic_crtc_needs_modeset(state)) { 328 ingenic_drm_crtc_update_timings(priv, &state->mode); 329 priv->update_clk_rate = true; 330 } 331 332 if (priv->update_clk_rate) { 333 mutex_lock(&priv->clk_mutex); 334 clk_set_rate(priv->pix_clk, state->adjusted_mode.clock * 1000); 335 priv->update_clk_rate = false; 336 mutex_unlock(&priv->clk_mutex); 337 } 338 339 if (event) { 340 state->event = NULL; 341 342 spin_lock_irq(&crtc->dev->event_lock); 343 if (drm_crtc_vblank_get(crtc) == 0) 344 drm_crtc_arm_vblank_event(crtc, event); 345 else 346 drm_crtc_send_vblank_event(crtc, event); 347 spin_unlock_irq(&crtc->dev->event_lock); 348 } 349 } 350 351 static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, 352 struct drm_plane_state *state) 353 { 354 struct ingenic_drm *priv = drm_device_get_priv(plane->dev); 355 struct drm_crtc_state *crtc_state; 356 struct drm_crtc *crtc = state->crtc ?: plane->state->crtc; 357 int ret; 358 359 if (!crtc) 360 return 0; 361 362 crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); 363 if (WARN_ON(!crtc_state)) 364 return -EINVAL; 365 366 ret = drm_atomic_helper_check_plane_state(state, crtc_state, 367 DRM_PLANE_HELPER_NO_SCALING, 368 DRM_PLANE_HELPER_NO_SCALING, 369 priv->soc_info->has_osd, 370 true); 371 if (ret) 372 return ret; 373 374 /* 375 * If OSD is not available, check that the width/height match. 376 * Note that state->src_* are in 16.16 fixed-point format. 377 */ 378 if (!priv->soc_info->has_osd && 379 (state->src_x != 0 || 380 (state->src_w >> 16) != state->crtc_w || 381 (state->src_h >> 16) != state->crtc_h)) 382 return -EINVAL; 383 384 /* 385 * Require full modeset if enabling or disabling a plane, or changing 386 * its position, size or depth. 387 */ 388 if (priv->soc_info->has_osd && 389 (!plane->state->fb || !state->fb || 390 plane->state->crtc_x != state->crtc_x || 391 plane->state->crtc_y != state->crtc_y || 392 plane->state->crtc_w != state->crtc_w || 393 plane->state->crtc_h != state->crtc_h || 394 plane->state->fb->format->format != state->fb->format->format)) 395 crtc_state->mode_changed = true; 396 397 return 0; 398 } 399 400 static void ingenic_drm_plane_enable(struct ingenic_drm *priv, 401 struct drm_plane *plane) 402 { 403 unsigned int en_bit; 404 405 if (priv->soc_info->has_osd) { 406 if (plane->type == DRM_PLANE_TYPE_PRIMARY) 407 en_bit = JZ_LCD_OSDC_F1EN; 408 else 409 en_bit = JZ_LCD_OSDC_F0EN; 410 411 regmap_set_bits(priv->map, JZ_REG_LCD_OSDC, en_bit); 412 } 413 } 414 415 void ingenic_drm_plane_disable(struct device *dev, struct drm_plane *plane) 416 { 417 struct ingenic_drm *priv = dev_get_drvdata(dev); 418 unsigned int en_bit; 419 420 if (priv->soc_info->has_osd) { 421 if (plane->type == DRM_PLANE_TYPE_PRIMARY) 422 en_bit = JZ_LCD_OSDC_F1EN; 423 else 424 en_bit = JZ_LCD_OSDC_F0EN; 425 426 regmap_clear_bits(priv->map, JZ_REG_LCD_OSDC, en_bit); 427 } 428 } 429 430 static void ingenic_drm_plane_atomic_disable(struct drm_plane *plane, 431 struct drm_plane_state *old_state) 432 { 433 struct ingenic_drm *priv = drm_device_get_priv(plane->dev); 434 435 ingenic_drm_plane_disable(priv->dev, plane); 436 } 437 438 void ingenic_drm_plane_config(struct device *dev, 439 struct drm_plane *plane, u32 fourcc) 440 { 441 struct ingenic_drm *priv = dev_get_drvdata(dev); 442 struct drm_plane_state *state = plane->state; 443 unsigned int xy_reg, size_reg; 444 unsigned int ctrl = 0; 445 446 ingenic_drm_plane_enable(priv, plane); 447 448 if (priv->soc_info->has_osd && 449 plane->type == DRM_PLANE_TYPE_PRIMARY) { 450 switch (fourcc) { 451 case DRM_FORMAT_XRGB1555: 452 ctrl |= JZ_LCD_OSDCTRL_RGB555; 453 fallthrough; 454 case DRM_FORMAT_RGB565: 455 ctrl |= JZ_LCD_OSDCTRL_BPP_15_16; 456 break; 457 case DRM_FORMAT_RGB888: 458 ctrl |= JZ_LCD_OSDCTRL_BPP_24_COMP; 459 break; 460 case DRM_FORMAT_XRGB8888: 461 ctrl |= JZ_LCD_OSDCTRL_BPP_18_24; 462 break; 463 case DRM_FORMAT_XRGB2101010: 464 ctrl |= JZ_LCD_OSDCTRL_BPP_30; 465 break; 466 } 467 468 regmap_update_bits(priv->map, JZ_REG_LCD_OSDCTRL, 469 JZ_LCD_OSDCTRL_BPP_MASK, ctrl); 470 } else { 471 switch (fourcc) { 472 case DRM_FORMAT_C8: 473 ctrl |= JZ_LCD_CTRL_BPP_8; 474 break; 475 case DRM_FORMAT_XRGB1555: 476 ctrl |= JZ_LCD_CTRL_RGB555; 477 fallthrough; 478 case DRM_FORMAT_RGB565: 479 ctrl |= JZ_LCD_CTRL_BPP_15_16; 480 break; 481 case DRM_FORMAT_RGB888: 482 ctrl |= JZ_LCD_CTRL_BPP_24_COMP; 483 break; 484 case DRM_FORMAT_XRGB8888: 485 ctrl |= JZ_LCD_CTRL_BPP_18_24; 486 break; 487 case DRM_FORMAT_XRGB2101010: 488 ctrl |= JZ_LCD_CTRL_BPP_30; 489 break; 490 } 491 492 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, 493 JZ_LCD_CTRL_BPP_MASK, ctrl); 494 } 495 496 if (priv->soc_info->has_osd) { 497 if (plane->type == DRM_PLANE_TYPE_PRIMARY) { 498 xy_reg = JZ_REG_LCD_XYP1; 499 size_reg = JZ_REG_LCD_SIZE1; 500 } else { 501 xy_reg = JZ_REG_LCD_XYP0; 502 size_reg = JZ_REG_LCD_SIZE0; 503 } 504 505 regmap_write(priv->map, xy_reg, 506 state->crtc_x << JZ_LCD_XYP01_XPOS_LSB | 507 state->crtc_y << JZ_LCD_XYP01_YPOS_LSB); 508 regmap_write(priv->map, size_reg, 509 state->crtc_w << JZ_LCD_SIZE01_WIDTH_LSB | 510 state->crtc_h << JZ_LCD_SIZE01_HEIGHT_LSB); 511 } 512 } 513 514 static void ingenic_drm_update_palette(struct ingenic_drm *priv, 515 const struct drm_color_lut *lut) 516 { 517 unsigned int i; 518 519 for (i = 0; i < ARRAY_SIZE(priv->dma_hwdescs->palette); i++) { 520 u16 color = drm_color_lut_extract(lut[i].red, 5) << 11 521 | drm_color_lut_extract(lut[i].green, 6) << 5 522 | drm_color_lut_extract(lut[i].blue, 5); 523 524 priv->dma_hwdescs->palette[i] = color; 525 } 526 } 527 528 static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, 529 struct drm_plane_state *oldstate) 530 { 531 struct ingenic_drm *priv = drm_device_get_priv(plane->dev); 532 struct drm_plane_state *state = plane->state; 533 struct drm_crtc_state *crtc_state; 534 struct ingenic_dma_hwdesc *hwdesc; 535 unsigned int width, height, cpp, offset; 536 dma_addr_t addr; 537 u32 fourcc; 538 539 if (state && state->fb) { 540 crtc_state = state->crtc->state; 541 542 addr = drm_fb_cma_get_gem_addr(state->fb, state, 0); 543 width = state->src_w >> 16; 544 height = state->src_h >> 16; 545 cpp = state->fb->format->cpp[0]; 546 547 if (priv->soc_info->has_osd && plane->type == DRM_PLANE_TYPE_OVERLAY) 548 hwdesc = &priv->dma_hwdescs->hwdesc_f0; 549 else 550 hwdesc = &priv->dma_hwdescs->hwdesc_f1; 551 552 hwdesc->addr = addr; 553 hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); 554 555 if (drm_atomic_crtc_needs_modeset(crtc_state)) { 556 fourcc = state->fb->format->format; 557 558 ingenic_drm_plane_config(priv->dev, plane, fourcc); 559 560 if (fourcc == DRM_FORMAT_C8) 561 offset = offsetof(struct ingenic_dma_hwdescs, hwdesc_pal); 562 else 563 offset = offsetof(struct ingenic_dma_hwdescs, hwdesc_f0); 564 565 priv->dma_hwdescs->hwdesc_f0.next = priv->dma_hwdescs_phys + offset; 566 567 crtc_state->color_mgmt_changed = fourcc == DRM_FORMAT_C8; 568 } 569 570 if (crtc_state->color_mgmt_changed) 571 ingenic_drm_update_palette(priv, crtc_state->gamma_lut->data); 572 } 573 } 574 575 static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, 576 struct drm_crtc_state *crtc_state, 577 struct drm_connector_state *conn_state) 578 { 579 struct ingenic_drm *priv = drm_device_get_priv(encoder->dev); 580 struct drm_display_mode *mode = &crtc_state->adjusted_mode; 581 struct drm_connector *conn = conn_state->connector; 582 struct drm_display_info *info = &conn->display_info; 583 unsigned int cfg; 584 585 priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS; 586 587 if (priv->panel_is_sharp) { 588 cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY; 589 } else { 590 cfg = JZ_LCD_CFG_PS_DISABLE | JZ_LCD_CFG_CLS_DISABLE 591 | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE; 592 } 593 594 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 595 cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; 596 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 597 cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW; 598 if (info->bus_flags & DRM_BUS_FLAG_DE_LOW) 599 cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW; 600 if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) 601 cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; 602 603 if (!priv->panel_is_sharp) { 604 if (conn->connector_type == DRM_MODE_CONNECTOR_TV) { 605 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 606 cfg |= JZ_LCD_CFG_MODE_TV_OUT_I; 607 else 608 cfg |= JZ_LCD_CFG_MODE_TV_OUT_P; 609 } else { 610 switch (*info->bus_formats) { 611 case MEDIA_BUS_FMT_RGB565_1X16: 612 cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT; 613 break; 614 case MEDIA_BUS_FMT_RGB666_1X18: 615 cfg |= JZ_LCD_CFG_MODE_GENERIC_18BIT; 616 break; 617 case MEDIA_BUS_FMT_RGB888_1X24: 618 cfg |= JZ_LCD_CFG_MODE_GENERIC_24BIT; 619 break; 620 case MEDIA_BUS_FMT_RGB888_3X8: 621 cfg |= JZ_LCD_CFG_MODE_8BIT_SERIAL; 622 break; 623 default: 624 break; 625 } 626 } 627 } 628 629 regmap_write(priv->map, JZ_REG_LCD_CFG, cfg); 630 } 631 632 static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder, 633 struct drm_crtc_state *crtc_state, 634 struct drm_connector_state *conn_state) 635 { 636 struct drm_display_info *info = &conn_state->connector->display_info; 637 638 if (info->num_bus_formats != 1) 639 return -EINVAL; 640 641 if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) 642 return 0; 643 644 switch (*info->bus_formats) { 645 case MEDIA_BUS_FMT_RGB565_1X16: 646 case MEDIA_BUS_FMT_RGB666_1X18: 647 case MEDIA_BUS_FMT_RGB888_1X24: 648 case MEDIA_BUS_FMT_RGB888_3X8: 649 return 0; 650 default: 651 return -EINVAL; 652 } 653 } 654 655 static void ingenic_drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state) 656 { 657 /* 658 * Just your regular drm_atomic_helper_commit_tail(), but only calls 659 * drm_atomic_helper_wait_for_vblanks() if priv->no_vblank. 660 */ 661 struct drm_device *dev = old_state->dev; 662 struct ingenic_drm *priv = drm_device_get_priv(dev); 663 664 drm_atomic_helper_commit_modeset_disables(dev, old_state); 665 666 drm_atomic_helper_commit_planes(dev, old_state, 0); 667 668 drm_atomic_helper_commit_modeset_enables(dev, old_state); 669 670 drm_atomic_helper_commit_hw_done(old_state); 671 672 if (!priv->no_vblank) 673 drm_atomic_helper_wait_for_vblanks(dev, old_state); 674 675 drm_atomic_helper_cleanup_planes(dev, old_state); 676 } 677 678 static irqreturn_t ingenic_drm_irq_handler(int irq, void *arg) 679 { 680 struct ingenic_drm *priv = drm_device_get_priv(arg); 681 unsigned int state; 682 683 regmap_read(priv->map, JZ_REG_LCD_STATE, &state); 684 685 regmap_update_bits(priv->map, JZ_REG_LCD_STATE, 686 JZ_LCD_STATE_EOF_IRQ, 0); 687 688 if (state & JZ_LCD_STATE_EOF_IRQ) 689 drm_crtc_handle_vblank(&priv->crtc); 690 691 return IRQ_HANDLED; 692 } 693 694 static int ingenic_drm_enable_vblank(struct drm_crtc *crtc) 695 { 696 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 697 698 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, 699 JZ_LCD_CTRL_EOF_IRQ, JZ_LCD_CTRL_EOF_IRQ); 700 701 return 0; 702 } 703 704 static void ingenic_drm_disable_vblank(struct drm_crtc *crtc) 705 { 706 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 707 708 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_EOF_IRQ, 0); 709 } 710 711 DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops); 712 713 static struct drm_driver ingenic_drm_driver_data = { 714 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 715 .name = "ingenic-drm", 716 .desc = "DRM module for Ingenic SoCs", 717 .date = "20200716", 718 .major = 1, 719 .minor = 1, 720 .patchlevel = 0, 721 722 .fops = &ingenic_drm_fops, 723 DRM_GEM_CMA_DRIVER_OPS, 724 725 .irq_handler = ingenic_drm_irq_handler, 726 }; 727 728 static const struct drm_plane_funcs ingenic_drm_primary_plane_funcs = { 729 .update_plane = drm_atomic_helper_update_plane, 730 .disable_plane = drm_atomic_helper_disable_plane, 731 .reset = drm_atomic_helper_plane_reset, 732 .destroy = drm_plane_cleanup, 733 734 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 735 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 736 }; 737 738 static const struct drm_crtc_funcs ingenic_drm_crtc_funcs = { 739 .set_config = drm_atomic_helper_set_config, 740 .page_flip = drm_atomic_helper_page_flip, 741 .reset = drm_atomic_helper_crtc_reset, 742 .destroy = drm_crtc_cleanup, 743 744 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 745 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 746 747 .enable_vblank = ingenic_drm_enable_vblank, 748 .disable_vblank = ingenic_drm_disable_vblank, 749 750 .gamma_set = drm_atomic_helper_legacy_gamma_set, 751 }; 752 753 static const struct drm_plane_helper_funcs ingenic_drm_plane_helper_funcs = { 754 .atomic_update = ingenic_drm_plane_atomic_update, 755 .atomic_check = ingenic_drm_plane_atomic_check, 756 .atomic_disable = ingenic_drm_plane_atomic_disable, 757 .prepare_fb = drm_gem_fb_prepare_fb, 758 }; 759 760 static const struct drm_crtc_helper_funcs ingenic_drm_crtc_helper_funcs = { 761 .atomic_enable = ingenic_drm_crtc_atomic_enable, 762 .atomic_disable = ingenic_drm_crtc_atomic_disable, 763 .atomic_begin = ingenic_drm_crtc_atomic_begin, 764 .atomic_flush = ingenic_drm_crtc_atomic_flush, 765 .atomic_check = ingenic_drm_crtc_atomic_check, 766 .mode_valid = ingenic_drm_crtc_mode_valid, 767 }; 768 769 static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = { 770 .atomic_mode_set = ingenic_drm_encoder_atomic_mode_set, 771 .atomic_check = ingenic_drm_encoder_atomic_check, 772 }; 773 774 static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = { 775 .fb_create = drm_gem_fb_create, 776 .output_poll_changed = drm_fb_helper_output_poll_changed, 777 .atomic_check = drm_atomic_helper_check, 778 .atomic_commit = drm_atomic_helper_commit, 779 }; 780 781 static struct drm_mode_config_helper_funcs ingenic_drm_mode_config_helpers = { 782 .atomic_commit_tail = ingenic_drm_atomic_helper_commit_tail, 783 }; 784 785 static void ingenic_drm_unbind_all(void *d) 786 { 787 struct ingenic_drm *priv = d; 788 789 component_unbind_all(priv->dev, &priv->drm); 790 } 791 792 static void __maybe_unused ingenic_drm_release_rmem(void *d) 793 { 794 of_reserved_mem_device_release(d); 795 } 796 797 static int ingenic_drm_bind(struct device *dev, bool has_components) 798 { 799 struct platform_device *pdev = to_platform_device(dev); 800 const struct jz_soc_info *soc_info; 801 struct ingenic_drm *priv; 802 struct clk *parent_clk; 803 struct drm_bridge *bridge; 804 struct drm_panel *panel; 805 struct drm_encoder *encoder; 806 struct drm_device *drm; 807 void __iomem *base; 808 long parent_rate; 809 unsigned int i, clone_mask = 0; 810 dma_addr_t dma_hwdesc_phys_f0, dma_hwdesc_phys_f1; 811 int ret, irq; 812 813 soc_info = of_device_get_match_data(dev); 814 if (!soc_info) { 815 dev_err(dev, "Missing platform data\n"); 816 return -EINVAL; 817 } 818 819 if (IS_ENABLED(CONFIG_OF_RESERVED_MEM)) { 820 ret = of_reserved_mem_device_init(dev); 821 822 if (ret && ret != -ENODEV) 823 dev_warn(dev, "Failed to get reserved memory: %d\n", ret); 824 825 if (!ret) { 826 ret = devm_add_action_or_reset(dev, ingenic_drm_release_rmem, dev); 827 if (ret) 828 return ret; 829 } 830 } 831 832 priv = devm_drm_dev_alloc(dev, &ingenic_drm_driver_data, 833 struct ingenic_drm, drm); 834 if (IS_ERR(priv)) 835 return PTR_ERR(priv); 836 837 priv->soc_info = soc_info; 838 priv->dev = dev; 839 drm = &priv->drm; 840 841 platform_set_drvdata(pdev, priv); 842 843 ret = drmm_mode_config_init(drm); 844 if (ret) 845 return ret; 846 847 drm->mode_config.min_width = 0; 848 drm->mode_config.min_height = 0; 849 drm->mode_config.max_width = soc_info->max_width; 850 drm->mode_config.max_height = 4095; 851 drm->mode_config.funcs = &ingenic_drm_mode_config_funcs; 852 drm->mode_config.helper_private = &ingenic_drm_mode_config_helpers; 853 854 base = devm_platform_ioremap_resource(pdev, 0); 855 if (IS_ERR(base)) { 856 dev_err(dev, "Failed to get memory resource\n"); 857 return PTR_ERR(base); 858 } 859 860 priv->map = devm_regmap_init_mmio(dev, base, 861 &ingenic_drm_regmap_config); 862 if (IS_ERR(priv->map)) { 863 dev_err(dev, "Failed to create regmap\n"); 864 return PTR_ERR(priv->map); 865 } 866 867 irq = platform_get_irq(pdev, 0); 868 if (irq < 0) 869 return irq; 870 871 if (soc_info->needs_dev_clk) { 872 priv->lcd_clk = devm_clk_get(dev, "lcd"); 873 if (IS_ERR(priv->lcd_clk)) { 874 dev_err(dev, "Failed to get lcd clock\n"); 875 return PTR_ERR(priv->lcd_clk); 876 } 877 } 878 879 priv->pix_clk = devm_clk_get(dev, "lcd_pclk"); 880 if (IS_ERR(priv->pix_clk)) { 881 dev_err(dev, "Failed to get pixel clock\n"); 882 return PTR_ERR(priv->pix_clk); 883 } 884 885 priv->dma_hwdescs = dmam_alloc_coherent(dev, 886 sizeof(*priv->dma_hwdescs), 887 &priv->dma_hwdescs_phys, 888 GFP_KERNEL); 889 if (!priv->dma_hwdescs) 890 return -ENOMEM; 891 892 893 /* Configure DMA hwdesc for foreground0 plane */ 894 dma_hwdesc_phys_f0 = priv->dma_hwdescs_phys 895 + offsetof(struct ingenic_dma_hwdescs, hwdesc_f0); 896 priv->dma_hwdescs->hwdesc_f0.next = dma_hwdesc_phys_f0; 897 priv->dma_hwdescs->hwdesc_f0.id = 0xf0; 898 899 /* Configure DMA hwdesc for foreground1 plane */ 900 dma_hwdesc_phys_f1 = priv->dma_hwdescs_phys 901 + offsetof(struct ingenic_dma_hwdescs, hwdesc_f1); 902 priv->dma_hwdescs->hwdesc_f1.next = dma_hwdesc_phys_f1; 903 priv->dma_hwdescs->hwdesc_f1.id = 0xf1; 904 905 /* Configure DMA hwdesc for palette */ 906 priv->dma_hwdescs->hwdesc_pal.next = priv->dma_hwdescs_phys 907 + offsetof(struct ingenic_dma_hwdescs, hwdesc_f0); 908 priv->dma_hwdescs->hwdesc_pal.id = 0xc0; 909 priv->dma_hwdescs->hwdesc_pal.addr = priv->dma_hwdescs_phys 910 + offsetof(struct ingenic_dma_hwdescs, palette); 911 priv->dma_hwdescs->hwdesc_pal.cmd = JZ_LCD_CMD_ENABLE_PAL 912 | (sizeof(priv->dma_hwdescs->palette) / 4); 913 914 if (soc_info->has_osd) 915 priv->ipu_plane = drm_plane_from_index(drm, 0); 916 917 drm_plane_helper_add(&priv->f1, &ingenic_drm_plane_helper_funcs); 918 919 ret = drm_universal_plane_init(drm, &priv->f1, 1, 920 &ingenic_drm_primary_plane_funcs, 921 priv->soc_info->formats_f1, 922 priv->soc_info->num_formats_f1, 923 NULL, DRM_PLANE_TYPE_PRIMARY, NULL); 924 if (ret) { 925 dev_err(dev, "Failed to register plane: %i\n", ret); 926 return ret; 927 } 928 929 drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs); 930 931 ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->f1, 932 NULL, &ingenic_drm_crtc_funcs, NULL); 933 if (ret) { 934 dev_err(dev, "Failed to init CRTC: %i\n", ret); 935 return ret; 936 } 937 938 drm_crtc_enable_color_mgmt(&priv->crtc, 0, false, 939 ARRAY_SIZE(priv->dma_hwdescs->palette)); 940 941 if (soc_info->has_osd) { 942 drm_plane_helper_add(&priv->f0, 943 &ingenic_drm_plane_helper_funcs); 944 945 ret = drm_universal_plane_init(drm, &priv->f0, 1, 946 &ingenic_drm_primary_plane_funcs, 947 priv->soc_info->formats_f0, 948 priv->soc_info->num_formats_f0, 949 NULL, DRM_PLANE_TYPE_OVERLAY, 950 NULL); 951 if (ret) { 952 dev_err(dev, "Failed to register overlay plane: %i\n", 953 ret); 954 return ret; 955 } 956 957 if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && has_components) { 958 ret = component_bind_all(dev, drm); 959 if (ret) { 960 if (ret != -EPROBE_DEFER) 961 dev_err(dev, "Failed to bind components: %i\n", ret); 962 return ret; 963 } 964 965 ret = devm_add_action_or_reset(dev, ingenic_drm_unbind_all, priv); 966 if (ret) 967 return ret; 968 969 priv->ipu_plane = drm_plane_from_index(drm, 2); 970 if (!priv->ipu_plane) { 971 dev_err(dev, "Failed to retrieve IPU plane\n"); 972 return -EINVAL; 973 } 974 } 975 } 976 977 for (i = 0; ; i++) { 978 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, i, &panel, &bridge); 979 if (ret) { 980 if (ret == -ENODEV) 981 break; /* we're done */ 982 if (ret != -EPROBE_DEFER) 983 dev_err(dev, "Failed to get bridge handle\n"); 984 return ret; 985 } 986 987 if (panel) 988 bridge = devm_drm_panel_bridge_add_typed(dev, panel, 989 DRM_MODE_CONNECTOR_DPI); 990 991 encoder = devm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL); 992 if (!encoder) 993 return -ENOMEM; 994 995 encoder->possible_crtcs = 1; 996 997 drm_encoder_helper_add(encoder, &ingenic_drm_encoder_helper_funcs); 998 999 ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_DPI); 1000 if (ret) { 1001 dev_err(dev, "Failed to init encoder: %d\n", ret); 1002 return ret; 1003 } 1004 1005 ret = drm_bridge_attach(encoder, bridge, NULL, 0); 1006 if (ret) { 1007 dev_err(dev, "Unable to attach bridge\n"); 1008 return ret; 1009 } 1010 } 1011 1012 drm_for_each_encoder(encoder, drm) { 1013 clone_mask |= BIT(drm_encoder_index(encoder)); 1014 } 1015 1016 drm_for_each_encoder(encoder, drm) { 1017 encoder->possible_clones = clone_mask; 1018 } 1019 1020 ret = drm_irq_install(drm, irq); 1021 if (ret) { 1022 dev_err(dev, "Unable to install IRQ handler\n"); 1023 return ret; 1024 } 1025 1026 ret = drm_vblank_init(drm, 1); 1027 if (ret) { 1028 dev_err(dev, "Failed calling drm_vblank_init()\n"); 1029 return ret; 1030 } 1031 1032 drm_mode_config_reset(drm); 1033 1034 ret = clk_prepare_enable(priv->pix_clk); 1035 if (ret) { 1036 dev_err(dev, "Unable to start pixel clock\n"); 1037 return ret; 1038 } 1039 1040 if (priv->lcd_clk) { 1041 parent_clk = clk_get_parent(priv->lcd_clk); 1042 parent_rate = clk_get_rate(parent_clk); 1043 1044 /* LCD Device clock must be 3x the pixel clock for STN panels, 1045 * or 1.5x the pixel clock for TFT panels. To avoid having to 1046 * check for the LCD device clock everytime we do a mode change, 1047 * we set the LCD device clock to the highest rate possible. 1048 */ 1049 ret = clk_set_rate(priv->lcd_clk, parent_rate); 1050 if (ret) { 1051 dev_err(dev, "Unable to set LCD clock rate\n"); 1052 goto err_pixclk_disable; 1053 } 1054 1055 ret = clk_prepare_enable(priv->lcd_clk); 1056 if (ret) { 1057 dev_err(dev, "Unable to start lcd clock\n"); 1058 goto err_pixclk_disable; 1059 } 1060 } 1061 1062 /* Set address of our DMA descriptor chain */ 1063 regmap_write(priv->map, JZ_REG_LCD_DA0, dma_hwdesc_phys_f0); 1064 regmap_write(priv->map, JZ_REG_LCD_DA1, dma_hwdesc_phys_f1); 1065 1066 /* Enable OSD if available */ 1067 if (soc_info->has_osd) 1068 regmap_write(priv->map, JZ_REG_LCD_OSDC, JZ_LCD_OSDC_OSDEN); 1069 1070 mutex_init(&priv->clk_mutex); 1071 priv->clock_nb.notifier_call = ingenic_drm_update_pixclk; 1072 1073 parent_clk = clk_get_parent(priv->pix_clk); 1074 ret = clk_notifier_register(parent_clk, &priv->clock_nb); 1075 if (ret) { 1076 dev_err(dev, "Unable to register clock notifier\n"); 1077 goto err_devclk_disable; 1078 } 1079 1080 ret = drm_dev_register(drm, 0); 1081 if (ret) { 1082 dev_err(dev, "Failed to register DRM driver\n"); 1083 goto err_clk_notifier_unregister; 1084 } 1085 1086 drm_fbdev_generic_setup(drm, 32); 1087 1088 return 0; 1089 1090 err_clk_notifier_unregister: 1091 clk_notifier_unregister(parent_clk, &priv->clock_nb); 1092 err_devclk_disable: 1093 if (priv->lcd_clk) 1094 clk_disable_unprepare(priv->lcd_clk); 1095 err_pixclk_disable: 1096 clk_disable_unprepare(priv->pix_clk); 1097 return ret; 1098 } 1099 1100 static int ingenic_drm_bind_with_components(struct device *dev) 1101 { 1102 return ingenic_drm_bind(dev, true); 1103 } 1104 1105 static int compare_of(struct device *dev, void *data) 1106 { 1107 return dev->of_node == data; 1108 } 1109 1110 static void ingenic_drm_unbind(struct device *dev) 1111 { 1112 struct ingenic_drm *priv = dev_get_drvdata(dev); 1113 struct clk *parent_clk = clk_get_parent(priv->pix_clk); 1114 1115 clk_notifier_unregister(parent_clk, &priv->clock_nb); 1116 if (priv->lcd_clk) 1117 clk_disable_unprepare(priv->lcd_clk); 1118 clk_disable_unprepare(priv->pix_clk); 1119 1120 drm_dev_unregister(&priv->drm); 1121 drm_atomic_helper_shutdown(&priv->drm); 1122 } 1123 1124 static const struct component_master_ops ingenic_master_ops = { 1125 .bind = ingenic_drm_bind_with_components, 1126 .unbind = ingenic_drm_unbind, 1127 }; 1128 1129 static int ingenic_drm_probe(struct platform_device *pdev) 1130 { 1131 struct device *dev = &pdev->dev; 1132 struct component_match *match = NULL; 1133 struct device_node *np; 1134 1135 if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) 1136 return ingenic_drm_bind(dev, false); 1137 1138 /* IPU is at port address 8 */ 1139 np = of_graph_get_remote_node(dev->of_node, 8, 0); 1140 if (!np) 1141 return ingenic_drm_bind(dev, false); 1142 1143 drm_of_component_match_add(dev, &match, compare_of, np); 1144 of_node_put(np); 1145 1146 return component_master_add_with_match(dev, &ingenic_master_ops, match); 1147 } 1148 1149 static int ingenic_drm_remove(struct platform_device *pdev) 1150 { 1151 struct device *dev = &pdev->dev; 1152 1153 if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) 1154 ingenic_drm_unbind(dev); 1155 else 1156 component_master_del(dev, &ingenic_master_ops); 1157 1158 return 0; 1159 } 1160 1161 static const u32 jz4740_formats[] = { 1162 DRM_FORMAT_XRGB1555, 1163 DRM_FORMAT_RGB565, 1164 DRM_FORMAT_XRGB8888, 1165 }; 1166 1167 static const u32 jz4725b_formats_f1[] = { 1168 DRM_FORMAT_XRGB1555, 1169 DRM_FORMAT_RGB565, 1170 DRM_FORMAT_XRGB8888, 1171 }; 1172 1173 static const u32 jz4725b_formats_f0[] = { 1174 DRM_FORMAT_C8, 1175 DRM_FORMAT_XRGB1555, 1176 DRM_FORMAT_RGB565, 1177 DRM_FORMAT_XRGB8888, 1178 }; 1179 1180 static const u32 jz4770_formats_f1[] = { 1181 DRM_FORMAT_XRGB1555, 1182 DRM_FORMAT_RGB565, 1183 DRM_FORMAT_RGB888, 1184 DRM_FORMAT_XRGB8888, 1185 DRM_FORMAT_XRGB2101010, 1186 }; 1187 1188 static const u32 jz4770_formats_f0[] = { 1189 DRM_FORMAT_C8, 1190 DRM_FORMAT_XRGB1555, 1191 DRM_FORMAT_RGB565, 1192 DRM_FORMAT_RGB888, 1193 DRM_FORMAT_XRGB8888, 1194 DRM_FORMAT_XRGB2101010, 1195 }; 1196 1197 static const struct jz_soc_info jz4740_soc_info = { 1198 .needs_dev_clk = true, 1199 .has_osd = false, 1200 .max_width = 800, 1201 .max_height = 600, 1202 .formats_f1 = jz4740_formats, 1203 .num_formats_f1 = ARRAY_SIZE(jz4740_formats), 1204 /* JZ4740 has only one plane */ 1205 }; 1206 1207 static const struct jz_soc_info jz4725b_soc_info = { 1208 .needs_dev_clk = false, 1209 .has_osd = true, 1210 .max_width = 800, 1211 .max_height = 600, 1212 .formats_f1 = jz4725b_formats_f1, 1213 .num_formats_f1 = ARRAY_SIZE(jz4725b_formats_f1), 1214 .formats_f0 = jz4725b_formats_f0, 1215 .num_formats_f0 = ARRAY_SIZE(jz4725b_formats_f0), 1216 }; 1217 1218 static const struct jz_soc_info jz4770_soc_info = { 1219 .needs_dev_clk = false, 1220 .has_osd = true, 1221 .max_width = 1280, 1222 .max_height = 720, 1223 .formats_f1 = jz4770_formats_f1, 1224 .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1), 1225 .formats_f0 = jz4770_formats_f0, 1226 .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0), 1227 }; 1228 1229 static const struct of_device_id ingenic_drm_of_match[] = { 1230 { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info }, 1231 { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info }, 1232 { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info }, 1233 { /* sentinel */ }, 1234 }; 1235 MODULE_DEVICE_TABLE(of, ingenic_drm_of_match); 1236 1237 static struct platform_driver ingenic_drm_driver = { 1238 .driver = { 1239 .name = "ingenic-drm", 1240 .of_match_table = of_match_ptr(ingenic_drm_of_match), 1241 }, 1242 .probe = ingenic_drm_probe, 1243 .remove = ingenic_drm_remove, 1244 }; 1245 1246 static int ingenic_drm_init(void) 1247 { 1248 int err; 1249 1250 if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) { 1251 err = platform_driver_register(ingenic_ipu_driver_ptr); 1252 if (err) 1253 return err; 1254 } 1255 1256 return platform_driver_register(&ingenic_drm_driver); 1257 } 1258 module_init(ingenic_drm_init); 1259 1260 static void ingenic_drm_exit(void) 1261 { 1262 platform_driver_unregister(&ingenic_drm_driver); 1263 1264 if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) 1265 platform_driver_unregister(ingenic_ipu_driver_ptr); 1266 } 1267 module_exit(ingenic_drm_exit); 1268 1269 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); 1270 MODULE_DESCRIPTION("DRM driver for the Ingenic SoCs\n"); 1271 MODULE_LICENSE("GPL v2"); 1272