From: Rajesh Yadav <ryadav-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: robdclark-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org,
Rajesh Yadav <ryadav-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>,
hoegsberg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org
Subject: [DPU PATCH v3 03/12] drm/msm/dpu: add MDSS top level driver for dpu
Date: Mon, 14 May 2018 20:56:50 +0530 [thread overview]
Message-ID: <1526311619-3309-4-git-send-email-ryadav@codeaurora.org> (raw)
In-Reply-To: <1526311619-3309-1-git-send-email-ryadav-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
SoCs containing dpu have a MDSS top level wrapper
which includes sub-blocks as dpu, dsi, phy, dp etc.
MDSS top level wrapper manages common resources like
common clocks, power and irq for its sub-blocks.
Currently, in dpu driver, all the power resource
management is part of power_handle which manages
these resources via a custom implementation. And
the resource relationships are not modelled properly
in dt. Moreover the irq domain handling code is part
of dpu device (which is a child device) due to lack
of a dedicated driver for MDSS top level wrapper
device.
This change adds dpu_mdss top level driver to handle
common clock like - core clock, ahb clock
(for register access), main power supply (i.e. gdsc)
and irq management.
The top level mdss device/driver acts as an interrupt
controller and manage hwirq mapping for its child
devices.
It implements runtime_pm support for resource management.
Child nodes can control these resources via runtime_pm
get/put calls on their corresponding devices due to parent
child relationship defined in dt.
Changes in v3:
- use "clock-frequency" dt-binding instead of "clock-rate",
is it an optional binding (Sean Paul)
- remove handling of "clock-max-rate" proprietary
dt-binding (Sean Paul)
- remove intermediate storing of msm_ioremap() retcode
on failure instead return retcode directly (Sean Paul)
- msm_ioremap() prints error log in case of failure,
so remove additional log from it's caller
- updated max core clock rate
- dropped (Reviewed-by: Jordan Crouse) due to above changes
Changes in v2:
- merge _dpu_mdss_hw_rev_init to dpu_mdss_init (Sean Paul)
- merge _dpu_mdss_get_intr_sources to dpu_mdss_irq (Sean Paul)
- fix indentation for irq_find_mapping call (Sean Paul)
- remove unnecessary goto statements from dpu_mdss_irq (Sean Paul)
- remove redundant param checks from
dpu_mdss_irq_mask/unmask (Sean Paul/Jordan Crouse)
- remove redundant param checks from
dpu_mdss_irqdomain_map (Sean Paul/Jordan Crouse)
- return error code from dpu_mdss_enable/disable (Sean Paul/Jordan Crouse)
- remove redundant param check from dpu_mdss_destroy (Sean Paul)
- remove explicit calls to devm_kfree (Sean Paul/Jordan Crouse)
- remove compatibility check from dpu_mdss_init as
it is conditionally called from msm_drv (Sean Paul)
- reworked msm_dss_parse_clock() to add return checks for
of_property_read_* calls, fix log message and
fix alignment issues (Sean Paul/Jordan Crouse)
- remove extra line before dpu_mdss_init (Sean Paul)
- remove redundant param checks from __intr_offset and
make it a void function to avoid unnecessary error
handling from caller (Jordan Crouse)
- remove redundant param check from dpu_mdss_irq (Jordan Crouse)
- change mdss address space log message to debug and use %pK for
kernel pointers (Jordan Crouse)
- remove unnecessary log message from msm_dss_parse_clock (Jordan Crouse)
- don't export msm_dss_parse_clock since it is used
only by dpu driver (Jordan Crouse)
Signed-off-by: Rajesh Yadav <ryadav@codeaurora.org>
---
drivers/gpu/drm/msm/Makefile | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c | 97 ---------
drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 14 --
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 2 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 9 -
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 7 -
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 28 +--
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 11 -
drivers/gpu/drm/msm/disp/dpu1/dpu_irq.c | 48 +----
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 6 -
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 2 -
drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 251 ++++++++++++++++++++++
drivers/gpu/drm/msm/dpu_io_util.c | 49 +++++
drivers/gpu/drm/msm/msm_drv.c | 26 ++-
drivers/gpu/drm/msm/msm_drv.h | 2 +-
drivers/gpu/drm/msm/msm_kms.h | 1 +
include/linux/dpu_io_util.h | 2 +
17 files changed, 329 insertions(+), 227 deletions(-)
create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index d7558ed..d9826c1 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -81,6 +81,7 @@ msm-y := \
disp/dpu1/dpu_reg_dma.o \
disp/dpu1/dpu_rm.o \
disp/dpu1/dpu_vbif.o \
+ disp/dpu1/dpu_mdss.o \
dpu_dbg.o \
dpu_io_util.o \
dpu_dbg_evtlog.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
index fe33013..977adc4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
@@ -515,103 +515,6 @@ void dpu_core_irq_uninstall(struct dpu_kms *dpu_kms)
dpu_kms->irq_obj.total_irqs = 0;
}
-static void dpu_core_irq_mask(struct irq_data *irqd)
-{
- struct dpu_kms *dpu_kms;
-
- if (!irqd || !irq_data_get_irq_chip_data(irqd)) {
- DPU_ERROR("invalid parameters irqd %d\n", irqd != NULL);
- return;
- }
- dpu_kms = irq_data_get_irq_chip_data(irqd);
-
- /* memory barrier */
- smp_mb__before_atomic();
- clear_bit(irqd->hwirq, &dpu_kms->irq_controller.enabled_mask);
- /* memory barrier */
- smp_mb__after_atomic();
-}
-
-static void dpu_core_irq_unmask(struct irq_data *irqd)
-{
- struct dpu_kms *dpu_kms;
-
- if (!irqd || !irq_data_get_irq_chip_data(irqd)) {
- DPU_ERROR("invalid parameters irqd %d\n", irqd != NULL);
- return;
- }
- dpu_kms = irq_data_get_irq_chip_data(irqd);
-
- /* memory barrier */
- smp_mb__before_atomic();
- set_bit(irqd->hwirq, &dpu_kms->irq_controller.enabled_mask);
- /* memory barrier */
- smp_mb__after_atomic();
-}
-
-static struct irq_chip dpu_core_irq_chip = {
- .name = "dpu",
- .irq_mask = dpu_core_irq_mask,
- .irq_unmask = dpu_core_irq_unmask,
-};
-
-static int dpu_core_irqdomain_map(struct irq_domain *domain,
- unsigned int irq, irq_hw_number_t hwirq)
-{
- struct dpu_kms *dpu_kms;
- int rc;
-
- if (!domain || !domain->host_data) {
- DPU_ERROR("invalid parameters domain %d\n", domain != NULL);
- return -EINVAL;
- }
- dpu_kms = domain->host_data;
-
- irq_set_chip_and_handler(irq, &dpu_core_irq_chip, handle_level_irq);
- rc = irq_set_chip_data(irq, dpu_kms);
-
- return rc;
-}
-
-static const struct irq_domain_ops dpu_core_irqdomain_ops = {
- .map = dpu_core_irqdomain_map,
- .xlate = irq_domain_xlate_onecell,
-};
-
-int dpu_core_irq_domain_add(struct dpu_kms *dpu_kms)
-{
- struct device *dev;
- struct irq_domain *domain;
-
- if (!dpu_kms->dev || !dpu_kms->dev->dev) {
- pr_err("invalid device handles\n");
- return -EINVAL;
- }
-
- dev = dpu_kms->dev->dev;
-
- domain = irq_domain_add_linear(dev->of_node, 32,
- &dpu_core_irqdomain_ops, dpu_kms);
- if (!domain) {
- pr_err("failed to add irq_domain\n");
- return -EINVAL;
- }
-
- dpu_kms->irq_controller.enabled_mask = 0;
- dpu_kms->irq_controller.domain = domain;
-
- return 0;
-}
-
-int dpu_core_irq_domain_fini(struct dpu_kms *dpu_kms)
-{
- if (dpu_kms->irq_controller.domain) {
- irq_domain_remove(dpu_kms->irq_controller.domain);
- dpu_kms->irq_controller.domain = NULL;
- }
- return 0;
-}
-
irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms)
{
/*
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
index 64a54fe..8fa59db 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
@@ -38,20 +38,6 @@
void dpu_core_irq_uninstall(struct dpu_kms *dpu_kms);
/**
- * dpu_core_irq_domain_add - Add core IRQ domain for DPU
- * @dpu_kms: DPU handle
- * @return: none
- */
-int dpu_core_irq_domain_add(struct dpu_kms *dpu_kms);
-
-/**
- * dpu_core_irq_domain_fini - uninstall core IRQ domain
- * @dpu_kms: DPU handle
- * @return: 0 if success; error code otherwise
- */
-int dpu_core_irq_domain_fini(struct dpu_kms *dpu_kms);
-
-/**
* dpu_core_irq - core IRQ handler
* @dpu_kms: DPU handle
* @return: interrupt handling status
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
index 1965ff5..fe4d8ea 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -21,7 +21,7 @@
#include "dpu_hw_catalog.h"
#include "dpu_power_handle.h"
-#define DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE 320000000
+#define DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE 412500000
/**
* struct dpu_core_perf_params - definition of performance parameters
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 8e779c0..c5b370f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -77,13 +77,6 @@
.has_idle_pc = true,
};
-static struct dpu_mdss_base_cfg sdm845_mdss[] = {
- {
- .name = "mdss_0", .id = MDP_TOP,
- .base = 0x0, .features = 0
- },
-};
-
static struct dpu_mdp_cfg sdm845_mdp[] = {
{
.name = "top_0", .id = MDP_TOP,
@@ -550,8 +543,6 @@ void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
{
*dpu_cfg = (struct dpu_mdss_cfg){
.caps = &sdm845_dpu_caps,
- .mdss_count = ARRAY_SIZE(sdm845_mdss),
- .mdss = sdm845_mdss,
.mdp_count = ARRAY_SIZE(sdm845_mdp),
.mdp = sdm845_mdp,
.ctl_count = ARRAY_SIZE(sdm845_ctl),
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 39bec0a..7084643 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -492,10 +492,6 @@ struct dpu_wb_sub_blocks {
u32 maxlinewidth;
};
-struct dpu_mdss_base_cfg {
- DPU_HW_BLK_INFO;
-};
-
/**
* dpu_clk_ctrl_type - Defines top level clock control signals
*/
@@ -875,9 +871,6 @@ struct dpu_mdss_cfg {
const struct dpu_caps *caps;
- u32 mdss_count;
- struct dpu_mdss_base_cfg *mdss;
-
u32 mdp_count;
struct dpu_mdp_cfg *mdp;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index 9767cc8..73f084c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -22,7 +22,6 @@
* Register offsets in MDSS register file for the interrupt registers
* w.r.t. to the MDSS base
*/
-#define HW_INTR_STATUS 0x0010
#define MDP_SSPP_TOP0_OFF 0x1000
#define MDP_INTF_0_OFF 0x6B000
#define MDP_INTF_1_OFF 0x6B800
@@ -1017,17 +1016,6 @@ static int dpu_hw_intr_get_valid_interrupts(struct dpu_hw_intr *intr,
return 0;
}
-static int dpu_hw_intr_get_interrupt_sources(struct dpu_hw_intr *intr,
- uint32_t *sources)
-{
- if (!intr || !sources)
- return -EINVAL;
-
- *sources = DPU_REG_READ(&intr->hw, HW_INTR_STATUS);
-
- return 0;
-}
-
static void dpu_hw_intr_get_interrupt_statuses(struct dpu_hw_intr *intr)
{
int i;
@@ -1162,7 +1150,6 @@ static void __setup_intr_ops(struct dpu_hw_intr_ops *ops)
ops->clear_all_irqs = dpu_hw_intr_clear_irqs;
ops->disable_all_irqs = dpu_hw_intr_disable_irqs;
ops->get_valid_interrupts = dpu_hw_intr_get_valid_interrupts;
- ops->get_interrupt_sources = dpu_hw_intr_get_interrupt_sources;
ops->get_interrupt_statuses = dpu_hw_intr_get_interrupt_statuses;
ops->clear_interrupt_status = dpu_hw_intr_clear_interrupt_status;
ops->clear_intr_status_nolock = dpu_hw_intr_clear_intr_status_nolock;
@@ -1170,23 +1157,18 @@ static void __setup_intr_ops(struct dpu_hw_intr_ops *ops)
ops->get_intr_status_nolock = dpu_hw_intr_get_intr_status_nolock;
}
-static struct dpu_mdss_base_cfg *__intr_offset(struct dpu_mdss_cfg *m,
+static void __intr_offset(struct dpu_mdss_cfg *m,
void __iomem *addr, struct dpu_hw_blk_reg_map *hw)
{
- if (!m || !addr || !hw || m->mdp_count == 0)
- return NULL;
-
hw->base_off = addr;
- hw->blk_off = m->mdss[0].base;
+ hw->blk_off = m->mdp[0].base;
hw->hwversion = m->hwversion;
- return &m->mdss[0];
}
struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
struct dpu_mdss_cfg *m)
{
struct dpu_hw_intr *intr;
- struct dpu_mdss_base_cfg *cfg;
if (!addr || !m)
return ERR_PTR(-EINVAL);
@@ -1195,11 +1177,7 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
if (!intr)
return ERR_PTR(-ENOMEM);
- cfg = __intr_offset(m, addr, &intr->hw);
- if (!cfg) {
- kfree(intr);
- return ERR_PTR(-EINVAL);
- }
+ __intr_offset(m, addr, &intr->hw);
__setup_intr_ops(&intr->ops);
intr->irq_idx_tbl_size = ARRAY_SIZE(dpu_irq_map);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
index 2f1a828..b52cdca 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
@@ -242,17 +242,6 @@ struct dpu_hw_intr_ops {
int (*get_valid_interrupts)(
struct dpu_hw_intr *intr,
uint32_t *mask);
-
- /**
- * get_interrupt_sources - Gets the bitmask of the DPU interrupt
- * source that are currently fired.
- * @intr: HW interrupt handle
- * @sources: Returning the DPU interrupt source status bit mask
- * @return: 0 for success, otherwise failure
- */
- int (*get_interrupt_sources)(
- struct dpu_hw_intr *intr,
- uint32_t *sources);
};
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_irq.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_irq.c
index 19c0929..d5e6ce0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_irq.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_irq.c
@@ -19,56 +19,11 @@
#include "dpu_irq.h"
#include "dpu_core_irq.h"
-static uint32_t g_dpu_irq_status;
-
irqreturn_t dpu_irq(struct msm_kms *kms)
{
struct dpu_kms *dpu_kms = to_dpu_kms(kms);
- u32 interrupts;
-
- dpu_kms->hw_intr->ops.get_interrupt_sources(dpu_kms->hw_intr,
- &interrupts);
-
- /* store irq status in case of irq-storm debugging */
- g_dpu_irq_status = interrupts;
-
- /*
- * Taking care of MDP interrupt
- */
- if (interrupts & IRQ_SOURCE_MDP) {
- interrupts &= ~IRQ_SOURCE_MDP;
- dpu_core_irq(dpu_kms);
- }
-
- /*
- * Routing all other interrupts to external drivers
- */
- while (interrupts) {
- irq_hw_number_t hwirq = fls(interrupts) - 1;
- unsigned int mapping;
- int rc;
-
- mapping = irq_find_mapping(dpu_kms->irq_controller.domain,
- hwirq);
- if (mapping == 0) {
- DPU_EVT32(hwirq, DPU_EVTLOG_ERROR);
- goto error;
- }
-
- rc = generic_handle_irq(mapping);
- if (rc < 0) {
- DPU_EVT32(hwirq, mapping, rc, DPU_EVTLOG_ERROR);
- goto error;
- }
-
- interrupts &= ~(1 << hwirq);
- }
-
- return IRQ_HANDLED;
-error:
- /* bad situation, inform irq system, it may disable overall MDSS irq */
- return IRQ_NONE;
+ return dpu_core_irq(dpu_kms);
}
void dpu_irq_preinstall(struct msm_kms *kms)
@@ -108,5 +63,4 @@ void dpu_irq_uninstall(struct msm_kms *kms)
}
dpu_core_irq_uninstall(dpu_kms);
- dpu_core_irq_domain_fini(dpu_kms);
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 06adb38..e4ab753 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -636,10 +636,6 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
priv = dev->dev_private;
catalog = dpu_kms->catalog;
- ret = dpu_core_irq_domain_add(dpu_kms);
- if (ret)
- goto fail_irq;
-
/*
* Create encoder and query display drivers to create
* bridges and connectors
@@ -716,8 +712,6 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
return 0;
fail:
_dpu_kms_drm_obj_destroy(dpu_kms);
-fail_irq:
- dpu_core_irq_domain_fini(dpu_kms);
return ret;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 5b0c081..a1c0910 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -184,8 +184,6 @@ struct dpu_kms {
struct regulator *mmagic;
struct regulator *venus;
- struct dpu_irq_controller irq_controller;
-
struct dpu_hw_intr *hw_intr;
struct dpu_irq irq_obj;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
new file mode 100644
index 0000000..04accdf
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -0,0 +1,251 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ * Copyright (c) 2018, The Linux Foundation
+ */
+
+#include "dpu_kms.h"
+
+#define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
+
+#define HW_INTR_STATUS 0x0010
+
+struct dpu_mdss {
+ struct msm_mdss base;
+ void __iomem *mmio;
+ unsigned long mmio_len;
+ u32 hwversion;
+ struct dss_module_power mp;
+ struct dpu_irq_controller irq_controller;
+};
+
+static irqreturn_t dpu_mdss_irq(int irq, void *arg)
+{
+ struct dpu_mdss *dpu_mdss = arg;
+ u32 interrupts;
+
+ interrupts = readl_relaxed(dpu_mdss->mmio + HW_INTR_STATUS);
+
+ while (interrupts) {
+ irq_hw_number_t hwirq = fls(interrupts) - 1;
+ unsigned int mapping;
+ int rc;
+
+ mapping = irq_find_mapping(dpu_mdss->irq_controller.domain,
+ hwirq);
+ if (mapping == 0) {
+ DPU_EVT32(hwirq, DPU_EVTLOG_ERROR);
+ return IRQ_NONE;
+ }
+
+ rc = generic_handle_irq(mapping);
+ if (rc < 0) {
+ DPU_EVT32(hwirq, mapping, rc, DPU_EVTLOG_ERROR);
+ return IRQ_NONE;
+ }
+
+ interrupts &= ~(1 << hwirq);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void dpu_mdss_irq_mask(struct irq_data *irqd)
+{
+ struct dpu_mdss *dpu_mdss = irq_data_get_irq_chip_data(irqd);
+
+ /* memory barrier */
+ smp_mb__before_atomic();
+ clear_bit(irqd->hwirq, &dpu_mdss->irq_controller.enabled_mask);
+ /* memory barrier */
+ smp_mb__after_atomic();
+}
+
+static void dpu_mdss_irq_unmask(struct irq_data *irqd)
+{
+ struct dpu_mdss *dpu_mdss = irq_data_get_irq_chip_data(irqd);
+
+ /* memory barrier */
+ smp_mb__before_atomic();
+ set_bit(irqd->hwirq, &dpu_mdss->irq_controller.enabled_mask);
+ /* memory barrier */
+ smp_mb__after_atomic();
+}
+
+static struct irq_chip dpu_mdss_irq_chip = {
+ .name = "dpu_mdss",
+ .irq_mask = dpu_mdss_irq_mask,
+ .irq_unmask = dpu_mdss_irq_unmask,
+};
+
+static int dpu_mdss_irqdomain_map(struct irq_domain *domain,
+ unsigned int irq, irq_hw_number_t hwirq)
+{
+ struct dpu_mdss *dpu_mdss = domain->host_data;
+ int ret;
+
+ irq_set_chip_and_handler(irq, &dpu_mdss_irq_chip, handle_level_irq);
+ ret = irq_set_chip_data(irq, dpu_mdss);
+
+ return ret;
+}
+
+static const struct irq_domain_ops dpu_mdss_irqdomain_ops = {
+ .map = dpu_mdss_irqdomain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+static int _dpu_mdss_irq_domain_add(struct dpu_mdss *dpu_mdss)
+{
+ struct device *dev;
+ struct irq_domain *domain;
+
+ dev = dpu_mdss->base.dev->dev;
+
+ domain = irq_domain_add_linear(dev->of_node, 32,
+ &dpu_mdss_irqdomain_ops, dpu_mdss);
+ if (!domain) {
+ DPU_ERROR("failed to add irq_domain\n");
+ return -EINVAL;
+ }
+
+ dpu_mdss->irq_controller.enabled_mask = 0;
+ dpu_mdss->irq_controller.domain = domain;
+
+ return 0;
+}
+
+int _dpu_mdss_irq_domain_fini(struct dpu_mdss *dpu_mdss)
+{
+ if (dpu_mdss->irq_controller.domain) {
+ irq_domain_remove(dpu_mdss->irq_controller.domain);
+ dpu_mdss->irq_controller.domain = NULL;
+ }
+ return 0;
+}
+static int dpu_mdss_enable(struct msm_mdss *mdss)
+{
+ struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
+ struct dss_module_power *mp = &dpu_mdss->mp;
+ int ret;
+
+ ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
+ if (ret)
+ DPU_ERROR("clock enable failed, ret:%d\n", ret);
+
+ return ret;
+}
+
+static int dpu_mdss_disable(struct msm_mdss *mdss)
+{
+ struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
+ struct dss_module_power *mp = &dpu_mdss->mp;
+ int ret;
+
+ ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
+ if (ret)
+ DPU_ERROR("clock disable failed, ret:%d\n", ret);
+
+ return ret;
+}
+
+static void dpu_mdss_destroy(struct drm_device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev->dev);
+ struct msm_drm_private *priv = dev->dev_private;
+ struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss);
+ struct dss_module_power *mp = &dpu_mdss->mp;
+
+ _dpu_mdss_irq_domain_fini(dpu_mdss);
+
+ msm_dss_put_clk(mp->clk_config, mp->num_clk);
+ devm_kfree(&pdev->dev, mp->clk_config);
+
+ if (dpu_mdss->mmio)
+ msm_iounmap(pdev, dpu_mdss->mmio);
+ dpu_mdss->mmio = NULL;
+
+ pm_runtime_disable(dev->dev);
+ priv->mdss = NULL;
+}
+
+static const struct msm_mdss_funcs mdss_funcs = {
+ .enable = dpu_mdss_enable,
+ .disable = dpu_mdss_disable,
+ .destroy = dpu_mdss_destroy,
+};
+
+int dpu_mdss_init(struct drm_device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev->dev);
+ struct msm_drm_private *priv = dev->dev_private;
+ struct dpu_mdss *dpu_mdss;
+ struct dss_module_power *mp;
+ int ret = 0;
+
+ dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL);
+ if (!dpu_mdss)
+ return -ENOMEM;
+
+ dpu_mdss->mmio = msm_ioremap(pdev, "mdss_phys", "mdss_phys");
+ if (IS_ERR(dpu_mdss->mmio))
+ return PTR_ERR(dpu_mdss->mmio);
+
+ DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio);
+ dpu_mdss->mmio_len = msm_iomap_size(pdev, "mdss_phys");
+
+ mp = &dpu_mdss->mp;
+ ret = msm_dss_parse_clock(pdev, mp);
+ if (ret) {
+ DPU_ERROR("failed to parse clocks, ret=%d\n", ret);
+ goto clk_parse_err;
+ }
+
+ ret = msm_dss_get_clk(&pdev->dev, mp->clk_config, mp->num_clk);
+ if (ret) {
+ DPU_ERROR("failed to get clocks, ret=%d\n", ret);
+ goto clk_get_error;
+ }
+
+ ret = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
+ if (ret) {
+ DPU_ERROR("failed to set clock rate, ret=%d\n", ret);
+ goto clk_rate_error;
+ }
+
+ dpu_mdss->base.dev = dev;
+ dpu_mdss->base.funcs = &mdss_funcs;
+
+ ret = _dpu_mdss_irq_domain_add(dpu_mdss);
+ if (ret)
+ goto irq_domain_error;
+
+ ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0),
+ dpu_mdss_irq, 0, "dpu_mdss_isr", dpu_mdss);
+ if (ret) {
+ DPU_ERROR("failed to init irq: %d\n", ret);
+ goto irq_error;
+ }
+
+ pm_runtime_enable(dev->dev);
+
+ pm_runtime_get_sync(dev->dev);
+ dpu_mdss->hwversion = readl_relaxed(dpu_mdss->mmio);
+ pm_runtime_put_sync(dev->dev);
+
+ priv->mdss = &dpu_mdss->base;
+
+ return ret;
+
+irq_error:
+ _dpu_mdss_irq_domain_fini(dpu_mdss);
+irq_domain_error:
+clk_rate_error:
+ msm_dss_put_clk(mp->clk_config, mp->num_clk);
+clk_get_error:
+ devm_kfree(&pdev->dev, mp->clk_config);
+clk_parse_err:
+ if (dpu_mdss->mmio)
+ msm_iounmap(pdev, dpu_mdss->mmio);
+ dpu_mdss->mmio = NULL;
+ return ret;
+}
diff --git a/drivers/gpu/drm/msm/dpu_io_util.c b/drivers/gpu/drm/msm/dpu_io_util.c
index a18bc99..ecc297c 100644
--- a/drivers/gpu/drm/msm/dpu_io_util.c
+++ b/drivers/gpu/drm/msm/dpu_io_util.c
@@ -448,6 +448,55 @@ int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
} /* msm_dss_enable_clk */
EXPORT_SYMBOL(msm_dss_enable_clk);
+int msm_dss_parse_clock(struct platform_device *pdev,
+ struct dss_module_power *mp)
+{
+ u32 i, rc = 0;
+ const char *clock_name;
+ u32 rate = 0;
+ int num_clk = 0;
+
+ if (!pdev || !mp)
+ return -EINVAL;
+
+ mp->num_clk = 0;
+ num_clk = of_property_count_strings(pdev->dev.of_node, "clock-names");
+ if (num_clk <= 0) {
+ pr_debug("clocks are not defined\n");
+ return 0;
+ }
+
+ mp->clk_config = devm_kzalloc(&pdev->dev,
+ sizeof(struct dss_clk) * num_clk,
+ GFP_KERNEL);
+ if (!mp->clk_config)
+ return -ENOMEM;
+
+ for (i = 0; i < num_clk; i++) {
+ rc = of_property_read_string_index(pdev->dev.of_node,
+ "clock-names", i,
+ &clock_name);
+ if (rc)
+ break;
+ strlcpy(mp->clk_config[i].clk_name, clock_name,
+ sizeof(mp->clk_config[i].clk_name));
+
+ mp->clk_config[i].type = DSS_CLK_AHB;
+ rc = of_property_read_u32_index(pdev->dev.of_node,
+ "clock-frequency", i,
+ &rate);
+ if (rc)
+ continue;
+ mp->clk_config[i].rate = rate;
+ if (rate)
+ mp->clk_config[i].type = DSS_CLK_PCLK;
+ }
+
+ if (!rc)
+ mp->num_clk = num_clk;
+
+ return rc;
+}
int dpu_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr,
uint8_t reg_offset, uint8_t *read_buf)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 5d8f1b6..a0e73ea 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -503,7 +503,18 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
ddev->dev_private = priv;
priv->dev = ddev;
- ret = mdp5_mdss_init(ddev);
+ switch (get_mdp_ver(pdev)) {
+ case KMS_MDP5:
+ ret = mdp5_mdss_init(ddev);
+ break;
+ case KMS_DPU:
+ ret = dpu_mdss_init(ddev);
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
if (ret)
goto mdss_init_fail;
@@ -1539,12 +1550,13 @@ static int add_display_components(struct device *dev,
int ret;
/*
- * MDP5 based devices don't have a flat hierarchy. There is a top level
- * parent: MDSS, and children: MDP5, DSI, HDMI, eDP etc. Populate the
- * children devices, find the MDP5 node, and then add the interfaces
- * to our components list.
+ * MDP5/DPU based devices don't have a flat hierarchy. There is a top
+ * level parent: MDSS, and children: MDP5/DPU, DSI, HDMI, eDP etc.
+ * Populate the children devices, find the MDP5/DPU node, and then add
+ * the interfaces to our components list.
*/
- if (of_device_is_compatible(dev->of_node, "qcom,mdss")) {
+ if (of_device_is_compatible(dev->of_node, "qcom,mdss") ||
+ of_device_is_compatible(dev->of_node, "qcom,dpu-mdss")) {
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
if (ret) {
dev_err(dev, "failed to populate children devices\n");
@@ -1686,7 +1698,7 @@ static int msm_pdev_remove(struct platform_device *pdev)
{ .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 },
{ .compatible = "qcom,mdss", .data = (void *)KMS_MDP5 },
#ifdef CONFIG_DRM_MSM_DPU
- { .compatible = "qcom,dpu-kms", .data = (void *)KMS_DPU },
+ { .compatible = "qcom,dpu-mdss", .data = (void *)KMS_DPU },
#endif
{}
};
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 90a2521..e8e5e73 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -381,7 +381,7 @@ struct msm_drm_private {
/* subordinate devices, if present: */
struct platform_device *gpu_pdev;
- /* top level MDSS wrapper device (for MDP5 only) */
+ /* top level MDSS wrapper device (for MDP5/DPU only) */
struct msm_mdss *mdss;
/* possibly this should be in the kms component, but it is
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 9a7bc7d..5e1de85 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -144,6 +144,7 @@ struct msm_mdss {
};
int mdp5_mdss_init(struct drm_device *dev);
+int dpu_mdss_init(struct drm_device *dev);
/**
* Mode Set Utility Functions
diff --git a/include/linux/dpu_io_util.h b/include/linux/dpu_io_util.h
index 7c73899..45e606f 100644
--- a/include/linux/dpu_io_util.h
+++ b/include/linux/dpu_io_util.h
@@ -104,6 +104,8 @@ int msm_dss_config_vreg(struct device *dev, struct dss_vreg *in_vreg,
void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk);
int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk);
int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable);
+int msm_dss_parse_clock(struct platform_device *pdev,
+ struct dss_module_power *mp);
int dpu_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr,
uint8_t reg_offset, uint8_t *read_buf);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno
next prev parent reply other threads:[~2018-05-14 15:26 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-14 15:26 [DPU PATCH v3 00/12] Refactor DPU device/driver hierarchy and add runtime_pm support Rajesh Yadav
2018-05-14 15:26 ` [DPU PATCH v3 01/12] drm/msm: remove redundant pm_runtime_enable call from msm_drv Rajesh Yadav
[not found] ` <1526311619-3309-1-git-send-email-ryadav-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-05-14 15:26 ` [DPU PATCH v3 02/12] drm/msm/mdp5: subclass msm_mdss for mdp5 Rajesh Yadav
2018-05-14 15:26 ` Rajesh Yadav [this message]
2018-05-14 15:26 ` [DPU PATCH v3 04/12] drm/msm/dpu: create new platform driver for dpu device Rajesh Yadav
2018-05-14 15:26 ` [DPU PATCH v3 05/12] drm/msm/dpu: update dpu sub-block offsets wrt dpu base address Rajesh Yadav
[not found] ` <1526311619-3309-6-git-send-email-ryadav-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-06-19 8:59 ` ryadav-sgV2jX0FEOL9JmXXK+q4OQ
2018-05-14 15:26 ` [DPU PATCH v3 06/12] drm/msm/dpu: use runtime_pm calls on dpu device Rajesh Yadav
2018-05-14 15:26 ` [DPU PATCH v3 07/12] drm/msm/dpu: remove clock management code from dpu_power_handle Rajesh Yadav
2018-05-14 15:26 ` [DPU PATCH v3 08/12] drm/msm/dpu: remove power " Rajesh Yadav
2018-05-14 15:26 ` [DPU PATCH v3 09/12] drm/msm/dp: remove dpu_power_handle calls from dp driver Rajesh Yadav
2018-05-14 15:26 ` [DPU PATCH v3 10/12] drm/msm/dpu: use runtime_pm calls in dpu_dbg Rajesh Yadav
2018-05-14 15:26 ` [DPU PATCH v3 11/12] drm/msm/dpu: move dpu_power_handle to dpu folder Rajesh Yadav
2018-05-14 15:26 ` [DPU PATCH v3 12/12] drm/msm/dpu: add error handling in dpu_core_perf_crtc_update Rajesh Yadav
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1526311619-3309-4-git-send-email-ryadav@codeaurora.org \
--to=ryadav-sgv2jx0feol9jmxxk+q4oq@public.gmane.org \
--cc=dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
--cc=freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
--cc=hoegsberg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
--cc=linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=robdclark-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.