root/drivers/gpu/drm/ingenic/ingenic-drm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ingenic_drm_writeable_reg
  2. drm_device_get_priv
  3. drm_crtc_get_priv
  4. drm_encoder_get_priv
  5. drm_plane_get_priv
  6. ingenic_drm_crtc_atomic_enable
  7. ingenic_drm_crtc_atomic_disable
  8. ingenic_drm_crtc_update_timings
  9. ingenic_drm_crtc_update_ctrl
  10. ingenic_drm_crtc_atomic_check
  11. ingenic_drm_crtc_atomic_flush
  12. ingenic_drm_plane_atomic_update
  13. ingenic_drm_encoder_atomic_mode_set
  14. ingenic_drm_encoder_atomic_check
  15. ingenic_drm_irq_handler
  16. ingenic_drm_release
  17. ingenic_drm_enable_vblank
  18. ingenic_drm_disable_vblank
  19. ingenic_drm_free_dma_hwdesc
  20. ingenic_drm_probe
  21. ingenic_drm_remove

   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 
 146 struct ingenic_dma_hwdesc {
 147         u32 next;
 148         u32 addr;
 149         u32 id;
 150         u32 cmd;
 151 } __packed;
 152 
 153 struct jz_soc_info {
 154         bool needs_dev_clk;
 155 };
 156 
 157 struct 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         bool panel_is_sharp;
 171 };
 172 
 173 static const u32 ingenic_drm_primary_formats[] = {
 174         DRM_FORMAT_XRGB1555,
 175         DRM_FORMAT_RGB565,
 176         DRM_FORMAT_XRGB8888,
 177 };
 178 
 179 static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg)
 180 {
 181         switch (reg) {
 182         case JZ_REG_LCD_IID:
 183         case JZ_REG_LCD_SA0:
 184         case JZ_REG_LCD_FID0:
 185         case JZ_REG_LCD_CMD0:
 186         case JZ_REG_LCD_SA1:
 187         case JZ_REG_LCD_FID1:
 188         case JZ_REG_LCD_CMD1:
 189                 return false;
 190         default:
 191                 return true;
 192         }
 193 }
 194 
 195 static const struct regmap_config ingenic_drm_regmap_config = {
 196         .reg_bits = 32,
 197         .val_bits = 32,
 198         .reg_stride = 4,
 199 
 200         .max_register = JZ_REG_LCD_CMD1,
 201         .writeable_reg = ingenic_drm_writeable_reg,
 202 };
 203 
 204 static inline struct ingenic_drm *drm_device_get_priv(struct drm_device *drm)
 205 {
 206         return container_of(drm, struct ingenic_drm, drm);
 207 }
 208 
 209 static inline struct ingenic_drm *drm_crtc_get_priv(struct drm_crtc *crtc)
 210 {
 211         return container_of(crtc, struct ingenic_drm, crtc);
 212 }
 213 
 214 static inline struct ingenic_drm *
 215 drm_encoder_get_priv(struct drm_encoder *encoder)
 216 {
 217         return container_of(encoder, struct ingenic_drm, encoder);
 218 }
 219 
 220 static inline struct ingenic_drm *drm_plane_get_priv(struct drm_plane *plane)
 221 {
 222         return container_of(plane, struct ingenic_drm, primary);
 223 }
 224 
 225 static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc,
 226                                            struct drm_crtc_state *state)
 227 {
 228         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
 229 
 230         regmap_write(priv->map, JZ_REG_LCD_STATE, 0);
 231 
 232         regmap_update_bits(priv->map, JZ_REG_LCD_CTRL,
 233                            JZ_LCD_CTRL_ENABLE | JZ_LCD_CTRL_DISABLE,
 234                            JZ_LCD_CTRL_ENABLE);
 235 
 236         drm_crtc_vblank_on(crtc);
 237 }
 238 
 239 static void ingenic_drm_crtc_atomic_disable(struct drm_crtc *crtc,
 240                                             struct drm_crtc_state *state)
 241 {
 242         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
 243         unsigned int var;
 244 
 245         drm_crtc_vblank_off(crtc);
 246 
 247         regmap_update_bits(priv->map, JZ_REG_LCD_CTRL,
 248                            JZ_LCD_CTRL_DISABLE, JZ_LCD_CTRL_DISABLE);
 249 
 250         regmap_read_poll_timeout(priv->map, JZ_REG_LCD_STATE, var,
 251                                  var & JZ_LCD_STATE_DISABLED,
 252                                  1000, 0);
 253 }
 254 
 255 static void ingenic_drm_crtc_update_timings(struct ingenic_drm *priv,
 256                                             struct drm_display_mode *mode)
 257 {
 258         unsigned int vpe, vds, vde, vt, hpe, hds, hde, ht;
 259 
 260         vpe = mode->vsync_end - mode->vsync_start;
 261         vds = mode->vtotal - mode->vsync_start;
 262         vde = vds + mode->vdisplay;
 263         vt = vde + mode->vsync_start - mode->vdisplay;
 264 
 265         hpe = mode->hsync_end - mode->hsync_start;
 266         hds = mode->htotal - mode->hsync_start;
 267         hde = hds + mode->hdisplay;
 268         ht = hde + mode->hsync_start - mode->hdisplay;
 269 
 270         regmap_write(priv->map, JZ_REG_LCD_VSYNC,
 271                      0 << JZ_LCD_VSYNC_VPS_OFFSET |
 272                      vpe << JZ_LCD_VSYNC_VPE_OFFSET);
 273 
 274         regmap_write(priv->map, JZ_REG_LCD_HSYNC,
 275                      0 << JZ_LCD_HSYNC_HPS_OFFSET |
 276                      hpe << JZ_LCD_HSYNC_HPE_OFFSET);
 277 
 278         regmap_write(priv->map, JZ_REG_LCD_VAT,
 279                      ht << JZ_LCD_VAT_HT_OFFSET |
 280                      vt << JZ_LCD_VAT_VT_OFFSET);
 281 
 282         regmap_write(priv->map, JZ_REG_LCD_DAH,
 283                      hds << JZ_LCD_DAH_HDS_OFFSET |
 284                      hde << JZ_LCD_DAH_HDE_OFFSET);
 285         regmap_write(priv->map, JZ_REG_LCD_DAV,
 286                      vds << JZ_LCD_DAV_VDS_OFFSET |
 287                      vde << JZ_LCD_DAV_VDE_OFFSET);
 288 
 289         if (priv->panel_is_sharp) {
 290                 regmap_write(priv->map, JZ_REG_LCD_PS, hde << 16 | (hde + 1));
 291                 regmap_write(priv->map, JZ_REG_LCD_CLS, hde << 16 | (hde + 1));
 292                 regmap_write(priv->map, JZ_REG_LCD_SPL, hpe << 16 | (hpe + 1));
 293                 regmap_write(priv->map, JZ_REG_LCD_REV, mode->htotal << 16);
 294         }
 295 }
 296 
 297 static void ingenic_drm_crtc_update_ctrl(struct ingenic_drm *priv,
 298                                          const struct drm_format_info *finfo)
 299 {
 300         unsigned int ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
 301 
 302         switch (finfo->format) {
 303         case DRM_FORMAT_XRGB1555:
 304                 ctrl |= JZ_LCD_CTRL_RGB555;
 305                 /* fall-through */
 306         case DRM_FORMAT_RGB565:
 307                 ctrl |= JZ_LCD_CTRL_BPP_15_16;
 308                 break;
 309         case DRM_FORMAT_XRGB8888:
 310                 ctrl |= JZ_LCD_CTRL_BPP_18_24;
 311                 break;
 312         }
 313 
 314         regmap_update_bits(priv->map, JZ_REG_LCD_CTRL,
 315                            JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16 |
 316                            JZ_LCD_CTRL_BPP_MASK, ctrl);
 317 }
 318 
 319 static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc,
 320                                          struct drm_crtc_state *state)
 321 {
 322         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
 323         long rate;
 324 
 325         if (!drm_atomic_crtc_needs_modeset(state))
 326                 return 0;
 327 
 328         rate = clk_round_rate(priv->pix_clk,
 329                               state->adjusted_mode.clock * 1000);
 330         if (rate < 0)
 331                 return rate;
 332 
 333         return 0;
 334 }
 335 
 336 static void ingenic_drm_crtc_atomic_flush(struct drm_crtc *crtc,
 337                                           struct drm_crtc_state *oldstate)
 338 {
 339         struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
 340         struct drm_crtc_state *state = crtc->state;
 341         struct drm_pending_vblank_event *event = state->event;
 342         struct drm_framebuffer *drm_fb = crtc->primary->state->fb;
 343         const struct drm_format_info *finfo;
 344 
 345         if (drm_atomic_crtc_needs_modeset(state)) {
 346                 finfo = drm_format_info(drm_fb->format->format);
 347 
 348                 ingenic_drm_crtc_update_timings(priv, &state->mode);
 349                 ingenic_drm_crtc_update_ctrl(priv, finfo);
 350 
 351                 clk_set_rate(priv->pix_clk, state->adjusted_mode.clock * 1000);
 352 
 353                 regmap_write(priv->map, JZ_REG_LCD_DA0, priv->dma_hwdesc->next);
 354         }
 355 
 356         if (event) {
 357                 state->event = NULL;
 358 
 359                 spin_lock_irq(&crtc->dev->event_lock);
 360                 if (drm_crtc_vblank_get(crtc) == 0)
 361                         drm_crtc_arm_vblank_event(crtc, event);
 362                 else
 363                         drm_crtc_send_vblank_event(crtc, event);
 364                 spin_unlock_irq(&crtc->dev->event_lock);
 365         }
 366 }
 367 
 368 static void ingenic_drm_plane_atomic_update(struct drm_plane *plane,
 369                                             struct drm_plane_state *oldstate)
 370 {
 371         struct ingenic_drm *priv = drm_plane_get_priv(plane);
 372         struct drm_plane_state *state = plane->state;
 373         unsigned int width, height, cpp;
 374         dma_addr_t addr;
 375 
 376         if (state && state->fb) {
 377                 addr = drm_fb_cma_get_gem_addr(state->fb, state, 0);
 378                 width = state->crtc->state->adjusted_mode.hdisplay;
 379                 height = state->crtc->state->adjusted_mode.vdisplay;
 380                 cpp = state->fb->format->cpp[plane->index];
 381 
 382                 priv->dma_hwdesc->addr = addr;
 383                 priv->dma_hwdesc->cmd = width * height * cpp / 4;
 384                 priv->dma_hwdesc->cmd |= JZ_LCD_CMD_EOF_IRQ;
 385         }
 386 }
 387 
 388 static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
 389                                                 struct drm_crtc_state *crtc_state,
 390                                                 struct drm_connector_state *conn_state)
 391 {
 392         struct ingenic_drm *priv = drm_encoder_get_priv(encoder);
 393         struct drm_display_mode *mode = &crtc_state->adjusted_mode;
 394         struct drm_connector *conn = conn_state->connector;
 395         struct drm_display_info *info = &conn->display_info;
 396         unsigned int cfg;
 397 
 398         priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS;
 399 
 400         if (priv->panel_is_sharp) {
 401                 cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY;
 402         } else {
 403                 cfg = JZ_LCD_CFG_PS_DISABLE | JZ_LCD_CFG_CLS_DISABLE
 404                     | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE;
 405         }
 406 
 407         if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 408                 cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
 409         if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 410                 cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
 411         if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
 412                 cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
 413         if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
 414                 cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
 415 
 416         if (!priv->panel_is_sharp) {
 417                 if (conn->connector_type == DRM_MODE_CONNECTOR_TV) {
 418                         if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 419                                 cfg |= JZ_LCD_CFG_MODE_TV_OUT_I;
 420                         else
 421                                 cfg |= JZ_LCD_CFG_MODE_TV_OUT_P;
 422                 } else {
 423                         switch (*info->bus_formats) {
 424                         case MEDIA_BUS_FMT_RGB565_1X16:
 425                                 cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT;
 426                                 break;
 427                         case MEDIA_BUS_FMT_RGB666_1X18:
 428                                 cfg |= JZ_LCD_CFG_MODE_GENERIC_18BIT;
 429                                 break;
 430                         case MEDIA_BUS_FMT_RGB888_1X24:
 431                                 cfg |= JZ_LCD_CFG_MODE_GENERIC_24BIT;
 432                                 break;
 433                         case MEDIA_BUS_FMT_RGB888_3X8:
 434                                 cfg |= JZ_LCD_CFG_MODE_8BIT_SERIAL;
 435                                 break;
 436                         default:
 437                                 break;
 438                         }
 439                 }
 440         }
 441 
 442         regmap_write(priv->map, JZ_REG_LCD_CFG, cfg);
 443 }
 444 
 445 static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
 446                                             struct drm_crtc_state *crtc_state,
 447                                             struct drm_connector_state *conn_state)
 448 {
 449         struct drm_display_info *info = &conn_state->connector->display_info;
 450 
 451         if (info->num_bus_formats != 1)
 452                 return -EINVAL;
 453 
 454         if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV)
 455                 return 0;
 456 
 457         switch (*info->bus_formats) {
 458         case MEDIA_BUS_FMT_RGB565_1X16:
 459         case MEDIA_BUS_FMT_RGB666_1X18:
 460         case MEDIA_BUS_FMT_RGB888_1X24:
 461         case MEDIA_BUS_FMT_RGB888_3X8:
 462                 return 0;
 463         default:
 464                 return -EINVAL;
 465         }
 466 }
 467 
 468 static irqreturn_t ingenic_drm_irq_handler(int irq, void *arg)
 469 {
 470         struct ingenic_drm *priv = drm_device_get_priv(arg);
 471         unsigned int state;
 472 
 473         regmap_read(priv->map, JZ_REG_LCD_STATE, &state);
 474 
 475         regmap_update_bits(priv->map, JZ_REG_LCD_STATE,
 476                            JZ_LCD_STATE_EOF_IRQ, 0);
 477 
 478         if (state & JZ_LCD_STATE_EOF_IRQ)
 479                 drm_crtc_handle_vblank(&priv->crtc);
 480 
 481         return IRQ_HANDLED;
 482 }
 483 
 484 static void ingenic_drm_release(struct drm_device *drm)
 485 {
 486         struct ingenic_drm *priv = drm_device_get_priv(drm);
 487 
 488         drm_mode_config_cleanup(drm);
 489         drm_dev_fini(drm);
 490         kfree(priv);
 491 }
 492 
 493 static 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 
 503 static 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 
 510 DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops);
 511 
 512 static 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         .release                = ingenic_drm_release,
 537 };
 538 
 539 static const struct drm_plane_funcs ingenic_drm_primary_plane_funcs = {
 540         .update_plane           = drm_atomic_helper_update_plane,
 541         .disable_plane          = drm_atomic_helper_disable_plane,
 542         .reset                  = drm_atomic_helper_plane_reset,
 543         .destroy                = drm_plane_cleanup,
 544 
 545         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
 546         .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
 547 };
 548 
 549 static const struct drm_crtc_funcs ingenic_drm_crtc_funcs = {
 550         .set_config             = drm_atomic_helper_set_config,
 551         .page_flip              = drm_atomic_helper_page_flip,
 552         .reset                  = drm_atomic_helper_crtc_reset,
 553         .destroy                = drm_crtc_cleanup,
 554 
 555         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 556         .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
 557 
 558         .enable_vblank          = ingenic_drm_enable_vblank,
 559         .disable_vblank         = ingenic_drm_disable_vblank,
 560 
 561         .gamma_set              = drm_atomic_helper_legacy_gamma_set,
 562 };
 563 
 564 static const struct drm_plane_helper_funcs ingenic_drm_plane_helper_funcs = {
 565         .atomic_update          = ingenic_drm_plane_atomic_update,
 566         .prepare_fb             = drm_gem_fb_prepare_fb,
 567 };
 568 
 569 static const struct drm_crtc_helper_funcs ingenic_drm_crtc_helper_funcs = {
 570         .atomic_enable          = ingenic_drm_crtc_atomic_enable,
 571         .atomic_disable         = ingenic_drm_crtc_atomic_disable,
 572         .atomic_flush           = ingenic_drm_crtc_atomic_flush,
 573         .atomic_check           = ingenic_drm_crtc_atomic_check,
 574 };
 575 
 576 static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = {
 577         .atomic_mode_set        = ingenic_drm_encoder_atomic_mode_set,
 578         .atomic_check           = ingenic_drm_encoder_atomic_check,
 579 };
 580 
 581 static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
 582         .fb_create              = drm_gem_fb_create,
 583         .output_poll_changed    = drm_fb_helper_output_poll_changed,
 584         .atomic_check           = drm_atomic_helper_check,
 585         .atomic_commit          = drm_atomic_helper_commit,
 586 };
 587 
 588 static const struct drm_encoder_funcs ingenic_drm_encoder_funcs = {
 589         .destroy                = drm_encoder_cleanup,
 590 };
 591 
 592 static void ingenic_drm_free_dma_hwdesc(void *d)
 593 {
 594         struct ingenic_drm *priv = d;
 595 
 596         dma_free_coherent(priv->dev, sizeof(*priv->dma_hwdesc),
 597                           priv->dma_hwdesc, priv->dma_hwdesc_phys);
 598 }
 599 
 600 static int ingenic_drm_probe(struct platform_device *pdev)
 601 {
 602         const struct jz_soc_info *soc_info;
 603         struct device *dev = &pdev->dev;
 604         struct ingenic_drm *priv;
 605         struct clk *parent_clk;
 606         struct drm_bridge *bridge;
 607         struct drm_panel *panel;
 608         struct drm_device *drm;
 609         void __iomem *base;
 610         long parent_rate;
 611         int ret, irq;
 612 
 613         soc_info = of_device_get_match_data(dev);
 614         if (!soc_info) {
 615                 dev_err(dev, "Missing platform data\n");
 616                 return -EINVAL;
 617         }
 618 
 619         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 620         if (!priv)
 621                 return -ENOMEM;
 622 
 623         priv->dev = dev;
 624         drm = &priv->drm;
 625         drm->dev_private = priv;
 626 
 627         platform_set_drvdata(pdev, priv);
 628 
 629         ret = devm_drm_dev_init(dev, drm, &ingenic_drm_driver_data);
 630         if (ret) {
 631                 kfree(priv);
 632                 return ret;
 633         }
 634 
 635         drm_mode_config_init(drm);
 636         drm->mode_config.min_width = 0;
 637         drm->mode_config.min_height = 0;
 638         drm->mode_config.max_width = 800;
 639         drm->mode_config.max_height = 600;
 640         drm->mode_config.funcs = &ingenic_drm_mode_config_funcs;
 641 
 642         base = devm_platform_ioremap_resource(pdev, 0);
 643         if (IS_ERR(base)) {
 644                 dev_err(dev, "Failed to get memory resource");
 645                 return PTR_ERR(base);
 646         }
 647 
 648         priv->map = devm_regmap_init_mmio(dev, base,
 649                                           &ingenic_drm_regmap_config);
 650         if (IS_ERR(priv->map)) {
 651                 dev_err(dev, "Failed to create regmap");
 652                 return PTR_ERR(priv->map);
 653         }
 654 
 655         irq = platform_get_irq(pdev, 0);
 656         if (irq < 0) {
 657                 dev_err(dev, "Failed to get platform irq");
 658                 return irq;
 659         }
 660 
 661         if (soc_info->needs_dev_clk) {
 662                 priv->lcd_clk = devm_clk_get(dev, "lcd");
 663                 if (IS_ERR(priv->lcd_clk)) {
 664                         dev_err(dev, "Failed to get lcd clock");
 665                         return PTR_ERR(priv->lcd_clk);
 666                 }
 667         }
 668 
 669         priv->pix_clk = devm_clk_get(dev, "lcd_pclk");
 670         if (IS_ERR(priv->pix_clk)) {
 671                 dev_err(dev, "Failed to get pixel clock");
 672                 return PTR_ERR(priv->pix_clk);
 673         }
 674 
 675         ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, &bridge);
 676         if (ret) {
 677                 if (ret != -EPROBE_DEFER)
 678                         dev_err(dev, "Failed to get panel handle");
 679                 return ret;
 680         }
 681 
 682         if (panel)
 683                 bridge = devm_drm_panel_bridge_add(dev, panel,
 684                                                    DRM_MODE_CONNECTOR_DPI);
 685 
 686         priv->dma_hwdesc = dma_alloc_coherent(dev, sizeof(*priv->dma_hwdesc),
 687                                               &priv->dma_hwdesc_phys,
 688                                               GFP_KERNEL);
 689         if (!priv->dma_hwdesc)
 690                 return -ENOMEM;
 691 
 692         ret = devm_add_action_or_reset(dev, ingenic_drm_free_dma_hwdesc, priv);
 693         if (ret)
 694                 return ret;
 695 
 696         priv->dma_hwdesc->next = priv->dma_hwdesc_phys;
 697         priv->dma_hwdesc->id = 0xdeafbead;
 698 
 699         drm_plane_helper_add(&priv->primary, &ingenic_drm_plane_helper_funcs);
 700 
 701         ret = drm_universal_plane_init(drm, &priv->primary,
 702                                        0, &ingenic_drm_primary_plane_funcs,
 703                                        ingenic_drm_primary_formats,
 704                                        ARRAY_SIZE(ingenic_drm_primary_formats),
 705                                        NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 706         if (ret) {
 707                 dev_err(dev, "Failed to register primary plane: %i", ret);
 708                 return ret;
 709         }
 710 
 711         drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs);
 712 
 713         ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->primary,
 714                                         NULL, &ingenic_drm_crtc_funcs, NULL);
 715         if (ret) {
 716                 dev_err(dev, "Failed to init CRTC: %i", ret);
 717                 return ret;
 718         }
 719 
 720         priv->encoder.possible_crtcs = 1;
 721 
 722         drm_encoder_helper_add(&priv->encoder,
 723                                &ingenic_drm_encoder_helper_funcs);
 724 
 725         ret = drm_encoder_init(drm, &priv->encoder, &ingenic_drm_encoder_funcs,
 726                                DRM_MODE_ENCODER_DPI, NULL);
 727         if (ret) {
 728                 dev_err(dev, "Failed to init encoder: %i", ret);
 729                 return ret;
 730         }
 731 
 732         ret = drm_bridge_attach(&priv->encoder, bridge, NULL);
 733         if (ret) {
 734                 dev_err(dev, "Unable to attach bridge");
 735                 return ret;
 736         }
 737 
 738         ret = drm_irq_install(drm, irq);
 739         if (ret) {
 740                 dev_err(dev, "Unable to install IRQ handler");
 741                 return ret;
 742         }
 743 
 744         ret = drm_vblank_init(drm, 1);
 745         if (ret) {
 746                 dev_err(dev, "Failed calling drm_vblank_init()");
 747                 return ret;
 748         }
 749 
 750         drm_mode_config_reset(drm);
 751 
 752         ret = clk_prepare_enable(priv->pix_clk);
 753         if (ret) {
 754                 dev_err(dev, "Unable to start pixel clock");
 755                 return ret;
 756         }
 757 
 758         if (priv->lcd_clk) {
 759                 parent_clk = clk_get_parent(priv->lcd_clk);
 760                 parent_rate = clk_get_rate(parent_clk);
 761 
 762                 /* LCD Device clock must be 3x the pixel clock for STN panels,
 763                  * or 1.5x the pixel clock for TFT panels. To avoid having to
 764                  * check for the LCD device clock everytime we do a mode change,
 765                  * we set the LCD device clock to the highest rate possible.
 766                  */
 767                 ret = clk_set_rate(priv->lcd_clk, parent_rate);
 768                 if (ret) {
 769                         dev_err(dev, "Unable to set LCD clock rate");
 770                         goto err_pixclk_disable;
 771                 }
 772 
 773                 ret = clk_prepare_enable(priv->lcd_clk);
 774                 if (ret) {
 775                         dev_err(dev, "Unable to start lcd clock");
 776                         goto err_pixclk_disable;
 777                 }
 778         }
 779 
 780         ret = drm_dev_register(drm, 0);
 781         if (ret) {
 782                 dev_err(dev, "Failed to register DRM driver");
 783                 goto err_devclk_disable;
 784         }
 785 
 786         ret = drm_fbdev_generic_setup(drm, 32);
 787         if (ret)
 788                 dev_warn(dev, "Unable to start fbdev emulation: %i", ret);
 789 
 790         return 0;
 791 
 792 err_devclk_disable:
 793         if (priv->lcd_clk)
 794                 clk_disable_unprepare(priv->lcd_clk);
 795 err_pixclk_disable:
 796         clk_disable_unprepare(priv->pix_clk);
 797         return ret;
 798 }
 799 
 800 static int ingenic_drm_remove(struct platform_device *pdev)
 801 {
 802         struct ingenic_drm *priv = platform_get_drvdata(pdev);
 803 
 804         if (priv->lcd_clk)
 805                 clk_disable_unprepare(priv->lcd_clk);
 806         clk_disable_unprepare(priv->pix_clk);
 807 
 808         drm_dev_unregister(&priv->drm);
 809         drm_atomic_helper_shutdown(&priv->drm);
 810 
 811         return 0;
 812 }
 813 
 814 static const struct jz_soc_info jz4740_soc_info = {
 815         .needs_dev_clk = true,
 816 };
 817 
 818 static const struct jz_soc_info jz4725b_soc_info = {
 819         .needs_dev_clk = false,
 820 };
 821 
 822 static const struct of_device_id ingenic_drm_of_match[] = {
 823         { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info },
 824         { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info },
 825         { /* sentinel */ },
 826 };
 827 MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);
 828 
 829 static 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 };
 837 module_platform_driver(ingenic_drm_driver);
 838 
 839 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
 840 MODULE_DESCRIPTION("DRM driver for the Ingenic SoCs\n");
 841 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */