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