diff --git a/drivers/gpu/drm/msm/sde/sde_core_irq.c b/drivers/gpu/drm/msm/sde/sde_core_irq.c index b2853e874d92..dbfc2dd11a17 100644 --- a/drivers/gpu/drm/msm/sde/sde_core_irq.c +++ b/drivers/gpu/drm/msm/sde/sde_core_irq.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 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 @@ -432,6 +432,99 @@ void sde_core_irq_uninstall(struct sde_kms *sde_kms) sde_kms->irq_obj.total_irqs = 0; } +static void sde_hw_irq_mask(struct irq_data *irqd) +{ + struct sde_kms *sde_kms; + + if (!irqd || !irq_data_get_irq_chip_data(irqd)) { + SDE_ERROR("invalid parameters irqd %d\n", irqd != 0); + return; + } + sde_kms = irq_data_get_irq_chip_data(irqd); + + smp_mb__before_atomic(); + clear_bit(irqd->hwirq, &sde_kms->irq_controller.enabled_mask); + smp_mb__after_atomic(); +} + +static void sde_hw_irq_unmask(struct irq_data *irqd) +{ + struct sde_kms *sde_kms; + + if (!irqd || !irq_data_get_irq_chip_data(irqd)) { + SDE_ERROR("invalid parameters irqd %d\n", irqd != 0); + return; + } + sde_kms = irq_data_get_irq_chip_data(irqd); + + smp_mb__before_atomic(); + set_bit(irqd->hwirq, &sde_kms->irq_controller.enabled_mask); + smp_mb__after_atomic(); +} + +static struct irq_chip sde_hw_irq_chip = { + .name = "sde", + .irq_mask = sde_hw_irq_mask, + .irq_unmask = sde_hw_irq_unmask, +}; + +static int sde_hw_irqdomain_map(struct irq_domain *domain, + unsigned int irq, irq_hw_number_t hwirq) +{ + struct sde_kms *sde_kms; + int rc; + + if (!domain || !domain->host_data) { + SDE_ERROR("invalid parameters domain %d\n", domain != 0); + return -EINVAL; + } + sde_kms = domain->host_data; + + irq_set_chip_and_handler(irq, &sde_hw_irq_chip, handle_level_irq); + rc = irq_set_chip_data(irq, sde_kms); + + return rc; +} + +static struct irq_domain_ops sde_hw_irqdomain_ops = { + .map = sde_hw_irqdomain_map, + .xlate = irq_domain_xlate_onecell, +}; + +int sde_core_irq_domain_add(struct sde_kms *sde_kms) +{ + struct device *dev; + struct irq_domain *domain; + + if (!sde_kms->dev || !sde_kms->dev->dev) { + pr_err("invalid device handles\n"); + return -EINVAL; + } + + dev = sde_kms->dev->dev; + + domain = irq_domain_add_linear(dev->of_node, 32, + &sde_hw_irqdomain_ops, sde_kms); + if (!domain) { + pr_err("failed to add irq_domain\n"); + return -EINVAL; + } + + sde_kms->irq_controller.enabled_mask = 0; + sde_kms->irq_controller.domain = domain; + + return 0; +} + +int sde_core_irq_domain_fini(struct sde_kms *sde_kms) +{ + if (sde_kms->irq_controller.domain) { + irq_domain_remove(sde_kms->irq_controller.domain); + sde_kms->irq_controller.domain = NULL; + } + return 0; +} + irqreturn_t sde_core_irq(struct sde_kms *sde_kms) { /* diff --git a/drivers/gpu/drm/msm/sde/sde_core_irq.h b/drivers/gpu/drm/msm/sde/sde_core_irq.h index 92642e73daa8..ee1b9bd1d32b 100644 --- a/drivers/gpu/drm/msm/sde/sde_core_irq.h +++ b/drivers/gpu/drm/msm/sde/sde_core_irq.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 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 @@ -37,6 +37,20 @@ int sde_core_irq_postinstall(struct sde_kms *sde_kms); */ void sde_core_irq_uninstall(struct sde_kms *sde_kms); +/** + * sde_core_irq_domain_add - Add core IRQ domain for SDE + * @sde_kms: SDE handle + * @return: none + */ +int sde_core_irq_domain_add(struct sde_kms *sde_kms); + +/** + * sde_core_irq_domain_fini - uninstall core IRQ domain + * @sde_kms: SDE handle + * @return: 0 if success; error code otherwise + */ +int sde_core_irq_domain_fini(struct sde_kms *sde_kms); + /** * sde_core_irq - core IRQ handler * @sde_kms: SDE handle diff --git a/drivers/gpu/drm/msm/sde/sde_irq.c b/drivers/gpu/drm/msm/sde/sde_irq.c index 909d6df38260..eeb7a0002eab 100644 --- a/drivers/gpu/drm/msm/sde/sde_irq.c +++ b/drivers/gpu/drm/msm/sde/sde_irq.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 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 @@ -49,86 +49,14 @@ irqreturn_t sde_irq(struct msm_kms *kms) return IRQ_HANDLED; } -static void sde_hw_irq_mask(struct irq_data *irqd) -{ - struct sde_kms *sde_kms; - - if (!irqd || !irq_data_get_irq_chip_data(irqd)) { - SDE_ERROR("invalid parameters irqd %d\n", irqd != 0); - return; - } - sde_kms = irq_data_get_irq_chip_data(irqd); - - smp_mb__before_atomic(); - clear_bit(irqd->hwirq, &sde_kms->irq_controller.enabled_mask); - smp_mb__after_atomic(); -} - -static void sde_hw_irq_unmask(struct irq_data *irqd) -{ - struct sde_kms *sde_kms; - - if (!irqd || !irq_data_get_irq_chip_data(irqd)) { - SDE_ERROR("invalid parameters irqd %d\n", irqd != 0); - return; - } - sde_kms = irq_data_get_irq_chip_data(irqd); - - smp_mb__before_atomic(); - set_bit(irqd->hwirq, &sde_kms->irq_controller.enabled_mask); - smp_mb__after_atomic(); -} - -static struct irq_chip sde_hw_irq_chip = { - .name = "sde", - .irq_mask = sde_hw_irq_mask, - .irq_unmask = sde_hw_irq_unmask, -}; - -static int sde_hw_irqdomain_map(struct irq_domain *domain, - unsigned int irq, irq_hw_number_t hwirq) -{ - struct sde_kms *sde_kms; - int rc; - - if (!domain || !domain->host_data) { - SDE_ERROR("invalid parameters domain %d\n", domain != 0); - return -EINVAL; - } - sde_kms = domain->host_data; - - irq_set_chip_and_handler(irq, &sde_hw_irq_chip, handle_level_irq); - rc = irq_set_chip_data(irq, sde_kms); - - return rc; -} - -static struct irq_domain_ops sde_hw_irqdomain_ops = { - .map = sde_hw_irqdomain_map, - .xlate = irq_domain_xlate_onecell, -}; - void sde_irq_preinstall(struct msm_kms *kms) { struct sde_kms *sde_kms = to_sde_kms(kms); - struct device *dev; - struct irq_domain *domain; if (!sde_kms->dev || !sde_kms->dev->dev) { pr_err("invalid device handles\n"); return; } - dev = sde_kms->dev->dev; - - domain = irq_domain_add_linear(dev->of_node, 32, - &sde_hw_irqdomain_ops, sde_kms); - if (!domain) { - pr_err("failed to add irq_domain\n"); - return; - } - - sde_kms->irq_controller.enabled_mask = 0; - sde_kms->irq_controller.domain = domain; sde_core_irq_preinstall(sde_kms); } @@ -158,9 +86,5 @@ void sde_irq_uninstall(struct msm_kms *kms) } sde_core_irq_uninstall(sde_kms); - - if (sde_kms->irq_controller.domain) { - irq_domain_remove(sde_kms->irq_controller.domain); - sde_kms->irq_controller.domain = NULL; - } + sde_core_irq_domain_fini(sde_kms); } diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 5556ef9bd2c4..ebf618635cfb 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -811,6 +811,9 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms) priv = dev->dev_private; catalog = sde_kms->catalog; + ret = sde_core_irq_domain_add(sde_kms); + if (ret) + goto fail_irq; /* * Query for underlying display drivers, and create connectors, * bridges and encoders for them. @@ -869,6 +872,8 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms) return 0; fail: _sde_kms_drm_obj_destroy(sde_kms); +fail_irq: + sde_core_irq_domain_fini(sde_kms); return ret; } @@ -1219,6 +1224,14 @@ static int sde_kms_hw_init(struct msm_kms *kms) goto perf_err; } + sde_kms->hw_intr = sde_hw_intr_init(sde_kms->mmio, sde_kms->catalog); + if (IS_ERR_OR_NULL(sde_kms->hw_intr)) { + rc = PTR_ERR(sde_kms->hw_intr); + SDE_ERROR("hw_intr init failed: %d\n", rc); + sde_kms->hw_intr = NULL; + goto hw_intr_init_err; + } + /* * _sde_kms_drm_obj_init should create the DRM related objects * i.e. CRTCs, planes, encoders, connectors and so forth @@ -1244,21 +1257,12 @@ static int sde_kms_hw_init(struct msm_kms *kms) */ dev->mode_config.allow_fb_modifiers = true; - sde_kms->hw_intr = sde_hw_intr_init(sde_kms->mmio, sde_kms->catalog); - if (IS_ERR_OR_NULL(sde_kms->hw_intr)) { - rc = PTR_ERR(sde_kms->hw_intr); - SDE_ERROR("hw_intr init failed: %d\n", rc); - sde_kms->hw_intr = NULL; - goto hw_intr_init_err; - } - sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false); return 0; -hw_intr_init_err: - _sde_kms_drm_obj_destroy(sde_kms); drm_obj_init_err: sde_core_perf_destroy(&sde_kms->perf); +hw_intr_init_err: perf_err: power_error: sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);