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.8 841 lines 23 kB view raw
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 <linux/clk.h> 8#include <linux/dma-mapping.h> 9#include <linux/module.h> 10#include <linux/of_device.h> 11#include <linux/platform_device.h> 12#include <linux/regmap.h> 13 14#include <drm/drm_atomic.h> 15#include <drm/drm_atomic_helper.h> 16#include <drm/drm_bridge.h> 17#include <drm/drm_crtc.h> 18#include <drm/drm_crtc_helper.h> 19#include <drm/drm_drv.h> 20#include <drm/drm_gem_cma_helper.h> 21#include <drm/drm_fb_cma_helper.h> 22#include <drm/drm_fb_helper.h> 23#include <drm/drm_fourcc.h> 24#include <drm/drm_gem_framebuffer_helper.h> 25#include <drm/drm_irq.h> 26#include <drm/drm_managed.h> 27#include <drm/drm_of.h> 28#include <drm/drm_panel.h> 29#include <drm/drm_plane.h> 30#include <drm/drm_plane_helper.h> 31#include <drm/drm_probe_helper.h> 32#include <drm/drm_simple_kms_helper.h> 33#include <drm/drm_vblank.h> 34 35#define JZ_REG_LCD_CFG 0x00 36#define JZ_REG_LCD_VSYNC 0x04 37#define JZ_REG_LCD_HSYNC 0x08 38#define JZ_REG_LCD_VAT 0x0C 39#define JZ_REG_LCD_DAH 0x10 40#define JZ_REG_LCD_DAV 0x14 41#define JZ_REG_LCD_PS 0x18 42#define JZ_REG_LCD_CLS 0x1C 43#define JZ_REG_LCD_SPL 0x20 44#define JZ_REG_LCD_REV 0x24 45#define JZ_REG_LCD_CTRL 0x30 46#define JZ_REG_LCD_STATE 0x34 47#define JZ_REG_LCD_IID 0x38 48#define JZ_REG_LCD_DA0 0x40 49#define JZ_REG_LCD_SA0 0x44 50#define JZ_REG_LCD_FID0 0x48 51#define JZ_REG_LCD_CMD0 0x4C 52#define JZ_REG_LCD_DA1 0x50 53#define JZ_REG_LCD_SA1 0x54 54#define JZ_REG_LCD_FID1 0x58 55#define JZ_REG_LCD_CMD1 0x5C 56 57#define JZ_LCD_CFG_SLCD BIT(31) 58#define JZ_LCD_CFG_PS_DISABLE BIT(23) 59#define JZ_LCD_CFG_CLS_DISABLE BIT(22) 60#define JZ_LCD_CFG_SPL_DISABLE BIT(21) 61#define JZ_LCD_CFG_REV_DISABLE BIT(20) 62#define JZ_LCD_CFG_HSYNCM BIT(19) 63#define JZ_LCD_CFG_PCLKM BIT(18) 64#define JZ_LCD_CFG_INV BIT(17) 65#define JZ_LCD_CFG_SYNC_DIR BIT(16) 66#define JZ_LCD_CFG_PS_POLARITY BIT(15) 67#define JZ_LCD_CFG_CLS_POLARITY BIT(14) 68#define JZ_LCD_CFG_SPL_POLARITY BIT(13) 69#define JZ_LCD_CFG_REV_POLARITY BIT(12) 70#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11) 71#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10) 72#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9) 73#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8) 74#define JZ_LCD_CFG_18_BIT BIT(7) 75#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4)) 76 77#define JZ_LCD_CFG_MODE_GENERIC_16BIT 0 78#define JZ_LCD_CFG_MODE_GENERIC_18BIT BIT(7) 79#define JZ_LCD_CFG_MODE_GENERIC_24BIT BIT(6) 80 81#define JZ_LCD_CFG_MODE_SPECIAL_TFT_1 1 82#define JZ_LCD_CFG_MODE_SPECIAL_TFT_2 2 83#define JZ_LCD_CFG_MODE_SPECIAL_TFT_3 3 84 85#define JZ_LCD_CFG_MODE_TV_OUT_P 4 86#define JZ_LCD_CFG_MODE_TV_OUT_I 6 87 88#define JZ_LCD_CFG_MODE_SINGLE_COLOR_STN 8 89#define JZ_LCD_CFG_MODE_SINGLE_MONOCHROME_STN 9 90#define JZ_LCD_CFG_MODE_DUAL_COLOR_STN 10 91#define JZ_LCD_CFG_MODE_DUAL_MONOCHROME_STN 11 92 93#define JZ_LCD_CFG_MODE_8BIT_SERIAL 12 94#define JZ_LCD_CFG_MODE_LCM 13 95 96#define JZ_LCD_VSYNC_VPS_OFFSET 16 97#define JZ_LCD_VSYNC_VPE_OFFSET 0 98 99#define JZ_LCD_HSYNC_HPS_OFFSET 16 100#define JZ_LCD_HSYNC_HPE_OFFSET 0 101 102#define JZ_LCD_VAT_HT_OFFSET 16 103#define JZ_LCD_VAT_VT_OFFSET 0 104 105#define JZ_LCD_DAH_HDS_OFFSET 16 106#define JZ_LCD_DAH_HDE_OFFSET 0 107 108#define JZ_LCD_DAV_VDS_OFFSET 16 109#define JZ_LCD_DAV_VDE_OFFSET 0 110 111#define JZ_LCD_CTRL_BURST_4 (0x0 << 28) 112#define JZ_LCD_CTRL_BURST_8 (0x1 << 28) 113#define JZ_LCD_CTRL_BURST_16 (0x2 << 28) 114#define JZ_LCD_CTRL_RGB555 BIT(27) 115#define JZ_LCD_CTRL_OFUP BIT(26) 116#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24) 117#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24) 118#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24) 119#define JZ_LCD_CTRL_PDD_MASK (0xff << 16) 120#define JZ_LCD_CTRL_EOF_IRQ BIT(13) 121#define JZ_LCD_CTRL_SOF_IRQ BIT(12) 122#define JZ_LCD_CTRL_OFU_IRQ BIT(11) 123#define JZ_LCD_CTRL_IFU0_IRQ BIT(10) 124#define JZ_LCD_CTRL_IFU1_IRQ BIT(9) 125#define JZ_LCD_CTRL_DD_IRQ BIT(8) 126#define JZ_LCD_CTRL_QDD_IRQ BIT(7) 127#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6) 128#define JZ_LCD_CTRL_LSB_FISRT BIT(5) 129#define JZ_LCD_CTRL_DISABLE BIT(4) 130#define JZ_LCD_CTRL_ENABLE BIT(3) 131#define JZ_LCD_CTRL_BPP_1 0x0 132#define JZ_LCD_CTRL_BPP_2 0x1 133#define JZ_LCD_CTRL_BPP_4 0x2 134#define JZ_LCD_CTRL_BPP_8 0x3 135#define JZ_LCD_CTRL_BPP_15_16 0x4 136#define JZ_LCD_CTRL_BPP_18_24 0x5 137#define JZ_LCD_CTRL_BPP_MASK (JZ_LCD_CTRL_RGB555 | (0x7 << 0)) 138 139#define JZ_LCD_CMD_SOF_IRQ BIT(31) 140#define JZ_LCD_CMD_EOF_IRQ BIT(30) 141#define JZ_LCD_CMD_ENABLE_PAL BIT(28) 142 143#define JZ_LCD_SYNC_MASK 0x3ff 144 145#define JZ_LCD_STATE_EOF_IRQ BIT(5) 146#define JZ_LCD_STATE_SOF_IRQ BIT(4) 147#define JZ_LCD_STATE_DISABLED BIT(0) 148 149struct ingenic_dma_hwdesc { 150 u32 next; 151 u32 addr; 152 u32 id; 153 u32 cmd; 154} __packed; 155 156struct jz_soc_info { 157 bool needs_dev_clk; 158 unsigned int max_width, max_height; 159}; 160 161struct ingenic_drm { 162 struct drm_device drm; 163 struct drm_plane primary; 164 struct drm_crtc crtc; 165 struct drm_encoder encoder; 166 167 struct device *dev; 168 struct regmap *map; 169 struct clk *lcd_clk, *pix_clk; 170 const struct jz_soc_info *soc_info; 171 172 struct ingenic_dma_hwdesc *dma_hwdesc; 173 dma_addr_t dma_hwdesc_phys; 174 175 bool panel_is_sharp; 176}; 177 178static const u32 ingenic_drm_primary_formats[] = { 179 DRM_FORMAT_XRGB1555, 180 DRM_FORMAT_RGB565, 181 DRM_FORMAT_XRGB8888, 182}; 183 184static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg) 185{ 186 switch (reg) { 187 case JZ_REG_LCD_IID: 188 case JZ_REG_LCD_SA0: 189 case JZ_REG_LCD_FID0: 190 case JZ_REG_LCD_CMD0: 191 case JZ_REG_LCD_SA1: 192 case JZ_REG_LCD_FID1: 193 case JZ_REG_LCD_CMD1: 194 return false; 195 default: 196 return true; 197 } 198} 199 200static const struct regmap_config ingenic_drm_regmap_config = { 201 .reg_bits = 32, 202 .val_bits = 32, 203 .reg_stride = 4, 204 205 .max_register = JZ_REG_LCD_CMD1, 206 .writeable_reg = ingenic_drm_writeable_reg, 207}; 208 209static inline struct ingenic_drm *drm_device_get_priv(struct drm_device *drm) 210{ 211 return container_of(drm, struct ingenic_drm, drm); 212} 213 214static inline struct ingenic_drm *drm_crtc_get_priv(struct drm_crtc *crtc) 215{ 216 return container_of(crtc, struct ingenic_drm, crtc); 217} 218 219static inline struct ingenic_drm * 220drm_encoder_get_priv(struct drm_encoder *encoder) 221{ 222 return container_of(encoder, struct ingenic_drm, encoder); 223} 224 225static inline struct ingenic_drm *drm_plane_get_priv(struct drm_plane *plane) 226{ 227 return container_of(plane, struct ingenic_drm, primary); 228} 229 230static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, 231 struct drm_crtc_state *state) 232{ 233 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 234 235 regmap_write(priv->map, JZ_REG_LCD_STATE, 0); 236 237 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, 238 JZ_LCD_CTRL_ENABLE | JZ_LCD_CTRL_DISABLE, 239 JZ_LCD_CTRL_ENABLE); 240 241 drm_crtc_vblank_on(crtc); 242} 243 244static void ingenic_drm_crtc_atomic_disable(struct drm_crtc *crtc, 245 struct drm_crtc_state *state) 246{ 247 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 248 unsigned int var; 249 250 drm_crtc_vblank_off(crtc); 251 252 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, 253 JZ_LCD_CTRL_DISABLE, JZ_LCD_CTRL_DISABLE); 254 255 regmap_read_poll_timeout(priv->map, JZ_REG_LCD_STATE, var, 256 var & JZ_LCD_STATE_DISABLED, 257 1000, 0); 258} 259 260static void ingenic_drm_crtc_update_timings(struct ingenic_drm *priv, 261 struct drm_display_mode *mode) 262{ 263 unsigned int vpe, vds, vde, vt, hpe, hds, hde, ht; 264 265 vpe = mode->vsync_end - mode->vsync_start; 266 vds = mode->vtotal - mode->vsync_start; 267 vde = vds + mode->vdisplay; 268 vt = vde + mode->vsync_start - mode->vdisplay; 269 270 hpe = mode->hsync_end - mode->hsync_start; 271 hds = mode->htotal - mode->hsync_start; 272 hde = hds + mode->hdisplay; 273 ht = hde + mode->hsync_start - mode->hdisplay; 274 275 regmap_write(priv->map, JZ_REG_LCD_VSYNC, 276 0 << JZ_LCD_VSYNC_VPS_OFFSET | 277 vpe << JZ_LCD_VSYNC_VPE_OFFSET); 278 279 regmap_write(priv->map, JZ_REG_LCD_HSYNC, 280 0 << JZ_LCD_HSYNC_HPS_OFFSET | 281 hpe << JZ_LCD_HSYNC_HPE_OFFSET); 282 283 regmap_write(priv->map, JZ_REG_LCD_VAT, 284 ht << JZ_LCD_VAT_HT_OFFSET | 285 vt << JZ_LCD_VAT_VT_OFFSET); 286 287 regmap_write(priv->map, JZ_REG_LCD_DAH, 288 hds << JZ_LCD_DAH_HDS_OFFSET | 289 hde << JZ_LCD_DAH_HDE_OFFSET); 290 regmap_write(priv->map, JZ_REG_LCD_DAV, 291 vds << JZ_LCD_DAV_VDS_OFFSET | 292 vde << JZ_LCD_DAV_VDE_OFFSET); 293 294 if (priv->panel_is_sharp) { 295 regmap_write(priv->map, JZ_REG_LCD_PS, hde << 16 | (hde + 1)); 296 regmap_write(priv->map, JZ_REG_LCD_CLS, hde << 16 | (hde + 1)); 297 regmap_write(priv->map, JZ_REG_LCD_SPL, hpe << 16 | (hpe + 1)); 298 regmap_write(priv->map, JZ_REG_LCD_REV, mode->htotal << 16); 299 } 300} 301 302static void ingenic_drm_crtc_update_ctrl(struct ingenic_drm *priv, 303 const struct drm_format_info *finfo) 304{ 305 unsigned int ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16; 306 307 switch (finfo->format) { 308 case DRM_FORMAT_XRGB1555: 309 ctrl |= JZ_LCD_CTRL_RGB555; 310 /* fall-through */ 311 case DRM_FORMAT_RGB565: 312 ctrl |= JZ_LCD_CTRL_BPP_15_16; 313 break; 314 case DRM_FORMAT_XRGB8888: 315 ctrl |= JZ_LCD_CTRL_BPP_18_24; 316 break; 317 } 318 319 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, 320 JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16 | 321 JZ_LCD_CTRL_BPP_MASK, ctrl); 322} 323 324static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc, 325 struct drm_crtc_state *state) 326{ 327 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 328 long rate; 329 330 if (!drm_atomic_crtc_needs_modeset(state)) 331 return 0; 332 333 if (state->mode.hdisplay > priv->soc_info->max_width || 334 state->mode.vdisplay > priv->soc_info->max_height) 335 return -EINVAL; 336 337 rate = clk_round_rate(priv->pix_clk, 338 state->adjusted_mode.clock * 1000); 339 if (rate < 0) 340 return rate; 341 342 return 0; 343} 344 345static void ingenic_drm_crtc_atomic_flush(struct drm_crtc *crtc, 346 struct drm_crtc_state *oldstate) 347{ 348 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 349 struct drm_crtc_state *state = crtc->state; 350 struct drm_pending_vblank_event *event = state->event; 351 struct drm_framebuffer *drm_fb = crtc->primary->state->fb; 352 const struct drm_format_info *finfo; 353 354 if (drm_atomic_crtc_needs_modeset(state)) { 355 finfo = drm_format_info(drm_fb->format->format); 356 357 ingenic_drm_crtc_update_timings(priv, &state->mode); 358 ingenic_drm_crtc_update_ctrl(priv, finfo); 359 360 clk_set_rate(priv->pix_clk, state->adjusted_mode.clock * 1000); 361 362 regmap_write(priv->map, JZ_REG_LCD_DA0, priv->dma_hwdesc->next); 363 } 364 365 if (event) { 366 state->event = NULL; 367 368 spin_lock_irq(&crtc->dev->event_lock); 369 if (drm_crtc_vblank_get(crtc) == 0) 370 drm_crtc_arm_vblank_event(crtc, event); 371 else 372 drm_crtc_send_vblank_event(crtc, event); 373 spin_unlock_irq(&crtc->dev->event_lock); 374 } 375} 376 377static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, 378 struct drm_plane_state *oldstate) 379{ 380 struct ingenic_drm *priv = drm_plane_get_priv(plane); 381 struct drm_plane_state *state = plane->state; 382 unsigned int width, height, cpp; 383 dma_addr_t addr; 384 385 if (state && state->fb) { 386 addr = drm_fb_cma_get_gem_addr(state->fb, state, 0); 387 width = state->src_w >> 16; 388 height = state->src_h >> 16; 389 cpp = state->fb->format->cpp[plane->index]; 390 391 priv->dma_hwdesc->addr = addr; 392 priv->dma_hwdesc->cmd = width * height * cpp / 4; 393 priv->dma_hwdesc->cmd |= JZ_LCD_CMD_EOF_IRQ; 394 } 395} 396 397static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, 398 struct drm_crtc_state *crtc_state, 399 struct drm_connector_state *conn_state) 400{ 401 struct ingenic_drm *priv = drm_encoder_get_priv(encoder); 402 struct drm_display_mode *mode = &crtc_state->adjusted_mode; 403 struct drm_connector *conn = conn_state->connector; 404 struct drm_display_info *info = &conn->display_info; 405 unsigned int cfg; 406 407 priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS; 408 409 if (priv->panel_is_sharp) { 410 cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY; 411 } else { 412 cfg = JZ_LCD_CFG_PS_DISABLE | JZ_LCD_CFG_CLS_DISABLE 413 | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE; 414 } 415 416 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 417 cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; 418 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 419 cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW; 420 if (info->bus_flags & DRM_BUS_FLAG_DE_LOW) 421 cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW; 422 if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE) 423 cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; 424 425 if (!priv->panel_is_sharp) { 426 if (conn->connector_type == DRM_MODE_CONNECTOR_TV) { 427 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 428 cfg |= JZ_LCD_CFG_MODE_TV_OUT_I; 429 else 430 cfg |= JZ_LCD_CFG_MODE_TV_OUT_P; 431 } else { 432 switch (*info->bus_formats) { 433 case MEDIA_BUS_FMT_RGB565_1X16: 434 cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT; 435 break; 436 case MEDIA_BUS_FMT_RGB666_1X18: 437 cfg |= JZ_LCD_CFG_MODE_GENERIC_18BIT; 438 break; 439 case MEDIA_BUS_FMT_RGB888_1X24: 440 cfg |= JZ_LCD_CFG_MODE_GENERIC_24BIT; 441 break; 442 case MEDIA_BUS_FMT_RGB888_3X8: 443 cfg |= JZ_LCD_CFG_MODE_8BIT_SERIAL; 444 break; 445 default: 446 break; 447 } 448 } 449 } 450 451 regmap_write(priv->map, JZ_REG_LCD_CFG, cfg); 452} 453 454static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder, 455 struct drm_crtc_state *crtc_state, 456 struct drm_connector_state *conn_state) 457{ 458 struct drm_display_info *info = &conn_state->connector->display_info; 459 460 if (info->num_bus_formats != 1) 461 return -EINVAL; 462 463 if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) 464 return 0; 465 466 switch (*info->bus_formats) { 467 case MEDIA_BUS_FMT_RGB565_1X16: 468 case MEDIA_BUS_FMT_RGB666_1X18: 469 case MEDIA_BUS_FMT_RGB888_1X24: 470 case MEDIA_BUS_FMT_RGB888_3X8: 471 return 0; 472 default: 473 return -EINVAL; 474 } 475} 476 477static irqreturn_t ingenic_drm_irq_handler(int irq, void *arg) 478{ 479 struct ingenic_drm *priv = drm_device_get_priv(arg); 480 unsigned int state; 481 482 regmap_read(priv->map, JZ_REG_LCD_STATE, &state); 483 484 regmap_update_bits(priv->map, JZ_REG_LCD_STATE, 485 JZ_LCD_STATE_EOF_IRQ, 0); 486 487 if (state & JZ_LCD_STATE_EOF_IRQ) 488 drm_crtc_handle_vblank(&priv->crtc); 489 490 return IRQ_HANDLED; 491} 492 493static int ingenic_drm_enable_vblank(struct drm_crtc *crtc) 494{ 495 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 496 497 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, 498 JZ_LCD_CTRL_EOF_IRQ, JZ_LCD_CTRL_EOF_IRQ); 499 500 return 0; 501} 502 503static void ingenic_drm_disable_vblank(struct drm_crtc *crtc) 504{ 505 struct ingenic_drm *priv = drm_crtc_get_priv(crtc); 506 507 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_EOF_IRQ, 0); 508} 509 510DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops); 511 512static struct drm_driver ingenic_drm_driver_data = { 513 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 514 .name = "ingenic-drm", 515 .desc = "DRM module for Ingenic SoCs", 516 .date = "20190422", 517 .major = 1, 518 .minor = 0, 519 .patchlevel = 0, 520 521 .fops = &ingenic_drm_fops, 522 523 .dumb_create = drm_gem_cma_dumb_create, 524 .gem_free_object_unlocked = drm_gem_cma_free_object, 525 .gem_vm_ops = &drm_gem_cma_vm_ops, 526 527 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 528 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 529 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, 530 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, 531 .gem_prime_vmap = drm_gem_cma_prime_vmap, 532 .gem_prime_vunmap = drm_gem_cma_prime_vunmap, 533 .gem_prime_mmap = drm_gem_cma_prime_mmap, 534 535 .irq_handler = ingenic_drm_irq_handler, 536}; 537 538static const struct drm_plane_funcs ingenic_drm_primary_plane_funcs = { 539 .update_plane = drm_atomic_helper_update_plane, 540 .disable_plane = drm_atomic_helper_disable_plane, 541 .reset = drm_atomic_helper_plane_reset, 542 .destroy = drm_plane_cleanup, 543 544 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 545 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 546}; 547 548static const struct drm_crtc_funcs ingenic_drm_crtc_funcs = { 549 .set_config = drm_atomic_helper_set_config, 550 .page_flip = drm_atomic_helper_page_flip, 551 .reset = drm_atomic_helper_crtc_reset, 552 .destroy = drm_crtc_cleanup, 553 554 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 555 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 556 557 .enable_vblank = ingenic_drm_enable_vblank, 558 .disable_vblank = ingenic_drm_disable_vblank, 559 560 .gamma_set = drm_atomic_helper_legacy_gamma_set, 561}; 562 563static const struct drm_plane_helper_funcs ingenic_drm_plane_helper_funcs = { 564 .atomic_update = ingenic_drm_plane_atomic_update, 565 .prepare_fb = drm_gem_fb_prepare_fb, 566}; 567 568static const struct drm_crtc_helper_funcs ingenic_drm_crtc_helper_funcs = { 569 .atomic_enable = ingenic_drm_crtc_atomic_enable, 570 .atomic_disable = ingenic_drm_crtc_atomic_disable, 571 .atomic_flush = ingenic_drm_crtc_atomic_flush, 572 .atomic_check = ingenic_drm_crtc_atomic_check, 573}; 574 575static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = { 576 .atomic_mode_set = ingenic_drm_encoder_atomic_mode_set, 577 .atomic_check = ingenic_drm_encoder_atomic_check, 578}; 579 580static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = { 581 .fb_create = drm_gem_fb_create, 582 .output_poll_changed = drm_fb_helper_output_poll_changed, 583 .atomic_check = drm_atomic_helper_check, 584 .atomic_commit = drm_atomic_helper_commit, 585}; 586 587static void ingenic_drm_free_dma_hwdesc(void *d) 588{ 589 struct ingenic_drm *priv = d; 590 591 dma_free_coherent(priv->dev, sizeof(*priv->dma_hwdesc), 592 priv->dma_hwdesc, priv->dma_hwdesc_phys); 593} 594 595static int ingenic_drm_probe(struct platform_device *pdev) 596{ 597 const struct jz_soc_info *soc_info; 598 struct device *dev = &pdev->dev; 599 struct ingenic_drm *priv; 600 struct clk *parent_clk; 601 struct drm_bridge *bridge; 602 struct drm_panel *panel; 603 struct drm_device *drm; 604 void __iomem *base; 605 long parent_rate; 606 int ret, irq; 607 608 soc_info = of_device_get_match_data(dev); 609 if (!soc_info) { 610 dev_err(dev, "Missing platform data\n"); 611 return -EINVAL; 612 } 613 614 priv = devm_drm_dev_alloc(dev, &ingenic_drm_driver_data, 615 struct ingenic_drm, drm); 616 if (IS_ERR(priv)) 617 return PTR_ERR(priv); 618 619 priv->soc_info = soc_info; 620 priv->dev = dev; 621 drm = &priv->drm; 622 623 platform_set_drvdata(pdev, priv); 624 625 ret = drmm_mode_config_init(drm); 626 if (ret) 627 return ret; 628 629 drm->mode_config.min_width = 0; 630 drm->mode_config.min_height = 0; 631 drm->mode_config.max_width = soc_info->max_width; 632 drm->mode_config.max_height = 4095; 633 drm->mode_config.funcs = &ingenic_drm_mode_config_funcs; 634 635 base = devm_platform_ioremap_resource(pdev, 0); 636 if (IS_ERR(base)) { 637 dev_err(dev, "Failed to get memory resource"); 638 return PTR_ERR(base); 639 } 640 641 priv->map = devm_regmap_init_mmio(dev, base, 642 &ingenic_drm_regmap_config); 643 if (IS_ERR(priv->map)) { 644 dev_err(dev, "Failed to create regmap"); 645 return PTR_ERR(priv->map); 646 } 647 648 irq = platform_get_irq(pdev, 0); 649 if (irq < 0) 650 return irq; 651 652 if (soc_info->needs_dev_clk) { 653 priv->lcd_clk = devm_clk_get(dev, "lcd"); 654 if (IS_ERR(priv->lcd_clk)) { 655 dev_err(dev, "Failed to get lcd clock"); 656 return PTR_ERR(priv->lcd_clk); 657 } 658 } 659 660 priv->pix_clk = devm_clk_get(dev, "lcd_pclk"); 661 if (IS_ERR(priv->pix_clk)) { 662 dev_err(dev, "Failed to get pixel clock"); 663 return PTR_ERR(priv->pix_clk); 664 } 665 666 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, &bridge); 667 if (ret) { 668 if (ret != -EPROBE_DEFER) 669 dev_err(dev, "Failed to get panel handle"); 670 return ret; 671 } 672 673 if (panel) 674 bridge = devm_drm_panel_bridge_add_typed(dev, panel, 675 DRM_MODE_CONNECTOR_DPI); 676 677 priv->dma_hwdesc = dma_alloc_coherent(dev, sizeof(*priv->dma_hwdesc), 678 &priv->dma_hwdesc_phys, 679 GFP_KERNEL); 680 if (!priv->dma_hwdesc) 681 return -ENOMEM; 682 683 ret = devm_add_action_or_reset(dev, ingenic_drm_free_dma_hwdesc, priv); 684 if (ret) 685 return ret; 686 687 priv->dma_hwdesc->next = priv->dma_hwdesc_phys; 688 priv->dma_hwdesc->id = 0xdeafbead; 689 690 drm_plane_helper_add(&priv->primary, &ingenic_drm_plane_helper_funcs); 691 692 ret = drm_universal_plane_init(drm, &priv->primary, 693 0, &ingenic_drm_primary_plane_funcs, 694 ingenic_drm_primary_formats, 695 ARRAY_SIZE(ingenic_drm_primary_formats), 696 NULL, DRM_PLANE_TYPE_PRIMARY, NULL); 697 if (ret) { 698 dev_err(dev, "Failed to register primary plane: %i", ret); 699 return ret; 700 } 701 702 drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs); 703 704 ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->primary, 705 NULL, &ingenic_drm_crtc_funcs, NULL); 706 if (ret) { 707 dev_err(dev, "Failed to init CRTC: %i", ret); 708 return ret; 709 } 710 711 priv->encoder.possible_crtcs = 1; 712 713 drm_encoder_helper_add(&priv->encoder, 714 &ingenic_drm_encoder_helper_funcs); 715 716 ret = drm_simple_encoder_init(drm, &priv->encoder, 717 DRM_MODE_ENCODER_DPI); 718 if (ret) { 719 dev_err(dev, "Failed to init encoder: %i", ret); 720 return ret; 721 } 722 723 ret = drm_bridge_attach(&priv->encoder, bridge, NULL, 0); 724 if (ret) { 725 dev_err(dev, "Unable to attach bridge"); 726 return ret; 727 } 728 729 ret = drm_irq_install(drm, irq); 730 if (ret) { 731 dev_err(dev, "Unable to install IRQ handler"); 732 return ret; 733 } 734 735 ret = drm_vblank_init(drm, 1); 736 if (ret) { 737 dev_err(dev, "Failed calling drm_vblank_init()"); 738 return ret; 739 } 740 741 drm_mode_config_reset(drm); 742 743 ret = clk_prepare_enable(priv->pix_clk); 744 if (ret) { 745 dev_err(dev, "Unable to start pixel clock"); 746 return ret; 747 } 748 749 if (priv->lcd_clk) { 750 parent_clk = clk_get_parent(priv->lcd_clk); 751 parent_rate = clk_get_rate(parent_clk); 752 753 /* LCD Device clock must be 3x the pixel clock for STN panels, 754 * or 1.5x the pixel clock for TFT panels. To avoid having to 755 * check for the LCD device clock everytime we do a mode change, 756 * we set the LCD device clock to the highest rate possible. 757 */ 758 ret = clk_set_rate(priv->lcd_clk, parent_rate); 759 if (ret) { 760 dev_err(dev, "Unable to set LCD clock rate"); 761 goto err_pixclk_disable; 762 } 763 764 ret = clk_prepare_enable(priv->lcd_clk); 765 if (ret) { 766 dev_err(dev, "Unable to start lcd clock"); 767 goto err_pixclk_disable; 768 } 769 } 770 771 ret = drm_dev_register(drm, 0); 772 if (ret) { 773 dev_err(dev, "Failed to register DRM driver"); 774 goto err_devclk_disable; 775 } 776 777 drm_fbdev_generic_setup(drm, 32); 778 779 return 0; 780 781err_devclk_disable: 782 if (priv->lcd_clk) 783 clk_disable_unprepare(priv->lcd_clk); 784err_pixclk_disable: 785 clk_disable_unprepare(priv->pix_clk); 786 return ret; 787} 788 789static int ingenic_drm_remove(struct platform_device *pdev) 790{ 791 struct ingenic_drm *priv = platform_get_drvdata(pdev); 792 793 if (priv->lcd_clk) 794 clk_disable_unprepare(priv->lcd_clk); 795 clk_disable_unprepare(priv->pix_clk); 796 797 drm_dev_unregister(&priv->drm); 798 drm_atomic_helper_shutdown(&priv->drm); 799 800 return 0; 801} 802 803static const struct jz_soc_info jz4740_soc_info = { 804 .needs_dev_clk = true, 805 .max_width = 800, 806 .max_height = 600, 807}; 808 809static const struct jz_soc_info jz4725b_soc_info = { 810 .needs_dev_clk = false, 811 .max_width = 800, 812 .max_height = 600, 813}; 814 815static const struct jz_soc_info jz4770_soc_info = { 816 .needs_dev_clk = false, 817 .max_width = 1280, 818 .max_height = 720, 819}; 820 821static const struct of_device_id ingenic_drm_of_match[] = { 822 { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info }, 823 { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info }, 824 { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info }, 825 { /* sentinel */ }, 826}; 827MODULE_DEVICE_TABLE(of, ingenic_drm_of_match); 828 829static struct platform_driver ingenic_drm_driver = { 830 .driver = { 831 .name = "ingenic-drm", 832 .of_match_table = of_match_ptr(ingenic_drm_of_match), 833 }, 834 .probe = ingenic_drm_probe, 835 .remove = ingenic_drm_remove, 836}; 837module_platform_driver(ingenic_drm_driver); 838 839MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); 840MODULE_DESCRIPTION("DRM driver for the Ingenic SoCs\n"); 841MODULE_LICENSE("GPL v2");