Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f83b5ff authored by Samantha Tran's avatar Samantha Tran
Browse files

Revert "drm/msm: Add SDM845 DPU support"



This reverts commit 25fdd593.

DPU will not be used in 4.19 downstream display driver code.
Separate patches are submitted to introduce the downstream
version of the display driver.

Change-Id: I7230a55c502f1d62a889770728c25394c7d0dcd3
Signed-off-by: default avatarSamantha Tran <samtran@codeaurora.org>
parent 51c57544
Loading
Loading
Loading
Loading
+1 −31
Original line number Original line Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0
# SPDX-License-Identifier: GPL-2.0
ccflags-y := -Idrivers/gpu/drm/msm
ccflags-y := -Idrivers/gpu/drm/msm
ccflags-y += -Idrivers/gpu/drm/msm/disp/dpu1
ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi
ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi


msm-y := \
msm-y := \
@@ -49,34 +48,6 @@ msm-y := \
	disp/mdp5/mdp5_mixer.o \
	disp/mdp5/mdp5_mixer.o \
	disp/mdp5/mdp5_plane.o \
	disp/mdp5/mdp5_plane.o \
	disp/mdp5/mdp5_smp.o \
	disp/mdp5/mdp5_smp.o \
	disp/dpu1/dpu_core_irq.o \
	disp/dpu1/dpu_core_perf.o \
	disp/dpu1/dpu_crtc.o \
	disp/dpu1/dpu_encoder.o \
	disp/dpu1/dpu_encoder_phys_cmd.o \
	disp/dpu1/dpu_encoder_phys_vid.o \
	disp/dpu1/dpu_formats.o \
	disp/dpu1/dpu_hw_blk.o \
	disp/dpu1/dpu_hw_catalog.o \
	disp/dpu1/dpu_hw_cdm.o \
	disp/dpu1/dpu_hw_ctl.o \
	disp/dpu1/dpu_hw_interrupts.o \
	disp/dpu1/dpu_hw_intf.o \
	disp/dpu1/dpu_hw_lm.o \
	disp/dpu1/dpu_hw_pingpong.o \
	disp/dpu1/dpu_hw_sspp.o \
	disp/dpu1/dpu_hw_top.o \
	disp/dpu1/dpu_hw_util.o \
	disp/dpu1/dpu_hw_vbif.o \
	disp/dpu1/dpu_io_util.o \
	disp/dpu1/dpu_irq.o \
	disp/dpu1/dpu_kms.o \
	disp/dpu1/dpu_kms_utils.o \
	disp/dpu1/dpu_mdss.o \
	disp/dpu1/dpu_plane.o \
	disp/dpu1/dpu_power_handle.o \
	disp/dpu1/dpu_rm.o \
	disp/dpu1/dpu_vbif.o \
	msm_atomic.o \
	msm_atomic.o \
	msm_debugfs.o \
	msm_debugfs.o \
	msm_drv.o \
	msm_drv.o \
@@ -94,8 +65,7 @@ msm-y := \
	msm_ringbuffer.o \
	msm_ringbuffer.o \
	msm_submitqueue.o
	msm_submitqueue.o


msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \
msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o
			  disp/dpu1/dpu_dbg.o


msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o
msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o
msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o
msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o
+0 −479
Original line number Original line Diff line number Diff line
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__

#include <linux/debugfs.h>
#include <linux/irqdomain.h>
#include <linux/irq.h>
#include <linux/kthread.h>

#include "dpu_core_irq.h"
#include "dpu_trace.h"

/**
 * dpu_core_irq_callback_handler - dispatch core interrupts
 * @arg:		private data of callback handler
 * @irq_idx:		interrupt index
 */
static void dpu_core_irq_callback_handler(void *arg, int irq_idx)
{
	struct dpu_kms *dpu_kms = arg;
	struct dpu_irq *irq_obj = &dpu_kms->irq_obj;
	struct dpu_irq_callback *cb;
	unsigned long irq_flags;

	pr_debug("irq_idx=%d\n", irq_idx);

	if (list_empty(&irq_obj->irq_cb_tbl[irq_idx])) {
		DRM_ERROR("no registered cb, idx:%d enable_count:%d\n", irq_idx,
			atomic_read(&dpu_kms->irq_obj.enable_counts[irq_idx]));
	}

	atomic_inc(&irq_obj->irq_counts[irq_idx]);

	/*
	 * Perform registered function callback
	 */
	spin_lock_irqsave(&dpu_kms->irq_obj.cb_lock, irq_flags);
	list_for_each_entry(cb, &irq_obj->irq_cb_tbl[irq_idx], list)
		if (cb->func)
			cb->func(cb->arg, irq_idx);
	spin_unlock_irqrestore(&dpu_kms->irq_obj.cb_lock, irq_flags);

	/*
	 * Clear pending interrupt status in HW.
	 * NOTE: dpu_core_irq_callback_handler is protected by top-level
	 *       spinlock, so it is safe to clear any interrupt status here.
	 */
	dpu_kms->hw_intr->ops.clear_intr_status_nolock(
			dpu_kms->hw_intr,
			irq_idx);
}

int dpu_core_irq_idx_lookup(struct dpu_kms *dpu_kms,
		enum dpu_intr_type intr_type, u32 instance_idx)
{
	if (!dpu_kms || !dpu_kms->hw_intr ||
			!dpu_kms->hw_intr->ops.irq_idx_lookup)
		return -EINVAL;

	return dpu_kms->hw_intr->ops.irq_idx_lookup(intr_type,
			instance_idx);
}

/**
 * _dpu_core_irq_enable - enable core interrupt given by the index
 * @dpu_kms:		Pointer to dpu kms context
 * @irq_idx:		interrupt index
 */
static int _dpu_core_irq_enable(struct dpu_kms *dpu_kms, int irq_idx)
{
	unsigned long irq_flags;
	int ret = 0, enable_count;

	if (!dpu_kms || !dpu_kms->hw_intr ||
			!dpu_kms->irq_obj.enable_counts ||
			!dpu_kms->irq_obj.irq_counts) {
		DPU_ERROR("invalid params\n");
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
		DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}

	enable_count = atomic_read(&dpu_kms->irq_obj.enable_counts[irq_idx]);
	DRM_DEBUG_KMS("irq_idx=%d enable_count=%d\n", irq_idx, enable_count);
	trace_dpu_core_irq_enable_idx(irq_idx, enable_count);

	if (atomic_inc_return(&dpu_kms->irq_obj.enable_counts[irq_idx]) == 1) {
		ret = dpu_kms->hw_intr->ops.enable_irq(
				dpu_kms->hw_intr,
				irq_idx);
		if (ret)
			DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n",
					irq_idx);

		DPU_DEBUG("irq_idx=%d ret=%d\n", irq_idx, ret);

		spin_lock_irqsave(&dpu_kms->irq_obj.cb_lock, irq_flags);
		/* empty callback list but interrupt is enabled */
		if (list_empty(&dpu_kms->irq_obj.irq_cb_tbl[irq_idx]))
			DPU_ERROR("irq_idx=%d enabled with no callback\n",
					irq_idx);
		spin_unlock_irqrestore(&dpu_kms->irq_obj.cb_lock, irq_flags);
	}

	return ret;
}

int dpu_core_irq_enable(struct dpu_kms *dpu_kms, int *irq_idxs, u32 irq_count)
{
	int i, ret = 0, counts;

	if (!dpu_kms || !irq_idxs || !irq_count) {
		DPU_ERROR("invalid params\n");
		return -EINVAL;
	}

	counts = atomic_read(&dpu_kms->irq_obj.enable_counts[irq_idxs[0]]);
	if (counts)
		DRM_ERROR("irq_idx=%d enable_count=%d\n", irq_idxs[0], counts);

	for (i = 0; (i < irq_count) && !ret; i++)
		ret = _dpu_core_irq_enable(dpu_kms, irq_idxs[i]);

	return ret;
}

/**
 * _dpu_core_irq_disable - disable core interrupt given by the index
 * @dpu_kms:		Pointer to dpu kms context
 * @irq_idx:		interrupt index
 */
static int _dpu_core_irq_disable(struct dpu_kms *dpu_kms, int irq_idx)
{
	int ret = 0, enable_count;

	if (!dpu_kms || !dpu_kms->hw_intr || !dpu_kms->irq_obj.enable_counts) {
		DPU_ERROR("invalid params\n");
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
		DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}

	enable_count = atomic_read(&dpu_kms->irq_obj.enable_counts[irq_idx]);
	DRM_DEBUG_KMS("irq_idx=%d enable_count=%d\n", irq_idx, enable_count);
	trace_dpu_core_irq_disable_idx(irq_idx, enable_count);

	if (atomic_dec_return(&dpu_kms->irq_obj.enable_counts[irq_idx]) == 0) {
		ret = dpu_kms->hw_intr->ops.disable_irq(
				dpu_kms->hw_intr,
				irq_idx);
		if (ret)
			DPU_ERROR("Fail to disable IRQ for irq_idx:%d\n",
					irq_idx);
		DPU_DEBUG("irq_idx=%d ret=%d\n", irq_idx, ret);
	}

	return ret;
}

int dpu_core_irq_disable(struct dpu_kms *dpu_kms, int *irq_idxs, u32 irq_count)
{
	int i, ret = 0, counts;

	if (!dpu_kms || !irq_idxs || !irq_count) {
		DPU_ERROR("invalid params\n");
		return -EINVAL;
	}

	counts = atomic_read(&dpu_kms->irq_obj.enable_counts[irq_idxs[0]]);
	if (counts == 2)
		DRM_ERROR("irq_idx=%d enable_count=%d\n", irq_idxs[0], counts);

	for (i = 0; (i < irq_count) && !ret; i++)
		ret = _dpu_core_irq_disable(dpu_kms, irq_idxs[i]);

	return ret;
}

u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx, bool clear)
{
	if (!dpu_kms || !dpu_kms->hw_intr ||
			!dpu_kms->hw_intr->ops.get_interrupt_status)
		return 0;

	if (irq_idx < 0) {
		DPU_ERROR("[%pS] invalid irq_idx=%d\n",
				__builtin_return_address(0), irq_idx);
		return 0;
	}

	return dpu_kms->hw_intr->ops.get_interrupt_status(dpu_kms->hw_intr,
			irq_idx, clear);
}

int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
		struct dpu_irq_callback *register_irq_cb)
{
	unsigned long irq_flags;

	if (!dpu_kms || !dpu_kms->irq_obj.irq_cb_tbl) {
		DPU_ERROR("invalid params\n");
		return -EINVAL;
	}

	if (!register_irq_cb || !register_irq_cb->func) {
		DPU_ERROR("invalid irq_cb:%d func:%d\n",
				register_irq_cb != NULL,
				register_irq_cb ?
					register_irq_cb->func != NULL : -1);
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
		DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}

	DPU_DEBUG("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);

	spin_lock_irqsave(&dpu_kms->irq_obj.cb_lock, irq_flags);
	trace_dpu_core_irq_register_callback(irq_idx, register_irq_cb);
	list_del_init(&register_irq_cb->list);
	list_add_tail(&register_irq_cb->list,
			&dpu_kms->irq_obj.irq_cb_tbl[irq_idx]);
	spin_unlock_irqrestore(&dpu_kms->irq_obj.cb_lock, irq_flags);

	return 0;
}

int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx,
		struct dpu_irq_callback *register_irq_cb)
{
	unsigned long irq_flags;

	if (!dpu_kms || !dpu_kms->irq_obj.irq_cb_tbl) {
		DPU_ERROR("invalid params\n");
		return -EINVAL;
	}

	if (!register_irq_cb || !register_irq_cb->func) {
		DPU_ERROR("invalid irq_cb:%d func:%d\n",
				register_irq_cb != NULL,
				register_irq_cb ?
					register_irq_cb->func != NULL : -1);
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
		DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}

	DPU_DEBUG("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);

	spin_lock_irqsave(&dpu_kms->irq_obj.cb_lock, irq_flags);
	trace_dpu_core_irq_unregister_callback(irq_idx, register_irq_cb);
	list_del_init(&register_irq_cb->list);
	/* empty callback list but interrupt is still enabled */
	if (list_empty(&dpu_kms->irq_obj.irq_cb_tbl[irq_idx]) &&
			atomic_read(&dpu_kms->irq_obj.enable_counts[irq_idx]))
		DPU_ERROR("irq_idx=%d enabled with no callback\n", irq_idx);
	spin_unlock_irqrestore(&dpu_kms->irq_obj.cb_lock, irq_flags);

	return 0;
}

static void dpu_clear_all_irqs(struct dpu_kms *dpu_kms)
{
	if (!dpu_kms || !dpu_kms->hw_intr ||
			!dpu_kms->hw_intr->ops.clear_all_irqs)
		return;

	dpu_kms->hw_intr->ops.clear_all_irqs(dpu_kms->hw_intr);
}

static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms)
{
	if (!dpu_kms || !dpu_kms->hw_intr ||
			!dpu_kms->hw_intr->ops.disable_all_irqs)
		return;

	dpu_kms->hw_intr->ops.disable_all_irqs(dpu_kms->hw_intr);
}

#ifdef CONFIG_DEBUG_FS
#define DEFINE_DPU_DEBUGFS_SEQ_FOPS(__prefix)				\
static int __prefix ## _open(struct inode *inode, struct file *file)	\
{									\
	return single_open(file, __prefix ## _show, inode->i_private);	\
}									\
static const struct file_operations __prefix ## _fops = {		\
	.owner = THIS_MODULE,						\
	.open = __prefix ## _open,					\
	.release = single_release,					\
	.read = seq_read,						\
	.llseek = seq_lseek,						\
}

static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v)
{
	struct dpu_irq *irq_obj = s->private;
	struct dpu_irq_callback *cb;
	unsigned long irq_flags;
	int i, irq_count, enable_count, cb_count;

	if (!irq_obj || !irq_obj->enable_counts || !irq_obj->irq_cb_tbl) {
		DPU_ERROR("invalid parameters\n");
		return 0;
	}

	for (i = 0; i < irq_obj->total_irqs; i++) {
		spin_lock_irqsave(&irq_obj->cb_lock, irq_flags);
		cb_count = 0;
		irq_count = atomic_read(&irq_obj->irq_counts[i]);
		enable_count = atomic_read(&irq_obj->enable_counts[i]);
		list_for_each_entry(cb, &irq_obj->irq_cb_tbl[i], list)
			cb_count++;
		spin_unlock_irqrestore(&irq_obj->cb_lock, irq_flags);

		if (irq_count || enable_count || cb_count)
			seq_printf(s, "idx:%d irq:%d enable:%d cb:%d\n",
					i, irq_count, enable_count, cb_count);
	}

	return 0;
}

DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_debugfs_core_irq);

int dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms,
		struct dentry *parent)
{
	dpu_kms->irq_obj.debugfs_file = debugfs_create_file("core_irq", 0600,
			parent, &dpu_kms->irq_obj,
			&dpu_debugfs_core_irq_fops);

	return 0;
}

void dpu_debugfs_core_irq_destroy(struct dpu_kms *dpu_kms)
{
	debugfs_remove(dpu_kms->irq_obj.debugfs_file);
	dpu_kms->irq_obj.debugfs_file = NULL;
}

#else
int dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms,
		struct dentry *parent)
{
	return 0;
}

void dpu_debugfs_core_irq_destroy(struct dpu_kms *dpu_kms)
{
}
#endif

void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms)
{
	struct msm_drm_private *priv;
	int i;

	if (!dpu_kms) {
		DPU_ERROR("invalid dpu_kms\n");
		return;
	} else if (!dpu_kms->dev) {
		DPU_ERROR("invalid drm device\n");
		return;
	} else if (!dpu_kms->dev->dev_private) {
		DPU_ERROR("invalid device private\n");
		return;
	}
	priv = dpu_kms->dev->dev_private;

	pm_runtime_get_sync(&dpu_kms->pdev->dev);
	dpu_clear_all_irqs(dpu_kms);
	dpu_disable_all_irqs(dpu_kms);
	pm_runtime_put_sync(&dpu_kms->pdev->dev);

	spin_lock_init(&dpu_kms->irq_obj.cb_lock);

	/* Create irq callbacks for all possible irq_idx */
	dpu_kms->irq_obj.total_irqs = dpu_kms->hw_intr->irq_idx_tbl_size;
	dpu_kms->irq_obj.irq_cb_tbl = kcalloc(dpu_kms->irq_obj.total_irqs,
			sizeof(struct list_head), GFP_KERNEL);
	dpu_kms->irq_obj.enable_counts = kcalloc(dpu_kms->irq_obj.total_irqs,
			sizeof(atomic_t), GFP_KERNEL);
	dpu_kms->irq_obj.irq_counts = kcalloc(dpu_kms->irq_obj.total_irqs,
			sizeof(atomic_t), GFP_KERNEL);
	for (i = 0; i < dpu_kms->irq_obj.total_irqs; i++) {
		INIT_LIST_HEAD(&dpu_kms->irq_obj.irq_cb_tbl[i]);
		atomic_set(&dpu_kms->irq_obj.enable_counts[i], 0);
		atomic_set(&dpu_kms->irq_obj.irq_counts[i], 0);
	}
}

int dpu_core_irq_postinstall(struct dpu_kms *dpu_kms)
{
	return 0;
}

void dpu_core_irq_uninstall(struct dpu_kms *dpu_kms)
{
	struct msm_drm_private *priv;
	int i;

	if (!dpu_kms) {
		DPU_ERROR("invalid dpu_kms\n");
		return;
	} else if (!dpu_kms->dev) {
		DPU_ERROR("invalid drm device\n");
		return;
	} else if (!dpu_kms->dev->dev_private) {
		DPU_ERROR("invalid device private\n");
		return;
	}
	priv = dpu_kms->dev->dev_private;

	pm_runtime_get_sync(&dpu_kms->pdev->dev);
	for (i = 0; i < dpu_kms->irq_obj.total_irqs; i++)
		if (atomic_read(&dpu_kms->irq_obj.enable_counts[i]) ||
				!list_empty(&dpu_kms->irq_obj.irq_cb_tbl[i]))
			DPU_ERROR("irq_idx=%d still enabled/registered\n", i);

	dpu_clear_all_irqs(dpu_kms);
	dpu_disable_all_irqs(dpu_kms);
	pm_runtime_put_sync(&dpu_kms->pdev->dev);

	kfree(dpu_kms->irq_obj.irq_cb_tbl);
	kfree(dpu_kms->irq_obj.enable_counts);
	kfree(dpu_kms->irq_obj.irq_counts);
	dpu_kms->irq_obj.irq_cb_tbl = NULL;
	dpu_kms->irq_obj.enable_counts = NULL;
	dpu_kms->irq_obj.irq_counts = NULL;
	dpu_kms->irq_obj.total_irqs = 0;
}

irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms)
{
	/*
	 * Read interrupt status from all sources. Interrupt status are
	 * stored within hw_intr.
	 * Function will also clear the interrupt status after reading.
	 * Individual interrupt status bit will only get stored if it
	 * is enabled.
	 */
	dpu_kms->hw_intr->ops.get_interrupt_statuses(dpu_kms->hw_intr);

	/*
	 * Dispatch to HW driver to handle interrupt lookup that is being
	 * fired. When matching interrupt is located, HW driver will call to
	 * dpu_core_irq_callback_handler with the irq_idx from the lookup table.
	 * dpu_core_irq_callback_handler will perform the registered function
	 * callback, and do the interrupt status clearing once the registered
	 * callback is finished.
	 */
	dpu_kms->hw_intr->ops.dispatch_irqs(
			dpu_kms->hw_intr,
			dpu_core_irq_callback_handler,
			dpu_kms);

	return IRQ_HANDLED;
}
+0 −153
Original line number Original line Diff line number Diff line
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef __DPU_CORE_IRQ_H__
#define __DPU_CORE_IRQ_H__

#include "dpu_kms.h"
#include "dpu_hw_interrupts.h"

/**
 * dpu_core_irq_preinstall - perform pre-installation of core IRQ handler
 * @dpu_kms:		DPU handle
 * @return:		none
 */
void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms);

/**
 * dpu_core_irq_postinstall - perform post-installation of core IRQ handler
 * @dpu_kms:		DPU handle
 * @return:		0 if success; error code otherwise
 */
int dpu_core_irq_postinstall(struct dpu_kms *dpu_kms);

/**
 * dpu_core_irq_uninstall - uninstall core IRQ handler
 * @dpu_kms:		DPU handle
 * @return:		none
 */
void dpu_core_irq_uninstall(struct dpu_kms *dpu_kms);

/**
 * dpu_core_irq - core IRQ handler
 * @dpu_kms:		DPU handle
 * @return:		interrupt handling status
 */
irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms);

/**
 * dpu_core_irq_idx_lookup - IRQ helper function for lookup irq_idx from HW
 *                      interrupt mapping table.
 * @dpu_kms:		DPU handle
 * @intr_type:		DPU HW interrupt type for lookup
 * @instance_idx:	DPU HW block instance defined in dpu_hw_mdss.h
 * @return:		irq_idx or -EINVAL when fail to lookup
 */
int dpu_core_irq_idx_lookup(
		struct dpu_kms *dpu_kms,
		enum dpu_intr_type intr_type,
		uint32_t instance_idx);

/**
 * dpu_core_irq_enable - IRQ helper function for enabling one or more IRQs
 * @dpu_kms:		DPU handle
 * @irq_idxs:		Array of irq index
 * @irq_count:		Number of irq_idx provided in the array
 * @return:		0 for success enabling IRQ, otherwise failure
 *
 * This function increments count on each enable and decrements on each
 * disable.  Interrupts is enabled if count is 0 before increment.
 */
int dpu_core_irq_enable(
		struct dpu_kms *dpu_kms,
		int *irq_idxs,
		uint32_t irq_count);

/**
 * dpu_core_irq_disable - IRQ helper function for disabling one of more IRQs
 * @dpu_kms:		DPU handle
 * @irq_idxs:		Array of irq index
 * @irq_count:		Number of irq_idx provided in the array
 * @return:		0 for success disabling IRQ, otherwise failure
 *
 * This function increments count on each enable and decrements on each
 * disable.  Interrupts is disabled if count is 0 after decrement.
 */
int dpu_core_irq_disable(
		struct dpu_kms *dpu_kms,
		int *irq_idxs,
		uint32_t irq_count);

/**
 * dpu_core_irq_read - IRQ helper function for reading IRQ status
 * @dpu_kms:		DPU handle
 * @irq_idx:		irq index
 * @clear:		True to clear the irq after read
 * @return:		non-zero if irq detected; otherwise no irq detected
 */
u32 dpu_core_irq_read(
		struct dpu_kms *dpu_kms,
		int irq_idx,
		bool clear);

/**
 * dpu_core_irq_register_callback - For registering callback function on IRQ
 *                             interrupt
 * @dpu_kms:		DPU handle
 * @irq_idx:		irq index
 * @irq_cb:		IRQ callback structure, containing callback function
 *			and argument. Passing NULL for irq_cb will unregister
 *			the callback for the given irq_idx
 *			This must exist until un-registration.
 * @return:		0 for success registering callback, otherwise failure
 *
 * This function supports registration of multiple callbacks for each interrupt.
 */
int dpu_core_irq_register_callback(
		struct dpu_kms *dpu_kms,
		int irq_idx,
		struct dpu_irq_callback *irq_cb);

/**
 * dpu_core_irq_unregister_callback - For unregistering callback function on IRQ
 *                             interrupt
 * @dpu_kms:		DPU handle
 * @irq_idx:		irq index
 * @irq_cb:		IRQ callback structure, containing callback function
 *			and argument. Passing NULL for irq_cb will unregister
 *			the callback for the given irq_idx
 *			This must match with registration.
 * @return:		0 for success registering callback, otherwise failure
 *
 * This function supports registration of multiple callbacks for each interrupt.
 */
int dpu_core_irq_unregister_callback(
		struct dpu_kms *dpu_kms,
		int irq_idx,
		struct dpu_irq_callback *irq_cb);

/**
 * dpu_debugfs_core_irq_init - register core irq debugfs
 * @dpu_kms: pointer to kms
 * @parent: debugfs directory root
 * @Return: 0 on success
 */
int dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms,
		struct dentry *parent);

/**
 * dpu_debugfs_core_irq_destroy - deregister core irq debugfs
 * @dpu_kms: pointer to kms
 */
void dpu_debugfs_core_irq_destroy(struct dpu_kms *dpu_kms);

#endif /* __DPU_CORE_IRQ_H__ */
+0 −637

File deleted.

Preview size limit exceeded, changes collapsed.

+0 −133
Original line number Original line Diff line number Diff line
/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef _DPU_CORE_PERF_H_
#define _DPU_CORE_PERF_H_

#include <linux/types.h>
#include <linux/dcache.h>
#include <linux/mutex.h>
#include <drm/drm_crtc.h>

#include "dpu_hw_catalog.h"
#include "dpu_power_handle.h"

#define	DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE	412500000

/**
 * struct dpu_core_perf_params - definition of performance parameters
 * @max_per_pipe_ib: maximum instantaneous bandwidth request
 * @bw_ctl: arbitrated bandwidth request
 * @core_clk_rate: core clock rate request
 */
struct dpu_core_perf_params {
	u64 max_per_pipe_ib[DPU_POWER_HANDLE_DBUS_ID_MAX];
	u64 bw_ctl[DPU_POWER_HANDLE_DBUS_ID_MAX];
	u64 core_clk_rate;
};

/**
 * struct dpu_core_perf_tune - definition of performance tuning control
 * @mode: performance mode
 * @min_core_clk: minimum core clock
 * @min_bus_vote: minimum bus vote
 */
struct dpu_core_perf_tune {
	u32 mode;
	u64 min_core_clk;
	u64 min_bus_vote;
};

/**
 * struct dpu_core_perf - definition of core performance context
 * @dev: Pointer to drm device
 * @debugfs_root: top level debug folder
 * @catalog: Pointer to catalog configuration
 * @phandle: Pointer to power handler
 * @core_clk: Pointer to core clock structure
 * @core_clk_rate: current core clock rate
 * @max_core_clk_rate: maximum allowable core clock rate
 * @perf_tune: debug control for performance tuning
 * @enable_bw_release: debug control for bandwidth release
 * @fix_core_clk_rate: fixed core clock request in Hz used in mode 2
 * @fix_core_ib_vote: fixed core ib vote in bps used in mode 2
 * @fix_core_ab_vote: fixed core ab vote in bps used in mode 2
 */
struct dpu_core_perf {
	struct drm_device *dev;
	struct dentry *debugfs_root;
	struct dpu_mdss_cfg *catalog;
	struct dpu_power_handle *phandle;
	struct dss_clk *core_clk;
	u64 core_clk_rate;
	u64 max_core_clk_rate;
	struct dpu_core_perf_tune perf_tune;
	u32 enable_bw_release;
	u64 fix_core_clk_rate;
	u64 fix_core_ib_vote;
	u64 fix_core_ab_vote;
};

/**
 * dpu_core_perf_crtc_check - validate performance of the given crtc state
 * @crtc: Pointer to crtc
 * @state: Pointer to new crtc state
 * return: zero if success, or error code otherwise
 */
int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
		struct drm_crtc_state *state);

/**
 * dpu_core_perf_crtc_update - update performance of the given crtc
 * @crtc: Pointer to crtc
 * @params_changed: true if crtc parameters are modified
 * @stop_req: true if this is a stop request
 * return: zero if success, or error code otherwise
 */
int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
		int params_changed, bool stop_req);

/**
 * dpu_core_perf_crtc_release_bw - release bandwidth of the given crtc
 * @crtc: Pointer to crtc
 */
void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc);

/**
 * dpu_core_perf_destroy - destroy the given core performance context
 * @perf: Pointer to core performance context
 */
void dpu_core_perf_destroy(struct dpu_core_perf *perf);

/**
 * dpu_core_perf_init - initialize the given core performance context
 * @perf: Pointer to core performance context
 * @dev: Pointer to drm device
 * @catalog: Pointer to catalog
 * @phandle: Pointer to power handle
 * @core_clk: pointer to core clock
 */
int dpu_core_perf_init(struct dpu_core_perf *perf,
		struct drm_device *dev,
		struct dpu_mdss_cfg *catalog,
		struct dpu_power_handle *phandle,
		struct dss_clk *core_clk);

/**
 * dpu_core_perf_debugfs_init - initialize debugfs for core performance context
 * @perf: Pointer to core performance context
 * @debugfs_parent: Pointer to parent debugfs
 */
int dpu_core_perf_debugfs_init(struct dpu_core_perf *perf,
		struct dentry *parent);

#endif /* _DPU_CORE_PERF_H_ */
Loading