On Fri, May 11, 2018 at 08:19:29PM +0530, Rajesh Yadav wrote:
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 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
Reviewed-by: Jordan Crouse jcrouse@codeaurora.org
I know you'll get a hundred different opinions from a hundred different people but you don't need to credit me for every change - just a single line "fixed bugs" works for me.
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_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 | 254 ++++++++++++++++++++++ drivers/gpu/drm/msm/dpu_io_util.c | 57 +++++ 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 + 16 files changed, 339 insertions(+), 226 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_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),
.mdp_count = ARRAY_SIZE(sdm845_mdp), .mdp = sdm845_mdp, .ctl_count = ARRAY_SIZE(sdm845_ctl),.mdss = sdm845_mdss,
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..ce680ea --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -0,0 +1,254 @@ +/*
- 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)) {
ret = PTR_ERR(dpu_mdss->mmio);
DPU_ERROR("mdss register memory map failed: %d\n", ret);
dpu_mdss->mmio = NULL;
return ret;
- }
- 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..c44f33f 100644 --- a/drivers/gpu/drm/msm/dpu_io_util.c +++ b/drivers/gpu/drm/msm/dpu_io_util.c @@ -448,6 +448,63 @@ 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, max_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));
rc = of_property_read_u32_index(pdev->dev.of_node,
"clock-rate", i,
&rate);
if (rc)
break;
mp->clk_config[i].rate = rate;
if (!mp->clk_config[i].rate)
mp->clk_config[i].type = DSS_CLK_AHB;
else
mp->clk_config[i].type = DSS_CLK_PCLK;
rc = of_property_read_u32_index(pdev->dev.of_node,
"clock-max-rate", i,
&max_rate);
if (rc)
break;
mp->clk_config[i].max_rate = max_rate;
- }
- 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") ||
ret = of_platform_populate(dev->of_node, NULL, NULL, dev); if (ret) { dev_err(dev, "failed to populate children devices\n");of_device_is_compatible(dev->of_node, "qcom,dpu-mdss")) {
@@ -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