0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/clk.h>
0011 #include <linux/component.h>
0012 #include <linux/of_device.h>
0013 #include <linux/of_graph.h>
0014 #include <linux/of_reserved_mem.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/debugfs.h>
0017
0018 #include <drm/drm_atomic.h>
0019 #include <drm/drm_atomic_helper.h>
0020 #include <drm/drm_crtc.h>
0021 #include <drm/drm_drv.h>
0022 #include <drm/drm_fb_cma_helper.h>
0023 #include <drm/drm_fb_helper.h>
0024 #include <drm/drm_fourcc.h>
0025 #include <drm/drm_gem_cma_helper.h>
0026 #include <drm/drm_gem_framebuffer_helper.h>
0027 #include <drm/drm_modeset_helper.h>
0028 #include <drm/drm_module.h>
0029 #include <drm/drm_of.h>
0030 #include <drm/drm_probe_helper.h>
0031 #include <drm/drm_vblank.h>
0032
0033 #include "malidp_drv.h"
0034 #include "malidp_mw.h"
0035 #include "malidp_regs.h"
0036 #include "malidp_hw.h"
0037
0038 #define MALIDP_CONF_VALID_TIMEOUT 250
0039 #define AFBC_HEADER_SIZE 16
0040 #define AFBC_SUPERBLK_ALIGNMENT 128
0041
0042 static void malidp_write_gamma_table(struct malidp_hw_device *hwdev,
0043 u32 data[MALIDP_COEFFTAB_NUM_COEFFS])
0044 {
0045 int i;
0046
0047 const u32 gamma_write_mask = GENMASK(18, 16);
0048
0049
0050
0051
0052
0053 malidp_hw_write(hwdev, gamma_write_mask,
0054 hwdev->hw->map.coeffs_base + MALIDP_COEF_TABLE_ADDR);
0055 for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i)
0056 malidp_hw_write(hwdev, data[i],
0057 hwdev->hw->map.coeffs_base +
0058 MALIDP_COEF_TABLE_DATA);
0059 }
0060
0061 static void malidp_atomic_commit_update_gamma(struct drm_crtc *crtc,
0062 struct drm_crtc_state *old_state)
0063 {
0064 struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
0065 struct malidp_hw_device *hwdev = malidp->dev;
0066
0067 if (!crtc->state->color_mgmt_changed)
0068 return;
0069
0070 if (!crtc->state->gamma_lut) {
0071 malidp_hw_clearbits(hwdev,
0072 MALIDP_DISP_FUNC_GAMMA,
0073 MALIDP_DE_DISPLAY_FUNC);
0074 } else {
0075 struct malidp_crtc_state *mc =
0076 to_malidp_crtc_state(crtc->state);
0077
0078 if (!old_state->gamma_lut || (crtc->state->gamma_lut->base.id !=
0079 old_state->gamma_lut->base.id))
0080 malidp_write_gamma_table(hwdev, mc->gamma_coeffs);
0081
0082 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_GAMMA,
0083 MALIDP_DE_DISPLAY_FUNC);
0084 }
0085 }
0086
0087 static
0088 void malidp_atomic_commit_update_coloradj(struct drm_crtc *crtc,
0089 struct drm_crtc_state *old_state)
0090 {
0091 struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
0092 struct malidp_hw_device *hwdev = malidp->dev;
0093 int i;
0094
0095 if (!crtc->state->color_mgmt_changed)
0096 return;
0097
0098 if (!crtc->state->ctm) {
0099 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_CADJ,
0100 MALIDP_DE_DISPLAY_FUNC);
0101 } else {
0102 struct malidp_crtc_state *mc =
0103 to_malidp_crtc_state(crtc->state);
0104
0105 if (!old_state->ctm || (crtc->state->ctm->base.id !=
0106 old_state->ctm->base.id))
0107 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; ++i)
0108 malidp_hw_write(hwdev,
0109 mc->coloradj_coeffs[i],
0110 hwdev->hw->map.coeffs_base +
0111 MALIDP_COLOR_ADJ_COEF + 4 * i);
0112
0113 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_CADJ,
0114 MALIDP_DE_DISPLAY_FUNC);
0115 }
0116 }
0117
0118 static void malidp_atomic_commit_se_config(struct drm_crtc *crtc,
0119 struct drm_crtc_state *old_state)
0120 {
0121 struct malidp_crtc_state *cs = to_malidp_crtc_state(crtc->state);
0122 struct malidp_crtc_state *old_cs = to_malidp_crtc_state(old_state);
0123 struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
0124 struct malidp_hw_device *hwdev = malidp->dev;
0125 struct malidp_se_config *s = &cs->scaler_config;
0126 struct malidp_se_config *old_s = &old_cs->scaler_config;
0127 u32 se_control = hwdev->hw->map.se_base +
0128 ((hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ?
0129 0x10 : 0xC);
0130 u32 layer_control = se_control + MALIDP_SE_LAYER_CONTROL;
0131 u32 scr = se_control + MALIDP_SE_SCALING_CONTROL;
0132 u32 val;
0133
0134
0135 if (!s->scale_enable) {
0136 val = malidp_hw_read(hwdev, se_control);
0137 val &= ~MALIDP_SE_SCALING_EN;
0138 malidp_hw_write(hwdev, val, se_control);
0139 return;
0140 }
0141
0142 hwdev->hw->se_set_scaling_coeffs(hwdev, s, old_s);
0143 val = malidp_hw_read(hwdev, se_control);
0144 val |= MALIDP_SE_SCALING_EN | MALIDP_SE_ALPHA_EN;
0145
0146 val &= ~MALIDP_SE_ENH(MALIDP_SE_ENH_MASK);
0147 val |= s->enhancer_enable ? MALIDP_SE_ENH(3) : 0;
0148
0149 val |= MALIDP_SE_RGBO_IF_EN;
0150 malidp_hw_write(hwdev, val, se_control);
0151
0152
0153 val = MALIDP_SE_SET_V_SIZE(s->input_h) |
0154 MALIDP_SE_SET_H_SIZE(s->input_w);
0155 malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_IN_SIZE);
0156 val = MALIDP_SE_SET_V_SIZE(s->output_h) |
0157 MALIDP_SE_SET_H_SIZE(s->output_w);
0158 malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_OUT_SIZE);
0159
0160
0161 malidp_hw_write(hwdev, s->h_init_phase, scr + MALIDP_SE_H_INIT_PH);
0162 malidp_hw_write(hwdev, s->h_delta_phase, scr + MALIDP_SE_H_DELTA_PH);
0163 malidp_hw_write(hwdev, s->v_init_phase, scr + MALIDP_SE_V_INIT_PH);
0164 malidp_hw_write(hwdev, s->v_delta_phase, scr + MALIDP_SE_V_DELTA_PH);
0165 }
0166
0167
0168
0169
0170 static int malidp_set_and_wait_config_valid(struct drm_device *drm)
0171 {
0172 struct malidp_drm *malidp = drm->dev_private;
0173 struct malidp_hw_device *hwdev = malidp->dev;
0174 int ret;
0175
0176 hwdev->hw->set_config_valid(hwdev, 1);
0177
0178 if (hwdev->hw->in_config_mode(hwdev)) {
0179 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
0180 return 0;
0181 }
0182
0183 ret = wait_event_interruptible_timeout(malidp->wq,
0184 atomic_read(&malidp->config_valid) == MALIDP_CONFIG_VALID_DONE,
0185 msecs_to_jiffies(MALIDP_CONF_VALID_TIMEOUT));
0186
0187 return (ret > 0) ? 0 : -ETIMEDOUT;
0188 }
0189
0190 static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
0191 {
0192 struct drm_device *drm = state->dev;
0193 struct malidp_drm *malidp = drm->dev_private;
0194 int loop = 5;
0195
0196 malidp->event = malidp->crtc.state->event;
0197 malidp->crtc.state->event = NULL;
0198
0199 if (malidp->crtc.state->active) {
0200
0201
0202
0203
0204
0205 if (malidp->event)
0206 drm_crtc_vblank_get(&malidp->crtc);
0207
0208
0209 if (malidp_set_and_wait_config_valid(drm) < 0) {
0210
0211
0212
0213
0214 while (loop--) {
0215 if (!malidp_set_and_wait_config_valid(drm))
0216 break;
0217 }
0218 DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n");
0219 }
0220
0221 } else if (malidp->event) {
0222
0223 spin_lock_irq(&drm->event_lock);
0224 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
0225 malidp->event = NULL;
0226 spin_unlock_irq(&drm->event_lock);
0227 }
0228 drm_atomic_helper_commit_hw_done(state);
0229 }
0230
0231 static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
0232 {
0233 struct drm_device *drm = state->dev;
0234 struct malidp_drm *malidp = drm->dev_private;
0235 struct drm_crtc *crtc;
0236 struct drm_crtc_state *old_crtc_state;
0237 int i;
0238 bool fence_cookie = dma_fence_begin_signalling();
0239
0240 pm_runtime_get_sync(drm->dev);
0241
0242
0243
0244
0245
0246 atomic_set(&malidp->config_valid, MALIDP_CONFIG_START);
0247 malidp->dev->hw->set_config_valid(malidp->dev, 0);
0248
0249 drm_atomic_helper_commit_modeset_disables(drm, state);
0250
0251 for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
0252 malidp_atomic_commit_update_gamma(crtc, old_crtc_state);
0253 malidp_atomic_commit_update_coloradj(crtc, old_crtc_state);
0254 malidp_atomic_commit_se_config(crtc, old_crtc_state);
0255 }
0256
0257 drm_atomic_helper_commit_planes(drm, state, DRM_PLANE_COMMIT_ACTIVE_ONLY);
0258
0259 malidp_mw_atomic_commit(drm, state);
0260
0261 drm_atomic_helper_commit_modeset_enables(drm, state);
0262
0263 malidp_atomic_commit_hw_done(state);
0264
0265 dma_fence_end_signalling(fence_cookie);
0266
0267 pm_runtime_put(drm->dev);
0268
0269 drm_atomic_helper_cleanup_planes(drm, state);
0270 }
0271
0272 static const struct drm_mode_config_helper_funcs malidp_mode_config_helpers = {
0273 .atomic_commit_tail = malidp_atomic_commit_tail,
0274 };
0275
0276 static bool
0277 malidp_verify_afbc_framebuffer_caps(struct drm_device *dev,
0278 const struct drm_mode_fb_cmd2 *mode_cmd)
0279 {
0280 if (malidp_format_mod_supported(dev, mode_cmd->pixel_format,
0281 mode_cmd->modifier[0]) == false)
0282 return false;
0283
0284 if (mode_cmd->offsets[0] != 0) {
0285 DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n");
0286 return false;
0287 }
0288
0289 switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
0290 case AFBC_SIZE_16X16:
0291 if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) {
0292 DRM_DEBUG_KMS("AFBC buffers must be aligned to 16 pixels\n");
0293 return false;
0294 }
0295 break;
0296 default:
0297 DRM_DEBUG_KMS("Unsupported AFBC block size\n");
0298 return false;
0299 }
0300
0301 return true;
0302 }
0303
0304 static bool
0305 malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
0306 struct drm_file *file,
0307 const struct drm_mode_fb_cmd2 *mode_cmd)
0308 {
0309 int n_superblocks = 0;
0310 const struct drm_format_info *info;
0311 struct drm_gem_object *objs = NULL;
0312 u32 afbc_superblock_size = 0, afbc_superblock_height = 0;
0313 u32 afbc_superblock_width = 0, afbc_size = 0;
0314 int bpp = 0;
0315
0316 switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
0317 case AFBC_SIZE_16X16:
0318 afbc_superblock_height = 16;
0319 afbc_superblock_width = 16;
0320 break;
0321 default:
0322 DRM_DEBUG_KMS("AFBC superblock size is not supported\n");
0323 return false;
0324 }
0325
0326 info = drm_get_format_info(dev, mode_cmd);
0327
0328 n_superblocks = (mode_cmd->width / afbc_superblock_width) *
0329 (mode_cmd->height / afbc_superblock_height);
0330
0331 bpp = malidp_format_get_bpp(info->format);
0332
0333 afbc_superblock_size = (bpp * afbc_superblock_width * afbc_superblock_height)
0334 / BITS_PER_BYTE;
0335
0336 afbc_size = ALIGN(n_superblocks * AFBC_HEADER_SIZE, AFBC_SUPERBLK_ALIGNMENT);
0337 afbc_size += n_superblocks * ALIGN(afbc_superblock_size, AFBC_SUPERBLK_ALIGNMENT);
0338
0339 if ((mode_cmd->width * bpp) != (mode_cmd->pitches[0] * BITS_PER_BYTE)) {
0340 DRM_DEBUG_KMS("Invalid value of (pitch * BITS_PER_BYTE) (=%u) "
0341 "should be same as width (=%u) * bpp (=%u)\n",
0342 (mode_cmd->pitches[0] * BITS_PER_BYTE),
0343 mode_cmd->width, bpp);
0344 return false;
0345 }
0346
0347 objs = drm_gem_object_lookup(file, mode_cmd->handles[0]);
0348 if (!objs) {
0349 DRM_DEBUG_KMS("Failed to lookup GEM object\n");
0350 return false;
0351 }
0352
0353 if (objs->size < afbc_size) {
0354 DRM_DEBUG_KMS("buffer size (%zu) too small for AFBC buffer size = %u\n",
0355 objs->size, afbc_size);
0356 drm_gem_object_put(objs);
0357 return false;
0358 }
0359
0360 drm_gem_object_put(objs);
0361
0362 return true;
0363 }
0364
0365 static bool
0366 malidp_verify_afbc_framebuffer(struct drm_device *dev, struct drm_file *file,
0367 const struct drm_mode_fb_cmd2 *mode_cmd)
0368 {
0369 if (malidp_verify_afbc_framebuffer_caps(dev, mode_cmd))
0370 return malidp_verify_afbc_framebuffer_size(dev, file, mode_cmd);
0371
0372 return false;
0373 }
0374
0375 static struct drm_framebuffer *
0376 malidp_fb_create(struct drm_device *dev, struct drm_file *file,
0377 const struct drm_mode_fb_cmd2 *mode_cmd)
0378 {
0379 if (mode_cmd->modifier[0]) {
0380 if (!malidp_verify_afbc_framebuffer(dev, file, mode_cmd))
0381 return ERR_PTR(-EINVAL);
0382 }
0383
0384 return drm_gem_fb_create(dev, file, mode_cmd);
0385 }
0386
0387 static const struct drm_mode_config_funcs malidp_mode_config_funcs = {
0388 .fb_create = malidp_fb_create,
0389 .atomic_check = drm_atomic_helper_check,
0390 .atomic_commit = drm_atomic_helper_commit,
0391 };
0392
0393 static int malidp_init(struct drm_device *drm)
0394 {
0395 int ret;
0396 struct malidp_drm *malidp = drm->dev_private;
0397 struct malidp_hw_device *hwdev = malidp->dev;
0398
0399 drm_mode_config_init(drm);
0400
0401 drm->mode_config.min_width = hwdev->min_line_size;
0402 drm->mode_config.min_height = hwdev->min_line_size;
0403 drm->mode_config.max_width = hwdev->max_line_size;
0404 drm->mode_config.max_height = hwdev->max_line_size;
0405 drm->mode_config.funcs = &malidp_mode_config_funcs;
0406 drm->mode_config.helper_private = &malidp_mode_config_helpers;
0407
0408 ret = malidp_crtc_init(drm);
0409 if (ret)
0410 goto crtc_fail;
0411
0412 ret = malidp_mw_connector_init(drm);
0413 if (ret)
0414 goto crtc_fail;
0415
0416 return 0;
0417
0418 crtc_fail:
0419 drm_mode_config_cleanup(drm);
0420 return ret;
0421 }
0422
0423 static void malidp_fini(struct drm_device *drm)
0424 {
0425 drm_mode_config_cleanup(drm);
0426 }
0427
0428 static int malidp_irq_init(struct platform_device *pdev)
0429 {
0430 int irq_de, irq_se, ret = 0;
0431 struct drm_device *drm = dev_get_drvdata(&pdev->dev);
0432 struct malidp_drm *malidp = drm->dev_private;
0433 struct malidp_hw_device *hwdev = malidp->dev;
0434
0435
0436 irq_de = platform_get_irq_byname(pdev, "DE");
0437 if (irq_de < 0) {
0438 DRM_ERROR("no 'DE' IRQ specified!\n");
0439 return irq_de;
0440 }
0441 irq_se = platform_get_irq_byname(pdev, "SE");
0442 if (irq_se < 0) {
0443 DRM_ERROR("no 'SE' IRQ specified!\n");
0444 return irq_se;
0445 }
0446
0447 ret = malidp_de_irq_init(drm, irq_de);
0448 if (ret)
0449 return ret;
0450
0451 ret = malidp_se_irq_init(drm, irq_se);
0452 if (ret) {
0453 malidp_de_irq_fini(hwdev);
0454 return ret;
0455 }
0456
0457 return 0;
0458 }
0459
0460 DEFINE_DRM_GEM_CMA_FOPS(fops);
0461
0462 static int malidp_dumb_create(struct drm_file *file_priv,
0463 struct drm_device *drm,
0464 struct drm_mode_create_dumb *args)
0465 {
0466 struct malidp_drm *malidp = drm->dev_private;
0467
0468 u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 1);
0469
0470 args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), alignment);
0471
0472 return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
0473 }
0474
0475 #ifdef CONFIG_DEBUG_FS
0476
0477 static void malidp_error_stats_init(struct malidp_error_stats *error_stats)
0478 {
0479 error_stats->num_errors = 0;
0480 error_stats->last_error_status = 0;
0481 error_stats->last_error_vblank = -1;
0482 }
0483
0484 void malidp_error(struct malidp_drm *malidp,
0485 struct malidp_error_stats *error_stats, u32 status,
0486 u64 vblank)
0487 {
0488 unsigned long irqflags;
0489
0490 spin_lock_irqsave(&malidp->errors_lock, irqflags);
0491 error_stats->last_error_status = status;
0492 error_stats->last_error_vblank = vblank;
0493 error_stats->num_errors++;
0494 spin_unlock_irqrestore(&malidp->errors_lock, irqflags);
0495 }
0496
0497 static void malidp_error_stats_dump(const char *prefix,
0498 struct malidp_error_stats error_stats,
0499 struct seq_file *m)
0500 {
0501 seq_printf(m, "[%s] num_errors : %d\n", prefix,
0502 error_stats.num_errors);
0503 seq_printf(m, "[%s] last_error_status : 0x%08x\n", prefix,
0504 error_stats.last_error_status);
0505 seq_printf(m, "[%s] last_error_vblank : %lld\n", prefix,
0506 error_stats.last_error_vblank);
0507 }
0508
0509 static int malidp_show_stats(struct seq_file *m, void *arg)
0510 {
0511 struct drm_device *drm = m->private;
0512 struct malidp_drm *malidp = drm->dev_private;
0513 unsigned long irqflags;
0514 struct malidp_error_stats de_errors, se_errors;
0515
0516 spin_lock_irqsave(&malidp->errors_lock, irqflags);
0517 de_errors = malidp->de_errors;
0518 se_errors = malidp->se_errors;
0519 spin_unlock_irqrestore(&malidp->errors_lock, irqflags);
0520 malidp_error_stats_dump("DE", de_errors, m);
0521 malidp_error_stats_dump("SE", se_errors, m);
0522 return 0;
0523 }
0524
0525 static int malidp_debugfs_open(struct inode *inode, struct file *file)
0526 {
0527 return single_open(file, malidp_show_stats, inode->i_private);
0528 }
0529
0530 static ssize_t malidp_debugfs_write(struct file *file, const char __user *ubuf,
0531 size_t len, loff_t *offp)
0532 {
0533 struct seq_file *m = file->private_data;
0534 struct drm_device *drm = m->private;
0535 struct malidp_drm *malidp = drm->dev_private;
0536 unsigned long irqflags;
0537
0538 spin_lock_irqsave(&malidp->errors_lock, irqflags);
0539 malidp_error_stats_init(&malidp->de_errors);
0540 malidp_error_stats_init(&malidp->se_errors);
0541 spin_unlock_irqrestore(&malidp->errors_lock, irqflags);
0542 return len;
0543 }
0544
0545 static const struct file_operations malidp_debugfs_fops = {
0546 .owner = THIS_MODULE,
0547 .open = malidp_debugfs_open,
0548 .read = seq_read,
0549 .write = malidp_debugfs_write,
0550 .llseek = seq_lseek,
0551 .release = single_release,
0552 };
0553
0554 static void malidp_debugfs_init(struct drm_minor *minor)
0555 {
0556 struct malidp_drm *malidp = minor->dev->dev_private;
0557
0558 malidp_error_stats_init(&malidp->de_errors);
0559 malidp_error_stats_init(&malidp->se_errors);
0560 spin_lock_init(&malidp->errors_lock);
0561 debugfs_create_file("debug", S_IRUGO | S_IWUSR, minor->debugfs_root,
0562 minor->dev, &malidp_debugfs_fops);
0563 }
0564
0565 #endif
0566
0567 static const struct drm_driver malidp_driver = {
0568 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
0569 DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create),
0570 #ifdef CONFIG_DEBUG_FS
0571 .debugfs_init = malidp_debugfs_init,
0572 #endif
0573 .fops = &fops,
0574 .name = "mali-dp",
0575 .desc = "ARM Mali Display Processor driver",
0576 .date = "20160106",
0577 .major = 1,
0578 .minor = 0,
0579 };
0580
0581 static const struct of_device_id malidp_drm_of_match[] = {
0582 {
0583 .compatible = "arm,mali-dp500",
0584 .data = &malidp_device[MALIDP_500]
0585 },
0586 {
0587 .compatible = "arm,mali-dp550",
0588 .data = &malidp_device[MALIDP_550]
0589 },
0590 {
0591 .compatible = "arm,mali-dp650",
0592 .data = &malidp_device[MALIDP_650]
0593 },
0594 {},
0595 };
0596 MODULE_DEVICE_TABLE(of, malidp_drm_of_match);
0597
0598 static bool malidp_is_compatible_hw_id(struct malidp_hw_device *hwdev,
0599 const struct of_device_id *dev_id)
0600 {
0601 u32 core_id;
0602 const char *compatstr_dp500 = "arm,mali-dp500";
0603 bool is_dp500;
0604 bool dt_is_dp500;
0605
0606
0607
0608
0609
0610
0611 core_id = malidp_hw_read(hwdev, MALIDP500_DC_BASE + MALIDP_DE_CORE_ID);
0612
0613 is_dp500 = (MALIDP_PRODUCT_ID(core_id) == 0x500);
0614 dt_is_dp500 = strnstr(dev_id->compatible, compatstr_dp500,
0615 sizeof(dev_id->compatible)) != NULL;
0616 if (is_dp500 != dt_is_dp500) {
0617 DRM_ERROR("Device-tree expects %s, but hardware %s DP500.\n",
0618 dev_id->compatible, is_dp500 ? "is" : "is not");
0619 return false;
0620 } else if (!dt_is_dp500) {
0621 u16 product_id;
0622 char buf[32];
0623
0624 core_id = malidp_hw_read(hwdev,
0625 MALIDP550_DC_BASE + MALIDP_DE_CORE_ID);
0626 product_id = MALIDP_PRODUCT_ID(core_id);
0627 snprintf(buf, sizeof(buf), "arm,mali-dp%X", product_id);
0628 if (!strnstr(dev_id->compatible, buf,
0629 sizeof(dev_id->compatible))) {
0630 DRM_ERROR("Device-tree expects %s, but hardware is DP%03X.\n",
0631 dev_id->compatible, product_id);
0632 return false;
0633 }
0634 }
0635 return true;
0636 }
0637
0638 static bool malidp_has_sufficient_address_space(const struct resource *res,
0639 const struct of_device_id *dev_id)
0640 {
0641 resource_size_t res_size = resource_size(res);
0642 const char *compatstr_dp500 = "arm,mali-dp500";
0643
0644 if (!strnstr(dev_id->compatible, compatstr_dp500,
0645 sizeof(dev_id->compatible)))
0646 return res_size >= MALIDP550_ADDR_SPACE_SIZE;
0647 else if (res_size < MALIDP500_ADDR_SPACE_SIZE)
0648 return false;
0649 return true;
0650 }
0651
0652 static ssize_t core_id_show(struct device *dev, struct device_attribute *attr,
0653 char *buf)
0654 {
0655 struct drm_device *drm = dev_get_drvdata(dev);
0656 struct malidp_drm *malidp = drm->dev_private;
0657
0658 return snprintf(buf, PAGE_SIZE, "%08x\n", malidp->core_id);
0659 }
0660
0661 static DEVICE_ATTR_RO(core_id);
0662
0663 static struct attribute *mali_dp_attrs[] = {
0664 &dev_attr_core_id.attr,
0665 NULL,
0666 };
0667 ATTRIBUTE_GROUPS(mali_dp);
0668
0669 #define MAX_OUTPUT_CHANNELS 3
0670
0671 static int malidp_runtime_pm_suspend(struct device *dev)
0672 {
0673 struct drm_device *drm = dev_get_drvdata(dev);
0674 struct malidp_drm *malidp = drm->dev_private;
0675 struct malidp_hw_device *hwdev = malidp->dev;
0676
0677
0678 WARN_ON(!hwdev->hw->in_config_mode(hwdev));
0679
0680 malidp_se_irq_fini(hwdev);
0681 malidp_de_irq_fini(hwdev);
0682 hwdev->pm_suspended = true;
0683 clk_disable_unprepare(hwdev->mclk);
0684 clk_disable_unprepare(hwdev->aclk);
0685 clk_disable_unprepare(hwdev->pclk);
0686
0687 return 0;
0688 }
0689
0690 static int malidp_runtime_pm_resume(struct device *dev)
0691 {
0692 struct drm_device *drm = dev_get_drvdata(dev);
0693 struct malidp_drm *malidp = drm->dev_private;
0694 struct malidp_hw_device *hwdev = malidp->dev;
0695
0696 clk_prepare_enable(hwdev->pclk);
0697 clk_prepare_enable(hwdev->aclk);
0698 clk_prepare_enable(hwdev->mclk);
0699 hwdev->pm_suspended = false;
0700 malidp_de_irq_hw_init(hwdev);
0701 malidp_se_irq_hw_init(hwdev);
0702
0703 return 0;
0704 }
0705
0706 static int malidp_bind(struct device *dev)
0707 {
0708 struct resource *res;
0709 struct drm_device *drm;
0710 struct malidp_drm *malidp;
0711 struct malidp_hw_device *hwdev;
0712 struct platform_device *pdev = to_platform_device(dev);
0713 struct of_device_id const *dev_id;
0714 struct drm_encoder *encoder;
0715
0716 u8 output_width[MAX_OUTPUT_CHANNELS];
0717 int ret = 0, i;
0718 u32 version, out_depth = 0;
0719
0720 malidp = devm_kzalloc(dev, sizeof(*malidp), GFP_KERNEL);
0721 if (!malidp)
0722 return -ENOMEM;
0723
0724 hwdev = devm_kzalloc(dev, sizeof(*hwdev), GFP_KERNEL);
0725 if (!hwdev)
0726 return -ENOMEM;
0727
0728 hwdev->hw = (struct malidp_hw *)of_device_get_match_data(dev);
0729 malidp->dev = hwdev;
0730
0731 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0732 hwdev->regs = devm_ioremap_resource(dev, res);
0733 if (IS_ERR(hwdev->regs))
0734 return PTR_ERR(hwdev->regs);
0735
0736 hwdev->pclk = devm_clk_get(dev, "pclk");
0737 if (IS_ERR(hwdev->pclk))
0738 return PTR_ERR(hwdev->pclk);
0739
0740 hwdev->aclk = devm_clk_get(dev, "aclk");
0741 if (IS_ERR(hwdev->aclk))
0742 return PTR_ERR(hwdev->aclk);
0743
0744 hwdev->mclk = devm_clk_get(dev, "mclk");
0745 if (IS_ERR(hwdev->mclk))
0746 return PTR_ERR(hwdev->mclk);
0747
0748 hwdev->pxlclk = devm_clk_get(dev, "pxlclk");
0749 if (IS_ERR(hwdev->pxlclk))
0750 return PTR_ERR(hwdev->pxlclk);
0751
0752
0753 ret = of_reserved_mem_device_init(dev);
0754 if (ret && ret != -ENODEV)
0755 return ret;
0756
0757 drm = drm_dev_alloc(&malidp_driver, dev);
0758 if (IS_ERR(drm)) {
0759 ret = PTR_ERR(drm);
0760 goto alloc_fail;
0761 }
0762
0763 drm->dev_private = malidp;
0764 dev_set_drvdata(dev, drm);
0765
0766
0767 pm_runtime_enable(dev);
0768
0769
0770 if (pm_runtime_enabled(dev))
0771 pm_runtime_get_sync(dev);
0772 else
0773 malidp_runtime_pm_resume(dev);
0774
0775 dev_id = of_match_device(malidp_drm_of_match, dev);
0776 if (!dev_id) {
0777 ret = -EINVAL;
0778 goto query_hw_fail;
0779 }
0780
0781 if (!malidp_has_sufficient_address_space(res, dev_id)) {
0782 DRM_ERROR("Insufficient address space in device-tree.\n");
0783 ret = -EINVAL;
0784 goto query_hw_fail;
0785 }
0786
0787 if (!malidp_is_compatible_hw_id(hwdev, dev_id)) {
0788 ret = -EINVAL;
0789 goto query_hw_fail;
0790 }
0791
0792 ret = hwdev->hw->query_hw(hwdev);
0793 if (ret) {
0794 DRM_ERROR("Invalid HW configuration\n");
0795 goto query_hw_fail;
0796 }
0797
0798 version = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_DE_CORE_ID);
0799 DRM_INFO("found ARM Mali-DP%3x version r%dp%d\n", version >> 16,
0800 (version >> 12) & 0xf, (version >> 8) & 0xf);
0801
0802 malidp->core_id = version;
0803
0804 ret = of_property_read_u32(dev->of_node,
0805 "arm,malidp-arqos-value",
0806 &hwdev->arqos_value);
0807 if (ret)
0808 hwdev->arqos_value = 0x0;
0809
0810
0811 ret = of_property_read_u8_array(dev->of_node,
0812 "arm,malidp-output-port-lines",
0813 output_width, MAX_OUTPUT_CHANNELS);
0814 if (ret)
0815 goto query_hw_fail;
0816
0817 for (i = 0; i < MAX_OUTPUT_CHANNELS; i++)
0818 out_depth = (out_depth << 8) | (output_width[i] & 0xf);
0819 malidp_hw_write(hwdev, out_depth, hwdev->hw->map.out_depth_base);
0820 hwdev->output_color_depth = out_depth;
0821
0822 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_INIT);
0823 init_waitqueue_head(&malidp->wq);
0824
0825 ret = malidp_init(drm);
0826 if (ret < 0)
0827 goto query_hw_fail;
0828
0829
0830 malidp->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);
0831
0832 ret = component_bind_all(dev, drm);
0833 if (ret) {
0834 DRM_ERROR("Failed to bind all components\n");
0835 goto bind_fail;
0836 }
0837
0838
0839
0840
0841 WARN_ON(drm->mode_config.num_encoder > 2);
0842 list_for_each_entry(encoder, &drm->mode_config.encoder_list, head) {
0843 encoder->possible_clones =
0844 (1 << drm->mode_config.num_encoder) - 1;
0845 }
0846
0847 ret = malidp_irq_init(pdev);
0848 if (ret < 0)
0849 goto irq_init_fail;
0850
0851 ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
0852 if (ret < 0) {
0853 DRM_ERROR("failed to initialise vblank\n");
0854 goto vblank_fail;
0855 }
0856 pm_runtime_put(dev);
0857
0858 drm_mode_config_reset(drm);
0859
0860 drm_kms_helper_poll_init(drm);
0861
0862 ret = drm_dev_register(drm, 0);
0863 if (ret)
0864 goto register_fail;
0865
0866 drm_fbdev_generic_setup(drm, 32);
0867
0868 return 0;
0869
0870 register_fail:
0871 drm_kms_helper_poll_fini(drm);
0872 pm_runtime_get_sync(dev);
0873 vblank_fail:
0874 malidp_se_irq_fini(hwdev);
0875 malidp_de_irq_fini(hwdev);
0876 irq_init_fail:
0877 drm_atomic_helper_shutdown(drm);
0878 component_unbind_all(dev, drm);
0879 bind_fail:
0880 of_node_put(malidp->crtc.port);
0881 malidp->crtc.port = NULL;
0882 malidp_fini(drm);
0883 query_hw_fail:
0884 pm_runtime_put(dev);
0885 if (pm_runtime_enabled(dev))
0886 pm_runtime_disable(dev);
0887 else
0888 malidp_runtime_pm_suspend(dev);
0889 drm->dev_private = NULL;
0890 dev_set_drvdata(dev, NULL);
0891 drm_dev_put(drm);
0892 alloc_fail:
0893 of_reserved_mem_device_release(dev);
0894
0895 return ret;
0896 }
0897
0898 static void malidp_unbind(struct device *dev)
0899 {
0900 struct drm_device *drm = dev_get_drvdata(dev);
0901 struct malidp_drm *malidp = drm->dev_private;
0902 struct malidp_hw_device *hwdev = malidp->dev;
0903
0904 drm_dev_unregister(drm);
0905 drm_kms_helper_poll_fini(drm);
0906 pm_runtime_get_sync(dev);
0907 drm_atomic_helper_shutdown(drm);
0908 malidp_se_irq_fini(hwdev);
0909 malidp_de_irq_fini(hwdev);
0910 component_unbind_all(dev, drm);
0911 of_node_put(malidp->crtc.port);
0912 malidp->crtc.port = NULL;
0913 malidp_fini(drm);
0914 pm_runtime_put(dev);
0915 if (pm_runtime_enabled(dev))
0916 pm_runtime_disable(dev);
0917 else
0918 malidp_runtime_pm_suspend(dev);
0919 drm->dev_private = NULL;
0920 dev_set_drvdata(dev, NULL);
0921 drm_dev_put(drm);
0922 of_reserved_mem_device_release(dev);
0923 }
0924
0925 static const struct component_master_ops malidp_master_ops = {
0926 .bind = malidp_bind,
0927 .unbind = malidp_unbind,
0928 };
0929
0930 static int malidp_compare_dev(struct device *dev, void *data)
0931 {
0932 struct device_node *np = data;
0933
0934 return dev->of_node == np;
0935 }
0936
0937 static int malidp_platform_probe(struct platform_device *pdev)
0938 {
0939 struct device_node *port;
0940 struct component_match *match = NULL;
0941
0942 if (!pdev->dev.of_node)
0943 return -ENODEV;
0944
0945
0946 port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
0947 if (!port)
0948 return -ENODEV;
0949
0950 drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev,
0951 port);
0952 of_node_put(port);
0953 return component_master_add_with_match(&pdev->dev, &malidp_master_ops,
0954 match);
0955 }
0956
0957 static int malidp_platform_remove(struct platform_device *pdev)
0958 {
0959 component_master_del(&pdev->dev, &malidp_master_ops);
0960 return 0;
0961 }
0962
0963 static int __maybe_unused malidp_pm_suspend(struct device *dev)
0964 {
0965 struct drm_device *drm = dev_get_drvdata(dev);
0966
0967 return drm_mode_config_helper_suspend(drm);
0968 }
0969
0970 static int __maybe_unused malidp_pm_resume(struct device *dev)
0971 {
0972 struct drm_device *drm = dev_get_drvdata(dev);
0973
0974 drm_mode_config_helper_resume(drm);
0975
0976 return 0;
0977 }
0978
0979 static int __maybe_unused malidp_pm_suspend_late(struct device *dev)
0980 {
0981 if (!pm_runtime_status_suspended(dev)) {
0982 malidp_runtime_pm_suspend(dev);
0983 pm_runtime_set_suspended(dev);
0984 }
0985 return 0;
0986 }
0987
0988 static int __maybe_unused malidp_pm_resume_early(struct device *dev)
0989 {
0990 malidp_runtime_pm_resume(dev);
0991 pm_runtime_set_active(dev);
0992 return 0;
0993 }
0994
0995 static const struct dev_pm_ops malidp_pm_ops = {
0996 SET_SYSTEM_SLEEP_PM_OPS(malidp_pm_suspend, malidp_pm_resume) \
0997 SET_LATE_SYSTEM_SLEEP_PM_OPS(malidp_pm_suspend_late, malidp_pm_resume_early) \
0998 SET_RUNTIME_PM_OPS(malidp_runtime_pm_suspend, malidp_runtime_pm_resume, NULL)
0999 };
1000
1001 static struct platform_driver malidp_platform_driver = {
1002 .probe = malidp_platform_probe,
1003 .remove = malidp_platform_remove,
1004 .driver = {
1005 .name = "mali-dp",
1006 .pm = &malidp_pm_ops,
1007 .of_match_table = malidp_drm_of_match,
1008 .dev_groups = mali_dp_groups,
1009 },
1010 };
1011
1012 drm_module_platform_driver(malidp_platform_driver);
1013
1014 MODULE_AUTHOR("Liviu Dudau <Liviu.Dudau@arm.com>");
1015 MODULE_DESCRIPTION("ARM Mali DP DRM driver");
1016 MODULE_LICENSE("GPL v2");