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=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 58787CA9ECF for ; Fri, 1 Nov 2019 06:28:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2FF0A217D9 for ; Fri, 1 Nov 2019 06:28:18 +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="Y2hcxqs8"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="HmLf5JaG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730023AbfKAG2R (ORCPT ); Fri, 1 Nov 2019 02:28:17 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:46356 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727383AbfKAG2R (ORCPT ); Fri, 1 Nov 2019 02:28:17 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id A25BF60EB7; Fri, 1 Nov 2019 06:28:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589695; bh=VJaggXKkAdhdvmaFJtZWH3RtC9vQplMy8u1lGYxGYTg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y2hcxqs8MyKWxub3aHRhn7jeNU4pymCBuuE/Zp0+kf0bsvZ/9dMvwfSrudwXZOgi+ AJuSjqHwZtvj9gF03zXOsJwSKCn9AVaFwVhAzmn7Wo6mCzL7UKR3/ZfJH5SqO4dJSb 9L46Awqqik9zaMEzjNGptGQLMv8iBfRHrqAqkvFI= 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 1400360EB7; Fri, 1 Nov 2019 06:28:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589691; bh=VJaggXKkAdhdvmaFJtZWH3RtC9vQplMy8u1lGYxGYTg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HmLf5JaGY6YIvpYlkJBtpMfvi6jnTYUra3AgS9InadVmwFMZrTWNjiJp5ZHxlVTpa cquKypffS85HG0OEmQiOA2HIOOElQsZ0ip9qyCcy+Y0lluug6gjYEjyjEJgKBm7UKb gFfWAanxPKgEcTp8ivWNHae7SuIwacDj8GSBkbEM= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 1400360EB7 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 6/8] backlight: qcom-wled: Add support for WLED4 peripheral. Date: Fri, 1 Nov 2019 11:57:02 +0530 Message-Id: <1572589624-6095-7-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 WLED4 peripheral is present on some PMICs like pmi8998 and pm660l. It has a different register map and configurations are also different. Add support for it. Signed-off-by: Kiran Gunda Reviewed-by: Bjorn Andersson Reviewed-by: Daniel Thompson --- drivers/video/backlight/qcom-wled.c | 255 +++++++++++++++++++++++++++++++++++- 1 file changed, 253 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 45eeda4..5386ca9 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -17,7 +17,7 @@ #define WLED3_SINK_REG_BRIGHT_MAX 0xFFF -/* WLED3 control registers */ +/* WLED3/WLED4 control registers */ #define WLED3_CTRL_REG_MOD_EN 0x46 #define WLED3_CTRL_REG_MOD_EN_MASK BIT(7) #define WLED3_CTRL_REG_MOD_EN_SHIFT 7 @@ -31,7 +31,7 @@ #define WLED3_CTRL_REG_ILIMIT 0x4e #define WLED3_CTRL_REG_ILIMIT_MASK GENMASK(2, 0) -/* WLED3 sink registers */ +/* WLED3/WLED4 sink registers */ #define WLED3_SINK_REG_SYNC 0x47 #define WLED3_SINK_REG_SYNC_CLEAR 0x00 @@ -56,6 +56,28 @@ #define WLED3_SINK_REG_STR_CABC(n) (0x66 + (n * 0x10)) #define WLED3_SINK_REG_STR_CABC_MASK BIT(7) +/* WLED4 specific sink registers */ +#define WLED4_SINK_REG_CURR_SINK 0x46 +#define WLED4_SINK_REG_CURR_SINK_MASK GENMASK(7, 4) +#define WLED4_SINK_REG_CURR_SINK_SHFT 4 + +/* WLED4 specific per-'string' registers below */ +#define WLED4_SINK_REG_STR_MOD_EN(n) (0x50 + (n * 0x10)) +#define WLED4_SINK_REG_STR_MOD_MASK BIT(7) + +#define WLED4_SINK_REG_STR_FULL_SCALE_CURR(n) (0x52 + (n * 0x10)) +#define WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK GENMASK(3, 0) + +#define WLED4_SINK_REG_STR_MOD_SRC(n) (0x53 + (n * 0x10)) +#define WLED4_SINK_REG_STR_MOD_SRC_MASK BIT(0) +#define WLED4_SINK_REG_STR_MOD_SRC_INT 0x00 +#define WLED4_SINK_REG_STR_MOD_SRC_EXT 0x01 + +#define WLED4_SINK_REG_STR_CABC(n) (0x56 + (n * 0x10)) +#define WLED4_SINK_REG_STR_CABC_MASK BIT(7) + +#define WLED4_SINK_REG_BRIGHT(n) (0x57 + (n * 0x10)) + struct wled_var_cfg { const u32 *values; u32 (*fn)(u32); @@ -90,6 +112,7 @@ struct wled { struct device *dev; struct regmap *regmap; u16 ctrl_addr; + u16 sink_addr; u16 max_string_count; u32 brightness; u32 max_brightness; @@ -116,6 +139,29 @@ static int wled3_set_brightness(struct wled *wled, u16 brightness) return 0; } +static int wled4_set_brightness(struct wled *wled, u16 brightness) +{ + int rc, i; + u16 low_limit = wled->max_brightness * 4 / 1000; + u8 v[2]; + + /* WLED4's lower limit of operation is 0.4% */ + if (brightness > 0 && brightness < low_limit) + brightness = low_limit; + + v[0] = brightness & 0xff; + v[1] = (brightness >> 8) & 0xf; + + for (i = 0; i < wled->cfg.num_strings; ++i) { + rc = regmap_bulk_write(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_BRIGHT(i), v, 2); + if (rc < 0) + return rc; + } + + return 0; +} + static int wled_module_enable(struct wled *wled, int val) { int rc; @@ -267,6 +313,120 @@ static int wled3_setup(struct wled *wled) .enabled_strings = {0, 1, 2, 3}, }; +static int wled4_setup(struct wled *wled) +{ + int rc, temp, i, j; + u16 addr; + u8 sink_en = 0; + u32 sink_cfg = 0; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_OVP, + WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, + WLED3_CTRL_REG_ILIMIT_MASK, + wled->cfg.boost_i_limit); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_FREQ, + WLED3_CTRL_REG_FREQ_MASK, + wled->cfg.switch_freq); + if (rc < 0) + return rc; + + rc = regmap_read(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_CURR_SINK, &sink_cfg); + if (rc < 0) + return rc; + + for (i = 0; i < wled->cfg.num_strings; i++) { + j = wled->cfg.enabled_strings[i]; + temp = j + WLED4_SINK_REG_CURR_SINK_SHFT; + sink_en |= 1 << temp; + } + + if (sink_cfg == sink_en) + return 0; + + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED4_SINK_REG_CURR_SINK, + WLED4_SINK_REG_CURR_SINK_MASK, 0); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, 0); + if (rc < 0) + return rc; + + /* Per sink/string configuration */ + for (i = 0; i < wled->cfg.num_strings; i++) { + j = wled->cfg.enabled_strings[i]; + + addr = wled->sink_addr + + WLED4_SINK_REG_STR_MOD_EN(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED4_SINK_REG_STR_MOD_MASK, + WLED4_SINK_REG_STR_MOD_MASK); + if (rc < 0) + return rc; + + addr = wled->sink_addr + + WLED4_SINK_REG_STR_FULL_SCALE_CURR(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK, + wled->cfg.string_i_limit); + if (rc < 0) + return rc; + + addr = wled->sink_addr + + WLED4_SINK_REG_STR_CABC(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED4_SINK_REG_STR_CABC_MASK, + wled->cfg.cabc ? + WLED4_SINK_REG_STR_CABC_MASK : 0); + if (rc < 0) + return rc; + } + + 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) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED4_SINK_REG_CURR_SINK, + WLED4_SINK_REG_CURR_SINK_MASK, sink_en); + if (rc < 0) + return rc; + + rc = wled_sync_toggle(wled); + if (rc < 0) { + dev_err(wled->dev, "Failed to toggle sync reg rc:%d\n", rc); + return rc; + } + + return 0; +} + +static const struct wled_config wled4_config_defaults = { + .boost_i_limit = 4, + .string_i_limit = 10, + .ovp = 1, + .num_strings = 4, + .switch_freq = 11, + .cabc = false, +}; + static const u32 wled3_boost_i_limit_values[] = { 105, 385, 525, 805, 980, 1260, 1400, 1680, }; @@ -276,6 +436,15 @@ static int wled3_setup(struct wled *wled) .size = ARRAY_SIZE(wled3_boost_i_limit_values), }; +static const u32 wled4_boost_i_limit_values[] = { + 105, 280, 450, 620, 970, 1150, 1300, 1500, +}; + +static const struct wled_var_cfg wled4_boost_i_limit_cfg = { + .values = wled4_boost_i_limit_values, + .size = ARRAY_SIZE(wled4_boost_i_limit_values), +}; + static const u32 wled3_ovp_values[] = { 35, 32, 29, 27, }; @@ -285,6 +454,15 @@ static int wled3_setup(struct wled *wled) .size = ARRAY_SIZE(wled3_ovp_values), }; +static const u32 wled4_ovp_values[] = { + 31100, 29600, 19600, 18100, +}; + +static const struct wled_var_cfg wled4_ovp_cfg = { + .values = wled4_ovp_values, + .size = ARRAY_SIZE(wled4_ovp_values), +}; + static u32 wled3_num_strings_values_fn(u32 idx) { return idx + 1; @@ -295,6 +473,11 @@ static u32 wled3_num_strings_values_fn(u32 idx) .size = 3, }; +static const struct wled_var_cfg wled4_num_strings_cfg = { + .fn = wled3_num_strings_values_fn, + .size = 4, +}; + static u32 wled3_switch_freq_values_fn(u32 idx) { return 19200 / (2 * (1 + idx)); @@ -309,10 +492,24 @@ static u32 wled3_switch_freq_values_fn(u32 idx) .size = 26, }; +static const u32 wled4_string_i_limit_values[] = { + 0, 2500, 5000, 7500, 10000, 12500, 15000, 17500, 20000, + 22500, 25000, 27500, 30000, +}; + +static const struct wled_var_cfg wled4_string_i_limit_cfg = { + .values = wled4_string_i_limit_values, + .size = ARRAY_SIZE(wled4_string_i_limit_values), +}; + static const struct wled_var_cfg wled3_string_cfg = { .size = 8, }; +static const struct wled_var_cfg wled4_string_cfg = { + .size = 16, +}; + static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx) { if (idx >= cfg->size) @@ -361,6 +558,34 @@ static int wled_configure(struct wled *wled, int version) }, }; + const struct wled_u32_opts wled4_opts[] = { + { + .name = "qcom,current-boost-limit", + .val_ptr = &cfg->boost_i_limit, + .cfg = &wled4_boost_i_limit_cfg, + }, + { + .name = "qcom,current-limit-microamp", + .val_ptr = &cfg->string_i_limit, + .cfg = &wled4_string_i_limit_cfg, + }, + { + .name = "qcom,ovp-millivolt", + .val_ptr = &cfg->ovp, + .cfg = &wled4_ovp_cfg, + }, + { + .name = "qcom,switching-freq", + .val_ptr = &cfg->switch_freq, + .cfg = &wled3_switch_freq_cfg, + }, + { + .name = "qcom,num-strings", + .val_ptr = &cfg->num_strings, + .cfg = &wled4_num_strings_cfg, + }, + }; + const struct wled_bool_opts bool_opts[] = { { "qcom,cs-out", &cfg->cs_out_en, }, { "qcom,ext-gen", &cfg->ext_gen, }, @@ -385,6 +610,22 @@ static int wled_configure(struct wled *wled, int version) *cfg = wled3_config_defaults; wled->wled_set_brightness = wled3_set_brightness; wled->max_string_count = 3; + wled->sink_addr = wled->ctrl_addr; + break; + + case 4: + u32_opts = wled4_opts; + size = ARRAY_SIZE(wled4_opts); + *cfg = wled4_config_defaults; + wled->wled_set_brightness = wled4_set_brightness; + wled->max_string_count = 4; + + prop_addr = of_get_address(dev->of_node, 1, NULL, NULL); + if (!prop_addr) { + dev_err(wled->dev, "invalid IO resources\n"); + return -EINVAL; + } + wled->sink_addr = be32_to_cpu(*prop_addr); break; default: @@ -483,6 +724,14 @@ static int wled_probe(struct platform_device *pdev) } break; + case 4: + rc = wled4_setup(wled); + if (rc) { + dev_err(&pdev->dev, "wled4_setup failed\n"); + return rc; + } + break; + default: dev_err(wled->dev, "Invalid WLED version\n"); break; @@ -503,6 +752,8 @@ static int wled_probe(struct platform_device *pdev) static const struct of_device_id wled_match_table[] = { { .compatible = "qcom,pm8941-wled", .data = (void *)3 }, + { .compatible = "qcom,pmi8998-wled", .data = (void *)4 }, + { .compatible = "qcom,pm660l-wled", .data = (void *)4 }, {} }; MODULE_DEVICE_TABLE(of, wled_match_table); -- 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:02 +0000 Subject: [PATCH V10 6/8] backlight: qcom-wled: Add support for WLED4 peripheral. Message-Id: <1572589624-6095-7-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 WLED4 peripheral is present on some PMICs like pmi8998 and pm660l. It has a different register map and configurations are also different. Add support for it. Signed-off-by: Kiran Gunda Reviewed-by: Bjorn Andersson Reviewed-by: Daniel Thompson --- drivers/video/backlight/qcom-wled.c | 255 +++++++++++++++++++++++++++++++++++- 1 file changed, 253 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 45eeda4..5386ca9 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -17,7 +17,7 @@ #define WLED3_SINK_REG_BRIGHT_MAX 0xFFF -/* WLED3 control registers */ +/* WLED3/WLED4 control registers */ #define WLED3_CTRL_REG_MOD_EN 0x46 #define WLED3_CTRL_REG_MOD_EN_MASK BIT(7) #define WLED3_CTRL_REG_MOD_EN_SHIFT 7 @@ -31,7 +31,7 @@ #define WLED3_CTRL_REG_ILIMIT 0x4e #define WLED3_CTRL_REG_ILIMIT_MASK GENMASK(2, 0) -/* WLED3 sink registers */ +/* WLED3/WLED4 sink registers */ #define WLED3_SINK_REG_SYNC 0x47 #define WLED3_SINK_REG_SYNC_CLEAR 0x00 @@ -56,6 +56,28 @@ #define WLED3_SINK_REG_STR_CABC(n) (0x66 + (n * 0x10)) #define WLED3_SINK_REG_STR_CABC_MASK BIT(7) +/* WLED4 specific sink registers */ +#define WLED4_SINK_REG_CURR_SINK 0x46 +#define WLED4_SINK_REG_CURR_SINK_MASK GENMASK(7, 4) +#define WLED4_SINK_REG_CURR_SINK_SHFT 4 + +/* WLED4 specific per-'string' registers below */ +#define WLED4_SINK_REG_STR_MOD_EN(n) (0x50 + (n * 0x10)) +#define WLED4_SINK_REG_STR_MOD_MASK BIT(7) + +#define WLED4_SINK_REG_STR_FULL_SCALE_CURR(n) (0x52 + (n * 0x10)) +#define WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK GENMASK(3, 0) + +#define WLED4_SINK_REG_STR_MOD_SRC(n) (0x53 + (n * 0x10)) +#define WLED4_SINK_REG_STR_MOD_SRC_MASK BIT(0) +#define WLED4_SINK_REG_STR_MOD_SRC_INT 0x00 +#define WLED4_SINK_REG_STR_MOD_SRC_EXT 0x01 + +#define WLED4_SINK_REG_STR_CABC(n) (0x56 + (n * 0x10)) +#define WLED4_SINK_REG_STR_CABC_MASK BIT(7) + +#define WLED4_SINK_REG_BRIGHT(n) (0x57 + (n * 0x10)) + struct wled_var_cfg { const u32 *values; u32 (*fn)(u32); @@ -90,6 +112,7 @@ struct wled { struct device *dev; struct regmap *regmap; u16 ctrl_addr; + u16 sink_addr; u16 max_string_count; u32 brightness; u32 max_brightness; @@ -116,6 +139,29 @@ static int wled3_set_brightness(struct wled *wled, u16 brightness) return 0; } +static int wled4_set_brightness(struct wled *wled, u16 brightness) +{ + int rc, i; + u16 low_limit = wled->max_brightness * 4 / 1000; + u8 v[2]; + + /* WLED4's lower limit of operation is 0.4% */ + if (brightness > 0 && brightness < low_limit) + brightness = low_limit; + + v[0] = brightness & 0xff; + v[1] = (brightness >> 8) & 0xf; + + for (i = 0; i < wled->cfg.num_strings; ++i) { + rc = regmap_bulk_write(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_BRIGHT(i), v, 2); + if (rc < 0) + return rc; + } + + return 0; +} + static int wled_module_enable(struct wled *wled, int val) { int rc; @@ -267,6 +313,120 @@ static int wled3_setup(struct wled *wled) .enabled_strings = {0, 1, 2, 3}, }; +static int wled4_setup(struct wled *wled) +{ + int rc, temp, i, j; + u16 addr; + u8 sink_en = 0; + u32 sink_cfg = 0; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_OVP, + WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, + WLED3_CTRL_REG_ILIMIT_MASK, + wled->cfg.boost_i_limit); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_CTRL_REG_FREQ, + WLED3_CTRL_REG_FREQ_MASK, + wled->cfg.switch_freq); + if (rc < 0) + return rc; + + rc = regmap_read(wled->regmap, wled->sink_addr + + WLED4_SINK_REG_CURR_SINK, &sink_cfg); + if (rc < 0) + return rc; + + for (i = 0; i < wled->cfg.num_strings; i++) { + j = wled->cfg.enabled_strings[i]; + temp = j + WLED4_SINK_REG_CURR_SINK_SHFT; + sink_en |= 1 << temp; + } + + if (sink_cfg = sink_en) + return 0; + + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED4_SINK_REG_CURR_SINK, + WLED4_SINK_REG_CURR_SINK_MASK, 0); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, 0); + if (rc < 0) + return rc; + + /* Per sink/string configuration */ + for (i = 0; i < wled->cfg.num_strings; i++) { + j = wled->cfg.enabled_strings[i]; + + addr = wled->sink_addr + + WLED4_SINK_REG_STR_MOD_EN(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED4_SINK_REG_STR_MOD_MASK, + WLED4_SINK_REG_STR_MOD_MASK); + if (rc < 0) + return rc; + + addr = wled->sink_addr + + WLED4_SINK_REG_STR_FULL_SCALE_CURR(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK, + wled->cfg.string_i_limit); + if (rc < 0) + return rc; + + addr = wled->sink_addr + + WLED4_SINK_REG_STR_CABC(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED4_SINK_REG_STR_CABC_MASK, + wled->cfg.cabc ? + WLED4_SINK_REG_STR_CABC_MASK : 0); + if (rc < 0) + return rc; + } + + 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) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED4_SINK_REG_CURR_SINK, + WLED4_SINK_REG_CURR_SINK_MASK, sink_en); + if (rc < 0) + return rc; + + rc = wled_sync_toggle(wled); + if (rc < 0) { + dev_err(wled->dev, "Failed to toggle sync reg rc:%d\n", rc); + return rc; + } + + return 0; +} + +static const struct wled_config wled4_config_defaults = { + .boost_i_limit = 4, + .string_i_limit = 10, + .ovp = 1, + .num_strings = 4, + .switch_freq = 11, + .cabc = false, +}; + static const u32 wled3_boost_i_limit_values[] = { 105, 385, 525, 805, 980, 1260, 1400, 1680, }; @@ -276,6 +436,15 @@ static int wled3_setup(struct wled *wled) .size = ARRAY_SIZE(wled3_boost_i_limit_values), }; +static const u32 wled4_boost_i_limit_values[] = { + 105, 280, 450, 620, 970, 1150, 1300, 1500, +}; + +static const struct wled_var_cfg wled4_boost_i_limit_cfg = { + .values = wled4_boost_i_limit_values, + .size = ARRAY_SIZE(wled4_boost_i_limit_values), +}; + static const u32 wled3_ovp_values[] = { 35, 32, 29, 27, }; @@ -285,6 +454,15 @@ static int wled3_setup(struct wled *wled) .size = ARRAY_SIZE(wled3_ovp_values), }; +static const u32 wled4_ovp_values[] = { + 31100, 29600, 19600, 18100, +}; + +static const struct wled_var_cfg wled4_ovp_cfg = { + .values = wled4_ovp_values, + .size = ARRAY_SIZE(wled4_ovp_values), +}; + static u32 wled3_num_strings_values_fn(u32 idx) { return idx + 1; @@ -295,6 +473,11 @@ static u32 wled3_num_strings_values_fn(u32 idx) .size = 3, }; +static const struct wled_var_cfg wled4_num_strings_cfg = { + .fn = wled3_num_strings_values_fn, + .size = 4, +}; + static u32 wled3_switch_freq_values_fn(u32 idx) { return 19200 / (2 * (1 + idx)); @@ -309,10 +492,24 @@ static u32 wled3_switch_freq_values_fn(u32 idx) .size = 26, }; +static const u32 wled4_string_i_limit_values[] = { + 0, 2500, 5000, 7500, 10000, 12500, 15000, 17500, 20000, + 22500, 25000, 27500, 30000, +}; + +static const struct wled_var_cfg wled4_string_i_limit_cfg = { + .values = wled4_string_i_limit_values, + .size = ARRAY_SIZE(wled4_string_i_limit_values), +}; + static const struct wled_var_cfg wled3_string_cfg = { .size = 8, }; +static const struct wled_var_cfg wled4_string_cfg = { + .size = 16, +}; + static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx) { if (idx >= cfg->size) @@ -361,6 +558,34 @@ static int wled_configure(struct wled *wled, int version) }, }; + const struct wled_u32_opts wled4_opts[] = { + { + .name = "qcom,current-boost-limit", + .val_ptr = &cfg->boost_i_limit, + .cfg = &wled4_boost_i_limit_cfg, + }, + { + .name = "qcom,current-limit-microamp", + .val_ptr = &cfg->string_i_limit, + .cfg = &wled4_string_i_limit_cfg, + }, + { + .name = "qcom,ovp-millivolt", + .val_ptr = &cfg->ovp, + .cfg = &wled4_ovp_cfg, + }, + { + .name = "qcom,switching-freq", + .val_ptr = &cfg->switch_freq, + .cfg = &wled3_switch_freq_cfg, + }, + { + .name = "qcom,num-strings", + .val_ptr = &cfg->num_strings, + .cfg = &wled4_num_strings_cfg, + }, + }; + const struct wled_bool_opts bool_opts[] = { { "qcom,cs-out", &cfg->cs_out_en, }, { "qcom,ext-gen", &cfg->ext_gen, }, @@ -385,6 +610,22 @@ static int wled_configure(struct wled *wled, int version) *cfg = wled3_config_defaults; wled->wled_set_brightness = wled3_set_brightness; wled->max_string_count = 3; + wled->sink_addr = wled->ctrl_addr; + break; + + case 4: + u32_opts = wled4_opts; + size = ARRAY_SIZE(wled4_opts); + *cfg = wled4_config_defaults; + wled->wled_set_brightness = wled4_set_brightness; + wled->max_string_count = 4; + + prop_addr = of_get_address(dev->of_node, 1, NULL, NULL); + if (!prop_addr) { + dev_err(wled->dev, "invalid IO resources\n"); + return -EINVAL; + } + wled->sink_addr = be32_to_cpu(*prop_addr); break; default: @@ -483,6 +724,14 @@ static int wled_probe(struct platform_device *pdev) } break; + case 4: + rc = wled4_setup(wled); + if (rc) { + dev_err(&pdev->dev, "wled4_setup failed\n"); + return rc; + } + break; + default: dev_err(wled->dev, "Invalid WLED version\n"); break; @@ -503,6 +752,8 @@ static int wled_probe(struct platform_device *pdev) static const struct of_device_id wled_match_table[] = { { .compatible = "qcom,pm8941-wled", .data = (void *)3 }, + { .compatible = "qcom,pmi8998-wled", .data = (void *)4 }, + { .compatible = "qcom,pm660l-wled", .data = (void *)4 }, {} }; MODULE_DEVICE_TABLE(of, wled_match_table); -- 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 7A3D3CA9EC9 for ; Fri, 1 Nov 2019 08:10:06 +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 51FD7208E3 for ; Fri, 1 Nov 2019 08:10:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 51FD7208E3 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 937A46F754; Fri, 1 Nov 2019 08:09:56 +0000 (UTC) Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.29.96]) by gabe.freedesktop.org (Postfix) with ESMTPS id 96C286F6DF for ; Fri, 1 Nov 2019 06:28:15 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 64FEE60F36; Fri, 1 Nov 2019 06:28:15 +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 1400360EB7; Fri, 1 Nov 2019 06:28:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 1400360EB7 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 6/8] backlight: qcom-wled: Add support for WLED4 peripheral. Date: Fri, 1 Nov 2019 11:57:02 +0530 Message-Id: <1572589624-6095-7-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=1572589695; bh=VJaggXKkAdhdvmaFJtZWH3RtC9vQplMy8u1lGYxGYTg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y2hcxqs8MyKWxub3aHRhn7jeNU4pymCBuuE/Zp0+kf0bsvZ/9dMvwfSrudwXZOgi+ AJuSjqHwZtvj9gF03zXOsJwSKCn9AVaFwVhAzmn7Wo6mCzL7UKR3/ZfJH5SqO4dJSb 9L46Awqqik9zaMEzjNGptGQLMv8iBfRHrqAqkvFI= X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589691; bh=VJaggXKkAdhdvmaFJtZWH3RtC9vQplMy8u1lGYxGYTg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HmLf5JaGY6YIvpYlkJBtpMfvi6jnTYUra3AgS9InadVmwFMZrTWNjiJp5ZHxlVTpa cquKypffS85HG0OEmQiOA2HIOOElQsZ0ip9qyCcy+Y0lluug6gjYEjyjEJgKBm7UKb gFfWAanxPKgEcTp8ivWNHae7SuIwacDj8GSBkbEM= 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: <20191101062702.heax_K0x557GmFq3C7WEjiLNH9TtGKd73_M9u-Prq1s@z> V0xFRDQgcGVyaXBoZXJhbCBpcyBwcmVzZW50IG9uIHNvbWUgUE1JQ3MgbGlrZSBwbWk4OTk4IGFu ZApwbTY2MGwuIEl0IGhhcyBhIGRpZmZlcmVudCByZWdpc3RlciBtYXAgYW5kIGNvbmZpZ3VyYXRp b25zCmFyZSBhbHNvIGRpZmZlcmVudC4gQWRkIHN1cHBvcnQgZm9yIGl0LgoKU2lnbmVkLW9mZi1i eTogS2lyYW4gR3VuZGEgPGtndW5kYUBjb2RlYXVyb3JhLm9yZz4KUmV2aWV3ZWQtYnk6IEJqb3Ju IEFuZGVyc3NvbiA8Ympvcm4uYW5kZXJzc29uQGxpbmFyby5vcmc+ClJldmlld2VkLWJ5OiBEYW5p ZWwgVGhvbXBzb24gPGRhbmllbC50aG9tcHNvbkBsaW5hcm8ub3JnPgotLS0KIGRyaXZlcnMvdmlk ZW8vYmFja2xpZ2h0L3Fjb20td2xlZC5jIHwgMjU1ICsrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrLQogMSBmaWxlIGNoYW5nZWQsIDI1MyBpbnNlcnRpb25zKCspLCAyIGRlbGV0aW9u cygtKQoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvdmlkZW8vYmFja2xpZ2h0L3Fjb20td2xlZC5jIGIv ZHJpdmVycy92aWRlby9iYWNrbGlnaHQvcWNvbS13bGVkLmMKaW5kZXggNDVlZWRhNC4uNTM4NmNh OSAxMDA2NDQKLS0tIGEvZHJpdmVycy92aWRlby9iYWNrbGlnaHQvcWNvbS13bGVkLmMKKysrIGIv ZHJpdmVycy92aWRlby9iYWNrbGlnaHQvcWNvbS13bGVkLmMKQEAgLTE3LDcgKzE3LDcgQEAKIAog I2RlZmluZSBXTEVEM19TSU5LX1JFR19CUklHSFRfTUFYCQkJMHhGRkYKIAotLyogV0xFRDMgY29u dHJvbCByZWdpc3RlcnMgKi8KKy8qIFdMRUQzL1dMRUQ0IGNvbnRyb2wgcmVnaXN0ZXJzICovCiAj ZGVmaW5lIFdMRUQzX0NUUkxfUkVHX01PRF9FTgkJCQkweDQ2CiAjZGVmaW5lICBXTEVEM19DVFJM X1JFR19NT0RfRU5fTUFTSwkJCUJJVCg3KQogI2RlZmluZSAgV0xFRDNfQ1RSTF9SRUdfTU9EX0VO X1NISUZUCQkJNwpAQCAtMzEsNyArMzEsNyBAQAogI2RlZmluZSBXTEVEM19DVFJMX1JFR19JTElN SVQJCQkJMHg0ZQogI2RlZmluZSAgV0xFRDNfQ1RSTF9SRUdfSUxJTUlUX01BU0sJCQlHRU5NQVNL KDIsIDApCiAKLS8qIFdMRUQzIHNpbmsgcmVnaXN0ZXJzICovCisvKiBXTEVEMy9XTEVENCBzaW5r IHJlZ2lzdGVycyAqLwogI2RlZmluZSBXTEVEM19TSU5LX1JFR19TWU5DCQkJCTB4NDcKICNkZWZp bmUgIFdMRUQzX1NJTktfUkVHX1NZTkNfQ0xFQVIJCQkweDAwCiAKQEAgLTU2LDYgKzU2LDI4IEBA CiAjZGVmaW5lIFdMRUQzX1NJTktfUkVHX1NUUl9DQUJDKG4pCQkJKDB4NjYgKyAobiAqIDB4MTAp KQogI2RlZmluZSAgV0xFRDNfU0lOS19SRUdfU1RSX0NBQkNfTUFTSwkJCUJJVCg3KQogCisvKiBX TEVENCBzcGVjaWZpYyBzaW5rIHJlZ2lzdGVycyAqLworI2RlZmluZSBXTEVENF9TSU5LX1JFR19D VVJSX1NJTksJCQkweDQ2CisjZGVmaW5lICBXTEVENF9TSU5LX1JFR19DVVJSX1NJTktfTUFTSwkJ CUdFTk1BU0soNywgNCkKKyNkZWZpbmUgIFdMRUQ0X1NJTktfUkVHX0NVUlJfU0lOS19TSEZUCQkJ NAorCisvKiBXTEVENCBzcGVjaWZpYyBwZXItJ3N0cmluZycgcmVnaXN0ZXJzIGJlbG93ICovCisj ZGVmaW5lIFdMRUQ0X1NJTktfUkVHX1NUUl9NT0RfRU4obikJCQkoMHg1MCArIChuICogMHgxMCkp CisjZGVmaW5lICBXTEVENF9TSU5LX1JFR19TVFJfTU9EX01BU0sJCQlCSVQoNykKKworI2RlZmlu ZSBXTEVENF9TSU5LX1JFR19TVFJfRlVMTF9TQ0FMRV9DVVJSKG4pCQkoMHg1MiArIChuICogMHgx MCkpCisjZGVmaW5lICBXTEVENF9TSU5LX1JFR19TVFJfRlVMTF9TQ0FMRV9DVVJSX01BU0sJR0VO TUFTSygzLCAwKQorCisjZGVmaW5lIFdMRUQ0X1NJTktfUkVHX1NUUl9NT0RfU1JDKG4pCQkJKDB4 NTMgKyAobiAqIDB4MTApKQorI2RlZmluZSAgV0xFRDRfU0lOS19SRUdfU1RSX01PRF9TUkNfTUFT SwkJQklUKDApCisjZGVmaW5lICBXTEVENF9TSU5LX1JFR19TVFJfTU9EX1NSQ19JTlQJCQkweDAw CisjZGVmaW5lICBXTEVENF9TSU5LX1JFR19TVFJfTU9EX1NSQ19FWFQJCQkweDAxCisKKyNkZWZp bmUgV0xFRDRfU0lOS19SRUdfU1RSX0NBQkMobikJCQkoMHg1NiArIChuICogMHgxMCkpCisjZGVm aW5lICBXTEVENF9TSU5LX1JFR19TVFJfQ0FCQ19NQVNLCQkJQklUKDcpCisKKyNkZWZpbmUgV0xF RDRfU0lOS19SRUdfQlJJR0hUKG4pCQkJKDB4NTcgKyAobiAqIDB4MTApKQorCiBzdHJ1Y3Qgd2xl ZF92YXJfY2ZnIHsKIAljb25zdCB1MzIgKnZhbHVlczsKIAl1MzIgKCpmbikodTMyKTsKQEAgLTkw LDYgKzExMiw3IEBAIHN0cnVjdCB3bGVkIHsKIAlzdHJ1Y3QgZGV2aWNlICpkZXY7CiAJc3RydWN0 IHJlZ21hcCAqcmVnbWFwOwogCXUxNiBjdHJsX2FkZHI7CisJdTE2IHNpbmtfYWRkcjsKIAl1MTYg bWF4X3N0cmluZ19jb3VudDsKIAl1MzIgYnJpZ2h0bmVzczsKIAl1MzIgbWF4X2JyaWdodG5lc3M7 CkBAIC0xMTYsNiArMTM5LDI5IEBAIHN0YXRpYyBpbnQgd2xlZDNfc2V0X2JyaWdodG5lc3Moc3Ry dWN0IHdsZWQgKndsZWQsIHUxNiBicmlnaHRuZXNzKQogCXJldHVybiAwOwogfQogCitzdGF0aWMg aW50IHdsZWQ0X3NldF9icmlnaHRuZXNzKHN0cnVjdCB3bGVkICp3bGVkLCB1MTYgYnJpZ2h0bmVz cykKK3sKKwlpbnQgcmMsIGk7CisJdTE2IGxvd19saW1pdCA9IHdsZWQtPm1heF9icmlnaHRuZXNz ICogNCAvIDEwMDA7CisJdTggdlsyXTsKKworCS8qIFdMRUQ0J3MgbG93ZXIgbGltaXQgb2Ygb3Bl cmF0aW9uIGlzIDAuNCUgKi8KKwlpZiAoYnJpZ2h0bmVzcyA+IDAgJiYgYnJpZ2h0bmVzcyA8IGxv d19saW1pdCkKKwkJYnJpZ2h0bmVzcyA9IGxvd19saW1pdDsKKworCXZbMF0gPSBicmlnaHRuZXNz ICYgMHhmZjsKKwl2WzFdID0gKGJyaWdodG5lc3MgPj4gOCkgJiAweGY7CisKKwlmb3IgKGkgPSAw OyAgaSA8IHdsZWQtPmNmZy5udW1fc3RyaW5nczsgKytpKSB7CisJCXJjID0gcmVnbWFwX2J1bGtf d3JpdGUod2xlZC0+cmVnbWFwLCB3bGVkLT5zaW5rX2FkZHIgKworCQkJCSAgICAgICBXTEVENF9T SU5LX1JFR19CUklHSFQoaSksIHYsIDIpOworCQlpZiAocmMgPCAwKQorCQkJcmV0dXJuIHJjOwor CX0KKworCXJldHVybiAwOworfQorCiBzdGF0aWMgaW50IHdsZWRfbW9kdWxlX2VuYWJsZShzdHJ1 Y3Qgd2xlZCAqd2xlZCwgaW50IHZhbCkKIHsKIAlpbnQgcmM7CkBAIC0yNjcsNiArMzEzLDEyMCBA QCBzdGF0aWMgaW50IHdsZWQzX3NldHVwKHN0cnVjdCB3bGVkICp3bGVkKQogCS5lbmFibGVkX3N0 cmluZ3MgPSB7MCwgMSwgMiwgM30sCiB9OwogCitzdGF0aWMgaW50IHdsZWQ0X3NldHVwKHN0cnVj dCB3bGVkICp3bGVkKQoreworCWludCByYywgdGVtcCwgaSwgajsKKwl1MTYgYWRkcjsKKwl1OCBz aW5rX2VuID0gMDsKKwl1MzIgc2lua19jZmcgPSAwOworCisJcmMgPSByZWdtYXBfdXBkYXRlX2Jp dHMod2xlZC0+cmVnbWFwLAorCQkJCXdsZWQtPmN0cmxfYWRkciArIFdMRUQzX0NUUkxfUkVHX09W UCwKKwkJCQlXTEVEM19DVFJMX1JFR19PVlBfTUFTSywgd2xlZC0+Y2ZnLm92cCk7CisJaWYgKHJj IDwgMCkKKwkJcmV0dXJuIHJjOworCisJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVn bWFwLAorCQkJCXdsZWQtPmN0cmxfYWRkciArIFdMRUQzX0NUUkxfUkVHX0lMSU1JVCwKKwkJCQlX TEVEM19DVFJMX1JFR19JTElNSVRfTUFTSywKKwkJCQl3bGVkLT5jZmcuYm9vc3RfaV9saW1pdCk7 CisJaWYgKHJjIDwgMCkKKwkJcmV0dXJuIHJjOworCisJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMo d2xlZC0+cmVnbWFwLAorCQkJCXdsZWQtPmN0cmxfYWRkciArIFdMRUQzX0NUUkxfUkVHX0ZSRVEs CisJCQkJV0xFRDNfQ1RSTF9SRUdfRlJFUV9NQVNLLAorCQkJCXdsZWQtPmNmZy5zd2l0Y2hfZnJl cSk7CisJaWYgKHJjIDwgMCkKKwkJcmV0dXJuIHJjOworCisJcmMgPSByZWdtYXBfcmVhZCh3bGVk LT5yZWdtYXAsIHdsZWQtPnNpbmtfYWRkciArCisJCQkgV0xFRDRfU0lOS19SRUdfQ1VSUl9TSU5L LCAmc2lua19jZmcpOworCWlmIChyYyA8IDApCisJCXJldHVybiByYzsKKworCWZvciAoaSA9IDA7 IGkgPCB3bGVkLT5jZmcubnVtX3N0cmluZ3M7IGkrKykgeworCQlqID0gd2xlZC0+Y2ZnLmVuYWJs ZWRfc3RyaW5nc1tpXTsKKwkJdGVtcCA9IGogKyBXTEVENF9TSU5LX1JFR19DVVJSX1NJTktfU0hG VDsKKwkJc2lua19lbiB8PSAxIDw8IHRlbXA7CisJfQorCisJaWYgKHNpbmtfY2ZnID09IHNpbmtf ZW4pCisJCXJldHVybiAwOworCisJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFw LAorCQkJCXdsZWQtPnNpbmtfYWRkciArIFdMRUQ0X1NJTktfUkVHX0NVUlJfU0lOSywKKwkJCQlX TEVENF9TSU5LX1JFR19DVVJSX1NJTktfTUFTSywgMCk7CisJaWYgKHJjIDwgMCkKKwkJcmV0dXJu IHJjOworCisJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLCB3bGVkLT5jdHJs X2FkZHIgKworCQkJCVdMRUQzX0NUUkxfUkVHX01PRF9FTiwKKwkJCQlXTEVEM19DVFJMX1JFR19N T0RfRU5fTUFTSywgMCk7CisJaWYgKHJjIDwgMCkKKwkJcmV0dXJuIHJjOworCisJLyogUGVyIHNp bmsvc3RyaW5nIGNvbmZpZ3VyYXRpb24gKi8KKwlmb3IgKGkgPSAwOyBpIDwgd2xlZC0+Y2ZnLm51 bV9zdHJpbmdzOyBpKyspIHsKKwkJaiA9IHdsZWQtPmNmZy5lbmFibGVkX3N0cmluZ3NbaV07CisK KwkJYWRkciA9IHdsZWQtPnNpbmtfYWRkciArCisJCQkJV0xFRDRfU0lOS19SRUdfU1RSX01PRF9F TihqKTsKKwkJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLCBhZGRyLAorCQkJ CQlXTEVENF9TSU5LX1JFR19TVFJfTU9EX01BU0ssCisJCQkJCVdMRUQ0X1NJTktfUkVHX1NUUl9N T0RfTUFTSyk7CisJCWlmIChyYyA8IDApCisJCQlyZXR1cm4gcmM7CisKKwkJYWRkciA9IHdsZWQt PnNpbmtfYWRkciArCisJCQkJV0xFRDRfU0lOS19SRUdfU1RSX0ZVTExfU0NBTEVfQ1VSUihqKTsK KwkJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLCBhZGRyLAorCQkJCQlXTEVE NF9TSU5LX1JFR19TVFJfRlVMTF9TQ0FMRV9DVVJSX01BU0ssCisJCQkJCXdsZWQtPmNmZy5zdHJp bmdfaV9saW1pdCk7CisJCWlmIChyYyA8IDApCisJCQlyZXR1cm4gcmM7CisKKwkJYWRkciA9IHds ZWQtPnNpbmtfYWRkciArCisJCQkJV0xFRDRfU0lOS19SRUdfU1RSX0NBQkMoaik7CisJCXJjID0g cmVnbWFwX3VwZGF0ZV9iaXRzKHdsZWQtPnJlZ21hcCwgYWRkciwKKwkJCQkJV0xFRDRfU0lOS19S RUdfU1RSX0NBQkNfTUFTSywKKwkJCQkJd2xlZC0+Y2ZnLmNhYmMgPworCQkJCQlXTEVENF9TSU5L X1JFR19TVFJfQ0FCQ19NQVNLIDogMCk7CisJCWlmIChyYyA8IDApCisJCQlyZXR1cm4gcmM7CisJ fQorCisJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLCB3bGVkLT5jdHJsX2Fk ZHIgKworCQkJCVdMRUQzX0NUUkxfUkVHX01PRF9FTiwKKwkJCQlXTEVEM19DVFJMX1JFR19NT0Rf RU5fTUFTSywKKwkJCQlXTEVEM19DVFJMX1JFR19NT0RfRU5fTUFTSyk7CisJaWYgKHJjIDwgMCkK KwkJcmV0dXJuIHJjOworCisJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLAor CQkJCXdsZWQtPnNpbmtfYWRkciArIFdMRUQ0X1NJTktfUkVHX0NVUlJfU0lOSywKKwkJCQlXTEVE NF9TSU5LX1JFR19DVVJSX1NJTktfTUFTSywgc2lua19lbik7CisJaWYgKHJjIDwgMCkKKwkJcmV0 dXJuIHJjOworCisJcmMgPSB3bGVkX3N5bmNfdG9nZ2xlKHdsZWQpOworCWlmIChyYyA8IDApIHsK KwkJZGV2X2Vycih3bGVkLT5kZXYsICJGYWlsZWQgdG8gdG9nZ2xlIHN5bmMgcmVnIHJjOiVkXG4i LCByYyk7CisJCXJldHVybiByYzsKKwl9CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGNvbnN0 IHN0cnVjdCB3bGVkX2NvbmZpZyB3bGVkNF9jb25maWdfZGVmYXVsdHMgPSB7CisJLmJvb3N0X2lf bGltaXQgPSA0LAorCS5zdHJpbmdfaV9saW1pdCA9IDEwLAorCS5vdnAgPSAxLAorCS5udW1fc3Ry aW5ncyA9IDQsCisJLnN3aXRjaF9mcmVxID0gMTEsCisJLmNhYmMgPSBmYWxzZSwKK307CisKIHN0 YXRpYyBjb25zdCB1MzIgd2xlZDNfYm9vc3RfaV9saW1pdF92YWx1ZXNbXSA9IHsKIAkxMDUsIDM4 NSwgNTI1LCA4MDUsIDk4MCwgMTI2MCwgMTQwMCwgMTY4MCwKIH07CkBAIC0yNzYsNiArNDM2LDE1 IEBAIHN0YXRpYyBpbnQgd2xlZDNfc2V0dXAoc3RydWN0IHdsZWQgKndsZWQpCiAJLnNpemUgPSBB UlJBWV9TSVpFKHdsZWQzX2Jvb3N0X2lfbGltaXRfdmFsdWVzKSwKIH07CiAKK3N0YXRpYyBjb25z dCB1MzIgd2xlZDRfYm9vc3RfaV9saW1pdF92YWx1ZXNbXSA9IHsKKwkxMDUsIDI4MCwgNDUwLCA2 MjAsIDk3MCwgMTE1MCwgMTMwMCwgMTUwMCwKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgd2xl ZF92YXJfY2ZnIHdsZWQ0X2Jvb3N0X2lfbGltaXRfY2ZnID0geworCS52YWx1ZXMgPSB3bGVkNF9i b29zdF9pX2xpbWl0X3ZhbHVlcywKKwkuc2l6ZSA9IEFSUkFZX1NJWkUod2xlZDRfYm9vc3RfaV9s aW1pdF92YWx1ZXMpLAorfTsKKwogc3RhdGljIGNvbnN0IHUzMiB3bGVkM19vdnBfdmFsdWVzW10g PSB7CiAJMzUsIDMyLCAyOSwgMjcsCiB9OwpAQCAtMjg1LDYgKzQ1NCwxNSBAQCBzdGF0aWMgaW50 IHdsZWQzX3NldHVwKHN0cnVjdCB3bGVkICp3bGVkKQogCS5zaXplID0gQVJSQVlfU0laRSh3bGVk M19vdnBfdmFsdWVzKSwKIH07CiAKK3N0YXRpYyBjb25zdCB1MzIgd2xlZDRfb3ZwX3ZhbHVlc1td ID0geworCTMxMTAwLCAyOTYwMCwgMTk2MDAsIDE4MTAwLAorfTsKKworc3RhdGljIGNvbnN0IHN0 cnVjdCB3bGVkX3Zhcl9jZmcgd2xlZDRfb3ZwX2NmZyA9IHsKKwkudmFsdWVzID0gd2xlZDRfb3Zw X3ZhbHVlcywKKwkuc2l6ZSA9IEFSUkFZX1NJWkUod2xlZDRfb3ZwX3ZhbHVlcyksCit9OworCiBz dGF0aWMgdTMyIHdsZWQzX251bV9zdHJpbmdzX3ZhbHVlc19mbih1MzIgaWR4KQogewogCXJldHVy biBpZHggKyAxOwpAQCAtMjk1LDYgKzQ3MywxMSBAQCBzdGF0aWMgdTMyIHdsZWQzX251bV9zdHJp bmdzX3ZhbHVlc19mbih1MzIgaWR4KQogCS5zaXplID0gMywKIH07CiAKK3N0YXRpYyBjb25zdCBz dHJ1Y3Qgd2xlZF92YXJfY2ZnIHdsZWQ0X251bV9zdHJpbmdzX2NmZyA9IHsKKwkuZm4gPSB3bGVk M19udW1fc3RyaW5nc192YWx1ZXNfZm4sCisJLnNpemUgPSA0LAorfTsKKwogc3RhdGljIHUzMiB3 bGVkM19zd2l0Y2hfZnJlcV92YWx1ZXNfZm4odTMyIGlkeCkKIHsKIAlyZXR1cm4gMTkyMDAgLyAo MiAqICgxICsgaWR4KSk7CkBAIC0zMDksMTAgKzQ5MiwyNCBAQCBzdGF0aWMgdTMyIHdsZWQzX3N3 aXRjaF9mcmVxX3ZhbHVlc19mbih1MzIgaWR4KQogCS5zaXplID0gMjYsCiB9OwogCitzdGF0aWMg Y29uc3QgdTMyIHdsZWQ0X3N0cmluZ19pX2xpbWl0X3ZhbHVlc1tdID0geworCTAsIDI1MDAsIDUw MDAsIDc1MDAsIDEwMDAwLCAxMjUwMCwgMTUwMDAsIDE3NTAwLCAyMDAwMCwKKwkyMjUwMCwgMjUw MDAsIDI3NTAwLCAzMDAwMCwKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgd2xlZF92YXJfY2Zn IHdsZWQ0X3N0cmluZ19pX2xpbWl0X2NmZyA9IHsKKwkudmFsdWVzID0gd2xlZDRfc3RyaW5nX2lf bGltaXRfdmFsdWVzLAorCS5zaXplID0gQVJSQVlfU0laRSh3bGVkNF9zdHJpbmdfaV9saW1pdF92 YWx1ZXMpLAorfTsKKwogc3RhdGljIGNvbnN0IHN0cnVjdCB3bGVkX3Zhcl9jZmcgd2xlZDNfc3Ry aW5nX2NmZyA9IHsKIAkuc2l6ZSA9IDgsCiB9OwogCitzdGF0aWMgY29uc3Qgc3RydWN0IHdsZWRf dmFyX2NmZyB3bGVkNF9zdHJpbmdfY2ZnID0geworCS5zaXplID0gMTYsCit9OworCiBzdGF0aWMg dTMyIHdsZWRfdmFsdWVzKGNvbnN0IHN0cnVjdCB3bGVkX3Zhcl9jZmcgKmNmZywgdTMyIGlkeCkK IHsKIAlpZiAoaWR4ID49IGNmZy0+c2l6ZSkKQEAgLTM2MSw2ICs1NTgsMzQgQEAgc3RhdGljIGlu dCB3bGVkX2NvbmZpZ3VyZShzdHJ1Y3Qgd2xlZCAqd2xlZCwgaW50IHZlcnNpb24pCiAJCX0sCiAJ fTsKIAorCWNvbnN0IHN0cnVjdCB3bGVkX3UzMl9vcHRzIHdsZWQ0X29wdHNbXSA9IHsKKwkJewor CQkJLm5hbWUgPSAicWNvbSxjdXJyZW50LWJvb3N0LWxpbWl0IiwKKwkJCS52YWxfcHRyID0gJmNm Zy0+Ym9vc3RfaV9saW1pdCwKKwkJCS5jZmcgPSAmd2xlZDRfYm9vc3RfaV9saW1pdF9jZmcsCisJ CX0sCisJCXsKKwkJCS5uYW1lID0gInFjb20sY3VycmVudC1saW1pdC1taWNyb2FtcCIsCisJCQku dmFsX3B0ciA9ICZjZmctPnN0cmluZ19pX2xpbWl0LAorCQkJLmNmZyA9ICZ3bGVkNF9zdHJpbmdf aV9saW1pdF9jZmcsCisJCX0sCisJCXsKKwkJCS5uYW1lID0gInFjb20sb3ZwLW1pbGxpdm9sdCIs CisJCQkudmFsX3B0ciA9ICZjZmctPm92cCwKKwkJCS5jZmcgPSAmd2xlZDRfb3ZwX2NmZywKKwkJ fSwKKwkJeworCQkJLm5hbWUgPSAicWNvbSxzd2l0Y2hpbmctZnJlcSIsCisJCQkudmFsX3B0ciA9 ICZjZmctPnN3aXRjaF9mcmVxLAorCQkJLmNmZyA9ICZ3bGVkM19zd2l0Y2hfZnJlcV9jZmcsCisJ CX0sCisJCXsKKwkJCS5uYW1lID0gInFjb20sbnVtLXN0cmluZ3MiLAorCQkJLnZhbF9wdHIgPSAm Y2ZnLT5udW1fc3RyaW5ncywKKwkJCS5jZmcgPSAmd2xlZDRfbnVtX3N0cmluZ3NfY2ZnLAorCQl9 LAorCX07CisKIAljb25zdCBzdHJ1Y3Qgd2xlZF9ib29sX29wdHMgYm9vbF9vcHRzW10gPSB7CiAJ CXsgInFjb20sY3Mtb3V0IiwgJmNmZy0+Y3Nfb3V0X2VuLCB9LAogCQl7ICJxY29tLGV4dC1nZW4i LCAmY2ZnLT5leHRfZ2VuLCB9LApAQCAtMzg1LDYgKzYxMCwyMiBAQCBzdGF0aWMgaW50IHdsZWRf Y29uZmlndXJlKHN0cnVjdCB3bGVkICp3bGVkLCBpbnQgdmVyc2lvbikKIAkJKmNmZyA9IHdsZWQz X2NvbmZpZ19kZWZhdWx0czsKIAkJd2xlZC0+d2xlZF9zZXRfYnJpZ2h0bmVzcyA9IHdsZWQzX3Nl dF9icmlnaHRuZXNzOwogCQl3bGVkLT5tYXhfc3RyaW5nX2NvdW50ID0gMzsKKwkJd2xlZC0+c2lu a19hZGRyID0gd2xlZC0+Y3RybF9hZGRyOworCQlicmVhazsKKworCWNhc2UgNDoKKwkJdTMyX29w dHMgPSB3bGVkNF9vcHRzOworCQlzaXplID0gQVJSQVlfU0laRSh3bGVkNF9vcHRzKTsKKwkJKmNm ZyA9IHdsZWQ0X2NvbmZpZ19kZWZhdWx0czsKKwkJd2xlZC0+d2xlZF9zZXRfYnJpZ2h0bmVzcyA9 IHdsZWQ0X3NldF9icmlnaHRuZXNzOworCQl3bGVkLT5tYXhfc3RyaW5nX2NvdW50ID0gNDsKKwor CQlwcm9wX2FkZHIgPSBvZl9nZXRfYWRkcmVzcyhkZXYtPm9mX25vZGUsIDEsIE5VTEwsIE5VTEwp OworCQlpZiAoIXByb3BfYWRkcikgeworCQkJZGV2X2Vycih3bGVkLT5kZXYsICJpbnZhbGlkIElP IHJlc291cmNlc1xuIik7CisJCQlyZXR1cm4gLUVJTlZBTDsKKwkJfQorCQl3bGVkLT5zaW5rX2Fk ZHIgPSBiZTMyX3RvX2NwdSgqcHJvcF9hZGRyKTsKIAkJYnJlYWs7CiAKIAlkZWZhdWx0OgpAQCAt NDgzLDYgKzcyNCwxNCBAQCBzdGF0aWMgaW50IHdsZWRfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rl dmljZSAqcGRldikKIAkJfQogCQlicmVhazsKIAorCWNhc2UgNDoKKwkJcmMgPSB3bGVkNF9zZXR1 cCh3bGVkKTsKKwkJaWYgKHJjKSB7CisJCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJ3bGVkNF9zZXR1 cCBmYWlsZWRcbiIpOworCQkJcmV0dXJuIHJjOworCQl9CisJCWJyZWFrOworCiAJZGVmYXVsdDoK IAkJZGV2X2Vycih3bGVkLT5kZXYsICJJbnZhbGlkIFdMRUQgdmVyc2lvblxuIik7CiAJCWJyZWFr OwpAQCAtNTAzLDYgKzc1Miw4IEBAIHN0YXRpYyBpbnQgd2xlZF9wcm9iZShzdHJ1Y3QgcGxhdGZv cm1fZGV2aWNlICpwZGV2KQogCiBzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCB3bGVk X21hdGNoX3RhYmxlW10gPSB7CiAJeyAuY29tcGF0aWJsZSA9ICJxY29tLHBtODk0MS13bGVkIiwg LmRhdGEgPSAodm9pZCAqKTMgfSwKKwl7IC5jb21wYXRpYmxlID0gInFjb20scG1pODk5OC13bGVk IiwgLmRhdGEgPSAodm9pZCAqKTQgfSwKKwl7IC5jb21wYXRpYmxlID0gInFjb20scG02NjBsLXds ZWQiLCAuZGF0YSA9ICh2b2lkICopNCB9LAogCXt9CiB9OwogTU9EVUxFX0RFVklDRV9UQUJMRShv Ziwgd2xlZF9tYXRjaF90YWJsZSk7Ci0tIApUaGUgUXVhbGNvbW0gSW5ub3ZhdGlvbiBDZW50ZXIs IEluYy4gaXMgYSBtZW1iZXIgb2YgdGhlIENvZGUgQXVyb3JhIEZvcnVtLAogYSBMaW51eCBGb3Vu ZGF0aW9uIENvbGxhYm9yYXRpdmUgUHJvamVjdAoKX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmktZGV2ZWxAbGlz dHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4v bGlzdGluZm8vZHJpLWRldmVs