From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4304CA9ED0 for ; Fri, 1 Nov 2019 06:28:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 97EE5208E3 for ; Fri, 1 Nov 2019 06:28:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="itR0zejM"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="RoS3+f6S" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730077AbfKAG23 (ORCPT ); Fri, 1 Nov 2019 02:28:29 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:46662 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726609AbfKAG22 (ORCPT ); Fri, 1 Nov 2019 02:28:28 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 51D2960F94; Fri, 1 Nov 2019 06:28:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589707; bh=jbbKzMNuIKsCrSVBFloO4+6mFPMvXOegRo7cqvecICQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=itR0zejM6I132eKRiqxjPEFpFMAFUdV2q5YNP0aTPikCWeoL7G/xyRNBHygRyb8IA JiNLi9wuKMvSUsNVpYq7KoNQS3jrpikZgaRas2iaLFCZoP3LAw9RXQeT+8hdWBs3Ik 2EYYXhx3Ktg76uo8f/FIcotyGsTefw734REAfkEQ= Received: from kgunda-linux.qualcomm.com (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: kgunda@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 6769860F74; Fri, 1 Nov 2019 06:28:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589704; bh=jbbKzMNuIKsCrSVBFloO4+6mFPMvXOegRo7cqvecICQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RoS3+f6SQxZ/5SMMMjP0gY4vFWeYLedHhyccHBP6WPtxqO7rbkrF1KvV+jjcUTvyw zaDBxN5Exm3zIz/RFHZphpvF2di9rN3uePXxdThhQpa5Nks1wReux8ggABJmqYSQ5n /Jn1h8xwX9n6jm25Ef069jOLLW/HnUHGPm7n3StA= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 6769860F74 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=kgunda@codeaurora.org From: Kiran Gunda To: bjorn.andersson@linaro.org, jingoohan1@gmail.com, lee.jones@linaro.org, b.zolnierkie@samsung.com, dri-devel@lists.freedesktop.org, daniel.thompson@linaro.org, jacek.anaszewski@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, mark.rutland@arm.com, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Gross , linux-arm-msm@vger.kernel.org, linux-fbdev@vger.kernel.org Cc: Kiran Gunda Subject: [PATCH V10 8/8] backlight: qcom-wled: Add auto string detection logic Date: Fri, 1 Nov 2019 11:57:04 +0530 Message-Id: <1572589624-6095-9-git-send-email-kgunda@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1572589624-6095-1-git-send-email-kgunda@codeaurora.org> References: <1572589624-6095-1-git-send-email-kgunda@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org The auto string detection algorithm checks if the current WLED sink configuration is valid. It tries enabling every sink and checks if the OVP fault is observed. Based on this information it detects and enables the valid sink configuration. Auto calibration will be triggered when the OVP fault interrupts are seen frequently thereby it tries to fix the sink configuration. The auto-detection also kicks in when the connected LED string of the display-backlight malfunctions (because of damage) and requires the damaged string to be turned off to prevent the complete panel and/or board from being damaged. Signed-off-by: Kiran Gunda Reviewed-by: Daniel Thompson --- drivers/video/backlight/qcom-wled.c | 400 +++++++++++++++++++++++++++++++++++- 1 file changed, 394 insertions(+), 6 deletions(-) diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 658b1e0..33b6007 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -17,19 +17,29 @@ #define WLED_MAX_STRINGS 4 #define WLED_DEFAULT_BRIGHTNESS 2048 - +#define WLED_SOFT_START_DLY_US 10000 #define WLED3_SINK_REG_BRIGHT_MAX 0xFFF /* WLED3/WLED4 control registers */ +#define WLED3_CTRL_REG_FAULT_STATUS 0x08 +#define WLED3_CTRL_REG_ILIM_FAULT_BIT BIT(0) +#define WLED3_CTRL_REG_OVP_FAULT_BIT BIT(1) +#define WLED4_CTRL_REG_SC_FAULT_BIT BIT(2) + +#define WLED3_CTRL_REG_INT_RT_STS 0x10 +#define WLED3_CTRL_REG_OVP_FAULT_STATUS BIT(1) + #define WLED3_CTRL_REG_MOD_EN 0x46 #define WLED3_CTRL_REG_MOD_EN_MASK BIT(7) #define WLED3_CTRL_REG_MOD_EN_SHIFT 7 +#define WLED3_CTRL_REG_FEEDBACK_CONTROL 0x48 + #define WLED3_CTRL_REG_FREQ 0x4c #define WLED3_CTRL_REG_FREQ_MASK GENMASK(3, 0) #define WLED3_CTRL_REG_OVP 0x4d -#define WLED3_CTRL_REG_OVP_MASK GENMASK(1, 0) +#define WLED3_CTRL_REG_OVP_MASK GENMASK(1, 0) #define WLED3_CTRL_REG_ILIMIT 0x4e #define WLED3_CTRL_REG_ILIMIT_MASK GENMASK(2, 0) @@ -119,6 +129,7 @@ struct wled_config { bool ext_gen; bool cabc; bool external_pfet; + bool auto_detection_enabled; }; struct wled { @@ -127,17 +138,22 @@ struct wled { struct regmap *regmap; struct mutex lock; /* Lock to avoid race from thread irq handler */ ktime_t last_short_event; + ktime_t start_ovp_fault_time; u16 ctrl_addr; u16 sink_addr; u16 max_string_count; + u16 auto_detection_ovp_count; u32 brightness; u32 max_brightness; u32 short_count; + u32 auto_detect_count; bool disabled_by_short; bool has_short_detect; int short_irq; + int ovp_irq; struct wled_config cfg; + struct delayed_work ovp_work; int (*wled_set_brightness)(struct wled *wled, u16 brightness); }; @@ -182,6 +198,13 @@ static int wled4_set_brightness(struct wled *wled, u16 brightness) return 0; } +static void wled_ovp_work(struct work_struct *work) +{ + struct wled *wled = container_of(work, + struct wled, ovp_work.work); + enable_irq(wled->ovp_irq); +} + static int wled_module_enable(struct wled *wled, int val) { int rc; @@ -193,7 +216,25 @@ static int wled_module_enable(struct wled *wled, int val) WLED3_CTRL_REG_MOD_EN, WLED3_CTRL_REG_MOD_EN_MASK, val << WLED3_CTRL_REG_MOD_EN_SHIFT); - return rc; + if (rc < 0) + return rc; + + if (wled->ovp_irq > 0) { + if (val) { + /* + * The hardware generates a storm of spurious OVP + * interrupts during soft start operations. So defer + * enabling the IRQ for 10ms to ensure that the + * soft start is complete. + */ + schedule_delayed_work(&wled->ovp_work, HZ / 100); + } else { + if (!cancel_delayed_work_sync(&wled->ovp_work)) + disable_irq(wled->ovp_irq); + } + } + + return 0; } static int wled_sync_toggle(struct wled *wled) @@ -300,6 +341,304 @@ static irqreturn_t wled_short_irq_handler(int irq, void *_wled) return IRQ_HANDLED; } +#define AUTO_DETECT_BRIGHTNESS 200 + +static void wled_auto_string_detection(struct wled *wled) +{ + int rc = 0, i; + u32 sink_config = 0, int_sts; + u8 sink_test = 0, sink_valid = 0, val; + + /* Read configured sink configuration */ + rc = regmap_read(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_CURR_SINK, &sink_config); + if (rc < 0) { + dev_err(wled->dev, "Failed to read SINK configuration rc=%d\n", + rc); + goto failed_detect; + } + + /* Disable the module before starting detection */ + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, 0); + if (rc < 0) { + dev_err(wled->dev, "Failed to disable WLED module rc=%d\n", rc); + goto failed_detect; + } + + /* Set low brightness across all sinks */ + rc = wled4_set_brightness(wled, AUTO_DETECT_BRIGHTNESS); + if (rc < 0) { + dev_err(wled->dev, "Failed to set brightness for auto detection rc=%d\n", + rc); + goto failed_detect; + } + + if (wled->cfg.cabc) { + for (i = 0; i < wled->cfg.num_strings; i++) { + rc = regmap_update_bits(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_STR_CABC(i), + WLED4_SINK_REG_STR_CABC_MASK, + 0); + if (rc < 0) + goto failed_detect; + } + } + + /* Disable all sinks */ + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 0); + if (rc < 0) { + dev_err(wled->dev, "Failed to disable all sinks rc=%d\n", rc); + goto failed_detect; + } + + /* Iterate through the strings one by one */ + for (i = 0; i < wled->cfg.num_strings; i++) { + sink_test = BIT((WLED4_SINK_REG_CURR_SINK_SHFT + i)); + + /* Enable feedback control */ + rc = regmap_write(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_FEEDBACK_CONTROL, i + 1); + if (rc < 0) { + dev_err(wled->dev, "Failed to enable feedback for SINK %d rc = %d\n", + i + 1, rc); + goto failed_detect; + } + + /* Enable the sink */ + rc = regmap_write(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_CURR_SINK, sink_test); + if (rc < 0) { + dev_err(wled->dev, "Failed to configure SINK %d rc=%d\n", + i + 1, rc); + goto failed_detect; + } + + /* Enable the module */ + rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, + WLED3_CTRL_REG_MOD_EN_MASK); + if (rc < 0) { + dev_err(wled->dev, "Failed to enable WLED module rc=%d\n", + rc); + goto failed_detect; + } + + usleep_range(WLED_SOFT_START_DLY_US, + WLED_SOFT_START_DLY_US + 1000); + + rc = regmap_read(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_INT_RT_STS, &int_sts); + if (rc < 0) { + dev_err(wled->dev, "Error in reading WLED3_CTRL_INT_RT_STS rc=%d\n", + rc); + goto failed_detect; + } + + if (int_sts & WLED3_CTRL_REG_OVP_FAULT_STATUS) + dev_dbg(wled->dev, "WLED OVP fault detected with SINK %d\n", + i + 1); + else + sink_valid |= sink_test; + + /* Disable the module */ + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, 0); + if (rc < 0) { + dev_err(wled->dev, "Failed to disable WLED module rc=%d\n", + rc); + goto failed_detect; + } + } + + if (!sink_valid) { + dev_err(wled->dev, "No valid WLED sinks found\n"); + wled->disabled_by_short = true; + goto failed_detect; + } + + if (sink_valid != sink_config) { + dev_warn(wled->dev, "%x is not a valid sink configuration - using %x instead\n", + sink_config, sink_valid); + sink_config = sink_valid; + } + + /* Write the new sink configuration */ + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED4_SINK_REG_CURR_SINK, + sink_config); + if (rc < 0) { + dev_err(wled->dev, "Failed to reconfigure the default sink rc=%d\n", + rc); + goto failed_detect; + } + + /* Enable valid sinks */ + for (i = 0; i < wled->cfg.num_strings; i++) { + if (wled->cfg.cabc) { + rc = regmap_update_bits(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_STR_CABC(i), + WLED4_SINK_REG_STR_CABC_MASK, + WLED4_SINK_REG_STR_CABC_MASK); + if (rc < 0) + goto failed_detect; + } + + if (sink_config & BIT(WLED4_SINK_REG_CURR_SINK_SHFT + i)) + val = WLED4_SINK_REG_STR_MOD_MASK; + else + val = 0x0; /* Disable modulator_en for unused sink */ + + rc = regmap_write(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_STR_MOD_EN(i), val); + if (rc < 0) { + dev_err(wled->dev, "Failed to configure MODULATOR_EN rc=%d\n", + rc); + goto failed_detect; + } + } + + /* Restore the feedback setting */ + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_FEEDBACK_CONTROL, 0); + if (rc < 0) { + dev_err(wled->dev, "Failed to restore feedback setting rc=%d\n", + rc); + goto failed_detect; + } + + /* Restore brightness */ + rc = wled4_set_brightness(wled, wled->brightness); + if (rc < 0) { + dev_err(wled->dev, "Failed to set brightness after auto detection rc=%d\n", + rc); + goto failed_detect; + } + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, + WLED3_CTRL_REG_MOD_EN_MASK); + if (rc < 0) { + dev_err(wled->dev, "Failed to enable WLED module rc=%d\n", rc); + goto failed_detect; + } + +failed_detect: + return; +} + +#define WLED_AUTO_DETECT_OVP_COUNT 5 +#define WLED_AUTO_DETECT_CNT_DLY_US USEC_PER_SEC +static bool wled_auto_detection_required(struct wled *wled) +{ + s64 elapsed_time_us; + + if (!wled->cfg.auto_detection_enabled) + return false; + + /* + * Check if the OVP fault was an occasional one + * or if it's firing continuously, the latter qualifies + * for an auto-detection check. + */ + if (!wled->auto_detection_ovp_count) { + wled->start_ovp_fault_time = ktime_get(); + wled->auto_detection_ovp_count++; + } else { + elapsed_time_us = ktime_us_delta(ktime_get(), + wled->start_ovp_fault_time); + if (elapsed_time_us > WLED_AUTO_DETECT_CNT_DLY_US) + wled->auto_detection_ovp_count = 0; + else + wled->auto_detection_ovp_count++; + + if (wled->auto_detection_ovp_count >= + WLED_AUTO_DETECT_OVP_COUNT) { + wled->auto_detection_ovp_count = 0; + return true; + } + } + + return false; +} + +static int wled_auto_detection_at_init(struct wled *wled) +{ + int rc; + u32 fault_status, rt_status; + + if (!wled->cfg.auto_detection_enabled) + return 0; + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS, + &rt_status); + if (rc < 0) { + dev_err(wled->dev, "Failed to read RT status rc=%d\n", rc); + return rc; + } + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_FAULT_STATUS, + &fault_status); + if (rc < 0) { + dev_err(wled->dev, "Failed to read fault status rc=%d\n", rc); + return rc; + } + + if ((rt_status & WLED3_CTRL_REG_OVP_FAULT_STATUS) || + (fault_status & WLED3_CTRL_REG_OVP_FAULT_BIT)) { + mutex_lock(&wled->lock); + wled_auto_string_detection(wled); + mutex_unlock(&wled->lock); + } + + return rc; +} + +static irqreturn_t wled_ovp_irq_handler(int irq, void *_wled) +{ + struct wled *wled = _wled; + int rc; + u32 int_sts, fault_sts; + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS, &int_sts); + if (rc < 0) { + dev_err(wled->dev, "Error in reading WLED3_INT_RT_STS rc=%d\n", + rc); + return IRQ_HANDLED; + } + + rc = regmap_read(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_FAULT_STATUS, &fault_sts); + if (rc < 0) { + dev_err(wled->dev, "Error in reading WLED_FAULT_STATUS rc=%d\n", + rc); + return IRQ_HANDLED; + } + + if (fault_sts & (WLED3_CTRL_REG_OVP_FAULT_BIT | + WLED3_CTRL_REG_ILIM_FAULT_BIT)) + dev_dbg(wled->dev, "WLED OVP fault detected, int_sts=%x fault_sts= %x\n", + int_sts, fault_sts); + + if (fault_sts & WLED3_CTRL_REG_OVP_FAULT_BIT) { + if (wled_auto_detection_required(wled)) { + mutex_lock(&wled->lock); + wled_auto_string_detection(wled); + mutex_unlock(&wled->lock); + } + } + + return IRQ_HANDLED; +} + static int wled3_setup(struct wled *wled) { u16 addr; @@ -436,8 +775,10 @@ static int wled4_setup(struct wled *wled) sink_en |= 1 << temp; } - if (sink_cfg == sink_en) - return 0; + if (sink_cfg == sink_en) { + rc = wled_auto_detection_at_init(wled); + return rc; + } rc = regmap_update_bits(wled->regmap, wled->sink_addr + WLED4_SINK_REG_CURR_SINK, @@ -500,7 +841,9 @@ static int wled4_setup(struct wled *wled) return rc; } - return 0; + rc = wled_auto_detection_at_init(wled); + + return rc; } static const struct wled_config wled4_config_defaults = { @@ -511,6 +854,7 @@ static int wled4_setup(struct wled *wled) .switch_freq = 11, .cabc = false, .external_pfet = false, + .auto_detection_enabled = false, }; static const u32 wled3_boost_i_limit_values[] = { @@ -677,6 +1021,7 @@ static int wled_configure(struct wled *wled, int version) { "qcom,ext-gen", &cfg->ext_gen, }, { "qcom,cabc", &cfg->cabc, }, { "qcom,external-pfet", &cfg->external_pfet, }, + { "qcom,auto-string-detection", &cfg->auto_detection_enabled, }, }; prop_addr = of_get_address(dev->of_node, 0, NULL, NULL); @@ -797,6 +1142,40 @@ static int wled_configure_short_irq(struct wled *wled, return rc; } +static int wled_configure_ovp_irq(struct wled *wled, + struct platform_device *pdev) +{ + int rc; + u32 val; + + wled->ovp_irq = platform_get_irq_byname(pdev, "ovp"); + if (wled->ovp_irq < 0) { + dev_dbg(&pdev->dev, "OVP IRQ not found - disabling automatic string detection\n"); + return 0; + } + + rc = devm_request_threaded_irq(wled->dev, wled->ovp_irq, NULL, + wled_ovp_irq_handler, IRQF_ONESHOT, + "wled_ovp_irq", wled); + if (rc < 0) { + dev_err(wled->dev, "Unable to request ovp_irq (err:%d)\n", + rc); + wled->ovp_irq = 0; + return 0; + } + + rc = regmap_read(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_MOD_EN, &val); + if (rc < 0) + return rc; + + /* Keep OVP irq disabled until module is enabled */ + if (!(val & WLED3_CTRL_REG_MOD_EN_MASK)) + disable_irq(wled->ovp_irq); + + return 0; +} + static const struct backlight_ops wled_ops = { .update_status = wled_update_status, }; @@ -837,6 +1216,7 @@ static int wled_probe(struct platform_device *pdev) switch (version) { case 3: + wled->cfg.auto_detection_enabled = false; rc = wled3_setup(wled); if (rc) { dev_err(&pdev->dev, "wled3_setup failed\n"); @@ -858,10 +1238,16 @@ static int wled_probe(struct platform_device *pdev) break; } + INIT_DELAYED_WORK(&wled->ovp_work, wled_ovp_work); + rc = wled_configure_short_irq(wled, pdev); if (rc < 0) return rc; + rc = wled_configure_ovp_irq(wled, pdev); + if (rc < 0) + return rc; + val = WLED_DEFAULT_BRIGHTNESS; of_property_read_u32(pdev->dev.of_node, "default-brightness", &val); @@ -880,7 +1266,9 @@ static int wled_remove(struct platform_device *pdev) struct wled *wled = dev_get_drvdata(&pdev->dev); mutex_destroy(&wled->lock); + cancel_delayed_work_sync(&wled->ovp_work); disable_irq(wled->short_irq); + disable_irq(wled->ovp_irq); return 0; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kiran Gunda Date: Fri, 01 Nov 2019 06:39:04 +0000 Subject: [PATCH V10 8/8] backlight: qcom-wled: Add auto string detection logic Message-Id: <1572589624-6095-9-git-send-email-kgunda@codeaurora.org> List-Id: References: <1572589624-6095-1-git-send-email-kgunda@codeaurora.org> In-Reply-To: <1572589624-6095-1-git-send-email-kgunda@codeaurora.org> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: bjorn.andersson@linaro.org, jingoohan1@gmail.com, lee.jones@linaro.org, b.zolnierkie@samsung.com, dri-devel@lists.freedesktop.org, daniel.thompson@linaro.org, jacek.anaszewski@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, mark.rutland@arm.com, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Gross , linux-arm-msm@vger.kernel.org, linux-fbdev@vger.kernel.org Cc: Kiran Gunda The auto string detection algorithm checks if the current WLED sink configuration is valid. It tries enabling every sink and checks if the OVP fault is observed. Based on this information it detects and enables the valid sink configuration. Auto calibration will be triggered when the OVP fault interrupts are seen frequently thereby it tries to fix the sink configuration. The auto-detection also kicks in when the connected LED string of the display-backlight malfunctions (because of damage) and requires the damaged string to be turned off to prevent the complete panel and/or board from being damaged. Signed-off-by: Kiran Gunda Reviewed-by: Daniel Thompson --- drivers/video/backlight/qcom-wled.c | 400 +++++++++++++++++++++++++++++++++++- 1 file changed, 394 insertions(+), 6 deletions(-) diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 658b1e0..33b6007 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -17,19 +17,29 @@ #define WLED_MAX_STRINGS 4 #define WLED_DEFAULT_BRIGHTNESS 2048 - +#define WLED_SOFT_START_DLY_US 10000 #define WLED3_SINK_REG_BRIGHT_MAX 0xFFF /* WLED3/WLED4 control registers */ +#define WLED3_CTRL_REG_FAULT_STATUS 0x08 +#define WLED3_CTRL_REG_ILIM_FAULT_BIT BIT(0) +#define WLED3_CTRL_REG_OVP_FAULT_BIT BIT(1) +#define WLED4_CTRL_REG_SC_FAULT_BIT BIT(2) + +#define WLED3_CTRL_REG_INT_RT_STS 0x10 +#define WLED3_CTRL_REG_OVP_FAULT_STATUS BIT(1) + #define WLED3_CTRL_REG_MOD_EN 0x46 #define WLED3_CTRL_REG_MOD_EN_MASK BIT(7) #define WLED3_CTRL_REG_MOD_EN_SHIFT 7 +#define WLED3_CTRL_REG_FEEDBACK_CONTROL 0x48 + #define WLED3_CTRL_REG_FREQ 0x4c #define WLED3_CTRL_REG_FREQ_MASK GENMASK(3, 0) #define WLED3_CTRL_REG_OVP 0x4d -#define WLED3_CTRL_REG_OVP_MASK GENMASK(1, 0) +#define WLED3_CTRL_REG_OVP_MASK GENMASK(1, 0) #define WLED3_CTRL_REG_ILIMIT 0x4e #define WLED3_CTRL_REG_ILIMIT_MASK GENMASK(2, 0) @@ -119,6 +129,7 @@ struct wled_config { bool ext_gen; bool cabc; bool external_pfet; + bool auto_detection_enabled; }; struct wled { @@ -127,17 +138,22 @@ struct wled { struct regmap *regmap; struct mutex lock; /* Lock to avoid race from thread irq handler */ ktime_t last_short_event; + ktime_t start_ovp_fault_time; u16 ctrl_addr; u16 sink_addr; u16 max_string_count; + u16 auto_detection_ovp_count; u32 brightness; u32 max_brightness; u32 short_count; + u32 auto_detect_count; bool disabled_by_short; bool has_short_detect; int short_irq; + int ovp_irq; struct wled_config cfg; + struct delayed_work ovp_work; int (*wled_set_brightness)(struct wled *wled, u16 brightness); }; @@ -182,6 +198,13 @@ static int wled4_set_brightness(struct wled *wled, u16 brightness) return 0; } +static void wled_ovp_work(struct work_struct *work) +{ + struct wled *wled = container_of(work, + struct wled, ovp_work.work); + enable_irq(wled->ovp_irq); +} + static int wled_module_enable(struct wled *wled, int val) { int rc; @@ -193,7 +216,25 @@ static int wled_module_enable(struct wled *wled, int val) WLED3_CTRL_REG_MOD_EN, WLED3_CTRL_REG_MOD_EN_MASK, val << WLED3_CTRL_REG_MOD_EN_SHIFT); - return rc; + if (rc < 0) + return rc; + + if (wled->ovp_irq > 0) { + if (val) { + /* + * The hardware generates a storm of spurious OVP + * interrupts during soft start operations. So defer + * enabling the IRQ for 10ms to ensure that the + * soft start is complete. + */ + schedule_delayed_work(&wled->ovp_work, HZ / 100); + } else { + if (!cancel_delayed_work_sync(&wled->ovp_work)) + disable_irq(wled->ovp_irq); + } + } + + return 0; } static int wled_sync_toggle(struct wled *wled) @@ -300,6 +341,304 @@ static irqreturn_t wled_short_irq_handler(int irq, void *_wled) return IRQ_HANDLED; } +#define AUTO_DETECT_BRIGHTNESS 200 + +static void wled_auto_string_detection(struct wled *wled) +{ + int rc = 0, i; + u32 sink_config = 0, int_sts; + u8 sink_test = 0, sink_valid = 0, val; + + /* Read configured sink configuration */ + rc = regmap_read(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_CURR_SINK, &sink_config); + if (rc < 0) { + dev_err(wled->dev, "Failed to read SINK configuration rc=%d\n", + rc); + goto failed_detect; + } + + /* Disable the module before starting detection */ + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, 0); + if (rc < 0) { + dev_err(wled->dev, "Failed to disable WLED module rc=%d\n", rc); + goto failed_detect; + } + + /* Set low brightness across all sinks */ + rc = wled4_set_brightness(wled, AUTO_DETECT_BRIGHTNESS); + if (rc < 0) { + dev_err(wled->dev, "Failed to set brightness for auto detection rc=%d\n", + rc); + goto failed_detect; + } + + if (wled->cfg.cabc) { + for (i = 0; i < wled->cfg.num_strings; i++) { + rc = regmap_update_bits(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_STR_CABC(i), + WLED4_SINK_REG_STR_CABC_MASK, + 0); + if (rc < 0) + goto failed_detect; + } + } + + /* Disable all sinks */ + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 0); + if (rc < 0) { + dev_err(wled->dev, "Failed to disable all sinks rc=%d\n", rc); + goto failed_detect; + } + + /* Iterate through the strings one by one */ + for (i = 0; i < wled->cfg.num_strings; i++) { + sink_test = BIT((WLED4_SINK_REG_CURR_SINK_SHFT + i)); + + /* Enable feedback control */ + rc = regmap_write(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_FEEDBACK_CONTROL, i + 1); + if (rc < 0) { + dev_err(wled->dev, "Failed to enable feedback for SINK %d rc = %d\n", + i + 1, rc); + goto failed_detect; + } + + /* Enable the sink */ + rc = regmap_write(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_CURR_SINK, sink_test); + if (rc < 0) { + dev_err(wled->dev, "Failed to configure SINK %d rc=%d\n", + i + 1, rc); + goto failed_detect; + } + + /* Enable the module */ + rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, + WLED3_CTRL_REG_MOD_EN_MASK); + if (rc < 0) { + dev_err(wled->dev, "Failed to enable WLED module rc=%d\n", + rc); + goto failed_detect; + } + + usleep_range(WLED_SOFT_START_DLY_US, + WLED_SOFT_START_DLY_US + 1000); + + rc = regmap_read(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_INT_RT_STS, &int_sts); + if (rc < 0) { + dev_err(wled->dev, "Error in reading WLED3_CTRL_INT_RT_STS rc=%d\n", + rc); + goto failed_detect; + } + + if (int_sts & WLED3_CTRL_REG_OVP_FAULT_STATUS) + dev_dbg(wled->dev, "WLED OVP fault detected with SINK %d\n", + i + 1); + else + sink_valid |= sink_test; + + /* Disable the module */ + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, 0); + if (rc < 0) { + dev_err(wled->dev, "Failed to disable WLED module rc=%d\n", + rc); + goto failed_detect; + } + } + + if (!sink_valid) { + dev_err(wled->dev, "No valid WLED sinks found\n"); + wled->disabled_by_short = true; + goto failed_detect; + } + + if (sink_valid != sink_config) { + dev_warn(wled->dev, "%x is not a valid sink configuration - using %x instead\n", + sink_config, sink_valid); + sink_config = sink_valid; + } + + /* Write the new sink configuration */ + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED4_SINK_REG_CURR_SINK, + sink_config); + if (rc < 0) { + dev_err(wled->dev, "Failed to reconfigure the default sink rc=%d\n", + rc); + goto failed_detect; + } + + /* Enable valid sinks */ + for (i = 0; i < wled->cfg.num_strings; i++) { + if (wled->cfg.cabc) { + rc = regmap_update_bits(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_STR_CABC(i), + WLED4_SINK_REG_STR_CABC_MASK, + WLED4_SINK_REG_STR_CABC_MASK); + if (rc < 0) + goto failed_detect; + } + + if (sink_config & BIT(WLED4_SINK_REG_CURR_SINK_SHFT + i)) + val = WLED4_SINK_REG_STR_MOD_MASK; + else + val = 0x0; /* Disable modulator_en for unused sink */ + + rc = regmap_write(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_STR_MOD_EN(i), val); + if (rc < 0) { + dev_err(wled->dev, "Failed to configure MODULATOR_EN rc=%d\n", + rc); + goto failed_detect; + } + } + + /* Restore the feedback setting */ + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_FEEDBACK_CONTROL, 0); + if (rc < 0) { + dev_err(wled->dev, "Failed to restore feedback setting rc=%d\n", + rc); + goto failed_detect; + } + + /* Restore brightness */ + rc = wled4_set_brightness(wled, wled->brightness); + if (rc < 0) { + dev_err(wled->dev, "Failed to set brightness after auto detection rc=%d\n", + rc); + goto failed_detect; + } + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, + WLED3_CTRL_REG_MOD_EN_MASK); + if (rc < 0) { + dev_err(wled->dev, "Failed to enable WLED module rc=%d\n", rc); + goto failed_detect; + } + +failed_detect: + return; +} + +#define WLED_AUTO_DETECT_OVP_COUNT 5 +#define WLED_AUTO_DETECT_CNT_DLY_US USEC_PER_SEC +static bool wled_auto_detection_required(struct wled *wled) +{ + s64 elapsed_time_us; + + if (!wled->cfg.auto_detection_enabled) + return false; + + /* + * Check if the OVP fault was an occasional one + * or if it's firing continuously, the latter qualifies + * for an auto-detection check. + */ + if (!wled->auto_detection_ovp_count) { + wled->start_ovp_fault_time = ktime_get(); + wled->auto_detection_ovp_count++; + } else { + elapsed_time_us = ktime_us_delta(ktime_get(), + wled->start_ovp_fault_time); + if (elapsed_time_us > WLED_AUTO_DETECT_CNT_DLY_US) + wled->auto_detection_ovp_count = 0; + else + wled->auto_detection_ovp_count++; + + if (wled->auto_detection_ovp_count >+ WLED_AUTO_DETECT_OVP_COUNT) { + wled->auto_detection_ovp_count = 0; + return true; + } + } + + return false; +} + +static int wled_auto_detection_at_init(struct wled *wled) +{ + int rc; + u32 fault_status, rt_status; + + if (!wled->cfg.auto_detection_enabled) + return 0; + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS, + &rt_status); + if (rc < 0) { + dev_err(wled->dev, "Failed to read RT status rc=%d\n", rc); + return rc; + } + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_FAULT_STATUS, + &fault_status); + if (rc < 0) { + dev_err(wled->dev, "Failed to read fault status rc=%d\n", rc); + return rc; + } + + if ((rt_status & WLED3_CTRL_REG_OVP_FAULT_STATUS) || + (fault_status & WLED3_CTRL_REG_OVP_FAULT_BIT)) { + mutex_lock(&wled->lock); + wled_auto_string_detection(wled); + mutex_unlock(&wled->lock); + } + + return rc; +} + +static irqreturn_t wled_ovp_irq_handler(int irq, void *_wled) +{ + struct wled *wled = _wled; + int rc; + u32 int_sts, fault_sts; + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS, &int_sts); + if (rc < 0) { + dev_err(wled->dev, "Error in reading WLED3_INT_RT_STS rc=%d\n", + rc); + return IRQ_HANDLED; + } + + rc = regmap_read(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_FAULT_STATUS, &fault_sts); + if (rc < 0) { + dev_err(wled->dev, "Error in reading WLED_FAULT_STATUS rc=%d\n", + rc); + return IRQ_HANDLED; + } + + if (fault_sts & (WLED3_CTRL_REG_OVP_FAULT_BIT | + WLED3_CTRL_REG_ILIM_FAULT_BIT)) + dev_dbg(wled->dev, "WLED OVP fault detected, int_sts=%x fault_sts= %x\n", + int_sts, fault_sts); + + if (fault_sts & WLED3_CTRL_REG_OVP_FAULT_BIT) { + if (wled_auto_detection_required(wled)) { + mutex_lock(&wled->lock); + wled_auto_string_detection(wled); + mutex_unlock(&wled->lock); + } + } + + return IRQ_HANDLED; +} + static int wled3_setup(struct wled *wled) { u16 addr; @@ -436,8 +775,10 @@ static int wled4_setup(struct wled *wled) sink_en |= 1 << temp; } - if (sink_cfg = sink_en) - return 0; + if (sink_cfg = sink_en) { + rc = wled_auto_detection_at_init(wled); + return rc; + } rc = regmap_update_bits(wled->regmap, wled->sink_addr + WLED4_SINK_REG_CURR_SINK, @@ -500,7 +841,9 @@ static int wled4_setup(struct wled *wled) return rc; } - return 0; + rc = wled_auto_detection_at_init(wled); + + return rc; } static const struct wled_config wled4_config_defaults = { @@ -511,6 +854,7 @@ static int wled4_setup(struct wled *wled) .switch_freq = 11, .cabc = false, .external_pfet = false, + .auto_detection_enabled = false, }; static const u32 wled3_boost_i_limit_values[] = { @@ -677,6 +1021,7 @@ static int wled_configure(struct wled *wled, int version) { "qcom,ext-gen", &cfg->ext_gen, }, { "qcom,cabc", &cfg->cabc, }, { "qcom,external-pfet", &cfg->external_pfet, }, + { "qcom,auto-string-detection", &cfg->auto_detection_enabled, }, }; prop_addr = of_get_address(dev->of_node, 0, NULL, NULL); @@ -797,6 +1142,40 @@ static int wled_configure_short_irq(struct wled *wled, return rc; } +static int wled_configure_ovp_irq(struct wled *wled, + struct platform_device *pdev) +{ + int rc; + u32 val; + + wled->ovp_irq = platform_get_irq_byname(pdev, "ovp"); + if (wled->ovp_irq < 0) { + dev_dbg(&pdev->dev, "OVP IRQ not found - disabling automatic string detection\n"); + return 0; + } + + rc = devm_request_threaded_irq(wled->dev, wled->ovp_irq, NULL, + wled_ovp_irq_handler, IRQF_ONESHOT, + "wled_ovp_irq", wled); + if (rc < 0) { + dev_err(wled->dev, "Unable to request ovp_irq (err:%d)\n", + rc); + wled->ovp_irq = 0; + return 0; + } + + rc = regmap_read(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_MOD_EN, &val); + if (rc < 0) + return rc; + + /* Keep OVP irq disabled until module is enabled */ + if (!(val & WLED3_CTRL_REG_MOD_EN_MASK)) + disable_irq(wled->ovp_irq); + + return 0; +} + static const struct backlight_ops wled_ops = { .update_status = wled_update_status, }; @@ -837,6 +1216,7 @@ static int wled_probe(struct platform_device *pdev) switch (version) { case 3: + wled->cfg.auto_detection_enabled = false; rc = wled3_setup(wled); if (rc) { dev_err(&pdev->dev, "wled3_setup failed\n"); @@ -858,10 +1238,16 @@ static int wled_probe(struct platform_device *pdev) break; } + INIT_DELAYED_WORK(&wled->ovp_work, wled_ovp_work); + rc = wled_configure_short_irq(wled, pdev); if (rc < 0) return rc; + rc = wled_configure_ovp_irq(wled, pdev); + if (rc < 0) + return rc; + val = WLED_DEFAULT_BRIGHTNESS; of_property_read_u32(pdev->dev.of_node, "default-brightness", &val); @@ -880,7 +1266,9 @@ static int wled_remove(struct platform_device *pdev) struct wled *wled = dev_get_drvdata(&pdev->dev); mutex_destroy(&wled->lock); + cancel_delayed_work_sync(&wled->ovp_work); disable_irq(wled->short_irq); + disable_irq(wled->ovp_irq); return 0; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BAB60CA9EC9 for ; Fri, 1 Nov 2019 08:10:39 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 95584208E3 for ; Fri, 1 Nov 2019 08:10:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 95584208E3 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AEE4D884FD; Fri, 1 Nov 2019 08:10:27 +0000 (UTC) Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.29.96]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2053D6F6DF for ; Fri, 1 Nov 2019 06:28:28 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 0116460FB4; Fri, 1 Nov 2019 06:28:27 +0000 (UTC) Received: from kgunda-linux.qualcomm.com (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: kgunda@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 6769860F74; Fri, 1 Nov 2019 06:28:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 6769860F74 From: Kiran Gunda To: bjorn.andersson@linaro.org, jingoohan1@gmail.com, lee.jones@linaro.org, b.zolnierkie@samsung.com, dri-devel@lists.freedesktop.org, daniel.thompson@linaro.org, jacek.anaszewski@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, mark.rutland@arm.com, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Andy Gross , linux-arm-msm@vger.kernel.org, linux-fbdev@vger.kernel.org Subject: [PATCH V10 8/8] backlight: qcom-wled: Add auto string detection logic Date: Fri, 1 Nov 2019 11:57:04 +0530 Message-Id: <1572589624-6095-9-git-send-email-kgunda@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1572589624-6095-1-git-send-email-kgunda@codeaurora.org> References: <1572589624-6095-1-git-send-email-kgunda@codeaurora.org> X-Mailman-Approved-At: Fri, 01 Nov 2019 08:09:55 +0000 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589708; bh=jbbKzMNuIKsCrSVBFloO4+6mFPMvXOegRo7cqvecICQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XgHiQsvjJJtWjo/RjuPpY9G66eb6WzZHtdUIW1fB29BSX1tR02Cm9PJn/ExzeianQ MLMs0UAz6NCXDGx/w4c290tOsukUONYX92I5Uq8lW9pKqmXMSD61SbgvKY9Ggs0Ezi BmCQ8sJIo4/TeHpZkDps0Q+Si4UPgnnVTmACQZXY= X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589704; bh=jbbKzMNuIKsCrSVBFloO4+6mFPMvXOegRo7cqvecICQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RoS3+f6SQxZ/5SMMMjP0gY4vFWeYLedHhyccHBP6WPtxqO7rbkrF1KvV+jjcUTvyw zaDBxN5Exm3zIz/RFHZphpvF2di9rN3uePXxdThhQpa5Nks1wReux8ggABJmqYSQ5n /Jn1h8xwX9n6jm25Ef069jOLLW/HnUHGPm7n3StA= X-Mailman-Original-Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org X-Mailman-Original-Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=kgunda@codeaurora.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kiran Gunda MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Message-ID: <20191101062704.YQeGxAKo9WBP3SVpnEcCn4tcVL0y8KYcPaJjNUtTn7s@z> VGhlIGF1dG8gc3RyaW5nIGRldGVjdGlvbiBhbGdvcml0aG0gY2hlY2tzIGlmIHRoZSBjdXJyZW50 IFdMRUQKc2luayBjb25maWd1cmF0aW9uIGlzIHZhbGlkLiBJdCB0cmllcyBlbmFibGluZyBldmVy eSBzaW5rIGFuZApjaGVja3MgaWYgdGhlIE9WUCBmYXVsdCBpcyBvYnNlcnZlZC4gQmFzZWQgb24g dGhpcyBpbmZvcm1hdGlvbgppdCBkZXRlY3RzIGFuZCBlbmFibGVzIHRoZSB2YWxpZCBzaW5rIGNv bmZpZ3VyYXRpb24uCkF1dG8gY2FsaWJyYXRpb24gd2lsbCBiZSB0cmlnZ2VyZWQgd2hlbiB0aGUg T1ZQIGZhdWx0IGludGVycnVwdHMKYXJlIHNlZW4gZnJlcXVlbnRseSB0aGVyZWJ5IGl0IHRyaWVz IHRvIGZpeCB0aGUgc2luayBjb25maWd1cmF0aW9uLgoKVGhlIGF1dG8tZGV0ZWN0aW9uIGFsc28g a2lja3MgaW4gd2hlbiB0aGUgY29ubmVjdGVkIExFRCBzdHJpbmcKb2YgdGhlIGRpc3BsYXktYmFj a2xpZ2h0IG1hbGZ1bmN0aW9ucyAoYmVjYXVzZSBvZiBkYW1hZ2UpIGFuZApyZXF1aXJlcyB0aGUg ZGFtYWdlZCBzdHJpbmcgdG8gYmUgdHVybmVkIG9mZiB0byBwcmV2ZW50IHRoZQpjb21wbGV0ZSBw YW5lbCBhbmQvb3IgYm9hcmQgZnJvbSBiZWluZyBkYW1hZ2VkLgoKU2lnbmVkLW9mZi1ieTogS2ly YW4gR3VuZGEgPGtndW5kYUBjb2RlYXVyb3JhLm9yZz4KUmV2aWV3ZWQtYnk6IERhbmllbCBUaG9t cHNvbiA8ZGFuaWVsLnRob21wc29uQGxpbmFyby5vcmc+Ci0tLQogZHJpdmVycy92aWRlby9iYWNr bGlnaHQvcWNvbS13bGVkLmMgfCA0MDAgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KystCiAxIGZpbGUgY2hhbmdlZCwgMzk0IGluc2VydGlvbnMoKyksIDYgZGVsZXRpb25zKC0pCgpk aWZmIC0tZ2l0IGEvZHJpdmVycy92aWRlby9iYWNrbGlnaHQvcWNvbS13bGVkLmMgYi9kcml2ZXJz L3ZpZGVvL2JhY2tsaWdodC9xY29tLXdsZWQuYwppbmRleCA2NThiMWUwLi4zM2I2MDA3IDEwMDY0 NAotLS0gYS9kcml2ZXJzL3ZpZGVvL2JhY2tsaWdodC9xY29tLXdsZWQuYworKysgYi9kcml2ZXJz L3ZpZGVvL2JhY2tsaWdodC9xY29tLXdsZWQuYwpAQCAtMTcsMTkgKzE3LDI5IEBACiAjZGVmaW5l IFdMRURfTUFYX1NUUklOR1MJCQkJNAogCiAjZGVmaW5lIFdMRURfREVGQVVMVF9CUklHSFRORVNT CQkJCTIwNDgKLQorI2RlZmluZSBXTEVEX1NPRlRfU1RBUlRfRExZX1VTCQkJCTEwMDAwCiAjZGVm aW5lIFdMRUQzX1NJTktfUkVHX0JSSUdIVF9NQVgJCQkweEZGRgogCiAvKiBXTEVEMy9XTEVENCBj b250cm9sIHJlZ2lzdGVycyAqLworI2RlZmluZSBXTEVEM19DVFJMX1JFR19GQVVMVF9TVEFUVVMJ CQkweDA4CisjZGVmaW5lICBXTEVEM19DVFJMX1JFR19JTElNX0ZBVUxUX0JJVAkJCUJJVCgwKQor I2RlZmluZSAgV0xFRDNfQ1RSTF9SRUdfT1ZQX0ZBVUxUX0JJVAkJCUJJVCgxKQorI2RlZmluZSAg V0xFRDRfQ1RSTF9SRUdfU0NfRkFVTFRfQklUCQkJQklUKDIpCisKKyNkZWZpbmUgV0xFRDNfQ1RS TF9SRUdfSU5UX1JUX1NUUwkJCTB4MTAKKyNkZWZpbmUgIFdMRUQzX0NUUkxfUkVHX09WUF9GQVVM VF9TVEFUVVMJCUJJVCgxKQorCiAjZGVmaW5lIFdMRUQzX0NUUkxfUkVHX01PRF9FTgkJCQkweDQ2 CiAjZGVmaW5lICBXTEVEM19DVFJMX1JFR19NT0RfRU5fTUFTSwkJCUJJVCg3KQogI2RlZmluZSAg V0xFRDNfQ1RSTF9SRUdfTU9EX0VOX1NISUZUCQkJNwogCisjZGVmaW5lIFdMRUQzX0NUUkxfUkVH X0ZFRURCQUNLX0NPTlRST0wJCQkweDQ4CisKICNkZWZpbmUgV0xFRDNfQ1RSTF9SRUdfRlJFUQkJ CQkweDRjCiAjZGVmaW5lICBXTEVEM19DVFJMX1JFR19GUkVRX01BU0sJCQlHRU5NQVNLKDMsIDAp CiAKICNkZWZpbmUgV0xFRDNfQ1RSTF9SRUdfT1ZQCQkJCTB4NGQKLSNkZWZpbmUgIFdMRUQzX0NU UkxfUkVHX09WUF9NQVNLCQkJCUdFTk1BU0soMSwgMCkKKyNkZWZpbmUgIFdMRUQzX0NUUkxfUkVH X09WUF9NQVNLCQkJR0VOTUFTSygxLCAwKQogCiAjZGVmaW5lIFdMRUQzX0NUUkxfUkVHX0lMSU1J VAkJCQkweDRlCiAjZGVmaW5lICBXTEVEM19DVFJMX1JFR19JTElNSVRfTUFTSwkJCUdFTk1BU0so MiwgMCkKQEAgLTExOSw2ICsxMjksNyBAQCBzdHJ1Y3Qgd2xlZF9jb25maWcgewogCWJvb2wgZXh0 X2dlbjsKIAlib29sIGNhYmM7CiAJYm9vbCBleHRlcm5hbF9wZmV0OworCWJvb2wgYXV0b19kZXRl Y3Rpb25fZW5hYmxlZDsKIH07CiAKIHN0cnVjdCB3bGVkIHsKQEAgLTEyNywxNyArMTM4LDIyIEBA IHN0cnVjdCB3bGVkIHsKIAlzdHJ1Y3QgcmVnbWFwICpyZWdtYXA7CiAJc3RydWN0IG11dGV4IGxv Y2s7CS8qIExvY2sgdG8gYXZvaWQgcmFjZSBmcm9tIHRocmVhZCBpcnEgaGFuZGxlciAqLwogCWt0 aW1lX3QgbGFzdF9zaG9ydF9ldmVudDsKKwlrdGltZV90IHN0YXJ0X292cF9mYXVsdF90aW1lOwog CXUxNiBjdHJsX2FkZHI7CiAJdTE2IHNpbmtfYWRkcjsKIAl1MTYgbWF4X3N0cmluZ19jb3VudDsK Kwl1MTYgYXV0b19kZXRlY3Rpb25fb3ZwX2NvdW50OwogCXUzMiBicmlnaHRuZXNzOwogCXUzMiBt YXhfYnJpZ2h0bmVzczsKIAl1MzIgc2hvcnRfY291bnQ7CisJdTMyIGF1dG9fZGV0ZWN0X2NvdW50 OwogCWJvb2wgZGlzYWJsZWRfYnlfc2hvcnQ7CiAJYm9vbCBoYXNfc2hvcnRfZGV0ZWN0OwogCWlu dCBzaG9ydF9pcnE7CisJaW50IG92cF9pcnE7CiAKIAlzdHJ1Y3Qgd2xlZF9jb25maWcgY2ZnOwor CXN0cnVjdCBkZWxheWVkX3dvcmsgb3ZwX3dvcms7CiAJaW50ICgqd2xlZF9zZXRfYnJpZ2h0bmVz cykoc3RydWN0IHdsZWQgKndsZWQsIHUxNiBicmlnaHRuZXNzKTsKIH07CiAKQEAgLTE4Miw2ICsx OTgsMTMgQEAgc3RhdGljIGludCB3bGVkNF9zZXRfYnJpZ2h0bmVzcyhzdHJ1Y3Qgd2xlZCAqd2xl ZCwgdTE2IGJyaWdodG5lc3MpCiAJcmV0dXJuIDA7CiB9CiAKK3N0YXRpYyB2b2lkIHdsZWRfb3Zw X3dvcmsoc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQoreworCXN0cnVjdCB3bGVkICp3bGVkID0g Y29udGFpbmVyX29mKHdvcmssCisJCQkJCSBzdHJ1Y3Qgd2xlZCwgb3ZwX3dvcmsud29yayk7CisJ ZW5hYmxlX2lycSh3bGVkLT5vdnBfaXJxKTsKK30KKwogc3RhdGljIGludCB3bGVkX21vZHVsZV9l bmFibGUoc3RydWN0IHdsZWQgKndsZWQsIGludCB2YWwpCiB7CiAJaW50IHJjOwpAQCAtMTkzLDcg KzIxNiwyNSBAQCBzdGF0aWMgaW50IHdsZWRfbW9kdWxlX2VuYWJsZShzdHJ1Y3Qgd2xlZCAqd2xl ZCwgaW50IHZhbCkKIAkJCQlXTEVEM19DVFJMX1JFR19NT0RfRU4sCiAJCQkJV0xFRDNfQ1RSTF9S RUdfTU9EX0VOX01BU0ssCiAJCQkJdmFsIDw8IFdMRUQzX0NUUkxfUkVHX01PRF9FTl9TSElGVCk7 Ci0JcmV0dXJuIHJjOworCWlmIChyYyA8IDApCisJCXJldHVybiByYzsKKworCWlmICh3bGVkLT5v dnBfaXJxID4gMCkgeworCQlpZiAodmFsKSB7CisJCQkvKgorCQkJICogVGhlIGhhcmR3YXJlIGdl bmVyYXRlcyBhIHN0b3JtIG9mIHNwdXJpb3VzIE9WUAorCQkJICogaW50ZXJydXB0cyBkdXJpbmcg c29mdCBzdGFydCBvcGVyYXRpb25zLiBTbyBkZWZlcgorCQkJICogZW5hYmxpbmcgdGhlIElSUSBm b3IgMTBtcyB0byBlbnN1cmUgdGhhdCB0aGUKKwkJCSAqIHNvZnQgc3RhcnQgaXMgY29tcGxldGUu CisJCQkgKi8KKwkJCXNjaGVkdWxlX2RlbGF5ZWRfd29yaygmd2xlZC0+b3ZwX3dvcmssIEhaIC8g MTAwKTsKKwkJfSBlbHNlIHsKKwkJCWlmICghY2FuY2VsX2RlbGF5ZWRfd29ya19zeW5jKCZ3bGVk LT5vdnBfd29yaykpCisJCQkJZGlzYWJsZV9pcnEod2xlZC0+b3ZwX2lycSk7CisJCX0KKwl9CisK KwlyZXR1cm4gMDsKIH0KIAogc3RhdGljIGludCB3bGVkX3N5bmNfdG9nZ2xlKHN0cnVjdCB3bGVk ICp3bGVkKQpAQCAtMzAwLDYgKzM0MSwzMDQgQEAgc3RhdGljIGlycXJldHVybl90IHdsZWRfc2hv cnRfaXJxX2hhbmRsZXIoaW50IGlycSwgdm9pZCAqX3dsZWQpCiAJcmV0dXJuIElSUV9IQU5ETEVE OwogfQogCisjZGVmaW5lIEFVVE9fREVURUNUX0JSSUdIVE5FU1MJCTIwMAorCitzdGF0aWMgdm9p ZCB3bGVkX2F1dG9fc3RyaW5nX2RldGVjdGlvbihzdHJ1Y3Qgd2xlZCAqd2xlZCkKK3sKKwlpbnQg cmMgPSAwLCBpOworCXUzMiBzaW5rX2NvbmZpZyA9IDAsIGludF9zdHM7CisJdTggc2lua190ZXN0 ID0gMCwgc2lua192YWxpZCA9IDAsIHZhbDsKKworCS8qIFJlYWQgY29uZmlndXJlZCBzaW5rIGNv bmZpZ3VyYXRpb24gKi8KKwlyYyA9IHJlZ21hcF9yZWFkKHdsZWQtPnJlZ21hcCwgd2xlZC0+c2lu a19hZGRyICsKKwkJCSBXTEVENF9TSU5LX1JFR19DVVJSX1NJTkssICZzaW5rX2NvbmZpZyk7CisJ aWYgKHJjIDwgMCkgeworCQlkZXZfZXJyKHdsZWQtPmRldiwgIkZhaWxlZCB0byByZWFkIFNJTksg Y29uZmlndXJhdGlvbiByYz0lZFxuIiwKKwkJCXJjKTsKKwkJZ290byBmYWlsZWRfZGV0ZWN0Owor CX0KKworCS8qIERpc2FibGUgdGhlIG1vZHVsZSBiZWZvcmUgc3RhcnRpbmcgZGV0ZWN0aW9uICov CisJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLAorCQkJCXdsZWQtPmN0cmxf YWRkciArIFdMRUQzX0NUUkxfUkVHX01PRF9FTiwKKwkJCQlXTEVEM19DVFJMX1JFR19NT0RfRU5f TUFTSywgMCk7CisJaWYgKHJjIDwgMCkgeworCQlkZXZfZXJyKHdsZWQtPmRldiwgIkZhaWxlZCB0 byBkaXNhYmxlIFdMRUQgbW9kdWxlIHJjPSVkXG4iLCByYyk7CisJCWdvdG8gZmFpbGVkX2RldGVj dDsKKwl9CisKKwkvKiBTZXQgbG93IGJyaWdodG5lc3MgYWNyb3NzIGFsbCBzaW5rcyAqLworCXJj ID0gd2xlZDRfc2V0X2JyaWdodG5lc3Mod2xlZCwgQVVUT19ERVRFQ1RfQlJJR0hUTkVTUyk7CisJ aWYgKHJjIDwgMCkgeworCQlkZXZfZXJyKHdsZWQtPmRldiwgIkZhaWxlZCB0byBzZXQgYnJpZ2h0 bmVzcyBmb3IgYXV0byBkZXRlY3Rpb24gcmM9JWRcbiIsCisJCQlyYyk7CisJCWdvdG8gZmFpbGVk X2RldGVjdDsKKwl9CisKKwlpZiAod2xlZC0+Y2ZnLmNhYmMpIHsKKwkJZm9yIChpID0gMDsgaSA8 IHdsZWQtPmNmZy5udW1fc3RyaW5nczsgaSsrKSB7CisJCQlyYyA9IHJlZ21hcF91cGRhdGVfYml0 cyh3bGVkLT5yZWdtYXAsIHdsZWQtPnNpbmtfYWRkciArCisJCQkJCQlXTEVENF9TSU5LX1JFR19T VFJfQ0FCQyhpKSwKKwkJCQkJCVdMRUQ0X1NJTktfUkVHX1NUUl9DQUJDX01BU0ssCisJCQkJCQkw KTsKKwkJCWlmIChyYyA8IDApCisJCQkJZ290byBmYWlsZWRfZGV0ZWN0OworCQl9CisJfQorCisJ LyogRGlzYWJsZSBhbGwgc2lua3MgKi8KKwlyYyA9IHJlZ21hcF93cml0ZSh3bGVkLT5yZWdtYXAs CisJCQkgIHdsZWQtPnNpbmtfYWRkciArIFdMRUQ0X1NJTktfUkVHX0NVUlJfU0lOSywgMCk7CisJ aWYgKHJjIDwgMCkgeworCQlkZXZfZXJyKHdsZWQtPmRldiwgIkZhaWxlZCB0byBkaXNhYmxlIGFs bCBzaW5rcyByYz0lZFxuIiwgcmMpOworCQlnb3RvIGZhaWxlZF9kZXRlY3Q7CisJfQorCisJLyog SXRlcmF0ZSB0aHJvdWdoIHRoZSBzdHJpbmdzIG9uZSBieSBvbmUgKi8KKwlmb3IgKGkgPSAwOyBp IDwgd2xlZC0+Y2ZnLm51bV9zdHJpbmdzOyBpKyspIHsKKwkJc2lua190ZXN0ID0gQklUKChXTEVE NF9TSU5LX1JFR19DVVJSX1NJTktfU0hGVCArIGkpKTsKKworCQkvKiBFbmFibGUgZmVlZGJhY2sg Y29udHJvbCAqLworCQlyYyA9IHJlZ21hcF93cml0ZSh3bGVkLT5yZWdtYXAsIHdsZWQtPmN0cmxf YWRkciArCisJCQkJICBXTEVEM19DVFJMX1JFR19GRUVEQkFDS19DT05UUk9MLCBpICsgMSk7CisJ CWlmIChyYyA8IDApIHsKKwkJCWRldl9lcnIod2xlZC0+ZGV2LCAiRmFpbGVkIHRvIGVuYWJsZSBm ZWVkYmFjayBmb3IgU0lOSyAlZCByYyA9ICVkXG4iLAorCQkJCWkgKyAxLCByYyk7CisJCQlnb3Rv IGZhaWxlZF9kZXRlY3Q7CisJCX0KKworCQkvKiBFbmFibGUgdGhlIHNpbmsgKi8KKwkJcmMgPSBy ZWdtYXBfd3JpdGUod2xlZC0+cmVnbWFwLCB3bGVkLT5zaW5rX2FkZHIgKworCQkJCSAgV0xFRDRf U0lOS19SRUdfQ1VSUl9TSU5LLCBzaW5rX3Rlc3QpOworCQlpZiAocmMgPCAwKSB7CisJCQlkZXZf ZXJyKHdsZWQtPmRldiwgIkZhaWxlZCB0byBjb25maWd1cmUgU0lOSyAlZCByYz0lZFxuIiwKKwkJ CQlpICsgMSwgcmMpOworCQkJZ290byBmYWlsZWRfZGV0ZWN0OworCQl9CisKKwkJLyogRW5hYmxl IHRoZSBtb2R1bGUgKi8KKwkJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLCB3 bGVkLT5jdHJsX2FkZHIgKworCQkJCQlXTEVEM19DVFJMX1JFR19NT0RfRU4sCisJCQkJCVdMRUQz X0NUUkxfUkVHX01PRF9FTl9NQVNLLAorCQkJCQlXTEVEM19DVFJMX1JFR19NT0RfRU5fTUFTSyk7 CisJCWlmIChyYyA8IDApIHsKKwkJCWRldl9lcnIod2xlZC0+ZGV2LCAiRmFpbGVkIHRvIGVuYWJs ZSBXTEVEIG1vZHVsZSByYz0lZFxuIiwKKwkJCQlyYyk7CisJCQlnb3RvIGZhaWxlZF9kZXRlY3Q7 CisJCX0KKworCQl1c2xlZXBfcmFuZ2UoV0xFRF9TT0ZUX1NUQVJUX0RMWV9VUywKKwkJCSAgICAg V0xFRF9TT0ZUX1NUQVJUX0RMWV9VUyArIDEwMDApOworCisJCXJjID0gcmVnbWFwX3JlYWQod2xl ZC0+cmVnbWFwLCB3bGVkLT5jdHJsX2FkZHIgKworCQkJCSBXTEVEM19DVFJMX1JFR19JTlRfUlRf U1RTLCAmaW50X3N0cyk7CisJCWlmIChyYyA8IDApIHsKKwkJCWRldl9lcnIod2xlZC0+ZGV2LCAi RXJyb3IgaW4gcmVhZGluZyBXTEVEM19DVFJMX0lOVF9SVF9TVFMgcmM9JWRcbiIsCisJCQkJcmMp OworCQkJZ290byBmYWlsZWRfZGV0ZWN0OworCQl9CisKKwkJaWYgKGludF9zdHMgJiBXTEVEM19D VFJMX1JFR19PVlBfRkFVTFRfU1RBVFVTKQorCQkJZGV2X2RiZyh3bGVkLT5kZXYsICJXTEVEIE9W UCBmYXVsdCBkZXRlY3RlZCB3aXRoIFNJTksgJWRcbiIsCisJCQkJaSArIDEpOworCQllbHNlCisJ CQlzaW5rX3ZhbGlkIHw9IHNpbmtfdGVzdDsKKworCQkvKiBEaXNhYmxlIHRoZSBtb2R1bGUgKi8K KwkJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLAorCQkJCQl3bGVkLT5jdHJs X2FkZHIgKyBXTEVEM19DVFJMX1JFR19NT0RfRU4sCisJCQkJCVdMRUQzX0NUUkxfUkVHX01PRF9F Tl9NQVNLLCAwKTsKKwkJaWYgKHJjIDwgMCkgeworCQkJZGV2X2Vycih3bGVkLT5kZXYsICJGYWls ZWQgdG8gZGlzYWJsZSBXTEVEIG1vZHVsZSByYz0lZFxuIiwKKwkJCQlyYyk7CisJCQlnb3RvIGZh aWxlZF9kZXRlY3Q7CisJCX0KKwl9CisKKwlpZiAoIXNpbmtfdmFsaWQpIHsKKwkJZGV2X2Vycih3 bGVkLT5kZXYsICJObyB2YWxpZCBXTEVEIHNpbmtzIGZvdW5kXG4iKTsKKwkJd2xlZC0+ZGlzYWJs ZWRfYnlfc2hvcnQgPSB0cnVlOworCQlnb3RvIGZhaWxlZF9kZXRlY3Q7CisJfQorCisJaWYgKHNp bmtfdmFsaWQgIT0gc2lua19jb25maWcpIHsKKwkJZGV2X3dhcm4od2xlZC0+ZGV2LCAiJXggaXMg bm90IGEgdmFsaWQgc2luayBjb25maWd1cmF0aW9uIC0gdXNpbmcgJXggaW5zdGVhZFxuIiwKKwkJ CSBzaW5rX2NvbmZpZywgc2lua192YWxpZCk7CisJCXNpbmtfY29uZmlnID0gc2lua192YWxpZDsK Kwl9CisKKwkvKiBXcml0ZSB0aGUgbmV3IHNpbmsgY29uZmlndXJhdGlvbiAqLworCXJjID0gcmVn bWFwX3dyaXRlKHdsZWQtPnJlZ21hcCwKKwkJCSAgd2xlZC0+c2lua19hZGRyICsgV0xFRDRfU0lO S19SRUdfQ1VSUl9TSU5LLAorCQkJICBzaW5rX2NvbmZpZyk7CisJaWYgKHJjIDwgMCkgeworCQlk ZXZfZXJyKHdsZWQtPmRldiwgIkZhaWxlZCB0byByZWNvbmZpZ3VyZSB0aGUgZGVmYXVsdCBzaW5r IHJjPSVkXG4iLAorCQkJcmMpOworCQlnb3RvIGZhaWxlZF9kZXRlY3Q7CisJfQorCisJLyogRW5h YmxlIHZhbGlkIHNpbmtzICovCisJZm9yIChpID0gMDsgaSA8IHdsZWQtPmNmZy5udW1fc3RyaW5n czsgaSsrKSB7CisJCWlmICh3bGVkLT5jZmcuY2FiYykgeworCQkJcmMgPSByZWdtYXBfdXBkYXRl X2JpdHMod2xlZC0+cmVnbWFwLCB3bGVkLT5zaW5rX2FkZHIgKworCQkJCQkJV0xFRDRfU0lOS19S RUdfU1RSX0NBQkMoaSksCisJCQkJCQlXTEVENF9TSU5LX1JFR19TVFJfQ0FCQ19NQVNLLAorCQkJ CQkJV0xFRDRfU0lOS19SRUdfU1RSX0NBQkNfTUFTSyk7CisJCQlpZiAocmMgPCAwKQorCQkJCWdv dG8gZmFpbGVkX2RldGVjdDsKKwkJfQorCisJCWlmIChzaW5rX2NvbmZpZyAmIEJJVChXTEVENF9T SU5LX1JFR19DVVJSX1NJTktfU0hGVCArIGkpKQorCQkJdmFsID0gV0xFRDRfU0lOS19SRUdfU1RS X01PRF9NQVNLOworCQllbHNlCisJCQl2YWwgPSAweDA7IC8qIERpc2FibGUgbW9kdWxhdG9yX2Vu IGZvciB1bnVzZWQgc2luayAqLworCisJCXJjID0gcmVnbWFwX3dyaXRlKHdsZWQtPnJlZ21hcCwg d2xlZC0+c2lua19hZGRyICsKKwkJCQkgIFdMRUQ0X1NJTktfUkVHX1NUUl9NT0RfRU4oaSksIHZh bCk7CisJCWlmIChyYyA8IDApIHsKKwkJCWRldl9lcnIod2xlZC0+ZGV2LCAiRmFpbGVkIHRvIGNv bmZpZ3VyZSBNT0RVTEFUT1JfRU4gcmM9JWRcbiIsCisJCQkJcmMpOworCQkJZ290byBmYWlsZWRf ZGV0ZWN0OworCQl9CisJfQorCisJLyogUmVzdG9yZSB0aGUgZmVlZGJhY2sgc2V0dGluZyAqLwor CXJjID0gcmVnbWFwX3dyaXRlKHdsZWQtPnJlZ21hcCwKKwkJCSAgd2xlZC0+Y3RybF9hZGRyICsg V0xFRDNfQ1RSTF9SRUdfRkVFREJBQ0tfQ09OVFJPTCwgMCk7CisJaWYgKHJjIDwgMCkgeworCQlk ZXZfZXJyKHdsZWQtPmRldiwgIkZhaWxlZCB0byByZXN0b3JlIGZlZWRiYWNrIHNldHRpbmcgcmM9 JWRcbiIsCisJCQlyYyk7CisJCWdvdG8gZmFpbGVkX2RldGVjdDsKKwl9CisKKwkvKiBSZXN0b3Jl IGJyaWdodG5lc3MgKi8KKwlyYyA9IHdsZWQ0X3NldF9icmlnaHRuZXNzKHdsZWQsIHdsZWQtPmJy aWdodG5lc3MpOworCWlmIChyYyA8IDApIHsKKwkJZGV2X2Vycih3bGVkLT5kZXYsICJGYWlsZWQg dG8gc2V0IGJyaWdodG5lc3MgYWZ0ZXIgYXV0byBkZXRlY3Rpb24gcmM9JWRcbiIsCisJCQlyYyk7 CisJCWdvdG8gZmFpbGVkX2RldGVjdDsKKwl9CisKKwlyYyA9IHJlZ21hcF91cGRhdGVfYml0cyh3 bGVkLT5yZWdtYXAsCisJCQkJd2xlZC0+Y3RybF9hZGRyICsgV0xFRDNfQ1RSTF9SRUdfTU9EX0VO LAorCQkJCVdMRUQzX0NUUkxfUkVHX01PRF9FTl9NQVNLLAorCQkJCVdMRUQzX0NUUkxfUkVHX01P RF9FTl9NQVNLKTsKKwlpZiAocmMgPCAwKSB7CisJCWRldl9lcnIod2xlZC0+ZGV2LCAiRmFpbGVk IHRvIGVuYWJsZSBXTEVEIG1vZHVsZSByYz0lZFxuIiwgcmMpOworCQlnb3RvIGZhaWxlZF9kZXRl Y3Q7CisJfQorCitmYWlsZWRfZGV0ZWN0OgorCXJldHVybjsKK30KKworI2RlZmluZSBXTEVEX0FV VE9fREVURUNUX09WUF9DT1VOVAkJNQorI2RlZmluZSBXTEVEX0FVVE9fREVURUNUX0NOVF9ETFlf VVMJCVVTRUNfUEVSX1NFQworc3RhdGljIGJvb2wgd2xlZF9hdXRvX2RldGVjdGlvbl9yZXF1aXJl ZChzdHJ1Y3Qgd2xlZCAqd2xlZCkKK3sKKwlzNjQgZWxhcHNlZF90aW1lX3VzOworCisJaWYgKCF3 bGVkLT5jZmcuYXV0b19kZXRlY3Rpb25fZW5hYmxlZCkKKwkJcmV0dXJuIGZhbHNlOworCisJLyoK KwkgKiBDaGVjayBpZiB0aGUgT1ZQIGZhdWx0IHdhcyBhbiBvY2Nhc2lvbmFsIG9uZQorCSAqIG9y IGlmIGl0J3MgZmlyaW5nIGNvbnRpbnVvdXNseSwgdGhlIGxhdHRlciBxdWFsaWZpZXMKKwkgKiBm b3IgYW4gYXV0by1kZXRlY3Rpb24gY2hlY2suCisJICovCisJaWYgKCF3bGVkLT5hdXRvX2RldGVj dGlvbl9vdnBfY291bnQpIHsKKwkJd2xlZC0+c3RhcnRfb3ZwX2ZhdWx0X3RpbWUgPSBrdGltZV9n ZXQoKTsKKwkJd2xlZC0+YXV0b19kZXRlY3Rpb25fb3ZwX2NvdW50Kys7CisJfSBlbHNlIHsKKwkJ ZWxhcHNlZF90aW1lX3VzID0ga3RpbWVfdXNfZGVsdGEoa3RpbWVfZ2V0KCksCisJCQkJCQkgd2xl ZC0+c3RhcnRfb3ZwX2ZhdWx0X3RpbWUpOworCQlpZiAoZWxhcHNlZF90aW1lX3VzID4gV0xFRF9B VVRPX0RFVEVDVF9DTlRfRExZX1VTKQorCQkJd2xlZC0+YXV0b19kZXRlY3Rpb25fb3ZwX2NvdW50 ID0gMDsKKwkJZWxzZQorCQkJd2xlZC0+YXV0b19kZXRlY3Rpb25fb3ZwX2NvdW50Kys7CisKKwkJ aWYgKHdsZWQtPmF1dG9fZGV0ZWN0aW9uX292cF9jb3VudCA+PQorCQkJCVdMRURfQVVUT19ERVRF Q1RfT1ZQX0NPVU5UKSB7CisJCQl3bGVkLT5hdXRvX2RldGVjdGlvbl9vdnBfY291bnQgPSAwOwor CQkJcmV0dXJuIHRydWU7CisJCX0KKwl9CisKKwlyZXR1cm4gZmFsc2U7Cit9CisKK3N0YXRpYyBp bnQgd2xlZF9hdXRvX2RldGVjdGlvbl9hdF9pbml0KHN0cnVjdCB3bGVkICp3bGVkKQoreworCWlu dCByYzsKKwl1MzIgZmF1bHRfc3RhdHVzLCBydF9zdGF0dXM7CisKKwlpZiAoIXdsZWQtPmNmZy5h dXRvX2RldGVjdGlvbl9lbmFibGVkKQorCQlyZXR1cm4gMDsKKworCXJjID0gcmVnbWFwX3JlYWQo d2xlZC0+cmVnbWFwLAorCQkJIHdsZWQtPmN0cmxfYWRkciArIFdMRUQzX0NUUkxfUkVHX0lOVF9S VF9TVFMsCisJCQkgJnJ0X3N0YXR1cyk7CisJaWYgKHJjIDwgMCkgeworCQlkZXZfZXJyKHdsZWQt PmRldiwgIkZhaWxlZCB0byByZWFkIFJUIHN0YXR1cyByYz0lZFxuIiwgcmMpOworCQlyZXR1cm4g cmM7CisJfQorCisJcmMgPSByZWdtYXBfcmVhZCh3bGVkLT5yZWdtYXAsCisJCQkgd2xlZC0+Y3Ry bF9hZGRyICsgV0xFRDNfQ1RSTF9SRUdfRkFVTFRfU1RBVFVTLAorCQkJICZmYXVsdF9zdGF0dXMp OworCWlmIChyYyA8IDApIHsKKwkJZGV2X2Vycih3bGVkLT5kZXYsICJGYWlsZWQgdG8gcmVhZCBm YXVsdCBzdGF0dXMgcmM9JWRcbiIsIHJjKTsKKwkJcmV0dXJuIHJjOworCX0KKworCWlmICgocnRf c3RhdHVzICYgV0xFRDNfQ1RSTF9SRUdfT1ZQX0ZBVUxUX1NUQVRVUykgfHwKKwkgICAgKGZhdWx0 X3N0YXR1cyAmIFdMRUQzX0NUUkxfUkVHX09WUF9GQVVMVF9CSVQpKSB7CisJCW11dGV4X2xvY2so JndsZWQtPmxvY2spOworCQl3bGVkX2F1dG9fc3RyaW5nX2RldGVjdGlvbih3bGVkKTsKKwkJbXV0 ZXhfdW5sb2NrKCZ3bGVkLT5sb2NrKTsKKwl9CisKKwlyZXR1cm4gcmM7Cit9CisKK3N0YXRpYyBp cnFyZXR1cm5fdCB3bGVkX292cF9pcnFfaGFuZGxlcihpbnQgaXJxLCB2b2lkICpfd2xlZCkKK3sK KwlzdHJ1Y3Qgd2xlZCAqd2xlZCA9IF93bGVkOworCWludCByYzsKKwl1MzIgaW50X3N0cywgZmF1 bHRfc3RzOworCisJcmMgPSByZWdtYXBfcmVhZCh3bGVkLT5yZWdtYXAsCisJCQkgd2xlZC0+Y3Ry bF9hZGRyICsgV0xFRDNfQ1RSTF9SRUdfSU5UX1JUX1NUUywgJmludF9zdHMpOworCWlmIChyYyA8 IDApIHsKKwkJZGV2X2Vycih3bGVkLT5kZXYsICJFcnJvciBpbiByZWFkaW5nIFdMRUQzX0lOVF9S VF9TVFMgcmM9JWRcbiIsCisJCQlyYyk7CisJCXJldHVybiBJUlFfSEFORExFRDsKKwl9CisKKwly YyA9IHJlZ21hcF9yZWFkKHdsZWQtPnJlZ21hcCwgd2xlZC0+Y3RybF9hZGRyICsKKwkJCSBXTEVE M19DVFJMX1JFR19GQVVMVF9TVEFUVVMsICZmYXVsdF9zdHMpOworCWlmIChyYyA8IDApIHsKKwkJ ZGV2X2Vycih3bGVkLT5kZXYsICJFcnJvciBpbiByZWFkaW5nIFdMRURfRkFVTFRfU1RBVFVTIHJj PSVkXG4iLAorCQkJcmMpOworCQlyZXR1cm4gSVJRX0hBTkRMRUQ7CisJfQorCisJaWYgKGZhdWx0 X3N0cyAmIChXTEVEM19DVFJMX1JFR19PVlBfRkFVTFRfQklUIHwKKwkJV0xFRDNfQ1RSTF9SRUdf SUxJTV9GQVVMVF9CSVQpKQorCQlkZXZfZGJnKHdsZWQtPmRldiwgIldMRUQgT1ZQIGZhdWx0IGRl dGVjdGVkLCBpbnRfc3RzPSV4IGZhdWx0X3N0cz0gJXhcbiIsCisJCQlpbnRfc3RzLCBmYXVsdF9z dHMpOworCisJaWYgKGZhdWx0X3N0cyAmIFdMRUQzX0NUUkxfUkVHX09WUF9GQVVMVF9CSVQpIHsK KwkJaWYgKHdsZWRfYXV0b19kZXRlY3Rpb25fcmVxdWlyZWQod2xlZCkpIHsKKwkJCW11dGV4X2xv Y2soJndsZWQtPmxvY2spOworCQkJd2xlZF9hdXRvX3N0cmluZ19kZXRlY3Rpb24od2xlZCk7CisJ CQltdXRleF91bmxvY2soJndsZWQtPmxvY2spOworCQl9CisJfQorCisJcmV0dXJuIElSUV9IQU5E TEVEOworfQorCiBzdGF0aWMgaW50IHdsZWQzX3NldHVwKHN0cnVjdCB3bGVkICp3bGVkKQogewog CXUxNiBhZGRyOwpAQCAtNDM2LDggKzc3NSwxMCBAQCBzdGF0aWMgaW50IHdsZWQ0X3NldHVwKHN0 cnVjdCB3bGVkICp3bGVkKQogCQlzaW5rX2VuIHw9IDEgPDwgdGVtcDsKIAl9CiAKLQlpZiAoc2lu a19jZmcgPT0gc2lua19lbikKLQkJcmV0dXJuIDA7CisJaWYgKHNpbmtfY2ZnID09IHNpbmtfZW4p IHsKKwkJcmMgPSB3bGVkX2F1dG9fZGV0ZWN0aW9uX2F0X2luaXQod2xlZCk7CisJCXJldHVybiBy YzsKKwl9CiAKIAlyYyA9IHJlZ21hcF91cGRhdGVfYml0cyh3bGVkLT5yZWdtYXAsCiAJCQkJd2xl ZC0+c2lua19hZGRyICsgV0xFRDRfU0lOS19SRUdfQ1VSUl9TSU5LLApAQCAtNTAwLDcgKzg0MSw5 IEBAIHN0YXRpYyBpbnQgd2xlZDRfc2V0dXAoc3RydWN0IHdsZWQgKndsZWQpCiAJCXJldHVybiBy YzsKIAl9CiAKLQlyZXR1cm4gMDsKKwlyYyA9IHdsZWRfYXV0b19kZXRlY3Rpb25fYXRfaW5pdCh3 bGVkKTsKKworCXJldHVybiByYzsKIH0KIAogc3RhdGljIGNvbnN0IHN0cnVjdCB3bGVkX2NvbmZp ZyB3bGVkNF9jb25maWdfZGVmYXVsdHMgPSB7CkBAIC01MTEsNiArODU0LDcgQEAgc3RhdGljIGlu dCB3bGVkNF9zZXR1cChzdHJ1Y3Qgd2xlZCAqd2xlZCkKIAkuc3dpdGNoX2ZyZXEgPSAxMSwKIAku Y2FiYyA9IGZhbHNlLAogCS5leHRlcm5hbF9wZmV0ID0gZmFsc2UsCisJLmF1dG9fZGV0ZWN0aW9u X2VuYWJsZWQgPSBmYWxzZSwKIH07CiAKIHN0YXRpYyBjb25zdCB1MzIgd2xlZDNfYm9vc3RfaV9s aW1pdF92YWx1ZXNbXSA9IHsKQEAgLTY3Nyw2ICsxMDIxLDcgQEAgc3RhdGljIGludCB3bGVkX2Nv bmZpZ3VyZShzdHJ1Y3Qgd2xlZCAqd2xlZCwgaW50IHZlcnNpb24pCiAJCXsgInFjb20sZXh0LWdl biIsICZjZmctPmV4dF9nZW4sIH0sCiAJCXsgInFjb20sY2FiYyIsICZjZmctPmNhYmMsIH0sCiAJ CXsgInFjb20sZXh0ZXJuYWwtcGZldCIsICZjZmctPmV4dGVybmFsX3BmZXQsIH0sCisJCXsgInFj b20sYXV0by1zdHJpbmctZGV0ZWN0aW9uIiwgJmNmZy0+YXV0b19kZXRlY3Rpb25fZW5hYmxlZCwg fSwKIAl9OwogCiAJcHJvcF9hZGRyID0gb2ZfZ2V0X2FkZHJlc3MoZGV2LT5vZl9ub2RlLCAwLCBO VUxMLCBOVUxMKTsKQEAgLTc5Nyw2ICsxMTQyLDQwIEBAIHN0YXRpYyBpbnQgd2xlZF9jb25maWd1 cmVfc2hvcnRfaXJxKHN0cnVjdCB3bGVkICp3bGVkLAogCXJldHVybiByYzsKIH0KIAorc3RhdGlj IGludCB3bGVkX2NvbmZpZ3VyZV9vdnBfaXJxKHN0cnVjdCB3bGVkICp3bGVkLAorCQkJCSAgc3Ry dWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlpbnQgcmM7CisJdTMyIHZhbDsKKworCXds ZWQtPm92cF9pcnEgPSBwbGF0Zm9ybV9nZXRfaXJxX2J5bmFtZShwZGV2LCAib3ZwIik7CisJaWYg KHdsZWQtPm92cF9pcnEgPCAwKSB7CisJCWRldl9kYmcoJnBkZXYtPmRldiwgIk9WUCBJUlEgbm90 IGZvdW5kIC0gZGlzYWJsaW5nIGF1dG9tYXRpYyBzdHJpbmcgZGV0ZWN0aW9uXG4iKTsKKwkJcmV0 dXJuIDA7CisJfQorCisJcmMgPSBkZXZtX3JlcXVlc3RfdGhyZWFkZWRfaXJxKHdsZWQtPmRldiwg d2xlZC0+b3ZwX2lycSwgTlVMTCwKKwkJCQkgICAgICAgd2xlZF9vdnBfaXJxX2hhbmRsZXIsIElS UUZfT05FU0hPVCwKKwkJCQkgICAgICAgIndsZWRfb3ZwX2lycSIsIHdsZWQpOworCWlmIChyYyA8 IDApIHsKKwkJZGV2X2Vycih3bGVkLT5kZXYsICJVbmFibGUgdG8gcmVxdWVzdCBvdnBfaXJxIChl cnI6JWQpXG4iLAorCQkJcmMpOworCQl3bGVkLT5vdnBfaXJxID0gMDsKKwkJcmV0dXJuIDA7CisJ fQorCisJcmMgPSByZWdtYXBfcmVhZCh3bGVkLT5yZWdtYXAsIHdsZWQtPmN0cmxfYWRkciArCisJ CQkgV0xFRDNfQ1RSTF9SRUdfTU9EX0VOLCAmdmFsKTsKKwlpZiAocmMgPCAwKQorCQlyZXR1cm4g cmM7CisKKwkvKiBLZWVwIE9WUCBpcnEgZGlzYWJsZWQgdW50aWwgbW9kdWxlIGlzIGVuYWJsZWQg Ki8KKwlpZiAoISh2YWwgJiBXTEVEM19DVFJMX1JFR19NT0RfRU5fTUFTSykpCisJCWRpc2FibGVf aXJxKHdsZWQtPm92cF9pcnEpOworCisJcmV0dXJuIDA7Cit9CisKIHN0YXRpYyBjb25zdCBzdHJ1 Y3QgYmFja2xpZ2h0X29wcyB3bGVkX29wcyA9IHsKIAkudXBkYXRlX3N0YXR1cyA9IHdsZWRfdXBk YXRlX3N0YXR1cywKIH07CkBAIC04MzcsNiArMTIxNiw3IEBAIHN0YXRpYyBpbnQgd2xlZF9wcm9i ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQogCiAJc3dpdGNoICh2ZXJzaW9uKSB7CiAJ Y2FzZSAzOgorCQl3bGVkLT5jZmcuYXV0b19kZXRlY3Rpb25fZW5hYmxlZCA9IGZhbHNlOwogCQly YyA9IHdsZWQzX3NldHVwKHdsZWQpOwogCQlpZiAocmMpIHsKIAkJCWRldl9lcnIoJnBkZXYtPmRl diwgIndsZWQzX3NldHVwIGZhaWxlZFxuIik7CkBAIC04NTgsMTAgKzEyMzgsMTYgQEAgc3RhdGlj IGludCB3bGVkX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCiAJCWJyZWFrOwog CX0KIAorCUlOSVRfREVMQVlFRF9XT1JLKCZ3bGVkLT5vdnBfd29yaywgd2xlZF9vdnBfd29yayk7 CisKIAlyYyA9IHdsZWRfY29uZmlndXJlX3Nob3J0X2lycSh3bGVkLCBwZGV2KTsKIAlpZiAocmMg PCAwKQogCQlyZXR1cm4gcmM7CiAKKwlyYyA9IHdsZWRfY29uZmlndXJlX292cF9pcnEod2xlZCwg cGRldik7CisJaWYgKHJjIDwgMCkKKwkJcmV0dXJuIHJjOworCiAJdmFsID0gV0xFRF9ERUZBVUxU X0JSSUdIVE5FU1M7CiAJb2ZfcHJvcGVydHlfcmVhZF91MzIocGRldi0+ZGV2Lm9mX25vZGUsICJk ZWZhdWx0LWJyaWdodG5lc3MiLCAmdmFsKTsKIApAQCAtODgwLDcgKzEyNjYsOSBAQCBzdGF0aWMg aW50IHdsZWRfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCiAJc3RydWN0IHds ZWQgKndsZWQgPSBkZXZfZ2V0X2RydmRhdGEoJnBkZXYtPmRldik7CiAKIAltdXRleF9kZXN0cm95 KCZ3bGVkLT5sb2NrKTsKKwljYW5jZWxfZGVsYXllZF93b3JrX3N5bmMoJndsZWQtPm92cF93b3Jr KTsKIAlkaXNhYmxlX2lycSh3bGVkLT5zaG9ydF9pcnEpOworCWRpc2FibGVfaXJxKHdsZWQtPm92 cF9pcnEpOwogCiAJcmV0dXJuIDA7CiB9Ci0tIApUaGUgUXVhbGNvbW0gSW5ub3ZhdGlvbiBDZW50 ZXIsIEluYy4gaXMgYSBtZW1iZXIgb2YgdGhlIENvZGUgQXVyb3JhIEZvcnVtLAogYSBMaW51eCBG b3VuZGF0aW9uIENvbGxhYm9yYXRpdmUgUHJvamVjdAoKX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmktZGV2ZWxA bGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxt YW4vbGlzdGluZm8vZHJpLWRldmVs