cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

malidp_drv.c (27792B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
      4 * Author: Liviu Dudau <Liviu.Dudau@arm.com>
      5 *
      6 * ARM Mali DP500/DP550/DP650 KMS/DRM driver
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/clk.h>
     11#include <linux/component.h>
     12#include <linux/of_device.h>
     13#include <linux/of_graph.h>
     14#include <linux/of_reserved_mem.h>
     15#include <linux/pm_runtime.h>
     16#include <linux/debugfs.h>
     17
     18#include <drm/drm_atomic.h>
     19#include <drm/drm_atomic_helper.h>
     20#include <drm/drm_crtc.h>
     21#include <drm/drm_drv.h>
     22#include <drm/drm_fb_cma_helper.h>
     23#include <drm/drm_fb_helper.h>
     24#include <drm/drm_fourcc.h>
     25#include <drm/drm_gem_cma_helper.h>
     26#include <drm/drm_gem_framebuffer_helper.h>
     27#include <drm/drm_modeset_helper.h>
     28#include <drm/drm_module.h>
     29#include <drm/drm_of.h>
     30#include <drm/drm_probe_helper.h>
     31#include <drm/drm_vblank.h>
     32
     33#include "malidp_drv.h"
     34#include "malidp_mw.h"
     35#include "malidp_regs.h"
     36#include "malidp_hw.h"
     37
     38#define MALIDP_CONF_VALID_TIMEOUT	250
     39#define AFBC_HEADER_SIZE		16
     40#define AFBC_SUPERBLK_ALIGNMENT		128
     41
     42static void malidp_write_gamma_table(struct malidp_hw_device *hwdev,
     43				     u32 data[MALIDP_COEFFTAB_NUM_COEFFS])
     44{
     45	int i;
     46	/* Update all channels with a single gamma curve. */
     47	const u32 gamma_write_mask = GENMASK(18, 16);
     48	/*
     49	 * Always write an entire table, so the address field in
     50	 * DE_COEFFTAB_ADDR is 0 and we can use the gamma_write_mask bitmask
     51	 * directly.
     52	 */
     53	malidp_hw_write(hwdev, gamma_write_mask,
     54			hwdev->hw->map.coeffs_base + MALIDP_COEF_TABLE_ADDR);
     55	for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i)
     56		malidp_hw_write(hwdev, data[i],
     57				hwdev->hw->map.coeffs_base +
     58				MALIDP_COEF_TABLE_DATA);
     59}
     60
     61static void malidp_atomic_commit_update_gamma(struct drm_crtc *crtc,
     62					      struct drm_crtc_state *old_state)
     63{
     64	struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
     65	struct malidp_hw_device *hwdev = malidp->dev;
     66
     67	if (!crtc->state->color_mgmt_changed)
     68		return;
     69
     70	if (!crtc->state->gamma_lut) {
     71		malidp_hw_clearbits(hwdev,
     72				    MALIDP_DISP_FUNC_GAMMA,
     73				    MALIDP_DE_DISPLAY_FUNC);
     74	} else {
     75		struct malidp_crtc_state *mc =
     76			to_malidp_crtc_state(crtc->state);
     77
     78		if (!old_state->gamma_lut || (crtc->state->gamma_lut->base.id !=
     79					      old_state->gamma_lut->base.id))
     80			malidp_write_gamma_table(hwdev, mc->gamma_coeffs);
     81
     82		malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_GAMMA,
     83				  MALIDP_DE_DISPLAY_FUNC);
     84	}
     85}
     86
     87static
     88void malidp_atomic_commit_update_coloradj(struct drm_crtc *crtc,
     89					  struct drm_crtc_state *old_state)
     90{
     91	struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
     92	struct malidp_hw_device *hwdev = malidp->dev;
     93	int i;
     94
     95	if (!crtc->state->color_mgmt_changed)
     96		return;
     97
     98	if (!crtc->state->ctm) {
     99		malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_CADJ,
    100				    MALIDP_DE_DISPLAY_FUNC);
    101	} else {
    102		struct malidp_crtc_state *mc =
    103			to_malidp_crtc_state(crtc->state);
    104
    105		if (!old_state->ctm || (crtc->state->ctm->base.id !=
    106					old_state->ctm->base.id))
    107			for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; ++i)
    108				malidp_hw_write(hwdev,
    109						mc->coloradj_coeffs[i],
    110						hwdev->hw->map.coeffs_base +
    111						MALIDP_COLOR_ADJ_COEF + 4 * i);
    112
    113		malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_CADJ,
    114				  MALIDP_DE_DISPLAY_FUNC);
    115	}
    116}
    117
    118static void malidp_atomic_commit_se_config(struct drm_crtc *crtc,
    119					   struct drm_crtc_state *old_state)
    120{
    121	struct malidp_crtc_state *cs = to_malidp_crtc_state(crtc->state);
    122	struct malidp_crtc_state *old_cs = to_malidp_crtc_state(old_state);
    123	struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
    124	struct malidp_hw_device *hwdev = malidp->dev;
    125	struct malidp_se_config *s = &cs->scaler_config;
    126	struct malidp_se_config *old_s = &old_cs->scaler_config;
    127	u32 se_control = hwdev->hw->map.se_base +
    128			 ((hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ?
    129			 0x10 : 0xC);
    130	u32 layer_control = se_control + MALIDP_SE_LAYER_CONTROL;
    131	u32 scr = se_control + MALIDP_SE_SCALING_CONTROL;
    132	u32 val;
    133
    134	/* Set SE_CONTROL */
    135	if (!s->scale_enable) {
    136		val = malidp_hw_read(hwdev, se_control);
    137		val &= ~MALIDP_SE_SCALING_EN;
    138		malidp_hw_write(hwdev, val, se_control);
    139		return;
    140	}
    141
    142	hwdev->hw->se_set_scaling_coeffs(hwdev, s, old_s);
    143	val = malidp_hw_read(hwdev, se_control);
    144	val |= MALIDP_SE_SCALING_EN | MALIDP_SE_ALPHA_EN;
    145
    146	val &= ~MALIDP_SE_ENH(MALIDP_SE_ENH_MASK);
    147	val |= s->enhancer_enable ? MALIDP_SE_ENH(3) : 0;
    148
    149	val |= MALIDP_SE_RGBO_IF_EN;
    150	malidp_hw_write(hwdev, val, se_control);
    151
    152	/* Set IN_SIZE & OUT_SIZE. */
    153	val = MALIDP_SE_SET_V_SIZE(s->input_h) |
    154	      MALIDP_SE_SET_H_SIZE(s->input_w);
    155	malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_IN_SIZE);
    156	val = MALIDP_SE_SET_V_SIZE(s->output_h) |
    157	      MALIDP_SE_SET_H_SIZE(s->output_w);
    158	malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_OUT_SIZE);
    159
    160	/* Set phase regs. */
    161	malidp_hw_write(hwdev, s->h_init_phase, scr + MALIDP_SE_H_INIT_PH);
    162	malidp_hw_write(hwdev, s->h_delta_phase, scr + MALIDP_SE_H_DELTA_PH);
    163	malidp_hw_write(hwdev, s->v_init_phase, scr + MALIDP_SE_V_INIT_PH);
    164	malidp_hw_write(hwdev, s->v_delta_phase, scr + MALIDP_SE_V_DELTA_PH);
    165}
    166
    167/*
    168 * set the "config valid" bit and wait until the hardware acts on it
    169 */
    170static int malidp_set_and_wait_config_valid(struct drm_device *drm)
    171{
    172	struct malidp_drm *malidp = drm->dev_private;
    173	struct malidp_hw_device *hwdev = malidp->dev;
    174	int ret;
    175
    176	hwdev->hw->set_config_valid(hwdev, 1);
    177	/* don't wait for config_valid flag if we are in config mode */
    178	if (hwdev->hw->in_config_mode(hwdev)) {
    179		atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
    180		return 0;
    181	}
    182
    183	ret = wait_event_interruptible_timeout(malidp->wq,
    184			atomic_read(&malidp->config_valid) == MALIDP_CONFIG_VALID_DONE,
    185			msecs_to_jiffies(MALIDP_CONF_VALID_TIMEOUT));
    186
    187	return (ret > 0) ? 0 : -ETIMEDOUT;
    188}
    189
    190static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
    191{
    192	struct drm_device *drm = state->dev;
    193	struct malidp_drm *malidp = drm->dev_private;
    194	int loop = 5;
    195
    196	malidp->event = malidp->crtc.state->event;
    197	malidp->crtc.state->event = NULL;
    198
    199	if (malidp->crtc.state->active) {
    200		/*
    201		 * if we have an event to deliver to userspace, make sure
    202		 * the vblank is enabled as we are sending it from the IRQ
    203		 * handler.
    204		 */
    205		if (malidp->event)
    206			drm_crtc_vblank_get(&malidp->crtc);
    207
    208		/* only set config_valid if the CRTC is enabled */
    209		if (malidp_set_and_wait_config_valid(drm) < 0) {
    210			/*
    211			 * make a loop around the second CVAL setting and
    212			 * try 5 times before giving up.
    213			 */
    214			while (loop--) {
    215				if (!malidp_set_and_wait_config_valid(drm))
    216					break;
    217			}
    218			DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n");
    219		}
    220
    221	} else if (malidp->event) {
    222		/* CRTC inactive means vblank IRQ is disabled, send event directly */
    223		spin_lock_irq(&drm->event_lock);
    224		drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
    225		malidp->event = NULL;
    226		spin_unlock_irq(&drm->event_lock);
    227	}
    228	drm_atomic_helper_commit_hw_done(state);
    229}
    230
    231static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
    232{
    233	struct drm_device *drm = state->dev;
    234	struct malidp_drm *malidp = drm->dev_private;
    235	struct drm_crtc *crtc;
    236	struct drm_crtc_state *old_crtc_state;
    237	int i;
    238	bool fence_cookie = dma_fence_begin_signalling();
    239
    240	pm_runtime_get_sync(drm->dev);
    241
    242	/*
    243	 * set config_valid to a special value to let IRQ handlers
    244	 * know that we are updating registers
    245	 */
    246	atomic_set(&malidp->config_valid, MALIDP_CONFIG_START);
    247	malidp->dev->hw->set_config_valid(malidp->dev, 0);
    248
    249	drm_atomic_helper_commit_modeset_disables(drm, state);
    250
    251	for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
    252		malidp_atomic_commit_update_gamma(crtc, old_crtc_state);
    253		malidp_atomic_commit_update_coloradj(crtc, old_crtc_state);
    254		malidp_atomic_commit_se_config(crtc, old_crtc_state);
    255	}
    256
    257	drm_atomic_helper_commit_planes(drm, state, DRM_PLANE_COMMIT_ACTIVE_ONLY);
    258
    259	malidp_mw_atomic_commit(drm, state);
    260
    261	drm_atomic_helper_commit_modeset_enables(drm, state);
    262
    263	malidp_atomic_commit_hw_done(state);
    264
    265	dma_fence_end_signalling(fence_cookie);
    266
    267	pm_runtime_put(drm->dev);
    268
    269	drm_atomic_helper_cleanup_planes(drm, state);
    270}
    271
    272static const struct drm_mode_config_helper_funcs malidp_mode_config_helpers = {
    273	.atomic_commit_tail = malidp_atomic_commit_tail,
    274};
    275
    276static bool
    277malidp_verify_afbc_framebuffer_caps(struct drm_device *dev,
    278				    const struct drm_mode_fb_cmd2 *mode_cmd)
    279{
    280	if (malidp_format_mod_supported(dev, mode_cmd->pixel_format,
    281					mode_cmd->modifier[0]) == false)
    282		return false;
    283
    284	if (mode_cmd->offsets[0] != 0) {
    285		DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n");
    286		return false;
    287	}
    288
    289	switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
    290	case AFBC_SIZE_16X16:
    291		if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) {
    292			DRM_DEBUG_KMS("AFBC buffers must be aligned to 16 pixels\n");
    293			return false;
    294		}
    295		break;
    296	default:
    297		DRM_DEBUG_KMS("Unsupported AFBC block size\n");
    298		return false;
    299	}
    300
    301	return true;
    302}
    303
    304static bool
    305malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
    306				    struct drm_file *file,
    307				    const struct drm_mode_fb_cmd2 *mode_cmd)
    308{
    309	int n_superblocks = 0;
    310	const struct drm_format_info *info;
    311	struct drm_gem_object *objs = NULL;
    312	u32 afbc_superblock_size = 0, afbc_superblock_height = 0;
    313	u32 afbc_superblock_width = 0, afbc_size = 0;
    314	int bpp = 0;
    315
    316	switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
    317	case AFBC_SIZE_16X16:
    318		afbc_superblock_height = 16;
    319		afbc_superblock_width = 16;
    320		break;
    321	default:
    322		DRM_DEBUG_KMS("AFBC superblock size is not supported\n");
    323		return false;
    324	}
    325
    326	info = drm_get_format_info(dev, mode_cmd);
    327
    328	n_superblocks = (mode_cmd->width / afbc_superblock_width) *
    329		(mode_cmd->height / afbc_superblock_height);
    330
    331	bpp = malidp_format_get_bpp(info->format);
    332
    333	afbc_superblock_size = (bpp * afbc_superblock_width * afbc_superblock_height)
    334				/ BITS_PER_BYTE;
    335
    336	afbc_size = ALIGN(n_superblocks * AFBC_HEADER_SIZE, AFBC_SUPERBLK_ALIGNMENT);
    337	afbc_size += n_superblocks * ALIGN(afbc_superblock_size, AFBC_SUPERBLK_ALIGNMENT);
    338
    339	if ((mode_cmd->width * bpp) != (mode_cmd->pitches[0] * BITS_PER_BYTE)) {
    340		DRM_DEBUG_KMS("Invalid value of (pitch * BITS_PER_BYTE) (=%u) "
    341			      "should be same as width (=%u) * bpp (=%u)\n",
    342			      (mode_cmd->pitches[0] * BITS_PER_BYTE),
    343			      mode_cmd->width, bpp);
    344		return false;
    345	}
    346
    347	objs = drm_gem_object_lookup(file, mode_cmd->handles[0]);
    348	if (!objs) {
    349		DRM_DEBUG_KMS("Failed to lookup GEM object\n");
    350		return false;
    351	}
    352
    353	if (objs->size < afbc_size) {
    354		DRM_DEBUG_KMS("buffer size (%zu) too small for AFBC buffer size = %u\n",
    355			      objs->size, afbc_size);
    356		drm_gem_object_put(objs);
    357		return false;
    358	}
    359
    360	drm_gem_object_put(objs);
    361
    362	return true;
    363}
    364
    365static bool
    366malidp_verify_afbc_framebuffer(struct drm_device *dev, struct drm_file *file,
    367			       const struct drm_mode_fb_cmd2 *mode_cmd)
    368{
    369	if (malidp_verify_afbc_framebuffer_caps(dev, mode_cmd))
    370		return malidp_verify_afbc_framebuffer_size(dev, file, mode_cmd);
    371
    372	return false;
    373}
    374
    375static struct drm_framebuffer *
    376malidp_fb_create(struct drm_device *dev, struct drm_file *file,
    377		 const struct drm_mode_fb_cmd2 *mode_cmd)
    378{
    379	if (mode_cmd->modifier[0]) {
    380		if (!malidp_verify_afbc_framebuffer(dev, file, mode_cmd))
    381			return ERR_PTR(-EINVAL);
    382	}
    383
    384	return drm_gem_fb_create(dev, file, mode_cmd);
    385}
    386
    387static const struct drm_mode_config_funcs malidp_mode_config_funcs = {
    388	.fb_create = malidp_fb_create,
    389	.atomic_check = drm_atomic_helper_check,
    390	.atomic_commit = drm_atomic_helper_commit,
    391};
    392
    393static int malidp_init(struct drm_device *drm)
    394{
    395	int ret;
    396	struct malidp_drm *malidp = drm->dev_private;
    397	struct malidp_hw_device *hwdev = malidp->dev;
    398
    399	drm_mode_config_init(drm);
    400
    401	drm->mode_config.min_width = hwdev->min_line_size;
    402	drm->mode_config.min_height = hwdev->min_line_size;
    403	drm->mode_config.max_width = hwdev->max_line_size;
    404	drm->mode_config.max_height = hwdev->max_line_size;
    405	drm->mode_config.funcs = &malidp_mode_config_funcs;
    406	drm->mode_config.helper_private = &malidp_mode_config_helpers;
    407
    408	ret = malidp_crtc_init(drm);
    409	if (ret)
    410		goto crtc_fail;
    411
    412	ret = malidp_mw_connector_init(drm);
    413	if (ret)
    414		goto crtc_fail;
    415
    416	return 0;
    417
    418crtc_fail:
    419	drm_mode_config_cleanup(drm);
    420	return ret;
    421}
    422
    423static void malidp_fini(struct drm_device *drm)
    424{
    425	drm_mode_config_cleanup(drm);
    426}
    427
    428static int malidp_irq_init(struct platform_device *pdev)
    429{
    430	int irq_de, irq_se, ret = 0;
    431	struct drm_device *drm = dev_get_drvdata(&pdev->dev);
    432	struct malidp_drm *malidp = drm->dev_private;
    433	struct malidp_hw_device *hwdev = malidp->dev;
    434
    435	/* fetch the interrupts from DT */
    436	irq_de = platform_get_irq_byname(pdev, "DE");
    437	if (irq_de < 0) {
    438		DRM_ERROR("no 'DE' IRQ specified!\n");
    439		return irq_de;
    440	}
    441	irq_se = platform_get_irq_byname(pdev, "SE");
    442	if (irq_se < 0) {
    443		DRM_ERROR("no 'SE' IRQ specified!\n");
    444		return irq_se;
    445	}
    446
    447	ret = malidp_de_irq_init(drm, irq_de);
    448	if (ret)
    449		return ret;
    450
    451	ret = malidp_se_irq_init(drm, irq_se);
    452	if (ret) {
    453		malidp_de_irq_fini(hwdev);
    454		return ret;
    455	}
    456
    457	return 0;
    458}
    459
    460DEFINE_DRM_GEM_CMA_FOPS(fops);
    461
    462static int malidp_dumb_create(struct drm_file *file_priv,
    463			      struct drm_device *drm,
    464			      struct drm_mode_create_dumb *args)
    465{
    466	struct malidp_drm *malidp = drm->dev_private;
    467	/* allocate for the worst case scenario, i.e. rotated buffers */
    468	u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 1);
    469
    470	args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), alignment);
    471
    472	return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
    473}
    474
    475#ifdef CONFIG_DEBUG_FS
    476
    477static void malidp_error_stats_init(struct malidp_error_stats *error_stats)
    478{
    479	error_stats->num_errors = 0;
    480	error_stats->last_error_status = 0;
    481	error_stats->last_error_vblank = -1;
    482}
    483
    484void malidp_error(struct malidp_drm *malidp,
    485		  struct malidp_error_stats *error_stats, u32 status,
    486		  u64 vblank)
    487{
    488	unsigned long irqflags;
    489
    490	spin_lock_irqsave(&malidp->errors_lock, irqflags);
    491	error_stats->last_error_status = status;
    492	error_stats->last_error_vblank = vblank;
    493	error_stats->num_errors++;
    494	spin_unlock_irqrestore(&malidp->errors_lock, irqflags);
    495}
    496
    497static void malidp_error_stats_dump(const char *prefix,
    498				    struct malidp_error_stats error_stats,
    499				    struct seq_file *m)
    500{
    501	seq_printf(m, "[%s] num_errors : %d\n", prefix,
    502		   error_stats.num_errors);
    503	seq_printf(m, "[%s] last_error_status  : 0x%08x\n", prefix,
    504		   error_stats.last_error_status);
    505	seq_printf(m, "[%s] last_error_vblank : %lld\n", prefix,
    506		   error_stats.last_error_vblank);
    507}
    508
    509static int malidp_show_stats(struct seq_file *m, void *arg)
    510{
    511	struct drm_device *drm = m->private;
    512	struct malidp_drm *malidp = drm->dev_private;
    513	unsigned long irqflags;
    514	struct malidp_error_stats de_errors, se_errors;
    515
    516	spin_lock_irqsave(&malidp->errors_lock, irqflags);
    517	de_errors = malidp->de_errors;
    518	se_errors = malidp->se_errors;
    519	spin_unlock_irqrestore(&malidp->errors_lock, irqflags);
    520	malidp_error_stats_dump("DE", de_errors, m);
    521	malidp_error_stats_dump("SE", se_errors, m);
    522	return 0;
    523}
    524
    525static int malidp_debugfs_open(struct inode *inode, struct file *file)
    526{
    527	return single_open(file, malidp_show_stats, inode->i_private);
    528}
    529
    530static ssize_t malidp_debugfs_write(struct file *file, const char __user *ubuf,
    531				    size_t len, loff_t *offp)
    532{
    533	struct seq_file *m = file->private_data;
    534	struct drm_device *drm = m->private;
    535	struct malidp_drm *malidp = drm->dev_private;
    536	unsigned long irqflags;
    537
    538	spin_lock_irqsave(&malidp->errors_lock, irqflags);
    539	malidp_error_stats_init(&malidp->de_errors);
    540	malidp_error_stats_init(&malidp->se_errors);
    541	spin_unlock_irqrestore(&malidp->errors_lock, irqflags);
    542	return len;
    543}
    544
    545static const struct file_operations malidp_debugfs_fops = {
    546	.owner = THIS_MODULE,
    547	.open = malidp_debugfs_open,
    548	.read = seq_read,
    549	.write = malidp_debugfs_write,
    550	.llseek = seq_lseek,
    551	.release = single_release,
    552};
    553
    554static void malidp_debugfs_init(struct drm_minor *minor)
    555{
    556	struct malidp_drm *malidp = minor->dev->dev_private;
    557
    558	malidp_error_stats_init(&malidp->de_errors);
    559	malidp_error_stats_init(&malidp->se_errors);
    560	spin_lock_init(&malidp->errors_lock);
    561	debugfs_create_file("debug", S_IRUGO | S_IWUSR, minor->debugfs_root,
    562			    minor->dev, &malidp_debugfs_fops);
    563}
    564
    565#endif //CONFIG_DEBUG_FS
    566
    567static const struct drm_driver malidp_driver = {
    568	.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
    569	DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create),
    570#ifdef CONFIG_DEBUG_FS
    571	.debugfs_init = malidp_debugfs_init,
    572#endif
    573	.fops = &fops,
    574	.name = "mali-dp",
    575	.desc = "ARM Mali Display Processor driver",
    576	.date = "20160106",
    577	.major = 1,
    578	.minor = 0,
    579};
    580
    581static const struct of_device_id  malidp_drm_of_match[] = {
    582	{
    583		.compatible = "arm,mali-dp500",
    584		.data = &malidp_device[MALIDP_500]
    585	},
    586	{
    587		.compatible = "arm,mali-dp550",
    588		.data = &malidp_device[MALIDP_550]
    589	},
    590	{
    591		.compatible = "arm,mali-dp650",
    592		.data = &malidp_device[MALIDP_650]
    593	},
    594	{},
    595};
    596MODULE_DEVICE_TABLE(of, malidp_drm_of_match);
    597
    598static bool malidp_is_compatible_hw_id(struct malidp_hw_device *hwdev,
    599				       const struct of_device_id *dev_id)
    600{
    601	u32 core_id;
    602	const char *compatstr_dp500 = "arm,mali-dp500";
    603	bool is_dp500;
    604	bool dt_is_dp500;
    605
    606	/*
    607	 * The DP500 CORE_ID register is in a different location, so check it
    608	 * first. If the product id field matches, then this is DP500, otherwise
    609	 * check the DP550/650 CORE_ID register.
    610	 */
    611	core_id = malidp_hw_read(hwdev, MALIDP500_DC_BASE + MALIDP_DE_CORE_ID);
    612	/* Offset 0x18 will never read 0x500 on products other than DP500. */
    613	is_dp500 = (MALIDP_PRODUCT_ID(core_id) == 0x500);
    614	dt_is_dp500 = strnstr(dev_id->compatible, compatstr_dp500,
    615			      sizeof(dev_id->compatible)) != NULL;
    616	if (is_dp500 != dt_is_dp500) {
    617		DRM_ERROR("Device-tree expects %s, but hardware %s DP500.\n",
    618			  dev_id->compatible, is_dp500 ? "is" : "is not");
    619		return false;
    620	} else if (!dt_is_dp500) {
    621		u16 product_id;
    622		char buf[32];
    623
    624		core_id = malidp_hw_read(hwdev,
    625					 MALIDP550_DC_BASE + MALIDP_DE_CORE_ID);
    626		product_id = MALIDP_PRODUCT_ID(core_id);
    627		snprintf(buf, sizeof(buf), "arm,mali-dp%X", product_id);
    628		if (!strnstr(dev_id->compatible, buf,
    629			     sizeof(dev_id->compatible))) {
    630			DRM_ERROR("Device-tree expects %s, but hardware is DP%03X.\n",
    631				  dev_id->compatible, product_id);
    632			return false;
    633		}
    634	}
    635	return true;
    636}
    637
    638static bool malidp_has_sufficient_address_space(const struct resource *res,
    639						const struct of_device_id *dev_id)
    640{
    641	resource_size_t res_size = resource_size(res);
    642	const char *compatstr_dp500 = "arm,mali-dp500";
    643
    644	if (!strnstr(dev_id->compatible, compatstr_dp500,
    645		     sizeof(dev_id->compatible)))
    646		return res_size >= MALIDP550_ADDR_SPACE_SIZE;
    647	else if (res_size < MALIDP500_ADDR_SPACE_SIZE)
    648		return false;
    649	return true;
    650}
    651
    652static ssize_t core_id_show(struct device *dev, struct device_attribute *attr,
    653			    char *buf)
    654{
    655	struct drm_device *drm = dev_get_drvdata(dev);
    656	struct malidp_drm *malidp = drm->dev_private;
    657
    658	return snprintf(buf, PAGE_SIZE, "%08x\n", malidp->core_id);
    659}
    660
    661static DEVICE_ATTR_RO(core_id);
    662
    663static struct attribute *mali_dp_attrs[] = {
    664	&dev_attr_core_id.attr,
    665	NULL,
    666};
    667ATTRIBUTE_GROUPS(mali_dp);
    668
    669#define MAX_OUTPUT_CHANNELS	3
    670
    671static int malidp_runtime_pm_suspend(struct device *dev)
    672{
    673	struct drm_device *drm = dev_get_drvdata(dev);
    674	struct malidp_drm *malidp = drm->dev_private;
    675	struct malidp_hw_device *hwdev = malidp->dev;
    676
    677	/* we can only suspend if the hardware is in config mode */
    678	WARN_ON(!hwdev->hw->in_config_mode(hwdev));
    679
    680	malidp_se_irq_fini(hwdev);
    681	malidp_de_irq_fini(hwdev);
    682	hwdev->pm_suspended = true;
    683	clk_disable_unprepare(hwdev->mclk);
    684	clk_disable_unprepare(hwdev->aclk);
    685	clk_disable_unprepare(hwdev->pclk);
    686
    687	return 0;
    688}
    689
    690static int malidp_runtime_pm_resume(struct device *dev)
    691{
    692	struct drm_device *drm = dev_get_drvdata(dev);
    693	struct malidp_drm *malidp = drm->dev_private;
    694	struct malidp_hw_device *hwdev = malidp->dev;
    695
    696	clk_prepare_enable(hwdev->pclk);
    697	clk_prepare_enable(hwdev->aclk);
    698	clk_prepare_enable(hwdev->mclk);
    699	hwdev->pm_suspended = false;
    700	malidp_de_irq_hw_init(hwdev);
    701	malidp_se_irq_hw_init(hwdev);
    702
    703	return 0;
    704}
    705
    706static int malidp_bind(struct device *dev)
    707{
    708	struct resource *res;
    709	struct drm_device *drm;
    710	struct malidp_drm *malidp;
    711	struct malidp_hw_device *hwdev;
    712	struct platform_device *pdev = to_platform_device(dev);
    713	struct of_device_id const *dev_id;
    714	struct drm_encoder *encoder;
    715	/* number of lines for the R, G and B output */
    716	u8 output_width[MAX_OUTPUT_CHANNELS];
    717	int ret = 0, i;
    718	u32 version, out_depth = 0;
    719
    720	malidp = devm_kzalloc(dev, sizeof(*malidp), GFP_KERNEL);
    721	if (!malidp)
    722		return -ENOMEM;
    723
    724	hwdev = devm_kzalloc(dev, sizeof(*hwdev), GFP_KERNEL);
    725	if (!hwdev)
    726		return -ENOMEM;
    727
    728	hwdev->hw = (struct malidp_hw *)of_device_get_match_data(dev);
    729	malidp->dev = hwdev;
    730
    731	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    732	hwdev->regs = devm_ioremap_resource(dev, res);
    733	if (IS_ERR(hwdev->regs))
    734		return PTR_ERR(hwdev->regs);
    735
    736	hwdev->pclk = devm_clk_get(dev, "pclk");
    737	if (IS_ERR(hwdev->pclk))
    738		return PTR_ERR(hwdev->pclk);
    739
    740	hwdev->aclk = devm_clk_get(dev, "aclk");
    741	if (IS_ERR(hwdev->aclk))
    742		return PTR_ERR(hwdev->aclk);
    743
    744	hwdev->mclk = devm_clk_get(dev, "mclk");
    745	if (IS_ERR(hwdev->mclk))
    746		return PTR_ERR(hwdev->mclk);
    747
    748	hwdev->pxlclk = devm_clk_get(dev, "pxlclk");
    749	if (IS_ERR(hwdev->pxlclk))
    750		return PTR_ERR(hwdev->pxlclk);
    751
    752	/* Get the optional framebuffer memory resource */
    753	ret = of_reserved_mem_device_init(dev);
    754	if (ret && ret != -ENODEV)
    755		return ret;
    756
    757	drm = drm_dev_alloc(&malidp_driver, dev);
    758	if (IS_ERR(drm)) {
    759		ret = PTR_ERR(drm);
    760		goto alloc_fail;
    761	}
    762
    763	drm->dev_private = malidp;
    764	dev_set_drvdata(dev, drm);
    765
    766	/* Enable power management */
    767	pm_runtime_enable(dev);
    768
    769	/* Resume device to enable the clocks */
    770	if (pm_runtime_enabled(dev))
    771		pm_runtime_get_sync(dev);
    772	else
    773		malidp_runtime_pm_resume(dev);
    774
    775	dev_id = of_match_device(malidp_drm_of_match, dev);
    776	if (!dev_id) {
    777		ret = -EINVAL;
    778		goto query_hw_fail;
    779	}
    780
    781	if (!malidp_has_sufficient_address_space(res, dev_id)) {
    782		DRM_ERROR("Insufficient address space in device-tree.\n");
    783		ret = -EINVAL;
    784		goto query_hw_fail;
    785	}
    786
    787	if (!malidp_is_compatible_hw_id(hwdev, dev_id)) {
    788		ret = -EINVAL;
    789		goto query_hw_fail;
    790	}
    791
    792	ret = hwdev->hw->query_hw(hwdev);
    793	if (ret) {
    794		DRM_ERROR("Invalid HW configuration\n");
    795		goto query_hw_fail;
    796	}
    797
    798	version = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_DE_CORE_ID);
    799	DRM_INFO("found ARM Mali-DP%3x version r%dp%d\n", version >> 16,
    800		 (version >> 12) & 0xf, (version >> 8) & 0xf);
    801
    802	malidp->core_id = version;
    803
    804	ret = of_property_read_u32(dev->of_node,
    805					"arm,malidp-arqos-value",
    806					&hwdev->arqos_value);
    807	if (ret)
    808		hwdev->arqos_value = 0x0;
    809
    810	/* set the number of lines used for output of RGB data */
    811	ret = of_property_read_u8_array(dev->of_node,
    812					"arm,malidp-output-port-lines",
    813					output_width, MAX_OUTPUT_CHANNELS);
    814	if (ret)
    815		goto query_hw_fail;
    816
    817	for (i = 0; i < MAX_OUTPUT_CHANNELS; i++)
    818		out_depth = (out_depth << 8) | (output_width[i] & 0xf);
    819	malidp_hw_write(hwdev, out_depth, hwdev->hw->map.out_depth_base);
    820	hwdev->output_color_depth = out_depth;
    821
    822	atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_INIT);
    823	init_waitqueue_head(&malidp->wq);
    824
    825	ret = malidp_init(drm);
    826	if (ret < 0)
    827		goto query_hw_fail;
    828
    829	/* Set the CRTC's port so that the encoder component can find it */
    830	malidp->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);
    831
    832	ret = component_bind_all(dev, drm);
    833	if (ret) {
    834		DRM_ERROR("Failed to bind all components\n");
    835		goto bind_fail;
    836	}
    837
    838	/* We expect to have a maximum of two encoders one for the actual
    839	 * display and a virtual one for the writeback connector
    840	 */
    841	WARN_ON(drm->mode_config.num_encoder > 2);
    842	list_for_each_entry(encoder, &drm->mode_config.encoder_list, head) {
    843		encoder->possible_clones =
    844				(1 << drm->mode_config.num_encoder) -  1;
    845	}
    846
    847	ret = malidp_irq_init(pdev);
    848	if (ret < 0)
    849		goto irq_init_fail;
    850
    851	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
    852	if (ret < 0) {
    853		DRM_ERROR("failed to initialise vblank\n");
    854		goto vblank_fail;
    855	}
    856	pm_runtime_put(dev);
    857
    858	drm_mode_config_reset(drm);
    859
    860	drm_kms_helper_poll_init(drm);
    861
    862	ret = drm_dev_register(drm, 0);
    863	if (ret)
    864		goto register_fail;
    865
    866	drm_fbdev_generic_setup(drm, 32);
    867
    868	return 0;
    869
    870register_fail:
    871	drm_kms_helper_poll_fini(drm);
    872	pm_runtime_get_sync(dev);
    873vblank_fail:
    874	malidp_se_irq_fini(hwdev);
    875	malidp_de_irq_fini(hwdev);
    876irq_init_fail:
    877	drm_atomic_helper_shutdown(drm);
    878	component_unbind_all(dev, drm);
    879bind_fail:
    880	of_node_put(malidp->crtc.port);
    881	malidp->crtc.port = NULL;
    882	malidp_fini(drm);
    883query_hw_fail:
    884	pm_runtime_put(dev);
    885	if (pm_runtime_enabled(dev))
    886		pm_runtime_disable(dev);
    887	else
    888		malidp_runtime_pm_suspend(dev);
    889	drm->dev_private = NULL;
    890	dev_set_drvdata(dev, NULL);
    891	drm_dev_put(drm);
    892alloc_fail:
    893	of_reserved_mem_device_release(dev);
    894
    895	return ret;
    896}
    897
    898static void malidp_unbind(struct device *dev)
    899{
    900	struct drm_device *drm = dev_get_drvdata(dev);
    901	struct malidp_drm *malidp = drm->dev_private;
    902	struct malidp_hw_device *hwdev = malidp->dev;
    903
    904	drm_dev_unregister(drm);
    905	drm_kms_helper_poll_fini(drm);
    906	pm_runtime_get_sync(dev);
    907	drm_atomic_helper_shutdown(drm);
    908	malidp_se_irq_fini(hwdev);
    909	malidp_de_irq_fini(hwdev);
    910	component_unbind_all(dev, drm);
    911	of_node_put(malidp->crtc.port);
    912	malidp->crtc.port = NULL;
    913	malidp_fini(drm);
    914	pm_runtime_put(dev);
    915	if (pm_runtime_enabled(dev))
    916		pm_runtime_disable(dev);
    917	else
    918		malidp_runtime_pm_suspend(dev);
    919	drm->dev_private = NULL;
    920	dev_set_drvdata(dev, NULL);
    921	drm_dev_put(drm);
    922	of_reserved_mem_device_release(dev);
    923}
    924
    925static const struct component_master_ops malidp_master_ops = {
    926	.bind = malidp_bind,
    927	.unbind = malidp_unbind,
    928};
    929
    930static int malidp_compare_dev(struct device *dev, void *data)
    931{
    932	struct device_node *np = data;
    933
    934	return dev->of_node == np;
    935}
    936
    937static int malidp_platform_probe(struct platform_device *pdev)
    938{
    939	struct device_node *port;
    940	struct component_match *match = NULL;
    941
    942	if (!pdev->dev.of_node)
    943		return -ENODEV;
    944
    945	/* there is only one output port inside each device, find it */
    946	port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
    947	if (!port)
    948		return -ENODEV;
    949
    950	drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev,
    951				   port);
    952	of_node_put(port);
    953	return component_master_add_with_match(&pdev->dev, &malidp_master_ops,
    954					       match);
    955}
    956
    957static int malidp_platform_remove(struct platform_device *pdev)
    958{
    959	component_master_del(&pdev->dev, &malidp_master_ops);
    960	return 0;
    961}
    962
    963static int __maybe_unused malidp_pm_suspend(struct device *dev)
    964{
    965	struct drm_device *drm = dev_get_drvdata(dev);
    966
    967	return drm_mode_config_helper_suspend(drm);
    968}
    969
    970static int __maybe_unused malidp_pm_resume(struct device *dev)
    971{
    972	struct drm_device *drm = dev_get_drvdata(dev);
    973
    974	drm_mode_config_helper_resume(drm);
    975
    976	return 0;
    977}
    978
    979static int __maybe_unused malidp_pm_suspend_late(struct device *dev)
    980{
    981	if (!pm_runtime_status_suspended(dev)) {
    982		malidp_runtime_pm_suspend(dev);
    983		pm_runtime_set_suspended(dev);
    984	}
    985	return 0;
    986}
    987
    988static int __maybe_unused malidp_pm_resume_early(struct device *dev)
    989{
    990	malidp_runtime_pm_resume(dev);
    991	pm_runtime_set_active(dev);
    992	return 0;
    993}
    994
    995static const struct dev_pm_ops malidp_pm_ops = {
    996	SET_SYSTEM_SLEEP_PM_OPS(malidp_pm_suspend, malidp_pm_resume) \
    997	SET_LATE_SYSTEM_SLEEP_PM_OPS(malidp_pm_suspend_late, malidp_pm_resume_early) \
    998	SET_RUNTIME_PM_OPS(malidp_runtime_pm_suspend, malidp_runtime_pm_resume, NULL)
    999};
   1000
   1001static 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
   1012drm_module_platform_driver(malidp_platform_driver);
   1013
   1014MODULE_AUTHOR("Liviu Dudau <Liviu.Dudau@arm.com>");
   1015MODULE_DESCRIPTION("ARM Mali DP DRM driver");
   1016MODULE_LICENSE("GPL v2");